@interop/was-client 0.1.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 (51) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +204 -0
  3. package/dist/Collection.d.ts +112 -0
  4. package/dist/Collection.d.ts.map +1 -0
  5. package/dist/Collection.js +209 -0
  6. package/dist/Collection.js.map +1 -0
  7. package/dist/Resource.d.ts +67 -0
  8. package/dist/Resource.d.ts.map +1 -0
  9. package/dist/Resource.js +124 -0
  10. package/dist/Resource.js.map +1 -0
  11. package/dist/Space.d.ts +99 -0
  12. package/dist/Space.d.ts.map +1 -0
  13. package/dist/Space.js +202 -0
  14. package/dist/Space.js.map +1 -0
  15. package/dist/WasClient.d.ts +115 -0
  16. package/dist/WasClient.d.ts.map +1 -0
  17. package/dist/WasClient.js +191 -0
  18. package/dist/WasClient.js.map +1 -0
  19. package/dist/errors.d.ts +72 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +112 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/index.d.ts +14 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +13 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/internal/content.d.ts +43 -0
  28. package/dist/internal/content.d.ts.map +1 -0
  29. package/dist/internal/content.js +66 -0
  30. package/dist/internal/content.js.map +1 -0
  31. package/dist/internal/grant.d.ts +21 -0
  32. package/dist/internal/grant.d.ts.map +1 -0
  33. package/dist/internal/grant.js +19 -0
  34. package/dist/internal/grant.js.map +1 -0
  35. package/dist/internal/paths.d.ts +70 -0
  36. package/dist/internal/paths.d.ts.map +1 -0
  37. package/dist/internal/paths.js +92 -0
  38. package/dist/internal/paths.js.map +1 -0
  39. package/dist/internal/request.d.ts +64 -0
  40. package/dist/internal/request.d.ts.map +1 -0
  41. package/dist/internal/request.js +60 -0
  42. package/dist/internal/request.js.map +1 -0
  43. package/dist/internal/reserved.d.ts +16 -0
  44. package/dist/internal/reserved.d.ts.map +1 -0
  45. package/dist/internal/reserved.js +40 -0
  46. package/dist/internal/reserved.js.map +1 -0
  47. package/dist/types.d.ts +165 -0
  48. package/dist/types.d.ts.map +1 -0
  49. package/dist/types.js +2 -0
  50. package/dist/types.js.map +1 -0
  51. package/package.json +84 -0
