edinburgh 0.4.6 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +403 -461
  2. package/build/src/datapack.d.ts +9 -9
  3. package/build/src/datapack.js +10 -10
  4. package/build/src/datapack.js.map +1 -1
  5. package/build/src/edinburgh.d.ts +21 -10
  6. package/build/src/edinburgh.js +33 -55
  7. package/build/src/edinburgh.js.map +1 -1
  8. package/build/src/indexes.d.ts +99 -288
  9. package/build/src/indexes.js +253 -636
  10. package/build/src/indexes.js.map +1 -1
  11. package/build/src/migrate.js +17 -39
  12. package/build/src/migrate.js.map +1 -1
  13. package/build/src/models.d.ts +177 -113
  14. package/build/src/models.js +487 -259
  15. package/build/src/models.js.map +1 -1
  16. package/build/src/types.d.ts +41 -51
  17. package/build/src/types.js +39 -52
  18. package/build/src/types.js.map +1 -1
  19. package/build/src/utils.d.ts +4 -4
  20. package/build/src/utils.js +4 -4
  21. package/package.json +1 -3
  22. package/skill/AnyModelClass.md +7 -0
  23. package/skill/FindOptions.md +37 -0
  24. package/skill/Lifecycle Hooks.md +24 -0
  25. package/skill/{Model_delete.md → Lifecycle Hooks_delete.md } +2 -2
  26. package/skill/{Model_getPrimaryKeyHash.md → Lifecycle Hooks_getPrimaryKeyHash.md } +1 -1
  27. package/skill/{Model_isValid.md → Lifecycle Hooks_isValid.md } +1 -1
  28. package/skill/Lifecycle Hooks_migrate.md +26 -0
  29. package/skill/{Model_preCommit.md → Lifecycle Hooks_preCommit.md } +3 -5
  30. package/skill/{Model_preventPersist.md → Lifecycle Hooks_preventPersist.md } +2 -2
  31. package/skill/{Model_validate.md → Lifecycle Hooks_validate.md } +2 -2
  32. package/skill/ModelBase.md +7 -0
  33. package/skill/ModelClass.md +8 -0
  34. package/skill/SKILL.md +253 -215
  35. package/skill/Schema Evolution.md +19 -0
  36. package/skill/TypeWrapper_containsNull.md +11 -0
  37. package/skill/TypeWrapper_deserialize.md +9 -0
  38. package/skill/TypeWrapper_getError.md +11 -0
  39. package/skill/TypeWrapper_serialize.md +10 -0
  40. package/skill/TypeWrapper_serializeType.md +9 -0
  41. package/skill/array.md +2 -2
  42. package/skill/defineModel.md +23 -0
  43. package/skill/deleteEverything.md +8 -0
  44. package/skill/field.md +4 -4
  45. package/skill/link.md +12 -10
  46. package/skill/literal.md +1 -1
  47. package/skill/opt.md +1 -1
  48. package/skill/or.md +1 -1
  49. package/skill/record.md +1 -1
  50. package/skill/set.md +2 -2
  51. package/skill/setOnSaveCallback.md +2 -2
  52. package/skill/transact.md +3 -3
  53. package/src/datapack.ts +10 -10
  54. package/src/edinburgh.ts +46 -58
  55. package/src/indexes.ts +338 -802
  56. package/src/migrate.ts +15 -37
  57. package/src/models.ts +617 -314
  58. package/src/types.ts +61 -54
  59. package/src/utils.ts +4 -4
  60. package/skill/BaseIndex.md +0 -16
  61. package/skill/BaseIndex_batchProcess.md +0 -10
  62. package/skill/BaseIndex_find.md +0 -7
  63. package/skill/Model.md +0 -22
  64. package/skill/Model_findAll.md +0 -12
  65. package/skill/Model_migrate.md +0 -34
  66. package/skill/Model_replaceInto.md +0 -16
  67. package/skill/PrimaryIndex.md +0 -8
  68. package/skill/PrimaryIndex_get.md +0 -17
  69. package/skill/PrimaryIndex_getLazy.md +0 -13
  70. package/skill/SecondaryIndex.md +0 -9
  71. package/skill/UniqueIndex.md +0 -9
  72. package/skill/UniqueIndex_get.md +0 -17
  73. package/skill/dump.md +0 -8
  74. package/skill/index.md +0 -32
  75. package/skill/primary.md +0 -26
  76. package/skill/registerModel.md +0 -26
  77. package/skill/unique.md +0 -32
package/src/migrate.ts CHANGED
@@ -1,10 +1,9 @@
1
1
  import * as lowlevel from "olmdb/lowlevel";
2
2
  import DataPack from "./datapack.js";
3
- import { modelRegistry, currentTxn, Transaction } from "./models.js";
3
+ import { currentTxn, type Transaction, transact } from "./edinburgh.js";
4
+ import { modelRegistry } from "./models.js";
4
5
  import { dbDel, toBuffer, bytesEqual } from "./utils.js";
5
- import { PrimaryIndex } from "./indexes.js";
6
6
  import { deserializeType, TypeWrapper } from "./types.js";
7
- import { transact } from "./edinburgh.js";
8
7
 
9
8
  const INDEX_ID_PREFIX = -2;
10
9
 
@@ -118,14 +117,13 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
118
117
 
119
118
  // Build maps of known index IDs
