@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.
- package/LICENSE.md +20 -0
- package/README.md +410 -0
- package/dist/auth/chapi.d.ts +43 -0
- package/dist/auth/chapi.d.ts.map +1 -0
- package/dist/auth/chapi.js +107 -0
- package/dist/auth/chapi.js.map +1 -0
- package/dist/auth/loginFlow.d.ts +93 -0
- package/dist/auth/loginFlow.d.ts.map +1 -0
- package/dist/auth/loginFlow.js +149 -0
- package/dist/auth/loginFlow.js.map +1 -0
- package/dist/auth/loginRequest.d.ts +66 -0
- package/dist/auth/loginRequest.d.ts.map +1 -0
- package/dist/auth/loginRequest.js +83 -0
- package/dist/auth/loginRequest.js.map +1 -0
- package/dist/auth/verifyResponse.d.ts +52 -0
- package/dist/auth/verifyResponse.d.ts.map +1 -0
- package/dist/auth/verifyResponse.js +138 -0
- package/dist/auth/verifyResponse.js.map +1 -0
- package/dist/auth/verifyResponse.test.d.ts +2 -0
- package/dist/auth/verifyResponse.test.d.ts.map +1 -0
- package/dist/auth/verifyResponse.test.js +282 -0
- package/dist/auth/verifyResponse.test.js.map +1 -0
- package/dist/auth/walletRequestTypes.d.ts +143 -0
- package/dist/auth/walletRequestTypes.d.ts.map +1 -0
- package/dist/auth/walletRequestTypes.js +2 -0
- package/dist/auth/walletRequestTypes.js.map +1 -0
- package/dist/config.d.ts +150 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +27 -0
- package/dist/config.js.map +1 -0
- package/dist/dev/cli.d.ts +16 -0
- package/dist/dev/cli.d.ts.map +1 -0
- package/dist/dev/cli.js +122 -0
- package/dist/dev/cli.js.map +1 -0
- package/dist/dev/cli.test.d.ts +2 -0
- package/dist/dev/cli.test.d.ts.map +1 -0
- package/dist/dev/cli.test.js +39 -0
- package/dist/dev/cli.test.js.map +1 -0
- package/dist/dev/index.d.ts +10 -0
- package/dist/dev/index.d.ts.map +1 -0
- package/dist/dev/index.js +10 -0
- package/dist/dev/index.js.map +1 -0
- package/dist/dev/provisionDevGrants.d.ts +73 -0
- package/dist/dev/provisionDevGrants.d.ts.map +1 -0
- package/dist/dev/provisionDevGrants.js +176 -0
- package/dist/dev/provisionDevGrants.js.map +1 -0
- package/dist/grants.d.ts +59 -0
- package/dist/grants.d.ts.map +1 -0
- package/dist/grants.js +82 -0
- package/dist/grants.js.map +1 -0
- package/dist/grants.test.d.ts +2 -0
- package/dist/grants.test.d.ts.map +1 -0
- package/dist/grants.test.js +79 -0
- package/dist/grants.test.js.map +1 -0
- package/dist/identity/agents.d.ts +99 -0
- package/dist/identity/agents.d.ts.map +1 -0
- package/dist/identity/agents.js +132 -0
- package/dist/identity/agents.js.map +1 -0
- package/dist/identity/appSession.d.ts +78 -0
- package/dist/identity/appSession.d.ts.map +1 -0
- package/dist/identity/appSession.js +93 -0
- package/dist/identity/appSession.js.map +1 -0
- package/dist/identity/documentLoader.d.ts +20 -0
- package/dist/identity/documentLoader.d.ts.map +1 -0
- package/dist/identity/documentLoader.js +99 -0
- package/dist/identity/documentLoader.js.map +1 -0
- package/dist/identity/initAppSession.d.ts +27 -0
- package/dist/identity/initAppSession.d.ts.map +1 -0
- package/dist/identity/initAppSession.js +30 -0
- package/dist/identity/initAppSession.js.map +1 -0
- package/dist/identity/seedCredential.d.ts +74 -0
- package/dist/identity/seedCredential.d.ts.map +1 -0
- package/dist/identity/seedCredential.js +165 -0
- package/dist/identity/seedCredential.js.map +1 -0
- package/dist/identity/seedCredential.test.d.ts +2 -0
- package/dist/identity/seedCredential.test.d.ts.map +1 -0
- package/dist/identity/seedCredential.test.js +205 -0
- package/dist/identity/seedCredential.test.js.map +1 -0
- package/dist/identity/seedStore.d.ts +27 -0
- package/dist/identity/seedStore.d.ts.map +1 -0
- package/dist/identity/seedStore.js +74 -0
- package/dist/identity/seedStore.js.map +1 -0
- package/dist/index.d.ts +37 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +46 -0
- package/dist/index.js.map +1 -0
- package/dist/mui/ProtectedRoute.d.ts +10 -0
- package/dist/mui/ProtectedRoute.d.ts.map +1 -0
- package/dist/mui/ProtectedRoute.js +54 -0
- package/dist/mui/ProtectedRoute.js.map +1 -0
- package/dist/mui/ReconnectBanner.d.ts +2 -0
- package/dist/mui/ReconnectBanner.d.ts.map +1 -0
- package/dist/mui/ReconnectBanner.js +20 -0
- package/dist/mui/ReconnectBanner.js.map +1 -0
- package/dist/mui/SyncStatusChip.d.ts +2 -0
- package/dist/mui/SyncStatusChip.d.ts.map +1 -0
- package/dist/mui/SyncStatusChip.js +27 -0
- package/dist/mui/SyncStatusChip.js.map +1 -0
- package/dist/mui/index.d.ts +12 -0
- package/dist/mui/index.d.ts.map +1 -0
- package/dist/mui/index.js +12 -0
- package/dist/mui/index.js.map +1 -0
- package/dist/react/WasSessionProvider.d.ts +36 -0
- package/dist/react/WasSessionProvider.d.ts.map +1 -0
- package/dist/react/WasSessionProvider.js +35 -0
- package/dist/react/WasSessionProvider.js.map +1 -0
- package/dist/react/hooks.d.ts +66 -0
- package/dist/react/hooks.d.ts.map +1 -0
- package/dist/react/hooks.js +121 -0
- package/dist/react/hooks.js.map +1 -0
- package/dist/react/index.d.ts +11 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +11 -0
- package/dist/react/index.js.map +1 -0
- package/dist/session/appReadyStore.d.ts +10 -0
- package/dist/session/appReadyStore.d.ts.map +1 -0
- package/dist/session/appReadyStore.js +22 -0
- package/dist/session/appReadyStore.js.map +1 -0
- package/dist/session/authStore.d.ts +71 -0
- package/dist/session/authStore.d.ts.map +1 -0
- package/dist/session/authStore.js +347 -0
- package/dist/session/authStore.js.map +1 -0
- package/dist/session/index.d.ts +10 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +10 -0
- package/dist/session/index.js.map +1 -0
- package/dist/storage/entityStore.d.ts +51 -0
- package/dist/storage/entityStore.d.ts.map +1 -0
- package/dist/storage/entityStore.js +78 -0
- package/dist/storage/entityStore.js.map +1 -0
- package/dist/storage/localStore.d.ts +144 -0
- package/dist/storage/localStore.d.ts.map +1 -0
- package/dist/storage/localStore.js +289 -0
- package/dist/storage/localStore.js.map +1 -0
- package/dist/storage/rehydrate.d.ts +56 -0
- package/dist/storage/rehydrate.d.ts.map +1 -0
- package/dist/storage/rehydrate.js +87 -0
- package/dist/storage/rehydrate.js.map +1 -0
- package/dist/storage/rehydrate.test.d.ts +2 -0
- package/dist/storage/rehydrate.test.d.ts.map +1 -0
- package/dist/storage/rehydrate.test.js +172 -0
- package/dist/storage/rehydrate.test.js.map +1 -0
- package/dist/storage/storageManager.d.ts +39 -0
- package/dist/storage/storageManager.d.ts.map +1 -0
- package/dist/storage/storageManager.js +68 -0
- package/dist/storage/storageManager.js.map +1 -0
- package/dist/storage/syncController.d.ts +79 -0
- package/dist/storage/syncController.d.ts.map +1 -0
- package/dist/storage/syncController.js +189 -0
- package/dist/storage/syncController.js.map +1 -0
- package/dist/storage/syncStatusStore.d.ts +17 -0
- package/dist/storage/syncStatusStore.d.ts.map +1 -0
- package/dist/storage/syncStatusStore.js +19 -0
- package/dist/storage/syncStatusStore.js.map +1 -0
- package/dist/storage/wasRemoteStore.d.ts +73 -0
- package/dist/storage/wasRemoteStore.d.ts.map +1 -0
- package/dist/storage/wasRemoteStore.js +76 -0
- package/dist/storage/wasRemoteStore.js.map +1 -0
- package/dist/storage/wasSync.d.ts +42 -0
- package/dist/storage/wasSync.d.ts.map +1 -0
- package/dist/storage/wasSync.js +34 -0
- package/dist/storage/wasSync.js.map +1 -0
- package/dist/sync/changesQuery.d.ts +44 -0
- package/dist/sync/changesQuery.d.ts.map +1 -0
- package/dist/sync/changesQuery.js +61 -0
- package/dist/sync/changesQuery.js.map +1 -0
- package/dist/sync/changesQuery.test.d.ts +2 -0
- package/dist/sync/changesQuery.test.d.ts.map +1 -0
- package/dist/sync/changesQuery.test.js +145 -0
- package/dist/sync/changesQuery.test.js.map +1 -0
- package/dist/sync/docCipher.d.ts +68 -0
- package/dist/sync/docCipher.d.ts.map +1 -0
- package/dist/sync/docCipher.js +89 -0
- package/dist/sync/docCipher.js.map +1 -0
- package/dist/sync/feedMasterPort.d.ts +30 -0
- package/dist/sync/feedMasterPort.d.ts.map +1 -0
- package/dist/sync/feedMasterPort.js +58 -0
- package/dist/sync/feedMasterPort.js.map +1 -0
- package/dist/sync/index.d.ts +21 -0
- package/dist/sync/index.d.ts.map +1 -0
- package/dist/sync/index.js +21 -0
- package/dist/sync/index.js.map +1 -0
- package/dist/sync/lww.d.ts +29 -0
- package/dist/sync/lww.d.ts.map +1 -0
- package/dist/sync/lww.js +28 -0
- package/dist/sync/lww.js.map +1 -0
- package/dist/sync/lww.test.d.ts +2 -0
- package/dist/sync/lww.test.d.ts.map +1 -0
- package/dist/sync/lww.test.js +28 -0
- package/dist/sync/lww.test.js.map +1 -0
- package/dist/sync/lwwConflictHandler.d.ts +49 -0
- package/dist/sync/lwwConflictHandler.d.ts.map +1 -0
- package/dist/sync/lwwConflictHandler.js +65 -0
- package/dist/sync/lwwConflictHandler.js.map +1 -0
- package/dist/sync/lwwConflictHandler.test.d.ts +2 -0
- package/dist/sync/lwwConflictHandler.test.d.ts.map +1 -0
- package/dist/sync/lwwConflictHandler.test.js +78 -0
- package/dist/sync/lwwConflictHandler.test.js.map +1 -0
- package/dist/sync/pushWrites.d.ts +57 -0
- package/dist/sync/pushWrites.d.ts.map +1 -0
- package/dist/sync/pushWrites.js +159 -0
- package/dist/sync/pushWrites.js.map +1 -0
- package/dist/sync/pushWrites.test.d.ts +2 -0
- package/dist/sync/pushWrites.test.d.ts.map +1 -0
- package/dist/sync/pushWrites.test.js +287 -0
- package/dist/sync/pushWrites.test.js.map +1 -0
- package/dist/sync/syncedDocSchema.d.ts +22 -0
- package/dist/sync/syncedDocSchema.d.ts.map +1 -0
- package/dist/sync/syncedDocSchema.js +26 -0
- package/dist/sync/syncedDocSchema.js.map +1 -0
- package/dist/sync/types.d.ts +194 -0
- package/dist/sync/types.d.ts.map +1 -0
- package/dist/sync/types.js +36 -0
- package/dist/sync/types.js.map +1 -0
- package/dist/sync/wasReplication.d.ts +47 -0
- package/dist/sync/wasReplication.d.ts.map +1 -0
- package/dist/sync/wasReplication.js +55 -0
- package/dist/sync/wasReplication.js.map +1 -0
- package/dist/sync/wasSyncPort.d.ts +45 -0
- package/dist/sync/wasSyncPort.d.ts.map +1 -0
- package/dist/sync/wasSyncPort.js +170 -0
- package/dist/sync/wasSyncPort.js.map +1 -0
- package/package.json +142 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { WasSyncConflictError } from './types.js';
|
|
2
|
+
/**
|
|
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.
|
|
32
|
+
*
|
|
33
|
+
* @param options {object}
|
|
34
|
+
* @param options.port {WasSyncPort}
|
|
35
|
+
* @param options.id {string}
|
|
36
|
+
* @param options.fallbackUpdatedAt {string} used if the resource is now absent
|
|
37
|
+
* @param options.fallbackVersion {number} used if the resource is now absent
|
|
38
|
+
* @returns {Promise<WithDeleted<SyncedDoc>>}
|
|
39
|
+
*/
|
|
40
|
+
async function assembleConflict({ port, id, fallbackUpdatedAt, fallbackVersion }) {
|
|
41
|
+
const master = await port.get({ id });
|
|
42
|
+
if (master === null) {
|
|
43
|
+
return {
|
|
44
|
+
id,
|
|
45
|
+
updatedAt: fallbackUpdatedAt,
|
|
46
|
+
version: fallbackVersion,
|
|
47
|
+
_deleted: true
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
const conflict = {
|
|
51
|
+
id,
|
|
52
|
+
updatedAt: master.updatedAt,
|
|
53
|
+
version: master.version,
|
|
54
|
+
_deleted: master.deleted
|
|
55
|
+
};
|
|
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
|
+
}
|
|
65
|
+
return conflict;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Sends one local change to the remote Collection as up to two conditional
|
|
69
|
+
* writes (content, then metadata). Returns the master-state conflict entry on a
|
|
70
|
+
* `412` at either step, or `null` on success.
|
|
71
|
+
*
|
|
72
|
+
* @param options {object}
|
|
73
|
+
* @param options.port {WasSyncPort}
|
|
74
|
+
* @param options.newDocumentState {WithDeleted<SyncedDoc>}
|
|
75
|
+
* @param [options.assumedMasterState] {WithDeleted<SyncedDoc>}
|
|
76
|
+
* @returns {Promise<WithDeleted<SyncedDoc> | null>}
|
|
77
|
+
*/
|
|
78
|
+
async function pushRow({ port, newDocumentState, assumedMasterState }) {
|
|
79
|
+
const { id } = newDocumentState;
|
|
80
|
+
const assumedVersion = assumedMasterState?.version;
|
|
81
|
+
const isCreate = assumedMasterState === undefined;
|
|
82
|
+
try {
|
|
83
|
+
if (newDocumentState._deleted) {
|
|
84
|
+
// Delete supersedes any metadata write: drop the content, tombstone wins.
|
|
85
|
+
await port.deleteContent({
|
|
86
|
+
id,
|
|
87
|
+
...(assumedVersion !== undefined && {
|
|
88
|
+
ifMatch: formatEtag(assumedVersion)
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
// Content half: write on create, or when the content body changed. For a
|
|
94
|
+
// content-addressed collection the update case never fires (an immutable
|
|
95
|
+
// body for a stable id), but it is handled for generality.
|
|
96
|
+
const contentChanged = isCreate || !bodiesEqual(newDocumentState.data, assumedMasterState?.data);
|
|
97
|
+
if (contentChanged) {
|
|
98
|
+
await port.putContent({
|
|
99
|
+
id,
|
|
100
|
+
data: newDocumentState.data ?? null,
|
|
101
|
+
...(isCreate
|
|
102
|
+
? { ifNoneMatch: true }
|
|
103
|
+
: assumedVersion !== undefined && {
|
|
104
|
+
ifMatch: formatEtag(assumedVersion)
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
// Metadata half: write when the resource has metadata and it changed. On a
|
|
109
|
+
// create this runs after the content write (the resource must exist first).
|
|
110
|
+
const metadataChanged = !bodiesEqual(newDocumentState.custom, assumedMasterState?.custom);
|
|
111
|
+
if (newDocumentState.custom !== undefined && metadataChanged) {
|
|
112
|
+
const assumedMetaVersion = assumedMasterState?.metaVersion;
|
|
113
|
+
await port.putMeta({
|
|
114
|
+
id,
|
|
115
|
+
custom: newDocumentState.custom,
|
|
116
|
+
...(assumedMetaVersion !== undefined
|
|
117
|
+
? { ifMatch: formatEtag(assumedMetaVersion) }
|
|
118
|
+
: { ifNoneMatch: true })
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
if (err instanceof WasSyncConflictError) {
|
|
125
|
+
return assembleConflict({
|
|
126
|
+
port,
|
|
127
|
+
id,
|
|
128
|
+
fallbackUpdatedAt: newDocumentState.updatedAt,
|
|
129
|
+
fallbackVersion: assumedVersion ?? newDocumentState.version
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// Any non-conflict error (network, 5xx, auth) propagates so RxDB retries
|
|
133
|
+
// the whole batch with backoff.
|
|
134
|
+
throw err;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Builds the RxDB push handler that fans a batch of local changes out to
|
|
139
|
+
* conditional WAS writes and returns the conflicting rows' master states.
|
|
140
|
+
*
|
|
141
|
+
* Rows are pushed concurrently; if any non-conflict error is thrown the whole
|
|
142
|
+
* batch rejects (RxDB re-sends it later), matching RxDB's all-or-nothing retry.
|
|
143
|
+
*
|
|
144
|
+
* @param port {WasSyncPort}
|
|
145
|
+
* @returns {(rows: Array<{ newDocumentState: WithDeleted<SyncedDoc>,
|
|
146
|
+
* assumedMasterState?: WithDeleted<SyncedDoc> }>) =>
|
|
147
|
+
* Promise<WithDeleted<SyncedDoc>[]>}
|
|
148
|
+
*/
|
|
149
|
+
export function createPushHandler(port) {
|
|
150
|
+
return async function push(rows) {
|
|
151
|
+
const results = await Promise.all(rows.map(row => pushRow({
|
|
152
|
+
port,
|
|
153
|
+
newDocumentState: row.newDocumentState,
|
|
154
|
+
assumedMasterState: row.assumedMasterState
|
|
155
|
+
})));
|
|
156
|
+
return results.filter((conflict) => conflict !== null);
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
//# sourceMappingURL=pushWrites.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushWrites.js","sourceRoot":"","sources":["../../src/sync/pushWrites.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushWrites.test.d.ts","sourceRoot":"","sources":["../../src/sync/pushWrites.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Unit tests for the push side of the sync adapter (conditional-write routing
|
|
6
|
+
* and the 412 conflict assembler), driven by a fake WAS port -- no server, no
|
|
7
|
+
* RxDB engine.
|
|
8
|
+
*/
|
|
9
|
+
import { describe, it, expect } from 'vitest';
|
|
10
|
+
import { createPushHandler, formatEtag } from './pushWrites.js';
|
|
11
|
+
import { WasSyncConflictError } from './types.js';
|
|
12
|
+
/**
|
|
13
|
+
* A fake port that records every write, optionally throws a conflict for a
|
|
14
|
+
* chosen (kind,id), and serves a scripted `get` master state for the re-read.
|
|
15
|
+
*/
|
|
16
|
+
function fakePushPort(options = {}) {
|
|
17
|
+
const writes = [];
|
|
18
|
+
const getCalls = [];
|
|
19
|
+
const maybeConflict = (kind, id) => {
|
|
20
|
+
if (options.conflictOn?.kind === kind && options.conflictOn.id === id) {
|
|
21
|
+
throw new WasSyncConflictError();
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
return {
|
|
25
|
+
writes,
|
|
26
|
+
getCalls,
|
|
27
|
+
async query() {
|
|
28
|
+
return { documents: [], checkpoint: null };
|
|
29
|
+
},
|
|
30
|
+
async putContent({ id, data, ifMatch, ifNoneMatch }) {
|
|
31
|
+
writes.push({ kind: 'putContent', id, data, ifMatch, ifNoneMatch });
|
|
32
|
+
maybeConflict('putContent', id);
|
|
33
|
+
},
|
|
34
|
+
async deleteContent({ id, ifMatch }) {
|
|
35
|
+
writes.push({ kind: 'deleteContent', id, ifMatch });
|
|
36
|
+
maybeConflict('deleteContent', id);
|
|
37
|
+
},
|
|
38
|
+
async putMeta({ id, custom, ifMatch, ifNoneMatch }) {
|
|
39
|
+
writes.push({ kind: 'putMeta', id, custom, ifMatch, ifNoneMatch });
|
|
40
|
+
maybeConflict('putMeta', id);
|
|
41
|
+
},
|
|
42
|
+
async get({ id }) {
|
|
43
|
+
getCalls.push(id);
|
|
44
|
+
return options.master ?? null;
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function newDoc(over) {
|
|
49
|
+
return {
|
|
50
|
+
id: 'r1',
|
|
51
|
+
updatedAt: '2026-01-01T00:00:00Z',
|
|
52
|
+
version: 0,
|
|
53
|
+
_deleted: false,
|
|
54
|
+
...over
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
describe('createPushHandler routing', () => {
|
|
58
|
+
it('creates content with If-None-Match when there is no assumed master', async () => {
|
|
59
|
+
const port = fakePushPort();
|
|
60
|
+
const push = createPushHandler(port);
|
|
61
|
+
const conflicts = await push([
|
|
62
|
+
{ newDocumentState: newDoc({ id: 'r1', data: { a: 1 } }) }
|
|
63
|
+
]);
|
|
64
|
+
expect(conflicts).toEqual([]);
|
|
65
|
+
expect(port.writes).toEqual([
|
|
66
|
+
{ kind: 'putContent', id: 'r1', data: { a: 1 }, ifNoneMatch: true }
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
it('creates content then metadata (content first) on a create with custom', async () => {
|
|
70
|
+
const port = fakePushPort();
|
|
71
|
+
const push = createPushHandler(port);
|
|
72
|
+
await push([
|
|
73
|
+
{
|
|
74
|
+
newDocumentState: newDoc({
|
|
75
|
+
id: 'r1',
|
|
76
|
+
data: { a: 1 },
|
|
77
|
+
custom: { jwe: 'x' }
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
]);
|
|
81
|
+
expect(port.writes.map(w => w.kind)).toEqual(['putContent', 'putMeta']);
|
|
82
|
+
expect(port.writes[1]).toEqual({
|
|
83
|
+
kind: 'putMeta',
|
|
84
|
+
id: 'r1',
|
|
85
|
+
custom: { jwe: 'x' },
|
|
86
|
+
ifNoneMatch: true
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
it('updates content with If-Match "<version>" when the body changed', async () => {
|
|
90
|
+
const port = fakePushPort();
|
|
91
|
+
const push = createPushHandler(port);
|
|
92
|
+
await push([
|
|
93
|
+
{
|
|
94
|
+
assumedMasterState: newDoc({ version: 5, data: { a: 1 } }),
|
|
95
|
+
newDocumentState: newDoc({ version: 5, data: { a: 2 } })
|
|
96
|
+
}
|
|
97
|
+
]);
|
|
98
|
+
expect(port.writes).toEqual([
|
|
99
|
+
{ kind: 'putContent', id: 'r1', data: { a: 2 }, ifMatch: formatEtag(5) }
|
|
100
|
+
]);
|
|
101
|
+
});
|
|
102
|
+
it('routes a metadata-only change to /meta with If-Match "<metaVersion>", no content write', async () => {
|
|
103
|
+
const port = fakePushPort();
|
|
104
|
+
const push = createPushHandler(port);
|
|
105
|
+
await push([
|
|
106
|
+
{
|
|
107
|
+
assumedMasterState: newDoc({
|
|
108
|
+
version: 5,
|
|
109
|
+
metaVersion: 2,
|
|
110
|
+
data: { a: 1 },
|
|
111
|
+
custom: { jwe: 'old' }
|
|
112
|
+
}),
|
|
113
|
+
newDocumentState: newDoc({
|
|
114
|
+
version: 5,
|
|
115
|
+
metaVersion: 2,
|
|
116
|
+
data: { a: 1 },
|
|
117
|
+
custom: { jwe: 'new' }
|
|
118
|
+
})
|
|
119
|
+
}
|
|
120
|
+
]);
|
|
121
|
+
expect(port.writes).toEqual([
|
|
122
|
+
{
|
|
123
|
+
kind: 'putMeta',
|
|
124
|
+
id: 'r1',
|
|
125
|
+
custom: { jwe: 'new' },
|
|
126
|
+
ifMatch: formatEtag(2)
|
|
127
|
+
}
|
|
128
|
+
]);
|
|
129
|
+
});
|
|
130
|
+
it('creates metadata with If-None-Match when the master has no metaVersion yet', async () => {
|
|
131
|
+
const port = fakePushPort();
|
|
132
|
+
const push = createPushHandler(port);
|
|
133
|
+
await push([
|
|
134
|
+
{
|
|
135
|
+
assumedMasterState: newDoc({ version: 5, data: { a: 1 } }),
|
|
136
|
+
newDocumentState: newDoc({
|
|
137
|
+
version: 5,
|
|
138
|
+
data: { a: 1 },
|
|
139
|
+
custom: { jwe: 'x' }
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
]);
|
|
143
|
+
expect(port.writes).toEqual([
|
|
144
|
+
{ kind: 'putMeta', id: 'r1', custom: { jwe: 'x' }, ifNoneMatch: true }
|
|
145
|
+
]);
|
|
146
|
+
});
|
|
147
|
+
it('deletes with If-Match "<version>" and skips any metadata write', async () => {
|
|
148
|
+
const port = fakePushPort();
|
|
149
|
+
const push = createPushHandler(port);
|
|
150
|
+
await push([
|
|
151
|
+
{
|
|
152
|
+
assumedMasterState: newDoc({ version: 7, data: { a: 1 } }),
|
|
153
|
+
newDocumentState: newDoc({
|
|
154
|
+
version: 7,
|
|
155
|
+
_deleted: true,
|
|
156
|
+
custom: { jwe: 'x' }
|
|
157
|
+
})
|
|
158
|
+
}
|
|
159
|
+
]);
|
|
160
|
+
expect(port.writes).toEqual([
|
|
161
|
+
{ kind: 'deleteContent', id: 'r1', ifMatch: formatEtag(7) }
|
|
162
|
+
]);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
describe('createPushHandler conflicts', () => {
|
|
166
|
+
it('re-reads and returns the master state on a 412', async () => {
|
|
167
|
+
const master = {
|
|
168
|
+
version: 9,
|
|
169
|
+
updatedAt: '2026-02-02T00:00:00Z',
|
|
170
|
+
deleted: false,
|
|
171
|
+
data: { a: 99 }
|
|
172
|
+
};
|
|
173
|
+
const port = fakePushPort({
|
|
174
|
+
conflictOn: { kind: 'putContent', id: 'r1' },
|
|
175
|
+
master
|
|
176
|
+
});
|
|
177
|
+
const push = createPushHandler(port);
|
|
178
|
+
const conflicts = await push([
|
|
179
|
+
{ newDocumentState: newDoc({ id: 'r1', data: { a: 1 } }) }
|
|
180
|
+
]);
|
|
181
|
+
expect(port.getCalls).toEqual(['r1']);
|
|
182
|
+
expect(conflicts).toEqual([
|
|
183
|
+
{
|
|
184
|
+
id: 'r1',
|
|
185
|
+
updatedAt: '2026-02-02T00:00:00Z',
|
|
186
|
+
version: 9,
|
|
187
|
+
data: { a: 99 },
|
|
188
|
+
_deleted: false
|
|
189
|
+
}
|
|
190
|
+
]);
|
|
191
|
+
});
|
|
192
|
+
it('synthesizes a tombstone conflict when the resource is now absent', async () => {
|
|
193
|
+
const port = fakePushPort({
|
|
194
|
+
conflictOn: { kind: 'deleteContent', id: 'r1' },
|
|
195
|
+
master: null
|
|
196
|
+
});
|
|
197
|
+
const push = createPushHandler(port);
|
|
198
|
+
const conflicts = await push([
|
|
199
|
+
{
|
|
200
|
+
assumedMasterState: newDoc({ version: 4, data: { a: 1 } }),
|
|
201
|
+
newDocumentState: newDoc({ version: 4, _deleted: true })
|
|
202
|
+
}
|
|
203
|
+
]);
|
|
204
|
+
expect(conflicts).toEqual([
|
|
205
|
+
{
|
|
206
|
+
id: 'r1',
|
|
207
|
+
updatedAt: '2026-01-01T00:00:00Z',
|
|
208
|
+
version: 4,
|
|
209
|
+
_deleted: true
|
|
210
|
+
}
|
|
211
|
+
]);
|
|
212
|
+
});
|
|
213
|
+
it('carries metaVersion/custom into the assembled conflict', async () => {
|
|
214
|
+
const master = {
|
|
215
|
+
version: 3,
|
|
216
|
+
metaVersion: 6,
|
|
217
|
+
updatedAt: '2026-03-03T00:00:00Z',
|
|
218
|
+
deleted: false,
|
|
219
|
+
data: { a: 1 },
|
|
220
|
+
custom: { jwe: 'srv' }
|
|
221
|
+
};
|
|
222
|
+
const port = fakePushPort({
|
|
223
|
+
conflictOn: { kind: 'putMeta', id: 'r1' },
|
|
224
|
+
master
|
|
225
|
+
});
|
|
226
|
+
const push = createPushHandler(port);
|
|
227
|
+
const conflicts = await push([
|
|
228
|
+
{
|
|
229
|
+
assumedMasterState: newDoc({
|
|
230
|
+
version: 3,
|
|
231
|
+
metaVersion: 5,
|
|
232
|
+
data: { a: 1 },
|
|
233
|
+
custom: { jwe: 'old' }
|
|
234
|
+
}),
|
|
235
|
+
newDocumentState: newDoc({
|
|
236
|
+
version: 3,
|
|
237
|
+
metaVersion: 5,
|
|
238
|
+
data: { a: 1 },
|
|
239
|
+
custom: { jwe: 'mine' }
|
|
240
|
+
})
|
|
241
|
+
}
|
|
242
|
+
]);
|
|
243
|
+
expect(conflicts[0]).toMatchObject({
|
|
244
|
+
id: 'r1',
|
|
245
|
+
version: 3,
|
|
246
|
+
metaVersion: 6,
|
|
247
|
+
custom: { jwe: 'srv' },
|
|
248
|
+
_deleted: false
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
it('propagates a non-conflict error so RxDB retries the batch', async () => {
|
|
252
|
+
const port = {
|
|
253
|
+
async query() {
|
|
254
|
+
return { documents: [], checkpoint: null };
|
|
255
|
+
},
|
|
256
|
+
async putContent() {
|
|
257
|
+
throw new Error('network down');
|
|
258
|
+
},
|
|
259
|
+
async deleteContent() { },
|
|
260
|
+
async putMeta() { },
|
|
261
|
+
async get() {
|
|
262
|
+
return null;
|
|
263
|
+
}
|
|
264
|
+
};
|
|
265
|
+
const push = createPushHandler(port);
|
|
266
|
+
await expect(push([{ newDocumentState: newDoc({ data: { a: 1 } }) }])).rejects.toThrow('network down');
|
|
267
|
+
});
|
|
268
|
+
it('processes multiple rows and returns only the conflicting ones', async () => {
|
|
269
|
+
const port = fakePushPort({
|
|
270
|
+
conflictOn: { kind: 'putContent', id: 'bad' },
|
|
271
|
+
master: {
|
|
272
|
+
version: 1,
|
|
273
|
+
updatedAt: '2026-01-05T00:00:00Z',
|
|
274
|
+
deleted: false,
|
|
275
|
+
data: { server: true }
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
const push = createPushHandler(port);
|
|
279
|
+
const conflicts = await push([
|
|
280
|
+
{ newDocumentState: newDoc({ id: 'ok', data: { a: 1 } }) },
|
|
281
|
+
{ newDocumentState: newDoc({ id: 'bad', data: { a: 2 } }) }
|
|
282
|
+
]);
|
|
283
|
+
expect(conflicts).toHaveLength(1);
|
|
284
|
+
expect(conflicts[0].id).toBe('bad');
|
|
285
|
+
});
|
|
286
|
+
});
|
|
287
|
+
//# sourceMappingURL=pushWrites.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pushWrites.test.js","sourceRoot":"","sources":["../../src/sync/pushWrites.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*!
|
|
2
|
+
* Copyright (c) 2026 Interop Alliance. All rights reserved.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* The single generic RxDB JSON schema reused across every synced collection.
|
|
6
|
+
* One shape (`{ id, updatedAt, version, metaVersion?, data?, custom? }`) carries
|
|
7
|
+
* both a content revision and an independently-versioned metadata sub-resource;
|
|
8
|
+
* `_deleted` is added by RxDB via `deletedField`. `data` / `custom` are opaque
|
|
9
|
+
* bodies (plaintext JSON, or an EDV envelope on an encrypted collection), so
|
|
10
|
+
* they are typed as free-form objects.
|
|
11
|
+
*/
|
|
12
|
+
import type { RxJsonSchema } from 'rxdb/plugins/core';
|
|
13
|
+
import type { SyncedDoc } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Returns the synced-doc schema. `id` is the primary key (the WAS resourceId);
|
|
16
|
+
* `updatedAt` is indexed because it is the change-feed sort field / checkpoint
|
|
17
|
+
* component.
|
|
18
|
+
*
|
|
19
|
+
* @returns {RxJsonSchema<SyncedDoc>}
|
|
20
|
+
*/
|
|
21
|
+
export declare function syncedDocSchema(): RxJsonSchema<SyncedDoc>;
|
|
22
|
+
//# sourceMappingURL=syncedDocSchema.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the synced-doc schema. `id` is the primary key (the WAS resourceId);
|
|
3
|
+
* `updatedAt` is indexed because it is the change-feed sort field / checkpoint
|
|
4
|
+
* component.
|
|
5
|
+
*
|
|
6
|
+
* @returns {RxJsonSchema<SyncedDoc>}
|
|
7
|
+
*/
|
|
8
|
+
export function syncedDocSchema() {
|
|
9
|
+
return {
|
|
10
|
+
version: 0,
|
|
11
|
+
primaryKey: 'id',
|
|
12
|
+
type: 'object',
|
|
13
|
+
properties: {
|
|
14
|
+
id: { type: 'string', maxLength: 256 },
|
|
15
|
+
updatedAt: { type: 'string', maxLength: 64 },
|
|
16
|
+
version: { type: 'number' },
|
|
17
|
+
metaVersion: { type: 'number' },
|
|
18
|
+
// Opaque stored bodies -- content and metadata envelopes -- moved verbatim.
|
|
19
|
+
data: { type: 'object', additionalProperties: true },
|
|
20
|
+
custom: { type: 'object', additionalProperties: true }
|
|
21
|
+
},
|
|
22
|
+
required: ['id', 'updatedAt', 'version'],
|
|
23
|
+
indexes: ['updatedAt']
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=syncedDocSchema.js.map
|
|
@@ -0,0 +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"}
|