@interop/was-client 0.99.1 → 0.100.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +127 -69
- package/dist/Collection.d.ts +17 -9
- package/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +85 -70
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts +11 -4
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +34 -28
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts +20 -5
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +69 -65
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts +185 -57
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +340 -140
- package/dist/WasClient.js.map +1 -1
- package/dist/codec.d.ts +3 -2
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +1 -1
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +7 -4
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +39 -20
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/acquire.d.ts +3 -3
- package/dist/edv/acquire.d.ts.map +1 -1
- package/dist/edv/acquire.js +3 -3
- package/dist/edv/acquire.js.map +1 -1
- package/dist/edv/cipher.d.ts +1 -1
- package/dist/edv/cipher.js +1 -1
- package/dist/edv/docCipher.d.ts +6 -5
- package/dist/edv/docCipher.d.ts.map +1 -1
- package/dist/edv/docCipher.js +6 -5
- package/dist/edv/docCipher.js.map +1 -1
- package/dist/edv/encryption.d.ts +2 -2
- package/dist/edv/encryption.d.ts.map +1 -1
- package/dist/edv/encryption.js +8 -6
- package/dist/edv/encryption.js.map +1 -1
- package/dist/edv/refreshingDocCipher.d.ts +3 -3
- package/dist/edv/refreshingDocCipher.d.ts.map +1 -1
- package/dist/edv/refreshingDocCipher.js +3 -3
- package/dist/edv/refreshingDocCipher.js.map +1 -1
- package/dist/edv/transportFactory.d.ts +3 -3
- package/dist/edv/transportFactory.d.ts.map +1 -1
- package/dist/edv/transportFactory.js +3 -3
- package/dist/edv/transportFactory.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/codec.d.ts +7 -7
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +19 -18
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/conditional.d.ts +3 -3
- package/dist/internal/conditional.d.ts.map +1 -1
- package/dist/internal/conditional.js +5 -5
- package/dist/internal/conditional.js.map +1 -1
- package/dist/internal/grant.d.ts +15 -26
- package/dist/internal/grant.d.ts.map +1 -1
- package/dist/internal/grant.js +95 -29
- package/dist/internal/grant.js.map +1 -1
- package/dist/internal/meta.d.ts +8 -8
- package/dist/internal/meta.d.ts.map +1 -1
- package/dist/internal/meta.js +13 -10
- package/dist/internal/meta.js.map +1 -1
- package/dist/internal/paths.d.ts +423 -195
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +582 -369
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/policy.d.ts +23 -23
- package/dist/internal/policy.d.ts.map +1 -1
- package/dist/internal/policy.js +20 -20
- package/dist/internal/policy.js.map +1 -1
- package/dist/internal/request.d.ts +17 -21
- package/dist/internal/request.d.ts.map +1 -1
- package/dist/internal/request.js +10 -21
- package/dist/internal/request.js.map +1 -1
- package/dist/internal/reserved.d.ts +15 -3
- package/dist/internal/reserved.d.ts.map +1 -1
- package/dist/internal/reserved.js +37 -8
- package/dist/internal/reserved.js.map +1 -1
- package/dist/internal/revoke.d.ts +34 -13
- package/dist/internal/revoke.d.ts.map +1 -1
- package/dist/internal/revoke.js +97 -28
- package/dist/internal/revoke.js.map +1 -1
- package/dist/internal/service.d.ts +27 -7
- package/dist/internal/service.d.ts.map +1 -1
- package/dist/internal/service.js +51 -45
- package/dist/internal/service.js.map +1 -1
- package/dist/internal/write.d.ts +18 -18
- package/dist/internal/write.d.ts.map +1 -1
- package/dist/internal/write.js +27 -27
- package/dist/internal/write.js.map +1 -1
- package/dist/paths.d.ts +32 -25
- package/dist/paths.d.ts.map +1 -1
- package/dist/paths.js +32 -25
- package/dist/paths.js.map +1 -1
- package/dist/sync/port.d.ts +3 -3
- package/dist/sync/port.d.ts.map +1 -1
- package/dist/sync/port.js +12 -12
- package/dist/sync/port.js.map +1 -1
- package/dist/sync/provisioning.d.ts +10 -9
- package/dist/sync/provisioning.d.ts.map +1 -1
- package/dist/sync/provisioning.js +19 -18
- package/dist/sync/provisioning.js.map +1 -1
- package/dist/sync/types.d.ts +2 -2
- package/dist/types.d.ts +13 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -48,16 +48,16 @@ through cheap, lazy navigational handles modeled on a document store's DX
|
|
|
48
48
|
(`add`/`get`/`put`/`list`/`delete`) rather than `insertOne`/`findOne` (PWS has
|
|
49
49
|
no query-by-filter yet).
|
|
50
50
|
|
|
51
|
-
| Document db driver | PWS client
|
|
52
|
-
| ----------------------------------- |
|
|
53
|
-
| `new Client(url)` | `new WasClient({
|
|
54
|
-
| `client.db('app')` | `was.
|
|
55
|
-
| `db.collection('users')` | `space.collection(collectionId)`
|
|
56
|
-
| `collection.insertOne(doc)` | `collection.add(doc)`
|
|
57
|
-
| `collection.findOne({ _id })` | `collection.get(resourceId)`
|
|
58
|
-
| `collection.replaceOne({ _id }, d)` | `collection.put(resourceId, data)`
|
|
59
|
-
| `collection.find().toArray()` | `collection.list()`
|
|
60
|
-
| `collection.deleteOne({ _id })` | `collection.resource(resourceId).delete()`
|
|
51
|
+
| Document db driver | PWS client |
|
|
52
|
+
| ----------------------------------- | ---------------------------------------------- |
|
|
53
|
+
| `new Client(url)` | `new WasClient({ baseServerUrl, zcapClient })` |
|
|
54
|
+
| `client.db('app')` | `was.spaceAt(spaceUrl)` |
|
|
55
|
+
| `db.collection('users')` | `space.collection(collectionId)` |
|
|
56
|
+
| `collection.insertOne(doc)` | `collection.add(doc)` |
|
|
57
|
+
| `collection.findOne({ _id })` | `collection.get(resourceId)` |
|
|
58
|
+
| `collection.replaceOne({ _id }, d)` | `collection.put(resourceId, data)` |
|
|
59
|
+
| `collection.find().toArray()` | `collection.list()` |
|
|
60
|
+
| `collection.deleteOne({ _id })` | `collection.resource(resourceId).delete()` |
|
|
61
61
|
|
|
62
62
|
See also:
|
|
63
63
|
|
|
@@ -110,7 +110,7 @@ const zcapClient = new ZcapClient({
|
|
|
110
110
|
|
|
111
111
|
// 3. Wrap it.
|
|
112
112
|
const was = new WasClient({
|
|
113
|
-
|
|
113
|
+
baseServerUrl: 'https://was.example/',
|
|
114
114
|
zcapClient
|
|
115
115
|
})
|
|
116
116
|
```
|
|
@@ -130,7 +130,7 @@ keyPair.controller = `did:key:${keyPair.fingerprint()}`
|
|
|
130
130
|
keyPair.id = `${keyPair.controller}#${keyPair.fingerprint()}`
|
|
131
131
|
|
|
132
132
|
const was = WasClient.fromSigner({
|
|
133
|
-
|
|
133
|
+
baseServerUrl: 'https://was.example/',
|
|
134
134
|
signer: keyPair.signer()
|
|
135
135
|
})
|
|
136
136
|
```
|
|
@@ -139,15 +139,56 @@ The `seed` is where a passphrase-, stored-secret-, or KMS-derived key plugs in:
|
|
|
139
139
|
deriving the same 32-byte seed yields the same DID, and therefore access to the
|
|
140
140
|
same spaces.
|
|
141
141
|
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
`ValidationError`. The
|
|
148
|
-
|
|
149
|
-
(
|
|
150
|
-
`
|
|
142
|
+
A client is built from the server's base server URL. The spec's Server Layout
|
|
143
|
+
places the server-level endpoints under it: `{base}service` is the service
|
|
144
|
+
description, `{base}spaces/` is the Spaces Repository, and
|
|
145
|
+
`{base}space/{space_id}/` is a Space. The base must be an absolute `http(s)` URL
|
|
146
|
+
with no query or fragment. A missing trailing slash is supplied. Anything else
|
|
147
|
+
is refused with `ValidationError`. The result is exposed as `was.baseServerUrl`.
|
|
148
|
+
|
|
149
|
+
`was.space(spaceId)` opens a handle on `{base}space/{spaceId}/`, with no I/O.
|
|
150
|
+
`was.spaceAt(spaceUrl)` opens a handle on a Space URL you hold, such as the
|
|
151
|
+
`Location` of a create response, a listing item's `url`, a linkset entry, a
|
|
152
|
+
stored pointer, a capability's target, or a self-locating DID. A received Space
|
|
153
|
+
URL is used as given. It is never checked against the base, because a grant or a
|
|
154
|
+
DID may name a Space on another server.
|
|
155
|
+
|
|
156
|
+
The `./paths` entry exports the matching builders: `canonicalBaseServerUrl`,
|
|
157
|
+
`serviceDescriptionUrl({ baseServerUrl })`,
|
|
158
|
+
`spacesRepositoryUrl({ baseServerUrl })` and
|
|
159
|
+
`spaceUrlById({ baseServerUrl, spaceId })`. `baseServerUrlOf(url)` is their
|
|
160
|
+
inverse. It accepts the service, Spaces Repository or Space URL and rejects
|
|
161
|
+
anything else. `splitCollectionUrl(url)` splits a Collection URL into its Space
|
|
162
|
+
URL and id.
|
|
163
|
+
|
|
164
|
+
#### Single fixed Space
|
|
165
|
+
|
|
166
|
+
Some servers are one Space with no id and no base server URL, such as a personal
|
|
167
|
+
site whose Collections are `https://alice.example/posts/` and
|
|
168
|
+
`https://alice.example/images/`. Open one with `WasClient.forSpace()` and reach
|
|
169
|
+
a Collection directly with `collectionAt()`:
|
|
170
|
+
|
|
171
|
+
```ts
|
|
172
|
+
const was = WasClient.forSpace({
|
|
173
|
+
spaceUrl: 'https://alice.example/',
|
|
174
|
+
signer: keyPair.didKeySigner()
|
|
175
|
+
})
|
|
176
|
+
|
|
177
|
+
const posts = was.collectionAt('https://alice.example/posts/')
|
|
178
|
+
const post = await posts.get('hello')
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
`forSpace` takes
|
|
182
|
+
`{ spaceUrl, zcapClient | signer, encryption?, serviceDescription? }`. The
|
|
183
|
+
client exposes `was.spaceUrl`, and `was.baseServerUrl` is `undefined`. It finds
|
|
184
|
+
the service description with an unsigned `HEAD` of the Space URL and the
|
|
185
|
+
`Link: <...>; rel="service"` header. `space(id)`, `createSpace()` and
|
|
186
|
+
`listSpaces()` throw `NotSupportedError`.
|
|
187
|
+
|
|
188
|
+
`collectionAt(collectionUrl)` works on any client. The parent of the URL is the
|
|
189
|
+
Space URL and the last segment is the Collection id. A Space URL may be an
|
|
190
|
+
origin root, in which case `Space.id` is `undefined`. At an origin-root Space
|
|
191
|
+
the Collection ids `service`, `spaces` and `space` are reserved.
|
|
151
192
|
|
|
152
193
|
#### Deriving a client from a secret or seed (`./identity`)
|
|
153
194
|
|
|
@@ -162,7 +203,7 @@ import { WasClient } from '@interop/was-client'
|
|
|
162
203
|
const agents = await agentsFromSecret({ secret: 'the account secret' })
|
|
163
204
|
|
|
164
205
|
const was = WasClient.fromSigner({
|
|
165
|
-
|
|
206
|
+
baseServerUrl: 'https://was.example/',
|
|
166
207
|
signer: agents.keyAgent.getSigner()
|
|
167
208
|
})
|
|
168
209
|
```
|
|
@@ -203,15 +244,19 @@ own pace produces.
|
|
|
203
244
|
### Service discovery
|
|
204
245
|
|
|
205
246
|
Before its first signed request, the client reads the server's service
|
|
206
|
-
description.
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
247
|
+
description. A client built from `baseServerUrl` reads `{base}service` with an
|
|
248
|
+
unsigned `GET`. A client built by `forSpace` first sends an unsigned `HEAD` to
|
|
249
|
+
the Space URL and follows the `Link: <...>; rel="service"` header on the
|
|
250
|
+
response, whatever its status, then reads the linked document with an unsigned
|
|
251
|
+
`GET`. The spec fixes no path for the document on a fixed-Space server, so that
|
|
252
|
+
client assumes none.
|
|
253
|
+
|
|
254
|
+
A client with a base checks that the document describes that base. Its `url`
|
|
255
|
+
must equal `{base}service`, and its `spaces` member, when present, must equal
|
|
256
|
+
`{base}spaces/`. Otherwise every signed request rejects with
|
|
257
|
+
`IncompatibleServerError` naming both values. The check also applies to a
|
|
258
|
+
caller-supplied `serviceDescription`. A client built by `forSpace` has no base
|
|
259
|
+
and is not checked. `createSpace()` and `listSpaces()` address `{base}spaces/`.
|
|
215
260
|
|
|
216
261
|
From the document the client selects the PWS specification version it speaks.
|
|
217
262
|
This client speaks only v0.5. It ignores `specs` keys other than
|
|
@@ -254,8 +299,10 @@ that copy without fetching, and `service({ refresh: true })` discovers afresh.
|
|
|
254
299
|
The client exposes the PWS containment model
|
|
255
300
|
(`SpacesRepository > Space > Collection > Resource`) as navigational handles.
|
|
256
301
|
Handles are lazy and synchronous to obtain -- only the verb methods hit the
|
|
257
|
-
network.
|
|
258
|
-
|
|
302
|
+
network. A chain such as `was.spaceAt(url).collection(y)` does no I/O and just
|
|
303
|
+
accumulates URL context; the only way it throws is `ValidationError`, on a URL
|
|
304
|
+
that cannot name a Space or an id on the reserved-segment registry. Existence is
|
|
305
|
+
checked on the first network verb.
|
|
259
306
|
|
|
260
307
|
```ts
|
|
261
308
|
const space = await was.createSpace({ name: 'Home' })
|
|
@@ -282,21 +329,24 @@ one item" footgun. The next sections cover each level in turn.
|
|
|
282
329
|
|
|
283
330
|
A Space is the top-level container, created from the spaces repository. The
|
|
284
331
|
server requires a `name`; `controller` defaults to the client's own DID, and the
|
|
285
|
-
server generates the id unless you pass one. `createSpace()`
|
|
286
|
-
|
|
332
|
+
server generates the id unless you pass one. `createSpace()` reads the
|
|
333
|
+
`Location` header of the response and returns a handle on that Space URL. A
|
|
334
|
+
response without `Location` throws `WasServerError`. `createSpace()` and
|
|
335
|
+
`listSpaces()` address the Spaces Repository, `{base}spaces/` (see
|
|
287
336
|
[Service discovery](#service-discovery)). Against a server whose description has
|
|
288
337
|
no `spaces` URL, they throw `NotSupportedError` without sending anything.
|
|
289
338
|
|
|
290
339
|
```ts
|
|
291
|
-
const space = await was.createSpace({ name: 'Home' }) // POST {
|
|
340
|
+
const space = await was.createSpace({ name: 'Home' }) // POST {base}spaces/
|
|
292
341
|
// A typed Space, e.g. an auxiliary one; `type` defaults to ['Space'].
|
|
293
342
|
const aux = await was.createSpace({
|
|
294
343
|
name: 'Clients',
|
|
295
344
|
type: ['AuxiliarySpace', 'Space']
|
|
296
345
|
})
|
|
297
346
|
|
|
298
|
-
// Lazy handle to an existing space by
|
|
299
|
-
const same = was.
|
|
347
|
+
// Lazy handle to an existing space by its URL -- no I/O until a verb runs.
|
|
348
|
+
const same = was.spaceAt(space.url)
|
|
349
|
+
const byId = was.space('abc') // {base}space/abc/, no I/O
|
|
300
350
|
|
|
301
351
|
// Read the Space Metadata object (null if missing or not visible to you).
|
|
302
352
|
const desc = await space.describe() // { id, type: ['Space'], name, controller } | null
|
|
@@ -318,7 +368,7 @@ await space.replaceDescription(
|
|
|
318
368
|
{ ifMatch: read!.etag }
|
|
319
369
|
) // { etag? }
|
|
320
370
|
await was
|
|
321
|
-
.
|
|
371
|
+
.spaceAt(freshSpaceUrl)
|
|
322
372
|
.replaceDescription(
|
|
323
373
|
{ name: 'Fresh', controller: 'did:key:z6Mk...' },
|
|
324
374
|
{ ifNoneMatch: true }
|
|
@@ -493,9 +543,16 @@ await collection.put('greeting', new Blob(['hello'], { type: 'text/plain' }))
|
|
|
493
543
|
### Delegation and sharing
|
|
494
544
|
|
|
495
545
|
`was.grant(...)` is the general delegation primitive; `space.grant(...)` and
|
|
496
|
-
`collection.grant(...)` are sugar that prefill the grant `target`
|
|
497
|
-
handle
|
|
498
|
-
`
|
|
546
|
+
`collection.grant(...)` are sugar that prefill the grant `target` and `spaceUrl`
|
|
547
|
+
from the handle. A bare `was.grant(...)` with no `capability` and no `spaceUrl`
|
|
548
|
+
is rooted at the target's own root capability. Passing `spaceUrl` roots it at
|
|
549
|
+
that Space instead, and throws `ValidationError` if `target` is not at or
|
|
550
|
+
beneath the Space. The recipient rebuilds access from the received zcap with
|
|
551
|
+
`fromCapability()`, which reads the Space off the capability's chain root. A
|
|
552
|
+
zcap whose chain starts at no root capability, or at one whose target cannot be
|
|
553
|
+
a Space URL, is refused with `ValidationError`, as is one whose
|
|
554
|
+
`invocationTarget` is not the canonical form of the URL the handle would
|
|
555
|
+
address. The server is the authority on whether the root names a Space.
|
|
499
556
|
|
|
500
557
|
```ts
|
|
501
558
|
// Alice grants Bob read access to a resource.
|
|
@@ -503,7 +560,8 @@ const added = await collection.add({ secret: 'value' })
|
|
|
503
560
|
const zcap = await was.grant({
|
|
504
561
|
to: bobDid,
|
|
505
562
|
actions: ['GET'], // HTTP verbs: 'GET' | 'HEAD' | 'PUT' | 'POST' | 'DELETE'
|
|
506
|
-
target: added.url
|
|
563
|
+
target: added.url,
|
|
564
|
+
spaceUrl: space.url
|
|
507
565
|
})
|
|
508
566
|
|
|
509
567
|
// Bob, holding the zcap, rebuilds a handle at the right depth.
|
|
@@ -531,7 +589,7 @@ lowercase forms and normalizes them to uppercase in the signed zcap -- so
|
|
|
531
589
|
|
|
532
590
|
`space.revoke(zcap)` undoes a `grant()`, so a leaked capability need not be
|
|
533
591
|
waited out to its `expires`. `was.revoke(zcap)` is the same operation with the
|
|
534
|
-
Space
|
|
592
|
+
Space read off the capability's delegation chain root.
|
|
535
593
|
|
|
536
594
|
```ts
|
|
537
595
|
const zcap = await collection.grant({ to: appDid, actions: ['GET', 'PUT'] })
|
|
@@ -915,15 +973,15 @@ if (serverDid === undefined) {
|
|
|
915
973
|
|
|
916
974
|
// The pull capability: GET-only, rooted in the peer Space, delegated to that
|
|
917
975
|
// DID.
|
|
918
|
-
const capability = await peerWas.
|
|
976
|
+
const capability = await peerWas.spaceAt(peerSpaceUrl).grant({
|
|
919
977
|
to: serverDid,
|
|
920
978
|
actions: ['GET']
|
|
921
979
|
})
|
|
922
980
|
|
|
923
981
|
const registration = await space.registerReplica({
|
|
924
982
|
id: 'peer-1', // client-chosen and URL-safe
|
|
925
|
-
fromSpace:
|
|
926
|
-
toSpace:
|
|
983
|
+
fromSpace: peerSpaceUrl,
|
|
984
|
+
toSpace: space.url,
|
|
927
985
|
capability,
|
|
928
986
|
collections: [{ id: 'credentials' }], // omit to pull every Collection
|
|
929
987
|
role: 'source'
|
|
@@ -1039,16 +1097,16 @@ import { createEdvEncryption } from '@interop/was-client/edv'
|
|
|
1039
1097
|
|
|
1040
1098
|
const encryption = createEdvEncryption({
|
|
1041
1099
|
// The keystore: return the collection's keys (from your wallet).
|
|
1042
|
-
async resolveKeys({
|
|
1100
|
+
async resolveKeys({ spaceUrl, collectionId }) {
|
|
1043
1101
|
return { keyAgreementKey, keyResolver }
|
|
1044
1102
|
}
|
|
1045
1103
|
})
|
|
1046
|
-
const was = WasClient.fromSigner({
|
|
1104
|
+
const was = WasClient.fromSigner({ baseServerUrl, signer, encryption })
|
|
1047
1105
|
|
|
1048
1106
|
// Declare the collection encrypted (writes the descriptor). The returned handle is
|
|
1049
1107
|
// pre-seeded, so the first write encrypts with no extra round-trip.
|
|
1050
1108
|
const vault = await was
|
|
1051
|
-
.
|
|
1109
|
+
.spaceAt(spaceUrl)
|
|
1052
1110
|
.createCollection({ id: 'vault', encryption: { scheme: 'edv' } })
|
|
1053
1111
|
const { id } = await vault.add({ secret: 'hello' }) // encrypted; id is an EDV id
|
|
1054
1112
|
const back = await vault.get(id) // { secret: 'hello' } -- decrypted
|
|
@@ -1056,7 +1114,7 @@ const back = await vault.get(id) // { secret: 'hello' } -- decrypted
|
|
|
1056
1114
|
// A consumer that did not create it discovers the descriptor and decrypts with its
|
|
1057
1115
|
// own keys -- no override needed; one cached read of the Collection Metadata
|
|
1058
1116
|
// object:
|
|
1059
|
-
const same = was.
|
|
1117
|
+
const same = was.spaceAt(spaceUrl).collection('vault')
|
|
1060
1118
|
await same.get(id) // reads the descriptor, then decrypts
|
|
1061
1119
|
```
|
|
1062
1120
|
|
|
@@ -1073,7 +1131,7 @@ to force the decision and skip the Collection Metadata read --
|
|
|
1073
1131
|
inline), or `'plaintext'`:
|
|
1074
1132
|
|
|
1075
1133
|
```ts
|
|
1076
|
-
const vault = was.
|
|
1134
|
+
const vault = was.spaceAt(spaceUrl).collection('vault', {
|
|
1077
1135
|
encryption: { scheme: 'edv' }
|
|
1078
1136
|
})
|
|
1079
1137
|
```
|
|
@@ -1154,7 +1212,7 @@ same codec, doc ciphers, key epochs, recipient operations, blinding keys,
|
|
|
1154
1212
|
`resourceDescriptorStore`, and the log-governed descriptor stores, with every
|
|
1155
1213
|
transport module left out of the import graph. `collectionDescriptorStore` stays
|
|
1156
1214
|
on `./edv`, since it reads through a live `Collection` handle. The example below
|
|
1157
|
-
leaves `
|
|
1215
|
+
leaves `spaceUrl` unset. A cipher told which Space its collection lives in loads
|
|
1158
1216
|
the transport factory for the chunked paths. A cipher with no Space still reads
|
|
1159
1217
|
a chunked envelope when `decrypt` is given a `chunkSource`, a function that
|
|
1160
1218
|
serves each chunk (`{ docId, chunkIndex }` to the parsed chunk, or `undefined`)
|
|
@@ -1210,7 +1268,7 @@ await ensureFirstEpoch({
|
|
|
1210
1268
|
Then declare what is searchable and search it:
|
|
1211
1269
|
|
|
1212
1270
|
```ts
|
|
1213
|
-
const vault = was.
|
|
1271
|
+
const vault = was.spaceAt(spaceUrl).collection('vault')
|
|
1214
1272
|
await vault.declareIndex({ attribute: 'content.type' })
|
|
1215
1273
|
|
|
1216
1274
|
await vault.add({ type: 'note', title: 'alpha' })
|
|
@@ -1265,7 +1323,7 @@ to replicate one Space + Collection across devices, with PWS as the primary
|
|
|
1265
1323
|
copy. It is not a sync engine itself -- it provides the seams a change engine
|
|
1266
1324
|
plugs into:
|
|
1267
1325
|
|
|
1268
|
-
- **`createWasSyncPort({ was,
|
|
1326
|
+
- **`createWasSyncPort({ was, spaceUrl, collectionId })`** builds a
|
|
1269
1327
|
`WasSyncPort`: paged pulls over the collection's `changes` feed (resumable via
|
|
1270
1328
|
an opaque server-side checkpoint) and conditional pushes
|
|
1271
1329
|
(`putContent`/`deleteContent`/`putMeta`) guarded by the server's content
|
|
@@ -1311,10 +1369,10 @@ plugs into:
|
|
|
1311
1369
|
collection; `createEdvDocCipher(...)` (from `@interop/was-client/edv`) is the
|
|
1312
1370
|
encrypting one, built from the collection's key-epoch descriptor (every
|
|
1313
1371
|
encrypted collection carries one from birth; install epoch[0] at provision
|
|
1314
|
-
time with `ensureFirstEpoch`). Build it with the collection's `
|
|
1315
|
-
`decrypt` fetch a chunked blob's chunks, or pass `decrypt` a `chunkSource`
|
|
1316
|
-
serve them from bytes you hold. On a searchable collection, also hand it
|
|
1317
|
-
stored Collection `/meta` value (the `meta` input, or `applyMeta` when the
|
|
1372
|
+
time with `ensureFirstEpoch`). Build it with the collection's `spaceUrl` to
|
|
1373
|
+
let `decrypt` fetch a chunked blob's chunks, or pass `decrypt` a `chunkSource`
|
|
1374
|
+
to serve them from bytes you hold. On a searchable collection, also hand it
|
|
1375
|
+
the stored Collection `/meta` value (the `meta` input, or `applyMeta` when the
|
|
1318
1376
|
replica's copy changes) so pushed documents carry blinded index entries and
|
|
1319
1377
|
stay visible to `find()`. `createEdvEncryptOnlyDocCipher(...)` is the
|
|
1320
1378
|
write-only counterpart, built from the descriptor alone with no key-agreement
|
|
@@ -1356,21 +1414,21 @@ plugs into:
|
|
|
1356
1414
|
import {
|
|
1357
1415
|
createWasSyncPort,
|
|
1358
1416
|
createPlaintextDocCipher,
|
|
1359
|
-
deriveSpaceId,
|
|
1360
1417
|
ensureSpaceAndCollection,
|
|
1361
1418
|
isSyncConflictError
|
|
1362
1419
|
} from '@interop/was-client/sync'
|
|
1363
1420
|
|
|
1364
|
-
|
|
1421
|
+
// The Space URL is received, then stored: the same Space on every client.
|
|
1422
|
+
const spaceUrl = storedSpaceUrl
|
|
1365
1423
|
await ensureSpaceAndCollection({
|
|
1366
1424
|
was,
|
|
1367
|
-
|
|
1425
|
+
spaceUrl,
|
|
1368
1426
|
controllerDid,
|
|
1369
1427
|
collectionId: 'notes',
|
|
1370
1428
|
encryption: 'plaintext'
|
|
1371
1429
|
})
|
|
1372
1430
|
|
|
1373
|
-
const port = createWasSyncPort({ was,
|
|
1431
|
+
const port = createWasSyncPort({ was, spaceUrl, collectionId: 'notes' })
|
|
1374
1432
|
const cipher = createPlaintextDocCipher({ collectionId: 'notes' })
|
|
1375
1433
|
|
|
1376
1434
|
// Push: encrypt (mints the id), then write the stored body verbatim.
|
|
@@ -1474,14 +1532,14 @@ large Blobs to disk.)
|
|
|
1474
1532
|
|
|
1475
1533
|
### The manual-request escape hatch
|
|
1476
1534
|
|
|
1477
|
-
`was.request(...)` mirrors ezcap's generic `request()` for hand-built calls.
|
|
1478
|
-
a deliberate escape hatch it returns the raw
|
|
1479
|
-
ezcap/ky errors -- it does not apply the
|
|
1480
|
-
conveniences. It still waits on service discovery, so
|
|
1481
|
-
server it rejects with `IncompatibleServerError`.
|
|
1535
|
+
`was.request(...)` mirrors ezcap's generic `request()` for hand-built calls. It
|
|
1536
|
+
takes an absolute `url`. As a deliberate escape hatch it returns the raw
|
|
1537
|
+
`HttpResponse` and throws raw ezcap/ky errors -- it does not apply the
|
|
1538
|
+
null-on-404 or typed-error conveniences. It still waits on service discovery, so
|
|
1539
|
+
against an incompatible server it rejects with `IncompatibleServerError`.
|
|
1482
1540
|
|
|
1483
1541
|
```ts
|
|
1484
|
-
const response = await was.request({
|
|
1542
|
+
const response = await was.request({ url: space.url, method: 'GET' })
|
|
1485
1543
|
```
|
|
1486
1544
|
|
|
1487
1545
|
## Errors and the 404/null caveat
|
package/dist/Collection.d.ts
CHANGED
|
@@ -6,22 +6,32 @@ import type { ChangesCheckpoint, ChangesPage, ResourceChangeDocument } from '@in
|
|
|
6
6
|
import type { AddResult, BackendDescriptor, BackendUsage, CollectionMetadata, CollectionWritableFields, EncryptionOverride, FindPage, GrantOptions, HandleOptions, IDelegatedZcap, IZcap, Json, ResourceData, LinkSet, PolicyDocument, CollectionResourcesList, ResourceMetadataCustomInput, ResourceSummary } from './types.js';
|
|
7
7
|
export declare class Collection {
|
|
8
8
|
#private;
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* The URL of the Space this Collection lives in, in canonical form.
|
|
11
|
+
*/
|
|
12
|
+
readonly spaceUrl: string;
|
|
10
13
|
readonly id: string;
|
|
14
|
+
/**
|
|
15
|
+
* The Collection container in canonical (trailing-slash) form: the URL whose
|
|
16
|
+
* `GET` lists the Collection's Resources, whose `POST` adds one, and whose
|
|
17
|
+
* `DELETE` removes the Collection. A Collection's own description is not
|
|
18
|
+
* here -- it is the Metadata object at the reserved `meta` segment.
|
|
19
|
+
*/
|
|
20
|
+
readonly url: string;
|
|
11
21
|
/**
|
|
12
22
|
* @param options {object}
|
|
13
|
-
* @param options.context {ClientContext} - Shared context (
|
|
14
|
-
*
|
|
15
|
-
* @param options.
|
|
23
|
+
* @param options.context {ClientContext} - Shared context (ezcap client,
|
|
24
|
+
* controllerDid)
|
|
25
|
+
* @param options.spaceUrl {string} the Space's URL, as the server named it
|
|
16
26
|
* @param options.collectionId {string}
|
|
17
27
|
* @param [options.capability] {IZcap} - capability attached to every request
|
|
18
28
|
* @param [options.encryption] {EncryptionOverride} - per-handle encryption
|
|
19
29
|
* override; wins over the Collection's declared descriptor and skips the
|
|
20
30
|
* descriptor-discovery round-trip
|
|
21
31
|
*/
|
|
22
|
-
constructor({ context,
|
|
32
|
+
constructor({ context, spaceUrl, collectionId, capability, encryption }: {
|
|
23
33
|
context: ClientContext;
|
|
24
|
-
|
|
34
|
+
spaceUrl: string;
|
|
25
35
|
collectionId: string;
|
|
26
36
|
capability?: IZcap;
|
|
27
37
|
encryption?: EncryptionOverride;
|
|
@@ -303,10 +313,8 @@ export declare class Collection {
|
|
|
303
313
|
* sub-resource {@link getHistoryLog} reads. A log-governed descriptor's
|
|
304
314
|
* `history.resource` names this URL; a verifying reader compares the two
|
|
305
315
|
* before opening the log.
|
|
306
|
-
*
|
|
307
|
-
* @returns {string}
|
|
308
316
|
*/
|
|
309
|
-
|
|
317
|
+
readonly historyLogUrl: string;
|
|
310
318
|
/**
|
|
311
319
|
* Reads the Collection's governing history log (the encrypted-collections
|
|
312
320
|
* profile's `governed-history-logs` feature): the JSON Lines body served at the
|
package/dist/Collection.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AAgC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AA+BlE,OAAO,KAAK,EAEV,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,WAAW,EAEZ,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AAExC,OAAO,KAAK,EACV,iBAAiB,EACjB,WAAW,EACX,sBAAsB,EACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EACV,SAAS,EACT,iBAAiB,EACjB,YAAY,EAEZ,kBAAkB,EAClB,wBAAwB,EACxB,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,aAAa,EACb,cAAc,EACd,KAAK,EACL,IAAI,EACJ,YAAY,EACZ,OAAO,EACP,cAAc,EACd,uBAAuB,EAEvB,2BAA2B,EAC3B,eAAe,EAChB,MAAM,YAAY,CAAA;AA8FnB,qBAAa,UAAU;;IACrB,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
|