edinburgh 0.1.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.
@@ -0,0 +1,192 @@
1
+ import { DatabaseError } from "olmdb";
2
+ import { TypeWrapper } from "./types.js";
3
+ import { BaseIndex, PrimaryIndex } from "./indexes.js";
4
+ /**
5
+ * Configuration interface for model fields.
6
+ * @template T - The field type.
7
+ */
8
+ export interface FieldConfig<T> {
9
+ /** The type wrapper that defines how this field is serialized/validated. */
10
+ type: TypeWrapper<T>;
11
+ /** Optional human-readable description of the field. */
12
+ description?: string;
13
+ /** Optional default value or function that generates default values. */
14
+ default?: T | ((model: Record<string, any>) => T);
15
+ }
16
+ /**
17
+ * Create a field definition for a model property.
18
+ *
19
+ * This function uses TypeScript magic to return the field configuration object
20
+ * while appearing to return the actual field value type to the type system.
21
+ * This allows for both runtime introspection and compile-time type safety.
22
+ *
23
+ * @template T - The field type.
24
+ * @param type - The type wrapper for this field.
25
+ * @param options - Additional field configuration options.
26
+ * @returns The field value (typed as T, but actually returns FieldConfig<T>).
27
+ *
28
+ * @example
29
+ * ```typescript
30
+ * class User extends E.Model<User> {
31
+ * name = E.field(E.string, {description: "User's full name"});
32
+ * age = E.field(E.opt(E.number), {description: "User's age", default: 25});
33
+ * }
34
+ * ```
35
+ */
36
+ export declare function field<T>(type: TypeWrapper<T>, options?: Partial<FieldConfig<T>>): T;
37
+ export declare const modelRegistry: Record<string, typeof Model>;
38
+ export declare function resetModelCaches(): void;
39
+ type OnSaveType = (model: InstanceType<typeof Model>, newKey: Uint8Array | undefined, oldKey: Uint8Array | undefined) => void;
40
+ /**
41
+ * Set a callback function to be called after a model is saved and committed.
42
+ *
43
+ * @param callback The callback function to set. As arguments, it receives the model instance, the new key (undefined in case of a delete), and the old key (undefined in case of a create).
44
+ */
45
+ export declare function setOnSaveCallback(callback: OnSaveType | undefined): void;
46
+ /**
47
+ * Register a model class with the Edinburgh ORM system.
48
+ *
49
+ * This decorator function transforms the model class to use a proxy-based constructor
50
+ * that enables change tracking and automatic field initialization. It also extracts
51
+ * field metadata and sets up default values on the prototype.
52
+ *
53
+ * @template T - The model class type.
54
+ * @param MyModel - The model class to register.
55
+ * @returns The enhanced model class with ORM capabilities.
56
+ *
57
+ * @example
58
+ * ```typescript
59
+ * ⁣@E.registerModel
60
+ * class User extends E.Model<User> {
61
+ * static pk = E.index(User, ["id"], "primary");
62
+ * id = E.field(E.identifier);
63
+ * name = E.field(E.string);
64
+ * }
65
+ * ```
66
+ */
67
+ export declare function registerModel<T extends typeof Model<unknown>>(MyModel: T): T;
68
+ export declare function getMockModel<T extends typeof Model<unknown>>(OrgModel: T): T;
69
+ /** @internal Symbol used to attach modified instances to running transaction */
70
+ export declare const MODIFIED_INSTANCES_SYMBOL: unique symbol;
71
+ /** @internal Symbol used to access the underlying model from a proxy */
72
+ /**
73
+ * Model interface that ensures proper typing for the constructor property.
74
+ * @template SUB - The concrete model subclass.
75
+ */
76
+ export interface Model<SUB> {
77
+ constructor: typeof Model<SUB>;
78
+ }
79
+ /**
80
+ * Base class for all database models in the Edinburgh ORM.
81
+ *
82
+ * Models represent database entities with typed fields, automatic serialization,
83
+ * change tracking, and relationship management. All model classes should extend
84
+ * this base class and be decorated with `@registerModel`.
85
+ *
86
+ * @template SUB - The concrete model subclass (for proper typing).
87
+ *
88
+ * @example
89
+ * ```typescript
90
+ * ⁣@E.registerModel
91
+ * class User extends E.Model<User> {
92
+ * static pk = E.index(User, ["id"], "primary");
93
+ *
94
+ * id = E.field(E.identifier);
95
+ * name = E.field(E.string);
96
+ * email = E.field(E.string);
97
+ *
98
+ * static byEmail = E.index(User, "email", "unique");
99
+ * }
100
+ * ```
101
+ */
102
+ export declare abstract class Model<SUB> {
103
+ /** @internal Primary key index for this model. */
104
+ static _pk?: PrimaryIndex<any, any>;
105
+ /** @internal All indexes for this model, the primary key being first. */
106
+ static _indexes?: BaseIndex<any, any>[];
107
+ /** The database table name (defaults to class name). */
108
+ static tableName: string;
109
+ /** Field configuration metadata. */
110
+ static fields: Record<string, FieldConfig<unknown>>;
111
+ /** @internal Field configuration for this instance. */
112
+ _fields: Record<string, FieldConfig<unknown>>;
113
+ /**
114
+ * @internal State tracking for this model instance:
115
+ * - undefined: new instance, unmodified
116
+ * - 1: new instance, modified (and in modifiedInstances)
117
+ * - 2: loaded from disk, unmodified
118
+ * - 3: persistence disabled
119
+ * - array: loaded from disk, modified (and in modifiedInstances), array values are original index buffers
120
+ */
121
+ _state: undefined | 1 | 2 | 3 | Array<Uint8Array>;
122
+ constructor(initial?: Partial<Omit<SUB, "constructor">>);
123
+ _save(): void;
124
+ /**
125
+ * Load a model instance by primary key.
126
+ * @param args - Primary key field values.
127
+ * @returns The model instance if found, undefined otherwise.
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * const user = User.load("user123");
132
+ * const post = Post.load("post456", "en");
133
+ * ```
134
+ */
135
+ static load<SUB>(this: typeof Model<SUB>, ...args: any[]): SUB | undefined;
136
+ /**
137
+ * Prevent this instance from being persisted to the database.
138
+ *
139
+ * Removes the instance from the modified instances set and disables
140
+ * automatic persistence at transaction commit.
141
+ *
142
+ * @returns This model instance for chaining.
143
+ *
144
+ * @example
145
+ * ```typescript
146
+ * const user = User.load("user123");
147
+ * user.name = "New Name";
148
+ * user.preventPersist(); // Changes won't be saved
149
+ * ```
150
+ */
151
+ preventPersist(): this;
152
+ /**
153
+ * Delete this model instance from the database.
154
+ *
155
+ * Removes the instance and all its index entries from the database and prevents further persistence.
156
+ *
157
+ * @example
158
+ * ```typescript
159
+ * const user = User.load("user123");
160
+ * user.delete(); // Removes from database
161
+ * ```
162
+ */
163
+ delete(): void;
164
+ /**
165
+ * Validate all fields in this model instance.
166
+ * @param raise - If true, throw on first validation error.
167
+ * @returns Array of validation errors (empty if valid).
168
+ *
169
+ * @example
170
+ * ```typescript
171
+ * const user = new User();
172
+ * const errors = user.validate();
173
+ * if (errors.length > 0) {
174
+ * console.log("Validation failed:", errors);
175
+ * }
176
+ * ```
177
+ */
178
+ validate(raise?: boolean): DatabaseError[];
179
+ /**
180
+ * Check if this model instance is valid.
181
+ * @returns true if all validations pass.
182
+ *
183
+ * @example
184
+ * ```typescript
185
+ * const user = new User({name: "John"});
186
+ * if (!user.isValid()) shoutAtTheUser();
187
+ * ```
188
+ */
189
+ isValid(): boolean;
190
+ }
191
+ export declare const modificationTracker: ProxyHandler<any>;
192
+ export {};
@@ -0,0 +1,457 @@
1
+ import { DatabaseError } from "olmdb";
2
+ import * as olmdb from "olmdb";
3
+ import { TypeWrapper, identifier } from "./types.js";
4
+ import { TARGET_SYMBOL, PrimaryIndex } from "./indexes.js";
5
+ import { assert, addErrorPath, logLevel } from "./utils.js";
6
+ /**
7
+ * Create a field definition for a model property.
8
+ *
9
+ * This function uses TypeScript magic to return the field configuration object
10
+ * while appearing to return the actual field value type to the type system.
11
+ * This allows for both runtime introspection and compile-time type safety.
12
+ *
13
+ * @template T - The field type.
14
+ * @param type - The type wrapper for this field.
15
+ * @param options - Additional field configuration options.
16
+ * @returns The field value (typed as T, but actually returns FieldConfig<T>).
17
+ *
18
+ * @example
19
+ * ```typescript
20
+ * class User extends E.Model<User> {
21
+ * name = E.field(E.string, {description: "User's full name"});
22
+ * age = E.field(E.opt(E.number), {description: "User's age", default: 25});
23
+ * }
24
+ * ```
25
+ */
26
+ export function field(type, options = {}) {
27
+ // Return the config object, but TypeScript sees it as type T
28
+ options.type = type;
29
+ return options;
30
+ }
31
+ // Model registration and initialization
32
+ let uninitializedModels = new Set();
33
+ export const modelRegistry = {};
34
+ export function resetModelCaches() {
35
+ for (const model of Object.values(modelRegistry)) {
36
+ for (const index of model._indexes || []) {
37
+ index._cachedIndexId = undefined;
38
+ }
39
+ }
40
+ }
41
+ function isObjectEmpty(obj) {
42
+ for (let key in obj) {
43
+ if (obj.hasOwnProperty(key))
44
+ return false;
45
+ }
46
+ return true;
47
+ }
48
+ let onSave;
49
+ /**
50
+ * Set a callback function to be called after a model is saved and committed.
51
+ *
52
+ * @param callback The callback function to set. As arguments, it receives the model instance, the new key (undefined in case of a delete), and the old key (undefined in case of a create).
53
+ */
54
+ export function setOnSaveCallback(callback) {
55
+ onSave = callback;
56
+ }
57
+ const onSaveQueue = [];
58
+ function onSaveRevert() {
59
+ onSaveQueue.length = 0;
60
+ }
61
+ function onSaveCommit() {
62
+ if (onSave) {
63
+ for (let arr of onSaveQueue) {
64
+ onSave(...arr);
65
+ }
66
+ }
67
+ onSaveQueue.length = 0;
68
+ }
69
+ function queueOnSave(arr) {
70
+ if (onSave) {
71
+ if (!onSaveQueue.length) {
72
+ olmdb.onCommit(onSaveCommit);
73
+ olmdb.onRevert(onSaveRevert);
74
+ }
75
+ onSaveQueue.push(arr);
76
+ }
77
+ }
78
+ /**
79
+ * Register a model class with the Edinburgh ORM system.
80
+ *
81
+ * This decorator function transforms the model class to use a proxy-based constructor
82
+ * that enables change tracking and automatic field initialization. It also extracts
83
+ * field metadata and sets up default values on the prototype.
84
+ *
85
+ * @template T - The model class type.
86
+ * @param MyModel - The model class to register.
87
+ * @returns The enhanced model class with ORM capabilities.
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * ⁣@E.registerModel
92
+ * class User extends E.Model<User> {
93
+ * static pk = E.index(User, ["id"], "primary");
94
+ * id = E.field(E.identifier);
95
+ * name = E.field(E.string);
96
+ * }
97
+ * ```
98
+ */
99
+ export function registerModel(MyModel) {
100
+ const MockModel = getMockModel(MyModel);
101
+ // Copy own static methods/properties
102
+ for (const name of Object.getOwnPropertyNames(MyModel)) {
103
+ if (name !== 'length' && name !== 'prototype' && name !== 'name' && name !== 'mock') {
104
+ MockModel[name] = MyModel[name];
105
+ }
106
+ }
107
+ // Initialize an empty `fields` object, and set it on both constructors, as well as on the prototype.
108
+ MockModel.fields = MockModel.prototype._fields = {};
109
+ MockModel.tableName ||= MyModel.name; // Set the table name to the class name if not already set
110
+ // Register the constructor by name
111
+ if (MockModel.tableName in modelRegistry)
112
+ throw new DatabaseError(`Model with table name '${MockModel.tableName}' already registered`, 'INIT_ERROR');
113
+ modelRegistry[MockModel.tableName] = MockModel;
114
+ // Attempt to instantiate the class and gather field metadata
115
+ uninitializedModels.add(MyModel);
116
+ initModels();
117
+ return MockModel;
118
+ }
119
+ export function getMockModel(OrgModel) {
120
+ const AnyOrgModel = OrgModel;
121
+ if (AnyOrgModel._isMock)
122
+ return OrgModel;
123
+ if (AnyOrgModel._mock)
124
+ return AnyOrgModel._mock;
125
+ const MockModel = function (initial) {
126
+ if (uninitializedModels.has(this.constructor)) {
127
+ throw new DatabaseError("Cannot instantiate while linked models haven't been registered yet", 'INIT_ERROR');
128
+ }
129
+ if (initial && !isObjectEmpty(initial)) {
130
+ Object.assign(this, initial);
131
+ const modifiedInstances = olmdb.getTransactionData(MODIFIED_INSTANCES_SYMBOL);
132
+ modifiedInstances.add(this);
133
+ }
134
+ return new Proxy(this, modificationTracker);
135
+ };
136
+ // We want .constructor to point at our fake constructor function.
137
+ OrgModel.prototype.constructor = MockModel;
138
+ // Copy the prototype chain for the constructor as well as for instantiated objects
139
+ Object.setPrototypeOf(MockModel, Object.getPrototypeOf(OrgModel));
140
+ MockModel.prototype = OrgModel.prototype;
141
+ MockModel._isMock = true;
142
+ AnyOrgModel._mock = MockModel;
143
+ return MockModel;
144
+ }
145
+ function initModels() {
146
+ for (const OrgModel of uninitializedModels) {
147
+ const MockModel = getMockModel(OrgModel);
148
+ // Create an instance (the only one to ever exist) of the actual class,
149
+ // in order to gather field config data.
150
+ let instance;
151
+ try {
152
+ instance = new OrgModel(INIT_INSTANCE_SYMBOL);
153
+ }
154
+ catch (e) {
155
+ if (!(e instanceof ReferenceError))
156
+ throw e;
157
+ // ReferenceError: Cannot access 'SomeLinkedClass' before initialization.
158
+ // We'll try again after the next class has successfully initialized.
159
+ continue;
160
+ }
161
+ uninitializedModels.delete(OrgModel);
162
+ // If no primary key exists, create one using 'id' field
163
+ if (!MockModel._pk) {
164
+ // If no `id` field exists, add it automatically
165
+ if (!instance.id) {
166
+ instance.id = { type: identifier };
167
+ }
168
+ // @ts-ignore-next-line - `id` is not part of the type, but the user probably shouldn't touch it anyhow
169
+ new PrimaryIndex(MockModel, ['id']);
170
+ }
171
+ for (const key in instance) {
172
+ const value = instance[key];
173
+ // Check if this property contains field metadata
174
+ if (value && value.type instanceof TypeWrapper) {
175
+ // Set the configuration on the constructor's `fields` property
176
+ MockModel.fields[key] = value;
177
+ // Set default value on the prototype
178
+ const defObj = value.default === undefined ? value.type : value;
179
+ const def = defObj.default;
180
+ if (typeof def === 'function') {
181
+ // The default is a function. We'll define a getter on the property in the model prototype,
182
+ // and once it is read, we'll run the function and set the value as a plain old property
183
+ // on the instance object.
184
+ Object.defineProperty(MockModel.prototype, key, {
185
+ get() {
186
+ // This will call set(), which will define the property on the instance.
187
+ return (this[key] = def.call(defObj, this));
188
+ },
189
+ set(val) {
190
+ Object.defineProperty(this, key, {
191
+ value: val,
192
+ configurable: true,
193
+ writable: true
194
+ });
195
+ },
196
+ configurable: true,
197
+ });
198
+ }
199
+ else if (def !== undefined) {
200
+ MockModel.prototype[key] = def;
201
+ }
202
+ }
203
+ }
204
+ if (logLevel >= 1) {
205
+ console.log(`Registered model ${MockModel.tableName}[${MockModel._pk._fieldNames.join(',')}] with fields: ${Object.keys(MockModel.fields).join(' ')}`);
206
+ }
207
+ }
208
+ }
209
+ // Model base class and related symbols/state
210
+ const INIT_INSTANCE_SYMBOL = Symbol();
211
+ /** @internal Symbol used to attach modified instances to running transaction */
212
+ export const MODIFIED_INSTANCES_SYMBOL = Symbol('modifiedInstances');
213
+ /**
214
+ * Base class for all database models in the Edinburgh ORM.
215
+ *
216
+ * Models represent database entities with typed fields, automatic serialization,
217
+ * change tracking, and relationship management. All model classes should extend
218
+ * this base class and be decorated with `@registerModel`.
219
+ *
220
+ * @template SUB - The concrete model subclass (for proper typing).
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * ⁣@E.registerModel
225
+ * class User extends E.Model<User> {
226
+ * static pk = E.index(User, ["id"], "primary");
227
+ *
228
+ * id = E.field(E.identifier);
229
+ * name = E.field(E.string);
230
+ * email = E.field(E.string);
231
+ *
232
+ * static byEmail = E.index(User, "email", "unique");
233
+ * }
234
+ * ```
235
+ */
236
+ export class Model {
237
+ /** @internal Primary key index for this model. */
238
+ static _pk;
239
+ /** @internal All indexes for this model, the primary key being first. */
240
+ static _indexes;
241
+ /** The database table name (defaults to class name). */
242
+ static tableName;
243
+ /** Field configuration metadata. */
244
+ static fields;
245
+ /*
246
+ * IMPORTANT: We cannot use instance property initializers here, because we will be
247
+ * initializing the class through a fake constructor that will skip these. This is
248
+ * intentional, as we don't want to run the initializers for the fields.
249
+ */
250
+ /** @internal Field configuration for this instance. */
251
+ _fields;
252
+ /**
253
+ * @internal State tracking for this model instance:
254
+ * - undefined: new instance, unmodified
255
+ * - 1: new instance, modified (and in modifiedInstances)
256
+ * - 2: loaded from disk, unmodified
257
+ * - 3: persistence disabled
258
+ * - array: loaded from disk, modified (and in modifiedInstances), array values are original index buffers
259
+ */
260
+ _state;
261
+ constructor(initial = {}) {
262
+ // This constructor will only be called once, from `initModels`. All other instances will
263
+ // be created by the 'fake' constructor. The typing for `initial` *is* important though.
264
+ if (initial !== INIT_INSTANCE_SYMBOL) {
265
+ throw new DatabaseError("The model needs a @registerModel decorator", 'INIT_ERROR');
266
+ }
267
+ }
268
+ _save() {
269
+ // For performance, we'll work on the unproxied object, as we know we don't require change tracking for save.
270
+ const unproxiedModel = (this[TARGET_SYMBOL] || this);
271
+ unproxiedModel.validate(true);
272
+ // Handle unique indexes
273
+ const indexes = this.constructor._indexes;
274
+ const originalKeys = typeof unproxiedModel._state === 'object' ? unproxiedModel._state : undefined;
275
+ const newPk = indexes[0]._save(unproxiedModel, originalKeys?.[0]);
276
+ for (let i = 1; i < indexes.length; i++) {
277
+ indexes[i]._save(unproxiedModel, originalKeys?.[i]);
278
+ }
279
+ queueOnSave([this, newPk, originalKeys?.[0]]);
280
+ unproxiedModel._state = 2; // Loaded from disk, unmodified
281
+ }
282
+ /**
283
+ * Load a model instance by primary key.
284
+ * @param args - Primary key field values.
285
+ * @returns The model instance if found, undefined otherwise.
286
+ *
287
+ * @example
288
+ * ```typescript
289
+ * const user = User.load("user123");
290
+ * const post = Post.load("post456", "en");
291
+ * ```
292
+ */
293
+ static load(...args) {
294
+ return this._pk.get(...args);
295
+ }
296
+ /**
297
+ * Prevent this instance from being persisted to the database.
298
+ *
299
+ * Removes the instance from the modified instances set and disables
300
+ * automatic persistence at transaction commit.
301
+ *
302
+ * @returns This model instance for chaining.
303
+ *
304
+ * @example
305
+ * ```typescript
306
+ * const user = User.load("user123");
307
+ * user.name = "New Name";
308
+ * user.preventPersist(); // Changes won't be saved
309
+ * ```
310
+ */
311
+ preventPersist() {
312
+ const modifiedInstances = olmdb.getTransactionData(MODIFIED_INSTANCES_SYMBOL);
313
+ const unproxiedModel = this[TARGET_SYMBOL] || this;
314
+ modifiedInstances.delete(unproxiedModel);
315
+ unproxiedModel._state = 3; // no persist
316
+ return this;
317
+ }
318
+ /**
319
+ * Delete this model instance from the database.
320
+ *
321
+ * Removes the instance and all its index entries from the database and prevents further persistence.
322
+ *
323
+ * @example
324
+ * ```typescript
325
+ * const user = User.load("user123");
326
+ * user.delete(); // Removes from database
327
+ * ```
328
+ */
329
+ delete() {
330
+ const unproxiedModel = (this[TARGET_SYMBOL] || this);
331
+ if (this._state === 2 || typeof this._state === 'object') {
332
+ for (const index of unproxiedModel.constructor._indexes) {
333
+ const key = index._getKeyFromModel(unproxiedModel, true);
334
+ olmdb.del(key);
335
+ if (index instanceof PrimaryIndex)
336
+ queueOnSave([this, undefined, key]);
337
+ }
338
+ }
339
+ this.preventPersist();
340
+ }
341
+ /**
342
+ * Validate all fields in this model instance.
343
+ * @param raise - If true, throw on first validation error.
344
+ * @returns Array of validation errors (empty if valid).
345
+ *
346
+ * @example
347
+ * ```typescript
348
+ * const user = new User();
349
+ * const errors = user.validate();
350
+ * if (errors.length > 0) {
351
+ * console.log("Validation failed:", errors);
352
+ * }
353
+ * ```
354
+ */
355
+ validate(raise = false) {
356
+ const errors = [];
357
+ for (const [key, fieldConfig] of Object.entries(this._fields)) {
358
+ for (const error of fieldConfig.type.getErrors(this, key)) {
359
+ addErrorPath(error, key);
360
+ if (raise)
361
+ throw error;
362
+ errors.push(error);
363
+ }
364
+ }
365
+ return errors;
366
+ }
367
+ /**
368
+ * Check if this model instance is valid.
369
+ * @returns true if all validations pass.
370
+ *
371
+ * @example
372
+ * ```typescript
373
+ * const user = new User({name: "John"});
374
+ * if (!user.isValid()) shoutAtTheUser();
375
+ * ```
376
+ */
377
+ isValid() {
378
+ return this.validate().length === 0;
379
+ }
380
+ }
381
+ // We use recursive proxies to track modifications made to, say, arrays within models. In
382
+ // order to know which model a nested object belongs to, we maintain a WeakMap that maps
383
+ // objects to their owner (unproxied) model.
384
+ const modificationOwnerMap = new WeakMap();
385
+ // A cache for the proxies around nested objects, so that we don't need to recreate them
386
+ // every time we access a property on a nested object (and so that their identity remains
387
+ // the same).
388
+ const modificationProxyCache = new WeakMap();
389
+ // Single proxy handler for both models and nested objects
390
+ export const modificationTracker = {
391
+ get(target, prop) {
392
+ if (prop === TARGET_SYMBOL)
393
+ return target;
394
+ const value = target[prop];
395
+ if (!value || typeof value !== 'object' || (value instanceof Model))
396
+ return value;
397
+ // Check cache first
398
+ let proxy = modificationProxyCache.get(value);
399
+ if (proxy)
400
+ return proxy;
401
+ let model;
402
+ if (target instanceof Model) {
403
+ if (!target._fields[prop]) {
404
+ // No need to track properties that are not model fields.
405
+ return value;
406
+ }
407
+ model = target;
408
+ }
409
+ else {
410
+ model = modificationOwnerMap.get(target);
411
+ assert(model);
412
+ }
413
+ let state = model._state;
414
+ if (state !== undefined && state !== 2) {
415
+ // We don't need to track changes for this model (anymore). So we can just return the unproxied object.
416
+ // As we doing the modificationProxyCache lookup first, the identity of returned objects will not change:
417
+ // once a proxied object is returned, the same property will always return a proxied object.
418
+ return value;
419
+ }
420
+ if (modificationOwnerMap.get(value)) {
421
+ throw new DatabaseError("Object cannot be embedded in multiple model instances", 'VALUE_ERROR');
422
+ }
423
+ modificationOwnerMap.set(value, model);
424
+ proxy = new Proxy(value, modificationTracker);
425
+ modificationProxyCache.set(value, proxy);
426
+ return proxy;
427
+ },
428
+ set(target, prop, value) {
429
+ let model;
430
+ if (target instanceof Model) {
431
+ model = target;
432
+ if (!model._fields[prop]) {
433
+ // No need to track properties that are not model fields.
434
+ target[prop] = value;
435
+ return true;
436
+ }
437
+ }
438
+ else {
439
+ model = modificationOwnerMap.get(target);
440
+ assert(model);
441
+ }
442
+ let state = model._state;
443
+ if (state === undefined || state === 2) {
444
+ const modifiedInstances = olmdb.getTransactionData(MODIFIED_INSTANCES_SYMBOL);
445
+ modifiedInstances.add(model);
446
+ if (state === 2) {
447
+ model._state = model.constructor._indexes.map(idx => idx._getKeyFromModel(model, true));
448
+ }
449
+ else {
450
+ model._state = 1;
451
+ }
452
+ }
453
+ target[prop] = value;
454
+ return true;
455
+ }
456
+ };
457
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/models.ts"],"names":[],"mappings":"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"}