js-bao 0.3.0-alpha.4 → 0.3.0-alpha.5

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.
@@ -92,20 +92,20 @@ var JsonSchemaDDL = class {
92
92
  if (options.includeDocIdColumn) {
93
93
  return `
94
94
  CREATE TABLE IF NOT EXISTS records (
95
- id TEXT NOT NULL,
96
- type TEXT NOT NULL,
97
- data_json TEXT NOT NULL,
95
+ _id TEXT NOT NULL,
96
+ _type TEXT NOT NULL,
97
+ _data TEXT NOT NULL,
98
98
  _meta_doc_id TEXT,
99
99
  _meta_permission_hint TEXT,
100
- PRIMARY KEY (type, id)
100
+ PRIMARY KEY (_type, _id)
101
101
  )`.trim();
102
102
  } else {
103
103
  return `
104
104
  CREATE TABLE IF NOT EXISTS records (
105
- id TEXT NOT NULL,
106
- type TEXT NOT NULL,
107
- data_json TEXT NOT NULL,
108
- PRIMARY KEY (type, id)
105
+ _id TEXT NOT NULL,
106
+ _type TEXT NOT NULL,
107
+ _data TEXT NOT NULL,
108
+ PRIMARY KEY (_type, _id)
109
109
  )`.trim();
110
110
  }
111
111
  }
@@ -116,21 +116,21 @@ CREATE TABLE IF NOT EXISTS records (
116
116
  if (options.includeDocIdColumn) {
117
117
  return `
118
118
  CREATE TABLE IF NOT EXISTS stringset_index (
119
- record_id TEXT NOT NULL,
120
- type TEXT NOT NULL,
119
+ _record_id TEXT NOT NULL,
120
+ _type TEXT NOT NULL,
121
121
  field TEXT NOT NULL,
122
122
  value TEXT NOT NULL,
123
123
  _meta_doc_id TEXT,
124
- UNIQUE(type, field, record_id, value)
124
+ UNIQUE(_type, field, _record_id, value)
125
125
  )`.trim();
126
126
  } else {
127
127
  return `
128
128
  CREATE TABLE IF NOT EXISTS stringset_index (
129
- record_id TEXT NOT NULL,
130
- type TEXT NOT NULL,
129
+ _record_id TEXT NOT NULL,
130
+ _type TEXT NOT NULL,
131
131
  field TEXT NOT NULL,
132
132
  value TEXT NOT NULL,
133
- UNIQUE(type, field, record_id, value)
133
+ UNIQUE(_type, field, _record_id, value)
134
134
  )`.trim();
135
135
  }
136
136
  }