@@ -0,0 +1,70 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * URL path builders for the WAS server, encoding the trailing-slash
6
+ * canonicalization once. Item-create and listing endpoints use a trailing
7
+ * slash; get/put/delete-by-id endpoints do not. Path segments are
8
+ * percent-encoded so ids never break out of their slot.
9
+ *
10
+ * The zcap `invocationTarget` is derived from the request URL, so these
11
+ * trailing-slash rules must match the server's per-operation `allowedTarget`
12
+ * exactly or signature verification fails.
13
+ */
14
+ /**
15
+ * `/spaces/` -- the SpacesRepository (create / list spaces).
16
+ */
17
+ export declare function spacesRoot(): string;
18
+ /**
19
+ * `/spaces/:spaceId` -- canonical location of a created space (POST response).
20
+ */
21
+ export declare function spaceLocation(spaceId: string): string;
22
+ /**
23
+ * `/space/:spaceId` -- get / update / delete a space (no trailing slash).
24
+ */
25
+ export declare function spacePath(spaceId: string): string;
26
+ /**
27
+ * `/space/:spaceId/` -- create a collection within a space (trailing slash).
28
+ */
29
+ export declare function spaceItems(spaceId: string): string;
30
+ /**
31
+ * `/space/:spaceId/collections/` -- list collections (trailing slash).
32
+ */
33
+ export declare function spaceCollections(spaceId: string): string;
34
+ /**
35
+ * `/space/:spaceId/export` -- export a space as a tar archive.
36
+ */
37
+ export declare function spaceExport(spaceId: string): string;
38
+ /**
39
+ * `/space/:spaceId/import` -- import a tar archive into a space.
40
+ */
41
+ export declare function spaceImport(spaceId: string): string;
42
+ /**
43
+ * `/space/:spaceId/:collectionId` -- get / update / delete a collection
44
+ * (no trailing slash).
45
+ */
46
+ export declare function collectionPath(spaceId: string, collectionId: string): string;
47
+ /**
48
+ * `/space/:spaceId/:collectionId/` -- list items / add a resource
49
+ * (trailing slash).
50
+ */
51
+ export declare function collectionItems(spaceId: string, collectionId: string): string;
52
+ /**
53
+ * `/space/:spaceId/:collectionId/:resourceId` -- get / put / delete a resource
54
+ * (no trailing slash).
55
+ */
56
+ export declare function resourcePath(spaceId: string, collectionId: string, resourceId: string): string;
57
+ /**
58
+ * Resolves a path against the server base URL, producing an absolute URL
59
+ * string suitable for zcap `invocationTarget`s.
60
+ *
61
+ * @param options {object}
62
+ * @param options.serverUrl {string} the server base URL
63
+ * @param options.path {string} a leading-slash path (e.g. `/space/x`)
64
+ * @returns {string}
65
+ */
66
+ export declare function toUrl({ serverUrl, path }: {
67
+ serverUrl: string;
68
+ path: string;
69
+ }): string;
70
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../src/internal/paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AAMH;;GAEG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAErD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEjD;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;GAEG;AACH,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE5E;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM,CAE7E;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,YAAY,EAAE,MAAM,EACpB,UAAU,EAAE,MAAM,GACjB,MAAM,CAER;AAED;;;;;;;;GAQG;AACH,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,IAAI,EACL,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;CACb,GAAG,MAAM,CAET"}
@@ -0,0 +1,92 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * URL path builders for the WAS server, encoding the trailing-slash
6
+ * canonicalization once. Item-create and listing endpoints use a trailing
7
+ * slash; get/put/delete-by-id endpoints do not. Path segments are
8
+ * percent-encoded so ids never break out of their slot.
9
+ *
10
+ * The zcap `invocationTarget` is derived from the request URL, so these
11
+ * trailing-slash rules must match the server's per-operation `allowedTarget`
12
+ * exactly or signature verification fails.
13
+ */
14
+ function encode(segment) {
15
+ return encodeURIComponent(segment);
16
+ }
17
+ /**
18
+ * `/spaces/` -- the SpacesRepository (create / list spaces).
19
+ */
20
+ export function spacesRoot() {
21
+ return '/spaces/';
22
+ }
23
+ /**
24
+ * `/spaces/:spaceId` -- canonical location of a created space (POST response).
25
+ */
26
+ export function spaceLocation(spaceId) {
27
+ return `/spaces/${encode(spaceId)}`;
28
+ }
29
+ /**
30
+ * `/space/:spaceId` -- get / update / delete a space (no trailing slash).
31
+ */
32
+ export function spacePath(spaceId) {
33
+ return `/space/${encode(spaceId)}`;
34
+ }
35
+ /**
36
+ * `/space/:spaceId/` -- create a collection within a space (trailing slash).
37
+ */
38
+ export function spaceItems(spaceId) {
39
+ return `/space/${encode(spaceId)}/`;
40
+ }
41
+ /**
42
+ * `/space/:spaceId/collections/` -- list collections (trailing slash).
43
+ */
44
+ export function spaceCollections(spaceId) {
45
+ return `/space/${encode(spaceId)}/collections/`;
46
+ }
47
+ /**
48
+ * `/space/:spaceId/export` -- export a space as a tar archive.
49
+ */
50
+ export function spaceExport(spaceId) {
51
+ return `/space/${encode(spaceId)}/export`;
52
+ }
53
+ /**
54
+ * `/space/:spaceId/import` -- import a tar archive into a space.
55
+ */
56
+ export function spaceImport(spaceId) {
57
+ return `/space/${encode(spaceId)}/import`;
58
+ }
59
+ /**
60
+ * `/space/:spaceId/:collectionId` -- get / update / delete a collection
61
+ * (no trailing slash).
62
+ */
63
+ export function collectionPath(spaceId, collectionId) {
64
+ return `/space/${encode(spaceId)}/${encode(collectionId)}`;
65
+ }
66
+ /**
67
+ * `/space/:spaceId/:collectionId/` -- list items / add a resource
68
+ * (trailing slash).
69
+ */
70
+ export function collectionItems(spaceId, collectionId) {
71
+ return `/space/${encode(spaceId)}/${encode(collectionId)}/`;
72
+ }
73
+ /**
74
+ * `/space/:spaceId/:collectionId/:resourceId` -- get / put / delete a resource
75
+ * (no trailing slash).
76
+ */
77
+ export function resourcePath(spaceId, collectionId, resourceId) {
78
+ return `/space/${encode(spaceId)}/${encode(collectionId)}/${encode(resourceId)}`;
79
+ }
80
+ /**
81
+ * Resolves a path against the server base URL, producing an absolute URL
82
+ * string suitable for zcap `invocationTarget`s.
83
+ *
84
+ * @param options {object}
85
+ * @param options.serverUrl {string} the server base URL
86
+ * @param options.path {string} a leading-slash path (e.g. `/space/x`)
87
+ * @returns {string}
88
+ */
89
+ export function toUrl({ serverUrl, path }) {
90
+ return new URL(path, serverUrl).toString();
91
+ }
92
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/internal/paths.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AAEH,SAAS,MAAM,CAAC,OAAe;IAC7B,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,UAAU,CAAA;AACnB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,OAAO,WAAW,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,EAAE,CAAA;AACpC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe;IACxC,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,GAAG,CAAA;AACrC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAe;IAC9C,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,eAAe,CAAA;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,SAAS,CAAA;AAC3C,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,OAAe;IACzC,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,SAAS,CAAA;AAC3C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,OAAe,EAAE,YAAoB;IAClE,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,EAAE,CAAA;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe,EAAE,YAAoB;IACnE,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,GAAG,CAAA;AAC7D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAC1B,OAAe,EACf,YAAoB,EACpB,UAAkB;IAElB,OAAO,UAAU,MAAM,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,EAAE,CAAA;AAClF,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,KAAK,CAAC,EACpB,SAAS,EACT,IAAI,EAIL;IACC,OAAO,IAAI,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAA;AAC5C,CAAC"}
@@ -0,0 +1,64 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The load-bearing transport layer: wraps `zcapClient.request(...)`, resolving
6
+ * paths against the server URL and defaulting the capability `action` to the
7
+ * HTTP method (never ezcap's `read`/`write`). `send()` adds the typed-error
8
+ * mapping and the null-on-404 read translation; `rawRequest()` is the
9
+ * unmapped escape hatch used by `was.request()`.
10
+ */
11
+ import type { ZcapClient } from '@interop/ezcap';
12
+ import type { HttpResponse } from '@interop/http-client';
13
+ import type { IZcap } from '../types.js';
14
+ /**
15
+ * The shared context threaded through every handle: the server base URL, the
16
+ * wrapped ezcap client, and the cached controller DID of its signer.
17
+ */
18
+ export interface ClientContext {
19
+ serverUrl: string;
20
+ zcapClient: ZcapClient;
21
+ controllerDid: string;
22
+ }
23
+ /**
24
+ * A single signed request. Either `path` (resolved against `serverUrl`) or
25
+ * `url` (absolute) must be given.
26
+ */
27
+ export interface SendInput {
28
+ path?: string;
29
+ url?: string;
30
+ method?: string;
31
+ action?: string;
32
+ headers?: Record<string, string>;
33
+ json?: object;
34
+ body?: Blob | Uint8Array;
35
+ capability?: IZcap;
36
+ /** When true, a 404 response resolves to `null` instead of throwing. */
37
+ read?: boolean;
38
+ /**
39
+ * When true, a 404 response resolves to `null` instead of throwing, so a
40
+ * delete of an already-absent target succeeds (idempotent delete).
41
+ */
42
+ idempotent?: boolean;
43
+ }
44
+ /**
45
+ * Signs and sends a request via the wrapped ezcap client, returning the raw
46
+ * `HttpResponse` and throwing the raw ky/ezcap error. Does not apply error
47
+ * mapping or null-on-404 -- this is the escape-hatch primitive.
48
+ *
49
+ * @param context {ClientContext}
50
+ * @param input {SendInput}
51
+ * @returns {Promise<HttpResponse>}
52
+ */
53
+ export declare function rawRequest(context: ClientContext, input: SendInput): Promise<HttpResponse>;
54
+ /**
55
+ * Signs and sends a request, applying the typed-error mapping. When `read` is
56
+ * set, a 404 resolves to `null` (MongoDB `findOne` semantics); otherwise every
57
+ * non-2xx maps to a `WasError` subclass.
58
+ *
59
+ * @param context {ClientContext}
60
+ * @param input {SendInput}
61
+ * @returns {Promise<HttpResponse | null>}
62
+ */
63
+ export declare function send(context: ClientContext, input: SendInput): Promise<HttpResponse | null>;
64
+ //# sourceMappingURL=request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGxD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAExC;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,UAAU,CAAA;IACtB,aAAa,EAAE,MAAM,CAAA;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,SAAS;IAExB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IAEZ,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,IAAI,GAAG,UAAU,CAAA;IACxB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAA;IACd;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB;AAYD;;;;;;;;GAQG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,CAAC,CAavB;AAED;;;;;;;;GAQG;AACH,wBAAsB,IAAI,CACxB,OAAO,EAAE,aAAa,EACtB,KAAK,EAAE,SAAS,GACf,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAgB9B"}
@@ -0,0 +1,60 @@
1
+ import { mapError } from '../errors.js';
2
+ import { toUrl } from './paths.js';
3
+ function resolveRequestUrl(context, input) {
4
+ if (input.url !== undefined) {
5
+ return input.url;
6
+ }
7
+ if (input.path === undefined) {
8
+ throw new TypeError('Either "path" or "url" is required.');
9
+ }
10
+ return toUrl({ serverUrl: context.serverUrl, path: input.path });
11
+ }
12
+ /**
13
+ * Signs and sends a request via the wrapped ezcap client, returning the raw
14
+ * `HttpResponse` and throwing the raw ky/ezcap error. Does not apply error
15
+ * mapping or null-on-404 -- this is the escape-hatch primitive.
16
+ *
17
+ * @param context {ClientContext}
18
+ * @param input {SendInput}
19
+ * @returns {Promise<HttpResponse>}
20
+ */
21
+ export async function rawRequest(context, input) {
22
+ const url = resolveRequestUrl(context, input);
23
+ const method = input.method ?? 'GET';
24
+ return context.zcapClient.request({
25
+ url,
26
+ capability: input.capability,
27
+ method,
28
+ // Default the capability action to the HTTP method (never `read`/`write`).
29
+ action: input.action ?? method,
30
+ headers: input.headers,
31
+ json: input.json,
32
+ body: input.body
33
+ });
34
+ }
35
+ /**
36
+ * Signs and sends a request, applying the typed-error mapping. When `read` is
37
+ * set, a 404 resolves to `null` (MongoDB `findOne` semantics); otherwise every
38
+ * non-2xx maps to a `WasError` subclass.
39
+ *
40
+ * @param context {ClientContext}
41
+ * @param input {SendInput}
42
+ * @returns {Promise<HttpResponse | null>}
43
+ */
44
+ export async function send(context, input) {
45
+ try {
46
+ return await rawRequest(context, input);
47
+ }
48
+ catch (err) {
49
+ const status = err
50
+ ?.status;
51
+ const responseStatus = err?.response
52
+ ?.status;
53
+ if ((input.read || input.idempotent) &&
54
+ (status === 404 || responseStatus === 404)) {
55
+ return null;
56
+ }
57
+ throw mapError(err);
58
+ }
59
+ }
60
+ //# sourceMappingURL=request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request.js","sourceRoot":"","sources":["../../src/internal/request.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AACvC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AAuClC,SAAS,iBAAiB,CAAC,OAAsB,EAAE,KAAgB;IACjE,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC5B,OAAO,KAAK,CAAC,GAAG,CAAA;IAClB,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC7B,MAAM,IAAI,SAAS,CAAC,qCAAqC,CAAC,CAAA;IAC5D,CAAC;IACD,OAAO,KAAK,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAA;AAClE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAsB,EACtB,KAAgB;IAEhB,MAAM,GAAG,GAAG,iBAAiB,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IAC7C,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,IAAI,KAAK,CAAA;IACpC,OAAO,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC;QAChC,GAAG;QACH,UAAU,EAAE,KAAK,CAAC,UAAU;QAC5B,MAAM;QACN,2EAA2E;QAC3E,MAAM,EAAE,KAAK,CAAC,MAAM,IAAI,MAAM;QAC9B,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,IAAI,EAAE,KAAK,CAAC,IAAI;KACjB,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,OAAsB,EACtB,KAAgB;IAEhB,IAAI,CAAC;QACH,OAAO,MAAM,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAA;IACzC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,GAAI,GAA2D;YACzE,EAAE,MAAM,CAAA;QACV,MAAM,cAAc,GAAI,GAA0C,EAAE,QAAQ;YAC1E,EAAE,MAAM,CAAA;QACV,IACE,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,UAAU,CAAC;YAChC,CAAC,MAAM,KAAK,GAAG,IAAI,cAAc,KAAK,GAAG,CAAC,EAC1C,CAAC;YACD,OAAO,IAAI,CAAA;QACb,CAAC;QACD,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAA;IACrB,CAAC;AACH,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Path segments reserved by the spec's Reserved Path Segment Registry. A
3
+ * collection or resource id that collides with one of these is rejected before
4
+ * the request is sent.
5
+ */
6
+ export declare const RESERVED_SEGMENTS: readonly string[];
7
+ /**
8
+ * Throws a `ValidationError` if the given id collides with a reserved path
9
+ * segment.
10
+ *
11
+ * @param id {string} the proposed collection or resource id
12
+ * @param kind {string} 'collection' or 'resource', used in the message
13
+ * @returns {void}
14
+ */
15
+ export declare function assertNotReserved(id: string, kind: 'collection' | 'resource'): void;
16
+ //# sourceMappingURL=reserved.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reserved.d.ts","sourceRoot":"","sources":["../../src/internal/reserved.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,EAAE,SAAS,MAAM,EAW9C,CAAA;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,YAAY,GAAG,UAAU,GAC9B,IAAI,CAMN"}
@@ -0,0 +1,40 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Reserved path-segment registry and the client-side id-collision guard.
6
+ * Rejecting reserved ids up front (with a clear `ValidationError`) is friendlier
7
+ * than letting the server answer `409 Conflict`.
8
+ */
9
+ import { ValidationError } from '../errors.js';
10
+ /**
11
+ * Path segments reserved by the spec's Reserved Path Segment Registry. A
12
+ * collection or resource id that collides with one of these is rejected before
13
+ * the request is sent.
14
+ */
15
+ export const RESERVED_SEGMENTS = [
16
+ 'policy',
17
+ 'backends',
18
+ 'backend',
19
+ 'collections',
20
+ 'export',
21
+ 'linkset',
22
+ 'query',
23
+ 'quota',
24
+ 'quotas',
25
+ 'meta'
26
+ ];
27
+ /**
28
+ * Throws a `ValidationError` if the given id collides with a reserved path
29
+ * segment.
30
+ *
31
+ * @param id {string} the proposed collection or resource id
32
+ * @param kind {string} 'collection' or 'resource', used in the message
33
+ * @returns {void}
34
+ */
35
+ export function assertNotReserved(id, kind) {
36
+ if (RESERVED_SEGMENTS.includes(id)) {
37
+ throw new ValidationError(`Cannot use reserved path segment "${id}" as a ${kind} id.`);
38
+ }
39
+ }
40
+ //# sourceMappingURL=reserved.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reserved.js","sourceRoot":"","sources":["../../src/internal/reserved.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAsB;IAClD,QAAQ;IACR,UAAU;IACV,SAAS;IACT,aAAa;IACb,QAAQ;IACR,SAAS;IACT,OAAO;IACP,OAAO;IACP,QAAQ;IACR,MAAM;CACP,CAAA;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,EAAU,EACV,IAA+B;IAE/B,IAAI,iBAAiB,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,eAAe,CACvB,qCAAqC,EAAE,UAAU,IAAI,MAAM,CAC5D,CAAA;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,165 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Shared type definitions for the WAS client: containment descriptions,
6
+ * listing/result shapes, delegation options, and the manual-request input.
7
+ * ZCap and signer types are re-used from `@interop/data-integrity-core` rather
8
+ * than re-declared.
9
+ */
10
+ import type { IZcap, IDelegatedZcap } from '@interop/data-integrity-core/zcap';
11
+ import type { ISigner } from '@interop/data-integrity-core';
12
+ export type { IZcap, IDelegatedZcap, ISigner };
13
+ /**
14
+ * A JSON-serializable value, the shape stored for JSON resources and
15
+ * descriptions.
16
+ */
17
+ export type JsonPrimitive = string | number | boolean | null;
18
+ export interface JsonObject {
19
+ [key: string]: Json;
20
+ }
21
+ export type JsonArray = Json[];
22
+ export type Json = JsonPrimitive | JsonObject | JsonArray;
23
+ /**
24
+ * A capability action -- an HTTP verb in its canonical uppercase form, as it
25
+ * appears in the signed zcap. The WAS server matches actions case-sensitively.
26
+ */
27
+ export type Action = 'GET' | 'PUT' | 'POST' | 'DELETE';
28
+ /**
29
+ * The action input accepted by `grant()`: canonical uppercase or lowercase.
30
+ * Lowercase is normalized to uppercase before the zcap is signed, so a grant of
31
+ * `'get'` still validates on the server (which expects `'GET'`).
32
+ */
33
+ export type ActionInput = Action | Lowercase<Action>;
34
+ /**
35
+ * A Space Description object, as returned by the server.
36
+ */
37
+ export interface SpaceDescription {
38
+ id: string;
39
+ type: string[];
40
+ name?: string;
41
+ controller: string;
42
+ }
43
+ /**
44
+ * A Collection Description object, as returned by the server.
45
+ */
46
+ export interface CollectionDescription {
47
+ id: string;
48
+ type: string[];
49
+ name?: string;
50
+ }
51
+ /**
52
+ * One entry in a `CollectionListing` (a collection within a space).
53
+ */
54
+ export interface CollectionSummary {
55
+ id: string;
56
+ name: string;
57
+ url: string;
58
+ }
59
+ /**
60
+ * Return shape of `space.collections()`.
61
+ */
62
+ export interface CollectionListing {
63
+ url: string;
64
+ totalItems: number;
65
+ items: CollectionSummary[];
66
+ }
67
+ /**
68
+ * One entry in a `SpaceListing` (a space within the repository).
69
+ */
70
+ export interface SpaceSummary {
71
+ id: string;
72
+ name?: string;
73
+ url: string;
74
+ }
75
+ /**
76
+ * Return shape of `was.listSpaces()` (not yet implemented by the reference
77
+ * server, which answers 501).
78
+ */
79
+ export interface SpaceListing {
80
+ url: string;
81
+ totalItems: number;
82
+ items: SpaceSummary[];
83
+ }
84
+ /**
85
+ * One entry in a `ResourceListing` (a resource within a collection).
86
+ */
87
+ export interface ResourceSummary {
88
+ id: string;
89
+ url: string;
90
+ contentType: string;
91
+ }
92
+ /**
93
+ * Return shape of `collection.list()`.
94
+ */
95
+ export interface ResourceListing {
96
+ id: string;
97
+ url: string;
98
+ name?: string;
99
+ type: string[];
100
+ totalItems: number;
101
+ items: ResourceSummary[];
102
+ }
103
+ /**
104
+ * Return shape of `collection.add()` (server-generated resource id + location).
105
+ */
106
+ export interface AddResult {
107
+ id: string;
108
+ url: string;
109
+ contentType?: string;
110
+ }
111
+ /**
112
+ * Return shape of `space.import()`.
113
+ */
114
+ export interface ImportStats {
115
+ collectionsCreated: number;
116
+ collectionsSkipped: number;
117
+ resourcesCreated: number;
118
+ resourcesSkipped: number;
119
+ }
120
+ /**
121
+ * Options accepted by every handle factory (`space()`, `collection()`,
122
+ * `resource()`). A bound `capability` is attached to every request the handle
123
+ * makes.
124
+ */
125
+ export interface HandleOptions {
126
+ capability?: IZcap;
127
+ }
128
+ /**
129
+ * A reference to a storage backend, used when creating or configuring a
130
+ * Collection.
131
+ */
132
+ export interface BackendReference {
133
+ id: string;
134
+ }
135
+ /**
136
+ * Options for the general delegation primitive (`was.grant()`) and the
137
+ * `space`/`collection` sugar.
138
+ *
139
+ * @property to the delegate's controller DID
140
+ * @property actions allowed actions (aliases or raw HTTP verbs)
141
+ * @property [expires] expiration; defaults to ezcap's 5-minute default
142
+ * @property [target] invocationTarget URL; filled by scoped grants
143
+ * @property [capability] parent capability to attenuate / re-delegate
144
+ */
145
+ export interface GrantOptions {
146
+ to: string;
147
+ actions: ActionInput[];
148
+ expires?: string | Date;
149
+ target?: string;
150
+ capability?: IZcap;
151
+ }
152
+ /**
153
+ * Input for the low-level `was.request()` escape hatch.
154
+ */
155
+ export interface RequestInput {
156
+ path?: string;
157
+ url?: string;
158
+ method?: string;
159
+ action?: string;
160
+ headers?: Record<string, string>;
161
+ json?: object;
162
+ body?: Blob | Uint8Array;
163
+ capability?: IZcap;
164
+ }
165
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,84 @@
1
+ {
2
+ "name": "@interop/was-client",
3
+ "description": "A developer-friendly client for Wallet Attached Storage (WAS) servers.",
4
+ "version": "0.1.0",
5
+ "type": "module",
6
+ "scripts": {
7
+ "build": "pnpm run clear && tsc",
8
+ "clear": "rimraf dist/*",
9
+ "dev": "vite",
10
+ "fix": "eslint --fix src test && pnpm run format",
11
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\" \"*.md\"",
12
+ "lint": "eslint src test",
13
+ "prepare": "pnpm run build",
14
+ "rebuild": "pnpm run clear && pnpm run build",
15
+ "test": "pnpm run fix && pnpm run lint && pnpm run test-node && pnpm run test-browser",
16
+ "test-browser": "playwright test",
17
+ "test-node": "vitest run",
18
+ "test-coverage": "vitest run --coverage"
19
+ },
20
+ "files": [
21
+ "dist",
22
+ "README.md",
23
+ "LICENSE.md"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "react-native": "./dist/index.js",
29
+ "import": "./dist/index.js",
30
+ "default": "./dist/index.js"
31
+ }
32
+ },
33
+ "module": "dist/index.js",
34
+ "browser": "dist/index.js",
35
+ "types": "dist/index.d.ts",
36
+ "sideEffects": false,
37
+ "dependencies": {
38
+ "@interop/data-integrity-core": "^6.1.2",
39
+ "@interop/ed25519-signature": "^7.0.1",
40
+ "@interop/ezcap": "^7.1.1",
41
+ "@interop/http-client": "^1.0.3"
42
+ },
43
+ "devDependencies": {
44
+ "@eslint/js": "^10.0.1",
45
+ "@interop/ed25519-verification-key": "^7.0.1",
46
+ "@playwright/test": "^1.60.0",
47
+ "@types/node": "^25.9.1",
48
+ "@vitest/coverage-v8": "^4.1.7",
49
+ "eslint": "^10.4.0",
50
+ "eslint-config-prettier": "^10.1.8",
51
+ "globals": "^17.6.0",
52
+ "prettier": "^3.8.3",
53
+ "rimraf": "^6.1.3",
54
+ "typescript": "^5.9.3",
55
+ "typescript-eslint": "^8.59.4",
56
+ "vite": "^8.0.14",
57
+ "vitest": "^4.1.7",
58
+ "was-teaching-server": "link:../was-teaching-server"
59
+ },
60
+ "publishConfig": {
61
+ "access": "public"
62
+ },
63
+ "keywords": [
64
+ "wallet attached storage",
65
+ "was",
66
+ "zcap",
67
+ "ezcap"
68
+ ],
69
+ "packageManager": "pnpm@11.5.0",
70
+ "engines": {
71
+ "node": ">=24.0"
72
+ },
73
+ "author": {
74
+ "name": "Interop Alliance",
75
+ "url": "https://github.com/interop-alliance/"
76
+ },
77
+ "license": "MIT",
78
+ "repository": {
79
+ "type": "git",
80
+ "url": "git+https://github.com/interop-alliance/was-client.git"
81
+ },
82
+ "homepage": "https://github.com/interop-alliance/was-client",
83
+ "bugs": "https://github.com/interop-alliance/was-client/issues"
84
+ }