@interop/was-react 0.1.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 (223) hide show
  1. package/LICENSE.md +20 -0
  2. package/README.md +410 -0
  3. package/dist/auth/chapi.d.ts +43 -0
  4. package/dist/auth/chapi.d.ts.map +1 -0
  5. package/dist/auth/chapi.js +107 -0
  6. package/dist/auth/chapi.js.map +1 -0
  7. package/dist/auth/loginFlow.d.ts +93 -0
  8. package/dist/auth/loginFlow.d.ts.map +1 -0
  9. package/dist/auth/loginFlow.js +149 -0
  10. package/dist/auth/loginFlow.js.map +1 -0
  11. package/dist/auth/loginRequest.d.ts +66 -0
  12. package/dist/auth/loginRequest.d.ts.map +1 -0
  13. package/dist/auth/loginRequest.js +83 -0
  14. package/dist/auth/loginRequest.js.map +1 -0
  15. package/dist/auth/verifyResponse.d.ts +52 -0
  16. package/dist/auth/verifyResponse.d.ts.map +1 -0
  17. package/dist/auth/verifyResponse.js +138 -0
  18. package/dist/auth/verifyResponse.js.map +1 -0
  19. package/dist/auth/verifyResponse.test.d.ts +2 -0
  20. package/dist/auth/verifyResponse.test.d.ts.map +1 -0
  21. package/dist/auth/verifyResponse.test.js +282 -0
  22. package/dist/auth/verifyResponse.test.js.map +1 -0
  23. package/dist/auth/walletRequestTypes.d.ts +143 -0
  24. package/dist/auth/walletRequestTypes.d.ts.map +1 -0
  25. package/dist/auth/walletRequestTypes.js +2 -0
  26. package/dist/auth/walletRequestTypes.js.map +1 -0
  27. package/dist/config.d.ts +150 -0
  28. package/dist/config.d.ts.map +1 -0
  29. package/dist/config.js +27 -0
  30. package/dist/config.js.map +1 -0
  31. package/dist/dev/cli.d.ts +16 -0
  32. package/dist/dev/cli.d.ts.map +1 -0
  33. package/dist/dev/cli.js +122 -0
  34. package/dist/dev/cli.js.map +1 -0
  35. package/dist/dev/cli.test.d.ts +2 -0
  36. package/dist/dev/cli.test.d.ts.map +1 -0
  37. package/dist/dev/cli.test.js +39 -0
  38. package/dist/dev/cli.test.js.map +1 -0
  39. package/dist/dev/index.d.ts +10 -0
  40. package/dist/dev/index.d.ts.map +1 -0
  41. package/dist/dev/index.js +10 -0
  42. package/dist/dev/index.js.map +1 -0
  43. package/dist/dev/provisionDevGrants.d.ts +73 -0
  44. package/dist/dev/provisionDevGrants.d.ts.map +1 -0
  45. package/dist/dev/provisionDevGrants.js +176 -0
  46. package/dist/dev/provisionDevGrants.js.map +1 -0
  47. package/dist/grants.d.ts +59 -0
  48. package/dist/grants.d.ts.map +1 -0
  49. package/dist/grants.js +82 -0
  50. package/dist/grants.js.map +1 -0
  51. package/dist/grants.test.d.ts +2 -0
  52. package/dist/grants.test.d.ts.map +1 -0
  53. package/dist/grants.test.js +79 -0
  54. package/dist/grants.test.js.map +1 -0
  55. package/dist/identity/agents.d.ts +99 -0
  56. package/dist/identity/agents.d.ts.map +1 -0
  57. package/dist/identity/agents.js +132 -0
  58. package/dist/identity/agents.js.map +1 -0
  59. package/dist/identity/appSession.d.ts +78 -0
  60. package/dist/identity/appSession.d.ts.map +1 -0
  61. package/dist/identity/appSession.js +93 -0
  62. package/dist/identity/appSession.js.map +1 -0
  63. package/dist/identity/documentLoader.d.ts +20 -0
  64. package/dist/identity/documentLoader.d.ts.map +1 -0
  65. package/dist/identity/documentLoader.js +99 -0
  66. package/dist/identity/documentLoader.js.map +1 -0
  67. package/dist/identity/initAppSession.d.ts +27 -0
  68. package/dist/identity/initAppSession.d.ts.map +1 -0
  69. package/dist/identity/initAppSession.js +30 -0
  70. package/dist/identity/initAppSession.js.map +1 -0
  71. package/dist/identity/seedCredential.d.ts +74 -0
  72. package/dist/identity/seedCredential.d.ts.map +1 -0
  73. package/dist/identity/seedCredential.js +165 -0
  74. package/dist/identity/seedCredential.js.map +1 -0
  75. package/dist/identity/seedCredential.test.d.ts +2 -0
  76. package/dist/identity/seedCredential.test.d.ts.map +1 -0
  77. package/dist/identity/seedCredential.test.js +205 -0
  78. package/dist/identity/seedCredential.test.js.map +1 -0
  79. package/dist/identity/seedStore.d.ts +27 -0
  80. package/dist/identity/seedStore.d.ts.map +1 -0
  81. package/dist/identity/seedStore.js +74 -0
  82. package/dist/identity/seedStore.js.map +1 -0
  83. package/dist/index.d.ts +37 -0
  84. package/dist/index.d.ts.map +1 -0
  85. package/dist/index.js +46 -0
  86. package/dist/index.js.map +1 -0
  87. package/dist/mui/ProtectedRoute.d.ts +10 -0
  88. package/dist/mui/ProtectedRoute.d.ts.map +1 -0
  89. package/dist/mui/ProtectedRoute.js +54 -0
  90. package/dist/mui/ProtectedRoute.js.map +1 -0
  91. package/dist/mui/ReconnectBanner.d.ts +2 -0
  92. package/dist/mui/ReconnectBanner.d.ts.map +1 -0
  93. package/dist/mui/ReconnectBanner.js +20 -0
  94. package/dist/mui/ReconnectBanner.js.map +1 -0
  95. package/dist/mui/SyncStatusChip.d.ts +2 -0
  96. package/dist/mui/SyncStatusChip.d.ts.map +1 -0
  97. package/dist/mui/SyncStatusChip.js +27 -0
  98. package/dist/mui/SyncStatusChip.js.map +1 -0
  99. package/dist/mui/index.d.ts +12 -0
  100. package/dist/mui/index.d.ts.map +1 -0
  101. package/dist/mui/index.js +12 -0
  102. package/dist/mui/index.js.map +1 -0
  103. package/dist/react/WasSessionProvider.d.ts +36 -0
  104. package/dist/react/WasSessionProvider.d.ts.map +1 -0
  105. package/dist/react/WasSessionProvider.js +35 -0
  106. package/dist/react/WasSessionProvider.js.map +1 -0
  107. package/dist/react/hooks.d.ts +66 -0
  108. package/dist/react/hooks.d.ts.map +1 -0
  109. package/dist/react/hooks.js +121 -0
  110. package/dist/react/hooks.js.map +1 -0
  111. package/dist/react/index.d.ts +11 -0
  112. package/dist/react/index.d.ts.map +1 -0
  113. package/dist/react/index.js +11 -0
  114. package/dist/react/index.js.map +1 -0
  115. package/dist/session/appReadyStore.d.ts +10 -0
  116. package/dist/session/appReadyStore.d.ts.map +1 -0
  117. package/dist/session/appReadyStore.js +22 -0
  118. package/dist/session/appReadyStore.js.map +1 -0
  119. package/dist/session/authStore.d.ts +71 -0
  120. package/dist/session/authStore.d.ts.map +1 -0
  121. package/dist/session/authStore.js +347 -0
  122. package/dist/session/authStore.js.map +1 -0
  123. package/dist/session/index.d.ts +10 -0
  124. package/dist/session/index.d.ts.map +1 -0
  125. package/dist/session/index.js +10 -0
  126. package/dist/session/index.js.map +1 -0
  127. package/dist/storage/entityStore.d.ts +51 -0
  128. package/dist/storage/entityStore.d.ts.map +1 -0
  129. package/dist/storage/entityStore.js +78 -0
  130. package/dist/storage/entityStore.js.map +1 -0
  131. package/dist/storage/localStore.d.ts +144 -0
  132. package/dist/storage/localStore.d.ts.map +1 -0
  133. package/dist/storage/localStore.js +289 -0
  134. package/dist/storage/localStore.js.map +1 -0
  135. package/dist/storage/rehydrate.d.ts +56 -0
  136. package/dist/storage/rehydrate.d.ts.map +1 -0
  137. package/dist/storage/rehydrate.js +87 -0
  138. package/dist/storage/rehydrate.js.map +1 -0
  139. package/dist/storage/rehydrate.test.d.ts +2 -0
  140. package/dist/storage/rehydrate.test.d.ts.map +1 -0
  141. package/dist/storage/rehydrate.test.js +172 -0
  142. package/dist/storage/rehydrate.test.js.map +1 -0
  143. package/dist/storage/storageManager.d.ts +39 -0
  144. package/dist/storage/storageManager.d.ts.map +1 -0
  145. package/dist/storage/storageManager.js +68 -0
  146. package/dist/storage/storageManager.js.map +1 -0
  147. package/dist/storage/syncController.d.ts +79 -0
  148. package/dist/storage/syncController.d.ts.map +1 -0
  149. package/dist/storage/syncController.js +189 -0
  150. package/dist/storage/syncController.js.map +1 -0
  151. package/dist/storage/syncStatusStore.d.ts +17 -0
  152. package/dist/storage/syncStatusStore.d.ts.map +1 -0
  153. package/dist/storage/syncStatusStore.js +19 -0
  154. package/dist/storage/syncStatusStore.js.map +1 -0
  155. package/dist/storage/wasRemoteStore.d.ts +73 -0
  156. package/dist/storage/wasRemoteStore.d.ts.map +1 -0
  157. package/dist/storage/wasRemoteStore.js +76 -0
  158. package/dist/storage/wasRemoteStore.js.map +1 -0
  159. package/dist/storage/wasSync.d.ts +42 -0
  160. package/dist/storage/wasSync.d.ts.map +1 -0
  161. package/dist/storage/wasSync.js +34 -0
  162. package/dist/storage/wasSync.js.map +1 -0
  163. package/dist/sync/changesQuery.d.ts +44 -0
  164. package/dist/sync/changesQuery.d.ts.map +1 -0
  165. package/dist/sync/changesQuery.js +61 -0
  166. package/dist/sync/changesQuery.js.map +1 -0
  167. package/dist/sync/changesQuery.test.d.ts +2 -0
  168. package/dist/sync/changesQuery.test.d.ts.map +1 -0
  169. package/dist/sync/changesQuery.test.js +145 -0
  170. package/dist/sync/changesQuery.test.js.map +1 -0
  171. package/dist/sync/docCipher.d.ts +68 -0
  172. package/dist/sync/docCipher.d.ts.map +1 -0
  173. package/dist/sync/docCipher.js +89 -0
  174. package/dist/sync/docCipher.js.map +1 -0
  175. package/dist/sync/feedMasterPort.d.ts +30 -0
  176. package/dist/sync/feedMasterPort.d.ts.map +1 -0
  177. package/dist/sync/feedMasterPort.js +58 -0
  178. package/dist/sync/feedMasterPort.js.map +1 -0
  179. package/dist/sync/index.d.ts +21 -0
  180. package/dist/sync/index.d.ts.map +1 -0
  181. package/dist/sync/index.js +21 -0
  182. package/dist/sync/index.js.map +1 -0
  183. package/dist/sync/lww.d.ts +29 -0
  184. package/dist/sync/lww.d.ts.map +1 -0
  185. package/dist/sync/lww.js +28 -0
  186. package/dist/sync/lww.js.map +1 -0
  187. package/dist/sync/lww.test.d.ts +2 -0
  188. package/dist/sync/lww.test.d.ts.map +1 -0
  189. package/dist/sync/lww.test.js +28 -0
  190. package/dist/sync/lww.test.js.map +1 -0
  191. package/dist/sync/lwwConflictHandler.d.ts +49 -0
  192. package/dist/sync/lwwConflictHandler.d.ts.map +1 -0
  193. package/dist/sync/lwwConflictHandler.js +65 -0
  194. package/dist/sync/lwwConflictHandler.js.map +1 -0
  195. package/dist/sync/lwwConflictHandler.test.d.ts +2 -0
  196. package/dist/sync/lwwConflictHandler.test.d.ts.map +1 -0
  197. package/dist/sync/lwwConflictHandler.test.js +78 -0
  198. package/dist/sync/lwwConflictHandler.test.js.map +1 -0
  199. package/dist/sync/pushWrites.d.ts +57 -0
  200. package/dist/sync/pushWrites.d.ts.map +1 -0
  201. package/dist/sync/pushWrites.js +159 -0
  202. package/dist/sync/pushWrites.js.map +1 -0
  203. package/dist/sync/pushWrites.test.d.ts +2 -0
  204. package/dist/sync/pushWrites.test.d.ts.map +1 -0
  205. package/dist/sync/pushWrites.test.js +287 -0
  206. package/dist/sync/pushWrites.test.js.map +1 -0
  207. package/dist/sync/syncedDocSchema.d.ts +22 -0
  208. package/dist/sync/syncedDocSchema.d.ts.map +1 -0
  209. package/dist/sync/syncedDocSchema.js +26 -0
  210. package/dist/sync/syncedDocSchema.js.map +1 -0
  211. package/dist/sync/types.d.ts +194 -0
  212. package/dist/sync/types.d.ts.map +1 -0
  213. package/dist/sync/types.js +36 -0
  214. package/dist/sync/types.js.map +1 -0
  215. package/dist/sync/wasReplication.d.ts +47 -0
  216. package/dist/sync/wasReplication.d.ts.map +1 -0
  217. package/dist/sync/wasReplication.js +55 -0
  218. package/dist/sync/wasReplication.js.map +1 -0
  219. package/dist/sync/wasSyncPort.d.ts +45 -0
  220. package/dist/sync/wasSyncPort.d.ts.map +1 -0
  221. package/dist/sync/wasSyncPort.js +170 -0
  222. package/dist/sync/wasSyncPort.js.map +1 -0
  223. package/package.json +142 -0
