@interop/was-react 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/README.md +55 -44
  2. package/dist/auth/chapi.d.ts.map +1 -1
  3. package/dist/auth/chapi.js +16 -5
  4. package/dist/auth/chapi.js.map +1 -1
  5. package/dist/auth/loginFlow.d.ts.map +1 -1
  6. package/dist/auth/loginFlow.js +55 -49
  7. package/dist/auth/loginFlow.js.map +1 -1
  8. package/dist/auth/verifyResponse.d.ts.map +1 -1
  9. package/dist/auth/verifyResponse.js +27 -10
  10. package/dist/auth/verifyResponse.js.map +1 -1
  11. package/dist/auth/walletRequestTypes.d.ts +9 -90
  12. package/dist/auth/walletRequestTypes.d.ts.map +1 -1
  13. package/dist/config.d.ts +9 -9
  14. package/dist/config.js +0 -0
  15. package/dist/dev/provisionDevGrants.d.ts.map +1 -1
  16. package/dist/dev/provisionDevGrants.js +18 -19
  17. package/dist/dev/provisionDevGrants.js.map +1 -1
  18. package/dist/grants.d.ts +19 -9
  19. package/dist/grants.d.ts.map +1 -1
  20. package/dist/grants.js +17 -2
  21. package/dist/grants.js.map +1 -1
  22. package/dist/identity/agents.d.ts +1 -1
  23. package/dist/identity/agents.d.ts.map +1 -1
  24. package/dist/identity/agents.js +10 -25
  25. package/dist/identity/agents.js.map +1 -1
  26. package/dist/identity/appSession.d.ts +27 -0
  27. package/dist/identity/appSession.d.ts.map +1 -1
  28. package/dist/identity/appSession.js +51 -13
  29. package/dist/identity/appSession.js.map +1 -1
  30. package/dist/identity/seedCredential.d.ts +7 -0
  31. package/dist/identity/seedCredential.d.ts.map +1 -1
  32. package/dist/identity/seedCredential.js +11 -14
  33. package/dist/identity/seedCredential.js.map +1 -1
  34. package/dist/identity/seedStore.d.ts +19 -0
  35. package/dist/identity/seedStore.d.ts.map +1 -1
  36. package/dist/identity/seedStore.js +40 -13
  37. package/dist/identity/seedStore.js.map +1 -1
  38. package/dist/index.d.ts +4 -5
  39. package/dist/index.d.ts.map +1 -1
  40. package/dist/index.js +3 -4
  41. package/dist/index.js.map +1 -1
  42. package/dist/jsonLd.d.ts +19 -0
  43. package/dist/jsonLd.d.ts.map +1 -0
  44. package/dist/jsonLd.js +24 -0
  45. package/dist/jsonLd.js.map +1 -0
  46. package/dist/mui/AdoptDialog.d.ts.map +1 -1
  47. package/dist/mui/AdoptDialog.js +7 -3
  48. package/dist/mui/AdoptDialog.js.map +1 -1
  49. package/dist/mui/ClearDataDialog.d.ts.map +1 -1
  50. package/dist/mui/ClearDataDialog.js +12 -11
  51. package/dist/mui/ClearDataDialog.js.map +1 -1
  52. package/dist/mui/ConfirmDialog.d.ts +35 -0
  53. package/dist/mui/ConfirmDialog.d.ts.map +1 -0
  54. package/dist/mui/ConfirmDialog.js +18 -0
  55. package/dist/mui/ConfirmDialog.js.map +1 -0
  56. package/dist/mui/LogoutDialog.d.ts.map +1 -1
  57. package/dist/mui/LogoutDialog.js +7 -3
  58. package/dist/mui/LogoutDialog.js.map +1 -1
  59. package/dist/react/documentApp.d.ts +29 -0
  60. package/dist/react/documentApp.d.ts.map +1 -1
  61. package/dist/react/documentApp.js +9 -38
  62. package/dist/react/documentApp.js.map +1 -1
  63. package/dist/react/hooks.d.ts +13 -7
  64. package/dist/react/hooks.d.ts.map +1 -1
  65. package/dist/react/hooks.js +17 -11
  66. package/dist/react/hooks.js.map +1 -1
  67. package/dist/session/authStore.d.ts +9 -9
  68. package/dist/session/authStore.d.ts.map +1 -1
  69. package/dist/session/authStore.js +203 -112
  70. package/dist/session/authStore.js.map +1 -1
  71. package/dist/storage/adopt.d.ts +5 -1
  72. package/dist/storage/adopt.d.ts.map +1 -1
  73. package/dist/storage/adopt.js +8 -24
  74. package/dist/storage/adopt.js.map +1 -1
  75. package/dist/storage/entityStore.d.ts.map +1 -1
  76. package/dist/storage/entityStore.js +27 -20
  77. package/dist/storage/entityStore.js.map +1 -1
  78. package/dist/storage/localStore.d.ts +12 -6
  79. package/dist/storage/localStore.d.ts.map +1 -1
  80. package/dist/storage/localStore.js +146 -77
  81. package/dist/storage/localStore.js.map +1 -1
  82. package/dist/storage/rehydrate.d.ts.map +1 -1
  83. package/dist/storage/rehydrate.js +20 -4
  84. package/dist/storage/rehydrate.js.map +1 -1
  85. package/dist/storage/sharedCollectionReader.d.ts +1 -1
  86. package/dist/storage/sharedCollectionReader.d.ts.map +1 -1
  87. package/dist/storage/sharedCollectionReader.js +79 -64
  88. package/dist/storage/sharedCollectionReader.js.map +1 -1
  89. package/dist/storage/storageManager.d.ts +3 -1
  90. package/dist/storage/storageManager.d.ts.map +1 -1
  91. package/dist/storage/storageManager.js +20 -6
  92. package/dist/storage/storageManager.js.map +1 -1
  93. package/dist/storage/syncController.d.ts +1 -16
  94. package/dist/storage/syncController.d.ts.map +1 -1
  95. package/dist/storage/syncController.js +48 -37
  96. package/dist/storage/syncController.js.map +1 -1
  97. package/dist/storage/syncStatusStore.d.ts +8 -6
  98. package/dist/storage/syncStatusStore.d.ts.map +1 -1
  99. package/dist/storage/syncStatusStore.js +6 -6
  100. package/dist/storage/syncStatusStore.js.map +1 -1
  101. package/dist/storage/wasRemoteStore.d.ts +34 -2
  102. package/dist/storage/wasRemoteStore.d.ts.map +1 -1
  103. package/dist/storage/wasRemoteStore.js +45 -7
  104. package/dist/storage/wasRemoteStore.js.map +1 -1
  105. package/dist/storage/wasSync.d.ts.map +1 -1
  106. package/dist/storage/wasSync.js +47 -38
  107. package/dist/storage/wasSync.js.map +1 -1
  108. package/dist/sync/changesQuery.d.ts.map +1 -1
  109. package/dist/sync/changesQuery.js +2 -9
  110. package/dist/sync/changesQuery.js.map +1 -1
  111. package/dist/sync/docCipher.d.ts +23 -10
  112. package/dist/sync/docCipher.d.ts.map +1 -1
  113. package/dist/sync/docCipher.js +17 -11
  114. package/dist/sync/docCipher.js.map +1 -1
  115. package/dist/sync/feedMasterPort.d.ts +6 -0
  116. package/dist/sync/feedMasterPort.d.ts.map +1 -1
  117. package/dist/sync/feedMasterPort.js +82 -37
  118. package/dist/sync/feedMasterPort.js.map +1 -1
  119. package/dist/sync/index.d.ts +6 -5
  120. package/dist/sync/index.d.ts.map +1 -1
  121. package/dist/sync/index.js +6 -3
  122. package/dist/sync/index.js.map +1 -1
  123. package/dist/sync/lww.d.ts +27 -18
  124. package/dist/sync/lww.d.ts.map +1 -1
  125. package/dist/sync/lww.js +35 -8
  126. package/dist/sync/lww.js.map +1 -1
  127. package/dist/sync/lwwConflictHandler.d.ts +15 -14
  128. package/dist/sync/lwwConflictHandler.d.ts.map +1 -1
  129. package/dist/sync/lwwConflictHandler.js +37 -26
  130. package/dist/sync/lwwConflictHandler.js.map +1 -1
  131. package/dist/sync/pushWrites.d.ts +9 -9
  132. package/dist/sync/pushWrites.d.ts.map +1 -1
  133. package/dist/sync/pushWrites.js +102 -68
  134. package/dist/sync/pushWrites.js.map +1 -1
  135. package/dist/sync/syncedDocSchema.d.ts.map +1 -1
  136. package/dist/sync/syncedDocSchema.js +3 -0
  137. package/dist/sync/syncedDocSchema.js.map +1 -1
  138. package/dist/sync/types.d.ts +115 -15
  139. package/dist/sync/types.d.ts.map +1 -1
  140. package/dist/sync/types.js +36 -18
  141. package/dist/sync/types.js.map +1 -1
  142. package/dist/sync/wasSyncPort.d.ts +0 -11
  143. package/dist/sync/wasSyncPort.d.ts.map +1 -1
  144. package/dist/sync/wasSyncPort.js +20 -36
  145. package/dist/sync/wasSyncPort.js.map +1 -1
  146. package/package.json +6 -6
  147. package/dist/identity/initAppSession.d.ts +0 -27
  148. package/dist/identity/initAppSession.d.ts.map +0 -1
  149. package/dist/identity/initAppSession.js +0 -30
  150. package/dist/identity/initAppSession.js.map +0 -1
