@interop/was-client 0.2.0 → 0.4.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.
package/README.md CHANGED
@@ -1,19 +1,25 @@
1
1
  # Wallet Attached Storage Client _(@interop/was-client)_
2
2
 
3
+ [![Node.js CI](https://github.com/interop-alliance/was-client/workflows/CI/badge.svg)](https://github.com/interop-alliance/was-client/actions?query=workflow%3A%22CI%22)
3
4
  [![NPM Version](https://img.shields.io/npm/v/@interop/was-client.svg)](https://npm.im/@interop/was-client)
4
5
 
5
6
  > A developer-friendly client for Wallet Attached Storage (WAS) servers, with a
6
- > MongoDB-driver-inspired navigational API over zcap-authorized HTTP.
7
+ > database-driver-inspired navigational API over zcap-authorized HTTP.
7
8
 
8
9
  ## Table of Contents
9
10
 
10
11
  - [Background](#background)
11
12
  - [Install](#install)
12
13
  - [Usage](#usage)
13
- - [Construction](#construction)
14
+ - [Creating a client (signer + zcapClient)](#creating-a-client-signer--zcapclient)
14
15
  - [The handle model](#the-handle-model)
16
+ - [Spaces](#spaces)
17
+ - [Collections](#collections)
15
18
  - [Resources: JSON and binary](#resources-json-and-binary)
16
19
  - [Delegation and sharing](#delegation-and-sharing)
20
+ - [Public sharing and access-control policies](#public-sharing-and-access-control-policies)
21
+ - [Resource metadata](#resource-metadata)
22
+ - [Storage introspection: backends and quotas](#storage-introspection-backends-and-quotas)
17
23
  - [Export and import](#export-and-import)
18
24
  - [The manual-request escape hatch](#the-manual-request-escape-hatch)
19
25
  - [Errors and the 404/null caveat](#errors-and-the-404null-caveat)
@@ -22,23 +28,19 @@
22
28
 
23
29
  ## Background
24
30
 
25
- The WAS protocol exposes a containment model --
31
+ The WAS protocol exposes a general purpose database-like container model --
26
32
  `SpacesRepository > Space > Collection > Resource` -- over HTTP, authorized with
27
- [Authorization Capabilities (zcaps)](https://w3c-ccg.github.io/zcap-spec/). The
28
- low-level transport is an
29
- [`@interop/ezcap`](https://www.npmjs.com/package/@interop/ezcap) `ZcapClient`,
30
- where every operation hand-builds a URL, picks a trailing-slash variant, threads
31
- JSON vs binary bodies, and reasons about delegation inline.
33
+ [Authorization Capabilities (zcaps)](https://w3c-ccg.github.io/zcap-spec/).
32
34
 
33
35
  `@interop/was-client` wraps that `ZcapClient` and exposes the containment model
34
- through cheap, lazy navigational handles modeled on the MongoDB driver's DX
36
+ through cheap, lazy navigational handles modeled on a document store's DX
35
37
  (`client > db > collection`), using WAS-specific verbs
36
38
  (`add`/`get`/`put`/`list`/`delete`) rather than `insertOne`/`findOne` (WAS has
37
39
  no query-by-filter yet).
38
40
 
39
- | MongoDB driver | WAS client |
41
+ | Document db driver | WAS client |
40
42
  | ----------------------------------- | ------------------------------------------ |
41
- | `new MongoClient(url)` | `new WasClient({ serverUrl, zcapClient })` |
43
+ | `new Client(url)` | `new WasClient({ serverUrl, zcapClient })` |
42
44
  | `client.db('app')` | `was.space(spaceId)` |
43
45
  | `db.collection('users')` | `space.collection(collectionId)` |
44
46
  | `collection.insertOne(doc)` | `collection.add(doc)` |
@@ -57,34 +59,86 @@ pnpm install @interop/was-client
57
59
 
58
60
  ## Usage
59
61
 
60
- ### Construction
62
+ ### Creating a client (signer + zcapClient)
63
+
64
+ A `WasClient` signs every request with a key you control. The key is held by an
65
+ ezcap `ZcapClient`, which you build from a `did:key` identity. You will need two
66
+ companion packages alongside this one (this library already depends on
67
+ `@interop/ed25519-signature`):
68
+
69
+ ```
70
+ pnpm install @interop/ezcap @interop/did-method-key @interop/ed25519-verification-key
71
+ ```
72
+
73
+ The primary form wraps a `ZcapClient` you build yourself. The `did:key` driver
74
+ generates a key pair and a matching DID document, wiring the signer's
75
+ `id`/`controller` correctly:
61
76
 
62
77
  ```ts
78
+ import { ZcapClient } from '@interop/ezcap'
79
+ import * as didKey from '@interop/did-method-key'
80
+ import { Ed25519Signature2020 } from '@interop/ed25519-signature'
81
+ import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'
63
82
  import { WasClient } from '@interop/was-client'
64
83
 
65
- // Primary form: wrap an existing ezcap ZcapClient (which holds the signer).
66
- const was = new WasClient({ serverUrl, zcapClient })
84
+ // 1. Generate a did:key identity (didDocument + keyPairs).
85
+ const didKeyDriver = didKey.driver()
86
+ didKeyDriver.use({ keyPairClass: Ed25519VerificationKey })
87
+ const { didDocument, keyPairs } = await didKeyDriver.generate()
67
88
 
68
- // Convenience: build the ZcapClient internally from a signer
69
- // (uses the Ed25519Signature2020 suite).
70
- const was = WasClient.fromSigner({ serverUrl, signer })
89
+ // 2. Build the ezcap ZcapClient (it holds the signer and signs every request).
90
+ const zcapClient = new ZcapClient({
91
+ didDocument,
92
+ keyPairs,
93
+ SuiteClass: Ed25519Signature2020
94
+ })
95
+
96
+ // 3. Wrap it.
97
+ const was = new WasClient({ serverUrl: 'https://was.example', zcapClient })
71
98
  ```
72
99
 
100
+ If you already have a single signer, `WasClient.fromSigner()` builds the
101
+ `ZcapClient` internally (using the `Ed25519Signature2020` suite). A signer is
102
+ any object with `{ id, sign() }`; here we get one from a generated key. The
103
+ signer's `id` must be a `did:key` so the server can resolve and verify it:
104
+
105
+ ```ts
106
+ import { Ed25519VerificationKey } from '@interop/ed25519-verification-key'
107
+ import { WasClient } from '@interop/was-client'
108
+
109
+ // Pass a 32-byte `seed` for a deterministic key, or omit it for a random one.
110
+ const keyPair = await Ed25519VerificationKey.generate({ seed })
111
+ keyPair.controller = `did:key:${keyPair.fingerprint()}`
112
+ keyPair.id = `${keyPair.controller}#${keyPair.fingerprint()}`
113
+
114
+ const was = WasClient.fromSigner({
115
+ serverUrl: 'https://was.example',
116
+ signer: keyPair.signer()
117
+ })
118
+ ```
119
+
120
+ The `seed` is where a passphrase-, stored-secret-, or KMS-derived key plugs in:
121
+ deriving the same 32-byte seed yields the same DID, and therefore access to the
122
+ same spaces. (Apps with user accounts often derive the signer from a passphrase
123
+ via `CapabilityAgent.fromSecret()` from `@digitalbazaar/webkms-client` -- not
124
+ required, just a common alternative.)
125
+
73
126
  `serverUrl` is the base for both URL building and zcap `invocationTarget`s, so
74
127
  the "server URL must equal the invocation target host:port" constraint holds by
75
128
  construction.
76
129
 
77
130
  ### The handle model
78
131
 
132
+ The client exposes the WAS containment model
133
+ (`SpacesRepository > Space > Collection > Resource`) as navigational handles.
79
134
  Handles are lazy and synchronous to obtain -- only the verb methods hit the
80
135
  network. Lazy chains never throw: `was.space(x).collection(y)` does no I/O and
81
136
  just accumulates URL context. Existence is checked on the first network verb.
82
137
 
83
138
  ```ts
84
- const space = await was.createSpace({ name: 'Home' }) // POST /spaces/
139
+ const space = await was.createSpace({ name: 'Home' })
85
140
 
86
141
  const collection = await space.createCollection({
87
- id: 'credentials',
88
142
  name: 'Verifiable Credentials'
89
143
  })
90
144
 
@@ -94,18 +148,99 @@ await collection.put('vc-1', {
94
148
  })
95
149
  const vc = await collection.get('vc-1') // parsed JSON object, or null on a miss
96
150
 
97
- const listing = await collection.list() // { id, url, totalItems, items, ... }
98
-
99
151
  await collection.resource('vc-1').delete() // delete one resource by id
100
152
  await space.delete() // delete the whole space (idempotent)
101
153
  ```
102
154
 
103
155
  `delete()` is uniform at every level, takes no argument, and always deletes the
104
156
  thing the handle points at -- so there is no "delete the collection" vs "delete
105
- one item" footgun.
157
+ one item" footgun. The next sections cover each level in turn.
158
+
159
+ ### Spaces
160
+
161
+ A Space is the top-level container, created from the spaces repository. The
162
+ server requires a `name`; `controller` defaults to the client's own DID, and the
163
+ server generates the id unless you pass one.
164
+
165
+ ```ts
166
+ const space = await was.createSpace({ name: 'Home' }) // POST /spaces/
167
+
168
+ // Lazy handle to an existing space by id -- no I/O until a verb runs.
169
+ const same = was.space(space.id)
170
+
171
+ // Read the Space Description (null if missing or not visible to you).
172
+ const desc = await space.describe() // { id, type: ['Space'], name, controller } | null
173
+
174
+ // Upsert: merges the given fields over the current description.
175
+ await space.configure({ name: 'Home (renamed)' })
176
+
177
+ await space.delete() // idempotent
178
+ ```
179
+
180
+ Listing every space in the repository (`was.listSpaces()`) is specified but not
181
+ yet implemented by the reference server, so it currently throws
182
+ `NotImplementedError`. To enumerate what is _inside_ a space, use
183
+ `space.collections()` (below).
184
+
185
+ ### Collections
186
+
187
+ A Collection lives inside a Space and holds resources. WAS does not auto-create
188
+ parents, so `createCollection` throws `NotFoundError` if the space does not
189
+ exist. The server generates the id unless you pass one (a handful of reserved
190
+ ids are rejected).
191
+
192
+ ```ts
193
+ // Create.
194
+ const collection = await space.createCollection({
195
+ name: 'Verifiable Credentials'
196
+ })
197
+
198
+ // Lazy handle to an existing collection by id.
199
+ const same = space.collection(collection.id)
200
+
201
+ // Read the Collection Description (null if missing or not visible).
202
+ const desc = await collection.describe() // { id, type: ['Collection'], name } | null
203
+
204
+ // Update (upsert; merges over the current description).
205
+ await collection.configure({ name: 'Credentials' })
206
+
207
+ // List the collections in a space.
208
+ const collections = await space.collections()
209
+ // { url, totalItems, items: [{ id, name, url }, ...] } | null
210
+
211
+ // List the resources inside this collection.
212
+ const resources = await collection.list()
213
+ // { id, url, totalItems, items: [{ id, url, contentType }, ...], ... } | null
214
+
215
+ await collection.delete() // deletes the whole collection; idempotent
216
+ ```
217
+
218
+ To delete a single resource instead of the whole collection, use
219
+ `collection.resource(id).delete()`.
106
220
 
107
221
  ### Resources: JSON and binary
108
222
 
223
+ A Resource is a JSON object or binary blob keyed by id within a Collection. Use
224
+ `add()` for a server-generated id or `put(id, ...)` to create-or-replace at a
225
+ known id (both throw `NotFoundError` if the parent collection is missing):
226
+
227
+ ```ts
228
+ // Server-generated id; returns { id, url, contentType? }.
229
+ const added = await collection.add({
230
+ type: ['VerifiableCredential'],
231
+ name: 'Diploma'
232
+ })
233
+
234
+ // Create or replace at a known id (upsert).
235
+ await collection.put('vc-1', {
236
+ type: ['VerifiableCredential'],
237
+ name: 'Diploma'
238
+ })
239
+
240
+ const vc = await collection.get('vc-1') // parsed JSON object, or null on a miss
241
+ await collection.resource('vc-1').delete() // idempotent
242
+ ```
243
+
109
244
  Writes detect the payload: a plain object/array is sent as JSON; a
110
245
  `Blob`/`Uint8Array`/`Buffer` is sent as binary, with the content-type taken from
111
246
  `options.contentType`, the `Blob.type`, or `application/octet-stream`.
@@ -168,6 +303,7 @@ const link = added.url // hand this URL out; a plain GET resolves it
168
303
 
169
304
  // Inspect or revoke.
170
305
  const policy = await collection.getPolicy() // { type: 'PublicCanRead' } | null
306
+ const isPublic = await collection.isPublic() // true if its own policy is PublicCanRead
171
307
  await collection.clearPolicy() // revert to capability-only access (idempotent)
172
308
 
173
309
  // setPolicy() is the generic, forward-compatible primitive; setPublic() is sugar.
@@ -176,10 +312,71 @@ await resource.setPublic() // a single public resource
176
312
  ```
177
313
 
178
314
  Policies are resolved most-specific-first (Resource over Collection over Space)
179
- and are permissive-only -- they broaden access, never restrict a valid capability
180
- holder. Managing a policy is a controller-level operation. Discover a policy via
181
- `space.linkset()` / `collection.linkset()` (RFC9264) or the `linkset` property on
182
- a description.
315
+ and are permissive-only -- they broaden access, never restrict a valid
316
+ capability holder. Managing a policy is a controller-level operation. Discover a
317
+ policy via `space.linkset()` / `collection.linkset()` (RFC9264) or the `linkset`
318
+ property on a description.
319
+
320
+ `isPublic()` is a read-only convenience that returns `true` when the Space,
321
+ Collection, or Resource has a `{ type: 'PublicCanRead' }` policy -- that is,
322
+ when it has been made public via `setPublic()` (or an equivalent `setPolicy()`
323
+ call). It's meant to drive data-browser style UI, to show a "This
324
+ space(/collection/resource) has been shared publicly" type of icon.
325
+
326
+ #### Consuming public links (unauthenticated reads)
327
+
328
+ The flip side of `setPublic()`: reading a `PublicCanRead` resource or collection
329
+ with no authorization, by its URL. These use an unsigned plain `fetch` (no
330
+ capability invocation), so they work for a consumer who only holds the link.
331
+
332
+ ```ts
333
+ // Fetch a single public resource (auto-parses JSON, returns binary as a Blob).
334
+ const doc = await was.publicRead({
335
+ resourceUrl: 'https://was.example/space/s/c/r'
336
+ }) // Json | Blob | null
337
+
338
+ // List a public collection -- e.g. a blog published as a public-read collection.
339
+ const listing = await was.publicListCollection({
340
+ collectionUrl: 'https://was.example/space/s/c'
341
+ }) // ResourceListing | null
342
+ ```
343
+
344
+ Both follow the read-method 404/null caveat: a missing or non-public target
345
+ resolves to `null`.
346
+
347
+ ### Resource metadata
348
+
349
+ Each Resource has a metadata object at its reserved `/meta` path: server-managed
350
+ properties (`contentType`, `size`, optional `createdAt` / `updatedAt`) plus a
351
+ user-writable `custom` object (`name` and `tags`).
352
+
353
+ ```ts
354
+ const resource = collection.resource('vc-1')
355
+
356
+ const meta = await resource.meta() // ResourceMetadata | null (null on a miss)
357
+
358
+ // setMeta() is a full replacement of `custom`; omitted properties are cleared.
359
+ await resource.setMeta({ custom: { name: 'Diploma', tags: { year: '2026' } } })
360
+
361
+ // setName() / setTags() are read-modify-write sugar that preserve the other.
362
+ await resource.setName('Renamed diploma') // keeps existing tags
363
+ await resource.setTags({ status: 'verified' }) // keeps existing name
364
+ ```
365
+
366
+ The `custom.name` is the same value surfaced as a resource's `name` in
367
+ collection listings; updating one updates the other.
368
+
369
+ ### Storage introspection: backends and quotas
370
+
371
+ A Space can report the storage backends available to it and a per-backend usage
372
+ report. Both are optional server features (a server without them surfaces a
373
+ `NotImplementedError`); both follow the read-method 404/null caveat.
374
+
375
+ ```ts
376
+ const backends = await space.backends() // BackendDescriptor[] | null
377
+ const report = await space.quotas() // SpaceQuotaReport | null
378
+ // report.backends[i]: { id, state, usageBytes, limit, restrictedActions, ... }
379
+ ```
183
380
 
184
381
  ### Export and import
185
382
 
@@ -208,20 +405,28 @@ MongoDB's `findOne` semantics. **WAS returns 404 for both not-found and
208
405
  unauthorized**, so `null` means "not visible to you" rather than strictly "does
209
406
  not exist". Write/delete methods throw a typed error instead.
210
407
 
211
- | Status | Read methods | Write / delete methods |
212
- | ------ | --------------------- | ---------------------- |
213
- | 404 | `null` | `NotFoundError` |
214
- | 400 | `ValidationError` | `ValidationError` |
215
- | 401 | `AuthRequiredError` | `AuthRequiredError` |
216
- | 501 | `NotImplementedError` | `NotImplementedError` |
217
- | 5xx | `WasServerError` | `WasServerError` |
218
-
219
- All error classes extend `WasError` (carrying `status`, `title`, `details`, and
220
- `requestUrl`). `delete()` additionally treats a 404 as success, so it is
221
- idempotent.
222
-
223
- Some spec endpoints (`listSpaces()`, `meta`, `query`, ...) are not yet
224
- implemented by the reference server and currently surface `NotImplementedError`.
408
+ | Status | Read methods | Write / delete methods |
409
+ | ------ | ---------------------- | ---------------------- |
410
+ | 404 | `null` | `NotFoundError` |
411
+ | 400 | `ValidationError` | `ValidationError` |
412
+ | 401 | `AuthRequiredError` | `AuthRequiredError` |
413
+ | 409 | `ConflictError` | `ConflictError` |
414
+ | 413 | `PayloadTooLargeError` | `PayloadTooLargeError` |
415
+ | 501 | `NotImplementedError` | `NotImplementedError` |
416
+ | 507 | `QuotaExceededError` | `QuotaExceededError` |
417
+ | 5xx | `WasServerError` | `WasServerError` |
418
+
419
+ All error classes extend `WasError` (carrying `status`, the problem-kind `type`
420
+ URI, `title`, `details`, and `requestUrl`). When the server sends a
421
+ `problem+json` `type` (the spec's Error Type Registry), `mapError()` dispatches
422
+ on that kind first and falls back to the HTTP status -- so, for example, a 409
423
+ `id-conflict` from `createSpace({ id })` is catchable as a `ConflictError`, and
424
+ a 507 `quota-exceeded` (a client-actionable storage-full condition, not a server
425
+ fault) as a `QuotaExceededError`. `delete()` additionally treats a 404 as
426
+ success, so it is idempotent.
427
+
428
+ Some spec endpoints (`listSpaces()`, ...) are not yet implemented by the
429
+ reference server and currently surface `NotImplementedError`.
225
430
 
226
431
  ## Contribute
227
432
 
@@ -1,6 +1,6 @@
1
1
  import type { ClientContext } from './internal/request.js';
2
2
  import { Resource } from './Resource.js';
3
- import type { AddResult, BackendReference, CollectionDescription, GrantOptions, HandleOptions, IDelegatedZcap, IZcap, Json, LinkSet, PolicyDocument, ResourceListing } from './types.js';
3
+ import type { AddResult, BackendReference, CollectionDescription, GrantOptions, HandleOptions, IDelegatedZcap, IZcap, Json, LinkSet, PolicyDocument, CollectionResourcesList } from './types.js';
4
4
  export declare class Collection {
5
5
  readonly spaceId: string;
6
6
  readonly id: string;
@@ -97,9 +97,9 @@ export declare class Collection {
97
97
  * Lists the items in the collection. Returns `null` if the collection is
98
98
  * missing or not visible to you (404 conflation caveat).
99
99
  *
100
- * @returns {Promise<ResourceListing | null>}
100
+ * @returns {Promise<CollectionResourcesList | null>}
101
101
  */
102
- list(): Promise<ResourceListing | null>;
102
+ list(): Promise<CollectionResourcesList | null>;
103
103
  /**
104
104
  * Delegates access to this collection. Prefills the grant `target` with this
105
105
  * collection's URL (and the bound `capability`, if any, for re-delegation).
@@ -124,6 +124,12 @@ export declare class Collection {
124
124
  * @returns {Promise<void>}
125
125
  */
126
126
  setPolicy(policy: PolicyDocument): Promise<void>;
127
+ /**
128
+ * Returns `true` when this collection's policy is `PublicCanRead`.
129
+ *
130
+ * @returns {Promise<boolean>}
131
+ */
132
+ isPublic(): Promise<boolean>;
127
133
  /**
128
134
  * Makes the collection world-readable: every resource in it becomes readable
129
135
  * without authorization (unless overridden by a more specific policy). Sugar
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"AAkBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,KAAK,EACL,IAAI,EACJ,OAAO,EACP,cAAc,EACd,eAAe,EAChB,MAAM,YAAY,CAAA;AAEnB,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAOD,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,UAAU,GAErB;IAED;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAUvD;;;;;;;;OAQG;IACG,SAAS,CAAC,IAAI,EAAE;QACpB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,gBAAgB,CAAA;KAC3B,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAoBlC;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,QAAQ;IAUnE;;;;;;;;;OASG;IACG,GAAG,CACP,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,SAAS,CAAC;IAgCrB;;;;;;;OAOG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAU1D;;;;;;;;OAQG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAIhB;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,eAAe,GAAG,IAAI,CAAC;IAU7C;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAU3D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAStD;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IASlC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;CASzC"}
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"AAmBA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,KAAK,EACV,SAAS,EACT,gBAAgB,EAChB,qBAAqB,EACrB,YAAY,EACZ,aAAa,EACb,cAAc,EACd,KAAK,EACL,IAAI,EACJ,OAAO,EACP,cAAc,EACd,uBAAuB,EACxB,MAAM,YAAY,CAAA;AAEnB,qBAAa,UAAU;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAOD,OAAO,KAAK,KAAK,GAEhB;IAED,OAAO,KAAK,UAAU,GAErB;IAED;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC;IAUvD;;;;;;;;OAQG;IACG,SAAS,CAAC,IAAI,EAAE;QACpB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,OAAO,CAAC,EAAE,gBAAgB,CAAA;KAC3B,GAAG,OAAO,CAAC,qBAAqB,CAAC;IAqBlC;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B;;;;;;;OAOG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,QAAQ;IAUnE;;;;;;;;;OASG;IACG,GAAG,CACP,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,SAAS,CAAC;IAgCrB;;;;;;;OAOG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAU1D;;;;;;;;OAQG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAIhB;;;;;OAKG;IACG,IAAI,IAAI,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAUrD;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAU3D;;;;;;;OAOG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAStD;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAKlC;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IASlC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;CASzC"}
@@ -8,6 +8,7 @@
8
8
  */
9
9
  import { collectionPath, collectionItems, collectionPolicy, collectionLinkset, resourcePath, toUrl } from './internal/paths.js';
10
10
  import { prepareBody, parseResource } from './internal/content.js';
11
+ import { assertNotReserved } from './internal/reserved.js';
11
12
  import { delegateGrant } from './internal/grant.js';
12
13
  import { send } from './internal/request.js';
13
14
  import { Resource } from './Resource.js';
@@ -62,6 +63,7 @@ export class Collection {
62
63
  * @returns {Promise<CollectionDescription>}
63
64
  */
64
65
  async configure(desc) {
66
+ assertNotReserved(this.id, 'collection');
65
67
  const current = await this.describe();
66
68
  const name = desc.name ?? current?.name;
67
69
  const body = { id: this.id, name };
@@ -179,7 +181,7 @@ export class Collection {
179
181
  * Lists the items in the collection. Returns `null` if the collection is
180
182
  * missing or not visible to you (404 conflation caveat).
181
183
  *
182
- * @returns {Promise<ResourceListing | null>}
184
+ * @returns {Promise<CollectionResourcesList | null>}
183
185
  */
184
186
  async list() {
185
187
  const response = await send(this._context, {
@@ -236,6 +238,15 @@ export class Collection {
236
238
  json: policy
237
239
  });
238
240
  }
241
+ /**
242
+ * Returns `true` when this collection's policy is `PublicCanRead`.
243
+ *
244
+ * @returns {Promise<boolean>}
245
+ */
246
+ async isPublic() {
247
+ const policy = await this.getPolicy();
248
+ return policy?.type === 'PublicCanRead';
249
+ }
239
250
  /**
240
251
  * Makes the collection world-readable: every resource in it becomes readable
241
252
  * without authorization (unless overridden by a more specific policy). Sugar
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Collection.js","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import type { ClientContext } from './internal/request.js';
2
- import type { IZcap, Json, PolicyDocument } from './types.js';
2
+ import type { IZcap, Json, PolicyDocument, ResourceMetadata, ResourceMetadataCustom } from './types.js';
3
3
  export declare class Resource {
4
4
  readonly spaceId: string;
5
5
  readonly collectionId: string;
@@ -63,6 +63,46 @@ export declare class Resource {
63
63
  * @returns {Promise<void>}
64
64
  */
65
65
  delete(): Promise<void>;
66
+ private get _metaPath();
67
+ /**
68
+ * Reads the resource's metadata object (server-managed `contentType` / `size`
69
+ * / timestamps plus the user-writable `custom` object). Returns `null` if the
70
+ * resource is missing or not visible to you (404 conflation caveat). A server
71
+ * without metadata support surfaces its 501 as `NotImplementedError`.
72
+ *
73
+ * @returns {Promise<ResourceMetadata | null>}
74
+ */
75
+ meta(): Promise<ResourceMetadata | null>;
76
+ /**
77
+ * Replaces the resource's user-writable metadata (`custom`). This is a full
78
+ * replacement: any property omitted from `custom` is cleared, and an omitted
79
+ * `custom` clears them all. Does not create the resource -- a `PUT` to the
80
+ * metadata of a nonexistent resource throws `NotFoundError`. Servers without
81
+ * metadata support surface their 501 as `NotImplementedError`.
82
+ *
83
+ * @param meta {object}
84
+ * @param [meta.custom] {ResourceMetadataCustom} the user-writable properties
85
+ * @returns {Promise<void>}
86
+ */
87
+ setMeta(meta?: {
88
+ custom?: ResourceMetadataCustom;
89
+ }): Promise<void>;
90
+ /**
91
+ * Sets the resource's human-readable `name` (the value surfaced in collection
92
+ * listings), preserving any existing `tags`. Convenience over `setMeta()`.
93
+ *
94
+ * @param name {string}
95
+ * @returns {Promise<void>}
96
+ */
97
+ setName(name: string): Promise<void>;
98
+ /**
99
+ * Sets the resource's `tags`, preserving any existing `name`. Convenience over
100
+ * `setMeta()`.
101
+ *
102
+ * @param tags {Record<string, string>}
103
+ * @returns {Promise<void>}
104
+ */
105
+ setTags(tags: Record<string, string>): Promise<void>;
66
106
  private get _policyPath();
67
107
  /**
68
108
  * Reads the resource's access-control policy. Returns `null` when no policy is
@@ -86,6 +126,12 @@ export declare class Resource {
86
126
  * @returns {Promise<void>}
87
127
  */
88
128
  setPublic(): Promise<void>;
129
+ /**
130
+ * Returns `true` when this resource policy is `PublicCanRead`.
131
+ *
132
+ * @returns {Promise<boolean>}
133
+ */
134
+ isPublic(): Promise<boolean>;
89
135
  /**
90
136
  * Removes the resource's access-control policy, reverting it to
91
137
  * capability-only access. Idempotent.
@@ -1 +1 @@
1
- {"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAE7D,qBAAa,QAAQ;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAQD,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;;OAMG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAUxC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUvC;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAa5C;;;;;;;;;OASG;IACG,GAAG,CACP,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAehB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,OAAO,KAAK,WAAW,GAEtB;IAED;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAStD;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAQnC"}
1
+ {"version":3,"file":"Resource.d.ts","sourceRoot":"","sources":["../src/Resource.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAE1D,OAAO,KAAK,EACV,KAAK,EACL,IAAI,EACJ,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACvB,MAAM,YAAY,CAAA;AAEnB,qBAAa,QAAQ;IACnB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAEnB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAe;IACxC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAO;IAEpC;;;;;;;OAOG;gBACS,EACV,OAAO,EACP,OAAO,EACP,YAAY,EACZ,UAAU,EACV,UAAU,EACX,EAAE;QACD,OAAO,EAAE,aAAa,CAAA;QACtB,OAAO,EAAE,MAAM,CAAA;QACf,YAAY,EAAE,MAAM,CAAA;QACpB,UAAU,EAAE,MAAM,CAAA;QAClB,UAAU,CAAC,EAAE,KAAK,CAAA;KACnB;IAQD,OAAO,KAAK,KAAK,GAEhB;IAED;;;;;;OAMG;IACG,GAAG,IAAI,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAUxC;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAUvC;;;;;OAKG;IACG,QAAQ,IAAI,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC;IAa5C;;;;;;;;;OASG;IACG,GAAG,CACP,IAAI,EAAE,IAAI,GAAG,IAAI,GAAG,UAAU,EAC9B,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,IAAI,CAAC;IAehB;;;;OAIG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAS7B,OAAO,KAAK,SAAS,GAEpB;IAED;;;;;;;OAOG;IACG,IAAI,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAU9C;;;;;;;;;;OAUG;IACG,OAAO,CAAC,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,sBAAsB,CAAA;KAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS5E;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C;;;;;;OAMG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1D,OAAO,KAAK,WAAW,GAEtB;IAED;;;;;;OAMG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAUjD;;;;;OAKG;IACG,SAAS,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAStD;;;;;OAKG;IACG,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAIhC;;;;OAIG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAKlC;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;CAQnC"}
package/dist/Resource.js CHANGED
@@ -6,7 +6,7 @@
6
6
  * keyed by id within a Collection). Sugar over the Collection item operations,
7
7
  * with explicit `getText()` / `getBytes()` escape hatches.
8
8
  */
9
- import { resourcePath, resourcePolicy } from './internal/paths.js';
9
+ import { resourcePath, resourcePolicy, resourceMeta } from './internal/paths.js';
10
10
  import { prepareBody, parseResource } from './internal/content.js';
11
11
  import { assertNotReserved } from './internal/reserved.js';
12
12
  import { send } from './internal/request.js';
@@ -120,6 +120,67 @@ export class Resource {
120
120
  idempotent: true
121
121
  });
122
122
  }
123
+ get _metaPath() {
124
+ return resourceMeta(this.spaceId, this.collectionId, this.id);
125
+ }
126
+ /**
127
+ * Reads the resource's metadata object (server-managed `contentType` / `size`
128
+ * / timestamps plus the user-writable `custom` object). Returns `null` if the
129
+ * resource is missing or not visible to you (404 conflation caveat). A server
130
+ * without metadata support surfaces its 501 as `NotImplementedError`.
131
+ *
132
+ * @returns {Promise<ResourceMetadata | null>}
133
+ */
134
+ async meta() {
135
+ const response = await send(this._context, {
136
+ path: this._metaPath,
137
+ method: 'GET',
138
+ capability: this._capability,
139
+ read: true
140
+ });
141
+ return response === null ? null : response.data;
142
+ }
143
+ /**
144
+ * Replaces the resource's user-writable metadata (`custom`). This is a full
145
+ * replacement: any property omitted from `custom` is cleared, and an omitted
146
+ * `custom` clears them all. Does not create the resource -- a `PUT` to the
147
+ * metadata of a nonexistent resource throws `NotFoundError`. Servers without
148
+ * metadata support surface their 501 as `NotImplementedError`.
149
+ *
150
+ * @param meta {object}
151
+ * @param [meta.custom] {ResourceMetadataCustom} the user-writable properties
152
+ * @returns {Promise<void>}
153
+ */
154
+ async setMeta(meta = {}) {
155
+ await send(this._context, {
156
+ path: this._metaPath,
157
+ method: 'PUT',
158
+ capability: this._capability,
159
+ json: { custom: meta.custom ?? {} }
160
+ });
161
+ }
162
+ /**
163
+ * Sets the resource's human-readable `name` (the value surfaced in collection
164
+ * listings), preserving any existing `tags`. Convenience over `setMeta()`.
165
+ *
166
+ * @param name {string}
167
+ * @returns {Promise<void>}
168
+ */
169
+ async setName(name) {
170
+ const current = await this.meta();
171
+ await this.setMeta({ custom: { ...current?.custom, name } });
172
+ }
173
+ /**
174
+ * Sets the resource's `tags`, preserving any existing `name`. Convenience over
175
+ * `setMeta()`.
176
+ *
177
+ * @param tags {Record<string, string>}
178
+ * @returns {Promise<void>}
179
+ */
180
+ async setTags(tags) {
181
+ const current = await this.meta();
182
+ await this.setMeta({ custom: { ...current?.custom, tags } });
183
+ }
123
184
  get _policyPath() {
124
185
  return resourcePolicy(this.spaceId, this.collectionId, this.id);
125
186
  }
@@ -162,6 +223,15 @@ export class Resource {
162
223
  async setPublic() {
163
224
  await this.setPolicy({ type: 'PublicCanRead' });
164
225
  }
226
+ /**
227
+ * Returns `true` when this resource policy is `PublicCanRead`.
228
+ *
229
+ * @returns {Promise<boolean>}
230
+ */
231
+ async isPublic() {
232
+ const policy = await this.getPolicy();
233
+ return policy?.type === 'PublicCanRead';
234
+ }
165
235
  /**
166
236
  * Removes the resource's access-control policy, reverting it to
167
237
  * capability-only access. Idempotent.