edinburgh 0.1.3 → 0.4.1

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,21 +1,28 @@
1
- import * as olmdb from "olmdb";
2
- import { Bytes } from "./bytes.js";
3
- import { Model } from "./models.js";
4
- /** @internal Symbol used to access the underlying model from a proxy */
5
- export declare const TARGET_SYMBOL: unique symbol;
1
+ import DataPack from "./datapack.js";
2
+ import { Model, Transaction } from "./models.js";
3
+ import { TypeWrapper } from "./types.js";
6
4
  type IndexArgTypes<M extends typeof Model<any>, F extends readonly (keyof InstanceType<M> & string)[]> = {
7
5
  [I in keyof F]: InstanceType<M>[F[I]];
8
6
  };
7
+ /** Cached information about a specific version of a primary index's value format. */
8
+ interface VersionInfo {
9
+ migrateHash: number;
10
+ /** Non-key field names → TypeWrappers for deserialization of this version's data. */
11
+ nonKeyFields: Map<string, TypeWrapper<any>>;
12
+ /** Set of serialized secondary index signatures that existed in this version. */
13
+ secondaryKeys: Set<string>;
14
+ }
9
15
  /**
10
16
  * Iterator for range queries on indexes.
11
17
  * Handles common iteration logic for both primary and unique indexes.
12
18
  * Implements both Iterator and Iterable interfaces for efficiency.
13
19
  */
