or3-provider-sqlite 0.0.6 → 0.0.8
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/README.md
CHANGED
|
@@ -146,7 +146,7 @@ All tables use snake_case aligned with the sync wire format.
|
|
|
146
146
|
|
|
147
147
|
### Sync semantics
|
|
148
148
|
|
|
149
|
-
- **Push**: validates ops → checks `op_id` idempotency → allocates contiguous `server_version` block → writes change_log → applies LWW to materialized tables → upserts tombstones for deletes
|
|
149
|
+
- **Push**: validates ops (including a 256 KB serialized payload ceiling per operation) → checks `op_id` idempotency → allocates contiguous `server_version` block → writes change_log → applies LWW to materialized tables → upserts tombstones for deletes
|
|
150
150
|
- **Pull**: returns ordered changes for `server_version > cursor` with limit/pagination and optional table filtering
|
|
151
151
|
- **Snapshot**: captures canonical live rows and current tombstones at one `highWatermark`, then serves immutable, keyset-paginated pages ordered by `(tableName, pk, kind)`
|
|
152
152
|
- **Cursor**: forward-only per-device cursor tracking
|
package/dist/module.json
CHANGED
|
@@ -243,14 +243,7 @@ async function importRuntimeModule(moduleName) {
|
|
|
243
243
|
return imported;
|
|
244
244
|
}
|
|
245
245
|
async function importCloudflareWorkersModule() {
|
|
246
|
-
|
|
247
|
-
/* @vite-ignore */
|
|
248
|
-
"cloudflare:workers"
|
|
249
|
-
);
|
|
250
|
-
if (!isRecord(imported)) {
|
|
251
|
-
throw new Error("cloudflare:workers did not export an object.");
|
|
252
|
-
}
|
|
253
|
-
return imported;
|
|
246
|
+
return importRuntimeModule("cloudflare:workers");
|
|
254
247
|
}
|
|
255
248
|
function isRecord(value) {
|
|
256
249
|
return typeof value === "object" && value !== null;
|
|
@@ -277,10 +270,7 @@ async function createBetterSqliteDatabase(path) {
|
|
|
277
270
|
async function createBunSqliteDatabase(path) {
|
|
278
271
|
let imported;
|
|
279
272
|
try {
|
|
280
|
-
imported = await
|
|
281
|
-
/* @vite-ignore */
|
|
282
|
-
"bun:sqlite"
|
|
283
|
-
);
|
|
273
|
+
imported = await importRuntimeModule("bun:sqlite");
|
|
284
274
|
} catch (error) {
|
|
285
275
|
throw new Error(
|
|
286
276
|
"OR3_SQLITE_DRIVER=bun requires Bun and its built-in bun:sqlite module.",
|
|
@@ -21,6 +21,7 @@ const SNAPSHOT_TTL_SECONDS = 60 * 60;
|
|
|
21
21
|
const SESSION_CONTEXT_KEY_PREFIX = "__or3_session_context_";
|
|
22
22
|
const MIN_SYNC_RETENTION_SECONDS = 60 * 60;
|
|
23
23
|
const MAX_SYNC_RETENTION_SECONDS = 365 * 24 * 60 * 60;
|
|
24
|
+
const MAX_SYNC_PAYLOAD_BYTES = 256 * 1024;
|
|
24
25
|
function uid() {
|
|
25
26
|
return globalThis.crypto.randomUUID();
|
|
26
27
|
}
|
|
@@ -56,11 +57,15 @@ function validatePushOperation(workspaceId, op) {
|
|
|
56
57
|
}
|
|
57
58
|
const payload = op.payload;
|
|
58
59
|
if (!payload) return void 0;
|
|
60
|
+
let serializedPayload;
|
|
59
61
|
try {
|
|
60
|
-
JSON.stringify(payload);
|
|
62
|
+
serializedPayload = JSON.stringify(payload);
|
|
61
63
|
} catch {
|
|
62
64
|
return `Invalid payload for ${op.tableName}: payload is not serializable`;
|
|
63
65
|
}
|
|
66
|
+
if (new TextEncoder().encode(serializedPayload).byteLength > MAX_SYNC_PAYLOAD_BYTES) {
|
|
67
|
+
return `Payload too large for ${op.tableName}: exceeds ${MAX_SYNC_PAYLOAD_BYTES} bytes`;
|
|
68
|
+
}
|
|
64
69
|
if ("_id" in payload) return `Invalid payload for ${op.tableName}: '_id' is immutable`;
|
|
65
70
|
if ("workspace_id" in payload && payload.workspace_id !== workspaceId) {
|
|
66
71
|
return `Invalid payload for ${op.tableName}: 'workspace_id' is immutable`;
|