A library for handling DID identifiers used in Bluesky AT Protocol

Compare changes

Choose any two refs to compare.

+392 -61
+1
.github/workflows/main.yml
··· 21 21 - '3.2' 22 22 - '3.3' 23 23 - '3.4' 24 + - '4.0' 24 25 25 26 steps: 26 27 - uses: actions/checkout@v3
+2
.gitignore
··· 1 1 .bundle 2 2 .DS_Store 3 3 .rspec_status 4 + .yardoc 4 5 coverage 6 + doc 5 7 Gemfile.lock
+4
.yardopts
··· 1 + --protected 2 + --no-private 3 + --markup markdown 4 + --embed-mixin "DIDKit::Services"
+3
Gemfile
··· 9 9 gem 'rspec', '~> 3.0' 10 10 gem 'irb' 11 11 12 + gem 'rdoc' 13 + gem 'yard' 14 + 12 15 gem 'mocha' 13 16 gem 'simplecov' 14 17 gem 'webmock'
+1 -1
LICENSE.txt
··· 1 1 The zlib License 2 2 3 - Copyright (c) 2025 Jakub Suder 3 + Copyright (c) 2026 Jakub Suder 4 4 5 5 This software is provided 'as-is', without any express or implied 6 6 warranty. In no event will the authors be held liable for any damages
+8 -4
README.md
··· 13 13 14 14 ## Installation 15 15 16 - From the command line: 16 + To use DIDKit, you need a reasonably new version of Ruby โ€“ it should run on Ruby 2.6 and above, although it's recommended to use a version that's still getting maintainance updates, i.e. currently 3.2+. A compatible version should be preinstalled on macOS Big Sur and above and on many Linux systems. Otherwise, you can install one using tools such as [RVM](https://rvm.io), [asdf](https://asdf-vm.com), [ruby-install](https://github.com/postmodern/ruby-install) or [ruby-build](https://github.com/rbenv/ruby-build), or `rpm` or `apt-get` on Linux (see more installation options on [ruby-lang.org](https://www.ruby-lang.org/en/downloads/)). 17 17 18 - gem install didkit 18 + To install the gem, run in the command line: 19 19 20 - Or, add this to your `Gemfile`: 20 + [sudo] gem install didkit 21 + 22 + Or add this to your app's `Gemfile`: 21 23 22 24 gem 'didkit', '~> 0.3' 23 25 ··· 106 108 107 109 ## Credits 108 110 109 - Copyright ยฉ 2025 Kuba Suder ([@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr)). 111 + Copyright ยฉ 2026 Kuba Suder ([@mackuba.eu](https://bsky.app/profile/did:plc:oio4hkxaop4ao4wz2pp3f4cr)). 110 112 111 113 The code is available under the terms of the [zlib license](https://choosealicense.com/licenses/zlib/) (permissive, similar to MIT). 114 + 115 + Bug reports and pull requests are welcome ๐Ÿ˜Ž
+9 -2
lib/didkit/at_handles.rb
··· 1 + require_relative 'errors' 2 + 1 3 module DIDKit 4 + 5 + # 6 + # @private 7 + # 8 + 2 9 module AtHandles 3 - class FormatError < StandardError 4 - end 10 + 11 + private 5 12 6 13 def parse_also_known_as(aka) 7 14 raise FormatError, "Invalid alsoKnownAs: #{aka.inspect}" unless aka.is_a?(Array)
+87 -2
lib/didkit/did.rb
··· 6 6 require_relative 'resolver' 7 7 8 8 module DIDKit 9 + 10 + # 11 + # Represents a DID identifier (account on the ATProto network). This class serves as an entry 12 + # point to various lookup helpers. For convenience it can also be accessed as just `DID` without 13 + # the `DIDKit::` prefix. 14 + # 15 + # @example Resolving a handle 16 + # did = DID.resolve_handle('bsky.app') 17 + # 18 + 9 19 class DID 10 20 GENERIC_REGEXP = /\Adid\:\w+\:.+\z/ 11 21 12 22 include Requests 13 23 24 + # Resolve a handle into a DID. Looks up the given ATProto domain handle using the DNS TXT method 25 + # and the HTTP .well-known method and returns a DID if one is assigned using either of the methods. 26 + # 27 + # If a DID string or a {DID} object is passed, it simply returns that DID, so you can use this 28 + # method to pass it an input string from the user which can be a DID or handle, without having to 29 + # check which one it is. 30 + # 31 + # @param handle [String, DID] a domain handle (may start with an `@`) or a DID string 32 + # @return [DID, nil] resolved DID if found, nil otherwise 33 + 14 34 def self.resolve_handle(handle) 15 35 Resolver.new.resolve_handle(handle) 16 36 end 17 37 18 - attr_reader :type, :did, :resolved_by 38 + # @return [Symbol] DID type (`:plc` or `:web`) 39 + attr_reader :type 40 + 41 + # @return [String] DID identifier string 42 + attr_reader :did 43 + 44 + # @return [Symbol, nil] `:dns` or `:http` if the DID was looked up using one of those methods 45 + attr_reader :resolved_by 46 + 47 + alias to_s did 48 + 49 + 50 + # Create a DID object from a DID string. 51 + # 52 + # @param did [String, DID] DID string or another DID object 53 + # @param resolved_by [Symbol, nil] optionally, how the DID was looked up (`:dns` or `:http`) 54 + # @raise [DIDError] when the DID format or type is invalid 19 55 20 56 def initialize(did, resolved_by = nil) 21 57 if did.is_a?(DID) ··· 36 72 @resolved_by = resolved_by 37 73 end 38 74 39 - alias to_s did 75 + # Returns or looks up the DID document with the DID's identity details from an appropriate source. 76 + # This method caches the document in a local variable if it's called again. 77 + # 78 + # @return [Document] resolved DID document 40 79 41 80 def document 42 81 @document ||= get_document 43 82 end 44 83 84 + # Looks up the DID document with the DID's identity details from an appropriate source. 85 + # @return [Document] resolved DID document 86 + 45 87 def get_document 46 88 Resolver.new.resolve_did(self) 47 89 end 48 90 91 + # Returns the first verified handle assigned to this DID. 92 + # 93 + # Looks up the domain handles assigned to this DID in its DID document, checks if they are 94 + # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns 95 + # the first handle that validates correctly, or nil if none matches. 96 + # 97 + # @return [String, nil] verified handle domain, if found 98 + 49 99 def get_verified_handle 50 100 Resolver.new.get_verified_handle(document) 51 101 end 52 102 103 + # Fetches the PLC audit log (list of all previous operations) for a did:plc DID. 104 + # 105 + # @return [Array<PLCOperation>] list of PLC operations in the audit log 106 + # @raise [DIDError] when the DID is not a did:plc 107 + 53 108 def get_audit_log 54 109 if @type == :plc 55 110 PLCImporter.new.fetch_audit_log(self) ··· 58 113 end 59 114 end 60 115 116 + # Returns the domain portion of a did:web identifier. 117 + # 118 + # @return [String, nil] DID domain if the DID is a did:web, nil for did:plc 119 + 61 120 def web_domain 62 121 did.gsub(/^did\:web\:/, '') if type == :web 63 122 end 64 123 124 + # Checks the status of the account/repo on its own PDS using the `getRepoStatus` endpoint. 125 + # 126 + # @param request_options [Hash] request options to override 127 + # @option request_options [Integer] :timeout request timeout (default: 15) 128 + # @option request_options [Integer] :max_redirects maximum number of redirects to follow (default: 5) 129 + # 130 + # @return [Symbol, nil] `:active`, or returned inactive status, or `nil` if account is not found 131 + # @raise [APIError] when the response is invalid 132 + 65 133 def account_status(request_options = {}) 66 134 doc = self.document 67 135 return nil if doc.pds_endpoint.nil? ··· 91 159 end 92 160 end 93 161 162 + # Checks if the account is seen as active on its own PDS, using the `getRepoStatus` endpoint. 163 + # This is a helper which calls the {#account_status} method and checks if the status is `:active`. 164 + # 165 + # @return [Boolean] true if the returned status is active 166 + # @raise [APIError] when the response is invalid 167 + 94 168 def account_active? 95 169 account_status == :active 96 170 end 97 171 172 + # Checks if the account exists its own PDS, using the `getRepoStatus` endpoint. 173 + # This is a helper which calls the {#account_status} method and checks if the repo is found at all. 174 + # 175 + # @return [Boolean] true if the returned status is valid, false if repo is not found 176 + # @raise [APIError] when the response is invalid 177 + 98 178 def account_exists? 99 179 account_status != nil 100 180 end 181 + 182 + # Compares the DID to another DID object or string. 183 + # 184 + # @param other [DID, String] other DID to compare with 185 + # @return [Boolean] true if it's the same DID 101 186 102 187 def ==(other) 103 188 if other.is_a?(String)
+39 -4
lib/didkit/document.rb
··· 1 1 require_relative 'at_handles' 2 + require_relative 'errors' 2 3 require_relative 'resolver' 3 4 require_relative 'service_record' 4 5 require_relative 'services' 5 6 6 7 module DIDKit 8 + 9 + # 10 + # Parsed DID document from a JSON file loaded from [plc.directory](https://plc.directory) or a did:web domain. 11 + # 12 + # Use {DID#document} or {Resolver#resolve_did} to fetch a DID document and return this object. 13 + # 14 + 7 15 class Document 8 - class FormatError < StandardError 9 - end 10 - 11 16 include AtHandles 12 17 include Services 13 18 14 - attr_reader :json, :did, :handles, :services 19 + # @return [Hash] the complete JSON data of the DID document 20 + attr_reader :json 21 + 22 + # @return [DID] the DID that this document describes 23 + attr_reader :did 24 + 25 + # Returns a list of handles assigned to this DID in its DID document. 26 + # 27 + # Note: the handles aren't guaranteed to be verified (validated in the other direction). 28 + # Use {#get_verified_handle} to find a handle that is correctly verified. 29 + # 30 + # @return [Array<String>] 31 + attr_reader :handles 32 + 33 + # @return [Array<ServiceRecords>] service records like PDS details assigned to the DID 34 + attr_reader :services 35 + 36 + # Creates a DID document object. 37 + # 38 + # @param did [DID] DID object 39 + # @param json [Hash] DID document JSON 40 + # @raise [FormatError] when required fields are missing or invalid. 15 41 16 42 def initialize(did, json) 17 43 raise FormatError, "Missing id field" if json['id'].nil? ··· 25 51 @handles = parse_also_known_as(json['alsoKnownAs'] || []) 26 52 end 27 53 54 + # Returns the first verified handle assigned to the DID. 55 + # 56 + # Looks up the domain handles assigned to this DID in the DID document, checks if they are 57 + # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns 58 + # the first handle that validates correctly, or nil if none matches. 59 + # 60 + # @return [String, nil] verified handle domain, if found 61 + 28 62 def get_verified_handle 29 63 Resolver.new.get_verified_handle(self) 30 64 end 65 + 31 66 32 67 private 33 68
+20 -2
lib/didkit/errors.rb
··· 1 1 module DIDKit 2 - class DIDError < StandardError 3 - end 4 2 3 + # 4 + # Raised when an HTTP request returns a response with an error status. 5 + # 5 6 class APIError < StandardError 7 + 8 + # @return [Net::HTTPResponse] the returned HTTP response 6 9 attr_reader :response 7 10 11 + # @param response [Net::HTTPResponse] the returned HTTP response 8 12 def initialize(response) 9 13 @response = response 10 14 super("APIError: #{response}") 11 15 end 12 16 17 + # @return [Integer] HTTP status code 13 18 def status 14 19 response.code.to_i 15 20 end 16 21 22 + # @return [String] HTTP response body 17 23 def body 18 24 response.body 19 25 end 26 + end 27 + 28 + # 29 + # Raised when a string is not a valid DID or not of the right type. 30 + # 31 + class DIDError < StandardError 32 + end 33 + 34 + # 35 + # Raised when the loaded data has some missing or invalid fields. 36 + # 37 + class FormatError < StandardError 20 38 end 21 39 end
+44 -4
lib/didkit/plc_operation.rb
··· 1 1 require 'time' 2 2 3 3 require_relative 'at_handles' 4 + require_relative 'errors' 4 5 require_relative 'service_record' 5 6 require_relative 'services' 6 7 7 8 module DIDKit 8 - class PLCOperation 9 - class FormatError < StandardError 10 - end 11 9 10 + # 11 + # Represents a single operation of changing a specific DID's data in the [plc.directory](https://plc.directory) 12 + # (e.g. changing assigned handles or migrating to a different PDS). 13 + # 14 + 15 + class PLCOperation 12 16 include AtHandles 13 17 include Services 14 18 15 - attr_reader :json, :did, :cid, :seq, :created_at, :type, :handles, :services 19 + # @return [Hash] the JSON from which the operation is parsed 20 + attr_reader :json 21 + 22 + # @return [String] the DID which the operation concerns 23 + attr_reader :did 24 + 25 + # @return [String] CID (Content Identifier) of the operation 26 + attr_reader :cid 27 + 28 + # Returns a sequential number of the operation (only used in the new export API). 29 + # @return [Integer, nil] sequential number of the operation 30 + attr_reader :seq 31 + 32 + # @return [Time] time when the operation was created 33 + attr_reader :created_at 34 + 35 + # Returns the `type` field of the operation (usually `"plc_operation"`). 36 + # @return [String] the operation type 37 + attr_reader :type 38 + 39 + # Returns a list of handles assigned to the DID in this operation. 40 + # 41 + # Note: the handles aren't guaranteed to be verified (validated in the other direction). 42 + # Use {DID#get_verified_handle} or {Document#get_verified_handle} to find a handle that is 43 + # correctly verified. 44 + # 45 + # @return [Array<String>] 46 + attr_reader :handles 47 + 48 + # @return [Array<ServiceRecords>] service records like PDS details assigned to the DID 49 + attr_reader :services 50 + 51 + 52 + # Creates a PLCOperation object. 53 + # 54 + # @param json [Hash] operation JSON 55 + # @raise [FormatError] when required fields are missing or invalid 16 56 17 57 def initialize(json) 18 58 @json = json
+8
lib/didkit/requests.rb
··· 5 5 require_relative 'errors' 6 6 7 7 module DIDKit 8 + 9 + # 10 + # @private 11 + # 12 + 8 13 module Requests 14 + 15 + private 16 + 9 17 def get_response(url, options = {}) 10 18 url = URI(url) unless url.is_a?(URI) 11 19
+82 -16
lib/didkit/resolver.rb
··· 6 6 require_relative 'requests' 7 7 8 8 module DIDKit 9 + 10 + # 11 + # A class which manages resolving of handles to DIDs and DIDs to DID documents. 12 + # 13 + 9 14 class Resolver 15 + # These TLDs are not allowed in ATProto handles, so the resolver returns nil for them 16 + # without trying to look them up. 10 17 RESERVED_DOMAINS = %w(alt arpa example internal invalid local localhost onion test) 11 18 12 19 include Requests 13 20 21 + # @return [String, Array<String>] custom DNS nameserver(s) to use for DNS TXT lookups 14 22 attr_accessor :nameserver 23 + 24 + # @param options [Hash] resolver options 25 + # @option options [String, Array<String>] :nameserver custom DNS nameserver(s) to use (IP or an array of IPs) 26 + # @option options [Integer] :timeout request timeout in seconds (default: 15) 27 + # @option options [Integer] :max_redirects maximum number of redirects to follow (default: 5) 15 28 16 29 def initialize(options = {}) 17 30 @nameserver = options[:nameserver] 18 31 @request_options = options.slice(:timeout, :max_redirects) 19 32 end 20 33 34 + # Resolve a handle into a DID. Looks up the given ATProto domain handle using the DNS TXT method 35 + # and the HTTP .well-known method and returns a DID if one is assigned using either of the methods. 36 + # 37 + # If a DID string or a {DID} object is passed, it simply returns that DID, so you can use this 38 + # method to pass it an input string from the user which can be a DID or handle, without having to 39 + # check which one it is. 40 + # 41 + # @param handle [String, DID] a domain handle (may start with an `@`) or a DID string 42 + # @return [DID, nil] resolved DID if found, nil otherwise 43 + 21 44 def resolve_handle(handle) 22 45 if handle.is_a?(DID) || handle =~ DID::GENERIC_REGEXP 23 46 return DID.new(handle) ··· 36 59 end 37 60 end 38 61 62 + # Tries to resolve a handle into DID using the DNS TXT method. 63 + # 64 + # Checks the DNS records for a given domain for an entry `_atproto.#{domain}` whose value is 65 + # a correct DID string. 66 + # 67 + # @param domain [String] a domain handle to look up 68 + # @return [String, nil] resolved DID if found, nil otherwise 69 + 39 70 def resolve_handle_by_dns(domain) 40 71 dns_records = Resolv::DNS.open(resolv_options) do |d| 41 72 d.getresources("_atproto.#{domain}", Resolv::DNS::Resource::IN::TXT) ··· 50 81 nil 51 82 end 52 83 84 + # Tries to resolve a handle into DID using the HTTP .well-known method. 85 + # 86 + # Checks the `/.well-known/atproto-did` endpoint on the given domain to see if it returns 87 + # a text file that contains a correct DID string. 88 + # 89 + # @param domain [String] a domain handle to look up 90 + # @return [String, nil] resolved DID if found, nil otherwise 91 + 53 92 def resolve_handle_by_well_known(domain) 54 93 url = "https://#{domain}/.well-known/atproto-did" 55 94 response = get_response(url, @request_options) ··· 63 102 nil 64 103 end 65 104 105 + # Resolve a DID to a DID document. 106 + # 107 + # Looks up the DID document with the DID's identity details from an appropriate source, i.e. either 108 + # [plc.directory](https://plc.directory) for did:plc DIDs, or the did:web's domain for did:web DIDs. 109 + # 110 + # @param did [String, DID] DID string or object 111 + # @return [Document] resolved DID document 112 + # @raise [APIError] if an incorrect response is returned 113 + 114 + def resolve_did(did) 115 + did = DID.new(did) if did.is_a?(String) 116 + 117 + did.type == :plc ? resolve_did_plc(did) : resolve_did_web(did) 118 + end 119 + 120 + # Returns the first verified handle assigned to the given DID. 121 + # 122 + # Looks up the domain handles assigned to the DID in the DID document, checks if they are 123 + # verified (i.e. assigned correctly to this DID using DNS TXT or .well-known) and returns 124 + # the first handle that validates correctly, or nil if none matches. 125 + # 126 + # @param subject [String, DID, Document] a DID or its DID document 127 + # @return [String, nil] verified handle domain, if found 128 + 129 + def get_verified_handle(subject) 130 + document = subject.is_a?(Document) ? subject : resolve_did(subject) 131 + 132 + first_verified_handle(document.did, document.handles) 133 + end 134 + 135 + # Returns the first handle from the list that resolves back to the given DID. 136 + # 137 + # @param did [DID, String] DID to verify the handles against 138 + # @param handles [Array<String>] handles to check 139 + # @return [String, nil] a verified handle, if found 140 + 141 + def first_verified_handle(did, handles) 142 + handles.detect { |h| resolve_handle(h) == did.to_s } 143 + end 144 + 145 + 146 + private 147 + 66 148 def resolv_options 67 149 options = Resolv::DNS::Config.default_config_hash.dup 68 150 options[:nameserver] = nameserver if nameserver ··· 78 160 text.lines.length == 1 && text =~ DID::GENERIC_REGEXP ? text : nil 79 161 end 80 162 81 - def resolve_did(did) 82 - did = DID.new(did) if did.is_a?(String) 83 - 84 - did.type == :plc ? resolve_did_plc(did) : resolve_did_web(did) 85 - end 86 - 87 163 def resolve_did_plc(did) 88 164 json = get_json("https://plc.directory/#{did}", content_type: /^application\/did\+ld\+json(;.+)?$/) 89 165 Document.new(did, json) ··· 92 168 def resolve_did_web(did) 93 169 json = get_json("https://#{did.web_domain}/.well-known/did.json") 94 170 Document.new(did, json) 95 - end 96 - 97 - def get_verified_handle(subject) 98 - document = subject.is_a?(Document) ? subject : resolve_did(subject) 99 - 100 - first_verified_handle(document.did, document.handles) 101 - end 102 - 103 - def first_verified_handle(did, handles) 104 - handles.detect { |h| resolve_handle(h) == did.to_s } 105 171 end 106 172 end 107 173 end
+21 -3
lib/didkit/service_record.rb
··· 2 2 require_relative 'errors' 3 3 4 4 module DIDKit 5 + 6 + # A parsed service record from either a DID document's `service` field or a PLC directory 7 + # operation's `services` field. 8 + 5 9 class ServiceRecord 6 - class FormatError < StandardError 7 - end 8 10 9 - attr_reader :key, :type, :endpoint 11 + # Returns the service's identifier (without `#`), like "atproto_pds". 12 + # @return [String] service's identifier 13 + attr_reader :key 14 + 15 + # Returns the service's type field, like "AtprotoPersonalDataServer". 16 + # @return [String] service's type 17 + attr_reader :type 18 + 19 + # @return [String] service's endpoint URL 20 + attr_reader :endpoint 21 + 22 + # Create a service record from DID document fields. 23 + # 24 + # @param key [String] service identifier (without `#`) 25 + # @param type [String] service type 26 + # @param endpoint [String] service endpoint URL 27 + # @raise [FormatError] when the endpoint is not a valid URI 10 28 11 29 def initialize(key, type, endpoint) 12 30 begin
+40
lib/didkit/services.rb
··· 1 1 require 'uri' 2 2 3 3 module DIDKit 4 + 5 + # 6 + # @api private 7 + # 8 + 4 9 module Services 10 + 11 + # Finds a service entry matching the given key and type. 12 + # 13 + # @api public 14 + # @param key [String] service key in the DID document 15 + # @param type [String] service type identifier 16 + # @return [ServiceRecord, nil] matching service record, if found 17 + 5 18 def get_service(key, type) 6 19 @services&.detect { |s| s.key == key && s.type == type } 7 20 end 8 21 22 + # Returns the PDS service endpoint, if present. 23 + # 24 + # If the DID has an `#atproto_pds` service declared in its `service` section, 25 + # returns the URL in its `serviceEndpoint` field. In other words, this is the URL 26 + # of the PDS assigned to a given user, which stores the user's account and repo. 27 + # 28 + # @api public 29 + # @return [String, nil] PDS service endpoint URL 30 + 9 31 def pds_endpoint 10 32 @pds_endpoint ||= get_service('atproto_pds', 'AtprotoPersonalDataServer')&.endpoint 11 33 end 34 + 35 + # Returns the labeler service endpoint, if present. 36 + # 37 + # If the DID has an `#atproto_labeler` service declared in its `service` section, 38 + # returns the URL in its `serviceEndpoint` field. 39 + # 40 + # @api public 41 + # @return [String, nil] labeler service endpoint URL 12 42 13 43 def labeler_endpoint 14 44 @labeler_endpoint ||= get_service('atproto_labeler', 'AtprotoLabeler')&.endpoint 15 45 end 16 46 47 + # Returns the hostname of the PDS service, if present. 48 + # 49 + # @api public 50 + # @return [String, nil] hostname of the PDS endpoint URL 51 + 17 52 def pds_host 18 53 pds_endpoint&.then { |x| URI(x).host } 19 54 end 55 + 56 + # Returns the hostname of the labeler service, if present. 57 + # 58 + # @api public 59 + # @return [String, nil] hostname of the labeler endpoint URL 20 60 21 61 def labeler_host 22 62 labeler_endpoint&.then { |x| URI(x).host }
+7 -7
spec/document_spec.rb
··· 41 41 it 'should raise a format error' do 42 42 expect { 43 43 subject.new(did, json) 44 - }.to raise_error(DIDKit::Document::FormatError) 44 + }.to raise_error(DIDKit::FormatError) 45 45 end 46 46 end 47 47 ··· 51 51 it 'should raise a format error' do 52 52 expect { 53 53 subject.new(did, json) 54 - }.to raise_error(DIDKit::Document::FormatError) 54 + }.to raise_error(DIDKit::FormatError) 55 55 end 56 56 end 57 57 ··· 61 61 it 'should raise a format error' do 62 62 expect { 63 63 subject.new(did, json) 64 - }.to raise_error(DIDKit::Document::FormatError) 64 + }.to raise_error(DIDKit::FormatError) 65 65 end 66 66 end 67 67 ··· 71 71 it 'should raise an AtHandles format error' do 72 72 expect { 73 73 subject.new(did, json) 74 - }.to raise_error(DIDKit::AtHandles::FormatError) 74 + }.to raise_error(DIDKit::FormatError) 75 75 end 76 76 end 77 77 ··· 81 81 it 'should raise an AtHandles format error' do 82 82 expect { 83 83 subject.new(did, json) 84 - }.to raise_error(DIDKit::AtHandles::FormatError) 84 + }.to raise_error(DIDKit::FormatError) 85 85 end 86 86 end 87 87 ··· 106 106 it 'should raise a format error' do 107 107 expect { 108 108 subject.new(did, json) 109 - }.to raise_error(DIDKit::Document::FormatError) 109 + }.to raise_error(DIDKit::FormatError) 110 110 end 111 111 end 112 112 ··· 116 116 it 'should raise a format error' do 117 117 expect { 118 118 subject.new(did, json) 119 - }.to raise_error(DIDKit::Document::FormatError) 119 + }.to raise_error(DIDKit::FormatError) 120 120 end 121 121 end 122 122
+16 -16
spec/plc_operation_spec.rb
··· 27 27 let(:json) { [base_json] } 28 28 29 29 it 'should raise a format error' do 30 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 30 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 31 31 end 32 32 end 33 33 ··· 35 35 let(:json) { base_json.tap { |h| h.delete('did') }} 36 36 37 37 it 'should raise a format error' do 38 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 38 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 39 39 end 40 40 end 41 41 ··· 43 43 let(:json) { base_json.merge('did' => 123) } 44 44 45 45 it 'should raise a format error' do 46 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 46 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 47 47 end 48 48 end 49 49 ··· 51 51 let(:json) { base_json.merge('did' => 'foobar') } 52 52 53 53 it 'should raise a format error' do 54 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 54 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 55 55 end 56 56 end 57 57 ··· 59 59 let(:json) { base_json.tap { |h| h.delete('cid') }} 60 60 61 61 it 'should raise a format error' do 62 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 62 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 63 63 end 64 64 end 65 65 ··· 67 67 let(:json) { base_json.merge('cid' => 700) } 68 68 69 69 it 'should raise a format error' do 70 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 70 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 71 71 end 72 72 end 73 73 ··· 75 75 let(:json) { base_json.tap { |h| h.delete('createdAt') }} 76 76 77 77 it 'should raise a format error' do 78 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 78 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 79 79 end 80 80 end 81 81 ··· 83 83 let(:json) { base_json.merge('createdAt' => 123) } 84 84 85 85 it 'should raise a format error' do 86 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 86 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 87 87 end 88 88 end 89 89 ··· 91 91 let(:json) { base_json.tap { |h| h.delete('operation') }} 92 92 93 93 it 'should raise a format error' do 94 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 94 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 95 95 end 96 96 end 97 97 ··· 99 99 let(:json) { base_json.merge('operation' => 'invalid') } 100 100 101 101 it 'should raise a format error' do 102 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 102 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 103 103 end 104 104 end 105 105 ··· 107 107 let(:json) { base_json.tap { |h| h['operation'].delete('type') }} 108 108 109 109 it 'should raise a format error' do 110 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 110 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 111 111 end 112 112 end 113 113 ··· 152 152 it 'should raise an AtHandles format error' do 153 153 expect { 154 154 subject.new(json) 155 - }.to raise_error(DIDKit::AtHandles::FormatError) 155 + }.to raise_error(DIDKit::FormatError) 156 156 end 157 157 end 158 158 ··· 162 162 it 'should raise an AtHandles format error' do 163 163 expect { 164 164 subject.new(json) 165 - }.to raise_error(DIDKit::AtHandles::FormatError) 165 + }.to raise_error(DIDKit::FormatError) 166 166 end 167 167 end 168 168 ··· 187 187 let(:json) { base_json.tap { |h| h['operation'].delete('services') }} 188 188 189 189 it 'should raise a format error' do 190 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 190 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 191 191 end 192 192 end 193 193 ··· 205 205 } 206 206 207 207 it 'should raise a format error' do 208 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 208 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 209 209 end 210 210 end 211 211 ··· 225 225 } 226 226 227 227 it 'should raise a format error' do 228 - expect { subject.new(json) }.to raise_error(DIDKit::PLCOperation::FormatError) 228 + expect { subject.new(json) }.to raise_error(DIDKit::FormatError) 229 229 end 230 230 end 231 231