14
- declare class IndexRangeIterator<M extends typeof Model, F extends readonly (keyof InstanceType<M> & string)[]> implements Iterator<InstanceType<M>>, Iterable<InstanceType<M>> {
15
- private iterator;
20
+ export declare class IndexRangeIterator<M extends typeof Model> implements Iterator<InstanceType<M>>, Iterable<InstanceType<M>> {
21
+ private txn;
22
+ private iteratorId;
16
23
  private indexId;
17
24
  private parentIndex;
18
- constructor(iterator: olmdb.DbIterator<any, any> | undefined, indexId: number, parentIndex: BaseIndex<M, F>);
25
+ constructor(txn: Transaction, iteratorId: number, indexId: number, parentIndex: BaseIndex<M, any>);
19
26
  [Symbol.iterator](): Iterator<InstanceType<M>>;
20
27
  next(): IteratorResult<InstanceType<M>>;
21
28
  count(): number;
@@ -46,72 +53,45 @@ type FindOptions<ARG_TYPES extends readonly any[]> = (({
46
53
  export declare abstract class BaseIndex<M extends typeof Model, const F extends readonly (keyof InstanceType<M> & string)[]> {
47
54
  _fieldNames: F;
48
55
  _MyModel: M;
56
+ _fieldTypes: Map<keyof InstanceType<M> & string, TypeWrapper<any>>;
57
+ _fieldCount: number;
58
+ _resetIndexFieldDescriptors: Record<string | symbol | number, PropertyDescriptor>;
49
59
  /**
50
60
  * Create a new index.
51
61
  * @param MyModel - The model class this index belongs to.
52
62
  * @param _fieldNames - Array of field names that make up this index.
53
63
  */
54
- constructor(MyModel: M, _fieldNames: F, isPrimary?: boolean);
55
- _cachedIndexId?: number;
56
- /**
57
- * Deserialize index key bytes back to field values.
58
- * @param bytes - Bytes to read from.
59
- * @returns Array of field values.
60
- */
61
- _deserializeKey(bytes: Bytes): IndexArgTypes<M, F>;
64
+ constructor(MyModel: M, _fieldNames: F);
65
+ _delayedInit(): Promise<void>;
66
+ _indexId?: number;
67
+ /** Human-readable signature for version tracking, e.g. "secondary category:string" */
68
+ _signature?: string;
62
69
  /**
63
- * Extract model from iterator entry - implemented differently by each index type.
64
- * @param keyBytes - Key bytes with index ID already read.
65
- * @param valueBytes - Value bytes from the entry.
66
- * @returns Model instance or undefined.
67
- * @internal
68
- */
69
- abstract _getModelFromEntry(keyBytes: Bytes, valueBytes: Bytes): InstanceType<M> | undefined;
70
- /**
71
- * Serialize field values to bytes for index key.
70
+ * Serialize array of key values to a (index-id prefixed) Bytes instance that can be used as a key.
72
71
  * @param args - Field values to serialize (can be partial for range queries).
73
- * @param bytes - Bytes to write to.
72
+ * @returns A Bytes instance containing the index id and serialized key parts.
74
73
  * @internal
75
74
  */
76
- _serializeArgs(args: Partial<IndexArgTypes<M, F>> | readonly any[], bytes: Bytes): void;
75
+ _argsToKeyBytes(args: [], allowPartial: boolean): DataPack;
76
+ _argsToKeyBytes(args: Partial<IndexArgTypes<M, F>>, allowPartial: boolean): DataPack;
77
77
  /**
78
- * Create database key from field values.
79
- * @param args - Field values.
80
- * @returns Database key bytes.
81
- */
82
- _getKeyFromArgs(args: IndexArgTypes<M, F>): Uint8Array;
83
- /**
84
- * Serialize model fields to bytes for index key.
85
- * @param model - Model instance.
86
- * @param bytes - Bytes to write to.
87
- */
88
- _serializeModel(model: InstanceType<M>, bytes: Bytes): void;
89
- /**
90
- * Create database key from model instance.
91
- * @param model - Model instance.
92
- * @param includeIndexId - Whether to include index ID in key.
93
- * @returns Database key bytes or undefined if skipped.
94
- * @internal
95
- */
96
- _getKeyFromModel(model: InstanceType<M>, includeIndexId: boolean): Uint8Array;
97
- /**
98
- * Extract field values from model for this index.
99
- * @param model - Model instance.
100
- * @returns Field values or undefined if should be skipped.
78
+ * Extract model from iterator entry - implemented differently by each index type.
79
+ * @param keyBuffer - Key bytes (including index id).
80
+ * @param valueBuffer - Value bytes from the entry.
81
+ * @returns Model instance or undefined.
101
82
  * @internal
102
83
  */
103
- _modelToArgs(model: InstanceType<M>): IndexArgTypes<M, F> | undefined;
104
- /**
105
- * Get or create unique index ID for this index.
106
- * @returns Numeric index ID.
107
- */
108
- _getIndexId(): number;
84
+ abstract _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, valueBuffer: ArrayBuffer): InstanceType<M>;
85
+ _hasNullIndexValues(data: Record<string, any>): boolean;
86
+ abstract _serializeKey(primaryKey: Uint8Array, data: Record<string, any>): Uint8Array;
87
+ _serializeKeyFields(data: Record<string, any>): DataPack;
109
88
  /**
110
- * Check if indexing should be skipped for a model instance.
111
- * @param model - Model instance.
112
- * @returns true if indexing should be skipped.
89
+ * Retrieve (or create) a stable index ID from the DB, with retry on transaction races.
90
+ * Sets `this._indexId` on success.
113
91
  */
114
- _checkSkip(model: InstanceType<M>): boolean;
92
+ _retrieveIndexId(): Promise<void>;
93
+ abstract _delete(txn: Transaction, primaryKey: Uint8Array, model: InstanceType<M>): void;
94
+ abstract _write(txn: Transaction, primaryKey: Uint8Array, model: InstanceType<M>): void;
115
95
  /**
116
96
  * Find model instances using flexible range query options.
117
97
  *
@@ -170,14 +150,25 @@ export declare abstract class BaseIndex<M extends typeof Model, const F extends
170
150
  * }
171
151
  * ```
172
152
  */
173
- find(opts?: FindOptions<IndexArgTypes<M, F>>): IndexRangeIterator<M, F>;
153
+ _computeKeyBounds(opts: FindOptions<IndexArgTypes<M, F>>): [DataPack | undefined, DataPack | undefined] | null;
154
+ find(opts?: FindOptions<IndexArgTypes<M, F>>): IndexRangeIterator<M>;
174
155
  /**
175
- * Save index entry for a model instance.
176
- * @param model - Model instance to save.
177
- * @param originalKey - Original key if updating.
156
+ * Process all matching rows in batched transactions.
157
+ *
158
+ * Uses the same query options as {@link find}. The batch is committed and a new
159
+ * transaction started once either `limitSeconds` or `limitRows` is exceeded.
160
+ *
161
+ * @param opts - Query options (same as `find()`), plus:
162
+ * @param opts.limitSeconds - Max seconds per transaction batch (default: 1)
163
+ * @param opts.limitRows - Max rows per transaction batch (default: 4096)
164
+ * @param callback - Called for each matching row within a transaction
178
165
  */
179
- abstract _save(model: InstanceType<M>, originalKey?: Uint8Array): Uint8Array | undefined;
166
+ batchProcess(opts: (FindOptions<IndexArgTypes<M, F>> & {
167
+ limitSeconds?: number;
168
+ limitRows?: number;
169
+ }) | undefined, callback: (row: InstanceType<M>) => void | Promise<void>): Promise<void>;
180
170
  abstract _getTypeName(): string;
171
+ toString(): string;
181
172
  }
182
173
  /**
183
174
  * Primary index that stores the actual model data.
@@ -186,7 +177,22 @@ export declare abstract class BaseIndex<M extends typeof Model, const F extends
186
177
  * @template F - The field names that make up this index.
187
178
  */
188
179
  export declare class PrimaryIndex<M extends typeof Model, const F extends readonly (keyof InstanceType<M> & string)[]> extends BaseIndex<M, F> {
180
+ _nonKeyFields: (keyof InstanceType<M> & string)[];
181
+ _lazyDescriptors: Record<string | symbol | number, PropertyDescriptor>;
182
+ _resetDescriptors: Record<string | symbol | number, PropertyDescriptor>;
183
+ _freezePrimaryKeyDescriptors: Record<string | symbol | number, PropertyDescriptor>;
184
+ /** Current version number for this primary index's value format. */
185
+ _currentVersion: number;
186
+ /** Hash of the current migrate() function source, or 0 if none. */
187
+ _currentMigrateHash: number;
188
+ /** Cached version info for old versions (loaded on demand). */
189
+ _versions: Map<number, VersionInfo>;
189
190
  constructor(MyModel: M, fieldNames: F);
191
+ _delayedInit(): Promise<void>;
192
+ /** Serialize the current version fingerprint as a DataPack object. */
193
+ _serializeVersionValue(): Uint8Array;
194
+ /** Look up or create the current version number for this primary index. */
195
+ _initVersioning(): Promise<void>;
190
196
  /**
191
197
  * Get a model instance by primary key values.
192
198
  * @param args - The primary key values.
@@ -199,20 +205,27 @@ export declare class PrimaryIndex<M extends typeof Model, const F extends readon
199
205
  */
200
206
  get(...args: IndexArgTypes<M, F>): InstanceType<M> | undefined;
201
207
  /**
202
- * Extract model from iterator entry for primary index.
203
- * @param keyBytes - Key bytes with index ID already read.
204
- * @param valueBytes - Value bytes from the entry.
205
- * @returns Model instance or undefined.
206
- * @internal
208
+ * Does the same as as `get()`, but will delay loading the instance from disk until the first
209
+ * property access. In case it turns out the instance doesn't exist, an error will be thrown
210
+ * at that time.
211
+ * @param args Primary key field values. (Or a single Uint8Array containing the key.)
212
+ * @returns The (lazily loaded) model instance.
207
213
  */
208
- _getModelFromEntry(keyBytes: Bytes, valueBytes: Bytes): InstanceType<M> | undefined;
209
- /**
210
- * Save primary index entry.
211
- * @param model - Model instance.
212
- * @param originalKey - Original key if updating.
213
- */
214
- _save(model: InstanceType<M>, originalKey?: Uint8Array): Uint8Array;
214
+ getLazy(...args: IndexArgTypes<M, F>): InstanceType<M>;
215
+ _get(txn: Transaction, args: IndexArgTypes<M, F> | Uint8Array, loadNow: false | Uint8Array): InstanceType<M>;
216
+ _get(txn: Transaction, args: IndexArgTypes<M, F> | Uint8Array, loadNow: true): InstanceType<M> | undefined;
217
+ _serializeKey(primaryKey: Uint8Array, _data: Record<string, any>): Uint8Array;
218
+ _lazyNow(model: InstanceType<M>): void;
219
+ _setNonKeyValues(model: InstanceType<M>, valueArray: Uint8Array): void;
220
+ /** Load a version's info from DB, caching the result. */
221
+ _loadVersionInfo(txnId: number, version: number): VersionInfo;
222
+ /** Deserialize and migrate a row from an old version. */
223
+ _migrateFromVersion(model: InstanceType<M>, version: number, valuePack: DataPack): void;
224
+ _keyToArray(key: Uint8Array): IndexArgTypes<M, F>;
225
+ _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, valueBuffer: ArrayBuffer): InstanceType<M>;
215
226
  _getTypeName(): string;
227
+ _write(txn: Transaction, primaryKey: Uint8Array, data: Record<string, any>): void;
228
+ _delete(txn: Transaction, primaryKey: Uint8Array, _data: Record<string, any>): void;
216
229
  }
217
230
  /**
218
231
  * Unique index that stores references to the primary key.
@@ -221,6 +234,7 @@ export declare class PrimaryIndex<M extends typeof Model, const F extends readon
221
234
  * @template F - The field names that make up this index.
222
235
  */
223
236
  export declare class UniqueIndex<M extends typeof Model, const F extends readonly (keyof InstanceType<M> & string)[]> extends BaseIndex<M, F> {
237
+ constructor(MyModel: M, fieldNames: F);
224
238
  /**
225
239
  * Get a model instance by unique index key values.
226
240
  * @param args - The unique index key values.
@@ -232,20 +246,10 @@ export declare class UniqueIndex<M extends typeof Model, const F extends readonl
232
246
  * ```
233
247
  */
234
248
  get(...args: IndexArgTypes<M, F>): InstanceType<M> | undefined;
235
- /**
236
- * Extract model from iterator entry for unique index.
237
- * @param keyBytes - Key bytes with index ID already read.
238
- * @param valueBytes - Value bytes from the entry.
239
- * @returns Model instance or undefined.
240
- * @internal
241
- */
242
- _getModelFromEntry(keyBytes: Bytes, valueBytes: Bytes): InstanceType<M> | undefined;
243
- /**
244
- * Save unique index entry.
245
- * @param model - Model instance.
246
- * @param originalKey - Original key if updating.
247
- */
248
- _save(model: InstanceType<M>, originalKey?: Uint8Array): Uint8Array | undefined;
249
+ _serializeKey(primaryKey: Uint8Array, data: Record<string, any>): Uint8Array;
250
+ _delete(txn: Transaction, primaryKey: Uint8Array, data: Record<string, any>): void;
251
+ _write(txn: Transaction, primaryKey: Uint8Array, data: Record<string, any>): void;
252
+ _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, valueBuffer: ArrayBuffer): InstanceType<M>;
249
253
  _getTypeName(): string;
250
254
  }
251
255
  /**
@@ -255,26 +259,11 @@ export declare class UniqueIndex<M extends typeof Model, const F extends readonl
255
259
  * @template F - The field names that make up this index.
256
260
  */
257
261
  export declare class SecondaryIndex<M extends typeof Model, const F extends readonly (keyof InstanceType<M> & string)[]> extends BaseIndex<M, F> {
258
- /**
259
- * Save secondary index entry.
260
- * @param model - Model instance.
261
- * @param originalKey - Original key if updating.
262
- */
263
- _save(model: InstanceType<M>, originalKey?: Uint8Array): Uint8Array | undefined;
264
- /**
265
- * Extract model from iterator entry for secondary index.
266
- * @param keyBytes - Key bytes with index ID already read.
267
- * @param valueBytes - Value bytes from the entry.
268
- * @returns Model instance or undefined.
269
- * @internal
270
- */
271
- _getModelFromEntry(keyBytes: Bytes, valueBytes: Bytes): InstanceType<M> | undefined;
272
- /**
273
- * Create secondary index key that includes both index fields and primary key.
274
- * @param model - Model instance.
275
- * @returns Database key bytes or undefined if skipped.
276
- */
277
- _getKeyFromModel(model: InstanceType<M>, includeIndexId: boolean): Uint8Array;
262
+ constructor(MyModel: M, fieldNames: F);
263
+ _pairToInstance(txn: Transaction, keyBuffer: ArrayBuffer, _valueBuffer: ArrayBuffer): InstanceType<M>;
264
+ _serializeKey(primaryKey: Uint8Array, model: InstanceType<M>): Uint8Array;
265
+ _write(txn: Transaction, primaryKey: Uint8Array, model: InstanceType<M>): void;
266
+ _delete(txn: Transaction, primaryKey: Uint8Array, model: InstanceType<M>): void;
278
267
  _getTypeName(): string;
279
268
  }
280
269
  export type Index<M extends typeof Model, F extends readonly (keyof InstanceType<M> & string)[]> = PrimaryIndex<M, F> | UniqueIndex<M, F> | SecondaryIndex<M, F>;