@interop/was-client 0.92.0 → 0.93.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.
Files changed (65) hide show
  1. package/README.md +176 -13
  2. package/dist/Collection.d.ts +43 -6
  3. package/dist/Collection.d.ts.map +1 -1
  4. package/dist/Collection.js +96 -21
  5. package/dist/Collection.js.map +1 -1
  6. package/dist/Resource.d.ts +35 -2
  7. package/dist/Resource.d.ts.map +1 -1
  8. package/dist/Resource.js +49 -5
  9. package/dist/Resource.js.map +1 -1
  10. package/dist/Space.d.ts +85 -1
  11. package/dist/Space.d.ts.map +1 -1
  12. package/dist/Space.js +160 -1
  13. package/dist/Space.js.map +1 -1
  14. package/dist/codec.d.ts +26 -0
  15. package/dist/codec.d.ts.map +1 -1
  16. package/dist/edv/EdvCodec.d.ts +20 -1
  17. package/dist/edv/EdvCodec.d.ts.map +1 -1
  18. package/dist/edv/EdvCodec.js +161 -85
  19. package/dist/edv/EdvCodec.js.map +1 -1
  20. package/dist/edv/WasTransport.d.ts.map +1 -1
  21. package/dist/edv/WasTransport.js +10 -7
  22. package/dist/edv/WasTransport.js.map +1 -1
  23. package/dist/errors.d.ts +13 -5
  24. package/dist/errors.d.ts.map +1 -1
  25. package/dist/errors.js +98 -49
  26. package/dist/errors.js.map +1 -1
  27. package/dist/identity/agents.d.ts +8 -0
  28. package/dist/identity/agents.d.ts.map +1 -1
  29. package/dist/identity/agents.js +13 -1
  30. package/dist/identity/agents.js.map +1 -1
  31. package/dist/index.d.ts +3 -3
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +4 -2
  34. package/dist/index.js.map +1 -1
  35. package/dist/internal/blob.d.ts +16 -1
  36. package/dist/internal/blob.d.ts.map +1 -1
  37. package/dist/internal/blob.js +34 -1
  38. package/dist/internal/blob.js.map +1 -1
  39. package/dist/internal/codec.d.ts +3 -2
  40. package/dist/internal/codec.d.ts.map +1 -1
  41. package/dist/internal/codec.js +26 -3
  42. package/dist/internal/codec.js.map +1 -1
  43. package/dist/internal/content.d.ts +65 -10
  44. package/dist/internal/content.d.ts.map +1 -1
  45. package/dist/internal/content.js +88 -11
  46. package/dist/internal/content.js.map +1 -1
  47. package/dist/internal/describe.d.ts.map +1 -1
  48. package/dist/internal/describe.js +6 -1
  49. package/dist/internal/describe.js.map +1 -1
  50. package/dist/internal/paths.d.ts +17 -11
  51. package/dist/internal/paths.d.ts.map +1 -1
  52. package/dist/internal/paths.js +23 -11
  53. package/dist/internal/paths.js.map +1 -1
  54. package/dist/sync/envelope.d.ts +11 -3
  55. package/dist/sync/envelope.d.ts.map +1 -1
  56. package/dist/sync/envelope.js +11 -3
  57. package/dist/sync/envelope.js.map +1 -1
  58. package/dist/sync/port.d.ts.map +1 -1
  59. package/dist/sync/port.js +6 -10
  60. package/dist/sync/port.js.map +1 -1
  61. package/dist/sync/types.d.ts +5 -8
  62. package/dist/sync/types.d.ts.map +1 -1
  63. package/dist/types.d.ts +12 -6
  64. package/dist/types.d.ts.map +1 -1
  65. package/package.json +8 -7