@@ -0,0 +1,194 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Shared types for the collection-agnostic WAS replication adapter.
6
+ *
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.
12
+ *
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
+ */
23
+ /**
24
+ * A JSON value -- the opaque stored resource body the sync layer moves verbatim.
25
+ * 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.
27
+ */
28
+ export type Json = null | boolean | number | string | Json[] | {
29
+ [key: string]: Json;
30
+ };
31
+ /**
32
+ * The keyset position in the change feed: the `{ id, updatedAt }` of the last
33
+ * document a pull returned. Passed back verbatim to resume, and used as the
34
+ * RxDB replication checkpoint. `id` is the total-order tiebreaker within a
35
+ * single `updatedAt`.
36
+ */
37
+ export interface SyncCheckpoint {
38
+ id: string;
39
+ updatedAt: string;
40
+ }
41
+ /**
42
+ * One document as it travels on the `changes` feed wire
43
+ * (`POST /space/:s/:c/query`, profile `changes`). `id` is the WAS resourceId,
44
+ * `version` is the content master revision (feeds the content push `If-Match`
45
+ * ETag) and the user content body is nested under `data`; `metaVersion` is the
46
+ * independent metadata revision (feeds the `/meta` push `If-Match` ETag) and the
47
+ * user-writable metadata body is under `custom`. A tombstone carries
48
+ * `_deleted: true` with no `data`. `metaVersion` / `custom` are present only
49
+ * once metadata has been written for the resource.
50
+ */
51
+ export interface WireDoc {
52
+ id: string;
53
+ _deleted: boolean;
54
+ updatedAt: string;
55
+ version: number;
56
+ metaVersion?: number;
57
+ data?: Json;
58
+ custom?: Json;
59
+ }
60
+ /**
61
+ * The local RxDB document shape, shared across every synced collection. The
62
+ * envelope fields are top-level (`id` primary key, `updatedAt` the checkpoint
63
+ * sort field, `version` / `metaVersion` the server master revisions); the user
64
+ * bodies stay nested (`data` for content, `custom` for metadata) to avoid field
65
+ * collisions. `_deleted` is managed by RxDB via `deletedField` and so is not
66
+ * part of this "clean" shape (handlers work with RxDB's `WithDeleted<SyncedDoc>`).
67
+ */
68
+ export interface SyncedDoc {
69
+ id: string;
70
+ updatedAt: string;
71
+ version: number;
72
+ metaVersion?: number;
73
+ data?: Json;
74
+ custom?: Json;
75
+ }
76
+ /**
77
+ * The current master state of a single resource, as read back for the 412
78
+ * conflict path. `deleted` distinguishes a tombstone from a live resource;
79
+ * `metaVersion` / `custom` are present only once metadata has been written.
80
+ */
81
+ export interface MasterState {
82
+ version: number;
83
+ updatedAt: string;
84
+ deleted: boolean;
85
+ metaVersion?: number;
86
+ data?: Json;
87
+ custom?: Json;
88
+ }
89
+ /**
90
+ * The injected WAS-access seam. An adapter (the app-side `wasSyncPort.ts`)
91
+ * implements this over `@interop/was-client`; the core module depends only on
92
+ * this interface, never on `was-client` itself. Every method moves the stored
93
+ * body verbatim -- no codec, no key handling -- so the same port works for
94
+ * plaintext and encrypted collections alike.
95
+ *
96
+ * `putContent` / `deleteContent` / `putMeta` MUST throw
97
+ * {@link WasSyncConflictError} when the server rejects a conditional write with
98
+ * `412 precondition-failed`, and let every other error propagate so RxDB's
99
+ * retry/backoff handles it.
100
+ */
101
+ export interface WasSyncPort {
102
+ /**
103
+ * Pulls one page of the `changes` feed. Omit `checkpoint` for the first page.
104
+ * Returns the page's `documents` and its resume `checkpoint`, or
105
+ * `checkpoint: null` for an empty (no-change) page.
106
+ *
107
+ * @param options {object}
108
+ * @param [options.checkpoint] {SyncCheckpoint} resume position
109
+ * @param options.limit {number} requested batch size
110
+ * @returns {Promise<{ documents: WireDoc[], checkpoint: SyncCheckpoint | null }>}
111
+ */
112
+ query(options: {
113
+ checkpoint?: SyncCheckpoint;
114
+ limit: number;
115
+ }): Promise<{
116
+ documents: WireDoc[];
117
+ checkpoint: SyncCheckpoint | null;
118
+ }>;
119
+ /**
120
+ * Conditionally writes the content body verbatim (`PUT /:id`). Pass
121
+ * `ifNoneMatch: true` for a create-if-absent, or `ifMatch` (a quoted ETag over
122
+ * the content `version`) for an update-if-unchanged.
123
+ *
124
+ * @param options {object}
125
+ * @param options.id {string}
126
+ * @param options.data {Json}
127
+ * @param [options.ifMatch] {string}
128
+ * @param [options.ifNoneMatch] {boolean}
129
+ * @returns {Promise<void>}
130
+ */
131
+ putContent(options: {
132
+ id: string;
133
+ data: Json;
134
+ ifMatch?: string;
135
+ ifNoneMatch?: boolean;
136
+ }): Promise<void>;
137
+ /**
138
+ * Conditionally deletes a resource (writes a tombstone; `DELETE /:id`). Pass
139
+ * `ifMatch` (a quoted ETag over the content `version`) to delete only if
140
+ * unchanged.
141
+ *
142
+ * @param options {object}
143
+ * @param options.id {string}
144
+ * @param [options.ifMatch] {string}
145
+ * @returns {Promise<void>}
146
+ */
147
+ deleteContent(options: {
148
+ id: string;
149
+ ifMatch?: string;
150
+ }): Promise<void>;
151
+ /**
152
+ * Conditionally writes the metadata body verbatim (`PUT /:id/meta`, body
153
+ * `{ custom }`). Pass `ifNoneMatch: true` when the resource has no metadata
154
+ * yet, or `ifMatch` (a quoted ETag over `metaVersion`) for an
155
+ * update-if-unchanged. The resource must already exist (the server does not
156
+ * create a resource from a `/meta` write).
157
+ *
158
+ * @param options {object}
159
+ * @param options.id {string}
160
+ * @param options.custom {Json}
161
+ * @param [options.ifMatch] {string}
162
+ * @param [options.ifNoneMatch] {boolean}
163
+ * @returns {Promise<void>}
164
+ */
165
+ putMeta(options: {
166
+ id: string;
167
+ custom: Json;
168
+ ifMatch?: string;
169
+ ifNoneMatch?: boolean;
170
+ }): Promise<void>;
171
+ /**
172
+ * Re-reads a single resource's current master state (content + metadata) for
173
+ * the 412 conflict assembler. Returns `null` when the resource is genuinely
174
+ * absent (a delete/delete race).
175
+ *
176
+ * @param options {object}
177
+ * @param options.id {string}
178
+ * @returns {Promise<MasterState | null>}
179
+ */
180
+ get(options: {
181
+ id: string;
182
+ }): Promise<MasterState | null>;
183
+ }
184
+ /**
185
+ * Thrown by a {@link WasSyncPort} implementation when a conditional write is
186
+ * rejected with `412 precondition-failed` (a lost-update conflict, or a
187
+ * create-if-absent whose target already exists). The core push handler catches
188
+ * exactly this type to trigger the re-read-and-report-conflict path; any other
189
+ * error propagates to RxDB for retry.
190
+ */
191
+ export declare class WasSyncConflictError extends Error {
192
+ constructor(message?: string);
193
+ }
194
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AAEH;;;;GAIG;AACH,MAAM,MAAM,IAAI,GACd,IAAI,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,EAAE,GAAG;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAA;AAErE;;;;;GAKG;AACH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;CAClB;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,OAAO,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,OAAO,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,MAAM,CAAC,EAAE,IAAI,CAAA;CACd;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;;;;OASG;IACH,KAAK,CAAC,OAAO,EAAE;QAAE,UAAU,CAAC,EAAE,cAAc,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC;QACtE,SAAS,EAAE,OAAO,EAAE,CAAA;QACpB,UAAU,EAAE,cAAc,GAAG,IAAI,CAAA;KAClC,CAAC,CAAA;IAEF;;;;;;;;;;;OAWG;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;KACtB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjB;;;;;;;;;OASG;IACH,aAAa,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;IAEvE;;;;;;;;;;;;;OAaG;IACH,OAAO,CAAC,OAAO,EAAE;QACf,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;;;;;;;;OAQG;IACH,GAAG,CAAC,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;CAC1D;AAED;;;;;;GAMG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,SAA+C;CAInE"}
@@ -0,0 +1,36 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * Shared types for the collection-agnostic WAS replication adapter.
6
+ *
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.
12
+ *
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
+ */
23
+ /**
24
+ * Thrown by a {@link WasSyncPort} implementation when a conditional write is
25
+ * rejected with `412 precondition-failed` (a lost-update conflict, or a
26
+ * create-if-absent whose target already exists). The core push handler catches
27
+ * exactly this type to trigger the re-read-and-report-conflict path; any other
28
+ * error propagates to RxDB for retry.
29
+ */
30
+ export class WasSyncConflictError extends Error {
31
+ constructor(message = 'WAS conditional write precondition failed.') {
32
+ super(message);
33
+ this.name = 'WasSyncConflictError';
34
+ }
35
+ }
36
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/sync/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AAoKH;;;;;;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"}
@@ -0,0 +1,47 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * `createWasReplication` -- wires an RxDB collection to a remote WAS Collection
6
+ * through the collection-agnostic pull/push handlers. This is the single public
7
+ * entry point of the sync module; the caller supplies an already-open RxDB
8
+ * collection and a {@link WasSyncPort} (its only WAS dependency), and gets back
9
+ * the live `RxReplicationState` to observe (`error$` / `active$`) and control
10
+ * (`reSync()` / `cancel()`).
11
+ *
12
+ * No React and no `@interop/was-client` imports -- only RxDB (the replication
13
+ * engine being wrapped) and the injected port. This is the seam that keeps the
14
+ * WAS access injectable.
15
+ */
16
+ import { type RxReplicationState } from 'rxdb/plugins/replication';
17
+ import type { RxCollection } from 'rxdb/plugins/core';
18
+ import type { SyncCheckpoint, SyncedDoc, WasSyncPort } from './types.js';
19
+ /**
20
+ * Starts (or configures) replication of one RxDB collection against a remote WAS
21
+ * Collection. Poll-based only -- no `pull.stream$` (live streaming is deferred
22
+ * server-side); RxDB's own `retryTime` backoff and `error$` are the reachability
23
+ * signal (the replication attempt is the probe).
24
+ *
25
+ * @param options {object}
26
+ * @param options.rxCollection {RxCollection<SyncedDoc>} the local replica
27
+ * @param options.wasPort {WasSyncPort} injected WAS access
28
+ * @param options.replicationIdentifier {string} stable id (include the server
29
+ * URL + collection) so RxDB can resume across reloads
30
+ * @param [options.batchSize] {number} pull `limit` / push batch (default 100)
31
+ * @param [options.retryTime] {number} ms backoff between failed cycles
32
+ * @param [options.live] {boolean} ongoing (default true) vs one-shot
33
+ * @param [options.autoStart] {boolean} start immediately (default true)
34
+ * @param [options.deletedField] {string} RxDB deleted flag (default `_deleted`)
35
+ * @returns {RxReplicationState<SyncedDoc, SyncCheckpoint>}
36
+ */
37
+ export declare function createWasReplication({ rxCollection, wasPort, replicationIdentifier, batchSize, retryTime, live, autoStart, deletedField }: {
38
+ rxCollection: RxCollection<SyncedDoc>;
39
+ wasPort: WasSyncPort;
40
+ replicationIdentifier: string;
41
+ batchSize?: number;
42
+ retryTime?: number;
43
+ live?: boolean;
44
+ autoStart?: boolean;
45
+ deletedField?: string;
46
+ }): RxReplicationState<SyncedDoc, SyncCheckpoint>;
47
+ //# sourceMappingURL=wasReplication.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasReplication.d.ts","sourceRoot":"","sources":["../../src/sync/wasReplication.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAIxE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,YAAY,EACZ,OAAO,EACP,qBAAqB,EACrB,SAAe,EACf,SAAS,EACT,IAAW,EACX,SAAgB,EAChB,YAAyB,EAC1B,EAAE;IACD,YAAY,EAAE,YAAY,CAAC,SAAS,CAAC,CAAA;IACrC,OAAO,EAAE,WAAW,CAAA;IACpB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB,GAAG,kBAAkB,CAAC,SAAS,EAAE,cAAc,CAAC,CAiBhD"}
@@ -0,0 +1,55 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * `createWasReplication` -- wires an RxDB collection to a remote WAS Collection
6
+ * through the collection-agnostic pull/push handlers. This is the single public
7
+ * entry point of the sync module; the caller supplies an already-open RxDB
8
+ * collection and a {@link WasSyncPort} (its only WAS dependency), and gets back
9
+ * the live `RxReplicationState` to observe (`error$` / `active$`) and control
10
+ * (`reSync()` / `cancel()`).
11
+ *
12
+ * No React and no `@interop/was-client` imports -- only RxDB (the replication
13
+ * engine being wrapped) and the injected port. This is the seam that keeps the
14
+ * WAS access injectable.
15
+ */
16
+ import { replicateRxCollection } from 'rxdb/plugins/replication';
17
+ import { createPullHandler } from './changesQuery.js';
18
+ import { createPushHandler } from './pushWrites.js';
19
+ /**
20
+ * Starts (or configures) replication of one RxDB collection against a remote WAS
21
+ * Collection. Poll-based only -- no `pull.stream$` (live streaming is deferred
22
+ * server-side); RxDB's own `retryTime` backoff and `error$` are the reachability
23
+ * signal (the replication attempt is the probe).
24
+ *
25
+ * @param options {object}
26
+ * @param options.rxCollection {RxCollection<SyncedDoc>} the local replica
27
+ * @param options.wasPort {WasSyncPort} injected WAS access
28
+ * @param options.replicationIdentifier {string} stable id (include the server
29
+ * URL + collection) so RxDB can resume across reloads
30
+ * @param [options.batchSize] {number} pull `limit` / push batch (default 100)
31
+ * @param [options.retryTime] {number} ms backoff between failed cycles
32
+ * @param [options.live] {boolean} ongoing (default true) vs one-shot
33
+ * @param [options.autoStart] {boolean} start immediately (default true)
34
+ * @param [options.deletedField] {string} RxDB deleted flag (default `_deleted`)
35
+ * @returns {RxReplicationState<SyncedDoc, SyncCheckpoint>}
36
+ */
37
+ export function createWasReplication({ rxCollection, wasPort, replicationIdentifier, batchSize = 100, retryTime, live = true, autoStart = true, deletedField = '_deleted' }) {
38
+ return replicateRxCollection({
39
+ replicationIdentifier,
40
+ collection: rxCollection,
41
+ deletedField,
42
+ live,
43
+ autoStart,
44
+ ...(retryTime !== undefined && { retryTime }),
45
+ pull: {
46
+ handler: createPullHandler(wasPort),
47
+ batchSize
48
+ },
49
+ push: {
50
+ handler: createPushHandler(wasPort),
51
+ batchSize
52
+ }
53
+ });
54
+ }
55
+ //# sourceMappingURL=wasReplication.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasReplication.js","sourceRoot":"","sources":["../../src/sync/wasReplication.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;GAWG;AACH,OAAO,EACL,qBAAqB,EAEtB,MAAM,0BAA0B,CAAA;AAGjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AACrD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AAEnD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,oBAAoB,CAAC,EACnC,YAAY,EACZ,OAAO,EACP,qBAAqB,EACrB,SAAS,GAAG,GAAG,EACf,SAAS,EACT,IAAI,GAAG,IAAI,EACX,SAAS,GAAG,IAAI,EAChB,YAAY,GAAG,UAAU,EAU1B;IACC,OAAO,qBAAqB,CAA4B;QACtD,qBAAqB;QACrB,UAAU,EAAE,YAAY;QACxB,YAAY;QACZ,IAAI;QACJ,SAAS;QACT,GAAG,CAAC,SAAS,KAAK,SAAS,IAAI,EAAE,SAAS,EAAE,CAAC;QAC7C,IAAI,EAAE;YACJ,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC;YACnC,SAAS;SACV;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,iBAAiB,CAAC,OAAO,CAAC;YACnC,SAAS;SACV;KACF,CAAC,CAAA;AACJ,CAAC"}
@@ -0,0 +1,45 @@
1
+ /*!
2
+ * Copyright (c) 2026 Interop Alliance. All rights reserved.
3
+ */
4
+ /**
5
+ * The app-side seam between the generic sync adapter and `@interop/was-client`.
6
+ * Implements the `WasSyncPort` interface for one remote WAS Collection using the
7
+ * raw, signed `was.request()` escape hatch.
8
+ *
9
+ * Using `request()` (rather than the `Resource` / `Collection` handles) is
10
+ * deliberate: it moves the stored body VERBATIM, bypassing the encryption codec.
11
+ * The `changes` feed already ships opaque stored bodies (plaintext for a
12
+ * plaintext collection, the EDV envelope for an encrypted one), and the push
13
+ * side must write those same bytes back unchanged -- running them through
14
+ * `resource.put()` would re-encrypt an already-encrypted envelope. Encrypt /
15
+ * decrypt stays a read/write-time concern above this layer; this port is
16
+ * collection-agnostic and never touches keys.
17
+ *
18
+ * Conditional writes ride the server's monotonic `version` (content) and
19
+ * `metaVersion` (metadata) ETags, which the reference server enforces uniformly
20
+ * for plaintext and encrypted resources alike -- so there is no plaintext-vs-
21
+ * encrypted fork here.
22
+ */
23
+ import type { WasClient } from '@interop/was-client';
24
+ import type { IZcap } from '@interop/data-integrity-core';
25
+ import { type WasSyncPort } from './types.js';
26
+ /**
27
+ * Builds a `WasSyncPort` bound to a single Space + Collection on the remote WAS
28
+ * server, backed by the session's signed `WasClient`.
29
+ *
30
+ * @param options {object}
31
+ * @param options.was {WasClient} the session client (holds the signer)
32
+ * @param options.spaceId {string}
33
+ * @param options.collectionId {string} the WAS collection id (e.g. `public-credentials`)
34
+ * @param [options.capability] {IZcap} the delegated session capability for
35
+ * this collection (a restored `delegated` tier session); absent in the full
36
+ * tier, where requests invoke root capabilities
37
+ * @returns {WasSyncPort}
38
+ */
39
+ export declare function createWasSyncPort({ was, spaceId, collectionId, capability }: {
40
+ was: WasClient;
41
+ spaceId: string;
42
+ collectionId: string;
43
+ capability?: IZcap;
44
+ }): WasSyncPort;
45
+ //# sourceMappingURL=wasSyncPort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasSyncPort.d.ts","sourceRoot":"","sources":["../../src/sync/wasSyncPort.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAA;AACzD,OAAO,EAKL,KAAK,WAAW,EAEjB,MAAM,YAAY,CAAA;AAgCnB;;;;;;;;;;;;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,WAAW,CA0Jd"}
@@ -0,0 +1,170 @@
1
+ import { WasSyncConflictError } from './types.js';
2
+ /**
3
+ * Extracts an HTTP status from a raw ky/ezcap error. `was.request()` rejects on
4
+ * any non-2xx with `err.status` set (see `@interop/http-client`'s error
5
+ * normaliser); this reads it defensively from either location.
6
+ *
7
+ * @param err {unknown}
8
+ * @returns {number | undefined}
9
+ */
10
+ function errorStatus(err) {
11
+ return (err.status ??
12
+ err.response?.status);
13
+ }
14
+ /**
15
+ * Parses a quoted strong ETag (`"3"`) into its numeric revision, or `undefined`
16
+ * when the header is absent (the resource has no such revision yet).
17
+ *
18
+ * @param etag {string | null}
19
+ * @returns {number | undefined}
20
+ */
21
+ function parseEtag(etag) {
22
+ if (!etag) {
23
+ return undefined;
24
+ }
25
+ const revision = Number(etag.replace(/"/g, ''));
26
+ return Number.isFinite(revision) ? revision : undefined;
27
+ }
28
+ /**
29
+ * Builds a `WasSyncPort` bound to a single Space + Collection on the remote WAS
30
+ * server, backed by the session's signed `WasClient`.
31
+ *
32
+ * @param options {object}
33
+ * @param options.was {WasClient} the session client (holds the signer)
34
+ * @param options.spaceId {string}
35
+ * @param options.collectionId {string} the WAS collection id (e.g. `public-credentials`)
36
+ * @param [options.capability] {IZcap} the delegated session capability for
37
+ * this collection (a restored `delegated` tier session); absent in the full
38
+ * tier, where requests invoke root capabilities
39
+ * @returns {WasSyncPort}
40
+ */
41
+ export function createWasSyncPort({ was, spaceId, collectionId, capability }) {
42
+ const collectionPath = `/space/${spaceId}/${collectionId}`;
43
+ const resourcePath = (id) => `${collectionPath}/${encodeURIComponent(id)}`;
44
+ /**
45
+ * Builds the conditional-write headers from the port's precondition options.
46
+ */
47
+ const writeHeaders = ({ ifMatch, ifNoneMatch }) => {
48
+ const headers = {};
49
+ if (ifMatch !== undefined) {
50
+ headers['if-match'] = ifMatch;
51
+ }
52
+ if (ifNoneMatch) {
53
+ headers['if-none-match'] = '*';
54
+ }
55
+ return Object.keys(headers).length > 0 ? headers : undefined;
56
+ };
57
+ /**
58
+ * Runs a conditional write, mapping the server's `412 precondition-failed`
59
+ * into the core's `WasSyncConflictError` and letting all else propagate.
60
+ */
61
+ const conditionalWrite = async (run) => {
62
+ try {
63
+ await run();
64
+ }
65
+ catch (err) {
66
+ if (errorStatus(err) === 412) {
67
+ throw new WasSyncConflictError();
68
+ }
69
+ throw err;
70
+ }
71
+ };
72
+ return {
73
+ async query({ checkpoint, limit }) {
74
+ const response = await was.request({
75
+ capability,
76
+ path: `${collectionPath}/query`,
77
+ method: 'POST',
78
+ json: {
79
+ profile: 'changes',
80
+ ...(checkpoint !== undefined && { checkpoint }),
81
+ limit
82
+ }
83
+ });
84
+ return response.data;
85
+ },
86
+ async putContent({ id, data, ifMatch, ifNoneMatch }) {
87
+ await conditionalWrite(() => was.request({
88
+ capability,
89
+ path: resourcePath(id),
90
+ method: 'PUT',
91
+ json: data,
92
+ headers: writeHeaders({ ifMatch, ifNoneMatch })
93
+ }));
94
+ },
95
+ async deleteContent({ id, ifMatch }) {
96
+ await conditionalWrite(() => was.request({
97
+ capability,
98
+ path: resourcePath(id),
99
+ method: 'DELETE',
100
+ headers: writeHeaders({ ifMatch })
101
+ }));
102
+ },
103
+ async putMeta({ id, custom, ifMatch, ifNoneMatch }) {
104
+ await conditionalWrite(() => was.request({
105
+ capability,
106
+ path: `${resourcePath(id)}/meta`,
107
+ method: 'PUT',
108
+ json: { custom },
109
+ headers: writeHeaders({ ifMatch, ifNoneMatch })
110
+ }));
111
+ },
112
+ async get({ id }) {
113
+ // Content re-read: raw GET returns the stored body verbatim (no decrypt)
114
+ // and the content `version` in the ETag. A 404 means the resource is gone
115
+ // (or tombstoned) -- report absent so the core synthesizes a tombstone.
116
+ let contentResponse;
117
+ try {
118
+ contentResponse = await was.request({
119
+ capability,
120
+ path: resourcePath(id),
121
+ method: 'GET'
122
+ });
123
+ }
124
+ catch (err) {
125
+ if (errorStatus(err) === 404) {
126
+ return null;
127
+ }
128
+ throw err;
129
+ }
130
+ const master = {
131
+ version: parseEtag(contentResponse.headers.get('etag')) ?? 0,
132
+ // Filled from the `/meta` body's server-managed `updatedAt` below; the
133
+ // change feed remains the authority on ordering, so this only feeds the
134
+ // one-off conflict entry and is corrected on the next pull.
135
+ updatedAt: '',
136
+ deleted: false,
137
+ data: contentResponse.data
138
+ };
139
+ // Metadata re-read: the `/meta` body carries the server-managed
140
+ // `updatedAt` plus the user-writable `custom` (opaque), and its own
141
+ // `metaVersion` ETag (absent until metadata has been written).
142
+ try {
143
+ const metaResponse = await was.request({
144
+ capability,
145
+ path: `${resourcePath(id)}/meta`,
146
+ method: 'GET'
147
+ });
148
+ const metaBody = metaResponse.data;
149
+ if (metaBody?.updatedAt) {
150
+ master.updatedAt = metaBody.updatedAt;
151
+ }
152
+ const metaVersion = parseEtag(metaResponse.headers.get('etag'));
153
+ if (metaVersion !== undefined) {
154
+ master.metaVersion = metaVersion;
155
+ }
156
+ if (metaBody?.custom !== undefined) {
157
+ master.custom = metaBody.custom;
158
+ }
159
+ }
160
+ catch (err) {
161
+ // Metadata is optional; only a hard error (not 404) should propagate.
162
+ if (errorStatus(err) !== 404) {
163
+ throw err;
164
+ }
165
+ }
166
+ return master;
167
+ }
168
+ };
169
+ }
170
+ //# sourceMappingURL=wasSyncPort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wasSyncPort.js","sourceRoot":"","sources":["../../src/sync/wasSyncPort.ts"],"names":[],"mappings":"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"}