@bitcobblers/wod-wiki-storage 0.35.2116 → 0.35.2117

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.
@@ -1,5 +1,7 @@
1
+ import { validateNoteBlocks } from '@bitcobblers/wod-wiki-core';
2
+
1
3
  // src/schema.ts
2
- var DB_VERSION = 28;
4
+ var DB_VERSION = 29;
3
5
  var COLUMN_TYPES = {
4
6
  notes: { date: "number", createdAt: "number" },
5
7
  page: { createdAt: "number" },
@@ -8,16 +10,9 @@ var COLUMN_TYPES = {
8
10
  tags: { createdAt: "number" },
9
11
  tag_types: { createdAt: "number" },
10
12
  note_tags: {},
11
- segments: {
12
- version: "number",
13
- position: "number",
14
- createdAt: "number",
15
- updatedAt: "number",
16
- isHistory: "boolean"
17
- },
13
+ block_revisions: { version: "number", savedAt: "number" },
18
14
  sessions: {
19
- segmentVersion: "number",
20
- version: "number",
15
+ blockVersion: "number",
21
16
  startTime: "number",
22
17
  endTime: "number",
23
18
  duration: "number",
@@ -30,7 +25,7 @@ var COLUMN_TYPES = {
30
25
  attachments: { createdAt: "number" },
31
26
  events: {
32
27
  timestamp: "number",
33
- segmentVersion: "number",
28
+ blockVersion: "number",
34
29
  line: "number",
35
30
  sourceStatementId: "number",
36
31
  stackLevel: "number",
@@ -43,7 +38,10 @@ var COLUMN_TYPES = {
43
38
  field_catalog_meta: {},
44
39
  efforts: { "baseAttributes.met": "number" },
45
40
  block_index: {
46
- segmentVersion: "number",
41
+ blockVersion: "number",
42
+ sourceRevision: "number",
43
+ from: "number",
44
+ to: "number",
47
45
  position: "number",
48
46
  createdAt: "number",
49
47
  isStatic: "boolean"
@@ -90,17 +88,12 @@ var STORE_DEFS = [
90
88
  { name: "by-note-tag", keyPath: ["noteId", "tagId"], unique: true },
91
89
  { name: "by-user", keyPath: ["userId"] }
92
90
  ] },
93
- // 5. segments
94
- { name: "segments", keyPath: ["id", "version"], indexes: [
91
+ { name: "block_revisions", keyPath: ["noteId", "blockId", "version"], indexes: [
95
92
  { name: "by-note", keyPath: ["noteId"] },
96
- { name: "by-type", keyPath: ["dataType"] },
97
- { name: "by-page", keyPath: ["pageId"] },
98
- { name: "by-history", keyPath: ["isHistory"] },
99
- { name: "by-user", keyPath: ["userId"] }
93
+ { name: "by-block", keyPath: ["noteId", "blockId"] }
100
94
  ] },
101
95
  // 6. sessions
102
96
  { name: "sessions", keyPath: ["id"], indexes: [
103
- { name: "by-segment", keyPath: ["segmentId"] },
104
97
  { name: "by-note", keyPath: ["noteId"] },
105
98
  { name: "by-completed", keyPath: ["createdAt"] },
106
99
  { name: "by-content", keyPath: ["blockContentId"] },
@@ -109,9 +102,6 @@ var STORE_DEFS = [
109
102
  { name: "by-origin", keyPath: ["origin"] },
110
103
  { name: "by-user", keyPath: ["userId"] }
111
104
  ] },
112
- // 7. results — removed in V26: legacy alias of sessions. The V26 upgrade
113
- // migrates any residual rows into `sessions` (projecting pre-V21 data.logs
114
- // into event rows) before dropping the store; no compatibility alias.
115
105
  // 8. attachments
116
106
  { name: "attachments", keyPath: ["id"], indexes: [
117
107
  { name: "by-note", keyPath: ["noteId"] },
@@ -180,7 +170,6 @@ var USER_OWNED_STORES = [
180
170
  "tags",
181
171
  "tag_types",
182
172
  "note_tags",
183
- "segments",
184
173
  "sessions",
185
174
  "attachments",
186
175
  "events",
@@ -241,7 +230,7 @@ function rangeFromIDB(query) {
241
230
  wire.lowerOpen = query.lowerOpen === true;
242
231
  }
243
232
  if (query.upper !== void 0 && query.upper !== null) {
244
- wire.upper = query.upper;
233
+ wire.upper = Array.isArray(query.upper) ? query.upper.map((p) => Array.isArray(p) && p.length === 0 ? "\uFFFF" : p) : query.upper;
245
234
  wire.upperOpen = query.upperOpen === true;
246
235
  }
247
236
  return wire.lower !== void 0 || wire.upper !== void 0 ? wire : void 0;
@@ -273,9 +262,7 @@ function keyInRange(key, range) {
273
262
  }
274
263
  return true;
275
264
  }
276
-
277
- // src/domain.ts
278
- var DOMAIN_PROJECTION_VERSION = 1;
265
+ var DOMAIN_PROJECTION_VERSION = 2;
279
266
  function isObject(value) {
280
267
  return typeof value === "object" && value !== null && !Array.isArray(value);
281
268
  }
@@ -286,13 +273,16 @@ function finiteNumbers(row, fields) {
286
273
  return fields.every((field) => typeof row[field] === "number" && Number.isFinite(row[field]));
287
274
  }
288
275
  function isNote(value) {
289
- return isObject(value) && typeof value.id === "string" && typeof value.title === "string" && finiteNumbers(value, ["createdAt"]) && (value.date === void 0 || finiteNumbers(value, ["date"])) && optionalStrings(value, ["type", "sourceId", "catalog", "sourcePath", "seedOrigin", "seedChunkId"]) && (value.tags === void 0 || Array.isArray(value.tags) && value.tags.every((tag) => typeof tag === "string"));
276
+ if (!isObject(value) || typeof value.id !== "string" || typeof value.title !== "string" || typeof value.rawContent !== "string" || !Number.isSafeInteger(value.sourceRevision) || typeof value.sourceRevision !== "number" || value.sourceRevision < 1 || !isObject(value.blocks) || !finiteNumbers(value, ["createdAt"]) || value.date !== void 0 && !finiteNumbers(value, ["date"]) || !optionalStrings(value, ["type", "sourceId", "catalog", "sourcePath", "seedOrigin", "seedChunkId"]) || value.tags !== void 0 && (!Array.isArray(value.tags) || !value.tags.every((tag) => typeof tag === "string"))) return false;
277
+ try {
278
+ validateNoteBlocks(value.rawContent, value.blocks, value.sourceRevision);
279
+ return true;
280
+ } catch {
281
+ return false;
282
+ }
290
283
  }
291
284
  function isBlock(value) {
292
- return isObject(value) && typeof value.id === "string" && typeof value.noteId === "string" && typeof value.segmentId === "string" && finiteNumbers(value, ["segmentVersion", "createdAt"]) && typeof value.dataType === "string" && typeof value.rawContent === "string" && typeof value.noteTitle === "string" && optionalStrings(value, ["blockContentId", "sourceId", "sourcePath", "routeId"]) && (value.position === void 0 || finiteNumbers(value, ["position"])) && (value.isStatic === void 0 || typeof value.isStatic === "boolean");
293
- }
294
- function isSegment(value) {
295
- return isObject(value) && typeof value.id === "string" && typeof value.noteId === "string" && finiteNumbers(value, ["version", "createdAt"]) && typeof value.dataType === "string" && typeof value.rawContent === "string" && (value.data === null || isObject(value.data)) && optionalStrings(value, ["sourceContent", "pageId"]) && (value.position === void 0 || finiteNumbers(value, ["position"])) && (value.isHistory === void 0 || typeof value.isHistory === "boolean");
285
+ return isObject(value) && typeof value.id === "string" && typeof value.noteId === "string" && typeof value.blockId === "string" && finiteNumbers(value, ["blockVersion", "sourceRevision", "from", "to", "createdAt"]) && value.id === `${value.noteId}:${value.blockId}` && typeof value.blockVersion === "number" && Number.isSafeInteger(value.blockVersion) && value.blockVersion > 0 && typeof value.sourceRevision === "number" && Number.isSafeInteger(value.sourceRevision) && value.sourceRevision > 0 && typeof value.from === "number" && Number.isSafeInteger(value.from) && value.from >= 0 && typeof value.to === "number" && Number.isSafeInteger(value.to) && value.to > value.from && ["wod", "query", "widget", "embed"].includes(String(value.dataType)) && typeof value.rawContent === "string" && typeof value.noteTitle === "string" && optionalStrings(value, ["blockContentId", "sourceId", "sourcePath", "routeId"]) && (value.position === void 0 || finiteNumbers(value, ["position"])) && (value.isStatic === void 0 || typeof value.isStatic === "boolean");
296
286
  }
297
287
  function isTag(value) {
298
288
  return isObject(value) && typeof value.id === "string" && typeof value.label === "string" && finiteNumbers(value, ["createdAt"]) && optionalStrings(value, ["type"]);
@@ -304,7 +294,7 @@ function isLink(value) {
304
294
  return isObject(value) && typeof value.id === "string" && typeof value.noteId === "string" && typeof value.pageId === "string" && finiteNumbers(value, ["createdAt"]) && (value.position === void 0 || finiteNumbers(value, ["position"]));
305
295
  }
306
296
  function isEntry(value) {
307
- return isObject(value) && isNote(value.note) && Array.isArray(value.segments) && value.segments.every(isSegment) && Array.isArray(value.tags) && value.tags.every(isTag) && Array.isArray(value.links) && value.links.every(isLink) && Array.isArray(value.pages) && value.pages.every(isPage);
297
+ return isObject(value) && isNote(value.note) && Array.isArray(value.tags) && value.tags.every(isTag) && Array.isArray(value.links) && value.links.every(isLink) && Array.isArray(value.pages) && value.pages.every(isPage);
308
298
  }
309
299
  function parseDomainQueryResult(value, plan) {
310
300
  if (!isObject(value) || value.projectionVersion !== DOMAIN_PROJECTION_VERSION || value.plan !== plan || !Array.isArray(value.rows) || typeof value.selectedCount !== "number" || !Number.isSafeInteger(value.selectedCount) || value.selectedCount < 0 || typeof value.matchedCount !== "number" || !Number.isSafeInteger(value.matchedCount) || value.matchedCount < 0 || value.matchedCount > value.selectedCount || value.rows.length > value.matchedCount) {
@@ -325,6 +315,98 @@ function parseDomainQueryResult(value, plan) {
325
315
  throw new Error("ApiStorage: invalid domain query rows");
326
316
  }
327
317
 
318
+ // src/sql/errors.ts
319
+ var StorageError = class extends Error {
320
+ constructor(status, message, code) {
321
+ super(message);
322
+ this.status = status;
323
+ this.code = code;
324
+ this.name = "StorageError";
325
+ }
326
+ status;
327
+ code;
328
+ };
329
+ function rowsEqual(left, right) {
330
+ if (Object.is(left, right)) return true;
331
+ if (left instanceof ArrayBuffer && right instanceof ArrayBuffer) {
332
+ const a2 = new Uint8Array(left), b2 = new Uint8Array(right);
333
+ return a2.length === b2.length && a2.every((value, i) => value === b2[i]);
334
+ }
335
+ if (typeof left !== "object" || left === null || typeof right !== "object" || right === null) return false;
336
+ if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right) && left.length === right.length && left.every((value, i) => rowsEqual(value, right[i]));
337
+ const a = Object.keys(left).filter((key) => Reflect.get(left, key) !== void 0);
338
+ const b = Object.keys(right).filter((key) => Reflect.get(right, key) !== void 0);
339
+ return a.length === b.length && a.every((key) => Object.hasOwn(right, key) && rowsEqual(Reflect.get(left, key), Reflect.get(right, key)));
340
+ }
341
+ function record(value) {
342
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new StorageError(400, "storage row must be an object");
343
+ return value;
344
+ }
345
+ function validateStorageRow(store, value) {
346
+ if (store !== "notes" && store !== "block_revisions" && store !== "sessions" && store !== "block_index") return;
347
+ const row = record(value);
348
+ const positive = (field) => typeof row[field] === "number" && Number.isSafeInteger(row[field]) && row[field] > 0;
349
+ const required = (field) => typeof row[field] === "string" && row[field].length > 0;
350
+ if (store === "notes") {
351
+ if (!required("id") || typeof row.title !== "string" || typeof row.rawContent !== "string" || !positive("sourceRevision") || typeof row.createdAt !== "number" || !Number.isFinite(row.createdAt) || "segments" in row || "segmentIds" in row || row.date !== void 0 && (typeof row.date !== "number" || !Number.isFinite(row.date)) || row.seedOrigin !== void 0 && row.seedOrigin !== "seed" && row.seedOrigin !== "user" || row.seedVersion !== void 0 && !positive("seedVersion") || row.tags !== void 0 && (!Array.isArray(row.tags) || !row.tags.every((tag) => typeof tag === "string")) || ["type", "sourceId", "sourcePath", "catalog", "seedChunkId"].some((field) => row[field] !== void 0 && typeof row[field] !== "string")) {
352
+ throw new StorageError(400, "invalid whole Note", "invalid_note_blocks");
353
+ }
354
+ try {
355
+ validateNoteBlocks(row.rawContent, record(row.blocks), row.sourceRevision);
356
+ } catch (error) {
357
+ throw new StorageError(400, error instanceof Error ? error.message : "invalid block map", "invalid_note_blocks");
358
+ }
359
+ } else if (store === "block_revisions") {
360
+ if (!required("noteId") || !required("blockId") || !positive("version") || typeof row.rawContent !== "string" || typeof row.savedAt !== "number" || !Number.isFinite(row.savedAt) || !["wod", "query", "widget", "embed"].includes(String(row.kind)) || (row.kind === "wod" ? row.dialect !== "time" && row.dialect !== "log" : row.dialect !== void 0 || row.sport !== void 0) || row.sport !== void 0 && typeof row.sport !== "string") throw new StorageError(400, "invalid block revision", "invalid_note_blocks");
361
+ try {
362
+ validateNoteBlocks(row.rawContent, { [String(row.blockId)]: {
363
+ id: String(row.blockId),
364
+ kind: row.kind,
365
+ version: row.version,
366
+ sourceRevision: 1,
367
+ from: 0,
368
+ to: row.rawContent.length,
369
+ ...row.dialect === void 0 ? {} : { dialect: row.dialect },
370
+ ...row.sport === void 0 ? {} : { sport: row.sport }
371
+ } }, 1);
372
+ } catch (error) {
373
+ throw new StorageError(400, error instanceof Error ? error.message : "invalid revision source", "invalid_note_blocks");
374
+ }
375
+ } else if (store === "sessions") {
376
+ if (!required("noteId") || !required("blockId") || !positive("blockVersion") || ["segmentId", "segmentVersion", "version", "rawContent", "script", "serializedScript", "source", "data", "logs"].some((field) => field in row)) {
377
+ throw new StorageError(400, "Session requires immutable block pin", "invalid_session_pin");
378
+ }
379
+ } else if (!required("noteId") || !required("blockId") || !positive("blockVersion") || !positive("sourceRevision") || row.id !== `${row.noteId}:${row.blockId}` || !Number.isSafeInteger(row.from) || !Number.isSafeInteger(row.to) || "segmentId" in row || "segmentVersion" in row || !["wod", "query", "widget", "embed"].includes(String(row.dataType)) || typeof row.rawContent !== "string" || typeof row.noteTitle !== "string" || typeof row.from !== "number" || typeof row.to !== "number" || row.from < 0 || row.to <= row.from) {
380
+ throw new StorageError(400, "invalid actionable block projection", "invalid_note_blocks");
381
+ }
382
+ }
383
+ function validateNoteWrite(previous, value) {
384
+ if (previous === void 0 || rowsEqual(previous, value)) return;
385
+ const before = record(previous), after = record(value);
386
+ if (typeof before.sourceRevision !== "number" || typeof after.sourceRevision !== "number" || after.sourceRevision < before.sourceRevision || (!rowsEqual(before.blocks, after.blocks) || before.rawContent !== after.rawContent) && after.sourceRevision <= before.sourceRevision) throw new StorageError(409, "stale Note source revision", "transaction_conflict");
387
+ }
388
+ function validateSessionWrite(previous, value) {
389
+ if (previous === void 0) return;
390
+ const before = record(previous), after = record(value);
391
+ if (before.noteId !== after.noteId || before.blockId !== after.blockId || before.blockVersion !== after.blockVersion)
392
+ throw new StorageError(409, "Session pin is immutable", "invalid_session_pin");
393
+ }
394
+ async function validateStoredPins(notes, sessions, getRevisions) {
395
+ const keys = [];
396
+ for (const note of notes) for (const block of Object.values(note.blocks)) keys.push([note.id, block.id, block.version]);
397
+ for (const session of sessions) keys.push([session.noteId, session.blockId, session.blockVersion]);
398
+ const revisions = await getRevisions(keys);
399
+ let i = 0;
400
+ for (const note of notes) for (const block of Object.values(note.blocks)) {
401
+ const revision = revisions[i++];
402
+ if (!revision || revision.kind !== block.kind || revision.rawContent !== note.rawContent.slice(block.from, block.to) || revision.dialect !== block.dialect || revision.sport !== block.sport) throw new StorageError(409, "Note block has no matching immutable revision", "invalid_note_blocks");
403
+ }
404
+ for (let sessionIndex = 0; sessionIndex < sessions.length; sessionIndex++) {
405
+ const revision = revisions[i++];
406
+ if (!revision || revision.kind !== "wod") throw new StorageError(409, "Session pin must reference a saved workout revision", "invalid_session_pin");
407
+ }
408
+ }
409
+
328
410
  // src/overlay.ts
329
411
  var bufferSlot = (store, key) => `${store}\0${JSON.stringify(key)}`;
330
412
  function isDirty(store, buffer, cleared) {
@@ -400,6 +482,6 @@ function bufferToOps(storeNames, buffer, cleared) {
400
482
  return ops;
401
483
  }
402
484
 
403
- export { COLUMN_TYPES, DB_VERSION, DEFAULT_MEMBERSHIP_ID, DOMAIN_PROJECTION_VERSION, STORE_DEFS, USER_OWNED_STORES, bufferSlot, bufferToOps, bufferedGet, compareKeys, createDefaultMembership, encodeKey, extractKeyPart, isDirty, isRange, keyFromValue, keyInRange, overlayRows, parseDomainQueryResult, rangeFromIDB, stampUserOwned };
404
- //# sourceMappingURL=chunk-DAGT3P7M.mjs.map
405
- //# sourceMappingURL=chunk-DAGT3P7M.mjs.map
485
+ export { COLUMN_TYPES, DB_VERSION, DEFAULT_MEMBERSHIP_ID, DOMAIN_PROJECTION_VERSION, STORE_DEFS, StorageError, USER_OWNED_STORES, bufferSlot, bufferToOps, bufferedGet, compareKeys, createDefaultMembership, encodeKey, extractKeyPart, isDirty, isRange, keyFromValue, keyInRange, overlayRows, parseDomainQueryResult, rangeFromIDB, rowsEqual, stampUserOwned, validateNoteWrite, validateSessionWrite, validateStorageRow, validateStoredPins };
486
+ //# sourceMappingURL=chunk-Y576CUFQ.mjs.map
487
+ //# sourceMappingURL=chunk-Y576CUFQ.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/schema.ts","../src/membership.ts","../src/wire.ts","../src/domain.ts","../src/sql/errors.ts","../src/validation.ts","../src/overlay.ts"],"names":["a","b","validateNoteBlocks"],"mappings":"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","file":"chunk-Y576CUFQ.mjs","sourcesContent":["/** Fresh schema shared by browser, SQL and in-memory adapters. */\n\nimport type { StoreName } from './contract';\n\n// DOMAIN_PROJECTION_VERSION lives in ./domain (re-exported by the package\n// index) — deliberately not re-exported here to avoid a star-export\n// ambiguity between ./schema and ./domain.\n\nexport const DB_VERSION = 29;\n\n/**\n * Typed field metadata — column type per extracted field path, shared with\n * the API so its SQL DDL derives DOUBLE PRECISION / INTEGER / BOOLEAN /\n * TEXT from this table instead of a hardcoded per-index allowlist.\n *\n * Extraction rule (API side): a primary-key column `k<i>` takes the type of\n * STORE_DEFS store's keyPath[i]; an index column `i_<index>_<part>` takes the\n * type of that index's keyPath[part] here. Anything absent defaults to TEXT.\n * Civil-date strings stay TEXT on purpose (page.date is 'YYYY-MM-DD');\n * instants are epoch-ms numbers (notes.date, createdAt, timestamp).\n */\nexport type StorageColumnType = 'number' | 'text' | 'boolean';\n\nexport const COLUMN_TYPES: Record<StoreName, Record<string, StorageColumnType>> = {\n notes: { date: 'number', createdAt: 'number' },\n page: { createdAt: 'number' }, // page.date is a civil 'YYYY-MM-DD' string → TEXT\n page_notes: { position: 'number', createdAt: 'number' },\n tags: { createdAt: 'number' },\n tag_types: { createdAt: 'number' },\n note_tags: {},\n block_revisions: { version: 'number', savedAt: 'number' },\n sessions: {\n blockVersion: 'number',\n startTime: 'number',\n endTime: 'number',\n duration: 'number',\n roundsCompleted: 'number',\n totalRounds: 'number',\n repsCompleted: 'number',\n completed: 'boolean',\n createdAt: 'number',\n },\n attachments: { createdAt: 'number' },\n events: {\n timestamp: 'number',\n blockVersion: 'number',\n line: 'number',\n sourceStatementId: 'number',\n stackLevel: 'number',\n 'timeSpan.started': 'number',\n 'timeSpan.ended': 'number',\n },\n field_catalog: {},\n field_sources: {},\n field_values: {},\n field_catalog_meta: {},\n efforts: { 'baseAttributes.met': 'number' },\n block_index: {\n blockVersion: 'number',\n sourceRevision: 'number',\n from: 'number',\n to: 'number',\n position: 'number',\n createdAt: 'number',\n isStatic: 'boolean',\n },\n block_efforts: { createdAt: 'number', isStatic: 'boolean' },\n meta: {},\n memberships: { createdAt: 'number' },\n};\n\nexport interface IndexDef {\n name: string;\n keyPath: string[];\n unique?: boolean;\n multiEntry?: boolean;\n}\n\nexport interface StoreDef {\n name: StoreName;\n keyPath: string[];\n indexes: IndexDef[];\n /** System stores survive wipe() (identity must not be reset with data). */\n system?: boolean;\n}\n\nexport const STORE_DEFS: StoreDef[] = [\n // 1. notes\n { name: 'notes', keyPath: ['id'], indexes: [\n { name: 'by-date', keyPath: ['date'] },\n { name: 'by-created', keyPath: ['createdAt'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 2. page\n { name: 'page', keyPath: ['id'], indexes: [\n { name: 'by-date', keyPath: ['date'], unique: true },\n { name: 'by-slug', keyPath: ['slug'], unique: true },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 2b. page_notes (V22)\n { name: 'page_notes', keyPath: ['id'], indexes: [\n { name: 'by-page', keyPath: ['pageId'] },\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-page-note', keyPath: ['pageId', 'noteId'], unique: true },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 3. tags\n { name: 'tags', keyPath: ['id'], indexes: [\n { name: 'by-label', keyPath: ['label'], unique: true },\n { name: 'by-type', keyPath: ['type'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 3a. tag_types (V23)\n { name: 'tag_types', keyPath: ['id'], indexes: [\n { name: 'by-name', keyPath: ['name'], unique: true },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 4. note_tags\n { name: 'note_tags', keyPath: ['id'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-tag', keyPath: ['tagId'] },\n { name: 'by-note-tag', keyPath: ['noteId', 'tagId'], unique: true },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n { name: 'block_revisions', keyPath: ['noteId', 'blockId', 'version'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-block', keyPath: ['noteId', 'blockId'] },\n ] },\n // 6. sessions\n { name: 'sessions', keyPath: ['id'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-completed', keyPath: ['createdAt'] },\n { name: 'by-content', keyPath: ['blockContentId'] },\n { name: 'by-block', keyPath: ['blockId'] },\n { name: 'by-page', keyPath: ['pageId'] },\n { name: 'by-origin', keyPath: ['origin'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 8. attachments\n { name: 'attachments', keyPath: ['id'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-time', keyPath: ['createdAt'] },\n { name: 'by-page', keyPath: ['pageId'] },\n { name: 'by-result', keyPath: ['resultId'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 9. events\n { name: 'events', keyPath: ['id'], indexes: [\n { name: 'by-timestamp', keyPath: ['timestamp'] },\n { name: 'by-result-grain', keyPath: ['resultId', 'grain'] },\n { name: 'by-content-grain', keyPath: ['blockContentId', 'grain'] },\n { name: 'by-effort', keyPath: ['effortSlug'] },\n { name: 'by-outputType', keyPath: ['outputType'] },\n { name: 'by-grain', keyPath: ['grain'] },\n { name: 'by-metric-date', keyPath: ['metricDateKeys'], multiEntry: true },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 10. field catalog\n { name: 'field_catalog', keyPath: ['id'], indexes: [\n { name: 'by-path', keyPath: ['path'] },\n ] },\n { name: 'field_sources', keyPath: ['id'], indexes: [] },\n { name: 'field_values', keyPath: ['key'], indexes: [\n { name: 'by-field', keyPath: ['fieldId'] },\n ] },\n { name: 'field_catalog_meta', keyPath: ['id'], indexes: [] },\n // 11. efforts\n { name: 'efforts', keyPath: ['slug'], indexes: [\n { name: 'by-discipline', keyPath: ['baseAttributes.discipline'] },\n { name: 'by-source', keyPath: ['registrySource'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 12. block_index\n { name: 'block_index', keyPath: ['id'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-content', keyPath: ['blockContentId'] },\n { name: 'by-type', keyPath: ['dataType'] },\n { name: 'by-source', keyPath: ['sourceId'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 13. block_efforts\n { name: 'block_efforts', keyPath: ['id'], indexes: [\n { name: 'by-note', keyPath: ['noteId'] },\n { name: 'by-effort', keyPath: ['effortSlug'] },\n { name: 'by-block', keyPath: ['blockContentId'] },\n { name: 'by-user', keyPath: ['userId'] },\n ] },\n // 14. meta\n { name: 'meta', keyPath: ['key'], indexes: [] },\n // 15. memberships (V25, system — survives wipe; truth lives in\n // localStorage locally, in the SQL table on the API)\n { name: 'memberships', keyPath: ['id'], indexes: [], system: true },\n];\n","/**\n * membership.ts — identity contract shared by both backends.\n *\n * The single local membership (id 'default') is the owner of every\n * user-created record: adapters stamp `userId` onto rows on write (see\n * stampUserOwned), and the by-user index in STORE_DEFS is the ownership\n * crosswalk per store. Seed rows (seedOrigin === 'seed') stay unowned —\n * they are bundled content, not user data.\n */\n\nimport type { StoreName } from './contract';\nimport type { Membership } from './entities';\n\nexport const DEFAULT_MEMBERSHIP_ID = 'default';\n\nexport function createDefaultMembership(now: number = Date.now()): Membership {\n return { id: DEFAULT_MEMBERSHIP_ID, displayName: 'Anonymous', createdAt: now };\n}\n\n/** Stores that can hold user-created rows. Excluded: the pure seed catalog\n * (field_*), meta, and memberships itself. The by-user index in STORE_DEFS\n * mirrors this list — keep in lockstep. */\nexport const USER_OWNED_STORES: readonly StoreName[] = [\n 'notes', 'page', 'page_notes', 'tags', 'tag_types', 'note_tags',\n 'sessions', 'attachments', 'events',\n 'efforts', 'block_index', 'block_efforts',\n];\n\nconst STAMPABLE: Record<string, true> = Object.fromEntries(\n USER_OWNED_STORES.map((s) => [s, true as const])\n);\n\n/** Stamps `userId` onto a user-owned row. Seed rows pass through untouched;\n * already-stamped rows are returned as-is (no churn on re-put). Values in\n * non-user-owned stores are returned unchanged. */\nexport function stampUserOwned(store: StoreName, value: unknown, userId: string): unknown {\n if (!STAMPABLE[store]) return value;\n if (value === null || typeof value !== 'object' || Array.isArray(value)) return value;\n const row = value as Record<string, unknown>;\n if (row.seedOrigin === 'seed') return value;\n if (row.userId === userId) return value;\n return { ...row, userId };\n}\n","/**\n * Wire DTOs + key helpers shared by the storage client (ApiStorage) and the\n * API server. Keys are scalars or scalar tuples (keyPath order); ranges bound\n * them. Over HTTP, keys/ranges travel as urlencoded JSON query params.\n *\n * Range-typed helpers accept real IDBKeyRange instances AND plain RangeDTO\n * literals — non-IDB runtimes (Bun, node, tests) have no IDBKeyRange global,\n * so everything duck-types on field shape.\n */\n\nimport type { StoreName } from './contract';\nimport type { StoreDef } from './schema';\n\nexport type Scalar = string | number;\n\n/** Primary key: scalar for single-property keyPaths, tuple for compound. */\nexport type KeyDTO = Scalar | Scalar[];\n\nexport interface RangeDTO {\n only?: KeyDTO;\n /** Inclusive lower bound unless lowerOpen. Scalar or tuple (keyPath order). */\n lower?: KeyDTO;\n /** Inclusive upper bound unless upperOpen. Scalar or tuple (keyPath order). */\n upper?: KeyDTO;\n lowerOpen?: boolean;\n upperOpen?: boolean;\n}\n\nexport type TxOp =\n | { op: 'check'; store: StoreName; key: KeyDTO; value: unknown | null }\n | { op: 'put'; store: StoreName; value: unknown }\n | { op: 'delete'; store: StoreName; key: KeyDTO }\n | { op: 'clear'; store: StoreName };\n\n/** Anything shaped like a range: real IDBKeyRange or a plain RangeDTO literal. */\nexport function isRange(arg: unknown): arg is RangeDTO {\n return arg !== null && typeof arg === 'object' && !Array.isArray(arg) &&\n ('only' in arg || 'lower' in arg || 'upper' in arg || 'lowerOpen' in arg || 'upperOpen' in arg);\n}\n\n/** Reads one dotted property path ('a.b.c') off a row. */\nexport function extractKeyPart(value: unknown, dottedPath: string): Scalar | undefined {\n let cur: unknown = value;\n for (const part of dottedPath.split('.')) {\n if (cur === null || typeof cur !== 'object') return undefined;\n // Dynamic key on an untyped row: index-signature view is the only way to read it.\n const row = cur as Record<string, unknown>;\n if (!(part in row)) return undefined;\n cur = row[part];\n }\n if (cur === null || typeof cur === 'object' || cur === undefined) return undefined;\n return cur as Scalar; // string/number/boolean leaf narrowed to the wire subset\n}\n\n/** Extracts a row's primary key per the store's inline keyPath. */\nexport function keyFromValue(def: StoreDef, value: unknown): KeyDTO {\n const parts = def.keyPath.map((p) => extractKeyPart(value, p));\n for (const [i, part] of parts.entries()) {\n if (part === undefined) {\n throw new Error(`keyFromValue(${def.name}): keyPath part '${def.keyPath[i]}' missing on value`);\n }\n }\n // Loop above proved every element defined.\n const key = parts as Scalar[];\n return key.length === 1 ? key[0] : key;\n}\n\n/** Canonical url-safe string form of a key (also the buffer/tx match key). */\nexport function encodeKey(key: KeyDTO): string {\n return encodeURIComponent(JSON.stringify(key));\n}\n\n/**\n * Converts an IndexedDB query — bare key, IDBKeyRange, or an already-wire\n * RangeDTO — to its wire form. Duck-types: objects with lower/upper/\n * lowerOpen/upperOpen fields (real ranges or plain literals) pass through;\n * scalars and tuple arrays become {only}.\n */\nexport function rangeFromIDB(query?: IDBValidKey | IDBKeyRange | RangeDTO): RangeDTO | undefined {\n if (query === undefined) return undefined;\n if (!isRange(query)) {\n // Bare IDBValidKey (scalar/tuple; exotic keys like Date pass through lossy).\n const key = query as KeyDTO;\n return { only: key };\n }\n if (query.only !== undefined) return query;\n const wire: RangeDTO = {};\n if (query.lower !== undefined && query.lower !== null) {\n wire.lower = query.lower;\n wire.lowerOpen = query.lowerOpen === true;\n }\n if (query.upper !== undefined && query.upper !== null) {\n // IDB upper bound idiom [prefix, []] uses [] > strings; normalize [] to \\uffff on wire.\n wire.upper = Array.isArray(query.upper)\n ? (query.upper.map((p) => (Array.isArray(p) && p.length === 0 ? '\\uffff' : p)) as KeyDTO)\n : query.upper;\n wire.upperOpen = query.upperOpen === true;\n }\n return wire.lower !== undefined || wire.upper !== undefined ? wire : undefined;\n}\n\n/** IndexedDB key ordering: numbers < strings < tuples; tuples lexicographic. */\nexport function compareKeys(a: KeyDTO, b: KeyDTO): number {\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b)) return Array.isArray(a) ? 1 : -1;\n for (let i = 0; i < Math.min(a.length, b.length); i++) {\n const c = compareKeys(a[i], b[i]);\n if (c !== 0) return c;\n }\n return a.length - b.length;\n }\n if (typeof a === 'number' && typeof b === 'number') {\n return a < b ? -1 : a > b ? 1 : 0;\n }\n if (typeof a === 'number' || typeof b === 'number') return typeof a === 'number' ? -1 : 1;\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/** True when a key matches a wire range (IDB bound semantics). */\nexport function keyInRange(key: KeyDTO, range: RangeDTO): boolean {\n if (range.only !== undefined) return compareKeys(key, range.only) === 0;\n if (range.lower !== undefined) {\n const c = compareKeys(key, range.lower);\n if (c < 0 || (c === 0 && range.lowerOpen === true)) return false;\n }\n if (range.upper !== undefined) {\n const c = compareKeys(key, range.upper);\n if (c > 0 || (c === 0 && range.upperOpen === true)) return false;\n }\n return true;\n}\n","import type { BlockIndexRow, Note, Page, PageNote, Tag } from './entities';\nimport { validateNoteBlocks } from '@bitcobblers/wod-wiki-core';\n\nexport const DOMAIN_PROJECTION_VERSION = 2;\n\nexport type DomainPredicate =\n | { field: 'id' | 'noteId' | 'type' | 'catalog' | 'source' | 'tags' | 'effort'; values: string[]; negate?: boolean }\n | { field: 'text'; value: string }\n | { field: 'date'; start: number; end: number; endExclusive?: boolean }\n | { field: 'page'; value: boolean }\n | { field: 'defaultNotes'; feeds: boolean }\n | { field: 'sourceFence' };\n\nexport type DomainOrder = {\n field: 'id' | 'createdAt' | 'date' | 'title' | 'noteTitle' | 'dataType' | 'position';\n direction: 'asc' | 'desc';\n};\n\nexport type DomainQuery = {\n plan: 'notes' | 'blocks' | 'entries';\n selection?: DomainPredicate[];\n filters?: DomainPredicate[];\n order?: DomainOrder[];\n offset?: number;\n limit?: number;\n};\n\nexport interface DomainEntry {\n note: Note;\n tags: Tag[];\n links: PageNote[];\n pages: Page[];\n}\n\nexport type DomainQueryResult = {\n projectionVersion: typeof DOMAIN_PROJECTION_VERSION;\n selectedCount: number;\n matchedCount: number;\n} & (\n | { plan: 'notes'; rows: Note[] }\n | { plan: 'blocks'; rows: BlockIndexRow[] }\n | { plan: 'entries'; rows: DomainEntry[] }\n);\n\nfunction isObject(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction optionalStrings(row: Record<string, unknown>, fields: string[]): boolean {\n return fields.every(field => row[field] === undefined || typeof row[field] === 'string');\n}\n\nfunction finiteNumbers(row: Record<string, unknown>, fields: string[]): boolean {\n return fields.every(field => typeof row[field] === 'number' && Number.isFinite(row[field]));\n}\n\nfunction isNote(value: unknown): value is Note {\n if (!isObject(value) || typeof value.id !== 'string' || typeof value.title !== 'string'\n || typeof value.rawContent !== 'string' || !Number.isSafeInteger(value.sourceRevision)\n || typeof value.sourceRevision !== 'number' || value.sourceRevision < 1 || !isObject(value.blocks)\n || !finiteNumbers(value, ['createdAt'])\n || (value.date !== undefined && !finiteNumbers(value, ['date']))\n || !optionalStrings(value, ['type', 'sourceId', 'catalog', 'sourcePath', 'seedOrigin', 'seedChunkId'])\n || (value.tags !== undefined && (!Array.isArray(value.tags) || !value.tags.every(tag => typeof tag === 'string')))) return false;\n try {\n validateNoteBlocks(value.rawContent, value.blocks as Note['blocks'], value.sourceRevision);\n return true;\n } catch { return false; }\n}\n\nfunction isBlock(value: unknown): value is BlockIndexRow {\n return isObject(value) && typeof value.id === 'string' && typeof value.noteId === 'string'\n && typeof value.blockId === 'string' && finiteNumbers(value, ['blockVersion', 'sourceRevision', 'from', 'to', 'createdAt'])\n && value.id === `${value.noteId}:${value.blockId}`\n && typeof value.blockVersion === 'number' && Number.isSafeInteger(value.blockVersion) && value.blockVersion > 0\n && typeof value.sourceRevision === 'number' && Number.isSafeInteger(value.sourceRevision) && value.sourceRevision > 0\n && typeof value.from === 'number' && Number.isSafeInteger(value.from) && value.from >= 0\n && typeof value.to === 'number' && Number.isSafeInteger(value.to) && value.to > value.from\n && ['wod', 'query', 'widget', 'embed'].includes(String(value.dataType)) && typeof value.rawContent === 'string'\n && typeof value.noteTitle === 'string'\n && optionalStrings(value, ['blockContentId', 'sourceId', 'sourcePath', 'routeId'])\n && (value.position === undefined || finiteNumbers(value, ['position']))\n && (value.isStatic === undefined || typeof value.isStatic === 'boolean');\n}\n\n\nfunction isTag(value: unknown): value is Tag {\n return isObject(value) && typeof value.id === 'string' && typeof value.label === 'string'\n && finiteNumbers(value, ['createdAt']) && optionalStrings(value, ['type']);\n}\n\nfunction isPage(value: unknown): value is Page {\n return isObject(value) && typeof value.id === 'string' && finiteNumbers(value, ['createdAt'])\n && optionalStrings(value, ['date', 'slug', 'title']);\n}\n\nfunction isLink(value: unknown): value is PageNote {\n return isObject(value) && typeof value.id === 'string' && typeof value.noteId === 'string'\n && typeof value.pageId === 'string' && finiteNumbers(value, ['createdAt'])\n && (value.position === undefined || finiteNumbers(value, ['position']));\n}\n\nfunction isEntry(value: unknown): value is DomainEntry {\n return isObject(value) && isNote(value.note)\n && Array.isArray(value.tags) && value.tags.every(isTag)\n && Array.isArray(value.links) && value.links.every(isLink)\n && Array.isArray(value.pages) && value.pages.every(isPage);\n}\n\nexport function parseDomainQueryResult(value: unknown, plan: DomainQuery['plan']): DomainQueryResult {\n if (!isObject(value) || value.projectionVersion !== DOMAIN_PROJECTION_VERSION\n || value.plan !== plan || !Array.isArray(value.rows)\n || typeof value.selectedCount !== 'number' || !Number.isSafeInteger(value.selectedCount) || value.selectedCount < 0\n || typeof value.matchedCount !== 'number' || !Number.isSafeInteger(value.matchedCount) || value.matchedCount < 0\n || value.matchedCount > value.selectedCount || value.rows.length > value.matchedCount) {\n throw new Error('ApiStorage: invalid or stale domain projection response');\n }\n const counts = { projectionVersion: DOMAIN_PROJECTION_VERSION, selectedCount: value.selectedCount, matchedCount: value.matchedCount } as const;\n switch (plan) {\n case 'notes':\n if (value.rows.every(isNote)) return { ...counts, plan, rows: value.rows };\n break;\n case 'blocks':\n if (value.rows.every(isBlock)) return { ...counts, plan, rows: value.rows };\n break;\n case 'entries':\n if (value.rows.every(isEntry)) return { ...counts, plan, rows: value.rows };\n break;\n }\n throw new Error('ApiStorage: invalid domain query rows');\n}\n","/**\n * StorageError — the single error type every shared SQL layer throws.\n * Replaces the API server's HTTP-specific error: `status` keeps the wire\n * mapping for the HTTP surface, `code` carries a stable machine identifier\n * (e.g. 'domain_projection_unavailable') for browser callers.\n */\nexport class StorageError extends Error {\n constructor(readonly status: number, message: string, readonly code?: string) {\n super(message);\n this.name = 'StorageError';\n }\n}\n","import { validateNoteBlocks, type BlockRevision, type Note, type Session } from '@bitcobblers/wod-wiki-core';\nimport type { StoreName } from './contract';\nimport { StorageError } from './sql/errors';\n\nexport function rowsEqual(left: unknown, right: unknown): boolean {\n if (Object.is(left, right)) return true;\n if (left instanceof ArrayBuffer && right instanceof ArrayBuffer) {\n const a = new Uint8Array(left), b = new Uint8Array(right);\n return a.length === b.length && a.every((value, i) => value === b[i]);\n }\n if (typeof left !== 'object' || left === null || typeof right !== 'object' || right === null) return false;\n if (Array.isArray(left) || Array.isArray(right)) return Array.isArray(left) && Array.isArray(right)\n && left.length === right.length && left.every((value, i) => rowsEqual(value, right[i]));\n const a = Object.keys(left).filter(key => Reflect.get(left, key) !== undefined);\n const b = Object.keys(right).filter(key => Reflect.get(right, key) !== undefined);\n return a.length === b.length && a.every(key => Object.hasOwn(right, key)\n && rowsEqual(Reflect.get(left, key), Reflect.get(right, key)));\n}\n\nfunction record(value: unknown): Record<string, unknown> {\n if (typeof value !== 'object' || value === null || Array.isArray(value)) throw new StorageError(400, 'storage row must be an object');\n return value as Record<string, unknown>;\n}\n\nexport function validateStorageRow(store: StoreName, value: unknown): void {\n if (store !== 'notes' && store !== 'block_revisions' && store !== 'sessions' && store !== 'block_index') return;\n const row = record(value);\n const positive = (field: string): boolean => typeof row[field] === 'number' && Number.isSafeInteger(row[field]) && row[field] > 0;\n const required = (field: string): boolean => typeof row[field] === 'string' && row[field].length > 0;\n if (store === 'notes') {\n if (!required('id') || typeof row.title !== 'string' || typeof row.rawContent !== 'string'\n || !positive('sourceRevision') || typeof row.createdAt !== 'number' || !Number.isFinite(row.createdAt)\n || 'segments' in row || 'segmentIds' in row\n || (row.date !== undefined && (typeof row.date !== 'number' || !Number.isFinite(row.date)))\n || (row.seedOrigin !== undefined && row.seedOrigin !== 'seed' && row.seedOrigin !== 'user')\n || (row.seedVersion !== undefined && !positive('seedVersion'))\n || (row.tags !== undefined && (!Array.isArray(row.tags) || !row.tags.every(tag => typeof tag === 'string')))\n || ['type', 'sourceId', 'sourcePath', 'catalog', 'seedChunkId'].some(field => row[field] !== undefined && typeof row[field] !== 'string')) {\n throw new StorageError(400, 'invalid whole Note', 'invalid_note_blocks');\n }\n try { validateNoteBlocks(row.rawContent, record(row.blocks) as Note['blocks'], row.sourceRevision as number); }\n catch (error) { throw new StorageError(400, error instanceof Error ? error.message : 'invalid block map', 'invalid_note_blocks'); }\n } else if (store === 'block_revisions') {\n if (!required('noteId') || !required('blockId') || !positive('version') || typeof row.rawContent !== 'string'\n || typeof row.savedAt !== 'number' || !Number.isFinite(row.savedAt)\n || !['wod', 'query', 'widget', 'embed'].includes(String(row.kind))\n || (row.kind === 'wod' ? row.dialect !== 'time' && row.dialect !== 'log' : row.dialect !== undefined || row.sport !== undefined)\n || (row.sport !== undefined && typeof row.sport !== 'string')) throw new StorageError(400, 'invalid block revision', 'invalid_note_blocks');\n try {\n validateNoteBlocks(row.rawContent as string, { [String(row.blockId)]: {\n id: String(row.blockId), kind: row.kind as BlockRevision['kind'], version: row.version as number,\n sourceRevision: 1, from: 0, to: (row.rawContent as string).length,\n ...(row.dialect === undefined ? {} : { dialect: row.dialect as 'time' | 'log' }),\n ...(row.sport === undefined ? {} : { sport: row.sport as string }),\n } }, 1);\n } catch (error) { throw new StorageError(400, error instanceof Error ? error.message : 'invalid revision source', 'invalid_note_blocks'); }\n } else if (store === 'sessions') {\n if (!required('noteId') || !required('blockId') || !positive('blockVersion')\n || ['segmentId', 'segmentVersion', 'version', 'rawContent', 'script', 'serializedScript', 'source', 'data', 'logs'].some(field => field in row)) {\n throw new StorageError(400, 'Session requires immutable block pin', 'invalid_session_pin');\n }\n } else if (!required('noteId') || !required('blockId') || !positive('blockVersion') || !positive('sourceRevision')\n || row.id !== `${row.noteId}:${row.blockId}` || !Number.isSafeInteger(row.from) || !Number.isSafeInteger(row.to)\n || 'segmentId' in row || 'segmentVersion' in row\n || !['wod', 'query', 'widget', 'embed'].includes(String(row.dataType))\n || typeof row.rawContent !== 'string' || typeof row.noteTitle !== 'string'\n || typeof row.from !== 'number' || typeof row.to !== 'number' || row.from < 0 || row.to <= row.from) {\n throw new StorageError(400, 'invalid actionable block projection', 'invalid_note_blocks');\n }\n}\n\nexport function validateNoteWrite(previous: unknown, value: unknown): void {\n if (previous === undefined || rowsEqual(previous, value)) return;\n const before = record(previous), after = record(value);\n if (typeof before.sourceRevision !== 'number' || typeof after.sourceRevision !== 'number'\n || after.sourceRevision < before.sourceRevision\n || ((!rowsEqual(before.blocks, after.blocks) || before.rawContent !== after.rawContent)\n && after.sourceRevision <= before.sourceRevision)) throw new StorageError(409, 'stale Note source revision', 'transaction_conflict');\n}\n\nexport function validateSessionWrite(previous: unknown, value: unknown): void {\n if (previous === undefined) return;\n const before = record(previous), after = record(value);\n if (before.noteId !== after.noteId || before.blockId !== after.blockId || before.blockVersion !== after.blockVersion)\n throw new StorageError(409, 'Session pin is immutable', 'invalid_session_pin');\n}\n\nexport async function validateStoredPins(\n notes: Note[], sessions: Session[], getRevisions: (keys: IDBValidKey[]) => Promise<(BlockRevision | undefined)[]>,\n): Promise<void> {\n const keys: IDBValidKey[] = [];\n for (const note of notes) for (const block of Object.values(note.blocks)) keys.push([note.id, block.id, block.version]);\n for (const session of sessions) keys.push([session.noteId, session.blockId, session.blockVersion]);\n const revisions = await getRevisions(keys);\n let i = 0;\n for (const note of notes) for (const block of Object.values(note.blocks)) {\n const revision = revisions[i++];\n if (!revision || revision.kind !== block.kind || revision.rawContent !== note.rawContent.slice(block.from, block.to)\n || revision.dialect !== block.dialect || revision.sport !== block.sport) throw new StorageError(409, 'Note block has no matching immutable revision', 'invalid_note_blocks');\n }\n for (let sessionIndex = 0; sessionIndex < sessions.length; sessionIndex++) {\n const revision = revisions[i++];\n if (!revision || revision.kind !== 'wod') throw new StorageError(409, 'Session pin must reference a saved workout revision', 'invalid_session_pin');\n }\n}\n","/**\n * Transaction write-buffer + read-overlay helpers shared by the HTTP\n * ApiStorage and the SQL SqlStorage backends. A transaction buffers puts and\n * deletes; reads overlay the buffer on backend rows in op order, so\n * read-your-writes holds without round-tripping uncommitted data.\n */\n\nimport type { StoreName } from './contract';\nimport {\n compareKeys,\n extractKeyPart,\n keyFromValue,\n keyInRange,\n type KeyDTO,\n type RangeDTO,\n type TxOp,\n} from './wire';\nimport type { StoreDef } from './schema';\n\nexport interface BufferedPut { kind: 'put'; value: unknown }\nexport interface BufferedDelete { kind: 'delete'; key: KeyDTO }\nexport type BufferEntry = BufferedPut | BufferedDelete;\n\n// Buffer slot key: store + \\u0000 + raw JSON of the key (JSON text never\n// contains a literal \\u0000, so the separator is unambiguous).\nexport const bufferSlot = (store: StoreName, key: KeyDTO): string => `${store}\\u0000${JSON.stringify(key)}`;\n\n/** True when this tx has buffered writes (puts, deletes or a clear) for the store. */\nexport function isDirty(store: StoreName, buffer?: Map<string, BufferEntry>, cleared?: Set<StoreName>): boolean {\n if (cleared?.has(store)) return true;\n if (!buffer) return false;\n const prefix = `${store}\\u0000`;\n for (const slot of buffer.keys()) {\n if (slot.startsWith(prefix)) return true;\n }\n return false;\n}\n\n/** Point lookup against the buffer; undefined means consult the backend. */\nexport function bufferedGet<T>(store: StoreName, key: KeyDTO, buffer?: Map<string, BufferEntry>):\n | { hit: true; value: T }\n | { hit: false }\n | undefined {\n if (!buffer) return undefined;\n const entry = buffer.get(bufferSlot(store, key));\n if (!entry) return undefined;\n return entry.kind === 'put' ? { hit: true, value: entry.value as T } : { hit: false };\n}\n\n/**\n * Applies buffered puts and deletes before range filtering, ordering and\n * paging. Rows missing an index field are not in the index (IDB semantics);\n * multi-entry keys match when any entry is in range.\n */\nexport function overlayRows<T>(\n def: StoreDef,\n store: StoreName,\n buffer: Map<string, BufferEntry> | undefined,\n cleared: Set<StoreName> | undefined,\n rows: T[],\n count?: number,\n range?: RangeDTO,\n indexName?: string,\n): T[] {\n if (!buffer || !isDirty(store, buffer, cleared)) return count !== undefined ? rows.slice(0, count) : rows;\n const out = new Map<string, T>();\n if (!cleared?.has(store)) {\n // Out-map keys are raw JSON key text — same form as buffer slot suffixes.\n for (const row of rows) out.set(JSON.stringify(keyFromValue(def, row)), row);\n }\n const prefix = `${store}\\u0000`;\n for (const [slot, entry] of buffer) {\n if (!slot.startsWith(prefix)) continue;\n if (entry.kind === 'put') out.set(slot.slice(prefix.length), entry.value as T);\n else out.delete(slot.slice(prefix.length));\n }\n // Dirty reads fetch the complete candidate range: buffered deletes can\n // remove the remote head, and puts can change index membership or order.\n const index = indexName ? def.indexes.find(i => i.name === indexName) : undefined;\n if (indexName && !index) throw new Error(`unknown index '${indexName}' for ${store}`);\n const keyOf = (row: T): KeyDTO | undefined => {\n if (!index) return keyFromValue(def, row);\n const parts = index.keyPath.map(path => extractKeyPart(row, path));\n if (parts.some(part => part === undefined)) return undefined;\n const keys = parts.filter((part): part is string | number => part !== undefined);\n return keys.length === 1 ? keys[0] : keys;\n };\n const matches = (row: T): boolean => {\n if (index?.multiEntry) {\n let values: unknown = row;\n for (const part of index.keyPath[0].split('.')) {\n if (values === null || typeof values !== 'object' || !(part in values)) return false;\n values = Reflect.get(values, part);\n }\n return Array.isArray(values) && values.some(value =>\n (typeof value === 'string' || typeof value === 'number') && (!range || keyInRange(value, range)));\n }\n const key = keyOf(row);\n return key !== undefined && (!range || keyInRange(key, range));\n };\n const merged = [...out.values()].filter(matches);\n merged.sort((a, b) => {\n const primary = compareKeys(keyFromValue(def, a), keyFromValue(def, b));\n if (index?.multiEntry) return primary;\n const ak = keyOf(a), bk = keyOf(b);\n return ak !== undefined && bk !== undefined ? compareKeys(ak, bk) || primary : primary;\n });\n return count !== undefined ? merged.slice(0, count) : merged;\n}\n\n/** Drains the tx buffer into wire ops (clears first, then puts/deletes in op order). */\nexport function bufferToOps(storeNames: Iterable<StoreName>, buffer: Map<string, BufferEntry>, cleared: Set<StoreName>): TxOp[] {\n const known = new Set(storeNames);\n const ops: TxOp[] = [];\n for (const store of cleared) {\n if (known.has(store)) ops.push({ op: 'clear', store });\n }\n for (const [slot, entry] of buffer) {\n const sep = slot.indexOf('\\u0000');\n const store = slot.slice(0, sep) as StoreName;\n if (!known.has(store)) continue;\n if (entry.kind === 'put') ops.push({ op: 'put', store, value: entry.value });\n else ops.push({ op: 'delete', store, key: JSON.parse(slot.slice(sep + 1)) as KeyDTO });\n }\n return ops;\n}\n"]}