iso-ucan 0.4.2 → 0.5.0

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.
Files changed (44) hide show
  1. package/dist/src/capability.d.ts +0 -3
  2. package/dist/src/capability.d.ts.map +1 -1
  3. package/dist/src/delegation.d.ts +4 -1
  4. package/dist/src/delegation.d.ts.map +1 -1
  5. package/dist/src/invocation.d.ts.map +1 -1
  6. package/dist/src/rpc/client.d.ts +24 -0
  7. package/dist/src/rpc/client.d.ts.map +1 -0
  8. package/dist/src/rpc/command.d.ts +19 -0
  9. package/dist/src/rpc/command.d.ts.map +1 -0
  10. package/dist/src/rpc/index.d.ts +5 -0
  11. package/dist/src/rpc/index.d.ts.map +1 -0
  12. package/dist/src/rpc/receipt.d.ts +114 -0
  13. package/dist/src/rpc/receipt.d.ts.map +1 -0
  14. package/dist/src/rpc/server.d.ts +18 -0
  15. package/dist/src/rpc/server.d.ts.map +1 -0
  16. package/dist/src/rpc/types.d.ts +112 -0
  17. package/dist/src/rpc/types.d.ts.map +1 -0
  18. package/dist/src/store.d.ts +4 -2
  19. package/dist/src/store.d.ts.map +1 -1
  20. package/dist/src/types.d.ts +15 -3
  21. package/dist/src/types.d.ts.map +1 -1
  22. package/dist/src/utils.d.ts +4 -2
  23. package/dist/src/utils.d.ts.map +1 -1
  24. package/package.json +13 -20
  25. package/readme.md +130 -0
  26. package/src/capability.js +1 -6
  27. package/src/delegation.js +15 -13
  28. package/src/invocation.js +7 -4
  29. package/src/rpc/client.js +85 -0
  30. package/src/rpc/command.js +28 -0
  31. package/src/rpc/index.js +10 -0
  32. package/src/rpc/receipt.js +136 -0
  33. package/src/rpc/server.js +155 -0
  34. package/src/rpc/types.js +9 -0
  35. package/src/rpc/types.ts +153 -0
  36. package/src/store.js +41 -16
  37. package/src/types.ts +15 -6
  38. package/src/utils.js +20 -15
  39. package/dist/src/client.d.ts +0 -41
  40. package/dist/src/client.d.ts.map +0 -1
  41. package/dist/src/server.d.ts +0 -38
  42. package/dist/src/server.d.ts.map +0 -1
  43. package/src/client.js +0 -52
  44. package/src/server.js +0 -47
