@ucanto/core
Advanced tools
Comparing version 0.6.0 to 0.7.0
@@ -1,3 +0,4 @@ | ||
export function isLink(value: API.Proof): value is UCAN.Proof<UCAN.Capability<UCAN.Ability, `${string}:${string}`>, number>; | ||
export function isDelegation(proof: API.Proof): proof is API.Delegation<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>; | ||
export function isLink(value: API.Proof): value is UCAN.Link<UCAN.Capabilities, UCAN.MulticodecCode<number, string>, UCAN.SigAlg>; | ||
export function isDelegation(proof: API.Proof): proof is API.Delegation<UCAN.Capabilities>; | ||
export function allows<T extends [API.Delegation<UCAN.Capabilities>, ...API.Delegation<UCAN.Capabilities>[]]>(...delegations: T): API.InferAllowedFromDelegations<T>; | ||
/** | ||
@@ -7,33 +8,35 @@ * Represents UCAN chain view over the set of DAG UCAN nodes. You can think of | ||
* | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @template {API.Capabilities} C | ||
* @implements {API.Delegation<C>} | ||
* @extends {DelegationView<C>} | ||
*/ | ||
export class Delegation<C extends [UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]> implements API.Delegation<C> { | ||
export class Delegation<C extends UCAN.Capabilities> implements API.Delegation<C> { | ||
/** | ||
* @param {API.Block<C>} root | ||
* @param {Map<string, API.Block>} [blocks] | ||
* @param {API.UCANBlock<C>} root | ||
* @param {DAG.BlockStore} [blocks] | ||
*/ | ||
constructor(root: API.Block<C>, blocks?: Map<string, API.Block<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]], number>> | undefined); | ||
root: API.Block<C, number>; | ||
blocks: Map<string, API.Block<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]], number>>; | ||
constructor(root: API.UCANBlock<C>, blocks?: DAG.BlockStore<unknown> | undefined); | ||
root: UCAN.Block<C, UCAN.MulticodecCode<number, string>, UCAN.SigAlg>; | ||
blocks: DAG.BlockStore<unknown>; | ||
get version(): `${number}.${number}.${number}`; | ||
get signature(): UCAN.Signature<UCAN.SignPayload<C[number]>, number>; | ||
get cid(): UCAN.Proof<C[number], number>; | ||
get asCID(): UCAN.Proof<C[number], number>; | ||
get bytes(): UCAN.ByteView<UCAN.UCAN<C[number]>>; | ||
get data(): UCAN.View<C[number]>; | ||
export(): IterableIterator<API.Block<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]], number>>; | ||
get signature(): UCAN.SignatureView<unknown, UCAN.SigAlg>; | ||
get cid(): UCAN.IPLDLink<UCAN.UCAN<C>, UCAN.MulticodecCode<number, string>, UCAN.SigAlg, 1>; | ||
link(): UCAN.IPLDLink<UCAN.UCAN<C>, UCAN.MulticodecCode<number, string>, UCAN.SigAlg, 1>; | ||
get asCID(): UCAN.IPLDLink<UCAN.UCAN<C>, UCAN.MulticodecCode<number, string>, UCAN.SigAlg, 1>; | ||
get bytes(): UCAN.ByteView<UCAN.UCAN<C>>; | ||
get data(): UCAN.View<C>; | ||
export(): IterableIterator<API.Transport.Block<any, number, number, 1>>; | ||
iterateIPLDBlocks(): IterableIterator<API.Transport.Block<any, number, number, 1>>; | ||
/** | ||
* @type {API.Proof[]} | ||
*/ | ||
get proofs(): API.Proof<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>[]; | ||
get proofs(): API.Proof<UCAN.Capabilities>[]; | ||
/** | ||
* @type {API.Identity} | ||
* @type {API.Principal} | ||
*/ | ||
get issuer(): UCAN.Identity; | ||
get issuer(): UCAN.Principal<`did:${string}:${string}`>; | ||
/** | ||
* @type {API.Identity} | ||
* @type {API.Principal} | ||
*/ | ||
get audience(): UCAN.Identity; | ||
get audience(): UCAN.Principal<`did:${string}:${string}`>; | ||
/** | ||
@@ -65,21 +68,24 @@ * @returns {C} | ||
iterate(): IterableIterator<API.Delegation>; | ||
delegate(): Delegation<C>; | ||
buildIPLDView(): Delegation<C>; | ||
/** | ||
* @returns {API.DelegationJSON<this>} | ||
*/ | ||
toJSON(): API.DelegationJSON<Delegation<C>>; | ||
} | ||
export function delegate<A extends number, C extends [UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>({ issuer, audience, proofs, ...input }: API.DelegationOptions<C, A>, options?: API.EncodeOptions | undefined): Promise<API.Delegation<C>>; | ||
export function importDAG<C extends [UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>(dag: Iterable<API.Block & { | ||
data?: UCAN.UCAN; | ||
}>): API.Delegation<C>; | ||
export function create<C extends [UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>({ root, blocks }: { | ||
root: API.Block<C, number>; | ||
blocks?: Map<string, API.Block<[UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]], number>> | undefined; | ||
export function delegate<C extends UCAN.Capabilities>({ issuer, audience, proofs, ...input }: API.DelegationOptions<C>, options?: API.EncodeOptions | undefined): Promise<API.Delegation<C>>; | ||
export function exportDAG<C extends UCAN.Capabilities>(root: UCAN.Block<C, UCAN.MulticodecCode<number, string>, UCAN.SigAlg>, blocks: DAG.BlockStore<unknown>): IterableIterator<API.Block>; | ||
export function importDAG<C extends UCAN.Capabilities>(dag: Iterable<API.Block>): API.Delegation<C>; | ||
export function create<C extends UCAN.Capabilities>({ root, blocks }: { | ||
root: UCAN.Block<C, UCAN.MulticodecCode<number, string>, UCAN.SigAlg>; | ||
blocks?: DAG.BlockStore<unknown> | undefined; | ||
}): API.Delegation<C>; | ||
export function view<C extends UCAN.Capabilities, T = undefined>({ root, blocks }: { | ||
root: UCAN.Link<C, UCAN.MulticodecCode<number, string>, UCAN.SigAlg>; | ||
blocks: DAG.BlockStore<unknown>; | ||
}, fallback?: T | undefined): T | API.Delegation<C>; | ||
export { Delegation as View }; | ||
import * as API from "@ucanto/interface"; | ||
import * as UCAN from "@ipld/dag-ucan/src/lib"; | ||
/** | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @param {API.Block<C>} root | ||
* @param {Map<string, API.Block>} blocks | ||
* @returns {IterableIterator<API.Block>} | ||
*/ | ||
declare function exportDAG<C extends [UCAN.Capability<UCAN.Ability, `${string}:${string}`>, ...UCAN.Capability<UCAN.Ability, `${string}:${string}`>[]]>(root: API.Block<C, number>, blocks: Map<string, API.Block>): IterableIterator<API.Block>; | ||
export { exportDAG as export, _export as export, importDAG as import, _import as import, Delegation as View }; | ||
import * as UCAN from "@ipld/dag-ucan/."; | ||
import * as DAG from "./dag.js"; | ||
//# sourceMappingURL=delegation.d.ts.map |
@@ -1,3 +0,21 @@ | ||
export function invoke<Capability extends API.UCAN.Capability<API.UCAN.Ability, `${string}:${string}`>>(options: API.InvocationOptions<Capability>): API.IssuedInvocationView<Capability>; | ||
export function invoke<Capability extends API.Capability<API.Ability, `${string}:${string}`, any>>(options: API.InvocationOptions<Capability>): API.IssuedInvocationView<Capability>; | ||
export function create<C extends API.Capability<API.Ability, `${string}:${string}`, any>>({ root, blocks }: { | ||
root: API.UCANBlock<[C], API.MulticodecCode<number, string>, API.SigAlg>; | ||
blocks?: DAG.BlockStore<unknown> | undefined; | ||
}): API.Invocation<C>; | ||
export function view<C extends API.Capability<API.Ability, `${string}:${string}`, any>, Invocation_1 extends API.Invocation<API.Capability<API.Ability, `${string}:${string}`, unknown>>, T = never>({ root, blocks }: { | ||
root: API.UCANLink<[C], API.MulticodecCode<number, string>, API.SigAlg>; | ||
blocks: DAG.BlockStore<unknown>; | ||
}, fallback?: T | undefined): T | API.Invocation<C>; | ||
/** | ||
* @template {API.Capability} Capability | ||
* @implements {API.Invocation<Capability>} | ||
* @extends {Delegation<[Capability]>} | ||
*/ | ||
export class Invocation<Capability extends API.Capability<API.Ability, `${string}:${string}`, any>> extends Delegation<[Capability]> implements API.Invocation<Capability> { | ||
constructor(root: API.UCANBlock<[Capability], API.MulticodecCode<number, string>, API.SigAlg>, blocks?: DAG.BlockStore<unknown> | undefined); | ||
} | ||
import * as API from "@ucanto/interface"; | ||
import * as DAG from "./dag.js"; | ||
import { Delegation } from "./delegation.js"; | ||
//# sourceMappingURL=invocation.d.ts.map |
@@ -0,6 +1,18 @@ | ||
export * as API from "@ucanto/interface"; | ||
export * as Delegation from "./delegation.js"; | ||
export * as Invocation from "./invocation.js"; | ||
export * as Message from "./message.js"; | ||
export * as Receipt from "./receipt.js"; | ||
export * as DAG from "./dag.js"; | ||
export * as CBOR from "./cbor.js"; | ||
export * as CAR from "./car.js"; | ||
export { invoke } from "./invocation.js"; | ||
export * as UCAN from "@ipld/dag-ucan/src/lib"; | ||
export { sha256 } from "multiformats/hashes/sha2"; | ||
export * as UCAN from "@ipld/dag-ucan/."; | ||
export * as DID from "@ipld/dag-ucan/did"; | ||
export * as Signature from "@ipld/dag-ucan/signature"; | ||
export * from "./result.js"; | ||
export * as Schema from "./schema.js"; | ||
export { delegate, isDelegation } from "./delegation.js"; | ||
export { create as createLink, createV0 as createLegacyLink, isLink, asLink, parse as parseLink, decode as decodeLink } from "./link.js"; | ||
export { create as createLink, createLegacy as createLegacyLink, isLink, parse as parseLink, decode as decodeLink } from "./link.js"; | ||
//# sourceMappingURL=lib.d.ts.map |
@@ -1,9 +0,4 @@ | ||
export function create<Code extends number, Alg extends number>(code: Code, digest: API.UCAN.MultihashDigest<Alg>): API.UCAN.Link<unknown, Code, Alg, 1> & CID; | ||
export function createV0<Alg extends number>(digest: API.UCAN.MultihashDigest<Alg>): API.UCAN.Link<unknown, 112, Alg, 0> & CID; | ||
export function isLink<L extends API.UCAN.Link<unknown, number, number, 0 | 1>>(value: unknown): value is L & CID; | ||
export function asLink<L extends API.UCAN.Link<unknown, number, number, 0 | 1>>(value: unknown): (L & CID) | null; | ||
export function parse<P extends string>(source: string, base?: API.MultibaseDecoder<P> | undefined): API.Link<unknown, number, number, 0 | 1> & CID; | ||
export const decode: typeof CID.decode; | ||
import * as API from "@ucanto/interface"; | ||
import { CID } from "multiformats"; | ||
export * from "multiformats/dist/types/src/link"; | ||
export { base32 } from "multiformats/bases/base32"; | ||
export { base58btc } from "multiformats/bases/base58"; | ||
//# sourceMappingURL=link.d.ts.map |
{ | ||
"name": "@ucanto/core", | ||
"description": "ucanto core", | ||
"version": "0.6.0", | ||
"version": "0.7.0", | ||
"keywords": [ | ||
@@ -24,20 +24,18 @@ "UCAN", | ||
"dependencies": { | ||
"@ipld/car": "^4.1.0", | ||
"@ipld/dag-cbor": "^7.0.1", | ||
"@ipld/dag-ucan": "^1.7.0-beta", | ||
"@ucanto/interface": "^0.7.0", | ||
"multiformats": "^9.6.4" | ||
"@ipld/car": "^5.1.0", | ||
"@ipld/dag-cbor": "^9.0.0", | ||
"@ipld/dag-ucan": "^3.3.2", | ||
"multiformats": "^11.0.0", | ||
"@ucanto/interface": "^0.7.0" | ||
}, | ||
"devDependencies": { | ||
"@types/chai": "^4.3.0", | ||
"@types/chai-subset": "^1.3.3", | ||
"@types/mocha": "^9.1.0", | ||
"@ucanto/authority": "^0.5.0", | ||
"c8": "^7.11.0", | ||
"@types/chai": "^4.3.3", | ||
"@types/mocha": "^10.0.1", | ||
"c8": "^7.13.0", | ||
"chai": "^4.3.6", | ||
"chai-subset": "^1.6.0", | ||
"mocha": "^9.2.2", | ||
"mocha": "^10.1.0", | ||
"nyc": "^15.1.0", | ||
"playwright-test": "^8.0.0", | ||
"typescript": "^4.7.4" | ||
"playwright-test": "^8.2.0", | ||
"typescript": "^4.9.5", | ||
"@ucanto/principal": "^0.7.0" | ||
}, | ||
@@ -73,2 +71,26 @@ "type": "module", | ||
"import": "./src/delegation.js" | ||
}, | ||
"./receipt": { | ||
"types": "./dist/src/receipt.d.ts", | ||
"import": "./src/receipt.js" | ||
}, | ||
"./cbor": { | ||
"types": "./dist/src/cbor.d.ts", | ||
"import": "./src/cbor.js" | ||
}, | ||
"./car": { | ||
"types": "./dist/src/car.d.ts", | ||
"import": "./src/car.js" | ||
}, | ||
"./dag": { | ||
"types": "./dist/src/dag.d.ts", | ||
"import": "./src/dag.js" | ||
}, | ||
"./result": { | ||
"types": "./dist/src/result.d.ts", | ||
"import": "./src/result.js" | ||
}, | ||
"./schema": { | ||
"types": "./dist/src/schema.d.ts", | ||
"import": "./src/schema.js" | ||
} | ||
@@ -86,7 +108,7 @@ }, | ||
"test:node": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha test/*.spec.js", | ||
"test": "npm run test:node", | ||
"test": "c8 --check-coverage --branches 100 --functions 100 --lines 100 mocha --bail test/*.spec.js", | ||
"coverage": "c8 --reporter=html mocha test/*.spec.js && npm_config_yes=true npx st -d coverage -p 8080", | ||
"typecheck": "tsc --build", | ||
"check": "tsc --build", | ||
"build": "tsc --build" | ||
} | ||
} |
import * as UCAN from '@ipld/dag-ucan' | ||
import * as API from '@ucanto/interface' | ||
import * as Link from './link.js' | ||
import * as DAG from './dag.js' | ||
@@ -10,3 +11,3 @@ /** | ||
export const isLink = | ||
/** @type {(value:API.Proof) => value is API.LinkedProof} */ | ||
/** @type {(value:API.Proof) => value is API.UCANLink} */ | ||
(Link.isLink) | ||
@@ -19,9 +20,136 @@ | ||
*/ | ||
export const isDelegation = (proof) => !Link.isLink(proof) | ||
export const isDelegation = proof => !Link.isLink(proof) | ||
/** | ||
* Takes one or more delegations and returns all delegated capabilities in | ||
* UCAN 0.10 format, expanding all the special forms like `with: ucan:*` and | ||
* `can: *` to explicit forms. | ||
* | ||
* Note that this function only considers included proofs and ignores linked | ||
* proofs. It is up to the user of this function to resolve whatever proofs it | ||
* needs and build delegation with them before calling this function. | ||
* | ||
* Also note that this function does not validate the delegations and may | ||
* produce result containing capabilities that escalate, which for the validator | ||
* perspective is no different from not including such capabilities. | ||
* | ||
* @template {[API.Delegation, ...API.Delegation[]]} T | ||
* @param {T} delegations | ||
* @returns {API.InferAllowedFromDelegations<T>} | ||
*/ | ||
export const allows = (...delegations) => { | ||
/** @type {API.Allows} */ | ||
let allow = {} | ||
for (const delegation of delegations) { | ||
for (const { with: uri, can, nb } of iterateCapabilities(delegation)) { | ||
const resource = allow[uri] || (allow[uri] = {}) | ||
const abilities = resource[can] || (resource[can] = []) | ||
abilities.push({ ...nb }) | ||
} | ||
} | ||
return /** @type {API.InferAllowedFromDelegations<T>} */ (allow) | ||
} | ||
/** | ||
* Function takes a delegation and iterates over all the capabilities expanding | ||
* all the special forms like `with: ucan:*` and `can: *`. | ||
* | ||
* Note that this function only considers proofs that are included in the | ||
* delegation, linked proofs will not be resolved nor considered. It is up to | ||
* the user of this function to resolve whatever proofs it needs to consider | ||
* before calling this function. | ||
* | ||
* @param {API.Delegation} delegation | ||
* @returns {Iterable<API.Capability>} | ||
*/ | ||
const iterateCapabilities = function* ({ issuer, capabilities, proofs }) { | ||
for (const own of capabilities) { | ||
// If `with` field is set to `ucan:*` it implies re-delegation of all own | ||
// and delegated capabilities. | ||
if (own.with === 'ucan:*') { | ||
// Fist we include own capabilities. Note that we can not expand `can` | ||
// because it implicitly covers all possible options in the universe. | ||
yield { | ||
...own, | ||
with: issuer.did(), | ||
} | ||
// Next we iterate over all delegated capabilities including ones that | ||
// match ability in the `own.can` field. | ||
for (const proof of proofs) { | ||
// We only consider proofs that are included and ignore linked proofs. | ||
if (isDelegation(proof)) { | ||
for (const capability of iterateCapabilities(proof)) { | ||
// We attempt to match `capability.can` against `own.can` field | ||
// if there is a match we include the capability otherwise we skip | ||
const can = matchAbility(capability.can, own.can) | ||
if (can) { | ||
yield { | ||
...capability, | ||
can, | ||
// We do not know capability semantics so it is impossible | ||
// for us to eliminate capabilities that do not satisfy imposed | ||
// caveats (`own.nb`). Therefore we optimistically assume that | ||
// `own.nb` further constraints `capability.nb` and do a shallow | ||
// merge of the two. As a result we may include capabilities | ||
// that during validation will be considered invalid due to | ||
// constraint violations. While that is not ideal validator | ||
// will treat them as if they were omitted and therefore it | ||
// is a reasonable compromise. | ||
nb: { ...capability.nb, ...Object(own.nb) }, | ||
} | ||
} | ||
} | ||
} | ||
} | ||
} else { | ||
yield own | ||
} | ||
} | ||
} | ||
/** | ||
* Function takes `can` field from the delegated capability and attempts to | ||
* match it against `can` field of the claimed capability. If there is a match | ||
* the function returns more specific `can` field of two, otherwise it returns | ||
* `null`. | ||
* | ||
* @param {API.Ability} provided | ||
* @param {API.Ability} claimed | ||
*/ | ||
const matchAbility = (provided, claimed) => { | ||
// If provided capability delegates all abilities we can derive any `can` | ||
// from it so we return `claimed` as is. | ||
if (provided === '*') { | ||
return claimed | ||
} | ||
// If claimed capability delegates all abilities that includes any `can` | ||
// so we return `provided` as is. | ||
if (claimed === '*') { | ||
return provided | ||
} | ||
// If claimed `can` is a pattern that includes `provided` `can` we return | ||
// `provided` as is. | ||
if (claimed.endsWith('/*') && provided.startsWith(claimed.slice(0, -1))) { | ||
return provided | ||
} | ||
// If provided `can` is a pattern that includes `claimed` `can` we can derive | ||
// `claimed` from it so we return `claimed` as is. | ||
if (provided.endsWith('/*') && claimed.startsWith(provided.slice(0, -1))) { | ||
return claimed | ||
} | ||
// If `can` fields are concrete and the same we have a match and can return it. | ||
if (provided === claimed) { | ||
return provided | ||
} | ||
// otherwise two are incompatible and we return null. | ||
return null | ||
} | ||
/** | ||
* Represents UCAN chain view over the set of DAG UCAN nodes. You can think of | ||
* this as UCAN interface of the CAR. | ||
* | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @template {API.Capabilities} C | ||
* @implements {API.Delegation<C>} | ||
@@ -32,4 +160,4 @@ * @extends {DelegationView<C>} | ||
/** | ||
* @param {API.Block<C>} root | ||
* @param {Map<string, API.Block>} [blocks] | ||
* @param {API.UCANBlock<C>} root | ||
* @param {DAG.BlockStore} [blocks] | ||
*/ | ||
@@ -56,2 +184,5 @@ constructor(root, blocks = new Map()) { | ||
} | ||
link() { | ||
return this.root.cid | ||
} | ||
get asCID() { | ||
@@ -72,2 +203,6 @@ return this.cid | ||
iterateIPLDBlocks() { | ||
return exportDAG(this.root, this.blocks) | ||
} | ||
/** | ||
@@ -81,3 +216,3 @@ * @type {API.Proof[]} | ||
/** | ||
* @type {API.Identity} | ||
* @type {API.Principal} | ||
*/ | ||
@@ -89,3 +224,3 @@ get issuer() { | ||
/** | ||
* @type {API.Identity} | ||
* @type {API.Principal} | ||
*/ | ||
@@ -140,2 +275,23 @@ get audience() { | ||
} | ||
delegate() { | ||
return this | ||
} | ||
buildIPLDView() { | ||
return this | ||
} | ||
/** | ||
* @returns {API.DelegationJSON<this>} | ||
*/ | ||
toJSON() { | ||
return /** @type {any} */ ({ | ||
...this.data.toJSON(), | ||
'/': this.cid.toString(), | ||
prf: this.proofs.map(proof => | ||
isDelegation(proof) ? proof : { '/': proof.toString() } | ||
), | ||
}) | ||
} | ||
} | ||
@@ -158,5 +314,5 @@ | ||
/** | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @param {API.Block<C>} block | ||
* @returns {UCAN.View<C[number]>} | ||
* @template {API.Capabilities} C | ||
* @param {API.UCANBlock<C>} block | ||
* @returns {UCAN.View<C>} | ||
*/ | ||
@@ -178,5 +334,4 @@ const decode = ({ bytes }) => { | ||
* | ||
* @template {number} A | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @param {API.DelegationOptions<C, A>} data | ||
* @template {API.Capabilities} C | ||
* @param {API.DelegationOptions<C>} data | ||
* @param {API.EncodeOptions} [options] | ||
@@ -220,12 +375,12 @@ * @returns {Promise<API.Delegation<C>>} | ||
/** | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @param {API.Block<C>} root | ||
* @param {Map<string, API.Block>} blocks | ||
* @template {API.Capabilities} C | ||
* @param {API.UCANBlock<C>} root | ||
* @param {DAG.BlockStore} blocks | ||
* @returns {IterableIterator<API.Block>} | ||
*/ | ||
const exportDAG = function* (root, blocks) { | ||
export const exportDAG = function* (root, blocks) { | ||
for (const link of decode(root).proofs) { | ||
// Check if block is included in this delegation | ||
const root = blocks.get(link.toString()) | ||
const root = /** @type {UCAN.Block} */ (blocks.get(`${link}`)) | ||
if (root) { | ||
@@ -240,7 +395,7 @@ yield* exportDAG(root, blocks) | ||
/** | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @param {Iterable<API.Block & { data?: UCAN.UCAN }>} dag | ||
* @template {API.Capabilities} C | ||
* @param {Iterable<API.Block>} dag | ||
* @returns {API.Delegation<C>} | ||
*/ | ||
export const importDAG = (dag) => { | ||
export const importDAG = dag => { | ||
/** @type {Array<[string, API.Block]>} */ | ||
@@ -254,7 +409,10 @@ let entries = [] | ||
if (!last) { | ||
throw new RangeError('Empty DAG can not be turned into a dalagetion') | ||
throw new RangeError('Empty DAG can not be turned into a delegation') | ||
} else { | ||
const [, root] = last | ||
return new Delegation(/** @type {API.Block<C>} */ (root), new Map(entries)) | ||
return new Delegation( | ||
/** @type {API.UCANBlock<C>} */ (root), | ||
new Map(entries) | ||
) | ||
} | ||
@@ -264,6 +422,6 @@ } | ||
/** | ||
* @template {[API.Capability, ...API.Capability[]]} C | ||
* @template {API.Capabilities} C | ||
* @param {object} dag | ||
* @param {API.Block<C>} dag.root | ||
* @param {Map<string, API.Block>} [dag.blocks] | ||
* @param {API.UCANBlock<C>} dag.root | ||
* @param {DAG.BlockStore} [dag.blocks] | ||
* @returns {API.Delegation<C>} | ||
@@ -274,5 +432,19 @@ */ | ||
/** | ||
* @template {API.Capabilities} C | ||
* @template [T=undefined] | ||
* @param {object} dag | ||
* @param {API.UCANLink<C>} dag.root | ||
* @param {DAG.BlockStore} dag.blocks | ||
* @param {T} [fallback] | ||
* @returns {API.Delegation<C>|T} | ||
*/ | ||
export const view = ({ root, blocks }, fallback) => { | ||
const block = DAG.get(root, blocks, null) | ||
return block ? create({ root: block, blocks }) : /** @type {T} */ (fallback) | ||
} | ||
/** | ||
* @param {API.Delegation} delegation | ||
*/ | ||
const proofs = (delegation) => { | ||
const proofs = delegation => { | ||
/** @type {API.Proof[]} */ | ||
@@ -285,3 +457,3 @@ const proofs = [] | ||
// view otherwise use a link | ||
const root = blocks.get(link.toString()) | ||
const root = /** @type {UCAN.Block} */ (blocks.get(link.toString())) | ||
proofs.push(root ? create({ root, blocks }) : link) | ||
@@ -296,2 +468,2 @@ } | ||
export { exportDAG as export, importDAG as import, Delegation as View } | ||
export { Delegation as View } |
import * as API from '@ucanto/interface' | ||
import { delegate } from './delegation.js' | ||
import { delegate, Delegation } from './delegation.js' | ||
import * as DAG from './dag.js' | ||
@@ -9,5 +10,39 @@ /** | ||
*/ | ||
export const invoke = (options) => new IssuedInvocation(options) | ||
export const invoke = options => new IssuedInvocation(options) | ||
/** | ||
* @template {API.Capability} C | ||
* @param {object} dag | ||
* @param {API.UCANBlock<[C]>} dag.root | ||
* @param {DAG.BlockStore} [dag.blocks] | ||
* @returns {API.Invocation<C>} | ||
*/ | ||
export const create = ({ root, blocks }) => new Invocation(root, blocks) | ||
/** | ||
* Takes a link of the `root` block and a map of blocks and constructs an | ||
* `Invocation` from it. If `root` is not included in the provided blocks | ||
* provided fallback is returned and if not provided than throws an error. | ||
* If root points to wrong block (that is not an invocation) it will misbehave | ||
* and likely throw some errors on field access. | ||
* | ||
* @template {API.Capability} C | ||
* @template {API.Invocation} Invocation | ||
* @template [T=never] | ||
* @param {object} dag | ||
* @param {API.UCANLink<[C]>} dag.root | ||
* @param {DAG.BlockStore} dag.blocks | ||
* @param {T} [fallback] | ||
* @returns {API.Invocation<C>|T} | ||
*/ | ||
export const view = ({ root, blocks }, fallback) => { | ||
const block = DAG.get(root, blocks, null) | ||
if (block == null) { | ||
return fallback !== undefined ? fallback : DAG.notFound(root) | ||
} | ||
return /** @type {API.Invocation<C>} */ (create({ root: block, blocks })) | ||
} | ||
/** | ||
* @template {API.Capability} Capability | ||
@@ -56,6 +91,10 @@ * @implements {API.IssuedInvocationView<Capability>} | ||
buildIPLDView() { | ||
return delegate(this) | ||
} | ||
/** | ||
* @template {API.InvocationService<Capability>} Service | ||
* @param {API.ConnectionView<Service>} connection | ||
* @returns {Promise<API.InferServiceInvocationReturn<Capability, Service>>} | ||
* @returns {Promise<API.InferReceipt<Capability, Service>>} | ||
*/ | ||
@@ -72,1 +111,8 @@ async execute(connection) { | ||
} | ||
/** | ||
* @template {API.Capability} Capability | ||
* @implements {API.Invocation<Capability>} | ||
* @extends {Delegation<[Capability]>} | ||
*/ | ||
export class Invocation extends Delegation {} |
@@ -0,2 +1,9 @@ | ||
export * as API from '@ucanto/interface' | ||
export * as Delegation from './delegation.js' | ||
export * as Invocation from './invocation.js' | ||
export * as Message from './message.js' | ||
export * as Receipt from './receipt.js' | ||
export * as DAG from './dag.js' | ||
export * as CBOR from './cbor.js' | ||
export * as CAR from './car.js' | ||
export { delegate, isDelegation } from './delegation.js' | ||
@@ -6,8 +13,12 @@ export { invoke } from './invocation.js' | ||
create as createLink, | ||
createV0 as createLegacyLink, | ||
createLegacy as createLegacyLink, | ||
isLink, | ||
asLink, | ||
parse as parseLink, | ||
decode as decodeLink, | ||
} from './link.js' | ||
export { sha256 } from 'multiformats/hashes/sha2' | ||
export * as UCAN from '@ipld/dag-ucan' | ||
export * as DID from '@ipld/dag-ucan/did' | ||
export * as Signature from '@ipld/dag-ucan/signature' | ||
export * from './result.js' | ||
export * as Schema from './schema.js' |
@@ -1,41 +0,3 @@ | ||
import { CID } from 'multiformats' | ||
import * as API from '@ucanto/interface' | ||
/** | ||
* @template {number} Code | ||
* @template {number} Alg | ||
* @param {Code} code | ||
* @param {API.MultihashDigest<Alg>} digest | ||
* @return {API.Link<unknown, Code, Alg, 1> & CID} | ||
*/ | ||
export const create = (code, digest) => | ||
/** @type {any} */ (CID.createV1(code, digest)) | ||
/** | ||
* @template {number} Alg | ||
* @param {API.MultihashDigest<Alg>} digest | ||
* @return {API.Link<unknown, 0x70, Alg, 0> & CID} | ||
*/ | ||
export const createV0 = (digest) => /** @type {any} */ (CID.createV0(digest)) | ||
/** | ||
* Type predicate returns true if value is the link. | ||
* | ||
* @template {API.Link<unknown, number, number, 0|1>} L | ||
* @param {unknown} value | ||
* @returns {value is (L & CID)} | ||
*/ | ||
export const isLink = (value) => | ||
value != null && /** @type {{asCID: unknown}} */ (value).asCID === value | ||
export const asLink = | ||
/** @type {<L extends API.Link<unknown, number, number, 0|1>>(value:L|unknown) => (L & CID)|null} */ | ||
(CID.asCID) | ||
export const parse = | ||
/** @type {<P extends string>(source:string, base?:API.MultibaseDecoder<P>) => API.Link<unknown, number, number, 0|1> & CID} */ | ||
(CID.parse) | ||
export const decode = | ||
/** @type {(bytes:Uint8Array) => API.Link<unknown, number, number, 0|1> & CID} */ | ||
CID.decode | ||
export * from 'multiformats/link' | ||
export { base32 } from 'multiformats/bases/base32' | ||
export { base58btc } from 'multiformats/bases/base58' |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Deprecated
MaintenanceThe maintainer of the package marked it as deprecated. This could indicate that a single version should not be used, or that the package is no longer maintained and any new vulnerabilities will not be fixed.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
144014
9
53
3995
1
1
+ Added@ipld/car@5.3.3(transitive)
+ Added@ipld/dag-cbor@9.2.2(transitive)
+ Added@ipld/dag-json@10.2.3(transitive)
+ Added@ipld/dag-ucan@3.4.0(transitive)
+ Addedcborg@4.2.6(transitive)
+ Addedmultiformats@11.0.213.3.1(transitive)
- Removed@ipld/car@4.1.6(transitive)
Updated@ipld/car@^5.1.0
Updated@ipld/dag-cbor@^9.0.0
Updated@ipld/dag-ucan@^3.3.2
Updatedmultiformats@^11.0.0