120
119
  const knownIndexIds = new Set<number>();
121
- const primaryByIndexId = new Map<number, { model: typeof modelRegistry[string], primary: PrimaryIndex<any, any> }>();
120
+ const modelByPkIndexId = new Map<number, typeof modelRegistry[string]>();
122
121
 
123
122
  for (const model of Object.values(modelRegistry)) {
124
123
  if (options.tables && !options.tables.includes(model.tableName)) continue;
125
- const primary = model._primary;
126
- knownIndexIds.add(primary._indexId!);
127
- primaryByIndexId.set(primary._indexId!, { model, primary });
128
- for (const sec of model._secondaries || []) {
124
+ knownIndexIds.add(model._indexId!);
125
+ modelByPkIndexId.set(model._indexId!, model);
126
+ for (const sec of Object.values(model._secondaries || {})) {
129
127
  knownIndexIds.add(sec._indexId!);
130
128
  }
131
129
  }
@@ -155,24 +153,24 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
155
153
 
156
154
  // Phase 1: Populate secondary indexes and/or rewrite row data
157
155
  if (populateSecondaries || rewriteData) {
158
- for (const [indexId, { model, primary }] of primaryByIndexId) {
156
+ for (const [indexId, model] of modelByPkIndexId) {
159
157
  let secondaryCount = 0;
160
158
  let rewrittenCount = 0;
161
159
  const migrateFn = (model as any).migrate as ((record: Record<string, any>) => void) | undefined;
162
- const secondaries = model._secondaries || [];
160
+ const secondaries = Object.values(model._secondaries || {});
163
161
 
164
162
  await forEachRow(indexId, (txn, keyBuf, valueBuf) => {
165
163
  const valuePack = new DataPack(valueBuf);
166
164
  const version = valuePack.readNumber();
167
- if (version === primary._currentVersion) return; // Already current
165
+ if (version === model._currentVersion) return; // Already current
168
166
 
169
- const versionInfo = primary._loadVersionInfo(txn.id, version);
167
+ const versionInfo = model._loadVersionInfo(txn.id, version);
170
168
 
171
169
  // Deserialize pre-migrate values from key + old-format value
172
170
  const record: Record<string, any> = {};
173
171
  const keyPack = new DataPack(keyBuf);
174
172
  keyPack.readNumber(); // skip indexId
175
- for (const [name, type] of primary._fieldTypes.entries()) {
173
+ for (const [name, type] of model._indexFields.entries()) {
176
174
  record[name] = type.deserialize(keyPack);
177
175
  }
178
176
  for (const [name, type] of versionInfo.nonKeyFields.entries()) {
@@ -191,33 +189,14 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
191
189
  sec._write(txn, keyBuf, record as any);
192
190
  secondaryCount++;
193
191
  } else if (preMigrate) {
194
- if (sec._computeFn) {
195
- // Computed indexes: compare serialized keys to avoid unnecessary re-indexing
196
- const oldKeyBytes = sec._serializeKeyFields(preMigrate).toUint8Array();
197
- const newKeyBytes = sec._serializeKeyFields(record).toUint8Array();
198
- if (!bytesEqual(oldKeyBytes, newKeyBytes)) {
199
- sec._delete(txn, keyBuf, preMigrate as any);
200
- sec._write(txn, keyBuf, record as any);
201
- secondaryCount++;
202
- }
203
- } else {
204
- // Existing secondary, update if migrate changed any of its fields
205
- for (const [field, type] of sec._fieldTypes.entries()) {
206
- if (!type.equals(preMigrate[field], record[field])) {
207
- sec._delete(txn, keyBuf, preMigrate as any);
208
- sec._write(txn, keyBuf, record as any);
209
- secondaryCount++;
210
- break;
211
- }
212
- }
213
- }
192
+ if (sec._update(txn, keyBuf, record as any, preMigrate)) secondaryCount++;
214
193
  }
215
194
  }
216
195
  }
217
196
 
218
197
  // Rewrite primary row data to current version
219
198
  if (rewriteData) {
220
- primary._write(txn, keyBuf, record);
199
+ model._writePK(txn, keyBuf, record);
221
200
  rewrittenCount++;
222
201
  }
223
202
  });
@@ -245,7 +224,6 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
245
224
  const failures: Record<string, number> = {};
246
225
 
247
226
  await forEachRow(oldDef.id, (txn, keyBuf) => {
248
- let instance;
249
227
  try {
250
228
  // Deserialize old key
251
229
  const keyPack = new DataPack(keyBuf);
@@ -260,7 +238,7 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
260
238
  if (migrateFn) migrateFn(record);
261
239
 
262
240
  // _write validates, checks duplicates, writes primary + secondaries
263
- instance = new (model as any)(record, txn);
241
+ let instance = new (model as any)(record, txn);
264
242
  instance._write(txn);
265
243
  dbDel(txn.id, keyBuf);
266
244
  converted++;
@@ -271,7 +249,7 @@ export async function runMigration(options: MigrationOptions = {}): Promise<Migr
271
249
  failures['error'] = (failures['error'] || 0) + 1;
272
250
  }
273
251
  } finally {
274
- if (instance) txn.instances.delete(instance);
252
+ txn.instances.clear(); // We've already handled the _write() ourselves
275
253
  }
276
254
  });
277
255