@@ -139,11 +139,11 @@ CREATE TABLE IF NOT EXISTS stringset_index (
139
139
  */
140
140
  static createBaseIndexes(options) {
141
141
  const indexes = [
142
- // Index on type for filtering by model
143
- "CREATE INDEX IF NOT EXISTS idx_records_type ON records(type)",
142
+ // Index on _type for filtering by model
143
+ "CREATE INDEX IF NOT EXISTS idx_records_type ON records(_type)",
144
144
  // StringSet indexes for efficient lookups
145
- "CREATE INDEX IF NOT EXISTS idx_ss_type_field_value ON stringset_index(type, field, value)",
146
- "CREATE INDEX IF NOT EXISTS idx_ss_type_field_record ON stringset_index(type, field, record_id)"
145
+ "CREATE INDEX IF NOT EXISTS idx_ss_type_field_value ON stringset_index(_type, field, value)",
146
+ "CREATE INDEX IF NOT EXISTS idx_ss_type_field_record ON stringset_index(_type, field, _record_id)"
147
147
  ];
148
148
  if (options.includeDocIdColumn) {
149
149
  indexes.push(
@@ -161,7 +161,7 @@ CREATE TABLE IF NOT EXISTS stringset_index (
161
161
  assertValidIdentifier(modelName, "createFieldIndex modelName");
162
162
  assertValidIdentifier(fieldName, "createFieldIndex fieldName");
163
163
  const indexName = `idx_records_${modelName.toLowerCase()}_${fieldName.toLowerCase()}`;
164
- return `CREATE INDEX IF NOT EXISTS ${indexName} ON records(json_extract(data_json, '$.${fieldName}')) WHERE type = '${modelName}'`;
164
+ return `CREATE INDEX IF NOT EXISTS ${indexName} ON records(json_extract(_data, '$.${fieldName}')) WHERE _type = '${modelName}'`;
165
165
  }
166
166
  /**
167
167
  * Generate DROP INDEX statement for a model field
@@ -234,11 +234,11 @@ CREATE TABLE IF NOT EXISTS _model_fields (
234
234
  static buildInsertSQL(options) {
235
235
  if (options.includeDocIdColumn) {
236
236
  return `
237
- INSERT OR REPLACE INTO records (id, type, data_json, _meta_doc_id, _meta_permission_hint)
237
+ INSERT OR REPLACE INTO records (_id, _type, _data, _meta_doc_id, _meta_permission_hint)
238
238
  VALUES (?, ?, ?, ?, ?)`.trim();
239
239
  } else {
240
240
  return `
241
- INSERT OR REPLACE INTO records (id, type, data_json)
241
+ INSERT OR REPLACE INTO records (_id, _type, _data)
242
242
  VALUES (?, ?, ?)`.trim();
243
243
  }
244
244
  }
@@ -247,16 +247,16 @@ VALUES (?, ?, ?)`.trim();
247
247
  */
248
248
  static buildDeleteSQL(options) {
249
249
  if (options.includeDocIdColumn) {
250
- return "DELETE FROM records WHERE type = ? AND id = ?";
250
+ return "DELETE FROM records WHERE _type = ? AND _id = ?";
251
251
  } else {
252
- return "DELETE FROM records WHERE type = ? AND id = ?";
252
+ return "DELETE FROM records WHERE _type = ? AND _id = ?";
253
253
  }
254
254
  }
255
255
  /**
256
256
  * Generate DELETE statement for stringset values
257
257
  */
258
258
  static buildDeleteStringSetSQL() {
259
- return "DELETE FROM stringset_index WHERE type = ? AND record_id = ?";
259
+ return "DELETE FROM stringset_index WHERE _type = ? AND _record_id = ?";
260
260
  }
261
261
  /**
262
262
  * Generate INSERT statement for stringset values
@@ -264,11 +264,11 @@ VALUES (?, ?, ?)`.trim();
264
264
  static buildInsertStringSetSQL(options) {
265
265
  if (options.includeDocIdColumn) {
266
266
  return `
267
- INSERT OR IGNORE INTO stringset_index (record_id, type, field, value, _meta_doc_id)
267
+ INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value, _meta_doc_id)
268
268
  VALUES (?, ?, ?, ?, ?)`.trim();
269
269
  } else {
270
270
  return `
271
- INSERT OR IGNORE INTO stringset_index (record_id, type, field, value)
271
+ INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value)
272
272
  VALUES (?, ?, ?, ?)`.trim();
273
273
  }
274
274
  }
@@ -320,8 +320,7 @@ var JsonSchemaEngine = class extends DatabaseEngine {
320
320
  */
321
321
  async insert(modelName, data) {
322
322
  await this.initializeSchema();
323
- const { id, _meta_doc_id, _meta_permission_hint, ...rest } = data;
324
- const { type: _type, ...fieldsForJson } = rest;
323
+ const { id, _meta_doc_id, _meta_permission_hint, ...fieldsForJson } = data;
325
324
  const dataJson = JSON.stringify(fieldsForJson);
326
325
  const sql = JsonSchemaDDL.buildInsertSQL(this.schemaOptions);
327
326
  if (this.schemaOptions.includeDocIdColumn) {
@@ -356,11 +355,11 @@ var JsonSchemaEngine = class extends DatabaseEngine {
356
355
  );
357
356
  }
358
357
  await this.execSql(
359
- "DELETE FROM records WHERE type = ? AND _meta_doc_id = ?",
358
+ "DELETE FROM records WHERE _type = ? AND _meta_doc_id = ?",
360
359
  [modelName, docId]
361
360
  );
362
361
  await this.execSql(
363
- "DELETE FROM stringset_index WHERE type = ? AND _meta_doc_id = ?",
362
+ "DELETE FROM stringset_index WHERE _type = ? AND _meta_doc_id = ?",
364
363
  [modelName, docId]
365
364
  );
366
365
  }
@@ -390,7 +389,7 @@ var JsonSchemaEngine = class extends DatabaseEngine {
390
389
  async removeStringSetValues(modelName, fieldName, recordId, values) {
391
390
  if (values.length === 0) return;
392
391
  const placeholders = values.map(() => "?").join(", ");
393
- const sql = `DELETE FROM stringset_index WHERE type = ? AND field = ? AND record_id = ? AND value IN (${placeholders})`;
392
+ const sql = `DELETE FROM stringset_index WHERE _type = ? AND field = ? AND _record_id = ? AND value IN (${placeholders})`;
394
393
  await this.execSql(sql, [modelName, fieldName, recordId, ...values]);
395
394
  }
396
395
  /**
@@ -441,22 +440,22 @@ var JsonSchemaEngine = class extends DatabaseEngine {
441
440
  }
442
441
  /**
443
442
  * Parse a record row from the database.
444
- * Extracts fields from data_json and merges with direct columns.
443
+ * Extracts fields from _data and merges with direct columns.
445
444
  */
446
445
  parseRecordRow(row) {
447
446
  if (!row) return row;
448
- const { id, type, data_json, _meta_doc_id, _meta_permission_hint, ...rest } = row;
447
+ const { _id, _type, _data, _meta_doc_id, _meta_permission_hint, ...rest } = row;
449
448
  let parsedData = {};
450
- if (data_json) {
449
+ if (_data) {
451
450
  try {
452
- parsedData = JSON.parse(data_json);
451
+ parsedData = JSON.parse(_data);
453
452
  } catch (e) {
454
- console.warn("Failed to parse data_json:", e);
453
+ console.warn("Failed to parse _data:", e);
455
454
  }
456
455
  }
457
456
  const result = {
458
- id,
459
- type,
457
+ id: _id,
458
+ type: _type,
460
459
  ...parsedData,
461
460
  ...rest
462
461
  // Include any projected fields
@@ -508,6 +507,55 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
508
507
  PRIMARY KEY (model_name, field_name)
509
508
  )
510
509
  `);
510
+ const recordsCols = this.execSqlSync("PRAGMA table_info(records)");
511
+ const hasOldSchema = recordsCols.some((c) => c.name === "id");
512
+ if (hasOldSchema) {
513
+ this.execSqlSync("ALTER TABLE records RENAME COLUMN id TO _id");
514
+ this.execSqlSync("ALTER TABLE records RENAME COLUMN type TO _type");
515
+ this.execSqlSync("ALTER TABLE records RENAME COLUMN data_json TO _data");
516
+ this.execSqlSync("ALTER TABLE stringset_index RENAME COLUMN record_id TO _record_id");
517
+ this.execSqlSync("ALTER TABLE stringset_index RENAME COLUMN type TO _type");
518
+ this.execSqlSync("DROP INDEX IF EXISTS idx_records_type");
519
+ this.execSqlSync("CREATE INDEX IF NOT EXISTS idx_records_type ON records(_type)");
520
+ this.execSqlSync("DROP INDEX IF EXISTS idx_ss_type_field_value");
521
+ this.execSqlSync("CREATE INDEX IF NOT EXISTS idx_ss_type_field_value ON stringset_index(_type, field, value)");
522
+ this.execSqlSync("DROP INDEX IF EXISTS idx_ss_type_field_record");
523
+ this.execSqlSync("CREATE INDEX IF NOT EXISTS idx_ss_type_field_record ON stringset_index(_type, field, _record_id)");
524
+ try {
525
+ const indexes = this.execSqlSync(
526
+ "SELECT model_name, field_name FROM _indexes"
527
+ );
528
+ for (const row of indexes) {
529
+ const mn = row.model_name;
530
+ const fn = row.field_name;
531
+ const idxName = `idx_records_${mn.toLowerCase()}_${fn.toLowerCase()}`;
532
+ this.execSqlSync(`DROP INDEX IF EXISTS ${idxName}`);
533
+ this.execSqlSync(
534
+ `CREATE INDEX IF NOT EXISTS ${idxName} ON records(json_extract(_data, '$.${fn}')) WHERE _type = '${mn}'`
535
+ );
536
+ }
537
+ } catch (e) {
538
+ console.debug("Could not recreate field indexes during migration:", e);
539
+ }
540
+ try {
541
+ const constraints = this.execSqlSync(
542
+ "SELECT model_name, constraint_name, fields_json FROM _unique_constraints"
543
+ );
544
+ for (const row of constraints) {
545
+ const mn = row.model_name;
546
+ const cn = row.constraint_name;
547
+ const fields = JSON.parse(row.fields_json);
548
+ const idxName = `idx_uc_${mn.toLowerCase()}_${cn.toLowerCase()}`;
549
+ this.execSqlSync(`DROP INDEX IF EXISTS ${idxName}`);
550
+ const fieldExprs = fields.map((f) => `json_extract(_data, '$.${f}')`).join(", ");
551
+ this.execSqlSync(
552
+ `CREATE INDEX IF NOT EXISTS ${idxName} ON records(${fieldExprs}) WHERE _type = '${mn}'`
553
+ );
554
+ }
555
+ } catch (e) {
556
+ console.debug("Could not recreate unique constraint indexes during migration:", e);
557
+ }
558
+ }
511
559
  }
512
560
  /**
513
561
  * Load indexes from the _indexes table and re-ensure they exist.
@@ -595,10 +643,10 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
595
643
  VALUES (?, ?, ?)`,
596
644
  [modelName, constraintName, JSON.stringify(fields)]
597
645
  );
598
- const fieldExprs = fields.map((f) => `json_extract(data_json, '$.${f}')`).join(", ");
646
+ const fieldExprs = fields.map((f) => `json_extract(_data, '$.${f}')`).join(", ");
599
647
  const indexName = `idx_uc_${modelName.toLowerCase()}_${constraintName.toLowerCase()}`;
600
648
  this.execSqlSync(
601
- `CREATE INDEX IF NOT EXISTS ${indexName} ON records(${fieldExprs}) WHERE type = '${modelName}'`
649
+ `CREATE INDEX IF NOT EXISTS ${indexName} ON records(${fieldExprs}) WHERE _type = '${modelName}'`
602
650
  );
603
651
  }
604
652
  /**
@@ -638,11 +686,11 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
638
686
  const value = data[idx.field_name];
639
687
  if (value === null || value === void 0) continue;
640
688
  const conflicts = this.execSqlSync(
641
- `SELECT id FROM records WHERE type = ? AND json_extract(data_json, '$.${idx.field_name}') = ? AND id != ? LIMIT 1`,
689
+ `SELECT _id FROM records WHERE _type = ? AND json_extract(_data, '$.${idx.field_name}') = ? AND _id != ? LIMIT 1`,
642
690
  [modelName, value, id]
643
691
  );
644
692
  if (conflicts.length > 0) {
645
- return `Unique constraint violated on field '${idx.field_name}' for model '${modelName}'. Value '${String(value).substring(0, 50)}' already exists on record '${conflicts[0].id}'.`;
693
+ return `Unique constraint violated on field '${idx.field_name}' for model '${modelName}'. Value '${String(value).substring(0, 50)}' already exists on record '${conflicts[0]._id}'.`;
646
694
  }
647
695
  }
648
696
  const composites = this.listUniqueConstraints(modelName);
@@ -652,13 +700,13 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
652
700
  }
653
701
  const values = constraint.fields.map((f) => data[f]);
654
702
  if (values.some((v) => v === null || v === void 0)) continue;
655
- const conditions = constraint.fields.map((f) => `json_extract(data_json, '$.${f}') = ?`).join(" AND ");
703
+ const conditions = constraint.fields.map((f) => `json_extract(_data, '$.${f}') = ?`).join(" AND ");
656
704
  const conflicts = this.execSqlSync(
657
- `SELECT id FROM records WHERE type = ? AND ${conditions} AND id != ? LIMIT 1`,
705
+ `SELECT _id FROM records WHERE _type = ? AND ${conditions} AND _id != ? LIMIT 1`,
658
706
  [modelName, ...values, id]
659
707
  );
660
708
  if (conflicts.length > 0) {
661
- return `Unique constraint '${constraint.constraint_name}' violated for model '${modelName}' on fields [${constraint.fields.join(", ")}]. Values already exist on record '${conflicts[0].id}'.`;
709
+ return `Unique constraint '${constraint.constraint_name}' violated for model '${modelName}' on fields [${constraint.fields.join(", ")}]. Values already exist on record '${conflicts[0]._id}'.`;
662
710
  }
663
711
  }
664
712
  return null;
@@ -668,7 +716,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
668
716
  */
669
717
  recordExists(modelName, id) {
670
718
  const rows = this.execSqlSync(
671
- "SELECT 1 FROM records WHERE type = ? AND id = ? LIMIT 1",
719
+ "SELECT 1 FROM records WHERE _type = ? AND _id = ? LIMIT 1",
672
720
  [modelName, id]
673
721
  );
674
722
  return rows.length > 0;
@@ -726,25 +774,24 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
726
774
  */
727
775
  async insertWithStringSets(modelName, data, stringSets) {
728
776
  this.storage.transactionSync(() => {
729
- const { id, ...rest } = data;
730
- const { type: _type, ...fieldsForJson } = rest;
777
+ const { id, ...fieldsForJson } = data;
731
778
  const jsonFields = { ...fieldsForJson, ...stringSets };
732
779
  const dataJson = JSON.stringify(jsonFields);
733
780
  this.sql.exec(
734
- "INSERT OR REPLACE INTO records (id, type, data_json) VALUES (?, ?, ?)",
781
+ "INSERT OR REPLACE INTO records (_id, _type, _data) VALUES (?, ?, ?)",
735
782
  id,
736
783
  modelName,
737
784
  dataJson
738
785
  );
739
786
  this.sql.exec(
740
- "DELETE FROM stringset_index WHERE type = ? AND record_id = ?",
787
+ "DELETE FROM stringset_index WHERE _type = ? AND _record_id = ?",
741
788
  modelName,
742
789
  id
743
790
  );
744
791
  for (const [fieldName, values] of Object.entries(stringSets)) {
745
792
  for (const value of values) {
746
793
  this.sql.exec(
747
- "INSERT OR IGNORE INTO stringset_index (record_id, type, field, value) VALUES (?, ?, ?, ?)",
794
+ "INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value) VALUES (?, ?, ?, ?)",
748
795
  id,
749
796
  modelName,
750
797
  fieldName,
@@ -772,7 +819,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
772
819
  for (const [field, values] of Object.entries(sets)) {
773
820
  for (const value of values) {
774
821
  this.sql.exec(
775
- "INSERT OR IGNORE INTO stringset_index (record_id, type, field, value) VALUES (?, ?, ?, ?)",
822
+ "INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value) VALUES (?, ?, ?, ?)",
776
823
  id,
777
824
  modelName,
778
825
  field,
@@ -800,7 +847,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
800
847
  for (const [field, values] of Object.entries(sets)) {
801
848
  for (const value of values) {
802
849
  this.sql.exec(
803
- "DELETE FROM stringset_index WHERE record_id = ? AND type = ? AND field = ? AND value = ?",
850
+ "DELETE FROM stringset_index WHERE _record_id = ? AND _type = ? AND field = ? AND value = ?",
804
851
  id,
805
852
  modelName,
806
853
  field,
@@ -816,20 +863,20 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
816
863
  */
817
864
  _syncStringSetsToJson(modelName, id, fields) {
818
865
  const rows = this.execSqlSync(
819
- "SELECT data_json FROM records WHERE id = ? AND type = ?",
866
+ "SELECT _data FROM records WHERE _id = ? AND _type = ?",
820
867
  [id, modelName]
821
868
  );
822
869
  if (rows.length === 0) return;
823
- const data = JSON.parse(rows[0].data_json);
870
+ const data = JSON.parse(rows[0]._data);
824
871
  for (const field of fields) {
825
872
  const ssRows = this.execSqlSync(
826
- "SELECT value FROM stringset_index WHERE record_id = ? AND type = ? AND field = ? ORDER BY value",
873
+ "SELECT value FROM stringset_index WHERE _record_id = ? AND _type = ? AND field = ? ORDER BY value",
827
874
  [id, modelName, field]
828
875
  );
829
876
  data[field] = ssRows.map((r) => r.value);
830
877
  }
831
878
  this.sql.exec(
832
- "UPDATE records SET data_json = ? WHERE id = ? AND type = ?",
879
+ "UPDATE records SET _data = ? WHERE _id = ? AND _type = ?",
833
880
  JSON.stringify(data),
834
881
  id,
835
882
  modelName
@@ -855,14 +902,14 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
855
902
  */
856
903
  patchRecordRaw(modelName, id, fields, stringSets) {
857
904
  const rows = this.execSqlSync(
858
- "SELECT data_json FROM records WHERE id = ? AND type = ?",
905
+ "SELECT _data FROM records WHERE _id = ? AND _type = ?",
859
906
  [id, modelName]
860
907
  );
861
908
  if (rows.length === 0) {
862
909
  return false;
863
910
  }
864
- const existing = JSON.parse(rows[0].data_json);
865
- const { id: _id, type: _type, ...patchFields } = fields;
911
+ const existing = JSON.parse(rows[0]._data);
912
+ const { id: _stripId, ...patchFields } = fields;
866
913
  const merged = { ...existing, ...patchFields };
867
914
  if (stringSets) {
868
915
  for (const [field, values] of Object.entries(stringSets)) {
@@ -870,7 +917,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
870
917
  }
871
918
  }
872
919
  this.sql.exec(
873
- "UPDATE records SET data_json = ? WHERE id = ? AND type = ?",
920
+ "UPDATE records SET _data = ? WHERE _id = ? AND _type = ?",
874
921
  JSON.stringify(merged),
875
922
  id,
876
923
  modelName
@@ -878,14 +925,14 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
878
925
  if (stringSets) {
879
926
  for (const [fieldName, values] of Object.entries(stringSets)) {
880
927
  this.sql.exec(
881
- "DELETE FROM stringset_index WHERE record_id = ? AND type = ? AND field = ?",
928
+ "DELETE FROM stringset_index WHERE _record_id = ? AND _type = ? AND field = ?",
882
929
  id,
883
930
  modelName,
884
931
  fieldName
885
932
  );
886
933
  for (const value of values) {
887
934
  this.sql.exec(
888
- "INSERT OR IGNORE INTO stringset_index (record_id, type, field, value) VALUES (?, ?, ?, ?)",
935
+ "INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value) VALUES (?, ?, ?, ?)",
889
936
  id,
890
937
  modelName,
891
938
  fieldName,
@@ -916,11 +963,11 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
916
963
  */
917
964
  incrementFieldsRaw(modelName, id, fields) {
918
965
  const rows = this.execSqlSync(
919
- "SELECT data_json FROM records WHERE id = ? AND type = ?",
966
+ "SELECT _data FROM records WHERE _id = ? AND _type = ?",
920
967
  [id, modelName]
921
968
  );
922
969
  if (rows.length === 0) return null;
923
- const data = JSON.parse(rows[0].data_json);
970
+ const data = JSON.parse(rows[0]._data);
924
971
  const newValues = {};
925
972
  for (const [field, delta] of Object.entries(fields)) {
926
973
  const current = typeof data[field] === "number" ? data[field] : 0;
@@ -928,7 +975,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
928
975
  newValues[field] = data[field];
929
976
  }
930
977
  this.sql.exec(
931
- "UPDATE records SET data_json = ? WHERE id = ? AND type = ?",
978
+ "UPDATE records SET _data = ? WHERE _id = ? AND _type = ?",
932
979
  JSON.stringify(data),
933
980
  id,
934
981
  modelName
@@ -940,9 +987,9 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
940
987
  */
941
988
  async deleteWithStringSets(modelName, id) {
942
989
  this.storage.transactionSync(() => {
943
- this.sql.exec("DELETE FROM records WHERE type = ? AND id = ?", modelName, id);
990
+ this.sql.exec("DELETE FROM records WHERE _type = ? AND _id = ?", modelName, id);
944
991
  this.sql.exec(
945
- "DELETE FROM stringset_index WHERE type = ? AND record_id = ?",
992
+ "DELETE FROM stringset_index WHERE _type = ? AND _record_id = ?",
946
993
  modelName,
947
994
  id
948
995
  );
@@ -954,7 +1001,7 @@ var DurableObjectEngine = class extends JsonSchemaEngine {
954
1001
  */
955
1002
  trackModelFields(modelName, data) {
956
1003
  for (const [key, value] of Object.entries(data)) {
957
- if (key === "id" || key === "type" || value === null || value === void 0) {
1004
+ if (key === "id" || value === null || value === void 0) {
958
1005
  continue;
959
1006
  }
960
1007
  let inferredType;
@@ -1277,18 +1324,20 @@ var JsonQueryTranslator = class {
1277
1324
  }
1278
1325
  /**
1279
1326
  * Get SQL expression for a field.
1280
- * System fields (id, type) are direct columns; others use json_extract.
1327
+ * System fields (id, type) map to internal columns (_id, _type);
1328
+ * others use json_extract(_data, ...).
1281
1329
  * When no schema is provided, any field is accepted (schemaless mode).
1282
1330
  */
1283
1331
  getFieldSql(fieldName) {
1284
1332
  if (!this.fieldSqlCache.has(fieldName)) {
1285
1333
  if (SYSTEM_FIELDS.has(fieldName)) {
1286
- this.fieldSqlCache.set(fieldName, quoteIdentifier(fieldName));
1334
+ const internalName = `_${fieldName}`;
1335
+ this.fieldSqlCache.set(fieldName, quoteIdentifier(internalName));
1287
1336
  } else {
1288
1337
  assertValidIdentifier(fieldName, "query field");
1289
1338
  this.fieldSqlCache.set(
1290
1339
  fieldName,
1291
- `json_extract(data_json, '$.${fieldName}')`
1340
+ `json_extract(_data, '$.${fieldName}')`
1292
1341
  );
1293
1342
  }
1294
1343
  }
@@ -1315,7 +1364,7 @@ var JsonQueryTranslator = class {
1315
1364
  const selectClause = this.buildSelectClause(options?.projection);
1316
1365
  let sql = `SELECT ${selectClause} FROM records`;
1317
1366
  const params = [];
1318
- const conditions = [`${quoteIdentifier("type")} = ?`];
1367
+ const conditions = [`${quoteIdentifier("_type")} = ?`];
1319
1368
  params.push(this.modelName);
1320
1369
  if (whereClause.sql) {
1321
1370
  conditions.push(whereClause.sql);
@@ -1351,7 +1400,7 @@ var JsonQueryTranslator = class {
1351
1400
  */
1352
1401
  translateCount(filter, options) {
1353
1402
  const whereClause = this.translateFilter(filter);
1354
- const conditions = [`${quoteIdentifier("type")} = ?`];
1403
+ const conditions = [`${quoteIdentifier("_type")} = ?`];
1355
1404
  const params = [this.modelName];
1356
1405
  if (whereClause.sql) {
1357
1406
  conditions.push(whereClause.sql);
@@ -1536,7 +1585,7 @@ var JsonQueryTranslator = class {
1536
1585
  }
1537
1586
  }
1538
1587
  if (fieldType === "stringset") {
1539
- const likeSql = `EXISTS (SELECT 1 FROM stringset_index WHERE stringset_index.type = ? AND stringset_index.field = ? AND stringset_index.record_id = records.id AND stringset_index.value LIKE ? ESCAPE '\\' COLLATE NOCASE)`;
1588
+ const likeSql = `EXISTS (SELECT 1 FROM stringset_index WHERE stringset_index._type = ? AND stringset_index.field = ? AND stringset_index._record_id = records._id AND stringset_index.value LIKE ? ESCAPE '\\' COLLATE NOCASE)`;
1540
1589
  conditions.push(likeSql);
1541
1590
  params.push(this.modelName, fieldName, pattern);
1542
1591
  } else {
@@ -1682,10 +1731,10 @@ var JsonQueryTranslator = class {
1682
1731
  return value ? { sql: `${fieldSql} IS NOT NULL`, params: [] } : { sql: `${fieldSql} IS NULL`, params: [] };
1683
1732
  } else {
1684
1733
  return value ? {
1685
- sql: `json_type(data_json, '$.${fieldName}') IS NOT NULL`,
1734
+ sql: `json_type(_data, '$.${fieldName}') IS NOT NULL`,
1686
1735
  params: []
1687
1736
  } : {
1688
- sql: `json_type(data_json, '$.${fieldName}') IS NULL`,
1737
+ sql: `json_type(_data, '$.${fieldName}') IS NULL`,
1689
1738
  params: []
1690
1739
  };
1691
1740
  }
@@ -1707,7 +1756,7 @@ var JsonQueryTranslator = class {
1707
1756
  );
1708
1757
  }
1709
1758
  return {
1710
- sql: `EXISTS (SELECT 1 FROM stringset_index WHERE stringset_index.type = ? AND stringset_index.field = ? AND stringset_index.record_id = records.id AND stringset_index.value = ?)`,
1759
+ sql: `EXISTS (SELECT 1 FROM stringset_index WHERE stringset_index._type = ? AND stringset_index.field = ? AND stringset_index._record_id = records._id AND stringset_index.value = ?)`,
1711
1760
  params: [this.modelName, fieldName, value]
1712
1761
  };
1713
1762
  default:
@@ -1725,7 +1774,7 @@ var JsonQueryTranslator = class {
1725
1774
  */
1726
1775
  buildSelectClause(projection) {
1727
1776
  if (!projection || Object.keys(projection).length === 0) {
1728
- return "id, type, data_json";
1777
+ return "_id, _type, _data";
1729
1778
  }
1730
1779
  const includeFields = [];
1731
1780
  const excludeFields = [];
@@ -1751,18 +1800,18 @@ var JsonQueryTranslator = class {
1751
1800
  if (!includeFields.includes("id")) {
1752
1801
  includeFields.unshift("id");
1753
1802
  }
1754
- const selectParts = ["id", "type"];
1803
+ const selectParts = ["_id", "_type"];
1755
1804
  for (const field of includeFields) {
1756
1805
  if (field === "id" || field === "type") continue;
1757
1806
  selectParts.push(
1758
- `json_extract(data_json, '$.${field}') AS ${quoteIdentifier(field)}`
1807
+ `json_extract(_data, '$.${field}') AS ${quoteIdentifier(field)}`
1759
1808
  );
1760
1809
  }
1761
1810
  return selectParts.join(", ");
1762
1811
  } else if (hasExcludes) {
1763
- return "id, type, data_json";
1812
+ return "_id, _type, _data";
1764
1813
  }
1765
- return "id, type, data_json";
1814
+ return "_id, _type, _data";
1766
1815
  }
1767
1816
  /**
1768
1817
  * Build LIMIT clause
@@ -2104,11 +2153,9 @@ function createDatabaseDO(config = {}) {
2104
2153
  /** @internal — Check for reserved field names in record data */
2105
2154
  _checkReservedFields(data) {
2106
2155
  for (const key of Object.keys(data)) {
2107
- if (key === "type") {
2108
- return `Field 'type' is reserved and cannot be used in record data`;
2109
- }
2110
- if (key.startsWith("_meta")) {
2111
- return `Field '${key}' is reserved (fields starting with '_meta' are internal) and cannot be used in record data`;
2156
+ if (key === "id") continue;
2157
+ if (key.startsWith("_")) {
2158
+ return `Field '${key}' is reserved (fields starting with '_' are internal)`;
2112
2159
  }
2113
2160
  }
2114
2161
  return null;
@@ -2216,11 +2263,11 @@ function createDatabaseDO(config = {}) {
2216
2263
  }
2217
2264
  }
2218
2265
  const existing = this._engine.execSqlSync(
2219
- "SELECT data_json FROM records WHERE id = ? AND type = ?",
2266
+ "SELECT _data FROM records WHERE _id = ? AND _type = ?",
2220
2267
  [id, modelName]
2221
2268
  );
2222
2269
  if (existing.length > 0) {
2223
- const existingData = JSON.parse(existing[0].data_json);
2270
+ const existingData = JSON.parse(existing[0]._data);
2224
2271
  const mergedData = { ...existingData, ...data };
2225
2272
  const violation = this._engine.checkUniqueConstraints(
2226
2273
  modelName,
@@ -2252,7 +2299,7 @@ function createDatabaseDO(config = {}) {
2252
2299
  if (hooks?.beforeDelete) {
2253
2300
  let record = null;
2254
2301
  const rows = this._engine.execSqlSync(
2255
- "SELECT id, type, data_json FROM records WHERE id = ? AND type = ?",
2302
+ "SELECT _id, _type, _data FROM records WHERE _id = ? AND _type = ?",
2256
2303
  [id, modelName]
2257
2304
  );
2258
2305
  if (rows.length > 0) {
@@ -2326,7 +2373,7 @@ function createDatabaseDO(config = {}) {
2326
2373
  if (hooks?.beforeDelete) {
2327
2374
  let record = null;
2328
2375
  const rows = this._engine.execSqlSync(
2329
- "SELECT id, type, data_json FROM records WHERE id = ? AND type = ?",
2376
+ "SELECT _id, _type, _data FROM records WHERE _id = ? AND _type = ?",
2330
2377
  [op.id, op.modelName]
2331
2378
  );
2332
2379
  if (rows.length > 0) {
@@ -2412,30 +2459,30 @@ function createDatabaseDO(config = {}) {
2412
2459
  }
2413
2460
  }
2414
2461
  if (op.stringSets && Object.keys(op.stringSets).length > 0) {
2415
- const { id: _id, type: _type, ...fieldsForJson } = op.data;
2462
+ const { id: _id, ...fieldsForJson } = op.data;
2416
2463
  const jsonFields = { ...fieldsForJson, ...op.stringSets };
2417
2464
  const dataJson = JSON.stringify(jsonFields);
2418
2465
  this._engine.execSqlSync(
2419
- "INSERT OR REPLACE INTO records (id, type, data_json) VALUES (?, ?, ?)",
2466
+ "INSERT OR REPLACE INTO records (_id, _type, _data) VALUES (?, ?, ?)",
2420
2467
  [op.id, op.modelName, dataJson]
2421
2468
  );
2422
2469
  this._engine.execSqlSync(
2423
- "DELETE FROM stringset_index WHERE type = ? AND record_id = ?",
2470
+ "DELETE FROM stringset_index WHERE _type = ? AND _record_id = ?",
2424
2471
  [op.modelName, op.id]
2425
2472
  );
2426
2473
  for (const [fieldName, values] of Object.entries(op.stringSets)) {
2427
2474
  for (const value of values) {
2428
2475
  this._engine.execSqlSync(
2429
- "INSERT OR IGNORE INTO stringset_index (record_id, type, field, value) VALUES (?, ?, ?, ?)",
2476
+ "INSERT OR IGNORE INTO stringset_index (_record_id, _type, field, value) VALUES (?, ?, ?, ?)",
2430
2477
  [op.id, op.modelName, fieldName, value]
2431
2478
  );
2432
2479
  }
2433
2480
  }
2434
2481
  } else {
2435
- const { id: _id, type: _type, ...fieldsForJson } = op.data;
2482
+ const { id: _id, ...fieldsForJson } = op.data;
2436
2483
  const dataJson = JSON.stringify(fieldsForJson);
2437
2484
  this._engine.execSqlSync(
2438
- "INSERT OR REPLACE INTO records (id, type, data_json) VALUES (?, ?, ?)",
2485
+ "INSERT OR REPLACE INTO records (_id, _type, _data) VALUES (?, ?, ?)",
2439
2486
  [op.id, op.modelName, dataJson]
2440
2487
  );
2441
2488
  }
@@ -2452,11 +2499,11 @@ function createDatabaseDO(config = {}) {
2452
2499
  }
2453
2500
  if (op.data) {
2454
2501
  const existing = this._engine.execSqlSync(
2455
- "SELECT data_json FROM records WHERE id = ? AND type = ?",
2502
+ "SELECT _data FROM records WHERE _id = ? AND _type = ?",
2456
2503
  [op.id, op.modelName]
2457
2504
  );
2458
2505
  if (existing.length > 0) {
2459
- const existingData = JSON.parse(existing[0].data_json);
2506
+ const existingData = JSON.parse(existing[0]._data);
2460
2507
  const mergedData = { ...existingData, ...op.data };
2461
2508
  const violation = this._engine.checkUniqueConstraints(
2462
2509
  op.modelName,
@@ -2491,11 +2538,11 @@ function createDatabaseDO(config = {}) {
2491
2538
  }
2492
2539
  } else if (op.op === "delete") {
2493
2540
  this._engine.execSqlSync(
2494
- "DELETE FROM records WHERE id = ? AND type = ?",
2541
+ "DELETE FROM records WHERE _id = ? AND _type = ?",
2495
2542
  [op.id, op.modelName]
2496
2543
  );
2497
2544
  this._engine.execSqlSync(
2498
- "DELETE FROM stringset_index WHERE record_id = ? AND type = ?",
2545
+ "DELETE FROM stringset_index WHERE _record_id = ? AND _type = ?",
2499
2546
  [op.id, op.modelName]
2500
2547
  );
2501
2548
  results.push({ success: true, id: op.id });
@@ -2707,7 +2754,7 @@ function createDatabaseDO(config = {}) {
2707
2754
  for (const field of regularGroupBy) {
2708
2755
  assertValidIdentifier(field, "aggregation groupBy field");
2709
2756
  const ssCheck = this._engine.execSqlSync(
2710
- "SELECT 1 FROM stringset_index WHERE type = ? AND field = ? LIMIT 1",
2757
+ "SELECT 1 FROM stringset_index WHERE _type = ? AND field = ? LIMIT 1",
2711
2758
  [modelName, field]
2712
2759
  );
2713
2760
  if (ssCheck.length > 0) {
@@ -2783,9 +2830,9 @@ function createDatabaseDO(config = {}) {
2783
2830
  }
2784
2831
  }
2785
2832
  let sql = `SELECT ${selectParts.join(", ")} FROM stringset_index`;
2786
- sql += ` INNER JOIN records ON stringset_index.record_id = records.id AND records.type = stringset_index.type`;
2833
+ sql += ` INNER JOIN records ON stringset_index._record_id = records._id AND records._type = stringset_index._type`;
2787
2834
  const conditions = [
2788
- "stringset_index.type = ?",
2835
+ "stringset_index._type = ?",
2789
2836
  "stringset_index.field = ?"
2790
2837
  ];
2791
2838
  const params = [modelName, facetField];
@@ -2822,9 +2869,9 @@ function createDatabaseDO(config = {}) {
2822
2869
  const m = stringSetMemberships[i];
2823
2870
  const alias = `ss_${m.field}_${i}`;
2824
2871
  selectParts.push(
2825
- `CASE WHEN ${alias}.record_id IS NOT NULL THEN 'true' ELSE 'false' END AS "${alias}"`
2872
+ `CASE WHEN ${alias}._record_id IS NOT NULL THEN 'true' ELSE 'false' END AS "${alias}"`
2826
2873
  );
2827
- groupByParts.push(`CASE WHEN ${alias}.record_id IS NOT NULL THEN 'true' ELSE 'false' END`);
2874
+ groupByParts.push(`CASE WHEN ${alias}._record_id IS NOT NULL THEN 'true' ELSE 'false' END`);
2828
2875
  aliasMap.push({ alias, field: m.field, contains: m.contains });
2829
2876
  }
2830
2877
  for (const op of aggOptions.operations) {
@@ -2850,13 +2897,13 @@ function createDatabaseDO(config = {}) {
2850
2897
  const joinParams = [];
2851
2898
  for (const entry of aliasMap) {
2852
2899
  sql += ` LEFT JOIN stringset_index AS ${entry.alias}`;
2853
- sql += ` ON ${entry.alias}.record_id = records.id`;
2854
- sql += ` AND ${entry.alias}.type = records.type`;
2900
+ sql += ` ON ${entry.alias}._record_id = records._id`;
2901
+ sql += ` AND ${entry.alias}._type = records._type`;
2855
2902
  sql += ` AND ${entry.alias}.field = ?`;
2856
2903
  sql += ` AND ${entry.alias}.value = ?`;
2857
2904
  joinParams.push(entry.field, entry.contains);
2858
2905
  }
2859
- const conditions = ["records.type = ?"];
2906
+ const conditions = ["records._type = ?"];
2860
2907
  const params = [...joinParams, modelName];
2861
2908
  if (filter && Object.keys(filter).length > 0) {
2862
2909
  const whereClause = translator.translateFilter(filter);
@@ -3114,7 +3161,7 @@ function createDatabaseDO(config = {}) {
3114
3161
  );
3115
3162
  }
3116
3163
  const check = this._engine.execSqlSync(
3117
- `SELECT 1 FROM records WHERE type = ? AND json_type(data_json, '$.${field}') IS NOT NULL AND json_type(data_json, '$.${field}') != 'array' LIMIT 1`,
3164
+ `SELECT 1 FROM records WHERE _type = ? AND json_type(_data, '$.${field}') IS NOT NULL AND json_type(_data, '$.${field}') != 'array' LIMIT 1`,
3118
3165
  [modelName]
3119
3166
  );
3120
3167
  if (check.length > 0) {
@@ -3138,7 +3185,7 @@ function createDatabaseDO(config = {}) {
3138
3185
  includeDocId: false
3139
3186
  });
3140
3187
  const whereClause = translator.translateFilter(condition);
3141
- let sql = "SELECT 1 FROM records WHERE id = ? AND type = ?";
3188
+ let sql = "SELECT 1 FROM records WHERE _id = ? AND _type = ?";
3142
3189
  const params = [id, modelName];
3143
3190
  if (whereClause.sql) {
3144
3191
  sql += ` AND ${whereClause.sql}`;
@@ -3165,7 +3212,7 @@ function createDatabaseDO(config = {}) {
3165
3212
  /** @internal — List all known model names from records and _model_fields */
3166
3213
  _handleModelList() {
3167
3214
  const fromRecords = this._engine.execSqlSync(
3168
- "SELECT DISTINCT type FROM records ORDER BY type"
3215
+ "SELECT DISTINCT _type FROM records ORDER BY _type"
3169
3216
  );
3170
3217
  const fromFields = this._engine.execSqlSync(
3171
3218
  "SELECT DISTINCT model_name FROM _model_fields ORDER BY model_name"
@@ -3174,7 +3221,7 @@ function createDatabaseDO(config = {}) {
3174
3221
  "SELECT DISTINCT model_name FROM _indexes ORDER BY model_name"
3175
3222
  );
3176
3223
  const modelSet = /* @__PURE__ */ new Set();
3177
- for (const row of fromRecords) modelSet.add(row.type);
3224
+ for (const row of fromRecords) modelSet.add(row._type);
3178
3225
  for (const row of fromFields) modelSet.add(row.model_name);
3179
3226
  for (const row of fromIndexes) modelSet.add(row.model_name);
3180
3227
  return Response.json({ models: Array.from(modelSet).sort() });
@@ -3186,16 +3233,16 @@ function createDatabaseDO(config = {}) {
3186
3233
  }
3187
3234
  /** @internal */
3188
3235
  _parseRow(row) {
3189
- const { id, type, data_json, ...rest } = row;
3236
+ const { _id, _type, _data, ...rest } = row;
3190
3237
  let parsed = {};
3191
- if (data_json) {
3238
+ if (_data) {
3192
3239
  try {
3193
- parsed = JSON.parse(data_json);
3240
+ parsed = JSON.parse(_data);
3194
3241
  } catch (e) {
3195
- console.warn("Failed to parse data_json:", e);
3242
+ console.warn("Failed to parse _data:", e);
3196
3243
  }
3197
3244
  }
3198
- return { id, type, ...parsed, ...rest };
3245
+ return { id: _id, type: _type, ...parsed, ...rest };
3199
3246
  }
3200
3247
  // ─── Include (Related Data Loading) ──────────────────────────────
3201
3248
  /** @internal — Validate an IncludeSpec, returning an error message or null */
@@ -3425,12 +3472,12 @@ function createDatabaseDO(config = {}) {
3425
3472
  _resolveHasManyWithLimit(spec, parentValues) {
3426
3473
  const foreignKey = spec.foreignKey;
3427
3474
  assertValidIdentifier(foreignKey, "include foreignKey");
3428
- let sortClause = `"id" ASC`;
3475
+ let sortClause = `"_id" ASC`;
3429
3476
  if (spec.sort) {
3430
3477
  const parts = [];
3431
3478
  for (const [field, dir] of Object.entries(spec.sort)) {
3432
3479
  assertValidIdentifier(field, "include sort field");
3433
- const fieldSql = field === "id" || field === "type" ? `"${field}"` : `json_extract(data_json, '$.${field}')`;
3480
+ const fieldSql = field === "id" ? `"_id"` : field === "type" ? `"_type"` : `json_extract(_data, '$.${field}')`;
3434
3481
  parts.push(`${fieldSql} ${dir === -1 ? "DESC" : "ASC"}`);
3435
3482
  }
3436
3483
  sortClause = parts.join(", ");
@@ -3454,15 +3501,15 @@ function createDatabaseDO(config = {}) {
3454
3501
  const chunk = parentValues.slice(i, i + chunkSize);
3455
3502
  const inPlaceholders = chunk.map(() => "?").join(", ");
3456
3503
  const sql = `
3457
- SELECT "id", "type", data_json FROM (
3458
- SELECT "id", "type", data_json,
3504
+ SELECT "_id", "_type", _data FROM (
3505
+ SELECT "_id", "_type", _data,
3459
3506
  ROW_NUMBER() OVER (
3460
- PARTITION BY json_extract(data_json, '$.${foreignKey}')
3507
+ PARTITION BY json_extract(_data, '$.${foreignKey}')
3461
3508
  ORDER BY ${sortClause}
3462
3509
  ) as _rn
3463
3510
  FROM records
3464
- WHERE "type" = ?
3465
- AND json_extract(data_json, '$.${foreignKey}') IN (${inPlaceholders})
3511
+ WHERE "_type" = ?
3512
+ AND json_extract(_data, '$.${foreignKey}') IN (${inPlaceholders})
3466
3513
  ${filterClause}
3467
3514
  ) WHERE _rn <= ?
3468
3515
  `;