@interop/wallet-core 0.16.0 → 0.17.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/dist/clients/revocation.d.ts +5 -2
- package/dist/clients/revocation.d.ts.map +1 -1
- package/dist/clients/revocation.js +27 -11
- package/dist/clients/revocation.js.map +1 -1
- package/dist/clients/rosterPolicy.d.ts +26 -5
- package/dist/clients/rosterPolicy.d.ts.map +1 -1
- package/dist/clients/rosterPolicy.js +93 -35
- package/dist/clients/rosterPolicy.js.map +1 -1
- package/dist/descriptors/refresh.d.ts +3 -1
- package/dist/descriptors/refresh.d.ts.map +1 -1
- package/dist/descriptors/refresh.js +3 -1
- package/dist/descriptors/refresh.js.map +1 -1
- package/dist/display/alignment.d.ts +8 -2
- package/dist/display/alignment.d.ts.map +1 -1
- package/dist/display/alignment.js +11 -8
- package/dist/display/alignment.js.map +1 -1
- package/dist/display/displayFields.d.ts +6 -2
- package/dist/display/displayFields.d.ts.map +1 -1
- package/dist/display/displayFields.js.map +1 -1
- package/dist/display/evidence.d.ts +9 -3
- package/dist/display/evidence.d.ts.map +1 -1
- package/dist/display/evidence.js +3 -1
- package/dist/display/evidence.js.map +1 -1
- package/dist/display/index.d.ts +1 -1
- package/dist/display/index.d.ts.map +1 -1
- package/dist/display/index.js +1 -1
- package/dist/display/index.js.map +1 -1
- package/dist/display/issuer.d.ts +12 -4
- package/dist/display/issuer.d.ts.map +1 -1
- package/dist/display/issuer.js.map +1 -1
- package/dist/display/obv3.d.ts +7 -2
- package/dist/display/obv3.d.ts.map +1 -1
- package/dist/display/obv3.js +14 -24
- package/dist/display/obv3.js.map +1 -1
- package/dist/display/parse.d.ts +6 -2
- package/dist/display/parse.d.ts.map +1 -1
- package/dist/display/parse.js +6 -2
- package/dist/display/parse.js.map +1 -1
- package/dist/display/subject.d.ts +4 -0
- package/dist/display/subject.d.ts.map +1 -1
- package/dist/display/subject.js +12 -10
- package/dist/display/subject.js.map +1 -1
- package/dist/display/text.d.ts +11 -0
- package/dist/display/text.d.ts.map +1 -1
- package/dist/display/text.js +20 -4
- package/dist/display/text.js.map +1 -1
- package/dist/display/types.js +1 -1
- package/dist/display/types.js.map +1 -1
- package/dist/display/validity.js +4 -4
- package/dist/display/validity.js.map +1 -1
- package/dist/display/verificationView.d.ts +21 -7
- package/dist/display/verificationView.d.ts.map +1 -1
- package/dist/display/verificationView.js.map +1 -1
- package/dist/enrollment/enrollment.d.ts +5 -3
- package/dist/enrollment/enrollment.d.ts.map +1 -1
- package/dist/enrollment/enrollment.js +79 -15
- package/dist/enrollment/enrollment.js.map +1 -1
- package/dist/keys/clientKeyRecord.d.ts +3 -1
- package/dist/keys/clientKeyRecord.d.ts.map +1 -1
- package/dist/keys/clientKeyRecord.js +42 -10
- package/dist/keys/clientKeyRecord.js.map +1 -1
- package/dist/keys/index.d.ts +1 -1
- package/dist/keys/index.d.ts.map +1 -1
- package/dist/keys/index.js +1 -1
- package/dist/keys/index.js.map +1 -1
- package/dist/keys/pukCascade.d.ts.map +1 -1
- package/dist/keys/pukCascade.js +13 -14
- package/dist/keys/pukCascade.js.map +1 -1
- package/dist/keys/pukRoster.d.ts +85 -7
- package/dist/keys/pukRoster.d.ts.map +1 -1
- package/dist/keys/pukRoster.js +136 -11
- package/dist/keys/pukRoster.js.map +1 -1
- package/dist/request/classify.d.ts +15 -1
- package/dist/request/classify.d.ts.map +1 -1
- package/dist/request/classify.js +38 -14
- package/dist/request/classify.js.map +1 -1
- package/dist/request/composeVp.d.ts.map +1 -1
- package/dist/request/composeVp.js +10 -3
- package/dist/request/composeVp.js.map +1 -1
- package/dist/request/matching.d.ts +6 -0
- package/dist/request/matching.d.ts.map +1 -1
- package/dist/request/matching.js +33 -8
- package/dist/request/matching.js.map +1 -1
- package/dist/request/parse.d.ts +5 -2
- package/dist/request/parse.d.ts.map +1 -1
- package/dist/request/parse.js +30 -5
- package/dist/request/parse.js.map +1 -1
- package/dist/request/presentationSuite.d.ts.map +1 -1
- package/dist/request/presentationSuite.js +6 -2
- package/dist/request/presentationSuite.js.map +1 -1
- package/dist/request/processRequest.js +1 -1
- package/dist/request/processRequest.js.map +1 -1
- package/dist/space/activity.d.ts +21 -7
- package/dist/space/activity.d.ts.map +1 -1
- package/dist/space/activity.js +18 -6
- package/dist/space/activity.js.map +1 -1
- package/dist/space/collections.d.ts +18 -6
- package/dist/space/collections.d.ts.map +1 -1
- package/dist/space/collections.js +18 -6
- package/dist/space/collections.js.map +1 -1
- package/dist/space/wasLink.d.ts +6 -2
- package/dist/space/wasLink.d.ts.map +1 -1
- package/dist/space/wasLink.js +5 -2
- package/dist/space/wasLink.js.map +1 -1
- package/dist/sync/contactsConflict.d.ts +1 -1
- package/dist/sync/contactsConflict.js +1 -1
- package/dist/sync/engine.d.ts +33 -11
- package/dist/sync/engine.d.ts.map +1 -1
- package/dist/sync/engine.js +4 -3
- package/dist/sync/engine.js.map +1 -1
- package/dist/sync/pull.d.ts +5 -3
- package/dist/sync/pull.d.ts.map +1 -1
- package/dist/sync/pull.js +34 -10
- package/dist/sync/pull.js.map +1 -1
- package/dist/sync/push.d.ts.map +1 -1
- package/dist/sync/push.js +24 -8
- package/dist/sync/push.js.map +1 -1
- package/dist/sync/types.d.ts +30 -6
- package/dist/sync/types.d.ts.map +1 -1
- package/dist/webvh/didWebvh.d.ts +28 -0
- package/dist/webvh/didWebvh.d.ts.map +1 -1
- package/dist/webvh/didWebvh.js +40 -5
- package/dist/webvh/didWebvh.js.map +1 -1
- package/dist/webvh/index.d.ts +1 -1
- package/dist/webvh/index.d.ts.map +1 -1
- package/dist/webvh/index.js +1 -1
- package/dist/webvh/index.js.map +1 -1
- package/dist/webvh/listClients.d.ts +19 -0
- package/dist/webvh/listClients.d.ts.map +1 -1
- package/dist/webvh/listClients.js +37 -1
- package/dist/webvh/listClients.js.map +1 -1
- package/dist/webvh/revokeClient.d.ts +11 -3
- package/dist/webvh/revokeClient.d.ts.map +1 -1
- package/dist/webvh/revokeClient.js +83 -14
- package/dist/webvh/revokeClient.js.map +1 -1
- package/package.json +3 -3
|
@@ -15,11 +15,17 @@
|
|
|
15
15
|
* (`CONTACTS_COLLECTION_SPEC` / `CONTACTS_HISTORY_COLLECTION_SPEC`), which apps
|
|
16
16
|
* import directly. The field vocabulary below mirrors that spec.
|
|
17
17
|
*/
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* The immutable, content-addressed, EDV-encrypted credential replica.
|
|
20
|
+
*/
|
|
19
21
|
export const PRIVATE_CREDENTIALS_COLLECTION = 'private-credentials';
|
|
20
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* The plaintext, world-readable copies of publicly shared credentials.
|
|
24
|
+
*/
|
|
21
25
|
export const PUBLIC_CREDENTIALS_COLLECTION = 'public-credentials';
|
|
22
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* The append-only, EDV-encrypted wallet activity log.
|
|
28
|
+
*/
|
|
23
29
|
export const WALLET_ACTIVITY_COLLECTION = 'wallet-activity';
|
|
24
30
|
/**
|
|
25
31
|
* The immutable credential replica: each credential stored as an EDV envelope,
|
|
@@ -56,7 +62,9 @@ export const WALLET_ACTIVITY_COLLECTION_SPEC = {
|
|
|
56
62
|
encryption: 'edv',
|
|
57
63
|
isPublic: false
|
|
58
64
|
};
|
|
59
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* The wallet Space's own (non-contacts) collection specs, in provision order.
|
|
67
|
+
*/
|
|
60
68
|
export const WALLET_SPACE_COLLECTION_SPECS = [
|
|
61
69
|
PRIVATE_CREDENTIALS_COLLECTION_SPEC,
|
|
62
70
|
PUBLIC_CREDENTIALS_COLLECTION_SPEC,
|
|
@@ -83,7 +91,9 @@ export const WALLET_SPACE_COLLECTION_SPECS = [
|
|
|
83
91
|
export const ID_COLLECTION = { id: 'id', name: 'Identity' };
|
|
84
92
|
export const KEY_MAP_COLLECTION = { id: 'key-map', name: 'Key Map' };
|
|
85
93
|
export const KEYRING_COLLECTION = { id: 'keyring', name: 'Keyring' };
|
|
86
|
-
/**
|
|
94
|
+
/**
|
|
95
|
+
* The world-readable DID document, served as `application/did+json`.
|
|
96
|
+
*/
|
|
87
97
|
export const DID_DOCUMENT_RESOURCE = 'did.json';
|
|
88
98
|
/**
|
|
89
99
|
* The world-readable did:webvh history log, a raw JSON-Lines string served as
|
|
@@ -118,6 +128,8 @@ export const PUK_ROSTER_RESOURCE = 'puk.json';
|
|
|
118
128
|
* label adds only the display name.
|
|
119
129
|
*/
|
|
120
130
|
export const CLIENT_LABELS_RESOURCE = 'client-labels.json';
|
|
121
|
-
/**
|
|
131
|
+
/**
|
|
132
|
+
* The keyring record: the encrypted account pointer, in the unlock Space.
|
|
133
|
+
*/
|
|
122
134
|
export const KEYRING_RESOURCE = 'keyring.json';
|
|
123
135
|
//# sourceMappingURL=collections.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/space/collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AAEH
|
|
1
|
+
{"version":3,"file":"collections.js","sourceRoot":"","sources":["../../src/space/collections.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;GAaG;AAEH;;GAEG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAG,qBAAqB,CAAA;AACnE;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAAG,oBAAoB,CAAA;AACjE;;GAEG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,iBAAiB,CAAA;AAyB3D;;;GAGG;AACH,MAAM,CAAC,MAAM,mCAAmC,GAAwB;IACtE,YAAY,EAAE,8BAA8B;IAC5C,YAAY,EAAE,SAAS;IACvB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;CAChB,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,kCAAkC,GAAwB;IACrE,YAAY,EAAE,6BAA6B;IAC3C,YAAY,EAAE,SAAS;IACvB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,WAAW;IACvB,QAAQ,EAAE,IAAI;CACf,CAAA;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAwB;IAClE,YAAY,EAAE,0BAA0B;IACxC,YAAY,EAAE,SAAS;IACvB,OAAO,EAAE,KAAK;IACd,UAAU,EAAE,KAAK;IACjB,QAAQ,EAAE,KAAK;CAChB,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,6BAA6B,GAA0B;IAClE,mCAAmC;IACnC,kCAAkC;IAClC,+BAA+B;CAChC,CAAA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,CAAA;AAC3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AACpE,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE,CAAA;AAEpE;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,UAAU,CAAA;AAC/C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,WAAW,CAAA;AAC3C;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,WAAW,CAAA;AAC5C;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,CAAA;AAC7C;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,oBAAoB,CAAA;AAC1D;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,cAAc,CAAA"}
|
package/dist/space/wasLink.d.ts
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
|
-
/**
|
|
1
|
+
/**
|
|
2
|
+
* The decoded link: the WAS server plus the controller secret AS A STRING.
|
|
3
|
+
*/
|
|
2
4
|
export interface WasLinkPayload {
|
|
3
5
|
serverUrl: string;
|
|
4
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* The controller secret (already decoded back to the passphrase string).
|
|
8
|
+
*/
|
|
5
9
|
secret: string;
|
|
6
10
|
}
|
|
7
11
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasLink.d.ts","sourceRoot":"","sources":["../../src/space/wasLink.ts"],"names":[],"mappings":"AAgBA
|
|
1
|
+
{"version":3,"file":"wasLink.d.ts","sourceRoot":"","sources":["../../src/space/wasLink.ts"],"names":[],"mappings":"AAgBA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAA;CACf;AA4CD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,SAAS,EACT,UAAU,EACX,EAAE;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB,GAAG,MAAM,CAOT;AAED;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAyC/D"}
|
package/dist/space/wasLink.js
CHANGED
|
@@ -15,7 +15,9 @@ import { base64urlnopad } from '@scure/base';
|
|
|
15
15
|
import { HumanReadableError } from './errors.js';
|
|
16
16
|
const NOT_A_LINK = 'This QR code is not a wallet connection code.';
|
|
17
17
|
const BAD_SERVER = 'Connection code points at an insecure or invalid server and was rejected.';
|
|
18
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Strips optional base64 padding so the no-pad decoder accepts either form.
|
|
20
|
+
*/
|
|
19
21
|
function stripPadding(value) {
|
|
20
22
|
return value.replace(/=+$/, '');
|
|
21
23
|
}
|
|
@@ -42,7 +44,8 @@ function assertValidServerUrl(serverUrl) {
|
|
|
42
44
|
}
|
|
43
45
|
const isLoopback = url.hostname === 'localhost' ||
|
|
44
46
|
url.hostname === '127.0.0.1' ||
|
|
45
|
-
|
|
47
|
+
// WHATWG URL serializes an IPv6 host with its brackets
|
|
48
|
+
url.hostname === '[::1]';
|
|
46
49
|
if (url.protocol === 'https:' || (url.protocol === 'http:' && isLoopback)) {
|
|
47
50
|
return;
|
|
48
51
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wasLink.js","sourceRoot":"","sources":["../../src/space/wasLink.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;GASG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAA;
|
|
1
|
+
{"version":3,"file":"wasLink.js","sourceRoot":"","sources":["../../src/space/wasLink.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The rule lives here rather than in `@interop/social-core` because deciding
|
|
13
13
|
* it means DECRYPTING both sides: a head payload rides inside an encrypted
|
|
14
|
-
* envelope, and the `updatedAt` /
|
|
14
|
+
* envelope, and the `updatedAt` / `writerId` pair the rule compares is sealed
|
|
15
15
|
* inside it. The comparison itself is still social-core's
|
|
16
16
|
* (`remotePayloadWins`), and both replicas run the same one, so they converge
|
|
17
17
|
* with no duplicates and no round trips.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
*
|
|
12
12
|
* The rule lives here rather than in `@interop/social-core` because deciding
|
|
13
13
|
* it means DECRYPTING both sides: a head payload rides inside an encrypted
|
|
14
|
-
* envelope, and the `updatedAt` /
|
|
14
|
+
* envelope, and the `updatedAt` / `writerId` pair the rule compares is sealed
|
|
15
15
|
* inside it. The comparison itself is still social-core's
|
|
16
16
|
* (`remotePayloadWins`), and both replicas run the same one, so they converge
|
|
17
17
|
* with no duplicates and no round trips.
|
package/dist/sync/engine.d.ts
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
* DocCipher, provisioning, and lazy migration.
|
|
15
15
|
*/
|
|
16
16
|
import type { Json, ResolveConflict, SyncStore, WasSyncPort } from './types.js';
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* Per-feed replication status, surfaced to the app's state layer.
|
|
19
|
+
*/
|
|
18
20
|
export type SyncStatus = 'idle' | 'syncing' | 'synced' | 'error';
|
|
19
21
|
/**
|
|
20
22
|
* Everything the engine needs, injected. The pure protocol ({@link WasSyncPort},
|
|
@@ -25,7 +27,9 @@ export type SyncStatus = 'idle' | 'syncing' | 'synced' | 'error';
|
|
|
25
27
|
export interface SyncEngineDeps {
|
|
26
28
|
port: WasSyncPort;
|
|
27
29
|
store: SyncStore;
|
|
28
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* Decrypts a pulled body to its plaintext payload (DocCipher).
|
|
32
|
+
*/
|
|
29
33
|
decryptDoc: (envelope: Json) => Promise<Json>;
|
|
30
34
|
/**
|
|
31
35
|
* The collection's payload guard, when it has one: a pulled document that
|
|
@@ -39,27 +43,45 @@ export interface SyncEngineDeps {
|
|
|
39
43
|
*/
|
|
40
44
|
resolveConflict?: ResolveConflict;
|
|
41
45
|
batchSize?: number;
|
|
42
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Idempotent space + collection provisioning.
|
|
48
|
+
*/
|
|
43
49
|
ensureProvisioned: () => Promise<void>;
|
|
44
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Has this feed's lazy migration already run (per-collection milestone)?
|
|
52
|
+
*/
|
|
45
53
|
isMigrated: () => Promise<boolean>;
|
|
46
|
-
/**
|
|
54
|
+
/**
|
|
55
|
+
* Mint bodies for this feed's still-unlinked local rows.
|
|
56
|
+
*/
|
|
47
57
|
runLazyMigration: (signal: AbortSignal) => Promise<void>;
|
|
48
|
-
/**
|
|
58
|
+
/**
|
|
59
|
+
* Record this feed's migrated milestone after a successful first migration.
|
|
60
|
+
*/
|
|
49
61
|
stampMigrated: () => Promise<void>;
|
|
50
|
-
/**
|
|
62
|
+
/**
|
|
63
|
+
* Stamp the replica's last-synced time after a successful cycle.
|
|
64
|
+
*/
|
|
51
65
|
stampLastSynced: () => Promise<void>;
|
|
52
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* Called on every status transition (drives the app's state layer).
|
|
68
|
+
*/
|
|
53
69
|
onStatusChange?: (status: SyncStatus) => void;
|
|
54
|
-
/**
|
|
70
|
+
/**
|
|
71
|
+
* Called after a pull that applied >= 1 document (triggers the refetch).
|
|
72
|
+
*/
|
|
55
73
|
onPullApplied?: () => void;
|
|
56
74
|
backoff?: {
|
|
57
75
|
baseDelayMs?: number;
|
|
58
76
|
maxDelayMs?: number;
|
|
59
77
|
};
|
|
60
|
-
/**
|
|
78
|
+
/**
|
|
79
|
+
* Schedules a retry; returns a canceller. Defaults to setTimeout.
|
|
80
|
+
*/
|
|
61
81
|
schedule?: (fn: () => void, delayMs: number) => () => void;
|
|
62
|
-
/**
|
|
82
|
+
/**
|
|
83
|
+
* Jitter source in [0, 1). Defaults to Math.random.
|
|
84
|
+
*/
|
|
63
85
|
random?: () => number;
|
|
64
86
|
}
|
|
65
87
|
export declare class SyncEngine {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAI/E
|
|
1
|
+
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,KAAK,EAAE,IAAI,EAAE,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAI/E;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAMhE;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB;;OAEG;IACH,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C;;;OAGG;IACH,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C;;;;OAIG;IACH,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;OAEG;IACH,iBAAiB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACtC;;OAEG;IACH,UAAU,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAClC;;OAEG;IACH,gBAAgB,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACxD;;OAEG;IACH,aAAa,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAClC;;OAEG;IACH,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IAEpC;;OAEG;IACH,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAA;IAC7C;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAE1B,OAAO,CAAC,EAAE;QAAE,WAAW,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;IACvD;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,IAAI,CAAA;IAC1D;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,MAAM,CAAA;CACtB;AAOD,qBAAa,UAAU;IAiBT,OAAO,CAAC,QAAQ,CAAC,IAAI;IAhBjC,MAAM,EAAE,UAAU,CAAS;IAE3B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAQ;IAClC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IACpC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAQ;IACnC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAiD;IAC1E,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IAErC,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,cAAc,CAAQ;IAC9B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,YAAY,CAAI;IACxB,OAAO,CAAC,UAAU,CAA6B;IAC/C,OAAO,CAAC,eAAe,CAA+B;IACtD,OAAO,CAAC,WAAW,CAA4B;gBAElB,IAAI,EAAE,cAAc;IAQjD;;;;;;;;OAQG;IACH,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAYrB;;;;;OAKG;IACH,IAAI,IAAI,IAAI;YAOE,GAAG;IA8BjB;;;;;;;;;;;OAWG;YACW,QAAQ;YAoDR,IAAI;IAYlB,OAAO,CAAC,aAAa;IAgBrB,OAAO,CAAC,UAAU;IAOlB,OAAO,CAAC,SAAS;CAOlB"}
|
package/dist/sync/engine.js
CHANGED
|
@@ -163,9 +163,10 @@ export class SyncEngine {
|
|
|
163
163
|
}
|
|
164
164
|
scheduleRetry() {
|
|
165
165
|
const capped = Math.min(this.baseDelayMs * 2 ** this.failureCount, this.maxDelayMs);
|
|
166
|
-
//
|
|
167
|
-
// retrying in lockstep
|
|
168
|
-
|
|
166
|
+
// Jitter over the upper half of the capped interval keeps N engines from
|
|
167
|
+
// retrying in lockstep, while staying INSIDE the cap: the delay lands in
|
|
168
|
+
// [capped / 2, capped], so it never exceeds `maxDelayMs`.
|
|
169
|
+
const delay = capped * (0.5 + 0.5 * this.random());
|
|
169
170
|
this.failureCount += 1;
|
|
170
171
|
this.cancelRetry = this.schedule(() => {
|
|
171
172
|
this.cancelRetry = null;
|
package/dist/sync/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"engine.js","sourceRoot":"","sources":["../../src/sync/engine.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/pull.d.ts
CHANGED
|
@@ -46,9 +46,11 @@ export declare function projectionForDoc(doc: WireDoc, decryptDoc: (envelope: Js
|
|
|
46
46
|
/**
|
|
47
47
|
* Runs the pull loop to exhaustion for one feed. Fetches a page from the current
|
|
48
48
|
* checkpoint, decrypts it to projections, and applies it (upserts + projection +
|
|
49
|
-
* checkpoint advance) in one exclusive store transaction. Terminates on
|
|
50
|
-
* page (caught up
|
|
51
|
-
*
|
|
49
|
+
* checkpoint advance) in one exclusive store transaction. Terminates on an empty
|
|
50
|
+
* page (caught up / no change -- the prior checkpoint is kept, never overwritten
|
|
51
|
+
* with `null`), or on a checkpoint that did not advance. Page size is never used
|
|
52
|
+
* as the caught-up signal: the server may clamp `limit` below the requested
|
|
53
|
+
* `batchSize`. Honors `signal` between pages so a lock drops
|
|
52
54
|
* the loop promptly; a mid-loop abort leaves each already-applied page intact
|
|
53
55
|
* and the feed resumable.
|
|
54
56
|
*
|
package/dist/sync/pull.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EACV,IAAI,EACJ,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,OAAO,EACR,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,EAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;
|
|
1
|
+
{"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EACV,IAAI,EACJ,gBAAgB,EAEhB,SAAS,EACT,WAAW,EACX,OAAO,EACR,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,EAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,GAC3C,OAAO,CAAC,gBAAgB,CAAC,CAuB3B;AAqBD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,SAAS,EACT,UAAU,EACV,eAAe,EACf,MAAM,EACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,CAAC,QAAQ,EAAE,IAAI,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC7C,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,KAAK,OAAO,CAAA;IAC5C,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAyD/B"}
|
package/dist/sync/pull.js
CHANGED
|
@@ -39,12 +39,29 @@ export async function projectionForDoc(doc, decryptDoc, validatePayload) {
|
|
|
39
39
|
return { kind: 'none' };
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Are two feed positions the same point? Used as the pull loop's
|
|
44
|
+
* no-progress guard: a page whose resume checkpoint equals the one it was
|
|
45
|
+
* fetched with would be refetched forever.
|
|
46
|
+
*
|
|
47
|
+
* @param left {SyncCheckpoint | undefined}
|
|
48
|
+
* @param right {SyncCheckpoint | null}
|
|
49
|
+
* @returns {boolean}
|
|
50
|
+
*/
|
|
51
|
+
function sameCheckpoint(left, right) {
|
|
52
|
+
if (left === undefined || right === null) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return left.id === right.id && left.updatedAt === right.updatedAt;
|
|
56
|
+
}
|
|
42
57
|
/**
|
|
43
58
|
* Runs the pull loop to exhaustion for one feed. Fetches a page from the current
|
|
44
59
|
* checkpoint, decrypts it to projections, and applies it (upserts + projection +
|
|
45
|
-
* checkpoint advance) in one exclusive store transaction. Terminates on
|
|
46
|
-
* page (caught up
|
|
47
|
-
*
|
|
60
|
+
* checkpoint advance) in one exclusive store transaction. Terminates on an empty
|
|
61
|
+
* page (caught up / no change -- the prior checkpoint is kept, never overwritten
|
|
62
|
+
* with `null`), or on a checkpoint that did not advance. Page size is never used
|
|
63
|
+
* as the caught-up signal: the server may clamp `limit` below the requested
|
|
64
|
+
* `batchSize`. Honors `signal` between pages so a lock drops
|
|
48
65
|
* the loop promptly; a mid-loop abort leaves each already-applied page intact
|
|
49
66
|
* and the feed resumable.
|
|
50
67
|
*
|
|
@@ -75,10 +92,11 @@ export async function runPull({ port, store, batchSize, decryptDoc, validatePayl
|
|
|
75
92
|
if (documents.length === 0 || next === null) {
|
|
76
93
|
break;
|
|
77
94
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
95
|
+
// Decrypt the whole page concurrently -- each document is independent, and
|
|
96
|
+
// decryption dominates the page's cost. The entries are collected in
|
|
97
|
+
// document order, so `projections` is keyed identically to a sequential run.
|
|
98
|
+
const actions = await Promise.all(documents.map(doc => projectionForDoc(doc, decryptDoc, validatePayload)));
|
|
99
|
+
const projections = new Map(documents.map((doc, index) => [doc.id, actions[index]]));
|
|
82
100
|
// A lock/stop between decrypt and apply drops this page (checkpoint not
|
|
83
101
|
// advanced), leaving it to a clean re-pull -- cheaper than holding the write
|
|
84
102
|
// lock across the abort check.
|
|
@@ -91,9 +109,15 @@ export async function runPull({ port, store, batchSize, decryptDoc, validatePayl
|
|
|
91
109
|
projections
|
|
92
110
|
});
|
|
93
111
|
applied += documents.length;
|
|
94
|
-
//
|
|
95
|
-
//
|
|
96
|
-
|
|
112
|
+
// Caught-up is decided by the SERVER, not by page size: a server free to
|
|
113
|
+
// clamp `limit` returns full-but-short pages forever, so a
|
|
114
|
+
// `documents.length < batchSize` test would stop the loop one page into the
|
|
115
|
+
// backlog. We loop until the server itself says there is nothing left --
|
|
116
|
+
// an empty page (checked at the top of the next iteration), at the cost of
|
|
117
|
+
// one extra round trip at the tail. The checkpoint is the same page's
|
|
118
|
+
// resume position; if it somehow did not advance, stop rather than refetch
|
|
119
|
+
// the same page forever.
|
|
120
|
+
if (sameCheckpoint(checkpoint, next)) {
|
|
97
121
|
break;
|
|
98
122
|
}
|
|
99
123
|
}
|
package/dist/sync/pull.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"AA+BA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,GAAY,EACZ,UAA6C,EAC7C,eAA4C;IAE5C,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjB,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAA;IAC3B,CAAC;IACD,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;QAChD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACzB,CAAC;IACD,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,UAAU,CAAC,GAAG,CAAC,IAAY,CAAC,CAAA;QAClD,IAAI,eAAe,KAAK,SAAS,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/D,OAAO,CAAC,IAAI,CACV,uCAAuC,GAAG,CAAC,EAAE,oBAAoB,CAClE,CAAA;YACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;QACzB,CAAC;QACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAA;IACpC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,IAAI,CACV,2CAA2C,GAAG,CAAC,EAAE,oBAAoB,EACrE,GAAG,CACJ,CAAA;QACD,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAA;IACzB,CAAC;AACH,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/sync/pull.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/push.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,EAAQ,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM/E,OAAO,EAAE,UAAU,EAAE,CAAA;
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,KAAK,EAAQ,eAAe,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAM/E,OAAO,EAAE,UAAU,EAAE,CAAA;AA8KrB;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,OAAO,CAAC,EAC5B,IAAI,EACJ,KAAK,EACL,eAAe,EACf,MAAM,EACP,EAAE;IACD,IAAI,EAAE,WAAW,CAAA;IACjB,KAAK,EAAE,SAAS,CAAA;IAChB,eAAe,CAAC,EAAE,eAAe,CAAA;IACjC,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB,GAAG,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBzD"}
|
package/dist/sync/push.js
CHANGED
|
@@ -36,7 +36,10 @@ export { formatEtag };
|
|
|
36
36
|
* (`PUT /:id` with `If-None-Match: *`); an acked row (`version > 0`) is an
|
|
37
37
|
* in-place update (`If-Match` over its version) -- reachable only on a mutable
|
|
38
38
|
* collection, since a content-addressed row never mutates in place. On success
|
|
39
|
-
* the acked version is recorded and the row goes clean
|
|
39
|
+
* the acked version is recorded and the row goes clean -- unless a local write
|
|
40
|
+
* landed while the write was in flight, which the row's `revision` token
|
|
41
|
+
* detects (see {@link SyncStore.markPushed}) so the newer write stays dirty for
|
|
42
|
+
* the rerun cycle.
|
|
40
43
|
*
|
|
41
44
|
* A `412` is settled by the collection's policy:
|
|
42
45
|
* - A mutable collection defers to its {@link ResolveConflict} (re-read master,
|
|
@@ -56,7 +59,11 @@ async function pushUpsert({ port, store, row, resolveConflict }) {
|
|
|
56
59
|
? { ifMatch: formatEtag(row.version) }
|
|
57
60
|
: { ifNoneMatch: true })
|
|
58
61
|
});
|
|
59
|
-
await store.markPushed({
|
|
62
|
+
await store.markPushed({
|
|
63
|
+
id: row.id,
|
|
64
|
+
version,
|
|
65
|
+
...(row.revision !== undefined && { revision: row.revision })
|
|
66
|
+
});
|
|
60
67
|
return { conflictResolved: false };
|
|
61
68
|
}
|
|
62
69
|
catch (err) {
|
|
@@ -97,18 +104,19 @@ async function pushUpsert({ port, store, row, resolveConflict }) {
|
|
|
97
104
|
* on a `412` so the caller can re-read and retry. Any other error propagates to
|
|
98
105
|
* the engine's backoff.
|
|
99
106
|
*/
|
|
100
|
-
async function tryDelete({ port, store, id, ifMatch }) {
|
|
107
|
+
async function tryDelete({ port, store, id, ifMatch, revision }) {
|
|
108
|
+
const revisionAck = revision !== undefined ? { revision } : {};
|
|
101
109
|
try {
|
|
102
110
|
const version = await port.deleteContent({
|
|
103
111
|
id,
|
|
104
112
|
...(ifMatch !== undefined && { ifMatch })
|
|
105
113
|
});
|
|
106
|
-
await store.markDeletedPushed({ id, version });
|
|
114
|
+
await store.markDeletedPushed({ id, version, ...revisionAck });
|
|
107
115
|
return true;
|
|
108
116
|
}
|
|
109
117
|
catch (err) {
|
|
110
118
|
if (err instanceof WasSyncNotFoundError) {
|
|
111
|
-
await store.markDeletedPushed({ id });
|
|
119
|
+
await store.markDeletedPushed({ id, ...revisionAck });
|
|
112
120
|
return true;
|
|
113
121
|
}
|
|
114
122
|
if (err instanceof WasSyncConflictError) {
|
|
@@ -128,14 +136,21 @@ async function tryDelete({ port, store, id, ifMatch }) {
|
|
|
128
136
|
* becomes current).
|
|
129
137
|
*/
|
|
130
138
|
async function pushDelete({ port, store, row }) {
|
|
139
|
+
const revisionAck = row.revision !== undefined ? { revision: row.revision } : {};
|
|
131
140
|
const firstIfMatch = row.version > 0 ? formatEtag(row.version) : undefined;
|
|
132
|
-
if (await tryDelete({
|
|
141
|
+
if (await tryDelete({
|
|
142
|
+
port,
|
|
143
|
+
store,
|
|
144
|
+
id: row.id,
|
|
145
|
+
ifMatch: firstIfMatch,
|
|
146
|
+
...revisionAck
|
|
147
|
+
})) {
|
|
133
148
|
return;
|
|
134
149
|
}
|
|
135
150
|
const master = await port.get({ id: row.id });
|
|
136
151
|
if (master === null || master.deleted) {
|
|
137
152
|
// delete/delete race -- the resource is already a tombstone / absent.
|
|
138
|
-
await store.markDeletedPushed({ id: row.id });
|
|
153
|
+
await store.markDeletedPushed({ id: row.id, ...revisionAck });
|
|
139
154
|
return;
|
|
140
155
|
}
|
|
141
156
|
// Second attempt with the current master version. If it too hits 412 we simply
|
|
@@ -144,7 +159,8 @@ async function pushDelete({ port, store, row }) {
|
|
|
144
159
|
port,
|
|
145
160
|
store,
|
|
146
161
|
id: row.id,
|
|
147
|
-
ifMatch: formatEtag(master.version)
|
|
162
|
+
ifMatch: formatEtag(master.version),
|
|
163
|
+
...revisionAck
|
|
148
164
|
});
|
|
149
165
|
}
|
|
150
166
|
/**
|
package/dist/sync/push.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAErD,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEvE,0EAA0E;AAC1E,+EAA+E;AAC/E,0BAA0B;AAC1B,OAAO,EAAE,UAAU,EAAE,CAAA;AAErB
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/sync/push.ts"],"names":[],"mappings":"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"}
|
package/dist/sync/types.d.ts
CHANGED
|
@@ -29,6 +29,14 @@ import type { Json, MasterState, SyncCheckpoint, WireDoc } from '@interop/was-cl
|
|
|
29
29
|
* EDV envelope on an encrypted collection, or the plaintext JSON on a plaintext
|
|
30
30
|
* one), `null` for a tombstone. `version` is the last server-acked content
|
|
31
31
|
* revision (`0` = never acked, so a create).
|
|
32
|
+
*
|
|
33
|
+
* `revision` is the store's own local revision token for the row: any opaque
|
|
34
|
+
* value the store bumps on EVERY local write (a counter, a hash of the stored
|
|
35
|
+
* body, an RxDB `_rev`). The push loop carries it back through
|
|
36
|
+
* {@link SyncStore.markPushed} / {@link SyncStore.markDeletedPushed} so the ack
|
|
37
|
+
* can be made conditional -- a local write that lands while the HTTP write is
|
|
38
|
+
* in flight leaves a different token behind and keeps the row dirty. A store
|
|
39
|
+
* that omits it opts out of that protection and is acked unconditionally.
|
|
32
40
|
*/
|
|
33
41
|
export interface SyncedRow {
|
|
34
42
|
id: string;
|
|
@@ -36,6 +44,7 @@ export interface SyncedRow {
|
|
|
36
44
|
updatedAt: string;
|
|
37
45
|
deleted: boolean;
|
|
38
46
|
data: Json | null;
|
|
47
|
+
revision?: string | number;
|
|
39
48
|
}
|
|
40
49
|
/**
|
|
41
50
|
* What a pulled / reconciled document does to the decrypted read-model (the
|
|
@@ -77,9 +86,13 @@ export type ResolveConflict = (row: {
|
|
|
77
86
|
* the engine, outside these calls.
|
|
78
87
|
*/
|
|
79
88
|
export interface SyncStore {
|
|
80
|
-
/**
|
|
89
|
+
/**
|
|
90
|
+
* The last persisted pull checkpoint, or `undefined` before the first pull.
|
|
91
|
+
*/
|
|
81
92
|
getCheckpoint(): Promise<SyncCheckpoint | undefined>;
|
|
82
|
-
/**
|
|
93
|
+
/**
|
|
94
|
+
* All rows awaiting push (dirty).
|
|
95
|
+
*/
|
|
83
96
|
getDirtyRows(): Promise<SyncedRow[]>;
|
|
84
97
|
/**
|
|
85
98
|
* Applies one pulled page in a single exclusive transaction: reconcile each
|
|
@@ -93,20 +106,31 @@ export interface SyncStore {
|
|
|
93
106
|
projections: Map<string, ProjectionAction>;
|
|
94
107
|
}): Promise<void>;
|
|
95
108
|
/**
|
|
96
|
-
* Marks a pushed create as acked:
|
|
97
|
-
*
|
|
109
|
+
* Marks a pushed create/update as acked: record the server `version` when
|
|
110
|
+
* provided (the `204` ETag), and clear dirty -- but ONLY if the row's current
|
|
111
|
+
* {@link SyncedRow.revision} still equals the `revision` that was pushed. A
|
|
112
|
+
* local write that landed while the write was in flight leaves a newer token,
|
|
113
|
+
* and that row MUST stay dirty (with the acked `version` still recorded, so
|
|
114
|
+
* the re-push's `If-Match` is current) so the rerun cycle pushes it. When
|
|
115
|
+
* `revision` is `undefined` -- a store that does not track a revision token --
|
|
116
|
+
* dirty is cleared unconditionally.
|
|
98
117
|
*/
|
|
99
118
|
markPushed(options: {
|
|
100
119
|
id: string;
|
|
101
120
|
version?: number;
|
|
121
|
+
revision?: string | number;
|
|
102
122
|
}): Promise<void>;
|
|
103
123
|
/**
|
|
104
|
-
* Marks a pushed delete as settled: keep the tombstone,
|
|
105
|
-
*
|
|
124
|
+
* Marks a pushed delete as settled: keep the tombstone, record the server
|
|
125
|
+
* `version` when provided, and clear dirty under the same revision condition
|
|
126
|
+
* as {@link SyncStore.markPushed} -- a row rewritten locally mid-flight stays
|
|
127
|
+
* dirty and keeps its local state rather than being forced to a clean
|
|
128
|
+
* tombstone.
|
|
106
129
|
*/
|
|
107
130
|
markDeletedPushed(options: {
|
|
108
131
|
id: string;
|
|
109
132
|
version?: number;
|
|
133
|
+
revision?: string | number;
|
|
110
134
|
}): Promise<void>;
|
|
111
135
|
/**
|
|
112
136
|
* Adopts the server's latest state (its {@link MasterState}, in the wire
|
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;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EACV,IAAI,EACJ,cAAc,EACd,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EACX,cAAc,EACd,OAAO,EACR,MAAM,0BAA0B,CAAA;AAEjC
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACrB,MAAM,0BAA0B,CAAA;AACjC,YAAY,EACV,IAAI,EACJ,cAAc,EACd,OAAO,EACP,WAAW,EACX,WAAW,EACX,SAAS,EACV,MAAM,0BAA0B,CAAA;AAEjC,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EACX,cAAc,EACd,OAAO,EACR,MAAM,0BAA0B,CAAA;AAEjC;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CAC3B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,gBAAgB,GAC1B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE3E;;;;;;;;GAQG;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,GAAG,EAAE;IAClC,EAAE,EAAE,MAAM,CAAA;IACV,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;CAClB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;AAEnB;;;;;;GAMG;AACH,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,aAAa,IAAI,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAA;IAEpD;;OAEG;IACH,YAAY,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC,CAAA;IAEpC;;;;;OAKG;IACH,eAAe,CAAC,OAAO,EAAE;QACvB,SAAS,EAAE,OAAO,EAAE,CAAA;QACpB,UAAU,EAAE,cAAc,CAAA;QAC1B,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAA;KAC3C,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;;;;;;;OASG;IACH,UAAU,CAAC,OAAO,EAAE;QAClB,EAAE,EAAE,MAAM,CAAA;QACV,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC3B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;;;;OAMG;IACH,iBAAiB,CAAC,OAAO,EAAE;QACzB,EAAE,EAAE,MAAM,CAAA;QACV,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;KAC3B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;;;;OAMG;IACH,WAAW,CAAC,OAAO,EAAE;QACnB,EAAE,EAAE,MAAM,CAAA;QACV,MAAM,EAAE,WAAW,GAAG,IAAI,CAAA;QAC1B,UAAU,EAAE,gBAAgB,CAAA;KAC7B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAClB"}
|
package/dist/webvh/didWebvh.d.ts
CHANGED
|
@@ -177,6 +177,34 @@ export interface PublishedWebvhLog {
|
|
|
177
177
|
export declare function readPublishedLog({ idStore }: {
|
|
178
178
|
idStore: WebvhIdStore;
|
|
179
179
|
}): Promise<PublishedWebvhLog | undefined>;
|
|
180
|
+
/**
|
|
181
|
+
* The shared tail of every ceremony path that has nothing left to append to
|
|
182
|
+
* the log -- an adoption, a resumed rotation, an already-enrolled no-op, an
|
|
183
|
+
* already-revoked no-op. All of them used to infer completion from `did.jsonl`
|
|
184
|
+
* alone, which is a half of the state: {@link publishWebvhLog} writes the log
|
|
185
|
+
* and its `did:web` projection in two non-atomic PUTs, so a crash between them
|
|
186
|
+
* leaves a `did.jsonl` that is complete beside a `did.json` that lags it
|
|
187
|
+
* forever (nothing else republishes the projection).
|
|
188
|
+
*
|
|
189
|
+
* So the projection is re-derived from the resolved log and re-PUT
|
|
190
|
+
* unconditionally rather than compared first: the write is idempotent and one
|
|
191
|
+
* request either way, and the resolved log is the source of truth for what the
|
|
192
|
+
* projection must say. A ceremony that no-ops on the log therefore still heals
|
|
193
|
+
* a torn earlier publish.
|
|
194
|
+
*
|
|
195
|
+
* @param options {object}
|
|
196
|
+
* @param options.idStore {WebvhIdStore}
|
|
197
|
+
* @param options.published {PublishedWebvhLog} the resolved published log
|
|
198
|
+
* @returns {Promise<{ did: string; doc: DIDDoc }>} the published DID and its
|
|
199
|
+
* resolved document
|
|
200
|
+
*/
|
|
201
|
+
export declare function concludeWithPublishedLog({ idStore, published }: {
|
|
202
|
+
idStore: WebvhIdStore;
|
|
203
|
+
published: PublishedWebvhLog;
|
|
204
|
+
}): Promise<{
|
|
205
|
+
did: string;
|
|
206
|
+
doc: DIDDoc;
|
|
207
|
+
}>;
|
|
180
208
|
/**
|
|
181
209
|
* The per-entry EFFECTIVE `updateKeys` / `nextKeyHashes` of a log, with
|
|
182
210
|
* did:webvh's carry-forward semantics applied (an entry that omits a
|