@interop/was-client 0.27.0 → 0.27.2
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/dist/Collection.d.ts.map +1 -1
- package/dist/Collection.js +27 -66
- package/dist/Collection.js.map +1 -1
- package/dist/Resource.d.ts.map +1 -1
- package/dist/Resource.js +28 -6
- package/dist/Resource.js.map +1 -1
- package/dist/Space.d.ts.map +1 -1
- package/dist/Space.js +10 -25
- package/dist/Space.js.map +1 -1
- package/dist/WasClient.d.ts.map +1 -1
- package/dist/WasClient.js +9 -19
- package/dist/WasClient.js.map +1 -1
- package/dist/codec.d.ts +31 -5
- package/dist/codec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.d.ts +9 -14
- package/dist/edv/EdvCodec.d.ts.map +1 -1
- package/dist/edv/EdvCodec.js +147 -71
- package/dist/edv/EdvCodec.js.map +1 -1
- package/dist/edv/WasTransport.d.ts +1 -2
- package/dist/edv/WasTransport.d.ts.map +1 -1
- package/dist/edv/WasTransport.js +19 -28
- package/dist/edv/WasTransport.js.map +1 -1
- package/dist/edv/constants.d.ts +11 -0
- package/dist/edv/constants.d.ts.map +1 -1
- package/dist/edv/constants.js +16 -4
- package/dist/edv/constants.js.map +1 -1
- package/dist/edv/docCipher.d.ts +10 -26
- package/dist/edv/docCipher.d.ts.map +1 -1
- package/dist/edv/docCipher.js +62 -135
- package/dist/edv/docCipher.js.map +1 -1
- package/dist/edv/epochCrypto.d.ts +0 -4
- package/dist/edv/epochCrypto.d.ts.map +1 -1
- package/dist/edv/epochCrypto.js +4 -4
- package/dist/edv/epochCrypto.js.map +1 -1
- package/dist/edv/epochKeys.d.ts.map +1 -1
- package/dist/edv/epochKeys.js +2 -4
- package/dist/edv/epochKeys.js.map +1 -1
- package/dist/edv/epochMac.d.ts.map +1 -1
- package/dist/edv/epochMac.js +4 -4
- package/dist/edv/epochMac.js.map +1 -1
- package/dist/edv/index.d.ts +3 -2
- package/dist/edv/index.d.ts.map +1 -1
- package/dist/edv/index.js +2 -1
- package/dist/edv/index.js.map +1 -1
- package/dist/edv/recipients.d.ts +13 -14
- package/dist/edv/recipients.d.ts.map +1 -1
- package/dist/edv/recipients.js +126 -99
- package/dist/edv/recipients.js.map +1 -1
- package/dist/errors.d.ts +29 -12
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +37 -65
- package/dist/errors.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/codec.d.ts +15 -12
- package/dist/internal/codec.d.ts.map +1 -1
- package/dist/internal/codec.js +4 -6
- package/dist/internal/codec.js.map +1 -1
- package/dist/internal/conditional.d.ts +9 -4
- package/dist/internal/conditional.d.ts.map +1 -1
- package/dist/internal/conditional.js +9 -2
- package/dist/internal/conditional.js.map +1 -1
- package/dist/internal/content.d.ts +28 -24
- package/dist/internal/content.d.ts.map +1 -1
- package/dist/internal/content.js +28 -13
- package/dist/internal/content.js.map +1 -1
- package/dist/internal/describe.d.ts +15 -2
- package/dist/internal/describe.d.ts.map +1 -1
- package/dist/internal/describe.js +17 -0
- package/dist/internal/describe.js.map +1 -1
- package/dist/internal/pagination.d.ts +20 -1
- package/dist/internal/pagination.d.ts.map +1 -1
- package/dist/internal/pagination.js +22 -0
- package/dist/internal/pagination.js.map +1 -1
- package/dist/internal/paths.d.ts +0 -11
- package/dist/internal/paths.d.ts.map +1 -1
- package/dist/internal/paths.js +20 -33
- package/dist/internal/paths.js.map +1 -1
- package/dist/internal/policy.d.ts.map +1 -1
- package/dist/internal/policy.js +2 -9
- package/dist/internal/policy.js.map +1 -1
- package/dist/internal/write.d.ts +50 -4
- package/dist/internal/write.d.ts.map +1 -1
- package/dist/internal/write.js +45 -0
- package/dist/internal/write.js.map +1 -1
- package/dist/sync/cid.d.ts.map +1 -1
- package/dist/sync/cid.js +8 -2
- package/dist/sync/cid.js.map +1 -1
- package/dist/sync/port.d.ts +9 -8
- package/dist/sync/port.d.ts.map +1 -1
- package/dist/sync/port.js +74 -70
- package/dist/sync/port.js.map +1 -1
- package/dist/sync/provisioning.d.ts +4 -1
- package/dist/sync/provisioning.d.ts.map +1 -1
- package/dist/sync/provisioning.js +11 -2
- package/dist/sync/provisioning.js.map +1 -1
- package/dist/sync/types.d.ts +7 -10
- package/dist/sync/types.d.ts.map +1 -1
- package/package.json +13 -13
package/dist/internal/write.d.ts
CHANGED
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* The shared write orchestration. `sendEncodedWrite` turns a codec's
|
|
6
6
|
* {@link EncodedWrite} plus a conditional-write precondition into request
|
|
7
7
|
* headers and sends it (the shape `Collection.add` and `Resource.put` would
|
|
8
|
-
* otherwise each re-implement).
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* otherwise each re-implement). Two flows layer on top: `insertResource` (the
|
|
9
|
+
* create path behind `Collection.add` -- encode, the minted-id `PUT` vs
|
|
10
|
+
* server-minting `POST` branch, and the precondition selection) and
|
|
11
|
+
* `upsertResource` (the write-by-id path behind `Resource.put` -- the
|
|
12
|
+
* conditional-codec pre-read of the current document, the codec-vs-caller
|
|
13
|
+
* precondition selection, and the masked-404 policy for a document that exists
|
|
14
|
+
* but is not readable with the bound capability).
|
|
12
15
|
*/
|
|
13
16
|
import type { HttpResponse } from '@interop/http-client';
|
|
14
17
|
import type { EncodedWrite, ResourceCodec } from '../codec.js';
|
|
@@ -37,6 +40,49 @@ export declare function sendEncodedWrite(context: ClientContext, { path, method,
|
|
|
37
40
|
capability?: IZcap;
|
|
38
41
|
precondition?: WritePrecondition;
|
|
39
42
|
}): Promise<HttpResponse>;
|
|
43
|
+
/**
|
|
44
|
+
* Creates a resource with a codec-minted or server-minted id (insert) through
|
|
45
|
+
* its codec, owning the create orchestration in one place: the encode, the
|
|
46
|
+
* `PUT`-vs-`POST` branch, and the precondition selection.
|
|
47
|
+
*
|
|
48
|
+
* A codec that mints its own id (e.g. the encrypting codec's EDV id) writes it
|
|
49
|
+
* by `PUT` to that id's path; a codec that mints none (the identity codec)
|
|
50
|
+
* `POST`s to the items path and lets the server mint one. As in
|
|
51
|
+
* {@link upsertResource}, a conditional codec computes the precondition itself
|
|
52
|
+
* (the EDV codec guards its fresh insert with `If-None-Match: *`) and a
|
|
53
|
+
* non-conditional one defers to the caller's explicit precondition.
|
|
54
|
+
*
|
|
55
|
+
* Returns the codec's encoded write and the path actually written alongside the
|
|
56
|
+
* response, so the caller can shape its result (the created id and URL) without
|
|
57
|
+
* re-deriving either.
|
|
58
|
+
*
|
|
59
|
+
* @param context {ClientContext}
|
|
60
|
+
* @param options {object}
|
|
61
|
+
* @param options.itemsPath {string} the collection's items path, the
|
|
62
|
+
* `POST` target when the codec mints no id
|
|
63
|
+
* @param options.pathForId {function} builds the resource path for a
|
|
64
|
+
* codec-minted id
|
|
65
|
+
* @param options.codec {ResourceCodec} the collection's resolved codec
|
|
66
|
+
* @param options.data {ResourceData} the plaintext value
|
|
67
|
+
* @param [options.contentType] {string} caller-supplied content type
|
|
68
|
+
* @param [options.capability] {IZcap}
|
|
69
|
+
* @param [options.precondition] {WritePrecondition} the caller's explicit
|
|
70
|
+
* precondition (used only for a non-conditional codec)
|
|
71
|
+
* @returns {Promise<{ encoded: EncodedWrite; path: string; response: HttpResponse }>}
|
|
72
|
+
*/
|
|
73
|
+
export declare function insertResource(context: ClientContext, { itemsPath, pathForId, codec, data, contentType, capability, precondition }: {
|
|
74
|
+
itemsPath: string;
|
|
75
|
+
pathForId: (id: string) => string;
|
|
76
|
+
codec: ResourceCodec;
|
|
77
|
+
data: ResourceData;
|
|
78
|
+
contentType?: string;
|
|
79
|
+
capability?: IZcap;
|
|
80
|
+
precondition?: WritePrecondition;
|
|
81
|
+
}): Promise<{
|
|
82
|
+
encoded: EncodedWrite;
|
|
83
|
+
path: string;
|
|
84
|
+
response: HttpResponse;
|
|
85
|
+
}>;
|
|
40
86
|
/**
|
|
41
87
|
* Creates or replaces a resource by id (upsert) through its codec, owning the
|
|
42
88
|
* conditional-write orchestration in one place:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH
|
|
1
|
+
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE9D,OAAO,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AACtD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAGjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,aAAa,EACtB,EACE,IAAI,EACJ,MAAM,EACN,OAAO,EACP,UAAU,EACV,YAAY,EACb,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GACA,OAAO,CAAC,YAAY,CAAC,CAcvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,EACE,SAAS,EACT,SAAS,EACT,KAAK,EACL,IAAI,EACJ,WAAW,EACX,UAAU,EACV,YAAY,EACb,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,MAAM,CAAA;IACjC,KAAK,EAAE,aAAa,CAAA;IACpB,IAAI,EAAE,YAAY,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GACA,OAAO,CAAC;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAAC,CAc1E;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAsB,cAAc,CAClC,OAAO,EAAE,aAAa,EACtB,EACE,IAAI,EACJ,KAAK,EACL,EAAE,EACF,IAAI,EACJ,QAAQ,EACR,WAAW,EACX,UAAU,EACV,YAAY,EACb,EAAE;IACD,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,aAAa,CAAA;IACpB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,YAAY,CAAA;IAClB,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACjC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,YAAY,CAAC,EAAE,iBAAiB,CAAA;CACjC,GACA,OAAO,CAAC,YAAY,CAAC,CAgEvB"}
|
package/dist/internal/write.js
CHANGED
|
@@ -31,6 +31,51 @@ export async function sendEncodedWrite(context, { path, method, encoded, capabil
|
|
|
31
31
|
});
|
|
32
32
|
return response;
|
|
33
33
|
}
|
|
34
|
+
/**
|
|
35
|
+
* Creates a resource with a codec-minted or server-minted id (insert) through
|
|
36
|
+
* its codec, owning the create orchestration in one place: the encode, the
|
|
37
|
+
* `PUT`-vs-`POST` branch, and the precondition selection.
|
|
38
|
+
*
|
|
39
|
+
* A codec that mints its own id (e.g. the encrypting codec's EDV id) writes it
|
|
40
|
+
* by `PUT` to that id's path; a codec that mints none (the identity codec)
|
|
41
|
+
* `POST`s to the items path and lets the server mint one. As in
|
|
42
|
+
* {@link upsertResource}, a conditional codec computes the precondition itself
|
|
43
|
+
* (the EDV codec guards its fresh insert with `If-None-Match: *`) and a
|
|
44
|
+
* non-conditional one defers to the caller's explicit precondition.
|
|
45
|
+
*
|
|
46
|
+
* Returns the codec's encoded write and the path actually written alongside the
|
|
47
|
+
* response, so the caller can shape its result (the created id and URL) without
|
|
48
|
+
* re-deriving either.
|
|
49
|
+
*
|
|
50
|
+
* @param context {ClientContext}
|
|
51
|
+
* @param options {object}
|
|
52
|
+
* @param options.itemsPath {string} the collection's items path, the
|
|
53
|
+
* `POST` target when the codec mints no id
|
|
54
|
+
* @param options.pathForId {function} builds the resource path for a
|
|
55
|
+
* codec-minted id
|
|
56
|
+
* @param options.codec {ResourceCodec} the collection's resolved codec
|
|
57
|
+
* @param options.data {ResourceData} the plaintext value
|
|
58
|
+
* @param [options.contentType] {string} caller-supplied content type
|
|
59
|
+
* @param [options.capability] {IZcap}
|
|
60
|
+
* @param [options.precondition] {WritePrecondition} the caller's explicit
|
|
61
|
+
* precondition (used only for a non-conditional codec)
|
|
62
|
+
* @returns {Promise<{ encoded: EncodedWrite; path: string; response: HttpResponse }>}
|
|
63
|
+
*/
|
|
64
|
+
export async function insertResource(context, { itemsPath, pathForId, codec, data, contentType, capability, precondition }) {
|
|
65
|
+
const encoded = await codec.encode({ data, contentType });
|
|
66
|
+
const chosen = codec.conditionalWrites
|
|
67
|
+
? encodedPrecondition(encoded)
|
|
68
|
+
: precondition;
|
|
69
|
+
const path = encoded.id !== undefined ? pathForId(encoded.id) : itemsPath;
|
|
70
|
+
const response = await sendEncodedWrite(context, {
|
|
71
|
+
path,
|
|
72
|
+
method: encoded.id !== undefined ? 'PUT' : 'POST',
|
|
73
|
+
capability,
|
|
74
|
+
encoded,
|
|
75
|
+
precondition: chosen
|
|
76
|
+
});
|
|
77
|
+
return { encoded, path, response };
|
|
78
|
+
}
|
|
34
79
|
/**
|
|
35
80
|
* Creates or replaces a resource by id (upsert) through its codec, owning the
|
|
36
81
|
* conditional-write orchestration in one place:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/internal/write.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/cid.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../../src/sync/cid.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"cid.d.ts","sourceRoot":"","sources":["../../src/sync/cid.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AASvC;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,GAAG,EAAE,IAAI,GAAG,MAAM,CAE5C;AAED;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,EAAE,GAAG,EAAE,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAExD;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,aAAa,EAAE,MAAM,GAAG,MAAM,CAE3D"}
|
package/dist/sync/cid.js
CHANGED
|
@@ -19,6 +19,12 @@
|
|
|
19
19
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
20
20
|
import { base64urlnopad } from '@scure/base';
|
|
21
21
|
import { canonicalize } from 'json-canonicalize';
|
|
22
|
+
/**
|
|
23
|
+
* The one UTF-8 encoder every derivation here shares: hashing runs on the
|
|
24
|
+
* per-document hot path, so the encoder is allocated once for the module rather
|
|
25
|
+
* than per call. `TextEncoder` is stateless, so reuse is safe.
|
|
26
|
+
*/
|
|
27
|
+
const ENCODER = new TextEncoder();
|
|
22
28
|
/**
|
|
23
29
|
* Derives a document's content id: `base64url(SHA-256(utf8(canonicalize(doc))))`,
|
|
24
30
|
* no padding. Byte-identical across replicas for the same logical document, so a
|
|
@@ -28,7 +34,7 @@ import { canonicalize } from 'json-canonicalize';
|
|
|
28
34
|
* @returns {string} the unpadded base64url content id (43 chars for SHA-256)
|
|
29
35
|
*/
|
|
30
36
|
export function contentCid(doc) {
|
|
31
|
-
return base64urlnopad.encode(sha256(
|
|
37
|
+
return base64urlnopad.encode(sha256(ENCODER.encode(canonicalize(doc))));
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
40
|
* Named-options alias of {@link contentCid}, for callers that address a `doc`
|
|
@@ -50,6 +56,6 @@ export function cidFrom({ doc }) {
|
|
|
50
56
|
* @returns {string} the unpadded base64url Space id
|
|
51
57
|
*/
|
|
52
58
|
export function deriveSpaceId(controllerDid) {
|
|
53
|
-
return base64urlnopad.encode(sha256(
|
|
59
|
+
return base64urlnopad.encode(sha256(ENCODER.encode(controllerDid)));
|
|
54
60
|
}
|
|
55
61
|
//# sourceMappingURL=cid.js.map
|
package/dist/sync/cid.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cid.js","sourceRoot":"","sources":["../../src/sync/cid.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,GAAS;IAClC,OAAO,cAAc,CAAC,MAAM,
|
|
1
|
+
{"version":3,"file":"cid.js","sourceRoot":"","sources":["../../src/sync/cid.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAC9C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAGhD;;;;GAIG;AACH,MAAM,OAAO,GAAG,IAAI,WAAW,EAAE,CAAA;AAEjC;;;;;;;GAOG;AACH,MAAM,UAAU,UAAU,CAAC,GAAS;IAClC,OAAO,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAA;AACzE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,EAAE,GAAG,EAAmB;IAC9C,OAAO,UAAU,CAAC,GAAW,CAAC,CAAA;AAChC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAAC,aAAqB;IACjD,OAAO,cAAc,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAA;AACrE,CAAC"}
|
package/dist/sync/port.d.ts
CHANGED
|
@@ -26,22 +26,23 @@
|
|
|
26
26
|
* sent none), so a caller can record acked revisions immediately.
|
|
27
27
|
*/
|
|
28
28
|
import type { WasClient } from '../WasClient.js';
|
|
29
|
+
import { WAS_KEY_EPOCH_HEADER } from '../internal/conditional.js';
|
|
30
|
+
import { httpStatus } from '../errors.js';
|
|
29
31
|
import type { WasSyncPort } from './types.js';
|
|
30
32
|
/**
|
|
31
33
|
* The request header the server reads a content write's key-epoch id from,
|
|
32
|
-
* stamping it onto the Resource's metadata
|
|
33
|
-
*
|
|
34
|
+
* stamping it onto the Resource's metadata. Defined next to the header
|
|
35
|
+
* assembly it drives (`internal/conditional.ts`) and re-exported here as part
|
|
36
|
+
* of the sync subpath's public surface.
|
|
34
37
|
*/
|
|
35
|
-
export
|
|
38
|
+
export { WAS_KEY_EPOCH_HEADER };
|
|
36
39
|
/**
|
|
37
40
|
* Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
|
|
38
41
|
* any non-2xx with `err.status` set; this reads it defensively from either the
|
|
39
|
-
* flat `status` or the nested `response.status` shape.
|
|
40
|
-
*
|
|
41
|
-
* @param err {unknown} the caught error
|
|
42
|
-
* @returns {number | undefined}
|
|
42
|
+
* flat `status` or the nested `response.status` shape. The sync subpath's name
|
|
43
|
+
* for the client's own {@link httpStatus}.
|
|
43
44
|
*/
|
|
44
|
-
export declare
|
|
45
|
+
export declare const errorStatus: typeof httpStatus;
|
|
45
46
|
/**
|
|
46
47
|
* Formats a numeric content `version` as the quoted strong `ETag` an
|
|
47
48
|
* update-if-unchanged write passes as its `ifMatch` precondition (e.g. `3` to
|
package/dist/sync/port.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"port.d.ts","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAEhD,OAAO,EACL,oBAAoB,EAGrB,MAAM,4BAA4B,CAAA;AAEnC,OAAO,EACL,UAAU,EAGX,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EAAqB,WAAW,EAAE,MAAM,YAAY,CAAA;AAEhE;;;;;GAKG;AACH,OAAO,EAAE,oBAAoB,EAAE,CAAA;AAW/B;;;;;GAKG;AACH,eAAO,MAAM,WAAW,mBAAa,CAAA;AA4BrC;;;;;;;GAOG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAMjE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,OAAO,EACP,YAAY,EACb,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;CACrB,GAAG,WAAW,CAgJd"}
|
package/dist/sync/port.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import { writeHeaders } from '../internal/conditional.js';
|
|
2
|
-
import {
|
|
1
|
+
import { WAS_KEY_EPOCH_HEADER, readEtag, writeHeaders } from '../internal/conditional.js';
|
|
2
|
+
import { resourceMeta, resourcePath } from '../internal/paths.js';
|
|
3
|
+
import { httpStatus, WasSyncConflictError, WasSyncNotFoundError } from '../errors.js';
|
|
3
4
|
/**
|
|
4
5
|
* The request header the server reads a content write's key-epoch id from,
|
|
5
|
-
* stamping it onto the Resource's metadata
|
|
6
|
-
*
|
|
6
|
+
* stamping it onto the Resource's metadata. Defined next to the header
|
|
7
|
+
* assembly it drives (`internal/conditional.ts`) and re-exported here as part
|
|
8
|
+
* of the sync subpath's public surface.
|
|
7
9
|
*/
|
|
8
|
-
export
|
|
10
|
+
export { WAS_KEY_EPOCH_HEADER };
|
|
9
11
|
/**
|
|
10
12
|
* The placeholder `updatedAt` for a 412-conflict re-read whose resource has no
|
|
11
13
|
* `/meta` document yet (its server-managed timestamp is unknown). An epoch-zero
|
|
@@ -17,14 +19,31 @@ const UNKNOWN_UPDATED_AT = new Date(0).toISOString();
|
|
|
17
19
|
/**
|
|
18
20
|
* Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
|
|
19
21
|
* any non-2xx with `err.status` set; this reads it defensively from either the
|
|
20
|
-
* flat `status` or the nested `response.status` shape.
|
|
22
|
+
* flat `status` or the nested `response.status` shape. The sync subpath's name
|
|
23
|
+
* for the client's own {@link httpStatus}.
|
|
24
|
+
*/
|
|
25
|
+
export const errorStatus = httpStatus;
|
|
26
|
+
/**
|
|
27
|
+
* Maps a raw write error onto the port's typed signals, rethrowing anything
|
|
28
|
+
* else unchanged: `412` becomes a {@link WasSyncConflictError} for every write.
|
|
29
|
+
* `notFound` opts in to the `404` mapping, which only `deleteContent` performs
|
|
30
|
+
* (an already-gone target is a settled outcome for a delete, but a hard error
|
|
31
|
+
* for a content or metadata write).
|
|
21
32
|
*
|
|
22
33
|
* @param err {unknown} the caught error
|
|
23
|
-
* @
|
|
34
|
+
* @param [options] {object}
|
|
35
|
+
* @param [options.notFound] {boolean} map `404` to {@link WasSyncNotFoundError}
|
|
36
|
+
* @returns {never} always throws
|
|
24
37
|
*/
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
38
|
+
function mapWriteError(err, { notFound = false } = {}) {
|
|
39
|
+
const status = errorStatus(err);
|
|
40
|
+
if (notFound && status === 404) {
|
|
41
|
+
throw new WasSyncNotFoundError();
|
|
42
|
+
}
|
|
43
|
+
if (status === 412) {
|
|
44
|
+
throw new WasSyncConflictError();
|
|
45
|
+
}
|
|
46
|
+
throw err;
|
|
28
47
|
}
|
|
29
48
|
/**
|
|
30
49
|
* Formats a numeric content `version` as the quoted strong `ETag` an
|
|
@@ -63,8 +82,10 @@ export function parseEtag(etag) {
|
|
|
63
82
|
* @returns {WasSyncPort}
|
|
64
83
|
*/
|
|
65
84
|
export function createWasSyncPort({ was, spaceId, collectionId }) {
|
|
66
|
-
|
|
67
|
-
|
|
85
|
+
// Paths come from the internal builders, so this port inherits the same
|
|
86
|
+
// percent-encoding and reserved/dot-segment guards as the handle API.
|
|
87
|
+
const contentPath = (id) => resourcePath(spaceId, collectionId, id);
|
|
88
|
+
const metaPath = (id) => resourceMeta(spaceId, collectionId, id);
|
|
68
89
|
// Construction is I/O-free (the codec/feature probes are lazy thunks) and
|
|
69
90
|
// `changes()` never resolves the codec, so it ships the stored bodies
|
|
70
91
|
// verbatim -- what this codec-bypassing port requires.
|
|
@@ -73,7 +94,7 @@ export function createWasSyncPort({ was, spaceId, collectionId }) {
|
|
|
73
94
|
const readContent = async (id) => {
|
|
74
95
|
let response;
|
|
75
96
|
try {
|
|
76
|
-
response = await was.request({ path:
|
|
97
|
+
response = await was.request({ path: contentPath(id), method: 'GET' });
|
|
77
98
|
}
|
|
78
99
|
catch (err) {
|
|
79
100
|
if (errorStatus(err) === 404) {
|
|
@@ -82,15 +103,14 @@ export function createWasSyncPort({ was, spaceId, collectionId }) {
|
|
|
82
103
|
throw err;
|
|
83
104
|
}
|
|
84
105
|
return {
|
|
85
|
-
version: parseEtag(response
|
|
106
|
+
version: parseEtag(readEtag(response) ?? null) ?? 0,
|
|
86
107
|
updatedAt: UNKNOWN_UPDATED_AT,
|
|
87
|
-
deleted: false,
|
|
88
108
|
data: response.data
|
|
89
109
|
};
|
|
90
110
|
};
|
|
91
111
|
/** Resolves the acked version from a write response, or via a content re-read. */
|
|
92
112
|
const ackedVersion = async (response, id) => {
|
|
93
|
-
const version = parseEtag(response
|
|
113
|
+
const version = parseEtag(readEtag(response) ?? null);
|
|
94
114
|
if (version !== undefined) {
|
|
95
115
|
return version;
|
|
96
116
|
}
|
|
@@ -98,16 +118,12 @@ export function createWasSyncPort({ was, spaceId, collectionId }) {
|
|
|
98
118
|
};
|
|
99
119
|
return {
|
|
100
120
|
async query({ checkpoint, limit }) {
|
|
101
|
-
|
|
102
|
-
return {
|
|
103
|
-
documents: page.documents,
|
|
104
|
-
checkpoint: page.checkpoint
|
|
105
|
-
};
|
|
121
|
+
return changesCollection.changes({ checkpoint, limit });
|
|
106
122
|
},
|
|
107
123
|
async putContent({ id, data, ifMatch, ifNoneMatch, epoch }) {
|
|
108
124
|
try {
|
|
109
125
|
const response = await was.request({
|
|
110
|
-
path:
|
|
126
|
+
path: contentPath(id),
|
|
111
127
|
method: 'PUT',
|
|
112
128
|
json: data,
|
|
113
129
|
headers: writeHeaders({
|
|
@@ -118,84 +134,72 @@ export function createWasSyncPort({ was, spaceId, collectionId }) {
|
|
|
118
134
|
return await ackedVersion(response, id);
|
|
119
135
|
}
|
|
120
136
|
catch (err) {
|
|
121
|
-
|
|
122
|
-
throw new WasSyncConflictError();
|
|
123
|
-
}
|
|
124
|
-
throw err;
|
|
137
|
+
mapWriteError(err);
|
|
125
138
|
}
|
|
126
139
|
},
|
|
127
140
|
async deleteContent({ id, ifMatch }) {
|
|
128
141
|
try {
|
|
129
142
|
const response = await was.request({
|
|
130
|
-
path:
|
|
143
|
+
path: contentPath(id),
|
|
131
144
|
method: 'DELETE',
|
|
132
145
|
headers: writeHeaders({ precondition: { ifMatch } })
|
|
133
146
|
});
|
|
134
147
|
return await ackedVersion(response, id);
|
|
135
148
|
}
|
|
136
149
|
catch (err) {
|
|
137
|
-
|
|
138
|
-
if (status === 404) {
|
|
139
|
-
throw new WasSyncNotFoundError();
|
|
140
|
-
}
|
|
141
|
-
if (status === 412) {
|
|
142
|
-
throw new WasSyncConflictError();
|
|
143
|
-
}
|
|
144
|
-
throw err;
|
|
150
|
+
mapWriteError(err, { notFound: true });
|
|
145
151
|
}
|
|
146
152
|
},
|
|
147
153
|
async putMeta({ id, custom, ifMatch, ifNoneMatch }) {
|
|
148
154
|
try {
|
|
149
155
|
await was.request({
|
|
150
|
-
path:
|
|
156
|
+
path: metaPath(id),
|
|
151
157
|
method: 'PUT',
|
|
152
158
|
json: { custom },
|
|
153
159
|
headers: writeHeaders({ precondition: { ifMatch, ifNoneMatch } })
|
|
154
160
|
});
|
|
155
161
|
}
|
|
156
162
|
catch (err) {
|
|
157
|
-
|
|
158
|
-
throw new WasSyncConflictError();
|
|
159
|
-
}
|
|
160
|
-
throw err;
|
|
163
|
+
mapWriteError(err);
|
|
161
164
|
}
|
|
162
165
|
},
|
|
163
166
|
async get({ id }) {
|
|
167
|
+
// The content and metadata reads hit independent endpoints, so both fly
|
|
168
|
+
// together. The metadata read settles into a value (its rejection handler
|
|
169
|
+
// is attached before any `await` that can throw, so an abandoned read can
|
|
170
|
+
// never surface as an unhandled rejection).
|
|
171
|
+
const metaRead = was.request({ path: metaPath(id), method: 'GET' }).then(response => ({ ok: true, response }), (err) => ({ ok: false, err }));
|
|
164
172
|
const master = await readContent(id);
|
|
165
173
|
if (master === null) {
|
|
166
|
-
return null;
|
|
174
|
+
return null; // absent or tombstoned; the metadata read is discarded
|
|
167
175
|
}
|
|
168
|
-
// Metadata
|
|
169
|
-
//
|
|
170
|
-
//
|
|
171
|
-
//
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
});
|
|
177
|
-
const metaBody = metaResponse.data;
|
|
178
|
-
if (metaBody?.updatedAt) {
|
|
179
|
-
master.updatedAt = metaBody.updatedAt;
|
|
180
|
-
}
|
|
181
|
-
if (metaBody?.createdBy !== undefined) {
|
|
182
|
-
master.createdBy = metaBody.createdBy;
|
|
183
|
-
}
|
|
184
|
-
if (metaBody?.epoch !== undefined) {
|
|
185
|
-
master.epoch = metaBody.epoch;
|
|
186
|
-
}
|
|
187
|
-
if (metaBody?.custom !== undefined) {
|
|
188
|
-
master.custom = metaBody.custom;
|
|
189
|
-
}
|
|
190
|
-
const metaVersion = parseEtag(metaResponse.headers.get('etag'));
|
|
191
|
-
if (metaVersion !== undefined) {
|
|
192
|
-
master.metaVersion = metaVersion;
|
|
176
|
+
// Metadata (best-effort): the `/meta` body carries the server-managed
|
|
177
|
+
// `updatedAt`, the creator DID, the key-epoch id, and the user-writable
|
|
178
|
+
// `custom`, plus its own `metaVersion` ETag. A resource with no metadata
|
|
179
|
+
// yet 404s here; only a hard error propagates.
|
|
180
|
+
const meta = await metaRead;
|
|
181
|
+
if (!meta.ok) {
|
|
182
|
+
if (errorStatus(meta.err) !== 404) {
|
|
183
|
+
throw meta.err;
|
|
193
184
|
}
|
|
185
|
+
return master;
|
|
194
186
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
187
|
+
const metaBody = meta.response.data;
|
|
188
|
+
if (metaBody?.updatedAt) {
|
|
189
|
+
master.updatedAt = metaBody.updatedAt;
|
|
190
|
+
}
|
|
191
|
+
if (metaBody?.createdBy !== undefined) {
|
|
192
|
+
master.createdBy = metaBody.createdBy;
|
|
193
|
+
}
|
|
194
|
+
if (metaBody?.epoch !== undefined) {
|
|
195
|
+
master.epoch = metaBody.epoch;
|
|
196
|
+
}
|
|
197
|
+
if (metaBody?.custom !== undefined) {
|
|
198
|
+
master.custom = metaBody.custom;
|
|
199
|
+
}
|
|
200
|
+
const metaVersion = parseEtag(readEtag(meta.response) ?? null);
|
|
201
|
+
if (metaVersion !== undefined) {
|
|
202
|
+
master.metaVersion = metaVersion;
|
|
199
203
|
}
|
|
200
204
|
return master;
|
|
201
205
|
}
|
package/dist/sync/port.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"AA6BA,OAAO,
|
|
1
|
+
{"version":3,"file":"port.js","sourceRoot":"","sources":["../../src/sync/port.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,10 @@ import type { WasClient } from '../WasClient.js';
|
|
|
10
10
|
/**
|
|
11
11
|
* Ensures the controller's Space exists and one synced collection is
|
|
12
12
|
* configured. An `'edv'` collection declares the encryption descriptor `{
|
|
13
|
-
* scheme: 'edv' }
|
|
13
|
+
* scheme: 'edv', version: EDV_SCHEME_VERSION }`, so the server stores only
|
|
14
|
+
* ciphertext it can never decrypt and validates every write against the
|
|
15
|
+
* declared envelope wire format -- the same version the cipher binds into each
|
|
16
|
+
* envelope's AEAD-protected header, so descriptor and envelopes cannot drift;
|
|
14
17
|
* a `'plaintext'` collection is configured without one, with `force` so the
|
|
15
18
|
* descriptor-less upsert can create a fresh collection (running with the root
|
|
16
19
|
* capability, a 404 from the pre-merge describe really means absent). A public
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provisioning.d.ts","sourceRoot":"","sources":["../../src/sync/provisioning.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;
|
|
1
|
+
{"version":3,"file":"provisioning.d.ts","sourceRoot":"","sources":["../../src/sync/provisioning.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;GAIG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAKhD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,GAAG,EACH,OAAO,EACP,aAAa,EACb,YAAY,EACZ,UAAkB,EAClB,QAAgB,EAChB,SAAuB,EACvB,cAA6B,EAC9B,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,aAAa,EAAE,MAAM,CAAA;IACrB,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,GAAG,WAAW,CAAA;IAChC,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,GAAG,OAAO,CAAC,IAAI,CAAC,CA+BhB"}
|
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
// A direct module import (not the `./edv` subpath entry), so the crypto-free
|
|
2
|
+
// sync module does not pull the EDV crypto graph for one number.
|
|
3
|
+
import { EDV_SCHEME_VERSION } from '../edv/constants.js';
|
|
1
4
|
/**
|
|
2
5
|
* Ensures the controller's Space exists and one synced collection is
|
|
3
6
|
* configured. An `'edv'` collection declares the encryption descriptor `{
|
|
4
|
-
* scheme: 'edv' }
|
|
7
|
+
* scheme: 'edv', version: EDV_SCHEME_VERSION }`, so the server stores only
|
|
8
|
+
* ciphertext it can never decrypt and validates every write against the
|
|
9
|
+
* declared envelope wire format -- the same version the cipher binds into each
|
|
10
|
+
* envelope's AEAD-protected header, so descriptor and envelopes cannot drift;
|
|
5
11
|
* a `'plaintext'` collection is configured without one, with `force` so the
|
|
6
12
|
* descriptor-less upsert can create a fresh collection (running with the root
|
|
7
13
|
* capability, a 404 from the pre-merge describe really means absent). A public
|
|
@@ -33,7 +39,10 @@ export async function ensureSpaceAndCollection({ was, spaceId, controllerDid, co
|
|
|
33
39
|
try {
|
|
34
40
|
const collection = space.collection(collectionId);
|
|
35
41
|
await collection.configure(encryption === 'edv'
|
|
36
|
-
? {
|
|
42
|
+
? {
|
|
43
|
+
name: collectionName,
|
|
44
|
+
encryption: { scheme: 'edv', version: EDV_SCHEME_VERSION }
|
|
45
|
+
}
|
|
37
46
|
: { name: collectionName, force: true });
|
|
38
47
|
if (isPublic) {
|
|
39
48
|
await collection.setPublic();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provisioning.js","sourceRoot":"","sources":["../../src/sync/provisioning.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"provisioning.js","sourceRoot":"","sources":["../../src/sync/provisioning.ts"],"names":[],"mappings":"AASA,6EAA6E;AAC7E,iEAAiE;AACjE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,EAC7C,GAAG,EACH,OAAO,EACP,aAAa,EACb,YAAY,EACZ,UAAU,GAAG,KAAK,EAClB,QAAQ,GAAG,KAAK,EAChB,SAAS,GAAG,WAAW,EACvB,cAAc,GAAG,YAAY,EAU9B;IACC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IAEhC,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,aAAa,EAAE,CAAC,CAAA;IACvE,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,kCAAkC,OAAO,UAAU,aAAa,IAAI,EACpE,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAA;IACH,CAAC;IAED,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC,YAAY,CAAC,CAAA;QACjD,MAAM,UAAU,CAAC,SAAS,CACxB,UAAU,KAAK,KAAK;YAClB,CAAC,CAAC;gBACE,IAAI,EAAE,cAAc;gBACpB,UAAU,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,kBAAkB,EAAE;aAC3D;YACH,CAAC,CAAC,EAAE,IAAI,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,CAC1C,CAAA;QACD,IAAI,QAAQ,EAAE,CAAC;YACb,MAAM,UAAU,CAAC,SAAS,EAAE,CAAA;QAC9B,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CACb,mCAAmC,YAAY,eAAe,OAAO,IAAI,EACzE,EAAE,KAAK,EAAE,GAAG,EAAE,CACf,CAAA;IACH,CAAC;AACH,CAAC"}
|
package/dist/sync/types.d.ts
CHANGED
|
@@ -40,16 +40,16 @@ export type WireDoc = ChangeDocument;
|
|
|
40
40
|
export type SyncPage = ChangesPage;
|
|
41
41
|
/**
|
|
42
42
|
* The current master state of a single resource, read back for the 412-conflict
|
|
43
|
-
* path ({@link WasSyncPort.get}).
|
|
44
|
-
*
|
|
45
|
-
* are populated from the resource's `/meta`
|
|
46
|
-
* with no metadata yet reports an
|
|
47
|
-
*
|
|
43
|
+
* path ({@link WasSyncPort.get}). An absent or tombstoned resource surfaces as
|
|
44
|
+
* `get` resolving `null`, never as a `MasterState`. `updatedAt`, `metaVersion`,
|
|
45
|
+
* `custom`, `createdBy`, and `epoch` are populated from the resource's `/meta`
|
|
46
|
+
* document when it exists; a resource with no metadata yet reports an
|
|
47
|
+
* epoch-zero `updatedAt` placeholder (a valid, sortable timestamp -- the
|
|
48
|
+
* change feed remains the authority on ordering).
|
|
48
49
|
*/
|
|
49
50
|
export interface MasterState {
|
|
50
51
|
version: number;
|
|
51
52
|
updatedAt: string;
|
|
52
|
-
deleted: boolean;
|
|
53
53
|
metaVersion?: number;
|
|
54
54
|
data?: Json;
|
|
55
55
|
custom?: Json;
|
|
@@ -74,10 +74,7 @@ export interface WasSyncPort {
|
|
|
74
74
|
query(options: {
|
|
75
75
|
checkpoint?: SyncCheckpoint;
|
|
76
76
|
limit: number;
|
|
77
|
-
}): Promise<
|
|
78
|
-
documents: WireDoc[];
|
|
79
|
-
checkpoint: SyncCheckpoint | null;
|
|
80
|
-
}>;
|
|
77
|
+
}): Promise<SyncPage>;
|
|
81
78
|
/**
|
|
82
79
|
* Conditionally writes the content body verbatim (`PUT /:id`). Pass
|
|
83
80
|
* `ifNoneMatch: true` for create-if-absent, or `ifMatch` (a quoted ETag over
|
package/dist/sync/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AACH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAEvC,YAAY,EAAE,IAAI,EAAE,CAAA;AAEpB;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAA;AAE9C;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,GAAG,cAAc,CAAA;AAEpC;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AACH,OAAO,KAAK,EACV,cAAc,EACd,iBAAiB,EACjB,WAAW,EACZ,MAAM,uBAAuB,CAAA;AAC9B,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAEvC,YAAY,EAAE,IAAI,EAAE,CAAA;AAEpB;;;;;;GAMG;AACH,MAAM,MAAM,cAAc,GAAG,iBAAiB,CAAA;AAE9C;;;;;;;;GAQG;AACH,MAAM,MAAM,OAAO,GAAG,cAAc,CAAA;AAEpC;;;;GAIG;AACH,MAAM,MAAM,QAAQ,GAAG,WAAW,CAAA;AAElC;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,CAAC,EAAE,IAAI,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;OAIG;IACH,KAAK,CAAC,OAAO,EAAE;QACb,UAAU,CAAC,EAAE,cAAc,CAAA;QAC3B,KAAK,EAAE,MAAM,CAAA;KACd,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAA;IAErB;;;;;;;OAOG;IACH,UAAU,CAAC,OAAO,EAAE;QAClB,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,IAAI,CAAA;QACV,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,WAAW,CAAC,EAAE,OAAO,CAAA;QACrB,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAEnB;;;;;;OAMG;IACH,aAAa,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;IAEzE;;;;OAIG;IACH,OAAO,CAAC,CAAC,OAAO,EAAE;QAChB,EAAE,EAAE,MAAM,CAAA;QACV,MAAM,EAAE,IAAI,CAAA;QACZ,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,WAAW,CAAC,EAAE,OAAO,CAAA;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;;;OAKG;IACH,GAAG,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CAC1D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,OAAO,EAAE;QACf,IAAI,EAAE,IAAI,CAAA;KACX,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3D,aAAa,CAAC,CAAC,OAAO,EAAE;QACtB,EAAE,EAAE,MAAM,CAAA;QACV,IAAI,EAAE,IAAI,CAAA;QACV,OAAO,EAAE,IAAI,CAAA;KACd,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,IAAI,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IAC3D,OAAO,CAAC,OAAO,EAAE;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CACpD"}
|