@fyrestack/database 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,1071 @@
1
+ import { OmitPrivate, Prettify, Type } from "@fyrestack/core";
2
+ import { StandardSchemaV1 } from "@standard-schema/spec";
3
+
4
+ //#region src/batch.d.ts
5
+ /**
6
+ * Maximum operations per Firestore batch.
7
+ */
8
+ declare const MAX_BATCH_SIZE = 500;
9
+ /**
10
+ * Run operations within a write batch.
11
+ *
12
+ * Batches provide:
13
+ * - Atomic writes (all succeed or all fail)
14
+ * - Better performance than individual writes
15
+ * - Up to 500 operations per batch
16
+ * - Works across multiple repositories
17
+ *
18
+ * The batch context is **automatically propagated** to all repository
19
+ * methods called within the batch function - no need to pass context explicitly.
20
+ *
21
+ * Note: Batches are write-only. Use `runTransaction` if you need reads.
22
+ *
23
+ * @example
24
+ * ```typescript
25
+ * // Bulk create users
26
+ * await writeBatch(async () => {
27
+ * for (const user of users) {
28
+ * await UserRepo.save({}, user);
29
+ * }
30
+ * });
31
+ * ```
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * // Cross-repository batch write
36
+ * await writeBatch(async () => {
37
+ * await UserRepo.save({}, user);
38
+ * await ProfileRepo.save({ userId: user.id }, profile);
39
+ * await AuditRepo.save({}, auditLog);
40
+ * });
41
+ * ```
42
+ *
43
+ * @param fn - Async function to run within the batch
44
+ */
45
+ declare function writeBatch(fn: () => Promise<void>): Promise<void>;
46
+ /**
47
+ * Run operations with automatic batch chunking for large datasets.
48
+ *
49
+ * Automatically commits and creates new batches when exceeding 500 operations.
50
+ * Useful for migrations or bulk imports with thousands of records.
51
+ *
52
+ * The batch context is **automatically propagated** to all repository
53
+ * methods called within the function.
54
+ *
55
+ * @example
56
+ * ```typescript
57
+ * // Process 10,000 records with automatic batching
58
+ * await writeChunkedBatch(async () => {
59
+ * for (const user of thousandsOfUsers) {
60
+ * await UserRepo.save({}, user);
61
+ * // Automatically commits every 500 operations
62
+ * }
63
+ * });
64
+ * ```
65
+ *
66
+ * @param fn - Function to run with automatic batch chunking
67
+ */
68
+ declare function writeChunkedBatch(fn: () => Promise<void>): Promise<void>;
69
+ //#endregion
70
+ //#region src/firestore.types.d.ts
71
+ /**
72
+ * Sentinel type for server-generated timestamps.
73
+ * This is a branded type that represents Firebase's serverTimestamp() value.
74
+ */
75
+ interface ServerTimestampSentinel {
76
+ /** Brand to distinguish from other objects */
77
+ readonly __type__: 'serverTimestamp';
78
+ }
79
+ /**
80
+ * Type guard to check if a value is a ServerTimestampSentinel.
81
+ * Note: This checks the runtime structure, not the brand.
82
+ */
83
+ declare function isServerTimestamp(value: unknown): value is ServerTimestampSentinel;
84
+ /**
85
+ * Abstract document snapshot
86
+ */
87
+ interface DocumentSnapshot<T = unknown> {
88
+ id: string;
89
+ exists: boolean;
90
+ data(): T | undefined;
91
+ }
92
+ /**
93
+ * Abstract document reference
94
+ */
95
+ interface DocumentReference<T = unknown> {
96
+ id: string;
97
+ path: string;
98
+ /** Native reference for transaction/batch operations (internal use) */
99
+ _native?: unknown;
100
+ get(): Promise<DocumentSnapshot<T>>;
101
+ set(data: T): Promise<void>;
102
+ update(data: Record<string, unknown>): Promise<void>;
103
+ delete(): Promise<void>;
104
+ }
105
+ /**
106
+ * Abstract query snapshot
107
+ */
108
+ interface QuerySnapshot<T = unknown> {
109
+ docs: DocumentSnapshot<T>[];
110
+ empty: boolean;
111
+ size: number;
112
+ }
113
+ /**
114
+ * Supported Firestore operators
115
+ */
116
+ type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'array-contains-any' | 'in' | 'not-in';
117
+ /**
118
+ * Sort direction
119
+ */
120
+ type OrderByDirection = 'asc' | 'desc';
121
+ /**
122
+ * Abstract query reference - chainable query builder
123
+ */
124
+ interface QueryReference<T = unknown> {
125
+ where(field: string, op: WhereFilterOp, value: unknown): QueryReference<T>;
126
+ orderBy(field: string, direction?: OrderByDirection): QueryReference<T>;
127
+ limit(count: number): QueryReference<T>;
128
+ startAt(...values: unknown[]): QueryReference<T>;
129
+ startAfter(...values: unknown[]): QueryReference<T>;
130
+ endAt(...values: unknown[]): QueryReference<T>;
131
+ endBefore(...values: unknown[]): QueryReference<T>;
132
+ get(): Promise<QuerySnapshot<T>>;
133
+ }
134
+ /**
135
+ * Abstract collection reference
136
+ */
137
+ interface CollectionReference<T = unknown> extends QueryReference<T> {
138
+ path: string;
139
+ doc(id?: string): DocumentReference<T>;
140
+ }
141
+ /**
142
+ * Options for running a transaction.
143
+ */
144
+ interface TransactionOptions {
145
+ /** Maximum retry attempts on contention (default: 5) */
146
+ maxAttempts?: number;
147
+ }
148
+ /**
149
+ * Firestore Transaction handle for atomic read-write operations.
150
+ * All reads must happen before writes within a transaction.
151
+ */
152
+ interface Transaction {
153
+ /**
154
+ * Read a document within the transaction.
155
+ */
156
+ get<T>(docRef: DocumentReference<T>): Promise<DocumentSnapshot<T>>;
157
+ /**
158
+ * Set a document within the transaction.
159
+ */
160
+ set<T>(docRef: DocumentReference<T>, data: T): Transaction;
161
+ /**
162
+ * Update a document within the transaction.
163
+ */
164
+ update(docRef: DocumentReference, data: Record<string, unknown>): Transaction;
165
+ /**
166
+ * Delete a document within the transaction.
167
+ */
168
+ delete(docRef: DocumentReference): Transaction;
169
+ }
170
+ /**
171
+ * Firestore WriteBatch handle for atomic write-only operations.
172
+ * Up to 500 operations per batch.
173
+ */
174
+ interface WriteBatch {
175
+ /**
176
+ * Set a document in the batch.
177
+ */
178
+ set<T>(docRef: DocumentReference<T>, data: T): WriteBatch;
179
+ /**
180
+ * Update a document in the batch.
181
+ */
182
+ update(docRef: DocumentReference, data: Record<string, unknown>): WriteBatch;
183
+ /**
184
+ * Delete a document in the batch.
185
+ */
186
+ delete(docRef: DocumentReference): WriteBatch;
187
+ /**
188
+ * Commit all batched operations atomically.
189
+ */
190
+ commit(): Promise<void>;
191
+ }
192
+ /**
193
+ * Abstract Firestore instance - the main DI interface
194
+ */
195
+ interface FirestoreAdapter {
196
+ collection<T = unknown>(path: string): CollectionReference<T>;
197
+ doc<T = unknown>(path: string): DocumentReference<T>;
198
+ /**
199
+ * Returns a sentinel value for server-generated timestamp.
200
+ * Used for createdAt/updatedAt fields.
201
+ *
202
+ * Note: Returns the actual Firebase sentinel value which is cast to
203
+ * ServerTimestampSentinel for type safety. The runtime value is
204
+ * Firebase's internal FieldValue/serverTimestamp implementation.
205
+ */
206
+ serverTimestamp(): ServerTimestampSentinel;
207
+ /**
208
+ * Run a transaction with automatic retry on conflicts.
209
+ * @param updateFn - Function receiving Transaction object
210
+ * @param options - Transaction options (maxAttempts, etc.)
211
+ */
212
+ runTransaction<T>(updateFn: (transaction: Transaction) => Promise<T>, options?: TransactionOptions): Promise<T>;
213
+ /**
214
+ * Create a new write batch.
215
+ */
216
+ batch(): WriteBatch;
217
+ }
218
+ /**
219
+ * Set the Firestore adapter to use (call once at app initialization)
220
+ */
221
+ declare function setFirestoreAdapter(adapter: FirestoreAdapter): void;
222
+ /**
223
+ * Get the current Firestore adapter
224
+ * @throws AdapterNotInitializedError if adapter not initialized
225
+ */
226
+ declare function getFirestoreAdapter(): FirestoreAdapter;
227
+ /**
228
+ * Reset the Firestore adapter (for testing only)
229
+ * @internal
230
+ */
231
+ declare function _resetFirestoreAdapter(): void;
232
+ //#endregion
233
+ //#region src/context.d.ts
234
+ /**
235
+ * Transaction context - supports reads and writes.
236
+ */
237
+ interface TransactionContext {
238
+ readonly type: 'transaction';
239
+ readonly tx: Transaction;
240
+ }
241
+ /**
242
+ * Batch context - write-only operations.
243
+ */
244
+ interface BatchContext {
245
+ readonly type: 'batch';
246
+ readonly batch: WriteBatch;
247
+ }
248
+ /**
249
+ * Union of all operation contexts.
250
+ */
251
+ type OperationContext = TransactionContext | BatchContext;
252
+ /**
253
+ * Get the current operation context, if any.
254
+ * Returns undefined when not inside a transaction or batch.
255
+ */
256
+ declare function getCurrentContext(): OperationContext | undefined;
257
+ /**
258
+ * Check if we're currently inside a transaction.
259
+ */
260
+ declare function isInTransaction(): boolean;
261
+ /**
262
+ * Check if we're currently inside a batch.
263
+ */
264
+ declare function isInBatch(): boolean;
265
+ /**
266
+ * Get the current transaction, if inside one.
267
+ * Returns undefined when not in a transaction.
268
+ */
269
+ declare function getCurrentTransaction(): Transaction | undefined;
270
+ /**
271
+ * Get the current batch, if inside one.
272
+ * Returns undefined when not in a batch.
273
+ */
274
+ declare function getCurrentBatch(): WriteBatch | undefined;
275
+ /**
276
+ * Run a function within a transaction context.
277
+ * @internal Used by runTransaction()
278
+ */
279
+ declare function runWithTransaction<T>(tx: Transaction, fn: () => Promise<T>): Promise<T>;
280
+ /**
281
+ * Run a function within a batch context.
282
+ * @internal Used by writeBatch()
283
+ */
284
+ declare function runWithBatch<T>(batch: WriteBatch, fn: () => Promise<T>): Promise<T>;
285
+ /**
286
+ * Type guard for transaction context.
287
+ */
288
+ declare function isTransactionContext(ctx?: OperationContext): ctx is TransactionContext;
289
+ /**
290
+ * Type guard for batch context.
291
+ */
292
+ declare function isBatchContext(ctx?: OperationContext): ctx is BatchContext;
293
+ //#endregion
294
+ //#region src/errors.d.ts
295
+ /**
296
+ * FyreStack Custom Error Types
297
+ *
298
+ * Provides typed errors for better error handling and debugging.
299
+ */
300
+ /**
301
+ * Base error class for all FyreStack errors.
302
+ */
303
+ declare class FyreStackError extends Error {
304
+ readonly code: string;
305
+ constructor(message: string, code: string);
306
+ }
307
+ /**
308
+ * Error thrown when validation fails.
309
+ */
310
+ declare class ValidationError extends FyreStackError {
311
+ readonly issues: ValidationIssue[];
312
+ constructor(message: string, issues?: ValidationIssue[]);
313
+ /**
314
+ * Create a ValidationError from Standard Schema validation issues.
315
+ */
316
+ static fromStandardSchema(issues: readonly StandardSchemaIssue[]): ValidationError;
317
+ }
318
+ /**
319
+ * Validation issue structure.
320
+ */
321
+ interface ValidationIssue {
322
+ /** Path to the invalid field (e.g., ['address', 'zip']) */
323
+ path: string[];
324
+ /** Human-readable error message */
325
+ message: string;
326
+ }
327
+ /**
328
+ * Standard Schema issue structure (subset of StandardSchemaV1).
329
+ * Compatible with the path types from @standard-schema/spec.
330
+ */
331
+ interface StandardSchemaIssue {
332
+ message: string;
333
+ path?: ReadonlyArray<PropertyKey | {
334
+ key: PropertyKey;
335
+ }> | undefined;
336
+ }
337
+ /**
338
+ * Error thrown when path parameters are invalid.
339
+ */
340
+ declare class PathParamError extends FyreStackError {
341
+ readonly paramName: string;
342
+ readonly paramValue: string;
343
+ constructor(paramName: string, paramValue: string, reason: string);
344
+ }
345
+ /**
346
+ * Error thrown when Firestore adapter is not initialized.
347
+ */
348
+ declare class AdapterNotInitializedError extends FyreStackError {
349
+ constructor();
350
+ }
351
+ /**
352
+ * Error thrown when a model is missing required properties.
353
+ */
354
+ declare class ModelError extends FyreStackError {
355
+ constructor(message: string);
356
+ }
357
+ /**
358
+ * Error thrown when a document is not found.
359
+ */
360
+ declare class NotFoundError extends FyreStackError {
361
+ readonly documentPath: string;
362
+ constructor(documentPath: string);
363
+ }
364
+ /**
365
+ * Error thrown when a Firestore operation fails.
366
+ */
367
+ declare class FirestoreError extends FyreStackError {
368
+ readonly originalError: unknown;
369
+ constructor(message: string, originalError: unknown);
370
+ /**
371
+ * Wrap a Firestore error with context.
372
+ */
373
+ static wrap(operation: string, error: unknown): FirestoreError;
374
+ }
375
+ /**
376
+ * Validation result type for type-safe validation handling.
377
+ */
378
+ type ValidationResult<T> = {
379
+ valid: true;
380
+ value: T;
381
+ } | {
382
+ valid: false;
383
+ error: ValidationError;
384
+ };
385
+ /**
386
+ * Helper to check if a ValidationResult is valid.
387
+ */
388
+ declare function isValidResult<T>(result: ValidationResult<T>): result is {
389
+ valid: true;
390
+ value: T;
391
+ };
392
+ //#endregion
393
+ //#region src/model.hooks.d.ts
394
+ /**
395
+ * Context passed to repository hooks during operations.
396
+ * Provides access to the adapter, model info, and operation details.
397
+ */
398
+ interface RepositoryHookContext {
399
+ /** The Firestore adapter for accessing Firebase functionality */
400
+ adapter: FirestoreAdapter;
401
+ /** The model class being operated on */
402
+ modelClass: Type<unknown>;
403
+ /** The collection path template */
404
+ path: string;
405
+ /** The resolved path parameters */
406
+ params: Record<string, string>;
407
+ /** The document ID (if applicable) */
408
+ id?: string;
409
+ }
410
+ /**
411
+ * Context passed to model hooks during construction/validation.
412
+ */
413
+ interface ModelHookContext {
414
+ /** The model class being constructed */
415
+ modelClass: Type<unknown>;
416
+ }
417
+ /**
418
+ * Hooks that can be registered for model lifecycle events.
419
+ */
420
+ interface ModelHooks {
421
+ /**
422
+ * Called during model construction, can transform props.
423
+ * @param props - The properties being assigned to the model
424
+ * @param context - Model context
425
+ * @returns Transformed props
426
+ */
427
+ onConstruct?: (props: Record<string, unknown>, context: ModelHookContext) => Record<string, unknown>;
428
+ /**
429
+ * Called during model validation.
430
+ * Can throw ValidationError to fail validation.
431
+ * @param data - The data being validated
432
+ * @param context - Model context
433
+ */
434
+ onValidate?: (data: unknown, context: ModelHookContext) => void;
435
+ }
436
+ /**
437
+ * Hooks that can be registered for repository operations.
438
+ * Hooks can transform data or perform side effects.
439
+ */
440
+ interface RepositoryHooks {
441
+ /**
442
+ * Called before save operation.
443
+ * Can modify the data being saved.
444
+ * @param data - The data to be saved
445
+ * @param context - Repository context with adapter access
446
+ * @returns Modified data (or original if unchanged)
447
+ */
448
+ beforeSave?: (data: Record<string, unknown>, context: RepositoryHookContext) => Record<string, unknown>;
449
+ /**
450
+ * Called after save operation completes successfully.
451
+ * @param data - The data that was saved
452
+ * @param context - Repository context
453
+ */
454
+ afterSave?: (data: Record<string, unknown>, context: RepositoryHookContext) => void;
455
+ /**
456
+ * Called before update operation.
457
+ * Can modify the update data (dot-notation fields).
458
+ * @param updates - The update data
459
+ * @param context - Repository context with adapter access
460
+ * @returns Modified updates (or original if unchanged)
461
+ */
462
+ beforeUpdate?: (updates: Record<string, unknown>, context: RepositoryHookContext) => Record<string, unknown>;
463
+ /**
464
+ * Called after update operation completes successfully.
465
+ * @param updates - The update data that was applied
466
+ * @param context - Repository context
467
+ */
468
+ afterUpdate?: (updates: Record<string, unknown>, context: RepositoryHookContext) => void;
469
+ /**
470
+ * Called before delete operation.
471
+ * Can throw to prevent deletion.
472
+ * @param context - Repository context
473
+ */
474
+ beforeDelete?: (context: RepositoryHookContext) => void;
475
+ /**
476
+ * Called after delete operation completes successfully.
477
+ * @param context - Repository context
478
+ */
479
+ afterDelete?: (context: RepositoryHookContext) => void;
480
+ /**
481
+ * Called after get operation, can transform the result.
482
+ * @param data - The fetched data (or null if not found)
483
+ * @param context - Repository context
484
+ * @returns Transformed data
485
+ */
486
+ afterGet?: (data: Record<string, unknown> | null, context: RepositoryHookContext) => Record<string, unknown> | null;
487
+ /**
488
+ * Called after find operation, can transform results.
489
+ * @param data - Array of fetched documents
490
+ * @param context - Repository context
491
+ * @returns Transformed array
492
+ */
493
+ afterFind?: (data: Record<string, unknown>[], context: RepositoryHookContext) => Record<string, unknown>[];
494
+ }
495
+ /**
496
+ * Combined hooks for both model and repository lifecycle.
497
+ */
498
+ interface FeatureHooks {
499
+ /** Hooks for model lifecycle events */
500
+ model?: ModelHooks;
501
+ /** Hooks for repository operations */
502
+ repository?: RepositoryHooks;
503
+ }
504
+ /**
505
+ * Merge multiple repository hooks into a single hooks object.
506
+ * When multiple hooks define the same method, they are chained in order.
507
+ */
508
+ declare function mergeRepositoryHooks(...hooksList: (RepositoryHooks | undefined)[]): RepositoryHooks;
509
+ /**
510
+ * Merge multiple model hooks into a single hooks object.
511
+ */
512
+ declare function mergeModelHooks(...hooksList: (ModelHooks | undefined)[]): ModelHooks;
513
+ /**
514
+ * Merge feature hooks (combines both model and repository hooks).
515
+ */
516
+ declare function mergeFeatureHooks(...hooksList: (FeatureHooks | undefined)[]): FeatureHooks;
517
+ //#endregion
518
+ //#region src/model.metadata.d.ts
519
+ /**
520
+ * Symbol used to store metadata on model classes.
521
+ * Using a symbol prevents conflicts with user-defined properties.
522
+ */
523
+ declare const MODEL_METADATA: unique symbol;
524
+ /**
525
+ * Model metadata containing registered feature hooks.
526
+ * This is stored on the model class and read by repositories.
527
+ */
528
+ interface ModelMetadata {
529
+ /**
530
+ * Combined hooks from all registered features.
531
+ */
532
+ hooks?: FeatureHooks;
533
+ /**
534
+ * Feature-specific configuration data.
535
+ * Features can store their config here for introspection.
536
+ */
537
+ features?: Record<string, unknown>;
538
+ }
539
+ /**
540
+ * Get metadata from a model class.
541
+ */
542
+ declare function getModelMetadata(ModelClass: unknown): ModelMetadata | undefined;
543
+ /**
544
+ * Get repository hooks from a model class.
545
+ */
546
+ declare function getRepositoryHooks(ModelClass: unknown): RepositoryHooks | undefined;
547
+ /**
548
+ * Get model hooks from a model class.
549
+ */
550
+ declare function getModelHooks(ModelClass: unknown): ModelHooks | undefined;
551
+ /**
552
+ * Check if a model has any repository hooks registered.
553
+ */
554
+ declare function hasRepositoryHooks(ModelClass: unknown): boolean;
555
+ /**
556
+ * Check if a model has a specific feature registered.
557
+ */
558
+ declare function hasFeature(ModelClass: unknown, featureName: string): boolean;
559
+ /**
560
+ * Get configuration for a specific feature.
561
+ */
562
+ declare function getFeatureConfig<T>(ModelClass: unknown, featureName: string): T | undefined;
563
+ /**
564
+ * Create metadata for a feature.
565
+ * Used by feature functions like withTimestamps() to build metadata.
566
+ *
567
+ * @param featureName - Unique name for the feature
568
+ * @param config - Feature-specific configuration (for introspection)
569
+ * @param hooks - Hooks to register
570
+ * @param existingMetadata - Existing metadata to merge with
571
+ */
572
+ declare function createFeatureMetadata(featureName: string, config: unknown, hooks: FeatureHooks, existingMetadata?: ModelMetadata): ModelMetadata;
573
+ /**
574
+ * Configuration for automatic timestamp management.
575
+ */
576
+ interface TimestampsConfig {
577
+ /**
578
+ * Field name for creation timestamp.
579
+ * Set to `false` to disable.
580
+ * @default 'createdAt'
581
+ */
582
+ createdAt: string | false;
583
+ /**
584
+ * Field name for last update timestamp.
585
+ * Set to `false` to disable.
586
+ * @default 'updatedAt'
587
+ */
588
+ updatedAt: string | false;
589
+ /**
590
+ * Whether to use Firestore serverTimestamp() for accuracy.
591
+ * When false, uses client-side Date.
592
+ * @default true
593
+ */
594
+ useServerTimestamp: boolean;
595
+ }
596
+ /**
597
+ * User-provided options for configuring timestamps.
598
+ * All fields are optional with sensible defaults.
599
+ */
600
+ interface TimestampsOptions {
601
+ /**
602
+ * Field name for creation timestamp, or `false` to disable.
603
+ * @default 'createdAt'
604
+ */
605
+ createdAt?: string | false;
606
+ /**
607
+ * Field name for last update timestamp, or `false` to disable.
608
+ * @default 'updatedAt'
609
+ */
610
+ updatedAt?: string | false;
611
+ /**
612
+ * Whether to use Firestore serverTimestamp().
613
+ * @default true
614
+ */
615
+ useServerTimestamp?: boolean;
616
+ }
617
+ /**
618
+ * Default timestamp configuration.
619
+ */
620
+ declare const DEFAULT_TIMESTAMPS: TimestampsConfig;
621
+ /**
622
+ * Configuration for audit trail management.
623
+ * Tracks which user created/modified documents.
624
+ */
625
+ interface AuditConfig {
626
+ /**
627
+ * Field name for creator user ID.
628
+ * Set to `false` to disable.
629
+ * @default 'createdBy'
630
+ */
631
+ createdBy: string | false;
632
+ /**
633
+ * Field name for last modifier user ID.
634
+ * Set to `false` to disable.
635
+ * @default 'updatedBy'
636
+ */
637
+ updatedBy: string | false;
638
+ /**
639
+ * Function to get the current user ID.
640
+ * Must be provided when using audit feature.
641
+ */
642
+ getCurrentUserId: () => string | null;
643
+ }
644
+ /**
645
+ * User-provided options for configuring audit trail.
646
+ */
647
+ interface AuditOptions {
648
+ createdBy?: string | false;
649
+ updatedBy?: string | false;
650
+ getCurrentUserId: () => string | null;
651
+ }
652
+ /**
653
+ * Default audit configuration.
654
+ */
655
+ declare const DEFAULT_AUDIT: Omit<AuditConfig, 'getCurrentUserId'>;
656
+ /**
657
+ * Configuration for status field management including soft-delete.
658
+ */
659
+ interface StatusConfig {
660
+ /**
661
+ * Field name for status.
662
+ * @default 'status'
663
+ */
664
+ field: string;
665
+ /**
666
+ * Available status values.
667
+ * @default ['active', 'inactive', 'deleted']
668
+ */
669
+ values: readonly string[];
670
+ /**
671
+ * Default status for new documents.
672
+ * @default 'active'
673
+ */
674
+ defaultValue: string;
675
+ /**
676
+ * Status value that indicates soft-deletion.
677
+ * When set, delete operations will set this status instead of hard-deleting.
678
+ * @default 'deleted'
679
+ */
680
+ deletedValue: string | false;
681
+ /**
682
+ * Field name for deletion timestamp (when soft-delete is enabled).
683
+ * @default 'deletedAt'
684
+ */
685
+ deletedAt: string | false;
686
+ }
687
+ /**
688
+ * User-provided options for configuring status.
689
+ */
690
+ interface StatusOptions {
691
+ field?: string;
692
+ values?: readonly string[];
693
+ defaultValue?: string;
694
+ deletedValue?: string | false;
695
+ deletedAt?: string | false;
696
+ }
697
+ /**
698
+ * Default status configuration.
699
+ */
700
+ declare const DEFAULT_STATUS: StatusConfig;
701
+ /**
702
+ * Check if a model has timestamps feature.
703
+ */
704
+ declare function hasTimestamps(ModelClass: unknown): boolean;
705
+ /**
706
+ * Get timestamps configuration from a model class.
707
+ */
708
+ declare function getTimestampsConfig(ModelClass: unknown): TimestampsConfig | undefined;
709
+ /**
710
+ * Check if a model has audit feature.
711
+ */
712
+ declare function hasAudit(ModelClass: unknown): boolean;
713
+ /**
714
+ * Get audit configuration from a model class.
715
+ */
716
+ declare function getAuditConfig(ModelClass: unknown): AuditConfig | undefined;
717
+ /**
718
+ * Check if a model has status feature.
719
+ */
720
+ declare function hasStatus(ModelClass: unknown): boolean;
721
+ /**
722
+ * Get status configuration from a model class.
723
+ */
724
+ declare function getStatusConfig(ModelClass: unknown): StatusConfig | undefined;
725
+ //#endregion
726
+ //#region src/model.types.d.ts
727
+ /**
728
+ * Symbol for storing the schema on model instances (internal use).
729
+ */
730
+ declare const MODEL_SCHEMA: unique symbol;
731
+ /**
732
+ * Infer the instance type from a Model class.
733
+ * @example
734
+ * const UserModel = model(withSchema(UserSchema));
735
+ * type User = InferModel<typeof UserModel>;
736
+ */
737
+ type InferModel<T extends Type<any>> = InstanceType<T>;
738
+ type MethodsDictionary = Record<string, Function>;
739
+ type InnerModel<Schema extends StandardSchemaV1 = StandardSchemaV1, Props extends object = object, Methods extends MethodsDictionary = MethodsDictionary, Metadata extends ModelMetadata | undefined = ModelMetadata | undefined> = {
740
+ schema: Schema;
741
+ props: Props;
742
+ methods: Methods;
743
+ _metadata?: Metadata;
744
+ };
745
+ type ModelFeatureResult = {
746
+ schema: StandardSchemaV1;
747
+ props: object;
748
+ methods: MethodsDictionary;
749
+ _metadata?: ModelMetadata;
750
+ };
751
+ type ModelFeature<Input extends ModelFeatureResult = ModelFeatureResult, Output extends ModelFeatureResult = ModelFeatureResult> = (store: InnerModel<Input['schema'], Input['props'], Input['methods'], Input['_metadata']>) => InnerModel<Output['schema'], Output['props'], Output['methods'], Output['_metadata']>;
752
+ type EmptyFeatureResult = ModelFeatureResult & {
753
+ props: {};
754
+ methods: {};
755
+ };
756
+ /**
757
+ * Interface for model instances with validation methods.
758
+ */
759
+ interface ModelInstance<T = unknown> {
760
+ /**
761
+ * Validate the current model data.
762
+ * @returns ValidationResult with either the validated value or error
763
+ */
764
+ validate(): ValidationResult<T>;
765
+ /**
766
+ * Check if the model data is valid.
767
+ * @returns true if valid, false otherwise
768
+ */
769
+ isValid(): boolean;
770
+ /**
771
+ * Convert model to a plain object (for Firestore writes).
772
+ * Excludes methods, keeps only data properties.
773
+ */
774
+ toObject(): T;
775
+ }
776
+ //#endregion
777
+ //#region src/model.d.ts
778
+ type ModelMembers<FeatureResult extends ModelFeatureResult> = Prettify<OmitPrivate<FeatureResult['props'] & FeatureResult['methods']>>;
779
+ declare function model<F1 extends ModelFeatureResult>(f1: ModelFeature<EmptyFeatureResult, F1>): Type<ModelMembers<F1>>;
780
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>): Type<ModelMembers<R>>;
781
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>): Type<ModelMembers<R>>;
782
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>): Type<ModelMembers<R>>;
783
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, F5 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4 & F5>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>, f5: ModelFeature<F1 & F2 & F3 & F4, F5>): Type<ModelMembers<R>>;
784
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, F5 extends ModelFeatureResult, F6 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4 & F5 & F6>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>, f5: ModelFeature<F1 & F2 & F3 & F4, F5>, f6: ModelFeature<F1 & F2 & F3 & F4 & F5, F6>): Type<ModelMembers<R>>;
785
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, F5 extends ModelFeatureResult, F6 extends ModelFeatureResult, F7 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4 & F5 & F6 & F7>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>, f5: ModelFeature<F1 & F2 & F3 & F4, F5>, f6: ModelFeature<F1 & F2 & F3 & F4 & F5, F6>, f7: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6, F7>): Type<ModelMembers<R>>;
786
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, F5 extends ModelFeatureResult, F6 extends ModelFeatureResult, F7 extends ModelFeatureResult, F8 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4 & F5 & F6 & F7 & F8>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>, f5: ModelFeature<F1 & F2 & F3 & F4, F5>, f6: ModelFeature<F1 & F2 & F3 & F4 & F5, F6>, f7: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6, F7>, f8: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6 & F7, F8>): Type<ModelMembers<R>>;
787
+ declare function model<F1 extends ModelFeatureResult, F2 extends ModelFeatureResult, F3 extends ModelFeatureResult, F4 extends ModelFeatureResult, F5 extends ModelFeatureResult, F6 extends ModelFeatureResult, F7 extends ModelFeatureResult, F8 extends ModelFeatureResult, F9 extends ModelFeatureResult, R extends ModelFeatureResult = F1 & F2 & F3 & F4 & F5 & F6 & F7 & F8 & F9>(f1: ModelFeature<EmptyFeatureResult, F1>, f2: ModelFeature<{} & F1, F2>, f3: ModelFeature<F1 & F2, F3>, f4: ModelFeature<F1 & F2 & F3, F4>, f5: ModelFeature<F1 & F2 & F3 & F4, F5>, f6: ModelFeature<F1 & F2 & F3 & F4 & F5, F6>, f7: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6, F7>, f8: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6 & F7, F8>, f9: ModelFeature<F1 & F2 & F3 & F4 & F5 & F6 & F7 & F8, F9>): Type<ModelMembers<R>>;
788
+ //#endregion
789
+ //#region src/model.with-schema.d.ts
790
+ declare function withSchema<S extends StandardSchemaV1>(schema: S): ModelFeature<EmptyFeatureResult, {
791
+ schema: S;
792
+ props: StandardSchemaV1.InferOutput<S> & object;
793
+ methods: {};
794
+ }>;
795
+ //#endregion
796
+ //#region src/model.with-timestamps.d.ts
797
+ /**
798
+ * Firestore Timestamp interface - matches both firebase/firestore and firebase-admin/firestore.
799
+ * This allows strict typing without coupling to a specific Firebase SDK.
800
+ */
801
+ interface FirestoreTimestamp {
802
+ readonly seconds: number;
803
+ readonly nanoseconds: number;
804
+ toDate(): Date;
805
+ toMillis(): number;
806
+ }
807
+ /**
808
+ * Possible values for a timestamp field on a model instance:
809
+ * - `Date` - after conversion from Firestore
810
+ * - `FirestoreTimestamp` - raw Firestore Timestamp before conversion
811
+ * - `undefined` - if not yet set
812
+ */
813
+ type TimestampValue = Date | FirestoreTimestamp | undefined;
814
+ /**
815
+ * Timestamp props type - added to model by withTimestamps.
816
+ */
817
+ type TimestampProps<CreatedField extends string | false = 'createdAt', UpdatedField extends string | false = 'updatedAt'> = (CreatedField extends string ? { [K in CreatedField]?: TimestampValue } : object) & (UpdatedField extends string ? { [K in UpdatedField]?: TimestampValue } : object);
818
+ /**
819
+ * Output type for withTimestamps feature - includes metadata
820
+ */
821
+ type WithTimestampsOutput<Input extends ModelFeatureResult> = {
822
+ schema: Input['schema'];
823
+ props: Input['props'] & TimestampProps;
824
+ methods: Input['methods'];
825
+ _metadata: ModelMetadata;
826
+ };
827
+ /**
828
+ * Add automatic timestamp management to a model.
829
+ *
830
+ * This feature registers hooks that:
831
+ * - Set `createdAt` on save (if not already set)
832
+ * - Set `updatedAt` on save and update
833
+ *
834
+ * @example
835
+ * ```typescript
836
+ * // Basic usage with defaults (createdAt, updatedAt)
837
+ * const UserModel = model(
838
+ * withSchema(UserSchema),
839
+ * withTimestamps(),
840
+ * );
841
+ *
842
+ * // Custom field names
843
+ * const PostModel = model(
844
+ * withSchema(PostSchema),
845
+ * withTimestamps({ createdAt: 'publishedAt', updatedAt: 'modifiedAt' }),
846
+ * );
847
+ *
848
+ * // Disable one field
849
+ * const LogModel = model(
850
+ * withSchema(LogSchema),
851
+ * withTimestamps({ updatedAt: false }), // Only track creation
852
+ * );
853
+ *
854
+ * // Use client-side timestamps (for offline support)
855
+ * const OfflineModel = model(
856
+ * withSchema(OfflineSchema),
857
+ * withTimestamps({ useServerTimestamp: false }),
858
+ * );
859
+ * ```
860
+ *
861
+ * @param options - Optional configuration for field names and behavior
862
+ */
863
+ declare function withTimestamps<Input extends ModelFeatureResult>(options?: TimestampsOptions): ModelFeature<Input, WithTimestampsOutput<Input>>;
864
+ //#endregion
865
+ //#region src/repository.types.d.ts
866
+ type RepositoryMethodsDictionary = Record<string, Function>;
867
+ type InnerRepository<Model = unknown, Path extends string = string, Methods extends RepositoryMethodsDictionary = RepositoryMethodsDictionary> = {
868
+ model: Type<Model>;
869
+ path: Path;
870
+ methods: Methods;
871
+ getCollection(params: ExtractPathParams<Path>): CollectionReference<Model>;
872
+ getDocument(params: ExtractPathParams<Path>, id: string): DocumentReference<Model>;
873
+ };
874
+ type RepositoryFeatureResult<Model = unknown, Path extends string = string, Methods extends RepositoryMethodsDictionary = RepositoryMethodsDictionary> = {
875
+ model: Type<Model>;
876
+ path: Path;
877
+ methods: Methods;
878
+ };
879
+ type RepositoryFeature<Input extends RepositoryFeatureResult = RepositoryFeatureResult, Output extends RepositoryFeatureResult = RepositoryFeatureResult> = (repo: InnerRepository<Input['model'], Input['path'], Input['methods']>) => Output['methods'];
880
+ type RepositoryConfig<Model, Path extends string> = {
881
+ path: Path;
882
+ model: Type<Model>;
883
+ };
884
+ /**
885
+ * Base repository methods available on all repositories.
886
+ *
887
+ * Transaction/batch context is automatically detected from AsyncContext -
888
+ * no need to pass context explicitly.
889
+ */
890
+ type BaseRepositoryMethods<Model, Path extends string> = {
891
+ /**
892
+ * Get a single document by ID.
893
+ * Automatically uses transaction context if called within runTransaction().
894
+ *
895
+ * @param params - Path parameters for nested collections
896
+ * @param id - Document ID
897
+ */
898
+ get(params: ExtractPathParams<Path>, id: string): Promise<Model | null>;
899
+ /**
900
+ * Find documents matching a query.
901
+ * Automatically uses transaction context if called within runTransaction().
902
+ *
903
+ * @param params - Path parameters for nested collections
904
+ * @param queryFn - Optional query builder function
905
+ */
906
+ find(params: ExtractPathParams<Path>, queryFn?: QueryFn<Model>): Promise<Model[]>;
907
+ /**
908
+ * Save a model (create or overwrite entire document).
909
+ * Automatically uses transaction/batch context if called within runTransaction() or writeBatch().
910
+ *
911
+ * @param params - Path parameters for nested collections
912
+ * @param model - Model instance to save
913
+ */
914
+ save(params: ExtractPathParams<Path>, model: Model): Promise<void>;
915
+ /**
916
+ * Update specific fields using Firestore dot-notation.
917
+ * Automatically uses transaction/batch context if called within runTransaction() or writeBatch().
918
+ *
919
+ * @param params - Path parameters for nested collections
920
+ * @param modelOrId - Model instance or document ID
921
+ * @param updates - Fields to update (supports dot-notation)
922
+ */
923
+ update(params: ExtractPathParams<Path>, modelOrId: Model | string, updates: FirestoreUpdate<Model>): Promise<void>;
924
+ /**
925
+ * Delete a document.
926
+ * Automatically uses transaction/batch context if called within runTransaction() or writeBatch().
927
+ *
928
+ * @param params - Path parameters for nested collections
929
+ * @param modelOrId - Model instance or document ID
930
+ */
931
+ delete(params: ExtractPathParams<Path>, modelOrId: Model | string): Promise<void>;
932
+ };
933
+ /**
934
+ * Primitive types that should not be recursed into
935
+ */
936
+ type Primitive = string | number | boolean | bigint | symbol | null | undefined | Date;
937
+ /**
938
+ * Generate all valid dot-notation paths from a type.
939
+ * Handles nested objects and optional properties.
940
+ *
941
+ * @example
942
+ * type User = { name: string; address?: { city: string; zip: number } };
943
+ * type Paths = DotPaths<User>; // 'name' | 'address' | 'address.city' | 'address.zip'
944
+ */
945
+ type DotPaths<T, Prefix extends string = ''> = T extends Primitive ? never : T extends any[] ? Prefix extends '' ? never : never : T extends object ? { [K in keyof T & string]: `${Prefix}${K}` | (NonNullable<T[K]> extends Primitive ? never : NonNullable<T[K]> extends any[] ? never : DotPaths<NonNullable<T[K]>, `${Prefix}${K}.`>) }[keyof T & string] : never;
946
+ /**
947
+ * Get the value type at a specific dot-notation path.
948
+ *
949
+ * @example
950
+ * type User = { address: { zip: number } };
951
+ * type ZipType = PathValue<User, 'address.zip'>; // number
952
+ */
953
+ type PathValue<T, P$1 extends string> = P$1 extends `${infer K}.${infer Rest}` ? K extends keyof T ? PathValue<NonNullable<T[K]>, Rest> : never : P$1 extends keyof T ? T[P$1] : never;
954
+ /**
955
+ * Firestore-style update object where keys are dot-notation paths
956
+ * and values are type-checked against the path's type.
957
+ *
958
+ * @example
959
+ * type User = { name: string; address: { zip: number } };
960
+ * const update: FirestoreUpdate<User> = {
961
+ * name: 'Bob', // ✓ valid
962
+ * 'address.zip': 12345, // ✓ valid
963
+ * 'address.zip': 'bad', // ✗ type error
964
+ * };
965
+ */
966
+ type FirestoreUpdate<T> = { [P in DotPaths<T>]?: PathValue<T, P> };
967
+ /**
968
+ * Extract path parameters from a Firestore path string.
969
+ *
970
+ * @example
971
+ * type Params = ExtractPathParams<'organizations/{organization}/users/{user}'>;
972
+ * // { organization: string; user: string }
973
+ */
974
+ type ExtractPathParams<T extends string> = string extends T ? Record<string, string> : T extends `${string}{${infer Param}}${infer Rest}` ? { [K in Param]: string } & ExtractPathParams<Rest> : {};
975
+ /**
976
+ * Check if path params are required (not an empty object)
977
+ */
978
+ type HasPathParams<T extends string> = keyof ExtractPathParams<T> extends never ? false : true;
979
+ /**
980
+ * Type-safe query builder interface.
981
+ * Wraps Firestore query methods with typed field names.
982
+ */
983
+ interface TypedQueryBuilder<T> {
984
+ where<K$1 extends DotPaths<T>>(field: K$1, op: WhereFilterOp, value: PathValue<T, K$1>): TypedQueryBuilder<T>;
985
+ orderBy(field: DotPaths<T>, direction?: OrderByDirection): TypedQueryBuilder<T>;
986
+ limit(count: number): TypedQueryBuilder<T>;
987
+ startAt(...values: unknown[]): TypedQueryBuilder<T>;
988
+ startAfter(...values: unknown[]): TypedQueryBuilder<T>;
989
+ endAt(...values: unknown[]): TypedQueryBuilder<T>;
990
+ endBefore(...values: unknown[]): TypedQueryBuilder<T>;
991
+ }
992
+ /**
993
+ * Query function type for find() method
994
+ */
995
+ type QueryFn<T> = (query: TypedQueryBuilder<T>) => TypedQueryBuilder<T>;
996
+ //#endregion
997
+ //#region src/repository.d.ts
998
+ declare function repository<Model, Path extends string>(config: RepositoryConfig<Model, Path>): Type<BaseRepositoryMethods<Model, Path>>;
999
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods>>;
1000
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods>>;
1001
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods>>;
1002
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods>>;
1003
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary, F5Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>, f5: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F5Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods & F5Methods>>;
1004
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary, F5Methods extends RepositoryMethodsDictionary, F6Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>, f5: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F5Methods>>, f6: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F6Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods & F5Methods & F6Methods>>;
1005
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary, F5Methods extends RepositoryMethodsDictionary, F6Methods extends RepositoryMethodsDictionary, F7Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>, f5: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F5Methods>>, f6: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F6Methods>>, f7: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F7Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods & F5Methods & F6Methods & F7Methods>>;
1006
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary, F5Methods extends RepositoryMethodsDictionary, F6Methods extends RepositoryMethodsDictionary, F7Methods extends RepositoryMethodsDictionary, F8Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>, f5: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F5Methods>>, f6: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F6Methods>>, f7: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F7Methods>>, f8: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F8Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods & F5Methods & F6Methods & F7Methods & F8Methods>>;
1007
+ declare function repository<Model, Path extends string, F1Methods extends RepositoryMethodsDictionary, F2Methods extends RepositoryMethodsDictionary, F3Methods extends RepositoryMethodsDictionary, F4Methods extends RepositoryMethodsDictionary, F5Methods extends RepositoryMethodsDictionary, F6Methods extends RepositoryMethodsDictionary, F7Methods extends RepositoryMethodsDictionary, F8Methods extends RepositoryMethodsDictionary, F9Methods extends RepositoryMethodsDictionary>(config: RepositoryConfig<Model, Path>, f1: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F1Methods>>, f2: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F2Methods>>, f3: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F3Methods>>, f4: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F4Methods>>, f5: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F5Methods>>, f6: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F6Methods>>, f7: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F7Methods>>, f8: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F8Methods>>, f9: RepositoryFeature<RepositoryFeatureResult<Model, Path>, RepositoryFeatureResult<Model, Path, F9Methods>>): Type<Prettify<BaseRepositoryMethods<Model, Path> & F1Methods & F2Methods & F3Methods & F4Methods & F5Methods & F6Methods & F7Methods & F8Methods & F9Methods>>;
1008
+ //#endregion
1009
+ //#region src/repository.with-methods.d.ts
1010
+ /**
1011
+ * Add custom methods to a repository
1012
+ */
1013
+ declare function withMethods<Model, Path extends string, BaseMethods extends RepositoryMethodsDictionary, NewMethods extends RepositoryMethodsDictionary>(methodsFactory: (repo: InnerRepository<Model, Path, BaseMethods>) => NewMethods): RepositoryFeature<RepositoryFeatureResult<Model, Path, BaseMethods>, RepositoryFeatureResult<Model, Path, BaseMethods & NewMethods>>;
1014
+ //#endregion
1015
+ //#region src/transaction.d.ts
1016
+ /**
1017
+ * Run operations within a Firestore transaction.
1018
+ *
1019
+ * Transactions provide:
1020
+ * - Atomic reads and writes across multiple repositories
1021
+ * - Automatic retry on contention (up to maxAttempts)
1022
+ * - Consistent view of data (all reads see same snapshot)
1023
+ * - All-or-nothing semantics (all writes succeed or all fail)
1024
+ *
1025
+ * The transaction context is **automatically propagated** to all repository
1026
+ * methods called within the transaction function - no need to pass context explicitly.
1027
+ *
1028
+ * @example
1029
+ * ```typescript
1030
+ * // Transfer funds between accounts atomically
1031
+ * const result = await runTransaction(async () => {
1032
+ * const fromAccount = await AccountRepo.get({}, fromId);
1033
+ * const toAccount = await AccountRepo.get({}, toId);
1034
+ *
1035
+ * if (!fromAccount || !toAccount) throw new Error('Account not found');
1036
+ * if (fromAccount.balance < amount) throw new Error('Insufficient funds');
1037
+ *
1038
+ * await AccountRepo.update({}, fromId, {
1039
+ * balance: fromAccount.balance - amount
1040
+ * });
1041
+ *
1042
+ * await AccountRepo.update({}, toId, {
1043
+ * balance: toAccount.balance + amount
1044
+ * });
1045
+ *
1046
+ * return { newBalance: fromAccount.balance - amount };
1047
+ * });
1048
+ * ```
1049
+ *
1050
+ * @example
1051
+ * ```typescript
1052
+ * // Cross-repository transaction
1053
+ * await runTransaction(async () => {
1054
+ * const order = await OrderRepo.get({}, orderId);
1055
+ * const user = await UserRepo.get({}, order.userId);
1056
+ *
1057
+ * await OrderRepo.update({}, orderId, { status: 'paid' });
1058
+ * await UserRepo.update({}, user.id, {
1059
+ * balance: user.balance - order.total
1060
+ * });
1061
+ * });
1062
+ * ```
1063
+ *
1064
+ * @param fn - Async function to run within the transaction
1065
+ * @param options - Transaction options (maxAttempts, etc.)
1066
+ * @returns Result of the transaction function
1067
+ */
1068
+ declare function runTransaction<T>(fn: () => Promise<T>, options?: TransactionOptions): Promise<T>;
1069
+ //#endregion
1070
+ export { AdapterNotInitializedError, AuditConfig, AuditOptions, BaseRepositoryMethods, BatchContext, CollectionReference, DEFAULT_AUDIT, DEFAULT_STATUS, DEFAULT_TIMESTAMPS, DocumentReference, DocumentSnapshot, DotPaths, EmptyFeatureResult, ExtractPathParams, FeatureHooks, FirestoreAdapter, FirestoreError, FirestoreTimestamp, FirestoreUpdate, FyreStackError, HasPathParams, InferModel, InnerModel, InnerRepository, MAX_BATCH_SIZE, MODEL_METADATA, MODEL_SCHEMA, MethodsDictionary, ModelError, ModelFeature, ModelFeatureResult, ModelHookContext, ModelHooks, ModelInstance, ModelMetadata, NotFoundError, OperationContext, OrderByDirection, PathParamError, PathValue, QueryFn, QueryReference, QuerySnapshot, RepositoryConfig, RepositoryFeature, RepositoryFeatureResult, RepositoryHookContext, RepositoryHooks, RepositoryMethodsDictionary, ServerTimestampSentinel, StatusConfig, StatusOptions, TimestampProps, TimestampValue, TimestampsConfig, TimestampsOptions, Transaction, TransactionContext, TransactionOptions, TypedQueryBuilder, ValidationError, ValidationIssue, ValidationResult, WhereFilterOp, WriteBatch, _resetFirestoreAdapter, createFeatureMetadata, getAuditConfig, getCurrentBatch, getCurrentContext, getCurrentTransaction, getFeatureConfig, getFirestoreAdapter, getModelHooks, getModelMetadata, getRepositoryHooks, getStatusConfig, getTimestampsConfig, hasAudit, hasFeature, hasRepositoryHooks, hasStatus, hasTimestamps, isBatchContext, isInBatch, isInTransaction, isServerTimestamp, isTransactionContext, isValidResult, mergeFeatureHooks, mergeModelHooks, mergeRepositoryHooks, model, repository, runTransaction, runWithBatch, runWithTransaction, setFirestoreAdapter, withMethods, withSchema, withTimestamps, writeBatch, writeChunkedBatch };
1071
+ //# sourceMappingURL=index.d.cts.map