@korajs/store 1.0.0-beta.0 → 1.0.0-beta.2

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 (61) hide show
  1. package/dist/adapters/better-sqlite3.d.cts +1 -1
  2. package/dist/adapters/better-sqlite3.d.ts +1 -1
  3. package/dist/adapters/indexeddb.cjs +39 -5
  4. package/dist/adapters/indexeddb.cjs.map +1 -1
  5. package/dist/adapters/indexeddb.d.cts +1 -1
  6. package/dist/adapters/indexeddb.d.ts +1 -1
  7. package/dist/adapters/indexeddb.js +13 -6
  8. package/dist/adapters/indexeddb.js.map +1 -1
  9. package/dist/adapters/sqlite-wasm-worker.cjs +25 -3
  10. package/dist/adapters/sqlite-wasm-worker.cjs.map +1 -1
  11. package/dist/adapters/sqlite-wasm-worker.js +25 -3
  12. package/dist/adapters/sqlite-wasm-worker.js.map +1 -1
  13. package/dist/adapters/sqlite-wasm.cjs +29 -0
  14. package/dist/adapters/sqlite-wasm.cjs.map +1 -1
  15. package/dist/adapters/sqlite-wasm.d.cts +17 -2
  16. package/dist/adapters/sqlite-wasm.d.ts +17 -2
  17. package/dist/adapters/sqlite-wasm.js +1 -1
  18. package/dist/{backup-5XZ7THNJ.js → backup-IQE4QC7Q.js} +3 -3
  19. package/dist/blob-fs.cjs +166 -0
  20. package/dist/blob-fs.cjs.map +1 -0
  21. package/dist/blob-fs.d.cts +29 -0
  22. package/dist/blob-fs.d.ts +29 -0
  23. package/dist/blob-fs.js +128 -0
  24. package/dist/blob-fs.js.map +1 -0
  25. package/dist/{chunk-OUQDC5Z6.js → chunk-2VRPF25R.js} +58 -38
  26. package/dist/chunk-2VRPF25R.js.map +1 -0
  27. package/dist/{chunk-ETDJEH2I.js → chunk-6NKLDBTY.js} +11 -1
  28. package/dist/{chunk-ETDJEH2I.js.map → chunk-6NKLDBTY.js.map} +1 -1
  29. package/dist/{chunk-5R4QMY3Z.js → chunk-OCOGQRHW.js} +13 -10
  30. package/dist/chunk-OCOGQRHW.js.map +1 -0
  31. package/dist/{chunk-RBPVEAVM.js → chunk-QUJGXSZ6.js} +30 -1
  32. package/dist/chunk-QUJGXSZ6.js.map +1 -0
  33. package/dist/{chunk-EIVXWF4B.js → chunk-RCTG3IJG.js} +4 -3
  34. package/dist/chunk-RCTG3IJG.js.map +1 -0
  35. package/dist/chunk-W4MTTNEZ.js +55 -0
  36. package/dist/chunk-W4MTTNEZ.js.map +1 -0
  37. package/dist/content-addressed-blob-store-Dcj3SB9r.d.cts +60 -0
  38. package/dist/content-addressed-blob-store-Dcj3SB9r.d.ts +60 -0
  39. package/dist/{export-audit-VPGQWNR6.js → export-audit-MT2LTMIN.js} +3 -3
  40. package/dist/index.cjs +765 -128
  41. package/dist/index.cjs.map +1 -1
  42. package/dist/index.d.cts +397 -6
  43. package/dist/index.d.ts +397 -6
  44. package/dist/index.js +603 -60
  45. package/dist/index.js.map +1 -1
  46. package/dist/internal.cjs +68 -43
  47. package/dist/internal.cjs.map +1 -1
  48. package/dist/internal.d.cts +3 -3
  49. package/dist/internal.d.ts +3 -3
  50. package/dist/internal.js +3 -3
  51. package/dist/{types-CyjXwrjW.d.cts → types-5h4Hqcwc.d.ts} +10 -3
  52. package/dist/{types-DAxCladl.d.ts → types-DfPiPwKr.d.cts} +10 -3
  53. package/dist/{types-CJOVKxLw.d.cts → types-k6AZgiH4.d.cts} +6 -1
  54. package/dist/{types-CJOVKxLw.d.ts → types-k6AZgiH4.d.ts} +6 -1
  55. package/package.json +13 -2
  56. package/dist/chunk-5R4QMY3Z.js.map +0 -1
  57. package/dist/chunk-EIVXWF4B.js.map +0 -1
  58. package/dist/chunk-OUQDC5Z6.js.map +0 -1
  59. package/dist/chunk-RBPVEAVM.js.map +0 -1
  60. /package/dist/{backup-5XZ7THNJ.js.map → backup-IQE4QC7Q.js.map} +0 -0
  61. /package/dist/{export-audit-VPGQWNR6.js.map → export-audit-MT2LTMIN.js.map} +0 -0