@@ -1,44 +1,20 @@
1
- import { WasSyncConflictError } from './types.js';
1
+ import { formatEtag } from '@interop/was-client/sync';
2
+ import { bodiesEqual, copyOptionalBodyFields, WasSyncAuthError, WasSyncConflictError } from './types.js';
2
3
  /**
3
- * Formats a master revision (`version` or `metaVersion`) as the quoted strong
4
- * ETag the server compares `If-Match` against (revision `3` becomes `"3"`).
5
- *
6
- * @param revision {number}
7
- * @returns {string}
8
- */
9
- export function formatEtag(revision) {
10
- return `"${revision}"`;
11
- }
12
- /**
13
- * Structural equality over two opaque bodies, by canonical-free JSON string.
14
- * Used only to decide whether the content or the metadata half changed and thus
15
- * which endpoint(s) to write. Content-addressed collections never mutate `data`
16
- * for a given id (so the content half only fires on create/delete), and a real
17
- * metadata edit re-encrypts to fresh bytes, so this coarse comparison is
18
- * sufficient for routing.
19
- *
20
- * @param left {Json | undefined}
21
- * @param right {Json | undefined}
22
- * @returns {boolean}
23
- */
24
- function bodiesEqual(left, right) {
25
- return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
26
- }
27
- /**
28
- * Builds the RxDB conflict entry (the real current master state) for a row whose
29
- * conditional write was rejected with `412`. Re-reads the resource; when it is
30
- * genuinely absent (a delete/delete race) the master is a tombstone synthesized
31
- * from what we know locally.
4
+ * Maps a re-read master state into the RxDB conflict entry for one row, or --
5
+ * when the re-read found the resource genuinely absent (`master === null`, a
6
+ * delete/delete race) -- synthesizes the tombstone conflict entry from what we
7
+ * know locally. Shared by the `412` assembler and the `/meta` 404 recovery, so
8
+ * both report an absent master identically.
32
9
  *
33
10
  * @param options {object}
34
- * @param options.port {WasSyncPort}
35
11
  * @param options.id {string}
12
+ * @param options.master {MasterState | null}
36
13
  * @param options.fallbackUpdatedAt {string} used if the resource is now absent
37
14
  * @param options.fallbackVersion {number} used if the resource is now absent
38
- * @returns {Promise<WithDeleted<SyncedDoc>>}
15
+ * @returns {WithDeleted<SyncedDoc>}
39
16
  */