@@ -0,0 +1,155 @@
1
+ import { u8 } from 'iso-base/utils'
2
+ import { Invocation } from '../invocation.js'
3
+
4
+ /**
5
+ * @import {
6
+ * CommandsRecord,
7
+ * DefineServerOptions,
8
+ * ServerRequestHandler,
9
+ * } from './types.js'
10
+ * @import {ReceiptServerError} from './receipt.js'
11
+ */
12
+
13
+ /**
14
+ * Build a {@link ReceiptServerError} payload.
15
+ *
16
+ * @param {string} message
17
+ * @param {{
18
+ * cid?: import('multiformats').CID,
19
+ * cmd?: string,
20
+ * issues?: readonly import('@standard-schema/spec').StandardSchemaV1.Issue[],
21
+ * }} [extra]
22
+ * @returns {ReceiptServerError}
23
+ */
24
+ function buildServerError(message, extra) {
25
+ /** @type {Record<string, unknown> | undefined} */
26
+ let data
27
+ if (extra?.cmd !== undefined || extra?.issues !== undefined) {
28
+ data = {}
29
+ if (extra.cmd !== undefined) data.cmd = extra.cmd
30
+ if (extra.issues !== undefined) data.issues = extra.issues
31
+ }
32
+
33
+ /** @type {ReceiptServerError['error']} */
34
+ const error = { code: 'SERVER_ERROR', message }
35
+ if (data !== undefined) error.data = data
36
+ if (extra?.cid !== undefined) error.cid = extra.cid
37
+ return { error }
38
+ }
39
+
40
+ /**
41
+ * Build a JSON {@link Response} for a server error.
42
+ *
43
+ * @param {number} status
44
+ * @param {string} message
45
+ * @param {Parameters<typeof buildServerError>[1]} [extra]
46
+ */
47
+ function serverErrorResponse(status, message, extra) {
48
+ return Response.json(buildServerError(message, extra), { status })
49
+ }
50
+
51
+ /**
52
+ * Define a type-safe server from a record of commands.
53
+ *
54
+ * The returned function accepts a standard `Request`, decodes its body as a
55
+ * UCAN {@link Invocation}, validates the args against the matching command's
56
+ * schema, and dispatches to the corresponding handler in `options.handlers`.
57
+ * The handler's return value is serialized to JSON.
58
+ *
59
+ * @template {CommandsRecord} Commands
60
+ * @param {Commands} commands
61
+ * @param {DefineServerOptions<Commands>} options
62
+ * @returns {ServerRequestHandler}
63
+ */
64
+ export function defineServer(commands, options) {
65
+ /** @type {Record<string, CommandsRecord[string]>} */
66
+ const commandMap = {}
67
+ for (const command of Object.values(commands)) {
68
+ commandMap[command.capability.cmd] = command
69
+ }
70
+
71
+ /** @type {Record<string, (opts: any) => unknown>} */
72
+ const handlers = options.handlers
73
+
74
+ return async (request) => {
75
+ /** @type {Invocation | undefined} */
76
+ let invocation
77
+
78
+ try {
79
+ const bytes = u8(await request.arrayBuffer())
80
+
81
+ invocation = await Invocation.from({
82
+ bytes,
83
+ audience: options.signer,
84
+ verifierResolver: options.verifierResolver,
85
+ resolveProof: options.store.resolveProof.bind(options.store),
86
+ })
87
+ } catch (error) {
88
+ return serverErrorResponse(
89
+ 400,
90
+ `Invalid invocation: ${
91
+ error instanceof Error ? error.message : String(error)
92
+ }`
93
+ )
94
+ }
95
+
96
+ const cid = invocation.cid
97
+ const cmd = invocation.payload.cmd
98
+ const command = commandMap[cmd]
99
+ if (!command) {
100
+ return serverErrorResponse(404, `Command not found: ${cmd}`, {
101
+ cid,
102
+ cmd,
103
+ })
104
+ }
105
+
106
+ const handler = handlers[cmd]
107
+ if (!handler) {
108
+ return serverErrorResponse(404, `Handler not found: ${cmd}`, {
109
+ cid,
110
+ cmd,
111
+ })
112
+ }
113
+
114
+ const validated = await command.capability.validate(
115
+ /** @type {any} */ (invocation.payload.args)
116
+ )
117
+ if (validated.issues) {
118
+ return serverErrorResponse(400, `Invalid args for ${cmd}`, {
119
+ cid,
120
+ cmd,
121
+ issues: validated.issues,
122
+ })
123
+ }
124
+
125
+ /** @type {unknown} */
126
+ let receipt
127
+ try {
128
+ receipt = await handler({
129
+ args: validated.value,
130
+ invocation,
131
+ signer: options.signer,
132
+ store: options.store,
133
+ })
134
+ } catch (error) {
135
+ return serverErrorResponse(
136
+ 500,
137
+ error instanceof Error ? error.message : String(error),
138
+ { cid, cmd }
139
+ )
140
+ }
141
+
142
+ const validatedReceipt = await command.receipt['~standard'].validate(
143
+ /** @type {any} */ (receipt)
144
+ )
145
+ if (validatedReceipt.issues) {
146
+ return serverErrorResponse(500, `Invalid receipt for ${cmd}`, {
147
+ cid,
148
+ cmd,
149
+ issues: validatedReceipt.issues,
150
+ })
151
+ }
152
+
153
+ return Response.json(receipt)
154
+ }
155
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Runtime stub for the type-only `./types.ts` module so that
3
+ * `export * from './types.js'` in `index.js` resolves under plain Node
4
+ * (e.g. when consumers run `.ts` files via `--experimental-strip-types`).
5
+ *
6
+ * All real declarations live in `./types.ts`; TypeScript's bundler
7
+ * resolution prefers the `.ts` file at type-check time.
8
+ */
9
+ export {}
@@ -0,0 +1,153 @@
1
+ import type { StandardSchemaV1 } from '@standard-schema/spec'
2
+ import type { ISigner } from 'iso-signatures/types'
3
+ import type { Capability } from '../capability.js'
4
+ import type { Invocation } from '../invocation.js'
5
+ import type { Store } from '../store.js'
6
+ import type { ClientOptions, Promisable, VerifierResolver } from '../types.js'
7
+
8
+ export interface CommandOptions<
9
+ Args extends StandardSchemaV1,
10
+ Cmd extends string = string,
11
+ ReceiptSchema extends StandardSchemaV1 = StandardSchemaV1,
12
+ > {
13
+ cmd: Cmd
14
+ args: Args
15
+ receipt: ReceiptSchema
16
+ }
17
+
18
+ export interface CommandOutput<
19
+ Args extends StandardSchemaV1,
20
+ Cmd extends string = string,
21
+ ReceiptSchema extends StandardSchemaV1 = StandardSchemaV1,
22
+ > {
23
+ capability: Capability<Args, Cmd>
24
+ receipt: ReceiptSchema
25
+ }
26
+
27
+ export type AnyCommand = CommandOutput<
28
+ StandardSchemaV1,
29
+ string,
30
+ StandardSchemaV1
31
+ >
32
+
33
+ export type CommandsRecord = Record<string, AnyCommand>
34
+
35
+ /**
36
+ * Union of `{cmd, args, receipt}` shapes derived from a commands record.
37
+ * Used to discriminate `request` calls by `cmd`.
38
+ *
39
+ * `args` is the schema's input type (what the caller provides) and `receipt`
40
+ * is the schema's output type (what the caller receives back).
41
+ */
42
+ export type CommandUnion<Commands extends CommandsRecord> = {
43
+ [K in keyof Commands]: Commands[K] extends CommandOutput<
44
+ infer Args,
45
+ infer Cmd,
46
+ infer ReceiptSchema
47
+ >
48
+ ? {
49
+ cmd: Cmd
50
+ args: StandardSchemaV1.InferInput<Args>
51
+ receipt: StandardSchemaV1.InferOutput<ReceiptSchema>
52
+ }
53
+ : never
54
+ }[keyof Commands]
55
+
56
+ /**
57
+ * Server-side counterpart to {@link CommandUnion}: `args` is the schema's
58
+ * output (validated value passed to the handler) and `receipt` is the
59
+ * schema's input — the full receipt object, including `cid`, that the
60
+ * handler is responsible for constructing (typically using `invocation.cid`).
61
+ */
62
+ export type ServerCommandUnion<Commands extends CommandsRecord> = {
63
+ [K in keyof Commands]: Commands[K] extends CommandOutput<
64
+ infer Args,
65
+ infer Cmd,
66
+ infer ReceiptSchema
67
+ >
68
+ ? {
69
+ cmd: Cmd
70
+ args: StandardSchemaV1.InferOutput<Args>
71
+ receipt: StandardSchemaV1.InferInput<ReceiptSchema>
72
+ }
73
+ : never
74
+ }[keyof Commands]
75
+
76
+ /**
77
+ * Options for {@link defineClient}.
78
+ *
79
+ * Same as {@link ClientOptions} but the `capabilities` are derived from the
80
+ * commands record passed as the first argument.
81
+ */
82
+ export type DefineClientOptions = Omit<ClientOptions, 'capabilities'>
83
+
84
+ /**
85
+ * Options for {@link CommandClient.request}.
86
+ */
87
+ export type RequestOptions<
88
+ Commands extends CommandsRecord,
89
+ Cmd extends CommandUnion<Commands>['cmd'] = CommandUnion<Commands>['cmd'],
90
+ > = {
91
+ cmd: Cmd
92
+ args: Extract<CommandUnion<Commands>, { cmd: Cmd }>['args']
93
+ }
94
+
95
+ /**
96
+ * Type-safe client built from a record of commands.
97
+ */
98
+ export interface CommandClient<Commands extends CommandsRecord> {
99
+ request<Cmd extends CommandUnion<Commands>['cmd']>(
100
+ options: RequestOptions<Commands, Cmd>
101
+ ): Promise<Extract<CommandUnion<Commands>, { cmd: Cmd }>['receipt']>
102
+ invoke<Cmd extends CommandUnion<Commands>['cmd']>(
103
+ options: RequestOptions<Commands, Cmd>
104
+ ): Promise<Invocation>
105
+ }
106
+
107
+ /**
108
+ * Options passed to a server handler.
109
+ *
110
+ * `args` is the validated/decoded args from the command's schema.
111
+ */
112
+ export interface ServerHandlerOptions<Args> {
113
+ args: Args
114
+ invocation: Invocation
115
+ signer: ISigner
116
+ store: Store
117
+ }
118
+
119
+ /**
120
+ * Map of server handlers keyed by `cmd`, derived from a commands record.
121
+ *
122
+ * Each handler receives args typed as the command's args schema output and
123
+ * must return a value matching the command's receipt schema input.
124
+ */
125
+ export type ServerHandlers<Commands extends CommandsRecord> = {
126
+ [Cmd in ServerCommandUnion<Commands>['cmd']]: (
127
+ options: ServerHandlerOptions<
128
+ Extract<ServerCommandUnion<Commands>, { cmd: Cmd }>['args']
129
+ >
130
+ ) => Promisable<
131
+ Extract<ServerCommandUnion<Commands>, { cmd: Cmd }>['receipt']
132
+ >
133
+ }
134
+
135
+ /**
136
+ * Options for {@link defineServer}.
137
+ */
138
+ export interface DefineServerOptions<Commands extends CommandsRecord> {
139
+ handlers: ServerHandlers<Commands>
140
+ /**
141
+ * The server's signer. Used as the audience when decoding the incoming
142
+ * invocation and passed through to handlers as `signer` so they can issue
143
+ * receipts or further invocations.
144
+ */
145
+ signer: ISigner
146
+ store: Store
147
+ verifierResolver: VerifierResolver
148
+ }
149
+
150
+ /**
151
+ * Handler for an incoming HTTP request, returned by {@link defineServer}.
152
+ */
153
+ export type ServerRequestHandler = (request: Request) => Promise<Response>
package/src/store.js CHANGED
@@ -128,14 +128,28 @@ export class Store {
128
128
  }
129
129
 
130
130
  /**
131
- * Resolve a single chain of proofs ending with a root (subject === issuer).
132
- * Returns the first such chain found (depth-first).
131
+ * Resolve the first such chain found (depth-first), ordered from root to leaf.
132
+ *
133
+ * Cycles are detected via a per-path visited set of delegation CIDs so that
134
+ * self-delegations or other loops can be skipped without recursing forever.
133
135
  *
134
136
  * @param {import('./types.js').StoreProofsOptions} options
135
137
  * @returns {Promise<Delegation[]>}
136
138
  */
137
139
  async chain({ aud, sub, cmd, args }) {
138
- // console.log('🚀 ~ aud', aud, 'sub', sub, 'cmd', cmd)
140
+ const path = await this.#chain({ aud, sub, cmd, args }, new Set())
141
+ return path ? path.reverse() : []
142
+ }
143
+
144
+ /**
145
+ * Internal depth-first search for a delegation chain. Returns the path in
146
+ * leaf-to-root order, or `null` if no path exists.
147
+ *
148
+ * @param {import('./types.js').StoreProofsOptions} options
149
+ * @param {Set<string>} visited - delegation CIDs already on the current path
150
+ * @returns {Promise<Delegation[] | null>}
151
+ */
152
+ async #chain({ aud, sub, cmd, args }, visited) {
139
153
  const parents = parentCmds(cmd)
140
154
 
141
155
  const sources = merge(
@@ -147,28 +161,39 @@ export class Store {
147
161
  if (!parents.includes(proof.cmd)) continue
148
162
  if (!validate(args, proof.pol)) continue
149
163
 
164
+ const cidStr = proof.cid.toString()
165
+ if (visited.has(cidStr)) continue
166
+
167
+ const issDid = didParse(proof.iss).did
168
+
150
169
  // If root, return this proof as the end of the path
151
- if (proof.sub === didParse(proof.iss).did) {
152
- // console.log('🚀 ~ found root:', proof.iss, proof.sub, proof.cmd)
170
+ if (proof.sub === issDid) {
153
171
  return [proof]
154
172
  }
155
173
 
156
- // Otherwise, go deeper and prepend this proof if a path is found
157
- // console.log('🚀 ~ trying deeper:', proof.iss, proof.sub, proof.cmd)
158
- const nextPath = await this.chain({
159
- aud: didParse(proof.iss).did,
160
- sub: proof.sub ? proof.sub : sub,
161
- cmd: proof.cmd,
162
- args,
163
- })
174
+ // Skip non-root self-delegations (iss === aud). They never add
175
+ // capabilities a chain wouldn't already have through the predecessor
176
+ // delegation, and following them only lengthens the resulting chain.
177
+ if (issDid === proof.aud) continue
178
+
179
+ visited.add(cidStr)
180
+ const nextPath = await this.#chain(
181
+ {
182
+ aud: issDid,
183
+ sub: proof.sub ? proof.sub : sub,
184
+ cmd: proof.cmd,
185
+ args,
186
+ },
187
+ visited
188
+ )
189
+ visited.delete(cidStr)
190
+
164
191
  if (nextPath?.length) {
165
192
  return [proof, ...nextPath]
166
193
  }
167
- // console.log('🚀 ~ no path found')
168
194
  }
169
195
 
170
- // No path found
171
- return []
196
+ return null
172
197
  }
173
198
  }