package/dist/internal.cjs CHANGED
@@ -233,6 +233,9 @@ function serializeValue(value, descriptor) {
233
233
  case "boolean":
234
234
  return value ? 1 : 0;
235
235
  case "array":
236
+ case "object":
237
+ case "json":
238
+ case "blob":
236
239
  return JSON.stringify(value);
237
240
  case "richtext":
238
241
  return encodeRichtext(value);
@@ -249,6 +252,13 @@ function deserializeValue(value, descriptor) {
249
252
  return JSON.parse(value);
250
253
  }
251
254
  return value;
255
+ case "object":
256
+ case "json":
257
+ case "blob":
258
+ if (typeof value === "string") {
259
+ return JSON.parse(value);
260
+ }
261
+ return value;
252
262
  case "richtext":
253
263
  return decodeRichtext(value);
254
264
  default:
@@ -256,6 +266,9 @@ function deserializeValue(value, descriptor) {
256
266
  }
257
267
  }
258
268
 
269
+ // src/query/sql-builder.ts
270
+ var import_core5 = require("@korajs/core");
271
+
259
272
  // src/errors.ts
260
273
  var import_core3 = require("@korajs/core");
261
274
  var QueryError = class extends import_core3.KoraError {
@@ -300,7 +313,7 @@ function lwwVersionWhereClause(remoteVersion) {
300
313
  // src/query/sql-builder.ts
301
314
  function buildSelectQuery(descriptor, fields) {
302
315
  const params = [];
303
- const parts = [`SELECT * FROM ${descriptor.collection}`];
316
+ const parts = [`SELECT * FROM ${(0, import_core5.quoteIdent)(descriptor.collection)}`];
304
317
  const whereClause = buildWhereClauseParts(descriptor.where, fields, params);
305
318
  const deletedFilter = "_deleted = 0";
306
319
  if (whereClause) {
@@ -311,7 +324,7 @@ function buildSelectQuery(descriptor, fields) {
311
324
  if (descriptor.orderBy.length > 0) {
312
325
  const orderParts = descriptor.orderBy.map((o) => {
313
326
  validateFieldName(o.field, fields);
314
- return `${o.field} ${o.direction.toUpperCase()}`;
327
+ return `${(0, import_core5.quoteIdent)(o.field)} ${o.direction.toUpperCase()}`;
315
328
  });
316
329
  parts.push(`ORDER BY ${orderParts.join(", ")}`);
317
330
  }
@@ -325,7 +338,7 @@ function buildSelectQuery(descriptor, fields) {
325
338
  }
326
339
  function buildCountQuery(descriptor, fields) {
327
340
  const params = [];
328
- const parts = [`SELECT COUNT(*) as count FROM ${descriptor.collection}`];
341
+ const parts = [`SELECT COUNT(*) as count FROM ${(0, import_core5.quoteIdent)(descriptor.collection)}`];
329
342
  const whereClause = buildWhereClauseParts(descriptor.where, fields, params);
330
343
  const deletedFilter = "_deleted = 0";
331
344
  if (whereClause) {
@@ -339,38 +352,39 @@ function buildInsertQuery(collection, record) {
339
352
  const columns = Object.keys(record);
340
353
  const placeholders = columns.map(() => "?");
341
354
  const params = Object.values(record);
342
- const sql = `INSERT INTO ${collection} (${columns.join(", ")}) VALUES (${placeholders.join(", ")})`;
355
+ const quotedColumns = columns.map((col) => (0, import_core5.quoteIdent)(col));
356
+ const sql = `INSERT INTO ${(0, import_core5.quoteIdent)(collection)} (${quotedColumns.join(", ")}) VALUES (${placeholders.join(", ")})`;
343
357
  return { sql, params };
344
358
  }
345
359
  function buildUpdateQuery(collection, id, changes) {
346
- const setClauses = Object.keys(changes).map((col) => `${col} = ?`);
360
+ const setClauses = Object.keys(changes).map((col) => `${(0, import_core5.quoteIdent)(col)} = ?`);
347
361
  const params = [...Object.values(changes), id];
348
- const sql = `UPDATE ${collection} SET ${setClauses.join(", ")} WHERE id = ?`;
362
+ const sql = `UPDATE ${(0, import_core5.quoteIdent)(collection)} SET ${setClauses.join(", ")} WHERE id = ?`;
349
363
  return { sql, params };
350
364
  }
351
365
  function buildSoftDeleteQuery(collection, id, updatedAt, version) {
352
366
  if (version !== void 0) {
353
367
  return {
354
- sql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ?`,
368
+ sql: `UPDATE ${(0, import_core5.quoteIdent)(collection)} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ?`,
355
369
  params: [updatedAt, version, id]
356
370
  };
357
371
  }
358
372
  return {
359
- sql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ? WHERE id = ?`,
373
+ sql: `UPDATE ${(0, import_core5.quoteIdent)(collection)} SET _deleted = 1, _updated_at = ? WHERE id = ?`,
360
374
  params: [updatedAt, id]
361
375
  };
362
376
  }
363
377
  function buildLwwUpdateQuery(collection, id, changes, remoteVersion) {
364
- const setClauses = Object.keys(changes).map((col) => `${col} = ?`);
378
+ const setClauses = Object.keys(changes).map((col) => `${(0, import_core5.quoteIdent)(col)} = ?`);
365
379
  const lww = lwwVersionWhereClause(remoteVersion);
366
- const sql = `UPDATE ${collection} SET ${setClauses.join(", ")} WHERE id = ? AND ${lww.sql}`;
380
+ const sql = `UPDATE ${(0, import_core5.quoteIdent)(collection)} SET ${setClauses.join(", ")} WHERE id = ? AND ${lww.sql}`;
367
381
  const params = [...Object.values(changes), id, ...lww.params];
368
382
  return { sql, params };
369
383
  }
370
384
  function buildLwwSoftDeleteQuery(collection, id, updatedAt, version) {
371
385
  const lww = lwwVersionWhereClause(version);
372
386
  return {
373
- sql: `UPDATE ${collection} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ? AND ${lww.sql}`,
387
+ sql: `UPDATE ${(0, import_core5.quoteIdent)(collection)} SET _deleted = 1, _updated_at = ?, _version = ? WHERE id = ? AND ${lww.sql}`,
374
388
  params: [updatedAt, version, id, ...lww.params]
375
389
  };
376
390
  }
@@ -407,31 +421,32 @@ function buildWhereClauseParts(where, fields, params) {
407
421
  }
408
422
  function buildOperatorCondition(fieldName, operator, value, descriptor, params) {
409
423
  const sqlValue = descriptor?.kind === "boolean" && typeof value === "boolean" ? value ? 1 : 0 : value;
424
+ const column = (0, import_core5.quoteIdent)(fieldName);
410
425
  switch (operator) {
411
426
  case "$eq":
412
427
  if (sqlValue === null) {
413
- return `${fieldName} IS NULL`;
428
+ return `${column} IS NULL`;
414
429
  }
415
430
  params.push(sqlValue);
416
- return `${fieldName} = ?`;
431
+ return `${column} = ?`;
417
432
  case "$ne":
418
433
  if (sqlValue === null) {
419
- return `${fieldName} IS NOT NULL`;
434
+ return `${column} IS NOT NULL`;
420
435
  }
421
436
  params.push(sqlValue);
422
- return `${fieldName} != ?`;
437
+ return `${column} != ?`;
423
438
  case "$gt":
424
439
  params.push(sqlValue);
425
- return `${fieldName} > ?`;
440
+ return `${column} > ?`;
426
441
  case "$gte":
427
442
  params.push(sqlValue);
428
- return `${fieldName} >= ?`;
443
+ return `${column} >= ?`;
429
444
  case "$lt":
430
445
  params.push(sqlValue);
431
- return `${fieldName} < ?`;
446
+ return `${column} < ?`;
432
447
  case "$lte":
433
448
  params.push(sqlValue);
434
- return `${fieldName} <= ?`;
449
+ return `${column} <= ?`;
435
450
  case "$in": {
436
451
  if (!Array.isArray(sqlValue)) {
437
452
  throw new QueryError(`$in operator requires an array value for field "${fieldName}"`, {
@@ -445,7 +460,7 @@ function buildOperatorCondition(fieldName, operator, value, descriptor, params)
445
460
  descriptor?.kind === "boolean" && typeof item === "boolean" ? item ? 1 : 0 : item
446
461
  );
447
462
  }
448
- return `${fieldName} IN (${placeholders.join(", ")})`;
463
+ return `${column} IN (${placeholders.join(", ")})`;
449
464
  }
450
465
  default:
451
466
  throw new QueryError(`Unknown operator "${operator}"`, { operator });
@@ -469,7 +484,7 @@ function validateFieldName(fieldName, fields) {
469
484
  }
470
485
 
471
486
  // src/mutations/execute-insert.ts
472
- var import_core5 = require("@korajs/core");
487
+ var import_core6 = require("@korajs/core");
473
488
 
474
489
  // src/lww/field-versions.ts
475
490
  function parseFieldVersions(raw) {
@@ -536,19 +551,24 @@ function resolveCausalDeps(ctx) {
536
551
 
537
552
  // src/mutations/execute-insert.ts
538
553
  async function executeInsert(ctx, data) {
539
- const validated = (0, import_core5.validateRecord)(ctx.collection, ctx.definition, data, "insert");
540
- const recordId = (0, import_core5.generateUUIDv7)();
554
+ const validated = (0, import_core6.validateRecord)(ctx.collection, ctx.definition, data, "insert");
555
+ const recordId = (0, import_core6.generateUUIDv7)();
541
556
  for (const [fieldName, descriptor] of Object.entries(ctx.definition.fields)) {
542
557
  if (descriptor.auto && descriptor.kind === "timestamp") {
543
558
  validated[fieldName] = Date.now();
544
559
  }
545
560
  }
561
+ const writeData = await (0, import_core6.transformSecretFieldsForWrite)(
562
+ validated,
563
+ ctx.definition,
564
+ ctx.secretKeyProvider
565
+ );
546
566
  const causalDeps = resolveCausalDeps(ctx);
547
567
  let operation;
548
568
  let record;
549
569
  await ctx.adapter.transaction(async (tx) => {
550
570
  const sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId);
551
- operation = await (0, import_core5.createOperation)(
571
+ operation = await (0, import_core6.createOperation)(
552
572
  {
553
573
  nodeId: ctx.nodeId,
554
574
  type: "insert",
@@ -557,7 +577,7 @@ async function executeInsert(ctx, data) {
557
577
  // Binary richtext values are tagged as canonical JSON BEFORE the
558
578
  // operation is content-hashed, so the hash input, persisted JSON,
559
579
  // and wire payload are the identical value.
560
- data: encodeRichtextFieldsForOpData(validated, ctx.definition.fields),
580
+ data: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),
561
581
  previousData: null,
562
582
  sequenceNumber,
563
583
  causalDeps,
@@ -566,7 +586,7 @@ async function executeInsert(ctx, data) {
566
586
  ctx.clock
567
587
  );
568
588
  ctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction);
569
- const serializedData = serializeRecord(validated, ctx.definition.fields);
589
+ const serializedData = serializeRecord(writeData, ctx.definition.fields);
570
590
  const version = serializeRowVersion(operation.timestamp);
571
591
  record = {
572
592
  id: recordId,
@@ -591,18 +611,18 @@ async function executeInsert(ctx, data) {
591
611
  ctx.onMutation(ctx.collection, operation);
592
612
  return {
593
613
  id: recordId,
594
- ...validated,
614
+ ...writeData,
595
615
  createdAt: operation.timestamp.wallTime,
596
616
  updatedAt: operation.timestamp.wallTime
597
617
  };
598
618
  }
599
619
 
600
620
  // src/mutations/execute-update.ts
601
- var import_core7 = require("@korajs/core");
621
+ var import_core8 = require("@korajs/core");
602
622
 
603
623
  // src/state-machine/state-validator.ts
604
- var import_core6 = require("@korajs/core");
605
- var InvalidStateTransitionError = class extends import_core6.KoraError {
624
+ var import_core7 = require("@korajs/core");
625
+ var InvalidStateTransitionError = class extends import_core7.KoraError {
606
626
  constructor(collection, recordId, field, fromState, toState, allowedStates) {
607
627
  super(
608
628
  `Invalid state transition in collection "${collection}": cannot transition field "${field}" from "${fromState}" to "${toState}". Allowed transitions from "${fromState}": ${allowedStates.length > 0 ? allowedStates.join(", ") : "(none -- terminal state)"}`,
@@ -636,7 +656,7 @@ function validateStateTransition(collectionName, recordId, stateMachine, current
636
656
  collection: collectionName,
637
657
  transitions: stateMachine.transitions
638
658
  };
639
- const transitionResult = (0, import_core6.validateTransition)(constraint, currentState, newState);
659
+ const transitionResult = (0, import_core7.validateTransition)(constraint, currentState, newState);
640
660
  if (transitionResult.valid) {
641
661
  return { valid: true, allowedStates: transitionResult.allowedTargets };
642
662
  }
@@ -685,14 +705,14 @@ function validateUpdateStateMachine(collectionName, recordId, collectionDef, cur
685
705
  // src/mutations/execute-update.ts
686
706
  async function executeUpdate(ctx, id, data) {
687
707
  const currentRows = await ctx.adapter.query(
688
- `SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,
708
+ `SELECT * FROM ${(0, import_core8.quoteIdent)(ctx.collection)} WHERE id = ? AND _deleted = 0`,
689
709
  [id]
690
710
  );
691
711
  const currentRow = currentRows[0];
692
712
  if (!currentRow) {
693
713
  throw new RecordNotFoundError(ctx.collection, id);
694
714
  }
695
- let validated = (0, import_core7.validateRecord)(ctx.collection, ctx.definition, data, "update");
715
+ let validated = (0, import_core8.validateRecord)(ctx.collection, ctx.definition, data, "update");
696
716
  const currentRecord = deserializeRecord(currentRow, ctx.definition.fields);
697
717
  validated = validateUpdateStateMachine(
698
718
  ctx.collection,
@@ -710,19 +730,24 @@ async function executeUpdate(ctx, id, data) {
710
730
  for (const key of Object.keys(validated)) {
711
731
  const value = validated[key];
712
732
  previousData[key] = currentRecord[key];
713
- if ((0, import_core7.isAtomicOp)(value)) {
714
- resolvedData[key] = (0, import_core7.resolveAtomicOp)(currentRecord[key], value);
715
- atomicOps[key] = (0, import_core7.toAtomicOp)(value);
733
+ if ((0, import_core8.isAtomicOp)(value)) {
734
+ resolvedData[key] = (0, import_core8.resolveAtomicOp)(currentRecord[key], value);
735
+ atomicOps[key] = (0, import_core8.toAtomicOp)(value);
716
736
  } else {
717
737
  resolvedData[key] = value;
718
738
  }
719
739
  }
740
+ const writeData = await (0, import_core8.transformSecretFieldsForWrite)(
741
+ resolvedData,
742
+ ctx.definition,
743
+ ctx.secretKeyProvider
744
+ );
720
745
  const hasAtomicOps = Object.keys(atomicOps).length > 0;
721
746
  const causalDeps = resolveCausalDeps(ctx);
722
747
  let operation;
723
748
  await ctx.adapter.transaction(async (tx) => {
724
749
  const sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId);
725
- operation = await (0, import_core7.createOperation)(
750
+ operation = await (0, import_core8.createOperation)(
726
751
  {
727
752
  nodeId: ctx.nodeId,
728
753
  type: "update",
@@ -731,7 +756,7 @@ async function executeUpdate(ctx, id, data) {
731
756
  // Binary richtext values (new and previous) are tagged as canonical
732
757
  // JSON BEFORE the operation is content-hashed, so the hash input,
733
758
  // persisted JSON, and wire payload are the identical value.
734
- data: encodeRichtextFieldsForOpData(resolvedData, ctx.definition.fields),
759
+ data: encodeRichtextFieldsForOpData(writeData, ctx.definition.fields),
735
760
  previousData: encodeRichtextFieldsForOpData(previousData, ctx.definition.fields),
736
761
  sequenceNumber,
737
762
  causalDeps,
@@ -741,7 +766,7 @@ async function executeUpdate(ctx, id, data) {
741
766
  ctx.clock
742
767
  );
743
768
  ctx.causalTracker?.afterOperation(ctx.collection, operation.id, ctx.inTransaction);
744
- const serializedChanges = serializeRecord(resolvedData, ctx.definition.fields);
769
+ const serializedChanges = serializeRecord(writeData, ctx.definition.fields);
745
770
  const version = serializeRowVersion(operation.timestamp);
746
771
  const mergedFieldVersions = parseFieldVersions(currentRow._field_versions);
747
772
  for (const changedField of Object.keys(serializedChanges)) {
@@ -762,7 +787,7 @@ async function executeUpdate(ctx, id, data) {
762
787
  });
763
788
  ctx.onMutation(ctx.collection, operation);
764
789
  const rows = await ctx.adapter.query(
765
- `SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,
790
+ `SELECT * FROM ${(0, import_core8.quoteIdent)(ctx.collection)} WHERE id = ? AND _deleted = 0`,
766
791
  [id]
767
792
  );
768
793
  const row = rows[0];
@@ -773,10 +798,10 @@ async function executeUpdate(ctx, id, data) {
773
798
  }
774
799
 
775
800
  // src/mutations/execute-delete.ts
776
- var import_core8 = require("@korajs/core");
801
+ var import_core9 = require("@korajs/core");
777
802
  async function executeDelete(ctx, id, options) {
778
803
  const currentRows = await ctx.adapter.query(
779
- `SELECT * FROM ${ctx.collection} WHERE id = ? AND _deleted = 0`,
804
+ `SELECT * FROM ${(0, import_core9.quoteIdent)(ctx.collection)} WHERE id = ? AND _deleted = 0`,
780
805
  [id]
781
806
  );
782
807
  if (!currentRows[0]) {
@@ -788,7 +813,7 @@ async function executeDelete(ctx, id, options) {
788
813
  await ctx.adapter.transaction(async (tx) => {
789
814
  if (!operation) {
790
815
  const sequenceNumber = await allocateNextSequenceInTransaction(tx, ctx.nodeId);
791
- operation = await (0, import_core8.createOperation)(
816
+ operation = await (0, import_core9.createOperation)(
792
817
  {
793
818
  nodeId: ctx.nodeId,
794
819
  type: "delete",