40
- async function assembleConflict({ port, id, fallbackUpdatedAt, fallbackVersion }) {
41
- const master = await port.get({ id });
17
+ function masterOrTombstone({ id, master, fallbackUpdatedAt, fallbackVersion }) {
42
18
  if (master === null) {
43
19
  return {
44
20
  id,
@@ -53,36 +29,59 @@ async function assembleConflict({ port, id, fallbackUpdatedAt, fallbackVersion }
53
29
  version: master.version,
54
30
  _deleted: master.deleted
55
31
  };
56
- if (master.data !== undefined) {
57
- conflict.data = master.data;
58
- }
59
- if (master.metaVersion !== undefined) {
60
- conflict.metaVersion = master.metaVersion;
61
- }
62
- if (master.custom !== undefined) {
63
- conflict.custom = master.custom;
64
- }
32
+ copyOptionalBodyFields({ source: master, target: conflict });
65
33
  return conflict;
66
34
  }
67
35
  /**
68
36
  * Sends one local change to the remote Collection as up to two conditional
69
37
  * writes (content, then metadata). Returns the master-state conflict entry on a
70
- * `412` at either step (with `ack: null`), or the accepted writes' acked
71
- * revisions on success (`ack: null` when no response carried a revision).
38
+ * `412` at either step, or the accepted writes' acked revisions on success
39
+ * (`ack: null` when no response carried a revision). A conflict on the
40
+ * metadata half still returns the content half's earned ack alongside the
41
+ * conflict entry, so an accepted content version is never discarded.
72
42
  *
73
43
  * @param options {object}
74
44
  * @param options.port {WasSyncPort}
75
45
  * @param options.newDocumentState {WithDeleted<SyncedDoc>}
76
46
  * @param [options.assumedMasterState] {WithDeleted<SyncedDoc>}
47
+ * @param [options.cache] {MasterReadCache} the push batch's shared
48
+ * master-read memo
77
49
  * @returns {Promise<{ conflict: WithDeleted<SyncedDoc> | null,
78
50
  * ack: PushWriteAck | null }>}
79
51
  */
80
- async function pushRow({ port, newDocumentState, assumedMasterState }) {
52
+ async function pushRow({ port, newDocumentState, assumedMasterState, cache }) {
81
53
  const { id } = newDocumentState;
82
54
  const assumedVersion = assumedMasterState?.version;
83
55
  const isCreate = assumedMasterState === undefined;
56
+ const ack = { id };
57
+ const hasAck = () => ack.version !== undefined || ack.metaVersion !== undefined;
58
+ const fallbackVersion = () => ack.version ?? assumedVersion ?? newDocumentState.version;
59
+ // Re-reads this row's master. A row that has ALREADY written this batch
60
+ // (a content write accepted before a `/meta` rejection) bypasses the batch
61
+ // memo: a sibling's feed read may have paged past this resource before our
62
+ // own write landed, and the conflict entry must carry the revision that write
63
+ // produced. Rows that wrote nothing -- the ordinary content 412, the common
64
+ // case -- are exactly what the memo is for.
65
+ const readMaster = async () => hasAck()
66
+ ? port.get({ id })
67
+ : port.get({ id, ...(cache !== undefined && { cache }) });
68
+ // Builds the conflict outcome from a re-read master (or from its absence, a
69
+ // delete/delete race), PRESERVING any ack already earned: a content write
70
+ // accepted before a `/meta` 412 must keep its acked `version` (and feed it to
71
+ // the absent-master fallback), or the local row keeps the pre-write version
72
+ // and every later conditional write sends a stale `If-Match`.
73
+ const conflictOutcome = (master) => ({
74
+ conflict: masterOrTombstone({
75
+ id,
76
+ master,
77
+ fallbackUpdatedAt: newDocumentState.updatedAt,
78
+ fallbackVersion: fallbackVersion()
79
+ }),
80
+ ack: hasAck() ? ack : null
81
+ });
82
+ // The 412 path: re-read the resource, then report its real master state.
83
+ const conflictResult = async () => conflictOutcome(await readMaster());
84
84
  try {
85
- const ack = { id };
86
85
  if (newDocumentState._deleted) {
87
86
  // Delete supersedes any metadata write: drop the content, tombstone wins.
88
87
  const ackedVersion = await port.deleteContent({
@@ -104,6 +103,9 @@ async function pushRow({ port, newDocumentState, assumedMasterState }) {
104
103
  const ackedVersion = await port.putContent({
105
104
  id,
106
105
  data: newDocumentState.data ?? null,
106
+ ...(newDocumentState.epoch !== undefined && {
107
+ epoch: newDocumentState.epoch
108
+ }),
107
109
  ...(isCreate
108
110
  ? { ifNoneMatch: true }
109
111
  : assumedVersion !== undefined && {
@@ -114,14 +116,29 @@ async function pushRow({ port, newDocumentState, assumedMasterState }) {
114
116
  ack.version = ackedVersion;
115
117
  }
116
118
  }
117
- // Metadata half: write when the resource has metadata and it changed. On a
118
- // create this runs after the content write (the resource must exist first).
119
- const metadataChanged = !bodiesEqual(newDocumentState.custom, assumedMasterState?.custom);
120
- if (newDocumentState.custom !== undefined && metadataChanged) {
119
+ }
120
+ catch (err) {
121
+ if (err instanceof WasSyncConflictError) {
122
+ return await conflictResult();
123
+ }
124
+ // Any non-conflict error (network, 5xx, auth) propagates so RxDB retries
125
+ // the whole batch with backoff.
126
+ throw err;
127
+ }
128
+ // Metadata half: write when the metadata changed -- including a CLEAR (the
129
+ // new state carries no `custom` while the assumed master does; `putMeta`
130
+ // with no `custom` writes the cleared state). On a create this runs after
131
+ // the content write (the resource must exist first). Its own try/catch so a
132
+ // rejection here can never discard an ack the content half already earned.
133
+ const metadataChanged = !bodiesEqual(newDocumentState.custom, assumedMasterState?.custom);
134
+ if (metadataChanged) {
135
+ try {
121
136
  const assumedMetaVersion = assumedMasterState?.metaVersion;
122
137
  const ackedMetaVersion = await port.putMeta({
123
138
  id,
124
- custom: newDocumentState.custom,
139
+ ...(newDocumentState.custom !== undefined && {
140
+ custom: newDocumentState.custom
141
+ }),
125
142
  ...(assumedMetaVersion !== undefined
126
143
  ? { ifMatch: formatEtag(assumedMetaVersion) }
127
144
  : { ifNoneMatch: true })
@@ -130,23 +147,32 @@ async function pushRow({ port, newDocumentState, assumedMasterState }) {
130
147
  ack.metaVersion = ackedMetaVersion;
131
148
  }
132
149
  }
133
- const hasAck = ack.version !== undefined || ack.metaVersion !== undefined;
134
- return { conflict: null, ack: hasAck ? ack : null };
135
- }
136
- catch (err) {
137
- if (err instanceof WasSyncConflictError) {
138
- const conflict = await assembleConflict({
139
- port,
140
- id,
141
- fallbackUpdatedAt: newDocumentState.updatedAt,
142
- fallbackVersion: assumedVersion ?? newDocumentState.version
143
- });
144
- return { conflict, ack: null };
150
+ catch (err) {
151
+ if (err instanceof WasSyncConflictError) {
152
+ return await conflictResult();
153
+ }
154
+ // Corroborate before condemnation: under WAS 404-masking a `/meta` 404
155
+ // is ambiguous -- expired access, or an ordinary race with a remote
156
+ // delete (a PUT to the `/meta` of a nonexistent resource legitimately
157
+ // 404s). An independent request decides: re-read the master off the
158
+ // changes feed. A feed read that is itself denied rethrows its own auth
159
+ // error (access genuinely expired, so the controller escalates); a feed
160
+ // that answers with an absent/deleted master confirms the delete race,
161
+ // and the row is resolved with that tombstone as the conflict entry
162
+ // (the conflict handler reconciles it) instead of flipping the whole
163
+ // session to "access expired" and wedging the batch in RxDB's retries.
164
+ if (err instanceof WasSyncAuthError && err.status === 404) {
165
+ const master = await readMaster();
166
+ if (master === null || master.deleted) {
167
+ return conflictOutcome(master);
168
+ }
169
+ // The resource is alive and readable while its `/meta` write 404s:
170
+ // the write itself was rejected, so the auth signal stands.
171
+ }
172
+ throw err;
145
173
  }
146
- // Any non-conflict error (network, 5xx, auth) propagates so RxDB retries
147
- // the whole batch with backoff.
148
- throw err;
149
174
  }
175
+ return { conflict: null, ack: hasAck() ? ack : null };
150
176
  }
151
177
  /**
152
178
  * Builds the RxDB push handler that fans a batch of local changes out to
@@ -160,6 +186,12 @@ async function pushRow({ port, newDocumentState, assumedMasterState }) {
160
186
  * caller can write the new `version` / `metaVersion` back into the local row
161
187
  * and keep subsequent conditional writes' `If-Match` in step with the server.
162
188
  *
189
+ * Each batch gets one short-lived master-read memo, shared by its rows and
190
+ * discarded with the batch (never held across batches, where it would go
191
+ * stale). A conflict re-read walks the changes feed from its origin and so pages
192
+ * past every other conflicting row's master on the way; without the memo a batch
193
+ * with k conflicts would run k concurrent full-feed walks.
194
+ *
163
195
  * @param port {WasSyncPort}
164
196
  * @param [onWriteAccepted] {(ack: PushWriteAck) => Promise<void>}
165
197
  * @returns {(rows: Array<{ newDocumentState: WithDeleted<SyncedDoc>,
@@ -168,11 +200,13 @@ async function pushRow({ port, newDocumentState, assumedMasterState }) {
168
200
  */
169
201
  export function createPushHandler(port, onWriteAccepted) {
170
202
  return async function push(rows) {
203
+ const cache = { byId: new Map(), inFlight: null };
171
204
  const results = await Promise.all(rows.map(async (row) => {
172
205
  const result = await pushRow({
173
206
  port,
174
207
  newDocumentState: row.newDocumentState,
175
- assumedMasterState: row.assumedMasterState
208
+ assumedMasterState: row.assumedMasterState,
209
+ cache
176
210
  });
177
211
  if (result.ack !== null && onWriteAccepted !== undefined) {
178
212
  await onWriteAccepted(result.ack);
@@ -1 +1 @@
1
- {"version":3,"file":"pushWrites.js","sourceRoot":"","sources":["../../src/sync/pushWrites.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"pushWrites.js","sourceRoot":"","sources":["../../src/sync/pushWrites.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"syncedDocSchema.d.ts","sourceRoot":"","sources":["../../src/sync/syncedDocSchema.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAAC,SAAS,CAAC,CAiBzD"}
1
+ {"version":3,"file":"syncedDocSchema.d.ts","sourceRoot":"","sources":["../../src/sync/syncedDocSchema.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;GAOG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAE3C;;;;;;GAMG;AACH,wBAAgB,eAAe,IAAI,YAAY,CAAC,SAAS,CAAC,CAoBzD"}
@@ -15,6 +15,9 @@ export function syncedDocSchema() {
15
15
  updatedAt: { type: 'string', maxLength: 64 },
16
16
  version: { type: 'number' },
17
17
  metaVersion: { type: 'number' },
18
+ // The opaque key-epoch id `data` was encrypted under (the `WAS-Key-Epoch`
19
+ // content-push header), when known.
20
+ epoch: { type: 'string', maxLength: 256 },
18
21
  // Opaque stored bodies -- content and metadata envelopes -- moved verbatim.
19
22
  data: { type: 'object', additionalProperties: true },
20
23
  custom: { type: 'object', additionalProperties: true }
@@ -1 +1 @@
1
- {"version":3,"file":"syncedDocSchema.js","sourceRoot":"","sources":["../../src/sync/syncedDocSchema.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,IAAI;QAChB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE;YACtC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;YAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC3B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC/B,4EAA4E;YAC5E,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;YACpD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;SACvD;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC;QACxC,OAAO,EAAE,CAAC,WAAW,CAAC;KACI,CAAA;AAC9B,CAAC"}
1
+ {"version":3,"file":"syncedDocSchema.js","sourceRoot":"","sources":["../../src/sync/syncedDocSchema.ts"],"names":[],"mappings":"AAcA;;;;;;GAMG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO;QACL,OAAO,EAAE,CAAC;QACV,UAAU,EAAE,IAAI;QAChB,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACV,EAAE,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE;YACtC,SAAS,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,EAAE;YAC5C,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC3B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;YAC/B,0EAA0E;YAC1E,oCAAoC;YACpC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE;YACzC,4EAA4E;YAC5E,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;YACpD,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,IAAI,EAAE;SACvD;QACD,QAAQ,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC;QACxC,OAAO,EAAE,CAAC,WAAW,CAAC;KACI,CAAA;AAC9B,CAAC"}
@@ -19,15 +19,63 @@
19
19
  * or the EDV envelope on an encrypted collection) and `custom` is the stored
20
20
  * metadata body (an opaque envelope on an encrypted collection); encrypt/decrypt
21
21
  * stays a read/write-time concern above this layer.
22
+ *
23
+ * The two small helpers that travel with these shapes live here as well: the
24
+ * opaque-body equality every routing decision is made on, and the optional-field
25
+ * copy every wire-to-local mapping runs.
22
26
  */
27
+ import type { Json } from '@interop/was-client';
23
28
  /**
24
29
  * A JSON value -- the opaque stored resource body the sync layer moves verbatim.
25
30
  * For a plaintext collection this is the user document; for an encrypted one it
26
- * is the EDV envelope. The adapter never inspects or transforms it.
31
+ * is the EDV envelope. The adapter never inspects or transforms it. Re-exported
32
+ * from `@interop/was-client`, which owns the wire model, so a body crosses the
33
+ * port boundary without a cast.
34
+ */
35
+ export type { Json };
36
+ /**
37
+ * The optional half of a synced document, shared verbatim by every shape it
38
+ * travels in ({@link WireDoc} on the feed, {@link SyncedDoc} locally,
39
+ * {@link MasterState} on the conflict re-read): the independently-versioned
40
+ * metadata revision and body, the content body, and the content body's
41
+ * key-epoch stamp. Each is genuinely absent rather than `undefined` when the
42
+ * server has nothing for it, so every mapping between the shapes copies them
43
+ * conditionally -- see {@link copyOptionalBodyFields}.
44
+ */
45
+ export interface OptionalBodyFields {
46
+ metaVersion?: number;
47
+ data?: Json;
48
+ custom?: Json;
49
+ epoch?: string;
50
+ }
51
+ /**
52
+ * Structural equality over two opaque bodies, by canonical-free JSON string.
53
+ * Decides whether the content or the metadata half changed -- which endpoint(s)
54
+ * a push writes, and whether two states compare equal for conflict resolution.
55
+ * Content-addressed collections never mutate `data` for a given id, and a real
56
+ * metadata edit re-encrypts to fresh bytes, so this coarse comparison suffices.
57
+ *
58
+ * @param left {Json | undefined}
59
+ * @param right {Json | undefined}
60
+ * @returns {boolean}
61
+ */
62
+ export declare function bodiesEqual(left: Json | undefined, right: Json | undefined): boolean;
63
+ /**
64
+ * Copies the {@link OptionalBodyFields} that are present on `source` onto
65
+ * `target`, leaving an absent field absent (never writing an explicit
66
+ * `undefined`, which would surface the key in a serialized body). The single
67
+ * place every wire-to-local, feed-to-master, and master-to-conflict mapping
68
+ * shares, so a new optional wire field is added once.
69
+ *
70
+ * @param options {object}
71
+ * @param options.source {OptionalBodyFields}
72
+ * @param options.target {OptionalBodyFields} mutated in place
73
+ * @returns {void}
27
74
  */
28
- export type Json = null | boolean | number | string | Json[] | {
29
- [key: string]: Json;
30
- };
75
+ export declare function copyOptionalBodyFields({ source, target }: {
76
+ source: OptionalBodyFields;
77
+ target: OptionalBodyFields;
78
+ }): void;
31
79
  /**
32
80
  * The keyset position in the change feed: the `{ id, updatedAt }` of the last
33
81
  * document a pull returned. Passed back verbatim to resume, and used as the
@@ -56,6 +104,12 @@ export interface WireDoc {
56
104
  metaVersion?: number;
57
105
  data?: Json;
58
106
  custom?: Json;
107
+ /**
108
+ * The opaque key-epoch id the content body was encrypted under (the
109
+ * `key-epochs` feature), present when the server holds a stamp for the
110
+ * resource. Moved verbatim; the sync layer never interprets it.
111
+ */
112
+ epoch?: string;
59
113
  }
60
114
  /**
61
115
  * The local RxDB document shape, shared across every synced collection. The
@@ -72,6 +126,13 @@ export interface SyncedDoc {
72
126
  metaVersion?: number;
73
127
  data?: Json;
74
128
  custom?: Json;
129
+ /**
130
+ * The opaque key-epoch id `data` was encrypted under, when known (stamped by
131
+ * the encrypting cipher on a local write, or pulled off the feed). Sent as
132
+ * the `WAS-Key-Epoch` header on the content push so the server's stamp stays
133
+ * in step with the envelope.
134
+ */
135
+ epoch?: string;
75
136
  }
76
137
  /**
77
138
  * The current master state of a single resource, as read back for the 412
@@ -85,6 +146,30 @@ export interface MasterState {
85
146
  metaVersion?: number;
86
147
  data?: Json;
87
148
  custom?: Json;
149
+ /**
150
+ * The key-epoch stamp of the master's content body, when the feed carries one.
151
+ */
152
+ epoch?: string;
153
+ }
154
+ /**
155
+ * The short-lived master-read memo the rows of ONE push batch share. A
156
+ * resolving `get` implementation may answer from `byId` and MUST record every
157
+ * master it resolved on the way there; a feed-walking implementation pages past
158
+ * all of them anyway, so a batch of k conflicts costs one walk instead of k.
159
+ *
160
+ * `inFlight` is what makes that hold under concurrency: the batch's rows push in
161
+ * parallel, so without it every row would start its own walk before the first
162
+ * one finished and the memo would never be read. A `get` that must walk
163
+ * publishes its walk here; a `get` that finds a walk already running awaits it
164
+ * and re-checks `byId` first. It settles (never rejects) so one row's failed
165
+ * read is not another row's, and is `null` whenever no walk is running.
166
+ *
167
+ * The whole object is created per batch invocation and dropped with it: a memo
168
+ * held across batches would go stale.
169
+ */
170
+ export interface MasterReadCache {
171
+ byId: Map<string, MasterState | null>;
172
+ inFlight: Promise<void> | null;
88
173
  }
89
174
  /**
90
175
  * The write/query half of the injected WAS-access seam. An adapter (the app-side
@@ -124,15 +209,19 @@ export interface WasSyncBasePort {
124
209
  /**
125
210
  * Conditionally writes the content body verbatim (`PUT /:id`). Pass
126
211
  * `ifNoneMatch: true` for a create-if-absent, or `ifMatch` (a quoted ETag over
127
- * the content `version`) for an update-if-unchanged. Returns the new content
128
- * `version` parsed from the response ETag (the acked master revision), or
129
- * `undefined` when the server does not supply one.
212
+ * the content `version`) for an update-if-unchanged. `epoch` is the opaque
213
+ * key-epoch id the body was encrypted under, sent as the `WAS-Key-Epoch`
214
+ * header (an absent epoch clears any prior stamp on the server, per the
215
+ * `key-epochs` feature). Returns the new content `version` parsed from the
216
+ * response ETag (the acked master revision), or `undefined` when the server
217
+ * does not supply one.
130
218
  *
131
219
  * @param options {object}
132
220
  * @param options.id {string}
133
221
  * @param options.data {Json}
134
222
  * @param [options.ifMatch] {string}
135
223
  * @param [options.ifNoneMatch] {boolean}
224
+ * @param [options.epoch] {string}
136
225
  * @returns {Promise<number | undefined>}
137
226
  */
138
227
  putContent(options: {
@@ -140,6 +229,7 @@ export interface WasSyncBasePort {
140
229
  data: Json;
141
230
  ifMatch?: string;
142
231
  ifNoneMatch?: boolean;
232
+ epoch?: string;
143
233
  }): Promise<number | undefined>;
144
234
  /**
145
235
  * Conditionally deletes a resource (writes a tombstone; `DELETE /:id`). Pass
@@ -162,23 +252,25 @@ export interface WasSyncBasePort {
162
252
  }): Promise<number | undefined>;
163
253
  /**
164
254
  * Conditionally writes the metadata body verbatim (`PUT /:id/meta`, body
165
- * `{ custom }`). Pass `ifNoneMatch: true` when the resource has no metadata
166
- * yet, or `ifMatch` (a quoted ETag over `metaVersion`) for an
167
- * update-if-unchanged. The resource must already exist (the server does not
168
- * create a resource from a `/meta` write). Returns the new `metaVersion`
169
- * parsed from the response ETag, or `undefined` when the server does not
170
- * supply one.
255
+ * `{ custom }`). An ABSENT `custom` writes the CLEARED state (a body with no
256
+ * `custom` member -- the server's metadata replace clears every property the
257
+ * body omits), so removing a resource's metadata replicates rather than being
258
+ * skipped. Pass `ifNoneMatch: true` when the resource has no metadata yet, or
259
+ * `ifMatch` (a quoted ETag over `metaVersion`) for an update-if-unchanged.
260
+ * The resource must already exist (the server does not create a resource from
261
+ * a `/meta` write). Returns the new `metaVersion` parsed from the response
262
+ * ETag, or `undefined` when the server does not supply one.
171
263
  *
172
264
  * @param options {object}
265
+ * @param [options.custom] {Json} absent = write the cleared state
173
266
  * @param options.id {string}
174
- * @param options.custom {Json}
175
267
  * @param [options.ifMatch] {string}
176
268
  * @param [options.ifNoneMatch] {boolean}
177
269
  * @returns {Promise<number | undefined>}
178
270
  */
179
271
  putMeta(options: {
180
272
  id: string;
181
- custom: Json;
273
+ custom?: Json;
182
274
  ifMatch?: string;
183
275
  ifNoneMatch?: boolean;
184
276
  }): Promise<number | undefined>;
@@ -197,12 +289,20 @@ export interface WasSyncPort extends WasSyncBasePort {
197
289
  * cannot be resolved (e.g. a feed re-read that exhausts its scan budget), so
198
290
  * the replication cycle retries rather than fabricating a false tombstone.
199
291
  *
292
+ * `cache` is an OPTIONAL {@link MasterReadCache}, shared by the rows of one
293
+ * push batch (see its own docs for the contract). A hit is no staler than a
294
+ * read issued at the same moment, since the memo lives only for that batch. An
295
+ * implementation that ignores it is fully conformant, and a caller that omits
296
+ * it gets an uncached read.
297
+ *
200
298
  * @param options {object}
201
299
  * @param options.id {string}
300
+ * @param [options.cache] {MasterReadCache}
202
301
  * @returns {Promise<MasterState | null>}
203
302
  */
204
303
  get(options: {
205
304
  id: string;
305
+ cache?: MasterReadCache;
206
306
  }): Promise<MasterState | null>;
207
307
  }
208
308
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"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"}
@@ -1,25 +1,43 @@
1
- /*!
2
- * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
- */
4
1
  /**
5
- * Shared types for the collection-agnostic WAS replication adapter.
2
+ * Structural equality over two opaque bodies, by canonical-free JSON string.
3
+ * Decides whether the content or the metadata half changed -- which endpoint(s)
4
+ * a push writes, and whether two states compare equal for conflict resolution.
5
+ * Content-addressed collections never mutate `data` for a given id, and a real
6
+ * metadata edit re-encrypts to fresh bytes, so this coarse comparison suffices.
6
7
  *
7
- * The adapter drives an RxDB `replicateRxCollection` state machine against a
8
- * remote WAS Collection's replication endpoints. It is deliberately free of any
9
- * React or app imports so it can stand alone; all WAS access is injected through
10
- * the {@link WasSyncPort} seam rather than importing `@interop/was-client`
11
- * directly.
8
+ * @param left {Json | undefined}
9
+ * @param right {Json | undefined}
10
+ * @returns {boolean}
11
+ */
12
+ export function bodiesEqual(left, right) {
13
+ return JSON.stringify(left ?? null) === JSON.stringify(right ?? null);
14
+ }
15
+ /**
16
+ * Copies the {@link OptionalBodyFields} that are present on `source` onto
17
+ * `target`, leaving an absent field absent (never writing an explicit
18
+ * `undefined`, which would surface the key in a serialized body). The single
19
+ * place every wire-to-local, feed-to-master, and master-to-conflict mapping
20
+ * shares, so a new optional wire field is added once.
12
21
  *
13
- * The wire contract follows the WAS `changes` feed and its V2 encrypted-metadata
14
- * profile: a synced document carries both a content revision (`version` /
15
- * `data`) and an independently-versioned metadata sub-resource (`metaVersion` /
16
- * `custom`). A metadata-only edit re-surfaces the resource with a bumped
17
- * `updatedAt` / `metaVersion` but unchanged `version` / `data`. The sync layer
18
- * moves both bodies opaquely: `data` is the stored content body (plaintext JSON,
19
- * or the EDV envelope on an encrypted collection) and `custom` is the stored
20
- * metadata body (an opaque envelope on an encrypted collection); encrypt/decrypt
21
- * stays a read/write-time concern above this layer.
22
+ * @param options {object}
23
+ * @param options.source {OptionalBodyFields}
24
+ * @param options.target {OptionalBodyFields} mutated in place
25
+ * @returns {void}
22
26
  */
27
+ export function copyOptionalBodyFields({ source, target }) {
28
+ if (source.data !== undefined) {
29
+ target.data = source.data;
30
+ }
31
+ if (source.metaVersion !== undefined) {
32
+ target.metaVersion = source.metaVersion;
33
+ }
34
+ if (source.custom !== undefined) {
35
+ target.custom = source.custom;
36
+ }
37
+ if (source.epoch !== undefined) {
38
+ target.epoch = source.epoch;
39
+ }
40
+ }
23
41
  /**
24
42
  * Thrown by a {@link WasSyncPort} implementation when a conditional write is
25
43
  * rejected with `412 precondition-failed` (a lost-update conflict, or a
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AA+LH;;;;;;GAMG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,GAAG,4CAA4C;QAChE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,MAAM,CAAQ;IACvB,YAAY,MAAc;QACxB,KAAK,CAAC,mCAAmC,MAAM,IAAI,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF"}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAqDA;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CACzB,IAAsB,EACtB,KAAuB;IAEvB,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAA;AACvE,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CAAC,EACrC,MAAM,EACN,MAAM,EAIP;IACC,IAAI,MAAM,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAA;IAC3B,CAAC;IACD,IAAI,MAAM,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;QACrC,MAAM,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAA;IACzC,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAChC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAA;IAC/B,CAAC;IACD,IAAI,MAAM,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC/B,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAA;IAC7B,CAAC;AACH,CAAC;AA8OD;;;;;;GAMG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C,YAAY,OAAO,GAAG,4CAA4C;QAChE,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAA;IACpC,CAAC;CACF;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,MAAM,CAAQ;IACvB,YAAY,MAAc;QACxB,KAAK,CAAC,mCAAmC,MAAM,IAAI,CAAC,CAAA;QACpD,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;QAC9B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF"}
@@ -26,17 +26,6 @@
26
26
  import { type WasClient } from '@interop/was-client';
27
27
  import type { IZcap } from '@interop/data-integrity-core';
28
28
  import { type WasSyncBasePort } from './types.js';
29
- /**
30
- * Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
31
- * any non-2xx with `err.status` set (see `@interop/http-client`'s error
32
- * normaliser); this reads it defensively from either location. Shared with the
33
- * remote store's descriptor PUT and the dev-grant provisioner, which need the raw
34
- * status for diagnostics rather than the mapped sync error.
35
- *
36
- * @param err {unknown}
37
- * @returns {number | undefined}
38
- */
39
- export declare function errorStatus(err: unknown): number | undefined;
40
29
  /**
41
30
  * Normalizes an unknown caught error into a display string: the `Error`'s
42
31
  * `message` when it is one, else its `String(...)` coercion. Shared by the
@@ -1 +1 @@
1
- {"version":3,"file":"wasSyncPort.d.ts","sourceRoot":"","sources":["../../src/sync/wasSyncPort.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAC5E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;GASG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAK5D;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEjD;AAgDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,OAAO,EACP,YAAY,EACZ,UAAU,EACX,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GAAG,eAAe,CAwGlB"}
1
+ {"version":3,"file":"wasSyncPort.d.ts","sourceRoot":"","sources":["../../src/sync/wasSyncPort.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,qBAAqB,CAAA;AAE5E,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AAEzD,OAAO,EAIL,KAAK,eAAe,EAErB,MAAM,YAAY,CAAA;AAEnB;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAEjD;AAgCD;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,GAAG,EACH,OAAO,EACP,YAAY,EACZ,UAAU,EACX,EAAE;IACD,GAAG,EAAE,SAAS,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;IACf,YAAY,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAA;CACnB,GAAG,eAAe,CAkHlB"}