174
199
 
package/src/types.ts CHANGED
@@ -13,6 +13,7 @@ import type { Policy } from './types/policy'
13
13
  export type { StandardSchemaV1 } from '@standard-schema/spec'
14
14
  export type { DID, DIDURL, DIDURLObject } from 'iso-did/types'
15
15
  export type { ISigner } from 'iso-signatures/types'
16
+ export * from './rpc/types'
16
17
  export * from './types/envelope'
17
18
  export * from './types/policy'
18
19
  export * from './types/varsig'
@@ -63,12 +64,22 @@ export interface DelegationOptions<Schema extends StandardSchemaV1> {
63
64
  nonce?: Uint8Array
64
65
  cmd: string
65
66
  meta?: CborObject
67
+ /**
68
+ * The current time in seconds. Mostly used for testing.
69
+ * @default Math.floor(Date.now() / 1000)
70
+ */
71
+ now?: number
66
72
  }
67
73
 
68
74
  export interface DelegationValidateOptions {
69
75
  isRevoked?: IsRevoked
70
76
  didResolver?: DidResolver
71
77
  verifierResolver: VerifierResolver
78
+ /**
79
+ * The current time in seconds. Mostly used for testing.
80
+ * @default Math.floor(Date.now() / 1000)
81
+ */
82
+ now?: number
72
83
  }
