miragejs-orm 0.1.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.
@@ -0,0 +1,3044 @@
1
+ /**
2
+ * Type for allowed ID types
3
+ */
4
+ type IdType = number | string;
5
+ /**
6
+ * Type for ID generator function that takes current ID and returns next ID
7
+ * @template T - The type of ID
8
+ * @param currentId - The current ID
9
+ * @returns The next ID
10
+ */
11
+ type IdGenerator<T> = (currentId: T) => T;
12
+ /**
13
+ * Configuration options for the IdentityManager
14
+ * @template T - The type of ID
15
+ * @param initialCounter - The initial counter value
16
+ * @param initialUsedIds - A set of initial used IDs
17
+ * @param idGenerator - Custom function to generate the next ID
18
+ */
19
+ interface IdentityManagerConfig<T = string> {
20
+ initialCounter: T;
21
+ initialUsedIds?: T[];
22
+ idGenerator?: IdGenerator<T>;
23
+ }
24
+
25
+ /**
26
+ * Manages unique identifiers for database records.
27
+ * Handles different types of IDs, ensuring uniqueness and proper sequencing.
28
+ * @template T - The type of ID to manage (defaults to string)
29
+ * @param options - Configuration options for the identity manager.
30
+ * @param options.initialCounter - The initial counter value.
31
+ * @param options.initialUsedIds - A set of initial used IDs.
32
+ * @param options.idGenerator - Custom function to generate the next ID.
33
+ * @example
34
+ * const identityManager = new IdentityManager();
35
+ * identityManager.get(); // => "1"
36
+ * identityManager.set("1");
37
+ * identityManager.get(); // => "2"
38
+ * identityManager.fetch(); // => "2"
39
+ * identityManager.get(); // => "3"
40
+ * identityManager.reset(); // => "1"
41
+ */
42
+ declare class IdentityManager<T extends IdType = string> {
43
+ private _counter;
44
+ private _idGenerator;
45
+ private _initialCounter;
46
+ private _usedIds;
47
+ constructor(options: IdentityManagerConfig<T>);
48
+ /**
49
+ * Gets the next ID without incrementing the counter.
50
+ * @returns The next ID.
51
+ */
52
+ get(): T;
53
+ /**
54
+ * Gets the next ID and increments the counter.
55
+ * @returns The next ID.
56
+ */
57
+ fetch(): T;
58
+ /**
59
+ * Marks an ID as used and updates the counter if necessary.
60
+ * @param id - The ID to mark as used.
61
+ */
62
+ set(id: T): void;
63
+ /**
64
+ * Increments the counter.
65
+ */
66
+ inc(): void;
67
+ /**
68
+ * Resets the counter to its initial value and clears used IDs.
69
+ */
70
+ reset(): void;
71
+ /**
72
+ * Gets the default generator for the ID type.
73
+ * @returns The default generator function.
74
+ */
75
+ private getDefaultGenerator;
76
+ }
77
+ /**
78
+ * String-based identity manager with sensible defaults.
79
+ * @example
80
+ * const identityManager = new StringIdentityManager();
81
+ * identityManager.fetch(); // => "1"
82
+ * identityManager.fetch(); // => "2"
83
+ */
84
+ declare class StringIdentityManager extends IdentityManager<string> {
85
+ constructor(options?: Partial<IdentityManagerConfig<string>>);
86
+ }
87
+ /**
88
+ * Number-based identity manager with sensible defaults.
89
+ * @example
90
+ * const identityManager = new NumberIdentityManager();
91
+ * identityManager.fetch(); // => 1
92
+ * identityManager.fetch(); // => 2
93
+ */
94
+ declare class NumberIdentityManager extends IdentityManager<number> {
95
+ constructor(options?: Partial<IdentityManagerConfig<number>>);
96
+ }
97
+
98
+ /**
99
+ * Base record type with an ID field
100
+ * @template TId - The type of the ID field
101
+ */
102
+ type DbRecord<TId = IdType> = {
103
+ id: TId;
104
+ };
105
+ /**
106
+ * Type for input data when creating or updating a record
107
+ * @template TRecord - The type of the record's attributes
108
+ */
109
+ type DbRecordInput<TRecord extends DbRecord> = Partial<TRecord>;
110
+ /**
111
+ * Type for new record with optional id
112
+ * @template TRecord - The type of the record's attributes
113
+ */
114
+ type NewDbRecord<TRecord extends DbRecord> = Omit<TRecord, 'id'> & {
115
+ id?: TRecord['id'] | null;
116
+ };
117
+ /**
118
+ * Type for database collections
119
+ */
120
+ type DbCollections = Record<string, DbCollection<any>>;
121
+ /**
122
+ * Infers the collection type from data records
123
+ * @template TData - The type of data records
124
+ */
125
+ type DbCollectionFromStaticData<TData> = TData extends Array<infer TRecord> ? TRecord extends DbRecord ? DbCollection<TRecord> : DbCollection<DbRecord> : DbCollection<DbRecord>;
126
+ /**
127
+ * Infers collections map from data object
128
+ * @template TData - The type of data object
129
+ */
130
+ type DbCollectionsFromStaticData<TData> = {
131
+ [K in keyof TData]: DbCollectionFromStaticData<TData[K]>;
132
+ };
133
+ /**
134
+ * Gets the data of a collection
135
+ * @template T - The type of the collection
136
+ */
137
+ type DbCollectionData<T> = T extends DbCollection<infer TAttrs> ? TAttrs[] : never;
138
+ /**
139
+ * Configuration for creating a database collection
140
+ * @template TRecord - The type of the record's attributes
141
+ */
142
+ interface DbCollectionConfig<TRecord extends DbRecord> {
143
+ identityManager?: IdentityManager<TRecord['id']>;
144
+ initialData?: TRecord[];
145
+ }
146
+ /**
147
+ * Type for a database's data
148
+ * @template TCollections - The type of collections in the database
149
+ */
150
+ type DbData<TCollections extends Record<string, DbCollection<any>>> = {
151
+ [K in keyof TCollections]: DbCollectionData<TCollections[K]>;
152
+ };
153
+ /**
154
+ * Configuration for creating a DB instance
155
+ * @template TCollections - The type of collections in the database
156
+ */
157
+ type DbConfig<TCollections extends Record<string, DbCollection<any>>> = {
158
+ initialData?: DbData<TCollections>;
159
+ };
160
+ /**
161
+ * Primitive types that support comparison operations
162
+ */
163
+ type Primitive = string | number | boolean | Date;
164
+ /**
165
+ * Order direction for sorting
166
+ */
167
+ type OrderDirection = 'asc' | 'desc';
168
+ /**
169
+ * Defines ordering for query results
170
+ * Can be an object mapping fields to directions, or an array of [field, direction] tuples
171
+ * @template TRecord - The record type
172
+ */
173
+ type OrderBy<TRecord> = Partial<Record<keyof TRecord, OrderDirection>> | Array<readonly [keyof TRecord, OrderDirection]>;
174
+ /**
175
+ * Equality and membership operations
176
+ * @template T - The field type
177
+ */
178
+ type EqualityOps<T> = {
179
+ /** Equals */
180
+ eq?: T;
181
+ /** Not equals */
182
+ ne?: T;
183
+ /** In array */
184
+ in?: T[];
185
+ /** Not in array */
186
+ nin?: T[];
187
+ /** Is null or undefined */
188
+ isNull?: boolean;
189
+ };
190
+ /**
191
+ * Range comparison operations for primitive types
192
+ * @template T - The primitive field type
193
+ */
194
+ type RangeOps<T extends Primitive> = {
195
+ /** Less than */
196
+ lt?: T;
197
+ /** Less than or equal */
198
+ lte?: T;
199
+ /** Greater than */
200
+ gt?: T;
201
+ /** Greater than or equal */
202
+ gte?: T;
203
+ /** Between two values (inclusive) */
204
+ between?: readonly [T, T];
205
+ };
206
+ /**
207
+ * String-specific operations
208
+ */
209
+ type StringOps = {
210
+ /** SQL-like pattern matching with % wildcards */
211
+ like?: string;
212
+ /** Case-insensitive like */
213
+ ilike?: string;
214
+ /** Starts with prefix */
215
+ startsWith?: string;
216
+ /** Ends with suffix */
217
+ endsWith?: string;
218
+ /** Contains substring */
219
+ contains?: string;
220
+ };
221
+ /**
222
+ * Array-specific operations
223
+ * @template E - The array element type
224
+ */
225
+ type ArrayOps<E> = {
226
+ /** Array contains element(s) */
227
+ contains?: E | E[];
228
+ /** Array length operations */
229
+ length?: RangeOps<number>;
230
+ };
231
+ /**
232
+ * All available field operations based on field type
233
+ * @template T - The field type
234
+ */
235
+ type FieldOps<T> = EqualityOps<T> & (T extends string ? StringOps : {}) & (T extends Primitive ? RangeOps<T> : {}) & (T extends readonly (infer E)[] ? ArrayOps<E> : {});
236
+ /**
237
+ * Leaf-level where clause for field matching
238
+ * Fields can be matched by direct value or by field operations
239
+ * @template TRecord - The record type
240
+ */
241
+ type WhereLeaf<TRecord> = {
242
+ [K in keyof TRecord]?: TRecord[K] | FieldOps<TRecord[K]>;
243
+ };
244
+ /**
245
+ * Complete where clause with logical operators
246
+ * @template TRecord - The record type
247
+ */
248
+ type Where<TRecord> = WhereLeaf<TRecord> & {
249
+ /** Logical AND - all conditions must match */
250
+ AND?: Where<TRecord>[];
251
+ /** Logical OR - at least one condition must match */
252
+ OR?: Where<TRecord>[];
253
+ /** Logical NOT - condition must not match */
254
+ NOT?: Where<TRecord>;
255
+ };
256
+ /**
257
+ * Helper functions for use in where callback predicates
258
+ * These are comparison utilities - users access record values and pass them to helpers
259
+ * @template TRecord - The record type
260
+ */
261
+ type WhereHelperFns<TRecord> = {
262
+ /** Logical AND - all conditions must be true */
263
+ and: (...conditions: boolean[]) => boolean;
264
+ /** Logical OR - at least one condition must be true */
265
+ or: (...conditions: boolean[]) => boolean;
266
+ /** Logical NOT - inverts the condition */
267
+ not: (condition: boolean) => boolean;
268
+ /** Check equality */
269
+ eq: (value: any, compareWith: any) => boolean;
270
+ /** Check inequality */
271
+ ne: (value: any, compareWith: any) => boolean;
272
+ /** Greater than */
273
+ gt: (value: any, compareWith: any) => boolean;
274
+ /** Greater than or equal */
275
+ gte: (value: any, compareWith: any) => boolean;
276
+ /** Less than */
277
+ lt: (value: any, compareWith: any) => boolean;
278
+ /** Less than or equal */
279
+ lte: (value: any, compareWith: any) => boolean;
280
+ /** Between two values (inclusive) */
281
+ between: (value: any, min: any, max: any) => boolean;
282
+ /** SQL-like pattern matching */
283
+ like: (value: string, pattern: string) => boolean;
284
+ /** Case-insensitive like */
285
+ ilike: (value: string, pattern: string) => boolean;
286
+ /** Starts with string */
287
+ startsWith: (value: string, prefix: string) => boolean;
288
+ /** Ends with string */
289
+ endsWith: (value: string, suffix: string) => boolean;
290
+ /** Contains substring */
291
+ containsText: (value: string, substring: string) => boolean;
292
+ /** In array */
293
+ inArray: (value: any, values: any[]) => boolean;
294
+ /** Not in array */
295
+ notInArray: (value: any, values: any[]) => boolean;
296
+ /** Is null or undefined */
297
+ isNull: (value: any) => boolean;
298
+ /** Is not null and not undefined */
299
+ isNotNull: (value: any) => boolean;
300
+ };
301
+ /**
302
+ * Query options for finding records
303
+ * @template TRecord - The record type
304
+ */
305
+ interface QueryOptions<TRecord> {
306
+ /** Filter criteria - object DSL or callback function */
307
+ where?: Where<TRecord> | ((record: TRecord, helpers: WhereHelperFns<TRecord>) => boolean);
308
+ /** Sorting specification */
309
+ orderBy?: OrderBy<TRecord>;
310
+ /** Number of records to skip (offset pagination) */
311
+ offset?: number;
312
+ /** Maximum number of records to return */
313
+ limit?: number;
314
+ /** Cursor for keyset pagination (must align with orderBy fields) */
315
+ cursor?: Partial<TRecord>;
316
+ }
317
+
318
+ /**
319
+ * A collection of records in a database. Think of it as a table in a relational database.
320
+ * @param config - Configuration for the collection.
321
+ * @param config.name - The name of the collection.
322
+ * @param config.identityManager - The identity manager for the collection.
323
+ * @param config.initialData - Initial data for the collection.
324
+ * @example
325
+ * const users = new DbCollection({ name: 'users' });
326
+ * users.insert({ name: 'John' }); // => { id: "1", name: 'John' }
327
+ */
328
+ declare class DbCollection<TRecord extends DbRecord = DbRecord> {
329
+ name: string;
330
+ identityManager: IdentityManager<TRecord['id']>;
331
+ private _records;
332
+ private _queryManager;
333
+ constructor(name: string, config?: DbCollectionConfig<TRecord>);
334
+ /**
335
+ * The next ID for the collection.
336
+ * @returns The next ID for the collection.
337
+ */
338
+ get nextId(): TRecord['id'];
339
+ /**
340
+ * Returns the number of records in the collection.
341
+ * @returns The number of records in the collection.
342
+ */
343
+ get size(): number;
344
+ /**
345
+ * Checks if the collection is empty.
346
+ * @returns `true` if the collection is empty, `false` otherwise.
347
+ */
348
+ get isEmpty(): boolean;
349
+ /**
350
+ * Returns all records in the collection
351
+ * @returns An array of all records in the collection.
352
+ */
353
+ all(): TRecord[];
354
+ /**
355
+ * Gets a record by its index position in the collection.
356
+ * @param index - The index of the record to get.
357
+ * @returns The record at the specified index, or `undefined` if out of bounds.
358
+ */
359
+ at(index: number): TRecord | undefined;
360
+ /**
361
+ * Returns the first record in the collection.
362
+ * @returns The first record in the collection, or `undefined` if the collection is empty.
363
+ */
364
+ first(): TRecord | undefined;
365
+ /**
366
+ * Returns the last record in the collection.
367
+ * @returns The last record in the collection, or `undefined` if the collection is empty.
368
+ */
369
+ last(): TRecord | undefined;
370
+ /**
371
+ * Checks if a record exists in the collection.
372
+ * @param id - The ID of the record to check.
373
+ * @returns `true` if the record exists, `false` otherwise.
374
+ */
375
+ has(id: TRecord['id']): boolean;
376
+ /**
377
+ * Finds the first record that matches the given ID, predicate object, or query options.
378
+ * @param input - ID, predicate object, or query options
379
+ * @returns The first record that matches, or `null` if not found.
380
+ * @example
381
+ * ```typescript
382
+ * // By ID
383
+ * collection.find('user-1');
384
+ *
385
+ * // By predicate object (simple equality)
386
+ * collection.find({ email: 'user@example.com' });
387
+ *
388
+ * // By query options (advanced filtering, sorting)
389
+ * collection.find({
390
+ * where: { email: { ilike: '%@example.com' } },
391
+ * orderBy: { createdAt: 'desc' },
392
+ * });
393
+ * ```
394
+ */
395
+ find(input: TRecord['id'] | DbRecordInput<TRecord> | QueryOptions<TRecord>): TRecord | null;
396
+ /**
397
+ * Finds multiple records by IDs, predicate object, or query options.
398
+ * @param input - Array of IDs, predicate object, or query options
399
+ * @returns An array of records that match
400
+ * @example
401
+ * ```typescript
402
+ * // By IDs
403
+ * collection.findMany(['user-1', 'user-2']);
404
+ *
405
+ * // By predicate object (simple equality)
406
+ * collection.findMany({ active: true });
407
+ *
408
+ * // By query options (advanced filtering, sorting, pagination)
409
+ * collection.findMany({
410
+ * where: { age: { gte: 18 }, status: { in: ['active', 'pending'] } },
411
+ * orderBy: { createdAt: 'desc' },
412
+ * limit: 10,
413
+ * });
414
+ * ```
415
+ */
416
+ findMany(input: TRecord['id'][] | DbRecordInput<TRecord> | QueryOptions<TRecord>): TRecord[];
417
+ /**
418
+ * Count records matching a where clause.
419
+ * @param where - Optional where clause to filter records
420
+ * @returns Number of matching records
421
+ * @example
422
+ * ```typescript
423
+ * collection.count({ status: 'active' });
424
+ * collection.count({ age: { gte: 18, lte: 65 } });
425
+ * ```
426
+ */
427
+ count(where?: Where<TRecord>): number;
428
+ /**
429
+ * Check if any records match a where clause.
430
+ * @param where - Optional where clause to filter records
431
+ * @returns True if at least one record matches
432
+ * @example
433
+ * ```typescript
434
+ * collection.exists({ email: 'user@example.com' });
435
+ * collection.exists({ status: { in: ['active', 'pending'] } });
436
+ * ```
437
+ */
438
+ exists(where?: Where<TRecord>): boolean;
439
+ /**
440
+ * Inserts a new record into the collection.
441
+ * @param data - The record data to insert.
442
+ * @returns The inserted record.
443
+ */
444
+ insert(data: NewDbRecord<TRecord>): TRecord;
445
+ /**
446
+ * Inserts multiple records into the collection.
447
+ * @param data - An array of record data to insert.
448
+ * @returns An array of the inserted records.
449
+ */
450
+ insertMany(data: NewDbRecord<TRecord>[]): TRecord[];
451
+ /**
452
+ * Updates a single record by ID.
453
+ * @param id - The record ID to update.
454
+ * @param patch - The data to update the record with.
455
+ * @returns The updated record, or `null` if the record was not found.
456
+ */
457
+ update(id: TRecord['id'], patch: TRecord | DbRecordInput<TRecord>): TRecord | null;
458
+ /**
459
+ * Updates multiple records by IDs, predicate object, or query options.
460
+ * @param input - Array of IDs, predicate object, or query options to find records.
461
+ * @param patch - The data to update the records with.
462
+ * @returns Array of updated records.
463
+ */
464
+ updateMany(input: TRecord['id'][] | DbRecordInput<TRecord> | QueryOptions<TRecord>, patch: TRecord | DbRecordInput<TRecord>): TRecord[];
465
+ /**
466
+ * Deletes a record from the collection by its ID.
467
+ * @param id - The ID of the record to delete.
468
+ * @returns `true` if the record was deleted, `false` if it was not found.
469
+ */
470
+ delete(id: TRecord['id']): boolean;
471
+ /**
472
+ * Deletes multiple records by IDs, predicate object, or query options.
473
+ * @param input - Array of IDs, predicate object, or query options to find records.
474
+ * @returns The number of records that were deleted.
475
+ */
476
+ deleteMany(input: TRecord['id'][] | DbRecordInput<TRecord> | QueryOptions<TRecord>): number;
477
+ /**
478
+ * Removes all records from the collection.
479
+ */
480
+ clear(): void;
481
+ /**
482
+ * Prepares a record for insertion by generating an ID if it doesn't exist.
483
+ * @param data - The record to prepare.
484
+ * @returns The prepared record.
485
+ */
486
+ private _prepareRecord;
487
+ }
488
+
489
+ /**
490
+ * A database for storing and managing collections of records.
491
+ * @template TCollections - The type of collections in the database
492
+ * @example
493
+ * const db = DB.create({
494
+ * users: [{ id: "1", name: 'John' }],
495
+ * posts: [{ id: "1", title: 'Hello' }]
496
+ * });
497
+ * db.users.records;
498
+ */
499
+ declare class DB<TCollections extends DbCollections> {
500
+ private _collections;
501
+ constructor(config?: DbConfig<TCollections>);
502
+ /**
503
+ * Checks if a collection exists.
504
+ * @param name - The name of the collection to check.
505
+ * @returns `true` if the collection exists, `false` otherwise.
506
+ */
507
+ hasCollection(name: keyof TCollections): boolean;
508
+ /**
509
+ * Creates a new collection with the given name and initial data.
510
+ * @param name - The name of the collection to create.
511
+ * @param config - The configuration for the collection.
512
+ * @param config.initialData - The initial data to populate the collection with.
513
+ * @param config.identityManager - The identity manager for the collection.
514
+ * @returns The DB instance.
515
+ */
516
+ createCollection<TAttrs extends DbRecord>(name: keyof TCollections, config?: Omit<DbCollectionConfig<TAttrs>, 'name'>): DbInstance<TCollections & {
517
+ [K in keyof TCollections]: DbCollection<TAttrs>;
518
+ }>;
519
+ /**
520
+ * Retrieves a collection by its name.
521
+ * @template T - The collection key
522
+ * @param name - The name of the collection to retrieve.
523
+ * @returns The collection with the specified name.
524
+ * @throws {Error} If the collection does not exist.
525
+ */
526
+ getCollection<T extends keyof TCollections>(name: T): TCollections[T];
527
+ /**
528
+ * Retrieves the identity manager for a given collection name.
529
+ * @param collectionName - The name of the collection to get the identity manager for.
530
+ * @returns The identity manager for the given collection name.
531
+ * @throws {Error} If the collection does not exist.
532
+ */
533
+ identityManagerFor(collectionName: keyof TCollections): IdentityManager<IdType>;
534
+ /**
535
+ * Loads collections data from a record into the database.
536
+ * @template TData - The type of data to load
537
+ * @param data - Record of collection names and their initial data
538
+ * @returns The DB instance with collection accessors for the loaded data.
539
+ */
540
+ loadData<TData extends Record<string, DbRecord[]>>(data: TData): DbInstance<TCollections & DbCollectionsFromStaticData<TData>>;
541
+ /**
542
+ * Empties the data from all collections in the database.
543
+ */
544
+ emptyData(): void;
545
+ /**
546
+ * Dumps the data from all collections in the database.
547
+ * @returns A record of collection names and their data.
548
+ */
549
+ dump(): DbData<TCollections>;
550
+ private initCollectionAccessors;
551
+ }
552
+ /**
553
+ * Type for a DB instance with collection accessors
554
+ * @template TCollections - The type of collections in the database
555
+ */
556
+ type DbInstance<TCollections extends Record<string, DbCollection<any>>> = DB<TCollections> & {
557
+ [K in keyof TCollections]: TCollections[K];
558
+ };
559
+
560
+ /**
561
+ * Logger class for outputting structured log messages.
562
+ *
563
+ * Provides debug, info, warn, and error logging methods with automatic level filtering.
564
+ * Used internally by the ORM to log database operations, seed/fixture loading, and errors.
565
+ * @example
566
+ * ```typescript
567
+ * const logger = new Logger({
568
+ * enabled: true,
569
+ * level: 'debug',
570
+ * prefix: '[MyApp]'
571
+ * });
572
+ *
573
+ * logger.debug('Operation started', { userId: '123' });
574
+ * logger.info('Loaded 10 records');
575
+ * logger.warn('Missing optional field', { field: 'email' });
576
+ * logger.error('Validation failed', { errors: [...] });
577
+ * ```
578
+ */
579
+ declare class Logger {
580
+ private _config;
581
+ /**
582
+ * Creates a new Logger instance with the specified configuration.
583
+ * @param config - Logger configuration including enabled state, log level, and optional prefix
584
+ * @example
585
+ * ```typescript
586
+ * const logger = new Logger({
587
+ * enabled: true,
588
+ * level: 'debug',
589
+ * prefix: '[Mirage]'
590
+ * });
591
+ * ```
592
+ */
593
+ constructor(config: LoggerConfig);
594
+ /**
595
+ * Logs a debug message with optional context.
596
+ *
597
+ * Debug logs are the most verbose and show low-level operational details.
598
+ * Use for troubleshooting, understanding flow, and performance analysis.
599
+ *
600
+ * Only outputs if logger is enabled and level is set to 'debug'.
601
+ * @param message - The debug message to log
602
+ * @param context - Optional context object with additional information
603
+ * @example
604
+ * ```typescript
605
+ * logger.debug('Query executed', { collection: 'users', query: { name: 'John' } });
606
+ * // Output: [Mirage] DEBUG: Query executed { collection: 'users', query: { name: 'John' } }
607
+ * ```
608
+ */
609
+ debug(message: string, context?: Record<string, unknown>): void;
610
+ /**
611
+ * Logs an info message with optional context.
612
+ *
613
+ * Info logs show normal operations and important events.
614
+ * Use for high-level actions, successful operations, and summaries.
615
+ *
616
+ * Only outputs if logger is enabled and level is 'debug' or 'info'.
617
+ * @param message - The info message to log
618
+ * @param context - Optional context object with additional information
619
+ * @example
620
+ * ```typescript
621
+ * logger.info('Fixtures loaded', { collection: 'users', count: 50 });
622
+ * // Output: [Mirage] INFO: Fixtures loaded { collection: 'users', count: 50 }
623
+ * ```
624
+ */
625
+ info(message: string, context?: Record<string, unknown>): void;
626
+ /**
627
+ * Logs a warning message with optional context.
628
+ *
629
+ * Warning logs indicate something unexpected but not breaking.
630
+ * Use for deprecated features, unusual patterns, and potential issues.
631
+ *
632
+ * Only outputs if logger is enabled and level is 'debug', 'info', or 'warn'.
633
+ * @param message - The warning message to log
634
+ * @param context - Optional context object with additional information
635
+ * @example
636
+ * ```typescript
637
+ * logger.warn('Foreign key mismatch', { postId: '1', authorId: '999' });
638
+ * // Output: [Mirage] WARN: Foreign key mismatch { postId: '1', authorId: '999' }
639
+ * ```
640
+ */
641
+ warn(message: string, context?: Record<string, unknown>): void;
642
+ /**
643
+ * Logs an error message with optional context.
644
+ *
645
+ * Error logs indicate something failed or broke.
646
+ * Use for operations that couldn't complete and validation failures.
647
+ *
648
+ * Only outputs if logger is enabled and level is not 'silent'.
649
+ * @param message - The error message to log
650
+ * @param context - Optional context object with additional information
651
+ * @example
652
+ * ```typescript
653
+ * logger.error('Validation failed', { field: 'email', reason: 'required' });
654
+ * // Output: [Mirage] ERROR: Validation failed { field: 'email', reason: 'required' }
655
+ * ```
656
+ */
657
+ error(message: string, context?: Record<string, unknown>): void;
658
+ /**
659
+ * Internal method to handle actual logging with level filtering.
660
+ *
661
+ * Checks if logging is enabled and if the message level meets the configured threshold.
662
+ * Routes messages to appropriate console methods based on severity.
663
+ * @param level - The log level of the message
664
+ * @param message - The message to log
665
+ * @param context - Optional context object
666
+ * @private
667
+ */
668
+ private _log;
669
+ }
670
+ /**
671
+ * Log level type defining the severity of log messages.
672
+ *
673
+ * Log levels follow a hierarchy where setting a level shows that level and everything above it:
674
+ * - `silent`: No logging
675
+ * - `error`: Only errors
676
+ * - `warn`: Warnings and errors
677
+ * - `info`: Info, warnings, and errors
678
+ * - `debug`: All messages (most verbose)
679
+ * @example
680
+ * ```typescript
681
+ * // Debug level - see everything
682
+ * schema().logging({ enabled: true, level: 'debug' })
683
+ *
684
+ * // Info level - only important operations
685
+ * schema().logging({ enabled: true, level: 'info' })
686
+ *
687
+ * // Error level - only failures
688
+ * schema().logging({ enabled: true, level: 'error' })
689
+ * ```
690
+ */
691
+ type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'silent';
692
+ /**
693
+ * Logger configuration options.
694
+ */
695
+ interface LoggerConfig {
696
+ /**
697
+ * Whether logging is enabled. When false, no logs are output regardless of level.
698
+ * @default false
699
+ */
700
+ enabled: boolean;
701
+ /**
702
+ * The minimum log level to output. Messages below this level are filtered out.
703
+ * @default 'info'
704
+ */
705
+ level: LogLevel;
706
+ /**
707
+ * Custom prefix for log messages. Useful for distinguishing ORM logs from other output.
708
+ * @default '[Mirage]'
709
+ */
710
+ prefix?: string;
711
+ }
712
+
713
+ /**
714
+ * A collection of models with array-like interface
715
+ * @template TTemplate - The model template (most important for users)
716
+ * @template TSchema - The schema collections type for enhanced type inference
717
+ * @template TSerializer - The serializer type
718
+ */
719
+ declare class ModelCollection<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined> {
720
+ private readonly _template;
721
+ readonly collectionName: string;
722
+ models: Array<ModelInstance<TTemplate, TSchema, TSerializer>>;
723
+ protected _serializer?: TSerializer;
724
+ constructor(template: TTemplate, models?: Array<ModelInstance<TTemplate, TSchema, TSerializer>>, serializer?: TSerializer);
725
+ /**
726
+ * Get the length of the collection
727
+ * @returns The number of models in the collection
728
+ */
729
+ get length(): number;
730
+ /**
731
+ * Check if the collection is empty
732
+ * @returns True if the collection is empty, false otherwise
733
+ */
734
+ get isEmpty(): boolean;
735
+ /**
736
+ * Get a model by index
737
+ * @param index - The index of the model to get
738
+ * @returns The model at the given index or undefined
739
+ */
740
+ at(index: number): ModelInstance<TTemplate, TSchema, TSerializer> | undefined;
741
+ /**
742
+ * Get the first model in the collection
743
+ * @returns The first model or null if the collection is empty
744
+ */
745
+ first(): ModelInstance<TTemplate, TSchema, TSerializer> | null;
746
+ /**
747
+ * Get the last model in the collection
748
+ * @returns The last model or null if the collection is empty
749
+ */
750
+ last(): ModelInstance<TTemplate, TSchema, TSerializer> | null;
751
+ /**
752
+ * Execute a function for each model in the collection
753
+ * @param cb - The function to execute for each model
754
+ */
755
+ forEach(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => void): void;
756
+ /**
757
+ * Create a new array with the results of calling a function for each model
758
+ * @param cb - The function to call for each model
759
+ * @returns A new array with the results
760
+ */
761
+ map(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => ModelInstance<TTemplate, TSchema, TSerializer>): ModelCollection<TTemplate, TSchema, TSerializer>;
762
+ /**
763
+ * Create a new collection with models that pass a test
764
+ * @param cb - The test function
765
+ * @returns A new ModelCollection with the filtered models
766
+ */
767
+ filter(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => boolean): ModelCollection<TTemplate, TSchema, TSerializer>;
768
+ /**
769
+ * Find the first model that satisfies a test
770
+ * @param cb - The test function
771
+ * @returns The first model that passes the test, or undefined
772
+ */
773
+ find(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => boolean): ModelInstance<TTemplate, TSchema, TSerializer> | undefined;
774
+ /**
775
+ * Check if at least one model satisfies a test
776
+ * @param cb - The test function
777
+ * @returns True if at least one model passes the test
778
+ */
779
+ some(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => boolean): boolean;
780
+ /**
781
+ * Check if all models satisfy a test
782
+ * @param cb - The test function
783
+ * @returns True if all models pass the test
784
+ */
785
+ every(cb: (model: ModelInstance<TTemplate, TSchema, TSerializer>, index: number, collection: this) => boolean): boolean;
786
+ /**
787
+ * Concatenate this collection with other collections or arrays
788
+ * @param others - Other collections or arrays to concatenate
789
+ * @returns A new ModelCollection with all models
790
+ */
791
+ concat(...others: (ModelCollection<TTemplate, TSchema, TSerializer> | ModelInstance<TTemplate, TSchema, TSerializer>[])[]): ModelCollection<TTemplate, TSchema, TSerializer>;
792
+ /**
793
+ * Check if the collection includes a specific model
794
+ * @param model - The model to check for
795
+ * @returns True if the model is in the collection
796
+ */
797
+ includes(model: ModelInstance<TTemplate, TSchema, TSerializer>): boolean;
798
+ /**
799
+ * Find the index of a model in the collection
800
+ * @param model - The model to find
801
+ * @returns The index of the model, or -1 if not found
802
+ */
803
+ indexOf(model: ModelInstance<TTemplate, TSchema, TSerializer>): number;
804
+ /**
805
+ * Sort the models in the collection
806
+ * @param compareFn - The comparison function
807
+ * @returns A new sorted ModelCollection
808
+ */
809
+ sort(compareFn?: (a: ModelInstance<TTemplate, TSchema, TSerializer>, b: ModelInstance<TTemplate, TSchema, TSerializer>) => number): ModelCollection<TTemplate, TSchema, TSerializer>;
810
+ /**
811
+ * Reverse the order of models in the collection
812
+ * @returns A new reversed ModelCollection
813
+ */
814
+ reverse(): ModelCollection<TTemplate, TSchema, TSerializer>;
815
+ /**
816
+ * Add a model to the end of the collection (alias for push)
817
+ * @param model - The model to add
818
+ */
819
+ add(model: ModelInstance<TTemplate, TSchema, TSerializer>): void;
820
+ /**
821
+ * Remove a model from the collection
822
+ * @param model - The model to remove
823
+ * @returns True if the model was removed, false if not found
824
+ */
825
+ remove(model: ModelInstance<TTemplate, TSchema, TSerializer>): boolean;
826
+ /**
827
+ * Save all models in the collection
828
+ * @returns The collection instance for chaining
829
+ */
830
+ save(): this;
831
+ /**
832
+ * Destroy all models in the collection
833
+ * @returns The collection instance for chaining
834
+ */
835
+ destroy(): this;
836
+ /**
837
+ * Reload all models in the collection from the database
838
+ * @returns The collection instance for chaining
839
+ */
840
+ reload(): this;
841
+ /**
842
+ * Update all models in the collection with the given attributes
843
+ * @param attrs - The attributes to update
844
+ * @returns The collection instance for chaining
845
+ */
846
+ update(attrs: ModelUpdateAttrs<TTemplate, TSchema>): this;
847
+ /**
848
+ * Convert the collection to a plain array
849
+ * @returns An array of the models
850
+ */
851
+ toArray(): ModelInstance<TTemplate, TSchema, TSerializer>[];
852
+ /**
853
+ * Get a string representation of the collection
854
+ * @returns A string representation showing the collection name and count
855
+ */
856
+ toString(): string;
857
+ /**
858
+ * Convert the collection to JSON
859
+ * Uses serializer if configured, otherwise returns array of raw attributes
860
+ * @returns A serialized representation of the collection
861
+ */
862
+ toJSON(): TSerializer extends {
863
+ serializeCollection(collection: any): infer TSerializedCollection;
864
+ } ? TSerializedCollection : ModelAttrs<TTemplate, TSchema>[];
865
+ /**
866
+ * Make the collection iterable
867
+ * @returns An iterator for the models
868
+ */
869
+ [Symbol.iterator](): Iterator<ModelInstance<TTemplate, TSchema, TSerializer>>;
870
+ }
871
+
872
+ /**
873
+ * Structural serializer options (schema-level or collection-level)
874
+ * Controls how the response is formatted/structured
875
+ */
876
+ interface StructuralSerializerOptions {
877
+ /**
878
+ * Whether to wrap the serialized data in a root key
879
+ * - false: no wrapping (default)
880
+ * - true: wrap with modelName/collectionName
881
+ * - string: wrap with custom key name
882
+ */
883
+ root?: boolean | string;
884
+ /**
885
+ * Whether to embed related models in the serialized output
886
+ * - false: exclude relationships (default)
887
+ * - true: include embedded relationships
888
+ */
889
+ embed?: boolean;
890
+ }
891
+ /**
892
+ * Data selection serializer options (collection-level only)
893
+ * Controls what data to include in serialization
894
+ * @template TTemplate - The model template
895
+ */
896
+ interface DataSerializerOptions<TTemplate extends ModelTemplate> {
897
+ /**
898
+ * Specific attributes to include in serialization
899
+ * If not provided, all attributes are included
900
+ * Note: This is model-specific and not available at schema level
901
+ */
902
+ attrs?: (keyof InferModelAttrs<TTemplate>)[];
903
+ /**
904
+ * Relationship names to include in serialization
905
+ * Note: This is model-specific and not available at schema level
906
+ */
907
+ include?: string[];
908
+ }
909
+ /**
910
+ * Complete serializer options (collection-level)
911
+ * Combines structural and data selection options
912
+ * @template TTemplate - The model template
913
+ */
914
+ interface SerializerOptions<TTemplate extends ModelTemplate> extends StructuralSerializerOptions, DataSerializerOptions<TTemplate> {
915
+ }
916
+
917
+ /**
918
+ * Serializer class that handles model serialization with custom JSON types
919
+ * @template TTemplate - The model template
920
+ * @template TSerializedModel - The serialized model type (for single model)
921
+ * @template TSerializedCollection - The serialized collection type (for array of models)
922
+ * @template TOptions - The serializer options type
923
+ * @example
924
+ * ```typescript
925
+ * interface UserJSON {
926
+ * id: string;
927
+ * name: string;
928
+ * }
929
+ *
930
+ * interface UsersJSON {
931
+ * users: UserJSON[];
932
+ * }
933
+ *
934
+ * const serializer = new Serializer<UserTemplate, UserJSON, UsersJSON>(
935
+ * userTemplate,
936
+ * {
937
+ * attrs: ['id', 'name'],
938
+ * root: 'user'
939
+ * }
940
+ * );
941
+ * ```
942
+ */
943
+ declare class Serializer<TTemplate extends ModelTemplate, TSerializedModel = InferModelAttrs<TTemplate>, TSerializedCollection = TSerializedModel[], TOptions extends SerializerOptions<TTemplate> = SerializerOptions<TTemplate>> {
944
+ protected _template: TTemplate;
945
+ protected _modelName: string;
946
+ protected _collectionName: string;
947
+ protected _attrs: TOptions['attrs'];
948
+ protected _root: TOptions['root'];
949
+ protected _embed: TOptions['embed'];
950
+ protected _include: TOptions['include'];
951
+ constructor(template: TTemplate, options?: TOptions);
952
+ /**
953
+ * Get the model name
954
+ * @returns The model name
955
+ */
956
+ get modelName(): string;
957
+ /**
958
+ * Get the collection name
959
+ * @returns The collection name
960
+ */
961
+ get collectionName(): string;
962
+ /**
963
+ * Serialize raw data from a model without structural wrapping
964
+ * This method extracts and returns the data (attributes + relationships)
965
+ * without applying any root wrapping. Used for embedding relationships.
966
+ * @param model - The model instance to serialize
967
+ * @returns The serialized model data without root wrapping
968
+ */
969
+ serializeData<TSchema extends SchemaCollections>(model: ModelInstance<TTemplate, TSchema>): Record<string, any>;
970
+ /**
971
+ * Serialize a single model instance with structural formatting
972
+ * Applies root wrapping and side-loading if configured
973
+ * @param model - The model instance to serialize
974
+ * @returns The serialized model with structural formatting applied
975
+ */
976
+ serialize<TSchema extends SchemaCollections>(model: ModelInstance<TTemplate, TSchema>): TSerializedModel;
977
+ /**
978
+ * Serialize raw data from a collection without structural wrapping
979
+ * Returns an array of serialized model data without root wrapping
980
+ * @param collection - The model collection to serialize
981
+ * @returns Array of serialized model data
982
+ */
983
+ serializeCollectionData<TSchema extends SchemaCollections>(collection: ModelCollection<TTemplate, TSchema>): Record<string, any>[];
984
+ /**
985
+ * Serialize a model collection with structural formatting
986
+ * Applies root wrapping and side-loading if configured
987
+ * @param collection - The model collection to serialize
988
+ * @returns The serialized collection with structural formatting applied
989
+ */
990
+ serializeCollection<TSchema extends SchemaCollections>(collection: ModelCollection<TTemplate, TSchema>): TSerializedCollection;
991
+ /**
992
+ * Get the attributes to include in serialization
993
+ * Can be overridden in subclasses for custom serialization logic
994
+ * @param model - The model instance
995
+ * @returns Object with attributes
996
+ */
997
+ protected _getAttributes<TSchema extends SchemaCollections>(model: ModelInstance<TTemplate, TSchema>): Record<string, any>;
998
+ /**
999
+ * Get relationships to include in serialization
1000
+ * Returns embedded relationships, side-loaded relationships, and foreign keys
1001
+ * @param model - The model instance
1002
+ * @returns Object with embedded, sideLoaded, and foreignKeys
1003
+ */
1004
+ protected _getRelationships<TSchema extends SchemaCollections>(model: ModelInstance<TTemplate, TSchema>): {
1005
+ embedded: Record<string, any>;
1006
+ sideLoaded: Record<string, any>;
1007
+ foreignKeys: string[];
1008
+ };
1009
+ }
1010
+
1011
+ /**
1012
+ * Seed function that accepts a schema instance
1013
+ * @template TSchema - The schema collections type
1014
+ */
1015
+ type SeedFunction<TSchema extends SchemaCollections = SchemaCollections> = (schema: SchemaInstance<TSchema>) => void | Promise<void>;
1016
+ /**
1017
+ * Named seed scenarios - object with named seed methods
1018
+ * @template TSchema - The schema collections type
1019
+ */
1020
+ type SeedScenarios<TSchema extends SchemaCollections = SchemaCollections> = Record<string, SeedFunction<TSchema>>;
1021
+ /**
1022
+ * Seeds configuration - can be a function or object with named scenarios
1023
+ * @template TSchema - The schema collections type
1024
+ */
1025
+ type Seeds<TSchema extends SchemaCollections = SchemaCollections> = SeedFunction<TSchema> | SeedScenarios<TSchema>;
1026
+ /**
1027
+ * Strategy for loading fixtures
1028
+ * - 'auto': Load fixtures automatically during schema setup
1029
+ * - 'manual': Load fixtures manually by calling loadFixtures()
1030
+ */
1031
+ type FixtureLoadStrategy = 'auto' | 'manual';
1032
+ /**
1033
+ * A single fixture attributes object - matches the model attributes with optional foreign keys
1034
+ * @template TTemplate - The model template
1035
+ * @template TRelationships - The model relationships
1036
+ */
1037
+ type FixtureAttrs<TTemplate extends ModelTemplate, TRelationships extends ModelRelationships = {}> = ModelAttrs<TTemplate> & (Record<string, never> extends TRelationships ? {} : Partial<ModelForeignKeys<TRelationships>>);
1038
+ /**
1039
+ * Fixture configuration for a collection
1040
+ * @template TTemplate - The model template
1041
+ * @template TRelationships - The model relationships
1042
+ */
1043
+ interface FixtureConfig<TTemplate extends ModelTemplate, TRelationships extends ModelRelationships = {}> {
1044
+ /**
1045
+ * Array of fixture attributes to load
1046
+ */
1047
+ records: FixtureAttrs<TTemplate, TRelationships>[];
1048
+ /**
1049
+ * When to load the fixtures (default: 'manual')
1050
+ */
1051
+ strategy?: FixtureLoadStrategy;
1052
+ }
1053
+ /**
1054
+ * Global schema configuration
1055
+ * @template TIdentityManager - The identity manager type
1056
+ * @template TGlobalConfig - The global serializer configuration type
1057
+ */
1058
+ interface SchemaConfig<TIdentityManager extends IdentityManager = StringIdentityManager, TGlobalConfig extends StructuralSerializerOptions | undefined = undefined> {
1059
+ identityManager?: TIdentityManager;
1060
+ globalSerializerConfig?: TGlobalConfig;
1061
+ logging?: LoggerConfig;
1062
+ }
1063
+ /**
1064
+ * Type for collection config
1065
+ * @template TTemplate - The model template
1066
+ * @template TRelationships - The model relationships
1067
+ * @template TFactory - The factory type
1068
+ * @template TSerializer - The serializer instance type
1069
+ * @template TSchema - The schema collections type for seeds typing
1070
+ */
1071
+ interface CollectionConfig<TTemplate extends ModelTemplate, TRelationships extends ModelRelationships = {}, TFactory extends Factory<TTemplate, any, any> | undefined = undefined, TSerializer = undefined, TSchema extends SchemaCollections = SchemaCollections> {
1072
+ model: TTemplate;
1073
+ factory?: TFactory;
1074
+ relationships?: TRelationships;
1075
+ identityManager?: IdentityManager<ModelId<TTemplate>>;
1076
+ /**
1077
+ * Serializer configuration object (attrs, root, embed, include)
1078
+ * Used when collection().serializer({...config}) is called
1079
+ */
1080
+ serializerConfig?: SerializerOptions<TTemplate>;
1081
+ /**
1082
+ * Serializer instance (custom serializer class)
1083
+ * Used when collection().serializer(instance) is called
1084
+ */
1085
+ serializerInstance?: TSerializer;
1086
+ /**
1087
+ * Seeds configuration - can be a function or object with named scenarios
1088
+ * Used when collection().seeds(...) is called
1089
+ */
1090
+ seeds?: Seeds<TSchema>;
1091
+ /**
1092
+ * Fixtures configuration - static data to load into the collection
1093
+ * Used when collection().fixtures(...) is called
1094
+ */
1095
+ fixtures?: FixtureConfig<TTemplate, TRelationships>;
1096
+ }
1097
+ /**
1098
+ * Type for schema collections - provides both string-based property access and symbol-based relationship resolution
1099
+ * @template TCollections - The string-keyed schema collections config
1100
+ */
1101
+ type SchemaCollections = Record<string, CollectionConfig<any, any, any, any, any>>;
1102
+ /**
1103
+ * Type for schema collections - provides string-based property access
1104
+ * @template TCollections - The string-keyed schema collections config
1105
+ */
1106
+ type SchemaCollectionAccessors<TCollections extends SchemaCollections> = {
1107
+ [K in keyof TCollections]: TCollections[K] extends CollectionConfig<infer TTemplate, infer TRelationships, infer TFactory, infer TSerializer, any> ? Collection<TCollections, TTemplate, TRelationships, TFactory, TSerializer> : never;
1108
+ };
1109
+ /**
1110
+ * Maps schema collection configs to database collections with inferred foreign keys
1111
+ * This ensures that database records include foreign key fields based on defined relationships
1112
+ */
1113
+ type SchemaDbCollections<TCollections extends SchemaCollections> = {
1114
+ [K in keyof TCollections]: TCollections[K] extends CollectionConfig<infer TTemplate, infer TRelationships, any, any, any> ? DbCollection<ModelAttrs<TTemplate> & (TRelationships extends ModelRelationships ? ModelForeignKeys<TRelationships> : {})> : never;
1115
+ };
1116
+ /**
1117
+ * Type for collection create/factory attributes - all attributes are optional
1118
+ * Used for passing attributes to create() methods where factory provides defaults
1119
+ * @template TTemplate - The model template
1120
+ * @template TSchema - The schema collections type
1121
+ * @template TRelationships - The model relationships
1122
+ */
1123
+ type CollectionCreateAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>> = Partial<ModelAttrs<TTemplate, TSchema>> & (Record<string, never> extends TRelationships ? {} : Partial<RelatedModelAttrs<TSchema, TRelationships>>);
1124
+ /**
1125
+ * Simplified Collection instance type helper that only requires the template parameter.
1126
+ * Useful for typing collection references without verbose generic parameters.
1127
+ * @template TTemplate - The model template (required)
1128
+ * @template TRelationships - The model relationships (optional, defaults to {})
1129
+ * @template TFactory - The factory type (optional, defaults to undefined)
1130
+ * @template TSerializer - The serializer type (optional, defaults to undefined)
1131
+ * @example
1132
+ * ```typescript
1133
+ * import { CollectionInstance } from '@miragejs/orm';
1134
+ *
1135
+ * // Simple usage
1136
+ * const usersCollection: CollectionInstance<typeof userModel> = schema.users;
1137
+ *
1138
+ * // With relationships
1139
+ * const usersCollection: CollectionInstance<
1140
+ * typeof userModel,
1141
+ * { posts: HasMany<typeof postModel> }
1142
+ * > = schema.users;
1143
+ * ```
1144
+ */
1145
+ type CollectionInstance<TTemplate extends ModelTemplate, TRelationships extends ModelRelationships = {}, TFactory extends Factory<TTemplate, SchemaCollections, ModelTraits<SchemaCollections, TTemplate>> | undefined = undefined, TSerializer = undefined> = Collection<SchemaCollections, TTemplate, TRelationships, TFactory, TSerializer>;
1146
+
1147
+ /**
1148
+ * Collection for managing models of a specific type
1149
+ * @template TSchema - The schema collections type for enhanced type inference
1150
+ * @template TTemplate - The model template type (most important for users)
1151
+ * @template TRelationships - The raw relationships configuration for this collection (inferred from config)
1152
+ * @template TFactory - The factory type (inferred from config)
1153
+ * @template TSerializer - The serializer type (inferred from config)
1154
+ */
1155
+ declare class Collection<TSchema extends SchemaCollections = SchemaCollections, TTemplate extends ModelTemplate = ModelTemplate, TRelationships extends ModelRelationships = {}, TFactory extends Factory<TTemplate, TSchema, ModelTraits<TSchema, TTemplate>> | undefined = undefined, TSerializer = undefined> extends BaseCollection<TSchema, TTemplate, TRelationships, TFactory, TSerializer> {
1156
+ /**
1157
+ * Creates a new model instance (not persisted in the database).
1158
+ * @param attrs - The attributes to create the model with. All required attributes must be provided.
1159
+ * @returns The new model instance.
1160
+ */
1161
+ new(attrs: ModelCreateAttrs<TTemplate, TSchema>): NewModelInstance<TTemplate, TSchema, TSerializer>;
1162
+ /**
1163
+ * Create a new model for the collection.
1164
+ * @param traitsAndDefaults - The traits or default values to use for the model.
1165
+ * @returns The new model instance.
1166
+ */
1167
+ create(...traitsAndDefaults: (FactoryTraitNames<TFactory> | CollectionCreateAttrs<TTemplate, TSchema>)[]): ModelInstance<TTemplate, TSchema, TSerializer>;
1168
+ /**
1169
+ * Create a list of models for the collection.
1170
+ * @param count - The number of models to create.
1171
+ * @param traitsAndDefaults - The traits or default values to use for the models.
1172
+ * @returns A list of model instances.
1173
+ */
1174
+ createList(count: number, ...traitsAndDefaults: (FactoryTraitNames<TFactory> | CollectionCreateAttrs<TTemplate, TSchema>)[]): ModelCollection<TTemplate, TSchema, TSerializer>;
1175
+ /**
1176
+ * Finds the first model matching the query or creates a new one.
1177
+ * @param query - The query to find the model by.
1178
+ * @param traitsAndDefaults - The traits or default values to use when creating a new model.
1179
+ * @returns The model instance.
1180
+ */
1181
+ findOrCreateBy(query: DbRecordInput<ModelAttrs<TTemplate, TSchema>>, ...traitsAndDefaults: (FactoryTraitNames<TFactory> | CollectionCreateAttrs<TTemplate, TSchema>)[]): ModelInstance<TTemplate, TSchema, TSerializer>;
1182
+ /**
1183
+ * Finds or creates a specific number of models matching the query.
1184
+ * @param count - The number of models to find or create.
1185
+ * @param query - The query to find the models by (object or predicate function).
1186
+ * @param traitsAndDefaults - The traits or default values to use when creating new models.
1187
+ * @returns A collection of models.
1188
+ */
1189
+ findManyOrCreateBy(count: number, query: DbRecordInput<ModelAttrs<TTemplate, TSchema>> | ((model: ModelInstance<TTemplate, TSchema, TSerializer>) => boolean), ...traitsAndDefaults: (FactoryTraitNames<TFactory> | CollectionCreateAttrs<TTemplate, TSchema>)[]): ModelCollection<TTemplate, TSchema, TSerializer>;
1190
+ /**
1191
+ * Load seeds for this collection.
1192
+ * If scenarioId is not provided, all seeds will be loaded (or 'default' if seeds is a function).
1193
+ * If scenarioId is provided, only that specific seed scenario will be loaded.
1194
+ * @param scenarioId - Optional scenario ID to load a specific seed
1195
+ * @throws {MirageError} If the specified scenarioId does not exist
1196
+ * @example
1197
+ * ```typescript
1198
+ * // Load all seeds
1199
+ * collection.loadSeeds();
1200
+ *
1201
+ * // Load specific scenario
1202
+ * collection.loadSeeds('userForm');
1203
+ * ```
1204
+ */
1205
+ loadSeeds(scenarioId?: string): Promise<void>;
1206
+ /**
1207
+ * Load fixtures for this collection.
1208
+ * Fixtures are static data records that will be inserted into the collection.
1209
+ * This method will insert all fixture records into the database.
1210
+ * @example
1211
+ * ```typescript
1212
+ * // Load all fixtures
1213
+ * await collection.loadFixtures();
1214
+ * ```
1215
+ */
1216
+ loadFixtures(): Promise<void>;
1217
+ }
1218
+
1219
+ /**
1220
+ * Schema class that manages database and collections
1221
+ * @template TCollections - The type map of collection names to their configurations
1222
+ * @template TConfig - The schema configuration type with identity manager and global serializer config
1223
+ */
1224
+ declare class Schema<TCollections extends SchemaCollections, TConfig extends SchemaConfig<any, any> = SchemaConfig<StringIdentityManager, undefined>> {
1225
+ readonly db: DbInstance<SchemaDbCollections<TCollections>>;
1226
+ readonly identityManager: TConfig extends SchemaConfig<infer TIdentityManager, any> ? TIdentityManager : StringIdentityManager;
1227
+ readonly logger?: Logger;
1228
+ private _collections;
1229
+ private _globalSerializerConfig?;
1230
+ constructor(collections: TCollections, config?: TConfig);
1231
+ /**
1232
+ * Get a schema collection by collection name
1233
+ * @param collectionName - The name of the collection
1234
+ * @returns The schema collection for the collection with proper typing
1235
+ */
1236
+ getCollection<K extends keyof TCollections>(collectionName: K): TCollections[K] extends CollectionConfig<infer TTemplate, infer TRelationships, infer TFactory, infer TSerializer, any> ? Collection<TCollections, TTemplate, TRelationships, TFactory, TSerializer> : never;
1237
+ /**
1238
+ * Load all seeds for all collections in the schema.
1239
+ * This will run all seed scenarios for each collection.
1240
+ * To load specific scenarios, use collection.loadSeeds(scenarioId) on individual collections.
1241
+ * @example
1242
+ * ```typescript
1243
+ * // Load all seeds for all collections
1244
+ * await schema.loadSeeds();
1245
+ *
1246
+ * // Or load specific scenario for a single collection
1247
+ * await schema.users.loadSeeds('development');
1248
+ * ```
1249
+ */
1250
+ loadSeeds(): Promise<void>;
1251
+ /**
1252
+ * Load all fixtures for all collections in the schema.
1253
+ * This will insert all fixture records into each collection's database.
1254
+ * @example
1255
+ * ```typescript
1256
+ * // Load all fixtures for all collections
1257
+ * await schema.loadFixtures();
1258
+ * ```
1259
+ */
1260
+ loadFixtures(): Promise<void>;
1261
+ /**
1262
+ * Register collections from the configuration
1263
+ * @param collections - Collection configurations to register
1264
+ */
1265
+ private _registerCollections;
1266
+ /**
1267
+ * Validate that all inverse relationships are correctly defined
1268
+ * This checks that explicit inverse relationships exist and point back correctly
1269
+ * @param collections - The schema collections to validate
1270
+ * @private
1271
+ */
1272
+ private _validateInverseRelationships;
1273
+ /**
1274
+ * Merge global serializer config with collection-specific config
1275
+ * Collection config values override global config values
1276
+ * @param _template - The model template (used for type inference only)
1277
+ * @param collectionConfig - Collection-specific serializer config
1278
+ * @returns Merged serializer config or undefined if both are undefined
1279
+ */
1280
+ private _mergeConfigs;
1281
+ }
1282
+ /**
1283
+ * Type for a complete schema instance with collections
1284
+ * Provides both string-based property access and symbol-based relationship resolution
1285
+ */
1286
+ type SchemaInstance<TCollections extends SchemaCollections, TConfig extends SchemaConfig<any, any> = SchemaConfig<StringIdentityManager, undefined>> = Schema<TCollections, TConfig> & SchemaCollectionAccessors<TCollections>;
1287
+
1288
+ /**
1289
+ * Base collection class with query functionality.
1290
+ * @template TSchema - The schema collections type for enhanced type inference
1291
+ * @template TTemplate - The model template type (most important for users)
1292
+ * @template TRelationships - The raw relationships configuration for this collection (inferred from config)
1293
+ * @template TFactory - The factory type (inferred from config)
1294
+ * @template TSerializer - The serializer type (inferred from config)
1295
+ */
1296
+ declare abstract class BaseCollection<TSchema extends SchemaCollections = SchemaCollections, TTemplate extends ModelTemplate = ModelTemplate, TRelationships extends ModelRelationships = {}, TFactory extends Factory<TTemplate, TSchema, ModelTraits<TSchema, TTemplate>> | undefined = undefined, TSerializer = undefined> {
1297
+ readonly modelName: string;
1298
+ readonly collectionName: string;
1299
+ protected readonly Model: ModelClass<TTemplate, TSchema, TSerializer>;
1300
+ protected readonly _template: TTemplate;
1301
+ protected readonly _schema: SchemaInstance<TSchema>;
1302
+ protected readonly _dbCollection: DbCollection<ModelAttrs<TTemplate, TSchema>>;
1303
+ protected readonly _identityManager: IdentityManager<ModelAttrs<TTemplate, TSchema>['id']>;
1304
+ protected readonly _logger?: Logger;
1305
+ protected readonly _factory?: TFactory;
1306
+ protected readonly _relationships?: TRelationships;
1307
+ protected readonly _serializer?: TSerializer;
1308
+ protected readonly _seeds?: Seeds<TSchema>;
1309
+ protected readonly _fixtures?: FixtureConfig<TTemplate, TRelationships>;
1310
+ constructor(schema: SchemaInstance<TSchema>, config: {
1311
+ factory?: TFactory;
1312
+ identityManager?: IdentityManager<ModelId<TTemplate>>;
1313
+ model: TTemplate;
1314
+ relationships?: TRelationships;
1315
+ serializer?: TSerializer;
1316
+ seeds?: Seeds<TSchema>;
1317
+ fixtures?: FixtureConfig<TTemplate, TRelationships>;
1318
+ });
1319
+ /**
1320
+ * Get the collection relationships.
1321
+ * @returns The collection relationships configuration.
1322
+ */
1323
+ get relationships(): TRelationships | undefined;
1324
+ /**
1325
+ * Get the serializer for the collection.
1326
+ * @returns The collection serializer instance.
1327
+ */
1328
+ get serializer(): TSerializer | undefined;
1329
+ /**
1330
+ * Get a model by index.
1331
+ * @param index - The index of the model to get.
1332
+ * @returns The model instance or undefined if not found.
1333
+ */
1334
+ at(index: number): ModelInstance<TTemplate, TSchema, TSerializer> | undefined;
1335
+ /**
1336
+ * Returns all model instances in the collection.
1337
+ * @returns All model instances in the collection.
1338
+ */
1339
+ all(): ModelCollection<TTemplate, TSchema, TSerializer>;
1340
+ /**
1341
+ * Returns the first model in the collection.
1342
+ * @returns The first model in the collection or null if the collection is empty.
1343
+ */
1344
+ first(): ModelInstance<TTemplate, TSchema, TSerializer> | null;
1345
+ /**
1346
+ * Returns the last model in the collection.
1347
+ * @returns The last model in the collection or null if the collection is empty.
1348
+ */
1349
+ last(): ModelInstance<TTemplate, TSchema, TSerializer> | null;
1350
+ /**
1351
+ * Finds a model by ID, predicate object, or query options.
1352
+ * @param input - The ID, predicate object, or query options to find by.
1353
+ * @returns The model instance or null if not found.
1354
+ * @example
1355
+ * ```typescript
1356
+ * // Find by ID
1357
+ * collection.find('1');
1358
+ *
1359
+ * // Find by predicate object
1360
+ * collection.find({ email: 'user@example.com' });
1361
+ *
1362
+ * // Find with query options
1363
+ * collection.find({ where: { age: { gte: 18 } }, orderBy: { name: 'asc' } });
1364
+ * ```
1365
+ */
1366
+ find(input: ModelAttrs<TTemplate, TSchema>['id'] | DbRecordInput<ModelAttrs<TTemplate, TSchema>> | QueryOptions<ModelAttrs<TTemplate, TSchema>>): ModelInstance<TTemplate, TSchema, TSerializer> | null;
1367
+ /**
1368
+ * Finds multiple models by IDs, predicate object, or query options.
1369
+ * @param input - The array of IDs, predicate object, or query options to find by.
1370
+ * @returns A collection of matching model instances.
1371
+ * @example
1372
+ * ```typescript
1373
+ * // Find by IDs
1374
+ * collection.findMany(['1', '2', '3']);
1375
+ *
1376
+ * // Find by predicate object
1377
+ * collection.findMany({ status: 'active' });
1378
+ *
1379
+ * // Find with query options
1380
+ * collection.findMany({
1381
+ * where: { age: { gte: 18 } },
1382
+ * orderBy: { name: 'asc' },
1383
+ * limit: 10
1384
+ * });
1385
+ *
1386
+ * // Find with callback where clause
1387
+ * collection.findMany({
1388
+ * where: (model) => model.age >= 18 && model.status === 'active'
1389
+ * });
1390
+ * ```
1391
+ */
1392
+ findMany(input: ModelAttrs<TTemplate, TSchema>['id'][] | DbRecordInput<ModelAttrs<TTemplate, TSchema>> | QueryOptions<ModelAttrs<TTemplate, TSchema>>): ModelCollection<TTemplate, TSchema, TSerializer>;
1393
+ /**
1394
+ * Deletes a model from the collection.
1395
+ * @param id - The id of the model to delete.
1396
+ */
1397
+ delete(id: ModelAttrs<TTemplate, TSchema>['id']): void;
1398
+ /**
1399
+ * Deletes multiple models by IDs, predicate object, or query options.
1400
+ * @param input - The array of IDs, predicate object, or query options to delete by.
1401
+ * @returns The number of records that were deleted.
1402
+ * @example
1403
+ * ```typescript
1404
+ * // Delete by IDs
1405
+ * collection.deleteMany(['1', '2', '3']);
1406
+ *
1407
+ * // Delete by predicate object
1408
+ * collection.deleteMany({ status: 'inactive' });
1409
+ *
1410
+ * // Delete with query options
1411
+ * collection.deleteMany({
1412
+ * where: { age: { lt: 18 } },
1413
+ * limit: 10
1414
+ * });
1415
+ * ```
1416
+ */
1417
+ deleteMany(input: ModelAttrs<TTemplate, TSchema>['id'][] | DbRecordInput<ModelAttrs<TTemplate, TSchema>> | QueryOptions<ModelAttrs<TTemplate, TSchema>>): number;
1418
+ /**
1419
+ * Converts QueryOptions with a callback where clause to work with models instead of raw records.
1420
+ * @param options - The query options with a callback where clause
1421
+ * @returns Query options with converted where clause
1422
+ */
1423
+ private _convertQueryOptionsCallback;
1424
+ /**
1425
+ * Helper to create a model instance from a database record.
1426
+ * @param record - The database record to create the model from (must have ID).
1427
+ * @returns The model instance.
1428
+ */
1429
+ protected _createModelFromRecord(record: ModelAttrs<TTemplate, TSchema>): ModelInstance<TTemplate, TSchema, TSerializer>;
1430
+ /**
1431
+ * Initialize and create the database collection if needed
1432
+ * @param identityManager - The identity manager to use for the collection
1433
+ * @returns The database collection instance
1434
+ * @private
1435
+ */
1436
+ private _initializeDbCollection;
1437
+ }
1438
+
1439
+ /**
1440
+ * A fluent builder for creating schema collection configurations.
1441
+ *
1442
+ * The CollectionBuilder provides a type-safe way to construct CollectionConfig instances
1443
+ * with configurable model template, factory, relationships, serializer, and identity manager. It follows
1444
+ * the builder pattern, allowing method chaining to progressively configure the collection.
1445
+ * @template TTemplate - The model template type
1446
+ * @template TRelationships - The model relationships configuration
1447
+ * @template TFactory - The factory type
1448
+ * @template TIdentityManager - The identity manager type
1449
+ * @example
1450
+ * ```typescript
1451
+ * const userCollection = collection(UserModel)
1452
+ * .relationships({
1453
+ * posts: associations.hasMany(PostModel),
1454
+ * })
1455
+ * .factory(userFactory)
1456
+ * .identityManager(userIdentityManager)
1457
+ * .create();
1458
+ * ```
1459
+ */
1460
+ declare class CollectionBuilder<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = {}, TFactory extends Factory<TTemplate, TSchema, ModelTraits<TSchema, TTemplate>> | undefined = undefined, TIdentityManager extends IdentityManager = StringIdentityManager, TSerializer = undefined> {
1461
+ private _template?;
1462
+ private _factory?;
1463
+ private _relationships?;
1464
+ private _identityManager?;
1465
+ private _serializerConfig?;
1466
+ private _serializerInstance?;
1467
+ private _seeds?;
1468
+ private _fixtures?;
1469
+ /**
1470
+ * Creates a new CollectionBuilder instance.
1471
+ * @private
1472
+ */
1473
+ constructor();
1474
+ /**
1475
+ * Sets the model template for this collection.
1476
+ *
1477
+ * The template defines the model type, and collection name
1478
+ * for this collection configuration.
1479
+ * @template T - The model template type
1480
+ * @param template - The model template instance
1481
+ * @returns A new CollectionBuilder instance with the specified template
1482
+ * @example
1483
+ * ```typescript
1484
+ * const builder = collection.model(userTemplate);
1485
+ * ```
1486
+ */
1487
+ model<T extends ModelTemplate>(template: T): CollectionBuilder<T, TSchema, TRelationships, TFactory extends undefined ? undefined : Factory<T, TSchema, ModelTraits<TSchema, T>>, TIdentityManager, TSerializer>;
1488
+ /**
1489
+ * Sets the factory for creating model instances.
1490
+ *
1491
+ * The factory provides default attributes and traits for creating new model instances
1492
+ * in this collection.
1493
+ * @template F - The factory type
1494
+ * @param factory - The factory instance
1495
+ * @returns A new CollectionBuilder instance with the specified factory
1496
+ * @example
1497
+ * ```typescript
1498
+ * const builder = collection(UserModel).factory(userFactory);
1499
+ * ```
1500
+ */
1501
+ factory<F extends Factory<any, any, any>>(factory: F): CollectionBuilder<TTemplate, TSchema, TRelationships, F, TIdentityManager, TSerializer>;
1502
+ /**
1503
+ * Sets the relationships configuration for this collection.
1504
+ *
1505
+ * Relationships define how this model relates to other models in the schema,
1506
+ * including belongsTo and hasMany associations.
1507
+ * @template R - The relationships type
1508
+ * @param relationships - The relationships configuration object
1509
+ * @returns A new CollectionBuilder instance with the specified relationships
1510
+ * @example
1511
+ * ```typescript
1512
+ * const builder = collection(UserModel)
1513
+ * .relationships({
1514
+ * posts: associations.hasMany(PostModel),
1515
+ * profile: associations.belongsTo(profileTemplate),
1516
+ * });
1517
+ * ```
1518
+ */
1519
+ relationships<R extends ModelRelationships>(relationships: R): CollectionBuilder<TTemplate, TSchema, R, TFactory, TIdentityManager, TSerializer>;
1520
+ /**
1521
+ * Sets the serializer configuration or instance for this collection.
1522
+ *
1523
+ * Accepts either a configuration object (attrs, root, embed, include) or a custom
1524
+ * serializer instance. The config will be merged with global schema config if present.
1525
+ * @param configOrSerializer - The serializer configuration object or instance
1526
+ * @returns A new CollectionBuilder instance with the specified serializer
1527
+ * @example
1528
+ * ```typescript
1529
+ * // With config
1530
+ * const builder = collection()
1531
+ * .model(UserModel)
1532
+ * .serializer({ attrs: ['id', 'name'], root: true });
1533
+ *
1534
+ * // With custom serializer instance
1535
+ * const builder = collection()
1536
+ * .model(UserModel)
1537
+ * .serializer(new CustomUserSerializer(userModel));
1538
+ * ```
1539
+ */
1540
+ serializer(configOrSerializer: SerializerOptions<TTemplate> | any): CollectionBuilder<TTemplate, TSchema, TRelationships, TFactory, TIdentityManager, any>;
1541
+ /**
1542
+ * Sets the identity manager for this collection.
1543
+ *
1544
+ * The identity manager handles ID generation and management for model instances
1545
+ * in this collection. If not specified, the schema's global identity manager will be used.
1546
+ * @template I - The identity manager type
1547
+ * @param identityManager - The identity manager instance
1548
+ * @returns A new CollectionBuilder instance with the specified identity manager
1549
+ * @example
1550
+ * ```typescript
1551
+ * const builder = collection
1552
+ * .model(UserModel)
1553
+ * .identityManager(new StringIdentityManager());
1554
+ * ```
1555
+ */
1556
+ identityManager<I extends IdentityManager<any>>(identityManager: I): CollectionBuilder<TTemplate, TSchema, TRelationships, TFactory, I, TSerializer>;
1557
+ /**
1558
+ * Sets the seeds configuration for this collection.
1559
+ *
1560
+ * Seeds can be either a function or an object with named seed scenarios.
1561
+ * The function/methods receive the schema instance as a parameter.
1562
+ * @param seeds - A seed function or object with named seed scenarios
1563
+ * @returns A new CollectionBuilder instance with the specified seeds
1564
+ * @example
1565
+ * ```typescript
1566
+ * // With function
1567
+ * const builder = collection()
1568
+ * .model(UserModel)
1569
+ * .seeds((schema) => {
1570
+ * schema.users.create({ name: 'John' });
1571
+ * });
1572
+ *
1573
+ * // With named scenarios
1574
+ * const builder = collection()
1575
+ * .model(UserModel)
1576
+ * .seeds({
1577
+ * userForm: (schema) => {
1578
+ * schema.users.create({ name: 'John' });
1579
+ * },
1580
+ * userPosts: (schema) => {
1581
+ * const user = schema.users.create({ name: 'John' });
1582
+ * schema.posts.create({ title: 'Post 1', authorId: user.id });
1583
+ * },
1584
+ * });
1585
+ * ```
1586
+ */
1587
+ seeds(seeds: Seeds<TSchema>): CollectionBuilder<TTemplate, TSchema, TRelationships, TFactory, TIdentityManager, TSerializer>;
1588
+ /**
1589
+ * Sets the fixtures configuration for this collection.
1590
+ *
1591
+ * Fixtures are static data records that can be loaded into the collection.
1592
+ * @param records - Array of fixture records to load
1593
+ * @param options - Configuration options for loading fixtures
1594
+ * @param options.strategy - The strategy to use for loading fixtures (default: 'manual')
1595
+ * @returns A new CollectionBuilder instance with the specified fixtures
1596
+ * @example
1597
+ * ```typescript
1598
+ * // Manual loading (default)
1599
+ * const builder = collection()
1600
+ * .model(UserModel)
1601
+ * .fixtures([
1602
+ * { id: '1', name: 'John', email: 'john@example.com' },
1603
+ * { id: '2', name: 'Jane', email: 'jane@example.com' },
1604
+ * ]);
1605
+ *
1606
+ * // Auto-load fixtures during schema setup
1607
+ * const builder = collection()
1608
+ * .model(UserModel)
1609
+ * .fixtures(
1610
+ * [
1611
+ * { id: '1', name: 'John', email: 'john@example.com' },
1612
+ * { id: '2', name: 'Jane', email: 'jane@example.com' },
1613
+ * ],
1614
+ * { strategy: 'auto' }
1615
+ * );
1616
+ * ```
1617
+ */
1618
+ fixtures(records: FixtureAttrs<TTemplate, TRelationships>[], options?: {
1619
+ strategy?: FixtureLoadStrategy;
1620
+ }): CollectionBuilder<TTemplate, TSchema, TRelationships, TFactory, TIdentityManager, TSerializer>;
1621
+ /**
1622
+ * Creates the final schema collection configuration.
1623
+ * @returns The schema collection configuration
1624
+ */
1625
+ create(): CollectionConfig<TTemplate, TRelationships, TFactory, TSerializer, TSchema>;
1626
+ }
1627
+ /**
1628
+ * Creates a new CollectionBuilder instance for building collection configurations.
1629
+ * @template TSchema - The schema collections type (optional)
1630
+ * @returns A new CollectionBuilder instance ready for model specification
1631
+ * @example
1632
+ * ```typescript
1633
+ * // Schema-typed collection
1634
+ * const userCollection = collection<TestSchema>()
1635
+ * .model(UserModel)
1636
+ * .factory(userFactory)
1637
+ * .create();
1638
+ *
1639
+ * // Schema-less collection
1640
+ * const userCollection = collection()
1641
+ * .model(UserModel)
1642
+ * .create();
1643
+ * ```
1644
+ */
1645
+ declare function collection<TSchema extends SchemaCollections = SchemaCollections>(): CollectionBuilder<ModelTemplate, TSchema, {}, undefined, StringIdentityManager, undefined>;
1646
+
1647
+ /**
1648
+ * A fluent builder for creating schema instances.
1649
+ *
1650
+ * The SchemaBuilder provides a type-safe way to construct Schema instances with
1651
+ * configurable collections, identity manager, and global serializer. It follows the builder
1652
+ * pattern, allowing method chaining to progressively configure the schema.
1653
+ * @template TCollections - The schema collections configuration type
1654
+ * @template TIdentityManager - The global identity manager type
1655
+ * @template TGlobalConfig - The global serializer configuration type
1656
+ * @example
1657
+ * ```typescript
1658
+ * const appSchema = schema()
1659
+ * .collections({
1660
+ * users: userCollection,
1661
+ * posts: postCollection,
1662
+ * })
1663
+ * .serializer({ root: true })
1664
+ * .identityManager(appIdentityManager)
1665
+ * .setup();
1666
+ * ```
1667
+ */
1668
+ declare class SchemaBuilder<TCollections extends SchemaCollections = SchemaCollections, TIdentityManager extends IdentityManager<any> = StringIdentityManager, TGlobalConfig extends StructuralSerializerOptions | undefined = undefined> {
1669
+ private _collections?;
1670
+ private _identityManager?;
1671
+ private _globalSerializerConfig?;
1672
+ private _loggingConfig?;
1673
+ /**
1674
+ * Creates a new SchemaBuilder instance.
1675
+ * @private
1676
+ */
1677
+ constructor();
1678
+ /**
1679
+ * Sets the collections configuration for this schema.
1680
+ *
1681
+ * Collections define the models, factories, relationships, and other configuration
1682
+ * for each collection in the schema. Each collection is keyed by its collection name.
1683
+ * @template C - The collections configuration type
1684
+ * @param collections - The collections configuration object
1685
+ * @returns A new SchemaBuilder instance with the specified collections
1686
+ * @example
1687
+ * ```typescript
1688
+ * const builder = schema().collections({
1689
+ * users: userCollection,
1690
+ * posts: postCollection,
1691
+ * comments: commentCollection,
1692
+ * });
1693
+ * ```
1694
+ */
1695
+ collections<C extends SchemaCollections>(collections: C): SchemaBuilder<C, TIdentityManager, TGlobalConfig>;
1696
+ /**
1697
+ * Sets the global identity manager for this schema.
1698
+ *
1699
+ * The identity manager handles ID generation and management for model instances
1700
+ * across all collections in the schema. Individual collections can override this
1701
+ * with their own identity managers.
1702
+ * @template I - The identity manager type
1703
+ * @param identityManager - The identity manager instance
1704
+ * @returns A new SchemaBuilder instance with the specified identity manager
1705
+ * @example
1706
+ * ```typescript
1707
+ * const builder = schema()
1708
+ * .collections({ users: userCollection })
1709
+ * .identityManager(new StringIdentityManager());
1710
+ * ```
1711
+ */
1712
+ identityManager<I extends IdentityManager<any>>(identityManager: I): SchemaBuilder<TCollections, I, TGlobalConfig>;
1713
+ /**
1714
+ * Sets the global serializer configuration for this schema.
1715
+ *
1716
+ * The global serializer config defines structural serialization options (root, embed)
1717
+ * that apply to all collections by default. Individual collections can override
1718
+ * these settings or provide model-specific configuration (attrs, include).
1719
+ * @template TConfig - The global serializer configuration type
1720
+ * @param config - The global serializer configuration (only root and embed)
1721
+ * @returns A new SchemaBuilder instance with the specified global serializer config
1722
+ * @example
1723
+ * ```typescript
1724
+ * const builder = schema()
1725
+ * .serializer({ root: true, embed: false })
1726
+ * .collections({ users: userCollection });
1727
+ * ```
1728
+ */
1729
+ serializer<TConfig extends StructuralSerializerOptions>(config: TConfig): SchemaBuilder<TCollections, TIdentityManager, TConfig>;
1730
+ /**
1731
+ * Sets the logging configuration for this schema.
1732
+ *
1733
+ * The logging config enables debug output for database operations, validations,
1734
+ * and other schema behavior. This is useful for debugging test setup and understanding
1735
+ * how the ORM is behaving.
1736
+ * @param config - The logging configuration (enabled, level, prefix)
1737
+ * @returns A new SchemaBuilder instance with the specified logging config
1738
+ * @example
1739
+ * ```typescript
1740
+ * const builder = schema()
1741
+ * .logging({ enabled: true, level: 'debug' })
1742
+ * .collections({ users: userCollection });
1743
+ * ```
1744
+ */
1745
+ logging(config: LoggerConfig): SchemaBuilder<TCollections, TIdentityManager, TGlobalConfig>;
1746
+ /**
1747
+ * Sets up the final Schema instance with all configured options.
1748
+ *
1749
+ * This method produces the complete schema instance that can be used throughout
1750
+ * your application. Collections must be set before calling setup().
1751
+ * @returns The configured Schema instance with collection accessors
1752
+ * @throws Error if no collections have been configured
1753
+ * @example
1754
+ * ```typescript
1755
+ * const appSchema = schema()
1756
+ * .collections({
1757
+ * users: userCollection,
1758
+ * posts: postCollection,
1759
+ * })
1760
+ * .serializer({ root: true })
1761
+ * .identityManager(appIdentityManager)
1762
+ * .setup();
1763
+ *
1764
+ * // Use the schema
1765
+ * const userCollection = appSchema.getCollection('users');
1766
+ * const user = appSchema.users.create({ name: 'John' });
1767
+ * ```
1768
+ */
1769
+ setup(): SchemaInstance<TCollections, SchemaConfig<TIdentityManager, TGlobalConfig>>;
1770
+ }
1771
+ /**
1772
+ * Creates a new SchemaBuilder instance for building schema configurations.
1773
+ *
1774
+ * This is the main entry point for creating schemas in the builder-based API.
1775
+ * The returned SchemaBuilder can be configured with collections and identity manager
1776
+ * before setting up the final schema instance.
1777
+ * @returns A new SchemaBuilder instance ready for configuration
1778
+ * @example
1779
+ * ```typescript
1780
+ * // Basic schema creation
1781
+ * const appSchema = schema()
1782
+ * .collections({
1783
+ * users: userCollection,
1784
+ * })
1785
+ * .setup();
1786
+ *
1787
+ * // Full schema configuration
1788
+ * const appSchema = schema()
1789
+ * .collections({
1790
+ * users: userCollection,
1791
+ * posts: postCollection,
1792
+ * })
1793
+ * .identityManager(new StringIdentityManager())
1794
+ * .setup();
1795
+ * ```
1796
+ * @see {@link SchemaBuilder} for available configuration methods
1797
+ */
1798
+ declare function schema(): SchemaBuilder;
1799
+
1800
+ type FactoryAfterCreateHook<TSchema extends SchemaCollections = SchemaCollections, TTemplate extends ModelTemplate = ModelTemplate> = (model: ModelInstance<TTemplate, TSchema>, schema: SchemaInstance<TSchema>) => void;
1801
+ type TraitDefinition<TSchema extends SchemaCollections = SchemaCollections, TTemplate extends ModelTemplate = ModelTemplate> = Partial<FactoryAttrs<TTemplate>> & Partial<FactoryAssociations<TTemplate, TSchema>> & {
1802
+ afterCreate?: FactoryAfterCreateHook<TSchema, TTemplate>;
1803
+ };
1804
+ type ModelTraits<TSchema extends SchemaCollections = SchemaCollections, TTemplate extends ModelTemplate = ModelTemplate> = Record<string, TraitDefinition<TSchema, TTemplate>>;
1805
+ type TraitName<TTraits> = TTraits extends Record<string, any> ? Extract<keyof TTraits, string> : never;
1806
+ type FactoryAttrs<TTemplate extends ModelTemplate> = {
1807
+ [K in keyof ModelOnlyAttrs<TTemplate>]?: ModelOnlyAttrs<TTemplate>[K] | ((this: ModelOnlyAttrs<TTemplate>, modelId: NonNullable<ModelAttrs<TTemplate>['id']>) => InferModelAttrs<TTemplate>[K]);
1808
+ };
1809
+ type FactoryTraitNames<TFactory> = TFactory extends {
1810
+ traits: infer TTraits;
1811
+ } ? TTraits extends Record<string, any> ? Extract<keyof TTraits, string> : never : never;
1812
+
1813
+ /**
1814
+ * Factory that builds model attributes with optional schema support.
1815
+ * @template TTemplate - The model template (inferred from constructor)
1816
+ * @template TSchema - The schema collections type (never = sch)
1817
+ * @template TTraits - The factory traits (inferred from constructor)
1818
+ */
1819
+ declare class Factory<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TTraits extends ModelTraits<TSchema, TTemplate> = {}> {
1820
+ readonly attributes: FactoryAttrs<TTemplate>;
1821
+ readonly traits: TTraits;
1822
+ readonly associations?: FactoryAssociations<TTemplate, TSchema>;
1823
+ readonly afterCreate?: FactoryAfterCreateHook<TSchema, TTemplate>;
1824
+ private readonly _template;
1825
+ private readonly _associationsManager;
1826
+ constructor(template: TTemplate, attributes: FactoryAttrs<TTemplate>, traits?: TTraits, associations?: FactoryAssociations<TTemplate, TSchema>, afterCreate?: FactoryAfterCreateHook<TSchema, TTemplate>);
1827
+ /**
1828
+ * Get the model template
1829
+ * @returns The model template
1830
+ */
1831
+ get template(): TTemplate;
1832
+ /**
1833
+ * Build a model with the given model ID and trait names or default values.
1834
+ * @param modelId - The ID of the model to build.
1835
+ * @param traitsAndDefaults - The names of the traits to apply or default values for attributes.
1836
+ * @returns The built model.
1837
+ */
1838
+ build(modelId: ModelId<TTemplate>, ...traitsAndDefaults: (TraitName<TTraits> | PartialModelAttrs<TTemplate, TSchema>)[]): ModelAttrs<TTemplate, TSchema>;
1839
+ /**
1840
+ * Process associations and return relationship values
1841
+ * This runs with schema context and creates/links related models
1842
+ * @param schema - The schema instance
1843
+ * @param skipKeys - Optional list of relationship keys to skip (e.g., if user provided them)
1844
+ * @param traitsAndDefaults - Optional trait names to include trait associations
1845
+ * @returns A record of relationship values
1846
+ */
1847
+ processAssociations(schema: SchemaInstance<TSchema>, skipKeys?: string[], traitsAndDefaults?: (TraitName<TTraits> | PartialModelAttrs<TTemplate, TSchema>)[]): Record<string, ModelInstance<any, TSchema> | ModelCollection<any, TSchema>>;
1848
+ /**
1849
+ * Process the afterCreate hook and the trait hooks.
1850
+ * This method is intended to be called internally by schema collections.
1851
+ * @param schema - The schema instance.
1852
+ * @param model - The model to process.
1853
+ * @param traitsAndDefaults - The traits and defaults that were applied.
1854
+ * @returns The processed model.
1855
+ */
1856
+ processAfterCreateHooks(schema: SchemaInstance<TSchema>, model: ModelInstance<TTemplate, TSchema>, ...traitsAndDefaults: (TraitName<TTraits> | PartialModelAttrs<TTemplate, TSchema>)[]): ModelInstance<TTemplate, TSchema>;
1857
+ private _processAttributes;
1858
+ private _buildWithTraits;
1859
+ /**
1860
+ * Check if a value is an association object
1861
+ * @param value - The value to check
1862
+ * @returns True if the value is an association
1863
+ */
1864
+ private _isAssociation;
1865
+ /**
1866
+ * Extract associations from traits
1867
+ * @param traitsAndDefaults - The trait names to extract associations from
1868
+ * @returns The merged associations from all traits
1869
+ */
1870
+ private _getTraitAssociations;
1871
+ private _mergeAttributes;
1872
+ private _sortAttrs;
1873
+ }
1874
+
1875
+ /**
1876
+ * Builder class for creating factories with fluent API
1877
+ * @template TTemplate - The model template
1878
+ * @template TSchema - The schema collections type
1879
+ * @template TTraits - The traits type
1880
+ */
1881
+ declare class FactoryBuilder<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TTraits extends ModelTraits<TSchema, TTemplate> = {}> {
1882
+ protected _template?: TTemplate;
1883
+ protected _attributes: FactoryAttrs<TTemplate>;
1884
+ protected _traits: TTraits;
1885
+ protected _associations?: FactoryAssociations<TTemplate, TSchema>;
1886
+ protected _afterCreate?: FactoryAfterCreateHook<TSchema, TTemplate>;
1887
+ constructor();
1888
+ /**
1889
+ * Set the model template for the factory
1890
+ * @template T - The model template type
1891
+ * @param template - The model template
1892
+ * @returns A new builder instance with the specified template
1893
+ */
1894
+ model<T extends ModelTemplate>(template: T): FactoryBuilder<T, TSchema, {}>;
1895
+ /**
1896
+ * Set the attributes for the factory
1897
+ * @param attributes - The factory attributes
1898
+ * @returns The builder instance for chaining
1899
+ */
1900
+ attrs(attributes: FactoryAttrs<TTemplate>): this;
1901
+ /**
1902
+ * Add traits to the factory
1903
+ * @param traits - The traits to add
1904
+ * @returns A new builder instance with the added traits
1905
+ */
1906
+ traits<T extends ModelTraits<TSchema, TTemplate>>(traits: T): FactoryBuilder<TTemplate, TSchema, TTraits & T>;
1907
+ /**
1908
+ * Set the afterCreate hook
1909
+ * @param hook - The afterCreate hook function
1910
+ * @returns The builder instance for chaining
1911
+ */
1912
+ afterCreate(hook: FactoryAfterCreateHook<TSchema, TTemplate>): this;
1913
+ /**
1914
+ * Set factory associations for automatic relationship creation
1915
+ * @param associations - The associations configuration
1916
+ * @returns The builder instance for chaining
1917
+ */
1918
+ associations(associations: FactoryAssociations<TTemplate, TSchema>): this;
1919
+ /**
1920
+ * Create a factory builder by extending an existing factory
1921
+ * @param originalFactory - The factory to extend
1922
+ * @returns A new factory builder based on the existing factory
1923
+ */
1924
+ extend<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TTraits extends ModelTraits<TSchema, TTemplate> = {}>(originalFactory: Factory<TTemplate, TSchema, TTraits>): FactoryBuilder<TTemplate, TSchema, TTraits>;
1925
+ /**
1926
+ * Build the final factory instance
1927
+ * @returns The factory instance
1928
+ */
1929
+ create(): Factory<TTemplate, TSchema, TTraits>;
1930
+ }
1931
+ /**
1932
+ * Create a factory builder with optional schema type
1933
+ * @template TSchema - The schema collections type (optional)
1934
+ * @returns Factory builder instance ready for model specification
1935
+ */
1936
+ declare function factory<TSchema extends SchemaCollections>(): FactoryBuilder<ModelTemplate, TSchema, {}>;
1937
+
1938
+ /**
1939
+ * Extract the collection config for a model from the schema
1940
+ * @template TSchema - The schema collections type
1941
+ * @template TModel - The model template
1942
+ * @internal
1943
+ */
1944
+ type CollectionConfigFor<TSchema extends SchemaCollections, TModel extends ModelTemplate> = TSchema[InferCollectionName<TModel>];
1945
+ /**
1946
+ * Extract the factory from a model's collection in the schema
1947
+ * @template TSchema - The schema collections type
1948
+ * @template TModel - The model template
1949
+ * @internal
1950
+ */
1951
+ type FactoryFor<TSchema extends SchemaCollections, TModel extends ModelTemplate> = CollectionConfigFor<TSchema, TModel> extends CollectionConfig<any, any, infer TFactory, any, any> ? TFactory : undefined;
1952
+ /**
1953
+ * Extract valid trait names for a model from the schema
1954
+ * @template TSchema - The schema collections type
1955
+ * @template TModel - The model template
1956
+ * @internal
1957
+ */
1958
+ type TraitNamesFor<TSchema extends SchemaCollections, TModel extends ModelTemplate> = FactoryTraitNames<FactoryFor<TSchema, TModel>>;
1959
+ /**
1960
+ * BelongsTo relationship - this model contains a foreign key to another model
1961
+ * Example: Post belongsTo User (Post has authorId pointing to User.id)
1962
+ * @template TTarget - The target model template this relationship points to
1963
+ * @template TForeign - The foreign key field name (defaults to "{targetModelName}Id")
1964
+ */
1965
+ type BelongsTo<TTarget extends ModelTemplate, TForeign extends string = `${InferModelName<TTarget>}Id`> = {
1966
+ foreignKey: TForeign;
1967
+ targetModel: TTarget;
1968
+ type: 'belongsTo';
1969
+ /**
1970
+ * The name of the inverse relationship on the target model.
1971
+ * - `undefined`: Auto-detect inverse relationship (default behavior)
1972
+ * - `string`: Explicit inverse relationship name
1973
+ * - `null`: No inverse relationship (disable synchronization)
1974
+ */
1975
+ inverse?: string | null;
1976
+ };
1977
+ /**
1978
+ * HasMany relationship - this model can have multiple related models
1979
+ * Example: User hasMany Posts (User has postIds array containing Post.id values)
1980
+ * @template TTarget - The target model template this relationship points to
1981
+ * @template TForeign - The foreign key array field name (defaults to "{targetModelName}Ids")
1982
+ */
1983
+ type HasMany<TTarget extends ModelTemplate, TForeign extends string = `${InferModelName<TTarget>}Ids`> = {
1984
+ foreignKey: TForeign;
1985
+ targetModel: TTarget;
1986
+ type: 'hasMany';
1987
+ /**
1988
+ * The name of the inverse relationship on the target model.
1989
+ * - `undefined`: Auto-detect inverse relationship (default behavior)
1990
+ * - `string`: Explicit inverse relationship name
1991
+ * - `null`: No inverse relationship (disable synchronization)
1992
+ */
1993
+ inverse?: string | null;
1994
+ };
1995
+ /**
1996
+ * All relationship types
1997
+ */
1998
+ type Relationships = BelongsTo<any, any> | HasMany<any, any>;
1999
+ /**
2000
+ * The type of factory association
2001
+ */
2002
+ type AssociationType = 'create' | 'createMany' | 'link' | 'linkMany';
2003
+ /**
2004
+ * Predicate function for filtering models in link/linkMany associations
2005
+ * @template TModel - The model type to filter
2006
+ */
2007
+ type AssociationQueryPredicate<TModel> = (model: TModel) => boolean;
2008
+ /**
2009
+ * Query for finding models - can be an attributes object or a predicate function
2010
+ * @template TModel - The model type to query
2011
+ */
2012
+ type AssociationQuery<TModel = any> = Partial<TModel> | AssociationQueryPredicate<TModel>;
2013
+ /**
2014
+ * Runtime storage for traits and defaults passed to factory associations.
2015
+ * Type validation happens at the factory level through typed builder functions.
2016
+ */
2017
+ type AssociationTraitsAndDefaults = Array<string | Record<string, any>>;
2018
+ /**
2019
+ * Type-safe traits and defaults for a specific model in a schema.
2020
+ * Validates trait names against the model's factory and ensures defaults match model attributes.
2021
+ * @template TSchema - The schema collections type
2022
+ * @template TModel - The model template
2023
+ */
2024
+ type TypedAssociationTraitsAndDefaults<TSchema extends SchemaCollections, TModel extends ModelTemplate> = Array<TraitNamesFor<TSchema, TModel> | Partial<InferModelAttrs<TModel>>>;
2025
+ /**
2026
+ * Base interface for all factory associations
2027
+ * @template TModel - The model template to associate
2028
+ */
2029
+ interface BaseAssociation<TModel extends ModelTemplate = ModelTemplate> {
2030
+ /** The type of association */
2031
+ type: AssociationType;
2032
+ /** The model template to create or link */
2033
+ model: TModel;
2034
+ /** Optional relationship name - can be inferred from the key in FactoryAssociations */
2035
+ relationshipName?: string;
2036
+ /** Traits and defaults to apply when creating the associated model */
2037
+ traitsAndDefaults?: AssociationTraitsAndDefaults;
2038
+ }
2039
+ /**
2040
+ * Association that always creates one new related model
2041
+ * @template TModel - The model template to create
2042
+ */
2043
+ interface CreateAssociation<TModel extends ModelTemplate = ModelTemplate> extends BaseAssociation<TModel> {
2044
+ type: 'create';
2045
+ }
2046
+ /**
2047
+ * Association that always creates N new related models
2048
+ * @template TModel - The model template to create
2049
+ */
2050
+ interface CreateManyAssociation<TModel extends ModelTemplate = ModelTemplate> extends BaseAssociation<TModel> {
2051
+ type: 'createMany';
2052
+ /** Number of models to create */
2053
+ count: number;
2054
+ }
2055
+ /**
2056
+ * Association that tries to find an existing model, or creates one if not found
2057
+ * @template TModel - The model template to link or create
2058
+ */
2059
+ interface LinkAssociation<TModel extends ModelTemplate = ModelTemplate> extends BaseAssociation<TModel> {
2060
+ type: 'link';
2061
+ /** Optional query to find existing models */
2062
+ query?: AssociationQuery;
2063
+ }
2064
+ /**
2065
+ * Association that tries to find N existing models, or creates more if needed
2066
+ * @template TModel - The model template to link or create
2067
+ */
2068
+ interface LinkManyAssociation<TModel extends ModelTemplate = ModelTemplate> extends BaseAssociation<TModel> {
2069
+ type: 'linkMany';
2070
+ /** Number of models to link */
2071
+ count: number;
2072
+ /** Optional query to find existing models */
2073
+ query?: AssociationQuery;
2074
+ }
2075
+ /**
2076
+ * Union of all factory association types
2077
+ * @template TModel - The model template
2078
+ */
2079
+ type Association<TModel extends ModelTemplate = ModelTemplate> = CreateAssociation<TModel> | CreateManyAssociation<TModel> | LinkAssociation<TModel> | LinkManyAssociation<TModel>;
2080
+ /**
2081
+ * Extract the target model template from a relationship
2082
+ * @template TRelationship - The relationship type (BelongsTo or HasMany)
2083
+ * @internal
2084
+ */
2085
+ type RelationshipTargetTemplate<TRelationship> = TRelationship extends {
2086
+ targetModel: infer TTarget;
2087
+ } ? TTarget extends ModelTemplate ? TTarget : never : never;
2088
+ /**
2089
+ * Map of relationship names to factory associations for a model.
2090
+ * Keys are constrained to actual relationship names defined for the model.
2091
+ * Values must be associations for the correct target model of each relationship.
2092
+ * @template TTemplate - The model template
2093
+ * @template TSchema - The schema collections type
2094
+ * @example
2095
+ * ```typescript
2096
+ * // Post has relationships: { author: BelongsTo<UserModel>, comments: HasMany<CommentModel> }
2097
+ * const associations: FactoryAssociations<typeof postModel, AppSchema> = {
2098
+ * author: associations.create(userModel), // ✓ Valid: author relationship exists
2099
+ * comments: associations.createMany(commentModel, 3), // ✓ Valid: comments relationship exists
2100
+ * tags: associations.link(tagModel) // ✗ Error: no 'tags' relationship
2101
+ * }
2102
+ * ```
2103
+ */
2104
+ type FactoryAssociations<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections> = RelationshipsByTemplate<TTemplate, TSchema> extends ModelRelationships ? {
2105
+ [K in keyof RelationshipsByTemplate<TTemplate, TSchema>]?: Association<RelationshipTargetTemplate<RelationshipsByTemplate<TTemplate, TSchema>[K]>>;
2106
+ } : {};
2107
+
2108
+ /**
2109
+ * Define a belongs-to relationship.
2110
+ * @param targetModel - The template of the model that is being related to.
2111
+ * @param opts - The options for the relationship.
2112
+ * @param opts.foreignKey - The foreign key of the relationship.
2113
+ * @param opts.inverse - The name of the inverse relationship on the target model, or null to disable.
2114
+ * @returns The relationship definition object.
2115
+ * @example
2116
+ * ```typescript
2117
+ * // Auto-detect inverse
2118
+ * author: belongsTo(userModel)
2119
+ *
2120
+ * // Explicit inverse
2121
+ * author: belongsTo(userModel, { inverse: 'authoredPosts' })
2122
+ *
2123
+ * // No inverse (no synchronization)
2124
+ * reviewer: belongsTo(userModel, { inverse: null })
2125
+ * ```
2126
+ */
2127
+ declare function belongsTo<TTarget extends ModelTemplate, const TOpts extends {
2128
+ foreignKey?: string;
2129
+ inverse?: string | null;
2130
+ } | undefined = undefined>(targetModel: TTarget, opts?: TOpts): BelongsTo<TTarget, TOpts extends {
2131
+ foreignKey: infer F extends string;
2132
+ } ? F : `${InferModelName<TTarget>}Id`>;
2133
+
2134
+ /**
2135
+ * Always create one new related model and link it (with schema type for trait validation)
2136
+ * @template TSchema - The schema collections type
2137
+ * @template TModel - The model template (inferred from model parameter)
2138
+ * @param model - Model template to create
2139
+ * @param traitsAndDefaults - Traits and/or defaults to apply (variadic) - trait names are validated against schema
2140
+ * @returns The create association
2141
+ */
2142
+ declare function create<TSchema extends SchemaCollections, TModel extends ModelTemplate>(model: TModel, ...traitsAndDefaults: TypedAssociationTraitsAndDefaults<TSchema, TModel>): CreateAssociation<TModel>;
2143
+ /**
2144
+ * Always create one new related model and link it (without schema type - traits not validated)
2145
+ * @template TModel - The model template (inferred from model parameter)
2146
+ * @param model - Model template to create
2147
+ * @param traitsAndDefaults - Traits and/or defaults to apply (variadic) - trait names are strings
2148
+ * @returns The create association
2149
+ */
2150
+ declare function create<TModel extends ModelTemplate>(model: TModel, ...traitsAndDefaults: AssociationTraitsAndDefaults): CreateAssociation<TModel>;
2151
+
2152
+ /**
2153
+ * Always create N new related models and link them (with schema type for trait validation)
2154
+ * @template TSchema - The schema collections type
2155
+ * @template TModel - The model template (inferred from model parameter)
2156
+ * @param model - Model template to create
2157
+ * @param count - Number of models to create
2158
+ * @param traitsAndDefaults - Traits and/or defaults to apply (variadic) - trait names are validated against schema
2159
+ * @returns The create many association
2160
+ */
2161
+ declare function createMany<TSchema extends SchemaCollections, TModel extends ModelTemplate>(model: TModel, count: number, ...traitsAndDefaults: TypedAssociationTraitsAndDefaults<TSchema, TModel>): CreateManyAssociation<TModel>;
2162
+ /**
2163
+ * Always create N new related models and link them (without schema type - traits not validated)
2164
+ * @template TModel - The model template (inferred from model parameter)
2165
+ * @param model - Model template to create
2166
+ * @param count - Number of models to create
2167
+ * @param traitsAndDefaults - Traits and/or defaults to apply (variadic) - trait names are strings
2168
+ * @returns The create many association
2169
+ */
2170
+ declare function createMany<TModel extends ModelTemplate>(model: TModel, count: number, ...traitsAndDefaults: AssociationTraitsAndDefaults): CreateManyAssociation<TModel>;
2171
+
2172
+ /**
2173
+ * Define a has-many relationship.
2174
+ * @param targetModel - The template of the model that is being related to.
2175
+ * @param opts - The options for the relationship.
2176
+ * @param opts.foreignKey - The foreign key of the relationship.
2177
+ * @param opts.inverse - The name of the inverse relationship on the target model, or null to disable.
2178
+ * @returns The relationship definition object.
2179
+ * @example
2180
+ * ```typescript
2181
+ * // Auto-detect inverse
2182
+ * posts: hasMany(postModel)
2183
+ *
2184
+ * // Explicit inverse
2185
+ * authoredPosts: hasMany(postModel, { inverse: 'author' })
2186
+ *
2187
+ * // No inverse (no synchronization)
2188
+ * archivedPosts: hasMany(postModel, { inverse: null })
2189
+ * ```
2190
+ */
2191
+ declare function hasMany<TTarget extends ModelTemplate, const TOpts extends {
2192
+ foreignKey?: string;
2193
+ inverse?: string | null;
2194
+ } | undefined = undefined>(targetModel: TTarget, opts?: TOpts): HasMany<TTarget, TOpts extends {
2195
+ foreignKey: infer F extends string;
2196
+ } ? F : `${InferModelName<TTarget>}Ids`>;
2197
+
2198
+ /**
2199
+ * Try to find existing model, else create one (with schema type for trait validation)
2200
+ * @template TSchema - The schema collections type
2201
+ * @template TModel - The model template (inferred from model parameter)
2202
+ * @param model - Model template to use
2203
+ * @param query - Optional query to filter models (attributes object or predicate function)
2204
+ * @param traitsAndDefaults - Traits and/or defaults to apply when creating (variadic) - trait names are validated against schema
2205
+ * @returns The link association
2206
+ */
2207
+ declare function link<TSchema extends SchemaCollections, TModel extends ModelTemplate>(model: TModel, query?: AssociationQuery<InferModelAttrs<TModel>>, ...traitsAndDefaults: TypedAssociationTraitsAndDefaults<TSchema, TModel>): LinkAssociation<TModel>;
2208
+ /**
2209
+ * Try to find existing model, else create one (without schema type - traits not validated)
2210
+ * @template TModel - The model template (inferred from model parameter)
2211
+ * @param model - Model template to use
2212
+ * @param query - Optional query to filter models (attributes object or predicate function)
2213
+ * @param traitsAndDefaults - Traits and/or defaults to apply when creating (variadic) - trait names are strings
2214
+ * @returns The link association
2215
+ */
2216
+ declare function link<TModel extends ModelTemplate>(model: TModel, query?: AssociationQuery<InferModelAttrs<TModel>>, ...traitsAndDefaults: AssociationTraitsAndDefaults): LinkAssociation<TModel>;
2217
+
2218
+ /**
2219
+ * Try to find N existing models, else create more as needed (with schema type for trait validation)
2220
+ * @template TSchema - The schema collections type
2221
+ * @template TModel - The model template (inferred from model parameter)
2222
+ * @param model - Model template to use
2223
+ * @param count - Number of models needed
2224
+ * @param query - Optional query to filter models (attributes object or predicate function)
2225
+ * @param traitsAndDefaults - Traits and/or defaults to apply when creating (variadic) - trait names are validated against schema
2226
+ * @returns The link many association
2227
+ */
2228
+ declare function linkMany<TSchema extends SchemaCollections, TModel extends ModelTemplate>(model: TModel, count: number, query?: AssociationQuery<InferModelAttrs<TModel>>, ...traitsAndDefaults: TypedAssociationTraitsAndDefaults<TSchema, TModel>): LinkManyAssociation<TModel>;
2229
+ /**
2230
+ * Try to find N existing models, else create more as needed (without schema type - traits not validated)
2231
+ * @template TModel - The model template (inferred from model parameter)
2232
+ * @param model - Model template to use
2233
+ * @param count - Number of models needed
2234
+ * @param query - Optional query to filter models (attributes object or predicate function)
2235
+ * @param traitsAndDefaults - Traits and/or defaults to apply when creating (variadic) - trait names are strings
2236
+ * @returns The link many association
2237
+ */
2238
+ declare function linkMany<TModel extends ModelTemplate>(model: TModel, count: number, query?: AssociationQuery<InferModelAttrs<TModel>>, ...traitsAndDefaults: AssociationTraitsAndDefaults): LinkManyAssociation<TModel>;
2239
+
2240
+ /**
2241
+ * Associations object with all helper functions:
2242
+ * - belongsTo, hasMany: for model relationship definitions
2243
+ * - create, createMany, link, linkMany: for factory associations
2244
+ */
2245
+ declare const associations: {
2246
+ readonly belongsTo: typeof belongsTo;
2247
+ readonly hasMany: typeof hasMany;
2248
+ readonly create: typeof create;
2249
+ readonly createMany: typeof createMany;
2250
+ readonly link: typeof link;
2251
+ readonly linkMany: typeof linkMany;
2252
+ };
2253
+
2254
+ /**
2255
+ * ModelRelationshipsManager - Handles all relationship operations
2256
+ * Separated from core model logic for better maintainability
2257
+ * @template TTemplate - The model template
2258
+ * @template TSchema - The schema collections type
2259
+ * @template TRelationships - The relationships configuration
2260
+ */
2261
+ declare class RelationshipsManager<TTemplate extends ModelTemplate, TSchema extends SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>> {
2262
+ isApplyingPendingUpdates: boolean;
2263
+ private _model;
2264
+ private _pendingRelationshipOperations;
2265
+ private _relationshipDefs?;
2266
+ private _inverseMap;
2267
+ private _schema;
2268
+ constructor(model: Model<TTemplate, TSchema>, schema: SchemaInstance<TSchema>, relationships?: TRelationships);
2269
+ /**
2270
+ * Getter for the relationship definitions
2271
+ * @returns The relationship definitions
2272
+ */
2273
+ get relationshipDefs(): RelationshipDefs<TRelationships> | undefined;
2274
+ /**
2275
+ * Getter for the schema
2276
+ * @returns The schema
2277
+ */
2278
+ get schema(): SchemaInstance<TSchema>;
2279
+ /**
2280
+ * Set pending relationship updates by analyzing changes
2281
+ * Handles both model instances and raw foreign key values
2282
+ * Should be called BEFORE updating model attributes so we can access old FKs
2283
+ * @param relationshipUpdates - Raw relationship values from attrs (can be models or FK values)
2284
+ */
2285
+ setPendingRelationshipUpdates(relationshipUpdates: Partial<RelatedModelAttrs<TSchema, TRelationships>>): void;
2286
+ /**
2287
+ * Apply inverse relationship updates for pending operations
2288
+ * Should be called AFTER saving the model (when FK changes are in the database)
2289
+ * Note: FK updates are already applied to the model by _processAttrs or link/unlink methods
2290
+ */
2291
+ applyPendingInverseUpdates(): void;
2292
+ /**
2293
+ * Link this model to another model via a relationship
2294
+ * Returns foreign key updates without mutating model state
2295
+ * @param relationshipName - The name of the relationship
2296
+ * @param targetModel - The model to link to (or null to unlink)
2297
+ * @returns FK updates to apply and inverse relationship updates
2298
+ */
2299
+ link<K extends RelationshipNames<TRelationships>>(relationshipName: K, targetModel: RelationshipTargetModel<TSchema, TRelationships, K>): RelationshipUpdateResult;
2300
+ /**
2301
+ * Unlink this model from another model via a relationship
2302
+ * Returns foreign key updates without mutating model state
2303
+ * @param relationshipName - The name of the relationship
2304
+ * @param targetModel - The specific model to unlink (optional for hasMany, unlinks all if not provided)
2305
+ * @returns FK updates to apply
2306
+ */
2307
+ unlink<K extends RelationshipNames<TRelationships>>(relationshipName: K, targetModel?: RelationshipTargetModel<TSchema, TRelationships, K>): RelationshipUpdateResult;
2308
+ /**
2309
+ * Get related model(s) for a relationship with proper typing
2310
+ * @param relationshipName - The relationship name
2311
+ * @returns The related model(s) or null/empty collection
2312
+ */
2313
+ related<K extends RelationshipNames<TRelationships>>(relationshipName: K): RelationshipTargetModel<TSchema, TRelationships, K> | null;
2314
+ /**
2315
+ * Get a relationship definition by name
2316
+ * @param relationshipName - The relationship name
2317
+ * @returns The relationship definition or undefined
2318
+ */
2319
+ private _getRelationshipDef;
2320
+ /**
2321
+ * Get model attributes with proper typing
2322
+ * @returns Model attributes
2323
+ */
2324
+ private _getModelAttrs;
2325
+ /**
2326
+ * Get foreign key value from model attrs
2327
+ * @param foreignKey - The foreign key to retrieve
2328
+ * @returns The foreign key value
2329
+ */
2330
+ private _getForeignKeyValue;
2331
+ /**
2332
+ * Extract a single ID from foreign key value (for belongsTo relationships)
2333
+ * @param foreignKeyValue - The foreign key value
2334
+ * @returns A single ID or null
2335
+ */
2336
+ private _extractSingleId;
2337
+ /**
2338
+ * Extract array of IDs from foreign key value
2339
+ * @param foreignKeyValue - The foreign key value
2340
+ * @returns Array of IDs
2341
+ */
2342
+ private _extractIdsArray;
2343
+ /**
2344
+ * Parse relationships configuration into internal relationship definitions
2345
+ * This includes finding inverse relationships for bidirectional updates
2346
+ * @param relationships - The relationships configuration from schema
2347
+ * @returns Parsed relationship definitions with inverse information
2348
+ */
2349
+ private _parseRelationshipDefs;
2350
+ /**
2351
+ * Update the inverse relationship on the target model
2352
+ * @param relationshipName - The name of the relationship being updated
2353
+ * @param targetModel - The target model to update
2354
+ * @param action - Whether to 'link' or 'unlink'
2355
+ */
2356
+ private _updateInverseRelationship;
2357
+ /**
2358
+ * Extract foreign key value from a relationship value (model/array/collection)
2359
+ * @param relationship - The relationship configuration
2360
+ * @param value - The relationship value
2361
+ * @returns The extracted foreign key value
2362
+ */
2363
+ private _extractForeignKeyFromValue;
2364
+ /**
2365
+ * Check if foreign key has a meaningful value
2366
+ * @param fk - The foreign key value to check
2367
+ * @returns True if the foreign key has a value
2368
+ */
2369
+ private _hasForeignKeyValue;
2370
+ /**
2371
+ * Check if foreign key has changed
2372
+ * @param currentFk - The current foreign key value
2373
+ * @param newFk - The new foreign key value
2374
+ * @returns True if the foreign keys are different
2375
+ */
2376
+ private _hasForeignKeyChanged;
2377
+ /**
2378
+ * Compare two arrays for equality
2379
+ * @param arr1 - First array
2380
+ * @param arr2 - Second array
2381
+ * @returns True if arrays are equal
2382
+ */
2383
+ private _arraysEqual;
2384
+ }
2385
+
2386
+ /**
2387
+ * Model class for managing model instances with relationships
2388
+ * @template TTemplate - The model template (most important for users)
2389
+ * @template TSchema - The schema collections type for enhanced type inference
2390
+ * @template TSerializer - The serializer type
2391
+ */
2392
+ declare class Model<TTemplate extends ModelTemplate = ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined> extends BaseModel<ModelAttrs<TTemplate, TSchema>, TSerializer> {
2393
+ readonly relationships?: RelationshipsByTemplate<TTemplate, TSchema>;
2394
+ protected _relationshipsManager?: RelationshipsManager<TTemplate, TSchema>;
2395
+ constructor(template: TTemplate, config: ModelConfig<TTemplate, TSchema, RelationshipsByTemplate<TTemplate, TSchema>, TSerializer>);
2396
+ /**
2397
+ * Define a model class with attribute accessors
2398
+ * @template TTemplate - The model template (most important for users)
2399
+ * @template TSchema - The schema collections type for enhanced type inference
2400
+ * @template TSerializer - The serializer type
2401
+ * @param template - The model template to define
2402
+ * @returns A model class that can be instantiated with 'new'
2403
+ */
2404
+ static define<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined>(template: TTemplate): ModelClass<TTemplate, TSchema, TSerializer>;
2405
+ /**
2406
+ * Save the model to the database and apply pending relationship updates
2407
+ * @returns The model with saved instance type
2408
+ */
2409
+ save(): this & ModelInstance<TTemplate, TSchema, TSerializer>;
2410
+ /**
2411
+ * Update the model attributes and save the model
2412
+ * @param attrs - The attributes to update
2413
+ * @returns The model with saved instance type
2414
+ */
2415
+ update(attrs: ModelUpdateAttrs<TTemplate, TSchema>): this & ModelInstance<TTemplate, TSchema, TSerializer>;
2416
+ /**
2417
+ * Reload the model from the database
2418
+ * @returns The model with saved instance type
2419
+ */
2420
+ reload(): this & ModelInstance<TTemplate, TSchema, TSerializer>;
2421
+ /**
2422
+ * Destroy the model from the database
2423
+ * @returns The model with new instance type
2424
+ */
2425
+ destroy(): this & NewModelInstance<TTemplate, TSchema, TSerializer>;
2426
+ /**
2427
+ * Link this model to another model via a relationship
2428
+ * @param relationshipName - The name of the relationship
2429
+ * @param targetModel - The model to link to (or null to unlink)
2430
+ * @returns This model instance for chaining
2431
+ */
2432
+ link<K extends RelationshipNames<RelationshipsByTemplate<TTemplate, TSchema>>>(relationshipName: K, targetModel: RelationshipTargetModel<TSchema, RelationshipsByTemplate<TTemplate, TSchema>, K>): this & ModelInstance<TTemplate, TSchema, TSerializer>;
2433
+ /**
2434
+ * Unlink this model from another model via a relationship
2435
+ * @param relationshipName - The name of the relationship
2436
+ * @param targetModel - The specific model to unlink (optional for hasMany, unlinks all if not provided)
2437
+ * @returns This model instance for chaining
2438
+ */
2439
+ unlink<K extends RelationshipNames<RelationshipsByTemplate<TTemplate, TSchema>>>(relationshipName: K, targetModel?: RelationshipTargetModel<TSchema, RelationshipsByTemplate<TTemplate, TSchema>, K>): this & ModelInstance<TTemplate, TSchema, TSerializer>;
2440
+ /**
2441
+ * Get related model(s) for a relationship with proper typing
2442
+ * @param relationshipName - The relationship name
2443
+ * @returns The related model(s) or null/empty collection
2444
+ */
2445
+ related<K extends RelationshipNames<RelationshipsByTemplate<TTemplate, TSchema>>>(relationshipName: K): RelationshipTargetModel<TSchema, RelationshipsByTemplate<TTemplate, TSchema>, K> | null;
2446
+ /**
2447
+ * Extract foreign key value from a relationship value
2448
+ * @param relationship - The relationship configuration
2449
+ * @param value - The value to extract the foreign key from
2450
+ * @returns The foreign key value
2451
+ */
2452
+ private static _extractForeignKey;
2453
+ /**
2454
+ * Separate attributes into model attributes and relationship updates
2455
+ * Extracts foreign keys from relationship model instances and initializes default values
2456
+ * @param attrs - The attributes to separate
2457
+ * @param relationships - The relationships configuration
2458
+ * @returns Object containing:
2459
+ * - regularAttrs: Regular attributes (may include explicit FK values)
2460
+ * - relationshipValues: Relationship values
2461
+ * - foreignKeys: Foreign keys (extracted from relationship models or defaults)
2462
+ */
2463
+ private static _separateAttrs;
2464
+ /**
2465
+ * Process constructor/update attributes before model initialization
2466
+ * Separates relationship model instances from regular attributes and extracts foreign keys
2467
+ * @param attrs - The attributes to process (can include both regular attrs and relationship instances)
2468
+ * @param relationships - The relationships configuration (optional)
2469
+ * @returns Object containing:
2470
+ * - modelAttrs: Regular attributes and foreign keys ready for the database
2471
+ * - relationshipUpdates: Relationship model instances to be linked after save
2472
+ * @example
2473
+ * // Input: { title: 'Post', author: authorModelInstance }
2474
+ * // Output: {
2475
+ * // modelAttrs: { title: 'Post', authorId: '1' },
2476
+ * // relationshipUpdates: { author: authorModelInstance }
2477
+ * // }
2478
+ */
2479
+ static _processAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>>(attrs: ModelCreateAttrs<TTemplate, TSchema, TRelationships> | ModelUpdateAttrs<TTemplate, TSchema, TRelationships> | Partial<ModelCreateAttrs<TTemplate, TSchema, TRelationships>> | Record<string, unknown>, relationships?: TRelationships): {
2480
+ modelAttrs: NewModelAttrs<ModelAttrs<TTemplate, TSchema>> | Partial<ModelAttrs<TTemplate, TSchema>>;
2481
+ relationshipUpdates: Partial<RelatedModelAttrs<TSchema, TRelationships>>;
2482
+ };
2483
+ /**
2484
+ * Initialize attribute accessors for all attributes except id
2485
+ */
2486
+ private _initAttributeAccessors;
2487
+ /**
2488
+ * Initialize foreign key attributes if they don't exist
2489
+ */
2490
+ private _initForeignKeys;
2491
+ /**
2492
+ * Initialize relationship accessors for all relationships
2493
+ */
2494
+ private _initRelationshipAccessors;
2495
+ }
2496
+
2497
+ /**
2498
+ * Model template interface with hidden type properties
2499
+ *
2500
+ * This interface uses only 2 generics for clean type signatures,
2501
+ * while storing additional type metadata in hidden properties (__attrs, __json).
2502
+ * These hidden properties exist only in TypeScript's type system with zero runtime cost.
2503
+ *
2504
+ * Note: __attrs and __json are NOT defined in the base interface to avoid type pollution
2505
+ * when creating intersections. They are added via intersection types in ModelBuilder.create()
2506
+ * @template TModelName - The string literal type for the model name
2507
+ * @template TCollectionName - The string literal type for the collection name
2508
+ */
2509
+ interface ModelTemplate<TModelName extends string = string, TCollectionName extends string = string> {
2510
+ readonly key: symbol;
2511
+ readonly modelName: TModelName;
2512
+ readonly collectionName: TCollectionName;
2513
+ }
2514
+ /**
2515
+ * Infer model attributes from template
2516
+ * Uses conditional type to properly extract __attrs from intersection types
2517
+ * @template T - The model template
2518
+ */
2519
+ type InferModelAttrs<T> = T extends {
2520
+ __attrs: infer TAttrs extends {
2521
+ id: any;
2522
+ };
2523
+ } ? TAttrs : never;
2524
+ /**
2525
+ * Infer model ID type from template
2526
+ * @template T - The model template
2527
+ */
2528
+ type ModelId<T> = InferModelAttrs<T>['id'];
2529
+ /**
2530
+ * Infer model name from template
2531
+ * @template T - The model template
2532
+ */
2533
+ type InferModelName<T> = T extends ModelTemplate<infer Name, any> ? Name : never;
2534
+ /**
2535
+ * Infer collection name from template
2536
+ * @template T - The model template
2537
+ */
2538
+ type InferCollectionName<T> = T extends ModelTemplate<any, infer Name> ? Name : never;
2539
+ /**
2540
+ * Infer serialized model type from template
2541
+ * Uses conditional type to properly extract from intersection types
2542
+ * @template T - The model template
2543
+ */
2544
+ type InferSerializedModel<T> = T extends {
2545
+ __json: {
2546
+ model: infer M;
2547
+ };
2548
+ } ? M : InferModelAttrs<T>;
2549
+ /**
2550
+ * Infer serialized collection type from template
2551
+ * Uses conditional type to properly extract from intersection types
2552
+ * @template T - The model template
2553
+ */
2554
+ type InferSerializedCollection<T> = T extends {
2555
+ __json: {
2556
+ collection: infer C;
2557
+ };
2558
+ } ? C : InferModelAttrs<T>[];
2559
+ /**
2560
+ * Model relationships configuration object
2561
+ * @example { posts: HasMany<PostTemplate>, author: BelongsTo<UserTemplate, 'authorId'> }
2562
+ */
2563
+ type ModelRelationships = Record<string, Relationships>;
2564
+ /**
2565
+ * Type for foreign key values - either a single ID or array of IDs
2566
+ */
2567
+ type ForeignKeyValue = string | number | string[] | number[] | null | undefined;
2568
+ /**
2569
+ * Result of a relationship operation (link/unlink)
2570
+ * Contains foreign key updates for the current model
2571
+ */
2572
+ interface RelationshipUpdateResult {
2573
+ /** Foreign key updates to apply to the current model */
2574
+ foreignKeyUpdates: Record<string, ForeignKeyValue>;
2575
+ }
2576
+ /**
2577
+ * Internal relationship definition with inverse relationship information
2578
+ * Used internally by Model to track bidirectional relationships
2579
+ * @template TRelationship - The specific relationship type
2580
+ */
2581
+ interface RelationshipDef<TRelationship extends Relationships = Relationships> {
2582
+ /** The original relationship configuration */
2583
+ relationship: TRelationship;
2584
+ /** The inverse relationship information, if it exists */
2585
+ inverse?: {
2586
+ /** The foreign key used by the inverse relationship */
2587
+ foreignKey: string;
2588
+ /** The name of the inverse relationship in the target model */
2589
+ relationshipName: string;
2590
+ /** The target model template that has the inverse relationship */
2591
+ targetModel: ModelTemplate;
2592
+ /** The type of the inverse relationship */
2593
+ type: 'belongsTo' | 'hasMany';
2594
+ };
2595
+ }
2596
+ /**
2597
+ * Relationship definitions for internal use by Model class
2598
+ * Maps relationship names to their definitions including inverse information
2599
+ * Preserves specific relationship types from the input relationships configuration
2600
+ * @template TRelationships - The model relationships configuration
2601
+ * @example
2602
+ * // Input: { posts: HasMany<PostTemplate>, author: BelongsTo<UserTemplate> }
2603
+ * // Output: {
2604
+ * // posts: RelationshipDef<HasMany<PostTemplate>>,
2605
+ * // author: RelationshipDef<BelongsTo<UserTemplate>>
2606
+ * // }
2607
+ */
2608
+ type RelationshipDefs<TRelationships extends ModelRelationships = ModelRelationships> = {
2609
+ [K in keyof TRelationships]: RelationshipDef<TRelationships[K]>;
2610
+ };
2611
+ /**
2612
+ * Extract relationship names from relationships type
2613
+ * @template TRelationships - The relationships type
2614
+ */
2615
+ type RelationshipNames<TRelationships extends ModelRelationships> = keyof TRelationships;
2616
+ /**
2617
+ * Extract the target model instance type for a specific relationship
2618
+ * @template TSchema - The schema collections type
2619
+ * @template TRelationships - The relationships type
2620
+ * @template K - The relationship name
2621
+ */
2622
+ type RelationshipTargetModel<TSchema extends SchemaCollections, TRelationships extends ModelRelationships, K extends keyof TRelationships = keyof TRelationships> = TRelationships[K] extends BelongsTo<infer TTarget, any> ? ModelInstance<TTarget, TSchema> | null : TRelationships[K] extends HasMany<infer TTarget, any> ? ModelCollection<TTarget, TSchema> | ModelInstance<TTarget, TSchema>[] | null : never;
2623
+ /**
2624
+ * Type for collection by template model
2625
+ * @template TSchema - The schema collections
2626
+ * @template TTemplate - The model template
2627
+ */
2628
+ type CollectionByTemplate<TSchema extends SchemaCollections, TTemplate extends ModelTemplate> = {
2629
+ [K in keyof TSchema]: TSchema[K] extends CollectionConfig<infer TModel, any, any, any, any> ? TModel extends TTemplate ? K : never : never;
2630
+ }[keyof TSchema];
2631
+ /**
2632
+ * Type for relationships by template model
2633
+ * @template TSchema - The schema collections
2634
+ * @template TTemplate - The model template
2635
+ */
2636
+ type RelationshipsByTemplate<TTemplate extends ModelTemplate, TSchema extends SchemaCollections> = TSchema[CollectionByTemplate<TSchema, TTemplate>] extends CollectionConfig<any, infer TRelationships, any, any, any> ? TRelationships extends ModelRelationships ? TRelationships : {} : {};
2637
+ /**
2638
+ * Extract foreign key properties for BelongsTo relationships
2639
+ * @template TRelationships - The relationships configuration object
2640
+ */
2641
+ type BelongsToForeignKeys<TRelationships extends ModelRelationships> = UnionToIntersection<{
2642
+ [K in keyof TRelationships]: TRelationships[K] extends BelongsTo<infer TTarget, infer TForeign> ? {
2643
+ [FK in NonNullable<TForeign>]: ModelId<TTarget> | null;
2644
+ } : never;
2645
+ }[keyof TRelationships]>;
2646
+ /**
2647
+ * Extract foreign key properties for HasMany relationships
2648
+ * @template TRelationships - The relationships configuration object
2649
+ */
2650
+ type HasManyForeignKeys<TRelationships extends ModelRelationships> = UnionToIntersection<{
2651
+ [K in keyof TRelationships]: TRelationships[K] extends HasMany<infer TTarget, infer TForeign> ? {
2652
+ [FK in NonNullable<TForeign>]: ModelId<TTarget>[];
2653
+ } : never;
2654
+ }[keyof TRelationships]>;
2655
+ /**
2656
+ * Infer foreign key properties from relationships configuration
2657
+ * Creates properties like: authorId: string | null, postIds: string[]
2658
+ * @template TRelationships - The relationships configuration object
2659
+ */
2660
+ type ModelForeignKeys<TRelationships extends ModelRelationships> = TRelationships extends never ? {} : BelongsToForeignKeys<TRelationships> & HasManyForeignKeys<TRelationships>;
2661
+ /**
2662
+ * Type for related model
2663
+ * @template TSchema - The schema collections
2664
+ * @template TRelationship - The relationship
2665
+ */
2666
+ type RelatedModel<TSchema extends SchemaCollections, TRelationship extends Relationships> = TRelationship extends BelongsTo<infer TTarget, any> ? ModelInstance<TTarget, TSchema> | null : TRelationship extends HasMany<infer TTarget, any> ? ModelCollection<TTarget, TSchema> : never;
2667
+ type RelatedModelAttrs<TSchema extends SchemaCollections, TRelationships extends ModelRelationships> = TRelationships extends ModelRelationships ? {
2668
+ [K in keyof TRelationships]: TRelationships[K] extends BelongsTo<infer TTarget, any> ? ModelInstance<TTarget, TSchema> | null : TRelationships[K] extends HasMany<infer TTarget, any> ? ModelCollection<TTarget, TSchema> | ModelInstance<TTarget, TSchema>[] : never;
2669
+ } : {};
2670
+ type ForeignKeyAttrs<TRelationships extends ModelRelationships> = Partial<ModelForeignKeys<TRelationships>>;
2671
+ /**
2672
+ * Infer relationship accessor properties that can be updated
2673
+ * @template TSchema - The schema collections
2674
+ * @template TRelationships - The relationships configuration
2675
+ */
2676
+ type ModelRelationshipAccessors<TSchema extends SchemaCollections, TRelationships extends ModelRelationships> = keyof TRelationships extends never ? {} : {
2677
+ [K in keyof TRelationships]: RelatedModel<TSchema, TRelationships[K]>;
2678
+ };
2679
+ /**
2680
+ * Type for base model attributes (allowing null id for unsaved models)
2681
+ * @template TTemplate - The model template
2682
+ */
2683
+ type NewModelAttrs<TAttrs extends {
2684
+ id: any;
2685
+ }> = TAttrs | (Omit<TAttrs, 'id'> & {
2686
+ id?: TAttrs['id'] | null;
2687
+ });
2688
+ /**
2689
+ * Type for new base model instance with nullable ID
2690
+ * @template TAttrs - The model attributes type
2691
+ * @template TSerializer - The serializer type
2692
+ */
2693
+ type NewBaseModelInstance<TAttrs extends {
2694
+ id: any;
2695
+ }, TSerializer = undefined> = BaseModel<TAttrs, TSerializer> & {
2696
+ attrs: NewModelAttrs<TAttrs>;
2697
+ id: TAttrs['id'] | null;
2698
+ };
2699
+ /**
2700
+ * Type for base model instance with required ID
2701
+ * @template TAttrs - The model attributes type
2702
+ * @template TSerializer - The serializer type
2703
+ */
2704
+ type BaseModelInstance<TAttrs extends {
2705
+ id: any;
2706
+ }, TSerializer = undefined> = BaseModel<TAttrs, TSerializer> & {
2707
+ attrs: TAttrs;
2708
+ id: TAttrs['id'];
2709
+ };
2710
+ /**
2711
+ * Type for model attribute getters/setters
2712
+ * @template TTemplate - The model template
2713
+ */
2714
+ type ModelAttrAccessors<TTemplate extends ModelTemplate> = {
2715
+ [K in keyof Omit<InferModelAttrs<TTemplate>, 'id'>]: InferModelAttrs<TTemplate>[K];
2716
+ };
2717
+ /**
2718
+ * Type for model only attributes without ID
2719
+ */
2720
+ type ModelOnlyAttrs<TTemplate extends ModelTemplate> = Omit<InferModelAttrs<TTemplate>, 'id'>;
2721
+ /**
2722
+ * Type for model attributes that includes regular attributes, foreign keys, and relationship model instances
2723
+ * Only relationship-related properties are optional
2724
+ * @template TTemplate - The model template
2725
+ * @template TSchema - The schema collections type
2726
+ */
2727
+ type ModelAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>> = Omit<InferModelAttrs<TTemplate>, 'id'> & ModelForeignKeys<TRelationships> & {
2728
+ id: ModelId<TTemplate>;
2729
+ };
2730
+ /**
2731
+ * Type for partial model attributes
2732
+ * @template TTemplate - The model template
2733
+ * @template TSchema - The schema collections type
2734
+ */
2735
+ type PartialModelAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections> = Partial<ModelAttrs<TTemplate, TSchema>>;
2736
+ /**
2737
+ * Type for constructor attributes that includes regular attributes and relationship model instances
2738
+ * @template TTemplate - The model template
2739
+ * @template TSchema - The schema collections type
2740
+ */
2741
+ type ModelCreateAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>> = Omit<InferModelAttrs<TTemplate>, 'id'> & {
2742
+ id?: ModelId<TTemplate> | null;
2743
+ } & (Record<string, never> extends TRelationships ? {} : ForeignKeyAttrs<TRelationships> & Partial<RelatedModelAttrs<TSchema, TRelationships>>);
2744
+ /**
2745
+ * Type for update method that includes attributes, foreign keys, and relationship model instances
2746
+ * All properties are optional for updates
2747
+ * @template TTemplate - The model template
2748
+ * @template TSchema - The schema collections type
2749
+ */
2750
+ type ModelUpdateAttrs<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>> = Partial<ModelAttrs<TTemplate, TSchema, TRelationships>> & (Record<string, never> extends TRelationships ? {} : Partial<RelatedModelAttrs<TSchema, TRelationships>>);
2751
+ /**
2752
+ * Configuration for creating a schema-aware model
2753
+ * @template TTemplate - The model template
2754
+ * @template TSchema - The schema collections type
2755
+ * @template TRelationships - The model relationships
2756
+ * @template TSerializer - The serializer type
2757
+ */
2758
+ type ModelConfig<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TRelationships extends ModelRelationships = RelationshipsByTemplate<TTemplate, TSchema>, TSerializer = undefined> = {
2759
+ attrs: ModelCreateAttrs<TTemplate, TSchema, TRelationships>;
2760
+ schema: SchemaInstance<TSchema>;
2761
+ serializer?: TSerializer extends undefined ? any : TSerializer;
2762
+ } & (Record<string, never> extends TRelationships ? {
2763
+ relationships?: undefined;
2764
+ } : {
2765
+ relationships: TRelationships;
2766
+ });
2767
+ /**
2768
+ * Type for model class with attribute accessors (direct Model constructor)
2769
+ * @template TTemplate - The model template (most important for users)
2770
+ * @template TSchema - The schema collections type for enhanced type inference
2771
+ * @template TSerializer - The serializer type
2772
+ */
2773
+ type ModelClass<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined> = {
2774
+ new (config: ModelConfig<TTemplate, TSchema, RelationshipsByTemplate<TTemplate, TSchema>, TSerializer>): NewModelInstance<TTemplate, TSchema, TSerializer>;
2775
+ };
2776
+ /**
2777
+ * Type for new model instance with accessors for the attributes (nullable id)
2778
+ * @template TTemplate - The model template (most important for users)
2779
+ * @template TSchema - The schema collections type for enhanced type inference
2780
+ * @template TSerializer - The serializer type
2781
+ */
2782
+ type NewModelInstance<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined> = Model<TTemplate, TSchema, TSerializer> & {
2783
+ attrs: ModelAttrs<TTemplate, TSchema>;
2784
+ id: ModelAttrs<TTemplate, TSchema>['id'] | null;
2785
+ } & ModelAttrAccessors<TTemplate> & ModelForeignKeys<RelationshipsByTemplate<TTemplate, TSchema>> & ModelRelationshipAccessors<TSchema, RelationshipsByTemplate<TTemplate, TSchema>>;
2786
+ /**
2787
+ * Type for model instance with accessors for the attributes (required ID)
2788
+ * @template TTemplate - The model template (most important for users)
2789
+ * @template TSchema - The schema collections type for enhanced type inference
2790
+ * @template TSerializer - The serializer type
2791
+ */
2792
+ type ModelInstance<TTemplate extends ModelTemplate, TSchema extends SchemaCollections = SchemaCollections, TSerializer = undefined> = Model<TTemplate, TSchema, TSerializer> & {
2793
+ attrs: ModelAttrs<TTemplate, TSchema>;
2794
+ id: ModelAttrs<TTemplate, TSchema>['id'];
2795
+ } & ModelAttrAccessors<TTemplate> & ModelForeignKeys<RelationshipsByTemplate<TTemplate, TSchema>> & ModelRelationshipAccessors<TSchema, RelationshipsByTemplate<TTemplate, TSchema>>;
2796
+ /**
2797
+ * Model status type
2798
+ */
2799
+ type ModelStatus = 'new' | 'saved';
2800
+
2801
+ /**
2802
+ * BaseModel class for managing basic model operations without schema dependencies
2803
+ * Handles basic CRUD operations, db updates, attribute management, and status tracking
2804
+ * @template TAttrs - The model attributes type (e.g., { id: string, name: string })
2805
+ * @template TSerializer - The serializer type for custom JSON serialization
2806
+ */
2807
+ declare class BaseModel<TAttrs extends {
2808
+ id: any;
2809
+ }, TSerializer = undefined> {
2810
+ readonly modelName: string;
2811
+ readonly collectionName: string;
2812
+ protected _attrs: NewModelAttrs<TAttrs>;
2813
+ protected _dbCollection: DbCollection<TAttrs>;
2814
+ protected _serializer?: TSerializer;
2815
+ protected _status: ModelStatus;
2816
+ constructor(modelName: string, collectionName: string, attrs: NewModelAttrs<TAttrs>, dbCollection?: DbCollection<TAttrs>, serializer?: TSerializer);
2817
+ /**
2818
+ * Getter for the protected id attribute
2819
+ * @returns The id of the model
2820
+ */
2821
+ get id(): TAttrs['id'] | null;
2822
+ /**
2823
+ * Getter for the model attributes
2824
+ * @returns A copy of the model attributes
2825
+ */
2826
+ get attrs(): NewModelAttrs<TAttrs>;
2827
+ /**
2828
+ * Save the model to the database
2829
+ * @returns The model with saved instance type
2830
+ */
2831
+ save(): this & BaseModelInstance<TAttrs, TSerializer>;
2832
+ /**
2833
+ * Update the model attributes and save the model
2834
+ * @param attrs - The attributes to update
2835
+ * @returns The model instance for chaining
2836
+ */
2837
+ update(attrs: Partial<TAttrs>): this & BaseModelInstance<TAttrs, TSerializer>;
2838
+ /**
2839
+ * Reload the model from the database
2840
+ * @returns The model with saved instance type
2841
+ */
2842
+ reload(): this & BaseModelInstance<TAttrs, TSerializer>;
2843
+ /**
2844
+ * Destroy the model from the database
2845
+ * @returns The model with new instance type
2846
+ */
2847
+ destroy(): this & NewBaseModelInstance<TAttrs, TSerializer>;
2848
+ /**
2849
+ * Check if the model is new
2850
+ * @returns True if the model is new, false otherwise
2851
+ */
2852
+ isNew(): boolean;
2853
+ /**
2854
+ * Check if the model is saved
2855
+ * @returns True if the model is saved, false otherwise
2856
+ */
2857
+ isSaved(): boolean;
2858
+ /**
2859
+ * Serialize the model to a JSON object
2860
+ * @returns The serialized model using the configured serializer or raw attributes
2861
+ */
2862
+ toJSON(): TSerializer extends {
2863
+ serialize(model: any): infer TSerializedModel;
2864
+ } ? TSerializedModel : TAttrs;
2865
+ /**
2866
+ * Serialize the model to a string
2867
+ * @returns The simple string representation of the model and its id
2868
+ */
2869
+ toString(): string;
2870
+ private _checkStatus;
2871
+ }
2872
+
2873
+ /**
2874
+ * A fluent builder for creating strongly-typed model templates.
2875
+ *
2876
+ * The ModelBuilder provides a type-safe way to construct ModelTemplate instances with
2877
+ * configurable model attributes. It follows the builder pattern, allowing method chaining
2878
+ * to progressively refine the template's type parameters.
2879
+ * @template TModelAttrs - The model attributes type (must have an 'id' property)
2880
+ * @template TModelName - The string literal type for the model name
2881
+ * @template TCollectionName - The string literal type for the collection name
2882
+ * @template TSerializedModel - The serialized model type (for toJSON)
2883
+ * @template TSerializedCollection - The serialized collection type (for toJSON)
2884
+ * @example
2885
+ * ```typescript
2886
+ * // Create a basic template
2887
+ * const userTemplate = model().name('user').collection('users').create();
2888
+ *
2889
+ * // Create a template with specific model attributes
2890
+ * interface User { id: string; name: string; email: string; }
2891
+ * const typedUserTemplate = model()
2892
+ * .name('user')
2893
+ * .collection('users')
2894
+ * .attrs<UserAttrs>()
2895
+ * .create();
2896
+ *
2897
+ * // With custom JSON types
2898
+ * const jsonTypedTemplate = model()
2899
+ * .name('user')
2900
+ * .collection('users')
2901
+ * .attrs<UserAttrs>()
2902
+ * .json<UserJSON, UsersJSON>()
2903
+ * .create();
2904
+ * ```
2905
+ */
2906
+ declare class ModelBuilder<TModelAttrs extends {
2907
+ id: any;
2908
+ } = {
2909
+ id: string;
2910
+ }, TModelName extends string = string, TCollectionName extends string = string, TSerializedModel = TModelAttrs, TSerializedCollection = TSerializedModel[]> {
2911
+ private _modelName?;
2912
+ private _collectionName?;
2913
+ /**
2914
+ * Sets the model name identifier.
2915
+ * @template T - The string literal type for the model name
2916
+ * @param modelName - The name identifier for the model (e.g., 'user', 'post')
2917
+ * @returns A new ModelBuilder instance with the model name set
2918
+ * @example
2919
+ * ```typescript
2920
+ * const builder = model().name('user');
2921
+ * ```
2922
+ */
2923
+ name<T extends string>(modelName: T): ModelBuilder<TModelAttrs, T, TCollectionName, TSerializedModel, TSerializedCollection>;
2924
+ /**
2925
+ * Sets the collection name identifier.
2926
+ * @template T - The string literal type for the collection name
2927
+ * @param collectionName - The name identifier for the collection (e.g., 'users', 'posts')
2928
+ * @returns A new ModelBuilder instance with the collection name set
2929
+ * @example
2930
+ * ```typescript
2931
+ * const builder = model().name('user').collection('users');
2932
+ * ```
2933
+ */
2934
+ collection<T extends string>(collectionName: T): ModelBuilder<TModelAttrs, TModelName, T, TSerializedModel, TSerializedCollection>;
2935
+ /**
2936
+ * Sets the model attributes type.
2937
+ *
2938
+ * This method allows you to specify the exact shape of your model attributes,
2939
+ * providing strong typing for the resulting template. Serialization types are
2940
+ * reset to default to the new attributes type (use .json() to override).
2941
+ * @template T - The model attributes type (must extend { id: any })
2942
+ * @returns A new ModelBuilder instance with the specified model type
2943
+ * @example
2944
+ * ```typescript
2945
+ * interface User { id: string; name: string; email: string; }
2946
+ * const builder = model().name('user').collection('users').attrs<UserAttrs>();
2947
+ * ```
2948
+ */
2949
+ attrs<T extends {
2950
+ id: any;
2951
+ }>(): ModelBuilder<T, TModelName, TCollectionName, T, T[]>;
2952
+ /**
2953
+ * Specifies serialization types for this model.
2954
+ *
2955
+ * This method sets the types returned by model.toJSON() and collection.toJSON().
2956
+ * If not called, toJSON() will return the model attributes type.
2957
+ * @template TModel - The serialized model type (single instance)
2958
+ * @template TCollection - The serialized collection type (array)
2959
+ * @returns A new ModelBuilder with serialization types
2960
+ * @example
2961
+ * ```typescript
2962
+ * interface UserJSON {
2963
+ * id: string;
2964
+ * name: string;
2965
+ * email: string;
2966
+ * }
2967
+ *
2968
+ * interface UsersJSON {
2969
+ * users: UserJSON[];
2970
+ * }
2971
+ *
2972
+ * const userModel = model()
2973
+ * .name('user')
2974
+ * .collection('users')
2975
+ * .attrs<UserAttrs>()
2976
+ * .json<UserJSON, UsersJSON>() // Specify serialization types
2977
+ * .create();
2978
+ * ```
2979
+ */
2980
+ json<TModel = TModelAttrs, TCollection = TModel[]>(): ModelBuilder<TModelAttrs, TModelName, TCollectionName, TModel, TCollection>;
2981
+ /**
2982
+ * Creates the final ModelTemplate with all configured types and metadata.
2983
+ *
2984
+ * This method produces the immutable ModelTemplate that can be used throughout
2985
+ * your application for type-safe model operations. The template includes the
2986
+ * model and collection names, a unique symbol key, and hidden type properties
2987
+ * for attributes and serialization.
2988
+ * @returns The configured ModelTemplate instance with hidden type properties
2989
+ * @throws Error if model name or collection name is not set
2990
+ * @example
2991
+ * ```typescript
2992
+ * const userTemplate = model()
2993
+ * .name('user')
2994
+ * .collection('users')
2995
+ * .attrs<UserAttrs>()
2996
+ * .create();
2997
+ * ```
2998
+ */
2999
+ create(): ModelTemplate<TModelName, TCollectionName> & {
3000
+ __attrs: TModelAttrs;
3001
+ __json: {
3002
+ model: TSerializedModel;
3003
+ collection: TSerializedCollection;
3004
+ };
3005
+ };
3006
+ }
3007
+ /**
3008
+ * Creates a new ModelBuilder for constructing type-safe model templates.
3009
+ *
3010
+ * This is the primary entry point for creating model templates. It provides a fluent
3011
+ * interface for configuring model attributes and metadata.
3012
+ * @returns A new ModelBuilder instance ready for configuration
3013
+ * @example
3014
+ * ```typescript
3015
+ * // Basic usage
3016
+ * const userTemplate = model()
3017
+ * .name('user')
3018
+ * .collection('users')
3019
+ * .create();
3020
+ *
3021
+ * // With typed attributes
3022
+ * interface UserAttrs { id: string; name: string; email: string; }
3023
+ * const typedUserTemplate = model()
3024
+ * .name('user')
3025
+ * .collection('users')
3026
+ * .attrs<UserAttrs>()
3027
+ * .create();
3028
+ *
3029
+ * // With custom JSON types
3030
+ * interface UserJSON { id: string; name: string; email: string; }
3031
+ * interface UsersJSON { users: UserJSON[]; }
3032
+ * const jsonTypedTemplate = model()
3033
+ * .name('user')
3034
+ * .collection('users')
3035
+ * .attrs<UserAttrs>()
3036
+ * .json<UserJSON, UsersJSON>()
3037
+ * .create();
3038
+ * ```
3039
+ */
3040
+ declare function model(): ModelBuilder<{
3041
+ id: string;
3042
+ }, string, string>;
3043
+
3044
+ export { type Association, type BelongsTo, Collection, type CollectionConfig, type CollectionCreateAttrs, type CollectionInstance, type CreateAssociation, type CreateManyAssociation, type DataSerializerOptions, type DbRecordInput, Factory, type FactoryAfterCreateHook, type FactoryAttrs, type FixtureAttrs, type FixtureConfig, type FixtureLoadStrategy, type HasMany, IdentityManager, type InferCollectionName, type InferModelAttrs, type InferModelName, type InferSerializedCollection, type InferSerializedModel, type LinkAssociation, type LinkManyAssociation, type ModelAttrs, type ModelInstance, type ModelTemplate, type ModelTraits, type ModelUpdateAttrs, type NewModelInstance, NumberIdentityManager, type OrderBy, type PartialModelAttrs, type QueryOptions, type SchemaCollections, type SchemaInstance, type SeedFunction, type SeedScenarios, type Seeds, Serializer, type SerializerOptions, StringIdentityManager, type StructuralSerializerOptions, type TraitDefinition, type Where, associations, belongsTo, collection, create, createMany, factory, hasMany, link, linkMany, model, schema };