@enbox/agent 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/browser.js +2215 -0
- package/dist/browser.js.map +7 -0
- package/dist/browser.mjs +2215 -0
- package/dist/browser.mjs.map +7 -0
- package/dist/cjs/index.js +8530 -0
- package/dist/cjs/index.js.map +7 -0
- package/dist/cjs/package.json +1 -0
- package/dist/esm/agent-did-resolver-cache.js +87 -0
- package/dist/esm/agent-did-resolver-cache.js.map +1 -0
- package/dist/esm/bearer-identity.js +41 -0
- package/dist/esm/bearer-identity.js.map +1 -0
- package/dist/esm/connect.js +191 -0
- package/dist/esm/connect.js.map +1 -0
- package/dist/esm/crypto-api.js +346 -0
- package/dist/esm/crypto-api.js.map +1 -0
- package/dist/esm/did-api.js +278 -0
- package/dist/esm/did-api.js.map +1 -0
- package/dist/esm/dwn-api.js +336 -0
- package/dist/esm/dwn-api.js.map +1 -0
- package/dist/esm/dwn-registrar.js +120 -0
- package/dist/esm/dwn-registrar.js.map +1 -0
- package/dist/esm/hd-identity-vault.js +729 -0
- package/dist/esm/hd-identity-vault.js.map +1 -0
- package/dist/esm/identity-api.js +262 -0
- package/dist/esm/identity-api.js.map +1 -0
- package/dist/esm/index.js +23 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/local-key-manager.js +498 -0
- package/dist/esm/local-key-manager.js.map +1 -0
- package/dist/esm/oidc.js +507 -0
- package/dist/esm/oidc.js.map +1 -0
- package/dist/esm/permissions-api.js +322 -0
- package/dist/esm/permissions-api.js.map +1 -0
- package/dist/esm/prototyping/clients/dwn-rpc-types.js +2 -0
- package/dist/esm/prototyping/clients/dwn-rpc-types.js.map +1 -0
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js +74 -0
- package/dist/esm/prototyping/clients/dwn-server-info-cache-memory.js.map +1 -0
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js +105 -0
- package/dist/esm/prototyping/clients/http-dwn-rpc-client.js.map +1 -0
- package/dist/esm/prototyping/clients/json-rpc-socket.js +150 -0
- package/dist/esm/prototyping/clients/json-rpc-socket.js.map +1 -0
- package/dist/esm/prototyping/clients/json-rpc.js +58 -0
- package/dist/esm/prototyping/clients/json-rpc.js.map +1 -0
- package/dist/esm/prototyping/clients/server-info-types.js +2 -0
- package/dist/esm/prototyping/clients/server-info-types.js.map +1 -0
- package/dist/esm/prototyping/clients/web-socket-clients.js +90 -0
- package/dist/esm/prototyping/clients/web-socket-clients.js.map +1 -0
- package/dist/esm/prototyping/common/object.js +14 -0
- package/dist/esm/prototyping/common/object.js.map +1 -0
- package/dist/esm/prototyping/common/type-utils.js +2 -0
- package/dist/esm/prototyping/common/type-utils.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js +147 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-gcm.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js +137 -0
- package/dist/esm/prototyping/crypto/algorithms/aes-kw.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js +307 -0
- package/dist/esm/prototyping/crypto/algorithms/ecdsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js +264 -0
- package/dist/esm/prototyping/crypto/algorithms/eddsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js +39 -0
- package/dist/esm/prototyping/crypto/algorithms/hkdf.js.map +1 -0
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js +41 -0
- package/dist/esm/prototyping/crypto/algorithms/pbkdf2.js.map +1 -0
- package/dist/esm/prototyping/crypto/crypto-error.js +41 -0
- package/dist/esm/prototyping/crypto/crypto-error.js.map +1 -0
- package/dist/esm/prototyping/crypto/dsa.js +236 -0
- package/dist/esm/prototyping/crypto/dsa.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js +130 -0
- package/dist/esm/prototyping/crypto/jose/jwe-compact.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js +294 -0
- package/dist/esm/prototyping/crypto/jose/jwe-flattened.js.map +1 -0
- package/dist/esm/prototyping/crypto/jose/jwe.js +308 -0
- package/dist/esm/prototyping/crypto/jose/jwe.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/aes-gcm.js +352 -0
- package/dist/esm/prototyping/crypto/primitives/aes-gcm.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/aes-kw.js +247 -0
- package/dist/esm/prototyping/crypto/primitives/aes-kw.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/hkdf.js +80 -0
- package/dist/esm/prototyping/crypto/primitives/hkdf.js.map +1 -0
- package/dist/esm/prototyping/crypto/primitives/pbkdf2.js +85 -0
- package/dist/esm/prototyping/crypto/primitives/pbkdf2.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/cipher.js +2 -0
- package/dist/esm/prototyping/crypto/types/cipher.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/crypto-api.js +2 -0
- package/dist/esm/prototyping/crypto/types/crypto-api.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-converter.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-converter.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-deriver.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-deriver.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-io.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-io.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-manager.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-manager.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/key-wrapper.js +2 -0
- package/dist/esm/prototyping/crypto/types/key-wrapper.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/params-direct.js +2 -0
- package/dist/esm/prototyping/crypto/types/params-direct.js.map +1 -0
- package/dist/esm/prototyping/crypto/types/params-kms.js +2 -0
- package/dist/esm/prototyping/crypto/types/params-kms.js.map +1 -0
- package/dist/esm/prototyping/crypto/utils.js +19 -0
- package/dist/esm/prototyping/crypto/utils.js.map +1 -0
- package/dist/esm/prototyping/dids/resolver-cache-memory.js +77 -0
- package/dist/esm/prototyping/dids/resolver-cache-memory.js.map +1 -0
- package/dist/esm/prototyping/dids/utils.js +9 -0
- package/dist/esm/prototyping/dids/utils.js.map +1 -0
- package/dist/esm/rpc-client.js +123 -0
- package/dist/esm/rpc-client.js.map +1 -0
- package/dist/esm/store-data-protocols.js +38 -0
- package/dist/esm/store-data-protocols.js.map +1 -0
- package/dist/esm/store-data.js +320 -0
- package/dist/esm/store-data.js.map +1 -0
- package/dist/esm/store-did.js +136 -0
- package/dist/esm/store-did.js.map +1 -0
- package/dist/esm/store-identity.js +140 -0
- package/dist/esm/store-identity.js.map +1 -0
- package/dist/esm/store-key.js +136 -0
- package/dist/esm/store-key.js.map +1 -0
- package/dist/esm/sync-api.js +61 -0
- package/dist/esm/sync-api.js.map +1 -0
- package/dist/esm/sync-engine-level.js +618 -0
- package/dist/esm/sync-engine-level.js.map +1 -0
- package/dist/esm/test-harness.js +239 -0
- package/dist/esm/test-harness.js.map +1 -0
- package/dist/esm/types/agent.js +2 -0
- package/dist/esm/types/agent.js.map +1 -0
- package/dist/esm/types/dwn.js +31 -0
- package/dist/esm/types/dwn.js.map +1 -0
- package/dist/esm/types/identity-vault.js +2 -0
- package/dist/esm/types/identity-vault.js.map +1 -0
- package/dist/esm/types/identity.js +2 -0
- package/dist/esm/types/identity.js.map +1 -0
- package/dist/esm/types/key-manager.js +2 -0
- package/dist/esm/types/key-manager.js.map +1 -0
- package/dist/esm/types/permissions.js +2 -0
- package/dist/esm/types/permissions.js.map +1 -0
- package/dist/esm/types/sync.js +2 -0
- package/dist/esm/types/sync.js.map +1 -0
- package/dist/esm/types/vc.js +5 -0
- package/dist/esm/types/vc.js.map +1 -0
- package/dist/esm/utils-internal.js +147 -0
- package/dist/esm/utils-internal.js.map +1 -0
- package/dist/esm/utils.js +161 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/types/agent-did-resolver-cache.d.ts +30 -0
- package/dist/types/agent-did-resolver-cache.d.ts.map +1 -0
- package/dist/types/bearer-identity.d.ts +31 -0
- package/dist/types/bearer-identity.d.ts.map +1 -0
- package/dist/types/connect.d.ts +88 -0
- package/dist/types/connect.d.ts.map +1 -0
- package/dist/types/crypto-api.d.ts +286 -0
- package/dist/types/crypto-api.d.ts.map +1 -0
- package/dist/types/did-api.d.ts +119 -0
- package/dist/types/did-api.d.ts.map +1 -0
- package/dist/types/dwn-api.d.ts +66 -0
- package/dist/types/dwn-api.d.ts.map +1 -0
- package/dist/types/dwn-registrar.d.ts +29 -0
- package/dist/types/dwn-registrar.d.ts.map +1 -0
- package/dist/types/hd-identity-vault.d.ts +306 -0
- package/dist/types/hd-identity-vault.d.ts.map +1 -0
- package/dist/types/identity-api.d.ts +107 -0
- package/dist/types/identity-api.d.ts.map +1 -0
- package/dist/types/index.d.ts +30 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/local-key-manager.d.ts +311 -0
- package/dist/types/local-key-manager.d.ts.map +1 -0
- package/dist/types/oidc.d.ts +247 -0
- package/dist/types/oidc.d.ts.map +1 -0
- package/dist/types/permissions-api.d.ts +35 -0
- package/dist/types/permissions-api.d.ts.map +1 -0
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts +45 -0
- package/dist/types/prototyping/clients/dwn-rpc-types.d.ts.map +1 -0
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts +57 -0
- package/dist/types/prototyping/clients/dwn-server-info-cache-memory.d.ts.map +1 -0
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts +13 -0
- package/dist/types/prototyping/clients/http-dwn-rpc-client.d.ts.map +1 -0
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts +43 -0
- package/dist/types/prototyping/clients/json-rpc-socket.d.ts.map +1 -0
- package/dist/types/prototyping/clients/json-rpc.d.ts +49 -0
- package/dist/types/prototyping/clients/json-rpc.d.ts.map +1 -0
- package/dist/types/prototyping/clients/server-info-types.d.ts +20 -0
- package/dist/types/prototyping/clients/server-info-types.d.ts.map +1 -0
- package/dist/types/prototyping/clients/web-socket-clients.d.ts +10 -0
- package/dist/types/prototyping/clients/web-socket-clients.d.ts.map +1 -0
- package/dist/types/prototyping/common/object.d.ts +2 -0
- package/dist/types/prototyping/common/object.d.ts.map +1 -0
- package/dist/types/prototyping/common/type-utils.d.ts +7 -0
- package/dist/types/prototyping/common/type-utils.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts +151 -0
- package/dist/types/prototyping/crypto/algorithms/aes-gcm.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts +109 -0
- package/dist/types/prototyping/crypto/algorithms/aes-kw.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts +160 -0
- package/dist/types/prototyping/crypto/algorithms/ecdsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts +157 -0
- package/dist/types/prototyping/crypto/algorithms/eddsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts +21 -0
- package/dist/types/prototyping/crypto/algorithms/hkdf.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts +21 -0
- package/dist/types/prototyping/crypto/algorithms/pbkdf2.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/crypto-error.d.ts +29 -0
- package/dist/types/prototyping/crypto/crypto-error.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/dsa.d.ts +169 -0
- package/dist/types/prototyping/crypto/dsa.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts +135 -0
- package/dist/types/prototyping/crypto/jose/jwe-compact.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts +134 -0
- package/dist/types/prototyping/crypto/jose/jwe-flattened.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/jose/jwe.d.ts +378 -0
- package/dist/types/prototyping/crypto/jose/jwe.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/aes-gcm.d.ts +245 -0
- package/dist/types/prototyping/crypto/primitives/aes-gcm.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/aes-kw.d.ts +103 -0
- package/dist/types/prototyping/crypto/primitives/aes-kw.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/hkdf.d.ts +90 -0
- package/dist/types/prototyping/crypto/primitives/hkdf.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/primitives/pbkdf2.d.ts +84 -0
- package/dist/types/prototyping/crypto/primitives/pbkdf2.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/cipher.d.ts +14 -0
- package/dist/types/prototyping/crypto/types/cipher.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts +35 -0
- package/dist/types/prototyping/crypto/types/crypto-api.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-converter.d.ts +49 -0
- package/dist/types/prototyping/crypto/types/key-converter.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts +50 -0
- package/dist/types/prototyping/crypto/types/key-deriver.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-io.d.ts +49 -0
- package/dist/types/prototyping/crypto/types/key-io.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-manager.d.ts +69 -0
- package/dist/types/prototyping/crypto/types/key-manager.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/key-wrapper.d.ts +14 -0
- package/dist/types/prototyping/crypto/types/key-wrapper.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/params-direct.d.ts +75 -0
- package/dist/types/prototyping/crypto/types/params-direct.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/types/params-kms.d.ts +63 -0
- package/dist/types/prototyping/crypto/types/params-kms.d.ts.map +1 -0
- package/dist/types/prototyping/crypto/utils.d.ts +7 -0
- package/dist/types/prototyping/crypto/utils.d.ts.map +1 -0
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts +57 -0
- package/dist/types/prototyping/dids/resolver-cache-memory.d.ts.map +1 -0
- package/dist/types/prototyping/dids/utils.d.ts +3 -0
- package/dist/types/prototyping/dids/utils.d.ts.map +1 -0
- package/dist/types/rpc-client.d.ts +51 -0
- package/dist/types/rpc-client.d.ts.map +1 -0
- package/dist/types/store-data-protocols.d.ts +4 -0
- package/dist/types/store-data-protocols.d.ts.map +1 -0
- package/dist/types/store-data.d.ts +95 -0
- package/dist/types/store-data.d.ts.map +1 -0
- package/dist/types/store-did.d.ts +33 -0
- package/dist/types/store-did.d.ts.map +1 -0
- package/dist/types/store-identity.d.ts +34 -0
- package/dist/types/store-identity.d.ts.map +1 -0
- package/dist/types/store-key.d.ts +32 -0
- package/dist/types/store-key.d.ts.map +1 -0
- package/dist/types/sync-api.d.ts +41 -0
- package/dist/types/sync-api.d.ts.map +1 -0
- package/dist/types/sync-engine-level.d.ts +85 -0
- package/dist/types/sync-engine-level.d.ts.map +1 -0
- package/dist/types/test-harness.d.ts +69 -0
- package/dist/types/test-harness.d.ts.map +1 -0
- package/dist/types/types/agent.d.ts +172 -0
- package/dist/types/types/agent.d.ts.map +1 -0
- package/dist/types/types/dwn.d.ts +178 -0
- package/dist/types/types/dwn.d.ts.map +1 -0
- package/dist/types/types/identity-vault.d.ts +129 -0
- package/dist/types/types/identity-vault.d.ts.map +1 -0
- package/dist/types/types/identity.d.ts +16 -0
- package/dist/types/types/identity.d.ts.map +1 -0
- package/dist/types/types/key-manager.d.ts +9 -0
- package/dist/types/types/key-manager.d.ts.map +1 -0
- package/dist/types/types/permissions.d.ts +98 -0
- package/dist/types/types/permissions.d.ts.map +1 -0
- package/dist/types/types/sync.d.ts +66 -0
- package/dist/types/types/sync.d.ts.map +1 -0
- package/dist/types/types/vc.d.ts +7 -0
- package/dist/types/types/vc.d.ts.map +1 -0
- package/dist/types/utils-internal.d.ts +50 -0
- package/dist/types/utils-internal.d.ts.map +1 -0
- package/dist/types/utils.d.ts +37 -0
- package/dist/types/utils.d.ts.map +1 -0
- package/package.json +112 -0
- package/src/agent-did-resolver-cache.ts +95 -0
- package/src/bearer-identity.ts +42 -0
- package/src/connect.ts +296 -0
- package/src/crypto-api.ts +593 -0
- package/src/did-api.ts +429 -0
- package/src/dwn-api.ts +462 -0
- package/src/dwn-registrar.ts +127 -0
- package/src/hd-identity-vault.ts +853 -0
- package/src/identity-api.ts +324 -0
- package/src/index.ts +30 -0
- package/src/local-key-manager.ts +672 -0
- package/src/oidc.ts +857 -0
- package/src/permissions-api.ts +408 -0
- package/src/prototyping/clients/dwn-rpc-types.ts +55 -0
- package/src/prototyping/clients/dwn-server-info-cache-memory.ts +79 -0
- package/src/prototyping/clients/http-dwn-rpc-client.ts +110 -0
- package/src/prototyping/clients/json-rpc-socket.ts +169 -0
- package/src/prototyping/clients/json-rpc.ts +113 -0
- package/src/prototyping/clients/server-info-types.ts +21 -0
- package/src/prototyping/clients/web-socket-clients.ts +100 -0
- package/src/prototyping/common/object.ts +15 -0
- package/src/prototyping/common/type-utils.ts +6 -0
- package/src/prototyping/crypto/algorithms/aes-gcm.ts +211 -0
- package/src/prototyping/crypto/algorithms/aes-kw.ts +164 -0
- package/src/prototyping/crypto/algorithms/ecdsa.ts +365 -0
- package/src/prototyping/crypto/algorithms/eddsa.ts +310 -0
- package/src/prototyping/crypto/algorithms/hkdf.ts +40 -0
- package/src/prototyping/crypto/algorithms/pbkdf2.ts +44 -0
- package/src/prototyping/crypto/crypto-error.ts +45 -0
- package/src/prototyping/crypto/dsa.ts +367 -0
- package/src/prototyping/crypto/jose/jwe-compact.ts +225 -0
- package/src/prototyping/crypto/jose/jwe-flattened.ts +459 -0
- package/src/prototyping/crypto/jose/jwe.ts +653 -0
- package/src/prototyping/crypto/primitives/aes-gcm.ts +374 -0
- package/src/prototyping/crypto/primitives/aes-kw.ts +271 -0
- package/src/prototyping/crypto/primitives/hkdf.ts +121 -0
- package/src/prototyping/crypto/primitives/pbkdf2.ts +116 -0
- package/src/prototyping/crypto/types/cipher.ts +17 -0
- package/src/prototyping/crypto/types/crypto-api.ts +78 -0
- package/src/prototyping/crypto/types/key-converter.ts +53 -0
- package/src/prototyping/crypto/types/key-deriver.ts +56 -0
- package/src/prototyping/crypto/types/key-io.ts +51 -0
- package/src/prototyping/crypto/types/key-manager.ts +83 -0
- package/src/prototyping/crypto/types/key-wrapper.ts +17 -0
- package/src/prototyping/crypto/types/params-direct.ts +95 -0
- package/src/prototyping/crypto/types/params-kms.ts +76 -0
- package/src/prototyping/crypto/utils.ts +41 -0
- package/src/prototyping/dids/resolver-cache-memory.ts +83 -0
- package/src/prototyping/dids/utils.ts +10 -0
- package/src/rpc-client.ts +162 -0
- package/src/store-data-protocols.ts +40 -0
- package/src/store-data.ts +400 -0
- package/src/store-did.ts +105 -0
- package/src/store-identity.ts +109 -0
- package/src/store-key.ts +104 -0
- package/src/sync-api.ts +71 -0
- package/src/sync-engine-level.ts +714 -0
- package/src/test-harness.ts +330 -0
- package/src/types/agent.ts +195 -0
- package/src/types/dwn.ts +278 -0
- package/src/types/identity-vault.ts +137 -0
- package/src/types/identity.ts +18 -0
- package/src/types/key-manager.ts +15 -0
- package/src/types/permissions.ts +115 -0
- package/src/types/sync.ts +58 -0
- package/src/types/vc.ts +7 -0
- package/src/utils-internal.ts +157 -0
- package/src/utils.ts +181 -0
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
import { PermissionGrant, PermissionGrantData, PermissionRequestData, PermissionRevocationData, PermissionsProtocol } from '@enbox/dwn-sdk-js';
|
|
2
|
+
import { Web5Agent } from './types/agent.js';
|
|
3
|
+
import { DwnDataEncodedRecordsWriteMessage, DwnInterface, DwnMessageParams, DwnMessagesPermissionScope, DwnPermissionGrant, DwnPermissionRequest, DwnPermissionScope, DwnProtocolPermissionScope, DwnRecordsPermissionScope, ProcessDwnRequest } from './types/dwn.js';
|
|
4
|
+
import { Convert, TtlCache } from '@enbox/common';
|
|
5
|
+
import { CreateGrantParams, CreateRequestParams, CreateRevocationParams, FetchPermissionRequestParams, FetchPermissionsParams, GetPermissionParams, IsGrantRevokedParams, PermissionGrantEntry, PermissionRequestEntry, PermissionRevocationEntry, PermissionsApi } from './types/permissions.js';
|
|
6
|
+
import { isRecordsType } from './dwn-api.js';
|
|
7
|
+
|
|
8
|
+
export class AgentPermissionsApi implements PermissionsApi {
|
|
9
|
+
|
|
10
|
+
/** cache for fetching a permission {@link PermissionGrant}, keyed by a specific MessageType and protocol */
|
|
11
|
+
private _cachedPermissions: TtlCache<string, PermissionGrantEntry> = new TtlCache({ ttl: 60 * 1000 });
|
|
12
|
+
|
|
13
|
+
private _agent?: Web5Agent;
|
|
14
|
+
|
|
15
|
+
get agent(): Web5Agent {
|
|
16
|
+
if (!this._agent) {
|
|
17
|
+
throw new Error('AgentPermissionsApi: Agent is not set');
|
|
18
|
+
}
|
|
19
|
+
return this._agent;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
set agent(agent:Web5Agent) {
|
|
23
|
+
this._agent = agent;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
constructor({ agent }: { agent?: Web5Agent } = {}) {
|
|
27
|
+
this._agent = agent;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
async getPermissionForRequest({
|
|
31
|
+
connectedDid,
|
|
32
|
+
delegateDid,
|
|
33
|
+
delegate,
|
|
34
|
+
messageType,
|
|
35
|
+
protocol,
|
|
36
|
+
cached = false
|
|
37
|
+
}: GetPermissionParams): Promise<PermissionGrantEntry> {
|
|
38
|
+
// Currently we only support finding grants based on protocols
|
|
39
|
+
// A different approach may be necessary when we introduce `protocolPath` and `contextId` specific impersonation
|
|
40
|
+
const cacheKey = [ connectedDid, delegateDid, messageType, protocol ].join('~');
|
|
41
|
+
const cachedGrant = cached ? this._cachedPermissions.get(cacheKey) : undefined;
|
|
42
|
+
if (cachedGrant) {
|
|
43
|
+
return cachedGrant;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const permissionGrants = await this.fetchGrants({
|
|
47
|
+
author : delegateDid,
|
|
48
|
+
target : delegateDid,
|
|
49
|
+
grantor : connectedDid,
|
|
50
|
+
grantee : delegateDid,
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
// get the delegate grants that match the messageParams and are associated with the connectedDid as the grantor
|
|
54
|
+
const grant = await AgentPermissionsApi.matchGrantFromArray(
|
|
55
|
+
connectedDid,
|
|
56
|
+
delegateDid,
|
|
57
|
+
{ messageType, protocol },
|
|
58
|
+
permissionGrants,
|
|
59
|
+
delegate
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
if (!grant) {
|
|
63
|
+
throw new Error(`CachedPermissions: No permissions found for ${messageType}: ${protocol}`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
this._cachedPermissions.set(cacheKey, grant);
|
|
67
|
+
return grant;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
async fetchGrants({
|
|
71
|
+
author,
|
|
72
|
+
target,
|
|
73
|
+
grantee,
|
|
74
|
+
grantor,
|
|
75
|
+
protocol,
|
|
76
|
+
remote = false
|
|
77
|
+
}: FetchPermissionsParams): Promise<PermissionGrantEntry[]> {
|
|
78
|
+
|
|
79
|
+
// filter by a protocol using tags if provided
|
|
80
|
+
const tags = protocol ? { protocol } : undefined;
|
|
81
|
+
|
|
82
|
+
const params: ProcessDwnRequest<DwnInterface.RecordsQuery> = {
|
|
83
|
+
author : author,
|
|
84
|
+
target : target,
|
|
85
|
+
messageType : DwnInterface.RecordsQuery,
|
|
86
|
+
messageParams : {
|
|
87
|
+
filter: {
|
|
88
|
+
author : grantor, // the author of the grant would be the grantor
|
|
89
|
+
recipient : grantee, // the recipient of the grant would be the grantee
|
|
90
|
+
protocol : PermissionsProtocol.uri,
|
|
91
|
+
protocolPath : PermissionsProtocol.grantPath,
|
|
92
|
+
tags
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
const { reply } = remote ? await this.agent.sendDwnRequest(params) : await this.agent.processDwnRequest(params);
|
|
98
|
+
if (reply.status.code !== 200) {
|
|
99
|
+
throw new Error(`PermissionsApi: Failed to fetch grants: ${reply.status.detail}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const grants:PermissionGrantEntry[] = [];
|
|
103
|
+
for (const entry of reply.entries! as DwnDataEncodedRecordsWriteMessage[]) {
|
|
104
|
+
// TODO: Check for revocation status based on a request parameter and filter out revoked grants
|
|
105
|
+
const grant = await DwnPermissionGrant.parse(entry);
|
|
106
|
+
grants.push({ grant, message: entry });
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
return grants;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async fetchRequests({
|
|
113
|
+
author,
|
|
114
|
+
target,
|
|
115
|
+
protocol,
|
|
116
|
+
remote = false
|
|
117
|
+
}:FetchPermissionRequestParams):Promise<PermissionRequestEntry[]> {
|
|
118
|
+
// filter by a protocol using tags if provided
|
|
119
|
+
const tags = protocol ? { protocol } : undefined;
|
|
120
|
+
|
|
121
|
+
const params: ProcessDwnRequest<DwnInterface.RecordsQuery> = {
|
|
122
|
+
author : author,
|
|
123
|
+
target : target,
|
|
124
|
+
messageType : DwnInterface.RecordsQuery,
|
|
125
|
+
messageParams : {
|
|
126
|
+
filter: {
|
|
127
|
+
protocol : PermissionsProtocol.uri,
|
|
128
|
+
protocolPath : PermissionsProtocol.requestPath,
|
|
129
|
+
tags
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
const { reply } = remote ? await this.agent.sendDwnRequest(params) : await this.agent.processDwnRequest(params);
|
|
135
|
+
if (reply.status.code !== 200) {
|
|
136
|
+
throw new Error(`PermissionsApi: Failed to fetch requests: ${reply.status.detail}`);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const requests: PermissionRequestEntry[] = [];
|
|
140
|
+
for (const entry of reply.entries! as DwnDataEncodedRecordsWriteMessage[]) {
|
|
141
|
+
const request = await DwnPermissionRequest.parse(entry);
|
|
142
|
+
requests.push({ request, message: entry });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
return requests;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
async isGrantRevoked({
|
|
149
|
+
author,
|
|
150
|
+
target,
|
|
151
|
+
grantRecordId,
|
|
152
|
+
remote = false
|
|
153
|
+
}: IsGrantRevokedParams): Promise<boolean> {
|
|
154
|
+
const params: ProcessDwnRequest<DwnInterface.RecordsRead> = {
|
|
155
|
+
author,
|
|
156
|
+
target,
|
|
157
|
+
messageType : DwnInterface.RecordsRead,
|
|
158
|
+
messageParams : {
|
|
159
|
+
filter: {
|
|
160
|
+
parentId : grantRecordId,
|
|
161
|
+
protocol : PermissionsProtocol.uri,
|
|
162
|
+
protocolPath : PermissionsProtocol.revocationPath,
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const { reply: revocationReply } = remote ? await this.agent.sendDwnRequest(params) : await this.agent.processDwnRequest(params);
|
|
168
|
+
if (revocationReply.status.code === 404) {
|
|
169
|
+
// no revocation found, the grant is not revoked
|
|
170
|
+
return false;
|
|
171
|
+
} else if (revocationReply.status.code === 200) {
|
|
172
|
+
// a revocation was found, the grant is revoked
|
|
173
|
+
return true;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
throw new Error(`PermissionsApi: Failed to check if grant is revoked: ${revocationReply.status.detail}`);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
async createGrant(params: CreateGrantParams): Promise<PermissionGrantEntry> {
|
|
180
|
+
const { author, store = false, delegated = false, ...createGrantParams } = params;
|
|
181
|
+
|
|
182
|
+
let tags = undefined;
|
|
183
|
+
if (PermissionsProtocol.hasProtocolScope(createGrantParams.scope)) {
|
|
184
|
+
tags = { protocol: createGrantParams.scope.protocol };
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const permissionGrantData: PermissionGrantData = {
|
|
188
|
+
dateExpires : createGrantParams.dateExpires,
|
|
189
|
+
requestId : createGrantParams.requestId,
|
|
190
|
+
description : createGrantParams.description,
|
|
191
|
+
delegated,
|
|
192
|
+
scope : createGrantParams.scope
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
const permissionsGrantBytes = Convert.object(permissionGrantData).toUint8Array();
|
|
196
|
+
|
|
197
|
+
const messageParams: DwnMessageParams[DwnInterface.RecordsWrite] = {
|
|
198
|
+
recipient : createGrantParams.grantedTo,
|
|
199
|
+
protocol : PermissionsProtocol.uri,
|
|
200
|
+
protocolPath : PermissionsProtocol.grantPath,
|
|
201
|
+
dataFormat : 'application/json',
|
|
202
|
+
tags
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
const { reply, message } = await this.agent.processDwnRequest({
|
|
206
|
+
store,
|
|
207
|
+
author,
|
|
208
|
+
target : author,
|
|
209
|
+
messageType : DwnInterface.RecordsWrite,
|
|
210
|
+
messageParams,
|
|
211
|
+
dataStream : new Blob([ permissionsGrantBytes ])
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
if (reply.status.code !== 202) {
|
|
215
|
+
throw new Error(`PermissionsApi: Failed to create grant: ${reply.status.detail}`);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
const dataEncodedMessage: DwnDataEncodedRecordsWriteMessage = {
|
|
219
|
+
...message!,
|
|
220
|
+
encodedData: Convert.uint8Array(permissionsGrantBytes).toBase64Url()
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const grant = await DwnPermissionGrant.parse(dataEncodedMessage);
|
|
224
|
+
|
|
225
|
+
return { grant, message: dataEncodedMessage };
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
async createRequest(params: CreateRequestParams): Promise<PermissionRequestEntry> {
|
|
229
|
+
const { author, store = false, delegated = false, ...createGrantParams } = params;
|
|
230
|
+
|
|
231
|
+
let tags = undefined;
|
|
232
|
+
if (PermissionsProtocol.hasProtocolScope(createGrantParams.scope)) {
|
|
233
|
+
tags = { protocol: createGrantParams.scope.protocol };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const permissionRequestData: PermissionRequestData = {
|
|
237
|
+
description : createGrantParams.description,
|
|
238
|
+
delegated,
|
|
239
|
+
scope : createGrantParams.scope
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
const permissionRequestBytes = Convert.object(permissionRequestData).toUint8Array();
|
|
243
|
+
|
|
244
|
+
const messageParams: DwnMessageParams[DwnInterface.RecordsWrite] = {
|
|
245
|
+
protocol : PermissionsProtocol.uri,
|
|
246
|
+
protocolPath : PermissionsProtocol.requestPath,
|
|
247
|
+
dataFormat : 'application/json',
|
|
248
|
+
tags
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
const { reply, message } = await this.agent.processDwnRequest({
|
|
252
|
+
store,
|
|
253
|
+
author,
|
|
254
|
+
target : author,
|
|
255
|
+
messageType : DwnInterface.RecordsWrite,
|
|
256
|
+
messageParams,
|
|
257
|
+
dataStream : new Blob([ permissionRequestBytes ])
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
if (reply.status.code !== 202) {
|
|
261
|
+
throw new Error(`PermissionsApi: Failed to create request: ${reply.status.detail}`);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
const dataEncodedMessage: DwnDataEncodedRecordsWriteMessage = {
|
|
265
|
+
...message!,
|
|
266
|
+
encodedData: Convert.uint8Array(permissionRequestBytes).toBase64Url()
|
|
267
|
+
};
|
|
268
|
+
|
|
269
|
+
const request = await DwnPermissionRequest.parse(dataEncodedMessage);
|
|
270
|
+
|
|
271
|
+
return { request, message: dataEncodedMessage };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async createRevocation(params: CreateRevocationParams): Promise<PermissionRevocationEntry> {
|
|
275
|
+
const { author, store = false, grant, description } = params;
|
|
276
|
+
|
|
277
|
+
const revokeData: PermissionRevocationData = { description };
|
|
278
|
+
|
|
279
|
+
const permissionRevocationBytes = Convert.object(revokeData).toUint8Array();
|
|
280
|
+
|
|
281
|
+
let tags = undefined;
|
|
282
|
+
if (PermissionsProtocol.hasProtocolScope(grant.scope)) {
|
|
283
|
+
tags = { protocol: grant.scope.protocol };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
const messageParams: DwnMessageParams[DwnInterface.RecordsWrite] = {
|
|
287
|
+
parentContextId : grant.id,
|
|
288
|
+
protocol : PermissionsProtocol.uri,
|
|
289
|
+
protocolPath : PermissionsProtocol.revocationPath,
|
|
290
|
+
dataFormat : 'application/json',
|
|
291
|
+
tags
|
|
292
|
+
};
|
|
293
|
+
|
|
294
|
+
const { reply, message } = await this.agent.processDwnRequest({
|
|
295
|
+
store,
|
|
296
|
+
author,
|
|
297
|
+
target : author,
|
|
298
|
+
messageType : DwnInterface.RecordsWrite,
|
|
299
|
+
messageParams,
|
|
300
|
+
dataStream : new Blob([ permissionRevocationBytes ])
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
if (reply.status.code !== 202) {
|
|
304
|
+
throw new Error(`PermissionsApi: Failed to create revocation: ${reply.status.detail}`);
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const dataEncodedMessage: DwnDataEncodedRecordsWriteMessage = {
|
|
308
|
+
...message!,
|
|
309
|
+
encodedData: Convert.uint8Array(permissionRevocationBytes).toBase64Url()
|
|
310
|
+
};
|
|
311
|
+
|
|
312
|
+
return { message: dataEncodedMessage };
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
async clear():Promise<void> {
|
|
316
|
+
this._cachedPermissions.clear();
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Matches the appropriate grant from an array of grants based on the provided parameters.
|
|
321
|
+
*
|
|
322
|
+
* @param delegated if true, only delegated grants are turned, if false all grants are returned including delegated ones.
|
|
323
|
+
*/
|
|
324
|
+
static async matchGrantFromArray<T extends DwnInterface>(
|
|
325
|
+
grantor: string,
|
|
326
|
+
grantee: string,
|
|
327
|
+
messageParams: {
|
|
328
|
+
messageType: T,
|
|
329
|
+
protocol?: string,
|
|
330
|
+
protocolPath?: string,
|
|
331
|
+
contextId?: string,
|
|
332
|
+
},
|
|
333
|
+
grants: PermissionGrantEntry[],
|
|
334
|
+
delegated: boolean = false
|
|
335
|
+
): Promise<PermissionGrantEntry | undefined> {
|
|
336
|
+
for (const entry of grants) {
|
|
337
|
+
const { grant, message } = entry;
|
|
338
|
+
if (delegated === true && grant.delegated !== true) {
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
const { messageType, protocol, protocolPath, contextId } = messageParams;
|
|
342
|
+
|
|
343
|
+
if (this.matchScopeFromGrant(grantor, grantee, messageType, grant, protocol, protocolPath, contextId)) {
|
|
344
|
+
return { grant, message };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
private static matchScopeFromGrant<T extends DwnInterface>(
|
|
350
|
+
grantor: string,
|
|
351
|
+
grantee: string,
|
|
352
|
+
messageType: T,
|
|
353
|
+
grant: PermissionGrant,
|
|
354
|
+
protocol?: string,
|
|
355
|
+
protocolPath?: string,
|
|
356
|
+
contextId?: string
|
|
357
|
+
): boolean {
|
|
358
|
+
// Check if the grant matches the provided parameters
|
|
359
|
+
if (grant.grantee !== grantee || grant.grantor !== grantor) {
|
|
360
|
+
return false;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
const scope = grant.scope;
|
|
364
|
+
const scopeMessageType = scope.interface + scope.method;
|
|
365
|
+
if (scopeMessageType === messageType) {
|
|
366
|
+
if (isRecordsType(messageType)) {
|
|
367
|
+
const recordScope = scope as DwnRecordsPermissionScope;
|
|
368
|
+
if (recordScope.protocol !== protocol) {
|
|
369
|
+
return false;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// If the grant scope is not restricted to a specific context or protocol path, it is unrestricted and can be used
|
|
373
|
+
if (this.isUnrestrictedProtocolScope(recordScope)) {
|
|
374
|
+
return true;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// protocolPath and contextId are mutually exclusive
|
|
378
|
+
// If the permission is scoped to a protocolPath and the permissionParams matches that path, this grant can be used
|
|
379
|
+
if (recordScope.protocolPath !== undefined && recordScope.protocolPath === protocolPath) {
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
// If the permission is scoped to a contextId and the permissionParams starts with that contextId, this grant can be used
|
|
384
|
+
if (recordScope.contextId !== undefined && contextId?.startsWith(recordScope.contextId)) {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
} else {
|
|
388
|
+
const messagesScope = scope as DwnMessagesPermissionScope | DwnProtocolPermissionScope;
|
|
389
|
+
// Checks for unrestricted protocol scope, if no protocol is defined in the scope it is unrestricted
|
|
390
|
+
if (messagesScope.protocol === undefined) {
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
if (messagesScope.protocol !== protocol) {
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return this.isUnrestrictedProtocolScope(messagesScope);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
return false;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
private static isUnrestrictedProtocolScope(scope: DwnPermissionScope & { contextId?: string, protocolPath?: string }): boolean {
|
|
406
|
+
return scope.contextId === undefined && scope.protocolPath === undefined;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { RecordsReadReply, UnionMessageReply, MessageSubscriptionHandler, RecordSubscriptionHandler } from '@enbox/dwn-sdk-js';
|
|
2
|
+
|
|
3
|
+
export interface SerializableDwnMessage {
|
|
4
|
+
toJSON(): string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export type DwnSubscriptionHandler = MessageSubscriptionHandler | RecordSubscriptionHandler;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Interface for communicating with {@link https://github.com/TBD54566975/dwn-server | DWN Servers}
|
|
11
|
+
* via JSON-RPC, supporting operations like sending DWN requests.
|
|
12
|
+
*/
|
|
13
|
+
export interface DwnRpc {
|
|
14
|
+
/**
|
|
15
|
+
* Lists the transport protocols supported by the DWN RPC client, such as HTTP or HTTPS.
|
|
16
|
+
* @returns An array of strings representing the supported transport protocols.
|
|
17
|
+
*/
|
|
18
|
+
get transportProtocols(): string[]
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Sends a request to a DWN Server using the specified DWN RPC request parameters.
|
|
22
|
+
*
|
|
23
|
+
* @param request - The DWN RPC request containing the URL, target DID, message, and optional data.
|
|
24
|
+
* @returns A promise that resolves to the response from the DWN server.
|
|
25
|
+
*/
|
|
26
|
+
sendDwnRequest(request: DwnRpcRequest): Promise<DwnRpcResponse>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Represents a JSON RPC request to a DWN server, including the URL, target DID, the message to be
|
|
32
|
+
* processed, and optional data.
|
|
33
|
+
*/
|
|
34
|
+
export type DwnRpcRequest = {
|
|
35
|
+
/** Optional data to be sent with the request. */
|
|
36
|
+
data?: any;
|
|
37
|
+
|
|
38
|
+
/** The URL of the DWN server to which the request is sent. */
|
|
39
|
+
dwnUrl: string;
|
|
40
|
+
|
|
41
|
+
/** The message to be processed by the DWN server, which can be a serializable DWN message. */
|
|
42
|
+
message: SerializableDwnMessage | any;
|
|
43
|
+
|
|
44
|
+
/** The DID of the target to which the message is addressed. */
|
|
45
|
+
targetDid: string;
|
|
46
|
+
|
|
47
|
+
/** Optional subscription handler for DWN message events. */
|
|
48
|
+
subscriptionHandler?: DwnSubscriptionHandler;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Represents the JSON RPC response from a DWN server to a request, combining the results of various
|
|
53
|
+
* DWN operations.
|
|
54
|
+
*/
|
|
55
|
+
export type DwnRpcResponse = UnionMessageReply & RecordsReadReply;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
|
|
2
|
+
import ms from 'ms';
|
|
3
|
+
import { TtlCache } from '@enbox/common';
|
|
4
|
+
import { DwnServerInfoCache, ServerInfo } from './server-info-types.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Configuration parameters for creating an in-memory cache for DWN ServerInfo entries.
|
|
8
|
+
*
|
|
9
|
+
* Allows customization of the cache time-to-live (TTL) setting.
|
|
10
|
+
*/
|
|
11
|
+
export type DwnServerInfoCacheMemoryParams = {
|
|
12
|
+
/**
|
|
13
|
+
* Optional. The time-to-live for cache entries, expressed as a string (e.g., '1h', '15m').
|
|
14
|
+
* Determines how long a cache entry should remain valid before being considered expired.
|
|
15
|
+
*
|
|
16
|
+
* Defaults to '15m' if not specified.
|
|
17
|
+
*/
|
|
18
|
+
ttl?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export class DwnServerInfoCacheMemory implements DwnServerInfoCache {
|
|
22
|
+
private cache: TtlCache<string, ServerInfo>;
|
|
23
|
+
|
|
24
|
+
constructor({ ttl = '15m' }: DwnServerInfoCacheMemoryParams= {}) {
|
|
25
|
+
this.cache = new TtlCache({ ttl: ms(ttl) });
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves a DWN ServerInfo entry from the cache.
|
|
30
|
+
*
|
|
31
|
+
* If the cached item has exceeded its TTL, it's scheduled for deletion and undefined is returned.
|
|
32
|
+
*
|
|
33
|
+
* @param dwnUrl - The DWN URL endpoint string used as the key for getting the entry.
|
|
34
|
+
* @returns The cached DWN ServerInfo entry or undefined if not found or expired.
|
|
35
|
+
*/
|
|
36
|
+
public async get(dwnUrl: string): Promise<ServerInfo| undefined> {
|
|
37
|
+
return this.cache.get(dwnUrl);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Stores a DWN ServerInfo entry in the cache with a TTL.
|
|
42
|
+
*
|
|
43
|
+
* @param dwnUrl - The DWN URL endpoint string used as the key for storing the entry.
|
|
44
|
+
* @param value - The DWN ServerInfo entry to be cached.
|
|
45
|
+
* @returns A promise that resolves when the operation is complete.
|
|
46
|
+
*/
|
|
47
|
+
public async set(dwnUrl: string, value: ServerInfo): Promise<void> {
|
|
48
|
+
this.cache.set(dwnUrl, value);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Deletes a DWN ServerInfo entry from the cache.
|
|
53
|
+
*
|
|
54
|
+
* @param dwnUrl - The DWN URL endpoint string used as the key for deletion.
|
|
55
|
+
* @returns A promise that resolves when the operation is complete.
|
|
56
|
+
*/
|
|
57
|
+
public async delete(dwnUrl: string): Promise<void> {
|
|
58
|
+
this.cache.delete(dwnUrl);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Clears all entries from the cache.
|
|
63
|
+
*
|
|
64
|
+
* @returns A promise that resolves when the operation is complete.
|
|
65
|
+
*/
|
|
66
|
+
public async clear(): Promise<void> {
|
|
67
|
+
this.cache.clear();
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* This method is a no-op but exists to be consistent with other DWN ServerInfo Cache
|
|
72
|
+
* implementations.
|
|
73
|
+
*
|
|
74
|
+
* @returns A promise that resolves immediately.
|
|
75
|
+
*/
|
|
76
|
+
public async close(): Promise<void> {
|
|
77
|
+
// No-op since there is no underlying store to close.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import type { JsonRpcResponse } from './json-rpc.js';
|
|
2
|
+
import type { DwnRpc, DwnRpcRequest, DwnRpcResponse } from './dwn-rpc-types.js';
|
|
3
|
+
|
|
4
|
+
import { createJsonRpcRequest, parseJson } from './json-rpc.js';
|
|
5
|
+
import { CryptoUtils } from '@enbox/crypto';
|
|
6
|
+
import { DwnServerInfoCache, ServerInfo } from './server-info-types.js';
|
|
7
|
+
import { DwnServerInfoCacheMemory } from './dwn-server-info-cache-memory.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* HTTP client that can be used to communicate with Dwn Servers
|
|
11
|
+
*/
|
|
12
|
+
export class HttpDwnRpcClient implements DwnRpc {
|
|
13
|
+
private serverInfoCache: DwnServerInfoCache;
|
|
14
|
+
constructor(serverInfoCache?: DwnServerInfoCache) {
|
|
15
|
+
this.serverInfoCache = serverInfoCache ?? new DwnServerInfoCacheMemory();
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get transportProtocols() { return ['http:', 'https:']; }
|
|
19
|
+
|
|
20
|
+
async sendDwnRequest(request: DwnRpcRequest): Promise<DwnRpcResponse> {
|
|
21
|
+
const requestId = CryptoUtils.randomUuid();
|
|
22
|
+
const jsonRpcRequest = createJsonRpcRequest(requestId, 'dwn.processMessage', {
|
|
23
|
+
target : request.targetDid,
|
|
24
|
+
message : request.message
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const fetchOpts = {
|
|
28
|
+
method : 'POST',
|
|
29
|
+
headers : {
|
|
30
|
+
'dwn-request': JSON.stringify(jsonRpcRequest)
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
if (request.data) {
|
|
35
|
+
// @ts-expect-error TODO: REMOVE
|
|
36
|
+
fetchOpts.headers['content-type'] = 'application/octet-stream';
|
|
37
|
+
// @ts-expect-error TODO: REMOVE
|
|
38
|
+
fetchOpts['body'] = request.data;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const resp = await fetch(request.dwnUrl, fetchOpts);
|
|
42
|
+
let dwnRpcResponse: JsonRpcResponse;
|
|
43
|
+
|
|
44
|
+
// check to see if response is in header first. if it is, that means the response is a ReadableStream
|
|
45
|
+
let dataStream;
|
|
46
|
+
const { headers } = resp;
|
|
47
|
+
if (headers.has('dwn-response')) {
|
|
48
|
+
// @ts-expect-error TODO: REMOVE
|
|
49
|
+
const jsonRpcResponse = parseJson(headers.get('dwn-response')) as JsonRpcResponse;
|
|
50
|
+
|
|
51
|
+
if (jsonRpcResponse == null) {
|
|
52
|
+
throw new Error(`failed to parse json rpc response. dwn url: ${request.dwnUrl}`);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
dataStream = resp.body;
|
|
56
|
+
dwnRpcResponse = jsonRpcResponse;
|
|
57
|
+
} else {
|
|
58
|
+
// TODO: wonder if i need to try/catch this?
|
|
59
|
+
const responseBody = await resp.text();
|
|
60
|
+
dwnRpcResponse = JSON.parse(responseBody);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (dwnRpcResponse.error) {
|
|
64
|
+
const { code, message } = dwnRpcResponse.error;
|
|
65
|
+
throw new Error(`(${code}) - ${message}`);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
const { reply } = dwnRpcResponse.result;
|
|
69
|
+
if (dataStream && reply.record) {
|
|
70
|
+
reply.record.data = dataStream;
|
|
71
|
+
} else if (dataStream && reply.entry) {
|
|
72
|
+
reply.entry.data = dataStream;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return reply as DwnRpcResponse;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async getServerInfo(dwnUrl: string): Promise<ServerInfo> {
|
|
79
|
+
const serverInfo = await this.serverInfoCache.get(dwnUrl);
|
|
80
|
+
if (serverInfo) {
|
|
81
|
+
return serverInfo;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const url = new URL(dwnUrl);
|
|
85
|
+
|
|
86
|
+
// add `/info` to the dwn server url path
|
|
87
|
+
url.pathname.endsWith('/') ? url.pathname += 'info' : url.pathname += '/info';
|
|
88
|
+
|
|
89
|
+
try {
|
|
90
|
+
const response = await fetch(url.toString());
|
|
91
|
+
if(response.ok) {
|
|
92
|
+
const results = await response.json() as ServerInfo;
|
|
93
|
+
|
|
94
|
+
// explicitly return and cache only the desired properties.
|
|
95
|
+
const serverInfo = {
|
|
96
|
+
registrationRequirements : results.registrationRequirements,
|
|
97
|
+
maxFileSize : results.maxFileSize,
|
|
98
|
+
webSocketSupport : results.webSocketSupport,
|
|
99
|
+
};
|
|
100
|
+
this.serverInfoCache.set(dwnUrl, serverInfo);
|
|
101
|
+
|
|
102
|
+
return serverInfo;
|
|
103
|
+
} else {
|
|
104
|
+
throw new Error(`HTTP (${response.status}) - ${response.statusText}`);
|
|
105
|
+
}
|
|
106
|
+
} catch(error: any) {
|
|
107
|
+
throw new Error(`Error encountered while processing response from ${url.toString()}: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|