73
84
 
74
85
  export interface DelegationFromOptions extends DelegationValidateOptions {
@@ -113,7 +124,7 @@ export interface InvocationOptions extends DelegationValidateOptions {
113
124
 
114
125
  export interface InvocationFromOptions extends DelegationValidateOptions {
115
126
  bytes: Uint8Array
116
- audience: VerifiableDID
127
+ audience?: VerifiableDID
117
128
  resolveProof: ResolveProof
118
129
  }
119
130
 
@@ -127,7 +138,7 @@ export interface InvocationFromOptions extends DelegationValidateOptions {
127
138
  export interface CapabilityOptions<
128
139
  Schema extends StandardSchemaV1,
129
140
  Cmd extends string = string,
130
- > extends DelegationValidateOptions {
141
+ > {
131
142
  schema: Schema
132
143
  cmd: Cmd
133
144
  }
@@ -147,10 +158,7 @@ export interface CapabilityDelegateOptions<Schema extends StandardSchemaV1>
147
158
  * Invoke a capability
148
159
  */
149
160
  export interface CapabilityInvokeOptions<Schema extends StandardSchemaV1>
150
- extends Omit<
151
- InvocationOptions,
152
- 'cmd' | 'args' | 'prf' | 'verifierResolver' | 'didResolver' | 'isRevoked'
153
- > {
161
+ extends Omit<InvocationOptions, 'cmd' | 'args' | 'prf'> {
154
162
  args: StandardSchemaV1.InferOutput<Schema>
155
163
  /**
156
164
  * Store to resolve proofs from
@@ -267,4 +275,5 @@ export type ClientOptions = {
267
275
  audience: DIDURLObject
268
276
  store: Store
269
277
  capabilities: Capability<StandardSchemaV1, string>[]
278
+ verifierResolver: VerifierResolver
270
279
  }
package/src/utils.js CHANGED
@@ -42,7 +42,7 @@ export function nowInSeconds() {
42
42
  export async function cid(envelope) {
43
43
  const bytes = Envelope.encode({
44
44
  signature: envelope.signature,
45
- // @ts-ignore
45
+ // @ts-expect-error
46
46
  signaturePayload: signaturePayload(envelope),
47
47
  })
48
48
  const hash = await sha256.digest(bytes)
@@ -91,9 +91,9 @@ export function isSigAndDidCompatible(did, sigType) {
91
91
  * Validate the expiration of a UCAN
92
92
  *
93
93
  * @param {number | null} exp
94
+ * @param {number} [now]
94
95
  */
95
- export function assertExpiration(exp) {
96
- const now = nowInSeconds()
96
+ export function assertExpiration(exp, now = nowInSeconds()) {
97
97
  if (exp !== null && !Number.isSafeInteger(exp)) {
98
98
  throw new TypeError(
99
99
  `UCAN expiration must be null or a safe integer. Received: ${exp}`
@@ -111,9 +111,10 @@ export function assertExpiration(exp) {
111
111
  * Validate the not before time of a UCAN
112
112
  *
113
113
  * @param {number} [nbf]
114
+ * @param {number} [now]
114
115
  */
115
- export function assertNotBefore(nbf) {
116
- if (nbf && nbf > nowInSeconds()) {
116
+ export function assertNotBefore(nbf, now = nowInSeconds()) {
117
+ if (nbf && nbf > now) {
117
118
  throw new Error('UCAN not valid yet')
118
119
  }
119
120
  }
@@ -149,15 +150,19 @@ export async function verifySignature(
149
150
  didResolver
150
151
  ) {
151
152
  const issuer = await validateIssuerAndSignature(envelope, didResolver)
152
- const isVerified = await signatureVerifierResolver.verify({
153
- signature: envelope.signature,
154
- message: dagCbor.encode(signaturePayload(envelope)),
155
- did: issuer,
156
- type: envelope.alg,
157
- })
158
-
159
- if (!isVerified) {
160
- throw new Error('UCAN signature verification failed')
153
+ try {
154
+ const isVerified = await signatureVerifierResolver.verify({
155
+ signature: envelope.signature,
156
+ message: dagCbor.encode(signaturePayload(envelope)),
157
+ did: issuer,
158
+ type: envelope.alg,
159
+ })
160
+
161
+ if (!isVerified) {
162
+ throw new Error('UCAN signature verification failed')
163
+ }
164
+ } catch (error) {
165
+ throw new Error('UCAN signature verification failed', { cause: error })
161
166
  }
162
167
 
163
168
  return true
@@ -333,7 +338,7 @@ export const selector = z.union([
333
338
  export const statement =
334
339
  /** @type {typeof z.lazy<z.ZodType<import('../src/types.js').Statement<unknown>>>} */ (
335
340
  z.lazy
336
- // @ts-ignore
341
+ // @ts-expect-error
337
342
  )(() => {
338
343
  return z.union([
339
344
  z.tuple([
@@ -1,41 +0,0 @@
1
- /**
2
- * @import {InferProtocol, RouteOutput, StandardSchemaV1, ClientOptions, RouterClient} from './types'
3
- * @import {Capability} from './capability'
4
- */
5
- /**
6
- * Workaround to make imports types work
7
- * @template {{ cmd: string; in: unknown; out: unknown; }} T
8
- * @typedef {Object} DELETE_ME
9
- * @prop {string} url
10
- * @prop {Capability<StandardSchemaV1, string>[]} capabilities
11
- * @prop {InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>} router
12
- * @prop {ClientOptions} options
13
- * @prop {RouterClient<T>} routerClient
14
- */
15
- /**
16
- * @template {InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>} T
17
- * @param {ClientOptions} options
18
- * @returns {RouterClient<T>}
19
- */
20
- export function createClient<T extends InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>>(options: ClientOptions): RouterClient<T>;
21
- /**
22
- * Workaround to make imports types work
23
- */
24
- export type DELETE_ME<T extends {
25
- cmd: string;
26
- in: unknown;
27
- out: unknown;
28
- }> = {
29
- url: string;
30
- capabilities: Capability<StandardSchemaV1, string>[];
31
- router: InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>;
32
- options: ClientOptions;
33
- routerClient: RouterClient<T>;
34
- };
35
- import type { StandardSchemaV1 } from './types';
36
- import type { Capability } from './capability';
37
- import type { RouteOutput } from './types';
38
- import type { InferProtocol } from './types';
39
- import type { ClientOptions } from './types';
40
- import type { RouterClient } from './types';
41
- //# sourceMappingURL=client.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.js"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;;;;;;;;GASG;AAEH;;;;GAIG;AACH,6BAJiG,CAAC,SAArF,cAAe,MAAM,CAAC,MAAM,EAAE,YAAY,WAAW,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAE,WACrF,aAAa,GACX,aAAa,CAAC,CAAC,CAgC3B;;;;sBA5C0D,CAAC,SAA/C;IAAG,GAAG,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,OAAO,CAAC;CAAG;SAEhD,MAAM;kBACN,WAAW,gBAAgB,EAAE,MAAM,CAAC,EAAE;YACtC,cAAc,MAAM,CAAC,MAAM,EAAE,YAAY,WAAW,gBAAgB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;aACjF,aAAa;kBACb,aAAa,CAAC,CAAC;;sCAZmE,SAAS;gCACxE,cAAc;iCADiD,SAAS;mCAAT,SAAS;mCAAT,SAAS;kCAAT,SAAS"}
@@ -1,38 +0,0 @@
1
- /**
2
- * @import { RouteOutput, StandardSchemaV1, RouteOptions, RouteHandlerOptions} from './types'
3
- * @import {Capability} from './capability'
4
- */
5
- /**
6
- * Workaround to make imports types work
7
- * @template {Capability<StandardSchemaV1, string>} T
8
- * @template Output
9
- * @typedef {Object} DELETE_ME
10
- * @prop {string} url
11
- * @prop {Capability<StandardSchemaV1, string>[]} capabilities
12
- * @prop {RouteOutput<T, Output>} router
13
- * @prop {RouteOptions<T, Output>} options
14
- * @prop {RouteHandlerOptions} routerClient
15
- */
16
- /**
17
- * @template Output
18
- * @template {Capability<StandardSchemaV1>} Cap
19
- * @param {RouteOptions<Cap, Output>} options
20
- * @returns {RouteOutput<Cap, Output>}
21
- */
22
- export function route<Output, Cap extends Capability<StandardSchemaV1>>(options: RouteOptions<Cap, Output>): RouteOutput<Cap, Output>;
23
- /**
24
- * Workaround to make imports types work
25
- */
26
- export type DELETE_ME<T extends Capability<StandardSchemaV1, string>, Output> = {
27
- url: string;
28
- capabilities: Capability<StandardSchemaV1, string>[];
29
- router: RouteOutput<T, Output>;
30
- options: RouteOptions<T, Output>;
31
- routerClient: RouteHandlerOptions;
32
- };
33
- import type { StandardSchemaV1 } from './types';
34
- import type { Capability } from './capability';
35
- import type { RouteOptions } from './types';
36
- import type { RouteOutput } from './types';
37
- import type { RouteHandlerOptions } from './types';
38
- //# sourceMappingURL=server.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.js"],"names":[],"mappings":"AAIA;;;GAGG;AAEH;;;;;;;;;;GAUG;AAEH;;;;;GAKG;AACH,sBALa,MAAM,EACyB,GAAG,SAAlC,WAAY,gBAAgB,CAAE,WAChC,aAAa,GAAG,EAAE,MAAM,CAAC,GACvB,YAAY,GAAG,EAAE,MAAM,CAAC,CAqBpC;;;;sBAnCmD,CAAC,SAAxC,WAAY,gBAAgB,EAAE,MAAM,CAAE,EACtC,MAAM;SAET,MAAM;kBACN,WAAW,gBAAgB,EAAE,MAAM,CAAC,EAAE;YACtC,YAAY,CAAC,EAAE,MAAM,CAAC;aACtB,aAAa,CAAC,EAAE,MAAM,CAAC;kBACvB,mBAAmB;;sCAbuD,SAAS;gCAChE,cAAc;kCADyC,SAAS;iCAAT,SAAS;yCAAT,SAAS"}
package/src/client.js DELETED
@@ -1,52 +0,0 @@
1
- /**
2
- * @import {InferProtocol, RouteOutput, StandardSchemaV1, ClientOptions, RouterClient} from './types'
3
- * @import {Capability} from './capability'
4
- */
5
-
6
- /**
7
- * Workaround to make imports types work
8
- * @template {{ cmd: string; in: unknown; out: unknown; }} T
9
- * @typedef {Object} DELETE_ME
10
- * @prop {string} url
11
- * @prop {Capability<StandardSchemaV1, string>[]} capabilities
12
- * @prop {InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>} router
13
- * @prop {ClientOptions} options
14
- * @prop {RouterClient<T>} routerClient
15
- */
16
-
17
- /**
18
- * @template {InferProtocol<Record<string, RouteOutput<Capability<StandardSchemaV1>, unknown>>>} T
19
- * @param {ClientOptions} options
20
- * @returns {RouterClient<T>}
21
- */
22
- export function createClient(options) {
23
- const { url, capabilities } = options
24
-
25
- // Create a map of capabilities by their `cmd` property
26
- const capabilityMap = Object.fromEntries(
27
- capabilities.map((cap) => [cap.cmd, cap])
28
- )
29
- return {
30
- request: async (/** @type {string} */ cmd, /** @type {any} */ args) => {
31
- const capability = capabilityMap[cmd]
32
-
33
- if (!capability) {
34
- throw new Error(`Capability not found: ${cmd}`)
35
- }
36
-
37
- const inv = await capability.invoke({
38
- args,
39
- iss: options.issuer,
40
- sub: options.audience.did,
41
- store: options.store,
42
- exp: null,
43
- })
44
-
45
- const response = await fetch(url, {
46
- method: 'POST',
47
- body: /** @type {BufferSource} */ (inv.bytes),
48
- })
49
- return response.json()
50
- },
51
- }
52
- }