package/README.md CHANGED
@@ -26,6 +26,7 @@
26
26
  - [Conditional writes (optimistic concurrency)](#conditional-writes-optimistic-concurrency)
27
27
  - [Storage introspection: backends and quotas](#storage-introspection-backends-and-quotas)
28
28
  - [Registering a Bring-Your-Own-Storage backend](#registering-a-bring-your-own-storage-backend)
29
+ - [Replica registration](#replica-registration)
29
30
  - [Encrypted collections (EDV-over-WAS): pass-through encryption via the WAS client (recommended)](#encrypted-collections-edv-over-was-pass-through-encryption-via-the-was-client-recommended)
30
31
  - [Cross-replica sync](#cross-replica-sync)
31
32
  - [Resource logs (co-managed key resources)](#resource-logs-co-managed-key-resources)
@@ -432,7 +433,12 @@ await collection.resource('vc-1').delete() // idempotent
432
433
 
433
434
  Writes detect the payload: a plain object/array is sent as JSON; a
434
435
  `Blob`/`Uint8Array`/`Buffer` is sent as binary, with the content-type taken from
435
- `options.contentType`, the `Blob.type`, or `application/octet-stream`.
436
+ `options.contentType`, the `Blob.type`, or `application/octet-stream`. A
437
+ `ReadableStream<Uint8Array>` is accepted only by an encrypted collection (see
438
+ [Encrypted collections](#encrypted-collections-edv-over-was-pass-through-encryption-via-the-was-client-recommended)).
439
+ A plaintext collection refuses it with `ValidationError`. A plaintext resource
440
+ has no chunked representation, and a signed request carries a `Digest` of its
441
+ whole body. Buffer the stream into a `Blob` there.
436
442
 
437
443
  ```ts
438
444
  // JSON
@@ -452,13 +458,17 @@ Reads auto-parse: `get()` returns a parsed object for a JSON content-type and a
452
458
  `Blob` otherwise; `getText()` / `getBytes()` are explicit escape hatches.
453
459
  `getWithEtag()` pairs the decoded value with its ETag validator, and
454
460
  `getWithEtag({ as: 'text' })` projects it to text (decrypting where `getText()`
455
- would not).
456
-
457
- A write value is a JSON object/array or binary (`Blob`/`Uint8Array`) -- the
458
- `ResourceData` type. A top-level JSON primitive (a bare `string`, `number`,
459
- `boolean`, or `null`) is **not** accepted; it is a compile-time error. To store
460
- one, either wrap it in an object (`put('greeting', { value: 'hello' })`) or
461
- write it as binary via a `Blob`:
461
+ would not). `getStream()` resolves `{ stream, contentType?, etag? }`, or `null`
462
+ on a miss. It runs the codec like `get()`, so it decrypts on an encrypted
463
+ collection. A JSON body is re-serialized, so it is semantically identical JSON
464
+ but not guaranteed byte-identical.
465
+
466
+ A write value is a JSON object/array or binary (`Blob`/`Uint8Array`, or a
467
+ `ReadableStream<Uint8Array>` on an encrypted collection) -- the `ResourceData`
468
+ type. A top-level JSON primitive (a bare `string`, `number`, `boolean`, or
469
+ `null`) is **not** accepted; it is a compile-time error. To store one, either
470
+ wrap it in an object (`put('greeting', { value: 'hello' })`) or write it as
471
+ binary via a `Blob`:
462
472
 
463
473
  ```ts
464
474
  await collection.put('greeting', new Blob(['hello'], { type: 'text/plain' }))
@@ -627,11 +637,12 @@ collection listings; updating one updates the other.
627
637
  A Collection's configuration (`name`, `backend`, `encryption`, `generator`, read
628
638
  by [`describe()`](#collections)) and its annotations live in one object at the
629
639
  Collection's reserved `/meta` path: server-managed properties (`createdAt` /
630
- `updatedAt` / `createdBy`) plus a user-writable `custom` object (`name` and
631
- `tags`), under one `ETag` validator. `meta()` is that same object with `custom`
632
- decoded through the codec; `describe()` does not resolve the codec at all, so on
633
- an encrypted collection it reports `custom` as the opaque envelope. A server
634
- without the endpoint surfaces its 501 as `NotImplementedError`.
640
+ `updatedAt` / `createdBy` / `created`) plus a user-writable `custom` object
641
+ (`name` and `tags`), under one `ETag` validator. `meta()` is that same object
642
+ with `custom` decoded through the codec; `describe()` does not resolve the codec
643
+ at all, so on an encrypted collection it reports `custom` as the opaque
644
+ envelope. A server without the endpoint surfaces its 501 as
645
+ `NotImplementedError`.
635
646
 
636
647
  ```ts
637
648
  const meta = await collection.meta() // CollectionMetadata | null (null on a miss)
@@ -649,6 +660,12 @@ await collection.setMeta({ custom: { name: 'Vault' } }, { ifMatch: meta?.etag })
649
660
  await collection.setMeta({ custom: { name: 'Vault' } }, { ifNoneMatch: true })
650
661
  ```
651
662
 
663
+ `created` is the write stamp of the write that created the Collection
664
+ (`{ updatedAt, updatedAtCounter, originId }`), kept for the Collection's life. A
665
+ Collection deleted and created again carries the stamp of the later create. No
666
+ write sends it back. A Collection created before the server supported the stamp
667
+ may lack it.
668
+
652
669
  A failed precondition throws `PreconditionFailedError` (412). This `/meta` ETag
653
670
  is independent of every Resource's versions, but not of the configuration
654
671
  members: one validator covers the whole Collection Metadata object, so
@@ -844,6 +861,125 @@ sends no body on an in-place replace).
844
861
  > can actually serve bytes depends on the server having a live provider adapter
845
862
  > for it. Until then it is registered but inert (`status: 'registered'`).
846
863
 
864
+ ### Replica registration
865
+
866
+ A Space can pull from a copy of itself on another server. The Space controller
867
+ registers that peer Space with this server, and this server then runs a pull
868
+ loop against the peer. Replication is one-way. The peer receives nothing unless
869
+ its own server holds a registration pointing back.
870
+
871
+ A registration is a directed edge. `fromSpace` is the peer Space's canonical
872
+ trailing-slash URL, and `toSpace` is this Space's. `role` is always `source`.
873
+ `capability` is the pull capability: a zcap the controller delegates to this
874
+ server's DID, rooted in the peer Space, with `allowedAction` within `GET` and
875
+ `HEAD`. `collections` lists the Collections to pull. Leave it out to pull every
876
+ Collection.
877
+
878
+ ```ts
879
+ // The DID of the server that will pull: the reference server discloses it
880
+ // as `instance.serverDid` in its service description. `instance` is an
881
+ // operator disclosure, so a deployment may leave it out; ask the operator
882
+ // for the DID then.
883
+ const { description } = await was.service()
884
+ const serverDid = description.instance?.serverDid
885
+ if (serverDid === undefined) {
886
+ throw new Error('This server does not disclose its DID.')
887
+ }
888
+
889
+ // The pull capability: GET-only, rooted in the peer Space, delegated to that
890
+ // DID.
891
+ const capability = await peerWas.space(peerSpaceId).grant({
892
+ to: serverDid,
893
+ actions: ['GET']
894
+ })
895
+
896
+ const registration = await space.registerReplica({
897
+ id: 'peer-1', // client-chosen and URL-safe
898
+ fromSpace: `https://peer.example/space/${peerSpaceId}/`,
899
+ toSpace: `https://was.example/space/${space.id}/`,
900
+ capability,
901
+ collections: [{ id: 'credentials' }], // omit to pull every Collection
902
+ role: 'source'
903
+ }) // the stored ReplicaRegistration
904
+
905
+ const listing = await space.replicas() // { url, totalItems, items } | null
906
+ const one = await space.replica('peer-1') // ReplicaRegistration | null
907
+
908
+ const status = await space.replicaStatus('peer-1') // ReplicaStatus | null
909
+ // status.state: 'idle' | 'pulling' | 'backing-off' | 'stalled'
910
+ for (const entry of status?.collections ?? []) {
911
+ if (entry.state === 'stalled') {
912
+ // entry.stall: { reason, since, detail? }
913
+ }
914
+ }
915
+
916
+ // The data already pulled under the registration stays. 'not-found' is the
917
+ // server's masked 404: absent, or the caller is not the controller.
918
+ const { outcome } = await space.deregisterReplica('peer-1') // 'deleted' | 'not-found'
919
+ ```
920
+
921
+ `replicaStatus()` reports the pull loop's runtime state. The response is
922
+ uncacheable and is not part of the registration record. Each Collection entry
923
+ has its own `state` (`synced`, `syncing`, `stalled`, or `skipped`). A stalled
924
+ Collection keeps its checkpoint until the cause is removed, and the other
925
+ Collections continue. Its `stall.reason` is one of:
926
+
927
+ - `clock-bound` -- a received write stamp is dated further ahead of local time
928
+ than the server allows. It clears as local time catches up.
929
+ - `fork` -- a history log or an immutable Collection member differs from the
930
+ local one in a way no write order resolves.
931
+ - `quota-exceeded` -- applying the change would exceed a local quota.
932
+ - `unsupported-backend` -- the Collection names a `backend` this server has no
933
+ registration for.
934
+ - `container-refused` -- the local Space or Collection refused the write.
935
+
936
+ Every replica method is controller-only on the server, the reads included, since
937
+ a registration holds the pull capability. A delegated capability gets the
938
+ masked 404. `replicas()`, `replica()`, and `replicaStatus()` then return `null`,
939
+ and `registerReplica()` throws `NotFoundError`. `deregisterReplica()` reports it
940
+ as `{ outcome: 'not-found' }` rather than swallowing it, so a delegated caller
941
+ can tell that nothing was removed. The three reads reserve `null` for that 404.
942
+ A 2xx with no JSON body is a server fault and throws `WasServerError`.
943
+
944
+ `registerReplica()` throws `ValidationError` (400 `invalid-request-body`) for a
945
+ malformed body. Each entry of the error's `problems` carries a `pointer` naming
946
+ the offending member. It throws `ConflictError` (409) for two refusals, told
947
+ apart by the error's `type` URI:
948
+
949
+ - `replica-refused` (`ProblemTypes.REPLICA_REFUSED`) -- the server refuses the
950
+ peer. For example, the peer Space's `controller` or `type` differs from this
951
+ one, the peer advertises no replication, the capability's controller is not
952
+ this server, or a listed Collection's immutable members differ. The cause is
953
+ in the error's `details`.
954
+ - `id-conflict` (`ProblemTypes.ID_CONFLICT`) -- a registration with this `id`
955
+ already exists.
956
+
957
+ ```ts
958
+ import { ProblemTypes } from '@interop/was-client'
959
+
960
+ try {
961
+ await space.registerReplica(registration)
962
+ } catch (err) {
963
+ if (err instanceof ConflictError && err.type === ProblemTypes.ID_CONFLICT) {
964
+ // already registered under this id
965
+ } else {
966
+ throw err
967
+ }
968
+ }
969
+ ```
970
+
971
+ `deregisterReplica()` throws `ConflictError` (`replica-refused`) when the
972
+ registration is the one that maps this Space's did:webvh controller. Removing it
973
+ would leave the Space with no way to follow its controller's log.
974
+
975
+ A peer advertises replication in its service description, under
976
+ `specs['https://w3id.org/pws/replication']` (version `0.1` on the reference
977
+ server). A registration is per-server state. It is not replicated, it is not
978
+ part of an export, and deleting the Space removes it. `space.describe()`
979
+ surfaces the Space's registrations as the read-only `replicas` member, one
980
+ `{ fromSpace, toSpace, role }` summary per peer, with no registration id and no
981
+ capability. The server ignores `replicas` in a write body.
982
+
847
983
  ### Encrypted collections (EDV-over-WAS): pass-through encryption via the WAS client (recommended)
848
984
 
849
985
  This is the recommended way to use encrypted collections. For the low-level
@@ -966,6 +1102,21 @@ scope for now):
966
1102
  `isPendingStub` recognizes it, and `delete()` removes it with its chunks. Tune
967
1103
  the threshold and the chunk size with
968
1104
  `createEdvEncryption({ maxBlobBytes, chunkSize })`.
1105
+ - **Streams.** A `ReadableStream<Uint8Array>` has no known size, so `add()`
1106
+ always routes it to the chunked-stream path, however short it is. It is
1107
+ encrypted and written as it is read, without buffering. `put(id, stream)`
1108
+ takes the same route where no document is stored at `id` yet. Over an existing
1109
+ document it is refused with `ValidationError` before the stream is read. A
1110
+ content-addressed collection refuses a stream for the reason it refuses a
1111
+ large blob. A write that fails midway cancels the stream, so the source behind
1112
+ it is released. The content type is `options.contentType`, then a guess from
1113
+ the id's extension, then `application/octet-stream`. To read without
1114
+ buffering, call `resource.getStream()` or `collection.getStream(id)`. Its
1115
+ `contentType` is the bare media type, with no parameters, on every collection.
1116
+ For a chunked document the stream fetches and decrypts each chunk as it is
1117
+ read. A missing chunk therefore errors the stream, with `NotFoundError`,
1118
+ rather than the `getStream()` call; a tampered one errors it with
1119
+ `EncryptionError`. `get()` still returns a `Blob`.
969
1120
  - **Raw reads.** `get()` decrypts; the `getText()` / `getBytes()` escape hatches
970
1121
  do not (they return the stored representation).
971
1122
 
@@ -1224,6 +1375,17 @@ carries a blinded-index key, pass the cipher the stored `/meta` value
1224
1375
  Collection-handle write does; a cipher built without it writes documents
1225
1376
  `find()` cannot see until they are rewritten.
1226
1377
 
1378
+ `collection.changes()` reads one page of the raw feed, and sends the query as a
1379
+ `POST` by default. Pass `method: 'GET'` for the read-only form,
1380
+ `GET .../query?profile=changes&checkpoint=...&limit=...`. The server verifies it
1381
+ under the `GET` action and answers the same `ChangesPage`. A caller holding a
1382
+ GET-only capability, such as a pull capability, reads the feed this way. The
1383
+ `POST` form refuses that capability with `NotFoundError`.
1384
+
1385
+ ```ts
1386
+ const page = await collection.changes({ method: 'GET', checkpoint, limit: 100 })
1387
+ ```
1388
+
1227
1389
  ### Resource logs (co-managed key resources)
1228
1390
 
1229
1391
  The opt-in `@interop/was-client/log` subpath is the WAS binding of
@@ -1303,6 +1465,7 @@ not exist". Write/delete methods throw a typed error instead.
1303
1465
  | 400 | `ValidationError` | `ValidationError` |
1304
1466
  | 401 | `AuthRequiredError` | `AuthRequiredError` |
1305
1467
  | 409 | `ConflictError` | `ConflictError` |
1468
+ | 422 | `ValidationError` | `ValidationError` |
1306
1469
  | 413 | `PayloadTooLargeError` | `PayloadTooLargeError` |
1307
1470
  | 501 | `NotImplementedError` | `NotImplementedError` |
1308
1471
  | 507 | `QuotaExceededError` | `QuotaExceededError` |
@@ -1,6 +1,6 @@
1
1
  import type { ClientContext } from './internal/request.js';
2
2
  import type { WritePrecondition } from './internal/conditional.js';
3
- import type { CodecRequestContext, IndexDeclaration, IndexSchema } from './codec.js';
3
+ import type { CodecRequestContext, DecodedStream, IndexDeclaration, IndexSchema } from './codec.js';
4
4
  import { Resource } from './Resource.js';
5
5
  import type { ChangesCheckpoint, ChangesPage, ResourceChangeDocument } from '@interop/storage-core';
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';
@@ -458,12 +458,21 @@ export declare class Collection {
458
458
  resource(resourceId: string, options?: HandleOptions): Resource;
459
459
  /**
460
460
  * Adds a resource with a server-generated id. JSON for plain objects/arrays,
461
- * binary for `Blob`/`Uint8Array`. Throws `NotFoundError` if the collection
462
- * does not exist (WAS does not auto-create parents).
461
+ * binary for `Blob`/`Uint8Array` or `ReadableStream<Uint8Array>`. Throws
462
+ * `NotFoundError` if the collection does not exist (WAS does not
463
+ * auto-create parents).
463
464
  *
464
465
  * On an encrypted collection a binary payload above the codec's
465
466
  * single-document threshold is auto-routed to the chunked-stream path, which
466
- * a server that does not serve the chunk endpoints answers with `501`.
467
+ * a server that does not serve the chunk endpoints answers with `501`. A
468
+ * `ReadableStream<Uint8Array>` is always written through that path, without
469
+ * buffering, since its size is unknown. A content-addressed collection
470
+ * (`idDerivation: 'content'`) cannot store a chunked payload, so it refuses
471
+ * a stream with `ValidationError` before reading it.
472
+ *
473
+ * On a plaintext collection a stream is refused with `ValidationError`: a
474
+ * plaintext resource has no chunked representation, and a signed request
475
+ * carries a `Digest` of its whole body. Buffer it into a `Blob` there.
467
476
  *
468
477
  * @param data {ResourceData}
469
478
  * @param options {object}
@@ -482,11 +491,25 @@ export declare class Collection {
482
491
  * @returns {Promise<Json | Blob | null>}
483
492
  */
484
493
  get(resourceId: string): Promise<Json | Blob | null>;
494
+ /**
495
+ * Reads a resource by id as a byte stream, decrypting on an encrypted
496
+ * collection -- the read for a caller that cannot buffer a large chunked
497
+ * blob. Delegates to `Resource.getStream`; see it for the details. The
498
+ * ordinary {@link get} still returns a `Blob`. Returns `null` on a
499
+ * missing/unauthorized resource (404 conflation caveat).
500
+ *
501
+ * @param resourceId {string}
502
+ * @returns {Promise<(DecodedStream & { etag?: string }) | null>}
503
+ */
504
+ getStream(resourceId: string): Promise<(DecodedStream & {
505
+ etag?: string;
506
+ }) | null>;
485
507
  /**
486
508
  * Creates or replaces a resource by id (upsert). Forwards the
487
509
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
488
- * see it for the conditional-write semantics. Returns the stored
489
- * resource's new `etag`.
510
+ * see it for the conditional-write semantics and for which payloads
511
+ * (including a `ReadableStream<Uint8Array>`) each kind of collection
512
+ * accepts. Returns the stored resource's new `etag`.
490
513
  *
491
514
  * @param resourceId {string}
492
515
  * @param data {ResourceData}
@@ -579,14 +602,25 @@ export declare class Collection {
579
602
  * parse that resource's body). Entries of any other kind pass through
580
603
  * unchecked.
581
604
  *
605
+ * The query is sent as a `POST` whose body carries the parameters, or in
606
+ * the read-only `GET` form with the parameters in the query string, which
607
+ * the server verifies under the `GET` action and answers with the same page.
608
+ * A capability whose `allowedAction` excludes `POST` (a GET-only pull
609
+ * capability, say) reads the feed with `GET`, since the `POST` form refuses
610
+ * it with `NotFoundError`; every other handle sends `POST`. `method`
611
+ * overrides the derived form.
612
+ *
582
613
  * @param [options] {object}
583
614
  * @param [options.checkpoint] {ChangesCheckpoint} opaque checkpoint from a prior page; resume strictly after it
584
615
  * @param [options.limit] {number} max documents; the server reduces it to its own maximum
616
+ * @param [options.method] {'POST' | 'GET'} the request form; derived from
617
+ * the bound capability by default
585
618
  * @returns {Promise<ChangesPage>}
586
619
  */
587
620
  changes(options?: {
588
621
  checkpoint?: ChangesCheckpoint;
589
622
  limit?: number;
623
+ method?: 'POST' | 'GET';
590
624
  }): Promise<ChangesPage>;
591
625
  /**
592
626
  * Walks the `changes` feed page by page from `checkpoint` (or the beginning)
@@ -608,11 +642,14 @@ export declare class Collection {
608
642
  * @param [options] {object}
609
643
  * @param [options.checkpoint] {ChangesCheckpoint} resume strictly after it
610
644
  * @param [options.limit] {number} max entries per request, every kind counted
645
+ * @param [options.method] {'POST' | 'GET'} the request form of each page,
646
+ * as for {@link changes}
611
647
  * @returns {AsyncGenerator<{ documents: ResourceChangeDocument[], checkpoint: ChangesCheckpoint | null }>}
612
648
  */
613
649
  resourceChanges(options?: {
614
650
  checkpoint?: ChangesCheckpoint;
615
651
  limit?: number;
652
+ method?: 'POST' | 'GET';
616
653
  }): AsyncGenerator<{
617
654
  documents: ResourceChangeDocument[];
618
655
  checkpoint: ChangesCheckpoint | null;
@@ -1 +1 @@
1
- {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Collection.d.ts","sourceRoot":"","sources":["../src/Collection.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAA;AA+B1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAA;AA8BlE,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,EACvB,2BAA2B,EAC3B,eAAe,EAChB,MAAM,YAAY,CAAA;AAkGnB,qBAAa,UAAU;;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IAYnB;;;;;;;;;;OAUG;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,CAAC,EAAE,KAAK,CAAA;QAClB,UAAU,CAAC,EAAE,kBAAkB,CAAA;KAChC;IAsCD;;;;;;;;;OASG;IACH,YAAY,IAAI,mBAAmB;IAuBnC;;;;;;;;;;;;OAYG;IACG,QAAQ,IAAI,OAAO,CAAC,CAAC,kBAAkB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IAW1E;;;;;;;;;;OAUG;IACG,gBAAgB,IAAI,OAAO,CAAC;QAChC,WAAW,EAAE,kBAAkB,CAAA;QAC/B,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,GAAG,IAAI,CAAC;IAsNT;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8CG;IACG,SAAS,CACb,IAAI,EAAE,wBAAwB,GAAG;QAC/B,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,OAAO,CAAC,EAAE,CAAC,kBAAkB,GAAG;YAAE,IAAI,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC,GAAG,IAAI,CAAA;KAC1D,GACA,OAAO,CAAC;QAAE,WAAW,EAAE,kBAAkB,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA0F9D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAoCG;IACG,kBAAkB,CACtB,WAAW,EAAE,wBAAwB,EACrC,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC;QAAE,WAAW,EAAE,kBAAkB,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAgI9D;;;;;OAKG;IACG,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAa7B;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,IAAI,IAAI,OAAO,CAAC,CAAC,kBAAkB,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IA0BtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAuCG;IACG,OAAO,CACX,IAAI,GAAE;QAAE,MAAM,CAAC,EAAE,2BAA2B,CAAA;KAAO,EACnD,OAAO,GAAE,iBAAsB,GAC9B,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAiD7B;;;;;;;;;;;;;;;;;OAiBG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C;;;;;;;OAOG;IACG,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1D;;;;;;;OAOG;IACH,IAAI,aAAa,IAAI,MAAM,CAE1B;IAED;;;;;;;;;;;;;;;;;OAiBG;IACG,aAAa,IAAI,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IAqBtE;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,aAAa,CACjB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IA8E7B;;;;;;;;;;;;;OAaG;IACG,OAAO,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAK5C;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACG,YAAY,CAAC,EACjB,SAAS,EACT,MAAM,EACP,EAAE;QACD,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;QAC5B,MAAM,CAAC,EAAE,OAAO,CAAA;KACjB,GAAG,OAAO,CAAC,WAAW,CAAC;IAIxB;;;;;;;;;;;;;;;;;;OAkBG;IACG,cAAc,CAAC,EACnB,OAAO,EACR,EAAE;QACD,OAAO,EAAE,KAAK,CAAC;YAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;YAAC,MAAM,CAAC,EAAE,OAAO,CAAA;SAAE,CAAC,CAAA;KACnE,GAAG,OAAO,CAAC,WAAW,CAAC;IA8CxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA4BG;IACG,IAAI,CAAC,OAAO,EAAE;QAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAA;QACjE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;QACvB,KAAK,CAAC,EAAE,OAAO,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GAAG,OAAO,CAAC,QAAQ,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAiEzC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,GAAG,QAAQ;IAkBnE;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACG,GAAG,CACP,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAO,GACrC,OAAO,CAAC,SAAS,CAAC;IAqErB;;;;;;;OAOG;IACG,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC;IAM1D;;;;;;;;;OASG;IACG,SAAS,CACb,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,CAAC,aAAa,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,IAAI,CAAC;IAItD;;;;;;;;;;;;;;OAcG;IACG,GAAG,CACP,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,YAAY,EAClB,OAAO,GAAE;QACP,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,WAAW,CAAC,EAAE,OAAO,CAAA;KACjB,GACL,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAqB7B;;;;;;;;;OASG;IACG,IAAI,IAAI,OAAO,CAAC,uBAAuB,GAAG,IAAI,CAAC;IAIrD;;;;;;;;;OASG;IACI,SAAS,IAAI,cAAc,CAAC,uBAAuB,CAAC;IAI3D;;;;;;;OAOG;IACI,SAAS,IAAI,cAAc,CAAC,eAAe,CAAC;IAInD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2DG;IACG,OAAO,CACX,OAAO,GAAE;QACP,UAAU,CAAC,EAAE,iBAAiB,CAAA;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KACnB,GACL,OAAO,CAAC,WAAW,CAAC;IAqEvB;;;;;;;;;;;;;;;;;;;;;;;OAuBG;IACI,eAAe,CACpB,OAAO,GAAE;QACP,UAAU,CAAC,EAAE,iBAAiB,CAAA;QAC9B,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,GAAG,KAAK,CAAA;KACnB,GACL,cAAc,CAAC;QAChB,SAAS,EAAE,sBAAsB,EAAE,CAAA;QACnC,UAAU,EAAE,iBAAiB,GAAG,IAAI,CAAA;KACrC,CAAC;IAwBF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAgCG;IACG,SAAS,CACb,OAAO,GAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAO,GAC/B,OAAO,CAAC,sBAAsB,EAAE,GAAG,IAAI,CAAC;IAwB3C;;;;;;OAMG;IACG,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,cAAc,CAAC;IAQ3D;;;;;;;;;;;OAWG;IACG,SAAS,IAAI,OAAO,CAAC,cAAc,GAAG,IAAI,CAAC;IAOjD;;;;;;;;;OASG;IACG,iBAAiB,IAAI,OAAO,CAAC;QACjC,MAAM,EAAE,cAAc,CAAA;QACtB,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,GAAG,IAAI,CAAC;IAOT;;;;;;;;;;;;;;OAcG;IACG,SAAS,CACb,MAAM,EAAE,cAAc,EACtB,EAAE,OAAO,EAAE,WAAW,EAAE,GAAE,iBAAsB,GAC/C,OAAO,CAAC;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAU7B;;;;;;OAMG;IACG,QAAQ,IAAI,OAAO,CAAC,OAAO,CAAC;IAOlC;;;;;;;;;;OAUG;IACG,SAAS,CAAC,EAAE,OAAO,EAAE,WAAW,EAAE,GAAE,iBAAsB,GAAG,OAAO,CAAC;QACzE,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAC;IASF;;;;;;;;;;;;OAYG;IACG,WAAW,CAAC,EAAE,OAAO,EAAE,GAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,OAAO,CAAC;QACjE,IAAI,CAAC,EAAE,MAAM,CAAA;KACd,CAAC;IAQF;;;;;OAKG;IACG,OAAO,IAAI,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAOxC;;;;;;;;;;;;;OAaG;IACG,OAAO,IAAI,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC;IAOlD;;;;;;;OAOG;IACG,KAAK,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;CAM5C"}
@@ -71,6 +71,47 @@ function mergedConfiguration(desc, current) {
71
71
  plaintext: desc.plaintext ?? current?.plaintext
72
72
  });
73
73
  }
74
+ /**
75
+ * The request form of the `changes` query a bound capability admits: `GET`
76
+ * when the capability's `allowedAction` is stated and excludes `POST` (a
77
+ * GET-only pull capability), `POST` otherwise (no capability, a root one, or
78
+ * one whose actions are unrestricted or include `POST`).
79
+ */
80
+ function changesMethodFor(capability) {
81
+ const allowed = capability?.allowedAction ?? 'POST';
82
+ const actions = Array.isArray(allowed) ? allowed : [allowed];
83
+ return actions.some(action => action.toUpperCase() === 'POST')
84
+ ? 'POST'
85
+ : 'GET';
86
+ }
87
+ /**
88
+ * The path and body of a `changes` query in the given form. The `POST` form
89
+ * carries the parameters in its JSON body; the read-only `GET` form carries
90
+ * them in the query string, each percent-encoded by `URLSearchParams` so an
91
+ * opaque checkpoint never breaks the URL.
92
+ *
93
+ * @param options {object}
94
+ * @param options.queryPath {string} the collection's `/query` path
95
+ * @param options.method {'POST' | 'GET'}
96
+ * @param [options.checkpoint] {ChangesCheckpoint}
97
+ * @param [options.limit] {number}
98
+ * @returns {{ path: string, method: 'POST' | 'GET', json?: object }}
99
+ */
100
+ function changesRequest({ queryPath, method, checkpoint, limit }) {
101
+ const params = {
102
+ profile: 'changes',
103
+ ...(checkpoint !== undefined && { checkpoint }),
104
+ ...(limit !== undefined && { limit })
105
+ };
106
+ if (method === 'POST') {
107
+ return { path: queryPath, method, json: params };
108
+ }
109
+ const search = new URLSearchParams();
110
+ for (const [name, value] of Object.entries(params)) {
111
+ search.set(name, String(value));
112
+ }
113
+ return { path: `${queryPath}?${search.toString()}`, method };
114
+ }
74
115
  export class Collection {
75
116
  spaceId;
76
117
  id;
@@ -1208,12 +1249,21 @@ export class Collection {
1208
1249
  }
1209
1250
  /**
1210
1251
  * Adds a resource with a server-generated id. JSON for plain objects/arrays,
1211
- * binary for `Blob`/`Uint8Array`. Throws `NotFoundError` if the collection
1212
- * does not exist (WAS does not auto-create parents).
1252
+ * binary for `Blob`/`Uint8Array` or `ReadableStream<Uint8Array>`. Throws
1253
+ * `NotFoundError` if the collection does not exist (WAS does not
1254
+ * auto-create parents).
1213
1255
  *
1214
1256
  * On an encrypted collection a binary payload above the codec's
1215
1257
  * single-document threshold is auto-routed to the chunked-stream path, which
1216
- * a server that does not serve the chunk endpoints answers with `501`.
1258
+ * a server that does not serve the chunk endpoints answers with `501`. A
1259
+ * `ReadableStream<Uint8Array>` is always written through that path, without
1260
+ * buffering, since its size is unknown. A content-addressed collection
1261
+ * (`idDerivation: 'content'`) cannot store a chunked payload, so it refuses
1262
+ * a stream with `ValidationError` before reading it.
1263
+ *
1264
+ * On a plaintext collection a stream is refused with `ValidationError`: a
1265
+ * plaintext resource has no chunked representation, and a signed request
1266
+ * carries a `Digest` of its whole body. Buffer it into a `Blob` there.
1217
1267
  *
1218
1268
  * @param data {ResourceData}
1219
1269
  * @param options {object}
@@ -1292,11 +1342,25 @@ export class Collection {
1292
1342
  // guard in the `Resource` constructor applies to reads and writes alike.
1293
1343
  return this.resource(resourceId).get();
1294
1344
  }
1345
+ /**
1346
+ * Reads a resource by id as a byte stream, decrypting on an encrypted
1347
+ * collection -- the read for a caller that cannot buffer a large chunked
1348
+ * blob. Delegates to `Resource.getStream`; see it for the details. The
1349
+ * ordinary {@link get} still returns a `Blob`. Returns `null` on a
1350
+ * missing/unauthorized resource (404 conflation caveat).
1351
+ *
1352
+ * @param resourceId {string}
1353
+ * @returns {Promise<(DecodedStream & { etag?: string }) | null>}
1354
+ */
1355
+ async getStream(resourceId) {
1356
+ return this.resource(resourceId).getStream();
1357
+ }
1295
1358
  /**
1296
1359
  * Creates or replaces a resource by id (upsert). Forwards the
1297
1360
  * conditional-write options (`ifMatch` / `ifNoneMatch`) to `Resource.put`;
1298
- * see it for the conditional-write semantics. Returns the stored
1299
- * resource's new `etag`.
1361
+ * see it for the conditional-write semantics and for which payloads
1362
+ * (including a `ReadableStream<Uint8Array>`) each kind of collection
1363
+ * accepts. Returns the stored resource's new `etag`.
1300
1364
  *
1301
1365
  * @param resourceId {string}
1302
1366
  * @param data {ResourceData}
@@ -1407,28 +1471,37 @@ export class Collection {
1407
1471
  * parse that resource's body). Entries of any other kind pass through
1408
1472
  * unchecked.
1409
1473
  *
1474
+ * The query is sent as a `POST` whose body carries the parameters, or in
1475
+ * the read-only `GET` form with the parameters in the query string, which
1476
+ * the server verifies under the `GET` action and answers with the same page.
1477
+ * A capability whose `allowedAction` excludes `POST` (a GET-only pull
1478
+ * capability, say) reads the feed with `GET`, since the `POST` form refuses
1479
+ * it with `NotFoundError`; every other handle sends `POST`. `method`
1480
+ * overrides the derived form.
1481
+ *
1410
1482
  * @param [options] {object}
1411
1483
  * @param [options.checkpoint] {ChangesCheckpoint} opaque checkpoint from a prior page; resume strictly after it
1412
1484
  * @param [options.limit] {number} max documents; the server reduces it to its own maximum
1485
+ * @param [options.method] {'POST' | 'GET'} the request form; derived from
1486
+ * the bound capability by default
1413
1487
  * @returns {Promise<ChangesPage>}
1414
1488
  */
1415
1489
  async changes(options = {}) {
1416
- const { checkpoint, limit } = options;
1490
+ const { checkpoint, limit, method = changesMethodFor(this.#capability) } = options;
1417
1491
  const response = await send(this.#context, {
1418
- path: collectionQuery(this.spaceId, this.id),
1419
- method: 'POST',
1420
- capability: this.#capability,
1421
- json: {
1422
- profile: 'changes',
1423
- ...(checkpoint !== undefined && { checkpoint }),
1424
- ...(limit !== undefined && { limit })
1425
- }
1492
+ ...changesRequest({
1493
+ queryPath: collectionQuery(this.spaceId, this.id),
1494
+ method,
1495
+ checkpoint,
1496
+ limit
1497
+ }),
1498
+ capability: this.#capability
1426
1499
  });
1427
- // A `changes` query is a POST, so it never carries the null-on-404 `read`
1428
- // flag: a missing or unauthorized collection throws, as every other write
1429
- // -shaped call on this handle does. A `null` here is therefore a 2xx whose
1430
- // body did not parse as JSON, which must not masquerade as the end-of-feed
1431
- // page `{ documents: [], checkpoint: null }`.
1500
+ // Neither form carries the null-on-404 `read` flag: a missing or
1501
+ // unauthorized collection throws, as every other write-shaped call on this
1502
+ // handle does. A `null` here is therefore a 2xx whose body did not parse
1503
+ // as JSON, which must not masquerade as the end-of-feed page
1504
+ // `{ documents: [], checkpoint: null }`.
1432
1505
  const page = dataOrNull(response);
1433
1506
  if (page === null) {
1434
1507
  throw new WasServerError(`The changes feed of collection "${this.id}" answered with no JSON ` +
@@ -1487,14 +1560,16 @@ export class Collection {
1487
1560
  * @param [options] {object}
1488
1561
  * @param [options.checkpoint] {ChangesCheckpoint} resume strictly after it
1489
1562
  * @param [options.limit] {number} max entries per request, every kind counted
1563
+ * @param [options.method] {'POST' | 'GET'} the request form of each page,
1564
+ * as for {@link changes}
1490
1565
  * @returns {AsyncGenerator<{ documents: ResourceChangeDocument[], checkpoint: ChangesCheckpoint | null }>}
1491
1566
  */
1492
1567
  async *resourceChanges(options = {}) {
1493
- const { limit } = options;
1568
+ const { limit, method } = options;
1494
1569
  let checkpoint = options.checkpoint;
1495
1570
  const seen = new Set(checkpoint === undefined ? [] : [checkpoint]);
1496
1571
  for (;;) {
1497
- const page = await this.changes({ checkpoint, limit });
1572
+ const page = await this.changes({ checkpoint, limit, method });
1498
1573
  yield {
1499
1574
  documents: page.documents.filter(isResourceChange),
1500
1575
  checkpoint: page.checkpoint ?? null