@asaidimu/utils-workspace 2.1.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { QueryFilter, PaginationOptions } from '@asaidimu/query';
2
- import { SchemaDefinition, SchemaChange, DataTransform } from '@asaidimu/anansi';
2
+ import { IndexDefinition, SchemaDefinition, SchemaChange, DataTransform } from '@asaidimu/anansi';
3
3
 
4
4
  type UUID = string;
5
5
  type Timestamp = string;
@@ -539,14 +539,78 @@ interface TranscriptWindow {
539
539
  hasMore: boolean;
540
540
  }
541
541
 
542
+ /**
543
+ * Buffers write operations across one or more stores and commits them atomically.
544
+ *
545
+ * ## How atomicity works
546
+ *
547
+ * ### IndexedDB stores (same database)
548
+ * At commit time, TransactionContext collects the names of every IDB store that
549
+ * received operations, then opens a **single** `IDBTransaction` spanning all of
550
+ * them via `ConnectionManager.openTransaction`. Each store's `executeInTransaction`
551
+ * receives that shared transaction object and performs its writes against it
552
+ * without opening a new transaction of its own. IDB commits or aborts the
553
+ * entire multi-store transaction as one unit.
554
+ *
555
+ * ### MemoryStore
556
+ * MemoryStore's `executeInTransaction` receives `null` for the shared transaction.
557
+ * It applies ops against an internal staging map and returns. If a later
558
+ * participant fails, TransactionContext calls `rollbackMemory` on each
559
+ * MemoryStore that already applied its staged ops. MemoryStore restores its
560
+ * pre-transaction snapshot.
561
+ *
562
+ * ### Mixed (IDB + Memory in the same transaction)
563
+ * All IDB stores are committed first as a single atomic IDB transaction, then
564
+ * each MemoryStore is committed. If a MemoryStore fails after IDB has already
565
+ * committed, the IDB side cannot be rolled back — this is an inherent limitation
566
+ * of mixing two different storage engines. In practice the schema store is
567
+ * always MemoryStore-or-IDB consistently, so mixed transactions should not arise
568
+ * in normal usage.
569
+ */
542
570
  declare class TransactionContext {
543
571
  readonly id: string;
544
- private buffer;
545
- private committed;
572
+ /**
573
+ * Flat list of every operation staged so far, in the order they were added.
574
+ * We keep the store reference alongside the op so commit() can group them.
575
+ */
576
+ private staged;
577
+ private done;
546
578
  constructor();
547
- addOp(store: Store<any>, type: "put" | "delete", data: any): void;
579
+ /**
580
+ * Stages a single write operation against a store.
581
+ * Does NOT touch the store — no I/O happens until commit().
582
+ */
583
+ addOp<T extends Record<string, any>>(store: Store<T>, type: "put" | "delete" | "add", data: any): Promise<void>;
584
+ /**
585
+ * Commits all staged operations atomically.
586
+ *
587
+ * For IDB stores: opens one shared IDBTransaction across all participating
588
+ * stores, then dispatches ops to each store's executeInTransaction.
589
+ * For MemoryStores: dispatches sequentially; rolls back on failure.
590
+ */
548
591
  commit(): Promise<void>;
592
+ /**
593
+ * Discards all staged operations. No I/O has occurred so there is nothing
594
+ * to undo — we simply clear the buffer.
595
+ */
549
596
  rollback(): void;
597
+ /**
598
+ * Opens ONE IDBTransaction across all participating IDB stores and lets
599
+ * each store execute its ops against the shared transaction handle.
600
+ *
601
+ * We obtain the IDBDatabase from the first store (they all share the same
602
+ * ConnectionManager / database) and open the transaction ourselves so that
603
+ * the commit/abort lifecycle belongs entirely to this method.
604
+ */
605
+ private commitIDB;
606
+ /**
607
+ * Commits MemoryStore groups sequentially.
608
+ * Maintains a list of stores that have already applied their ops; if any
609
+ * store throws, all previously-applied stores are rolled back via the
610
+ * store-level `_rollbackMemory(snapshot)` escape hatch.
611
+ */
612
+ private commitMemory;
613
+ completed(): boolean;
550
614
  }
551
615
 
552
616
  interface CursorCallbackResult<T> {
@@ -560,8 +624,9 @@ interface CursorCallbackResult<T> {
560
624
  * @template T - The type of records stored.
561
625
  * @param value - The current record value (cloned, not a live reference).
562
626
  * @param key - The key (ID) of the current record.
563
- * @param cursor - The underlying cursor object (implementationspecific; may be `null` in memory adapters).
564
- * @returns A promise that resolves to an object indicating whether iteration should stop, and an optional offset to advance.
627
+ * @param cursor - The underlying cursor object (implementation-specific; may be `null` in memory adapters).
628
+ * @returns A promise resolving to an object indicating whether iteration should stop,
629
+ * and an optional offset to advance.
565
630
  */
566
631
  type CursorCallback<T> = (value: T, key: string | number, cursor: any) => Promise<CursorCallbackResult<T>>;
567
632
  /**
@@ -573,123 +638,100 @@ interface StoreKeyRange {
573
638
  lowerOpen?: boolean;
574
639
  upperOpen?: boolean;
575
640
  }
641
+ /**
642
+ * A single buffered operation staged inside a TransactionContext.
643
+ * Kept intentionally minimal — the context only needs to know what to
644
+ * replay against a store during commit.
645
+ */
646
+ type BufferedOperation<T> = {
647
+ type: "add" | "put";
648
+ data: T | T[];
649
+ } | {
650
+ type: "delete";
651
+ data: string | number | (string | number)[];
652
+ };
576
653
  /**
577
654
  * Storage adapter interface for a single object store (collection).
578
655
  *
579
- * This interface abstracts all low‑level persistence operations, allowing
580
- * different backends (IndexedDB, memory, remote, etc.) to be used interchangeably.
581
- * All methods return promises and operate on clones of data to prevent
582
- * unintended mutations.
656
+ * Stores own their indexes. Index lifecycle (create, drop) and index-aware reads
657
+ * (findByIndex) are part of this contract so that both MemoryStore and IndexedDBStore
658
+ * implement them natively MemoryStore via in-memory index maps, IndexedDB via its
659
+ * native index mechanism.
583
660
  *
584
- * @template T - The type of objects stored in this store. Must include the key path property.
661
+ * @template T - The type of objects stored. Must include the key path property.
585
662
  */
586
- interface Store<T = any> {
663
+ interface Store<T extends Record<string, any> = Record<string, any>> {
664
+ /**
665
+ * Returns the name of this store (the IDB object store / collection name).
666
+ * Used by TransactionContext to group operations and open a correctly-scoped
667
+ * multi-store IDB transaction at commit time.
668
+ */
669
+ name(): string;
670
+ /**
671
+ * Opens the store, ensuring underlying storage structures exist.
672
+ */
673
+ open(): Promise<void>;
587
674
  /**
588
675
  * Adds one or more records to the store.
589
- *
590
676
  * If a record does not have a value for the store's key path, an automatic
591
- * key (e.g., auto‑incremented number) may be assigned. The store's key path
592
- * property is then updated on the added record(s).
593
- *
594
- * @param data - A single record or an array of records to add.
595
- * @returns A promise that resolves to:
596
- * - the key(s) of the added record(s) – a single key if `data` was a single record,
597
- * or an array of keys if `data` was an array.
598
- * @throws {Error} If any record lacks the key path property and auto‑keying is not supported,
599
- * or if a record with the same key already exists.
677
+ * key may be assigned. Throws if a record with the same key already exists.
600
678
  */
601
679
  add(data: T | T[]): Promise<string | number | (string | number)[]>;
602
680
  /**
603
- * Removes all records from the store.
604
- *
605
- * @returns A promise that resolves when the store is cleared.
606
- * @throws {Error} If the operation fails (e.g., store is closed).
681
+ * Removes all records from the store without destroying index structures.
607
682
  */
608
683
  clear(): Promise<void>;
609
684
  /**
610
685
  * Returns the total number of records in the store.
611
- *
612
- * @returns A promise that resolves to the record count.
613
- * @throws {Error} If the operation fails.
614
686
  */
615
687
  count(): Promise<number>;
616
688
  /**
617
689
  * Deletes one or more records by their keys.
618
- *
619
- * @param id - A single key or an array of keys to delete.
620
- * @returns A promise that resolves when the records are deleted.
621
- * @throws {Error} If any key is `undefined` or the operation fails.
622
690
  */
623
691
  delete(id: string | number | (string | number)[]): Promise<void>;
624
692
  /**
625
693
  * Retrieves a single record by its primary key.
626
- *
627
- * @param id - The key of the record to retrieve.
628
- * @returns A promise that resolves to the record (cloned) if found, otherwise `undefined`.
629
- * @throws {Error} If the key is `undefined` or the operation fails.
630
694
  */
631
695
  getById(id: string | number): Promise<T | undefined>;
632
696
  /**
633
- * Retrieves a single record by an index and index key.
697
+ * Retrieves the first record matching an exact index key (point lookup).
698
+ * Useful for unique indexes — returns the single matching record or undefined.
634
699
  *
635
- * @param index - The name of the index to query.
636
- * @param key - The exact key value to look up in the index.
637
- * @returns A promise that resolves to the first matching record (cloned), or `undefined` if none.
638
- * @throws {Error} If the index does not exist, the key is `undefined`, or the operation fails.
700
+ * @param indexName - The name of the index to query.
701
+ * @param key - The exact key value to look up.
639
702
  */
640
- getByIndex(index: string, key: any): Promise<T | undefined>;
703
+ getByIndex(indexName: string, key: any): Promise<T | undefined>;
641
704
  /**
642
- * Retrieves multiple records from an index, optionally within a key range.
705
+ * Retrieves all records from a named index, optionally filtered by a key range.
706
+ * Use this for range scans over an index (e.g. all records where age >= 18).
643
707
  *
644
- * @param index - The name of the index to query.
645
- * @param keyRange - Optional `StoreKeyRange` to filter results. If omitted, all records are returned.
646
- * @returns A promise that resolves to an array of matching records (each cloned).
647
- * @throws {Error} If the index does not exist or the operation fails.
708
+ * @param indexName - The name of the index to query.
709
+ * @param keyRange - Optional range to filter results.
648
710
  */
649
- getByKeyRange(index: string, keyRange?: StoreKeyRange): Promise<T[]>;
711
+ getByKeyRange(indexName: string, keyRange?: StoreKeyRange): Promise<T[]>;
650
712
  /**
651
- * Retrieves all records from the store.
652
- *
653
- * @returns A promise that resolves to an array of all records (each cloned).
654
- * @throws {Error} If the operation fails.
713
+ * Retrieves all records from the store without index involvement.
655
714
  */
656
715
  getAll(): Promise<T[]>;
657
716
  /**
658
- * Inserts or replaces a record.
659
- *
660
- * If a record with the same key already exists, it is replaced.
661
- * The record must contain the store's key path property.
662
- *
663
- * @param data - The record to store.
664
- * @returns A promise that resolves to the key of the stored record.
665
- * @throws {Error} If the record lacks the key path property or the operation fails.
717
+ * Inserts or replaces a record. Validates OCC if a record with the same key exists.
666
718
  */
667
719
  put(data: T): Promise<string | number>;
668
720
  /**
669
721
  * Iterates over records using a cursor, allowing early termination and skipping.
670
722
  *
671
- * The callback is invoked for each record in iteration order. The callback
672
- * can control the iteration by returning `{ done: true }` to stop, or
673
- * `{ offset: n }` to skip ahead `n` records.
674
- *
675
- * @param callback - Function called for each record.
676
- * @param direction - Iteration direction: `"forward"` (ascending keys) or `"backward"` (descending keys).
677
- * @param keyRange - An optional StoreKeyRange to start from specific points.
678
- * @returns A promise that resolves to the last record processed (or `null` if none).
679
- * @throws {Error} If the callback throws or the operation fails.
723
+ * @param callback - Invoked for each record; return `{ done: true }` to stop,
724
+ * `{ offset: n }` to skip ahead n records.
725
+ * @param direction - Iteration order.
726
+ * @param keyRange - Optional range to restrict iteration.
680
727
  */
681
728
  cursor(callback: CursorCallback<T>, direction?: "forward" | "backward", keyRange?: StoreKeyRange): Promise<T | null>;
682
729
  /**
683
- * Executes a batch of write operations atomically.
730
+ * Executes a batch of write operations atomically within this store.
731
+ * All operations succeed or fail together.
684
732
  *
685
- * All operations in the batch succeed or fail together. This is useful for
686
- * maintaining consistency when multiple writes are required.
687
- *
688
- * @param operations - An array of operations. Each operation can be:
689
- * - `{ type: "add" | "put", data: T | T[] }`
690
- * - `{ type: "delete", data: string | number | (string | number)[] }`
691
- * @returns A promise that resolves when the batch is committed.
692
- * @throws {Error} If any operation fails or the batch cannot be completed.
733
+ * Used for standalone (single-store) atomic writes. For cross-store atomicity,
734
+ * use executeInTransaction instead.
693
735
  */
694
736
  batch(operations: Array<{
695
737
  type: "add" | "put";
@@ -698,44 +740,81 @@ interface Store<T = any> {
698
740
  type: "delete";
699
741
  data: string | number | (string | number)[];
700
742
  }>): Promise<void>;
701
- open(): Promise<void>;
743
+ /**
744
+ * Registers a new index on the store. Idempotent — no-op if the index already exists.
745
+ * For IndexedDB, this triggers a database version upgrade.
746
+ * For MemoryStore, this builds the index map from existing records.
747
+ *
748
+ * @param definition - The full index definition from the schema.
749
+ */
750
+ createIndex(definition: IndexDefinition): Promise<void>;
751
+ /**
752
+ * Removes a named index from the store.
753
+ * For IndexedDB, this triggers a database version upgrade.
754
+ * For MemoryStore, this drops the in-memory index map.
755
+ *
756
+ * @param name - The index name as declared in IndexDefinition.name.
757
+ */
758
+ dropIndex(name: string): Promise<void>;
759
+ /**
760
+ * Returns all records matching an exact index key.
761
+ * Unlike getByIndex (which returns only the first match), this returns all matches —
762
+ * essential for non-unique indexes where multiple records share the same indexed value.
763
+ *
764
+ * @param indexName - The name of the index to query.
765
+ * @param value - The exact value to look up.
766
+ */
767
+ findByIndex(indexName: string, value: any): Promise<T[]>;
768
+ /**
769
+ * Executes a set of buffered operations as part of a cross-store atomic transaction.
770
+ *
771
+ * For IndexedDBStore: `sharedTx` is the single IDBTransaction opened across all
772
+ * participating stores. Operations are applied directly to `sharedTx.objectStore(name)`
773
+ * without opening a new transaction — IDB commits or aborts the whole thing atomically.
774
+ *
775
+ * For MemoryStore: `sharedTx` is null. The store applies ops against its own staging
776
+ * area. The caller (TransactionContext) is responsible for coordinating rollback across
777
+ * all MemoryStores if any participant fails.
778
+ *
779
+ * This method must NOT open, commit, or abort any transaction itself.
780
+ *
781
+ * @param ops - The buffered operations to apply.
782
+ * @param sharedTx - The shared IDBTransaction (IndexedDB only), or null (MemoryStore).
783
+ */
784
+ executeInTransaction(ops: BufferedOperation<T>[], sharedTx: IDBTransaction | null): Promise<void>;
702
785
  }
703
786
  interface Collection<T> {
704
787
  /**
705
788
  * Finds a single document matching the query.
706
- * @param query - The query to execute.
707
- * @returns A promise resolving to the matching document or `null` if not found.
708
789
  */
709
790
  find: (query: QueryFilter<T>) => Promise<Document<T> | null>;
710
791
  /**
711
- * Lists documents based on the provided query.
712
- * @param query - The query to list documents (supports pagination and sorting).
713
- * @returns A promise resolving to an array of documents.
792
+ * Lists documents with pagination. Returns an AsyncIterator so consumers can
793
+ * wrap it in their own iteration protocol (e.g. for-await-of via AsyncIterable).
714
794
  */
715
795
  list: (query: PaginationOptions) => Promise<AsyncIterator<Document<T>[]>>;
716
796
  /**
717
- * Filters documents based on the provided query.
718
- * @param query - The query to filter documents.
719
- * @returns A promise resolving to an array of matching documents.
797
+ * Filters all documents matching the query.
720
798
  */
721
799
  filter: (query: QueryFilter<T>) => Promise<Document<T>[]>;
722
800
  /**
723
- * Creates a new document in the schema.
801
+ * Creates a new document in the collection.
802
+ *
803
+ * When a TransactionContext is provided the initial store.add is buffered into
804
+ * the transaction rather than written immediately. The document is returned in
805
+ * its fully initialised in-memory state regardless — callers can use it before
806
+ * the transaction commits.
807
+ *
724
808
  * @param initial - The initial data for the document.
725
- * @returns A promise resolving to the created document.
809
+ * @param tx - Optional transaction to buffer the write into.
726
810
  */
727
- create: (initial: T) => Promise<Document<T>>;
811
+ create: (initial: T, tx?: TransactionContext) => Promise<Document<T>>;
728
812
  /**
729
- * Subscribes to schema-level events (e.g., "create", "update", "delete", "access").
730
- * @param event - The event type to subscribe to.
731
- * @param callback - The function to call when the event occurs.
732
- * @returns A promise resolving to an unsubscribe function.
813
+ * Subscribes to collection-level events.
733
814
  */
734
- subscribe: (event: CollectionEventType | TelemetryEventType, callback: (event: CollectionEvent<T> | TelemetryEvent) => void) => Promise<() => void>;
815
+ subscribe: (event: CollectionEventType | TelemetryEventType, callback: (event: CollectionEvent<T> | TelemetryEvent) => void) => () => void;
735
816
  /**
736
- * Validate data
737
- * @param data - The data to validate
738
- * @returns An object containing validation results
817
+ * Validates data against the collection's schema.
739
818
  */
740
819
  validate(data: Record<string, any>): Promise<{
741
820
  value?: any;
@@ -744,9 +823,10 @@ interface Collection<T> {
744
823
  path: Array<string>;
745
824
  }>;
746
825
  }>;
826
+ invalidate(): void;
747
827
  }
748
828
  /**
749
- * Event payload for DocumentCursor events.
829
+ * Event payload for Collection events.
750
830
  */
751
831
  type CollectionEventType = "document:create" | "collection:read" | "migration:start" | "migration:end";
752
832
  type CollectionEvent<T> = {
@@ -759,91 +839,49 @@ type CollectionEvent<T> = {
759
839
  };
760
840
  interface Database {
761
841
  /**
762
- * Accesses a schema model by name.
763
- * @param schemaName - The name of the schema to access.
764
- * @returns A promise resolving to the schema's DocumentCursor.
765
- * @throws DatabaseError
842
+ * Opens an existing collection by name.
766
843
  */
767
844
  collection: <T>(schemaName: string) => Promise<Collection<T>>;
768
845
  /**
769
- * Creates a new schema model.
770
- * @param schema - The schema definition.
771
- * @returns A promise resolving to the created schema's DocumentCursor.
772
- * @throws DatabaseError
846
+ * Creates a new collection from a schema definition.
773
847
  */
774
848
  createCollection: <T>(schema: SchemaDefinition) => Promise<Collection<T>>;
775
849
  /**
776
- * Deletes a schema by name.
777
- * @param schemaName - The name of the schema to delete.
778
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
779
- * @throws DatabaseError
850
+ * Deletes a collection and its schema record.
780
851
  */
781
852
  deleteCollection: (schemaName: string) => Promise<boolean>;
782
853
  /**
783
- * Updates an existing schema.
784
- * @param schema - The updated schema definition.
785
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
786
- * @throws DatabaseError
854
+ * Updates an existing collection's schema record.
787
855
  */
788
856
  updateCollection: (schema: SchemaDefinition) => Promise<boolean>;
789
857
  /**
790
- * Migrates an existing collection's data and updates its schema definition metadata.
791
- * This function processes data in a streaming fashion to prevent loading
792
- * the entire collection into memory.
793
- *
794
- * It will:
795
- * 1. Verify the target collection exists.
796
- * 2. Retrieve the collection's current schema definition from a metadata store ($index).
797
- * 3. Initialize a `MigrationEngine` with this schema.
798
- * 4. Allow a callback to define specific data transformations using the `MigrationEngine`.
799
- * 5. **Crucially, it uses `migrationEngine.dryRun()` to get the `newSchema` that results**
800
- * **from the transformations defined in the callback.**
801
- * 6. Execute these transformations by streaming data from the collection,
802
- * through the `MigrationEngine`, and back into the same collection.
803
- * 7. Finally, update the schema definition for the collection in the `$index` metadata store
804
- * to reflect this `newSchema`.
805
- * All these steps for data and metadata updates happen within a single atomic IndexedDB transaction.
806
- *
807
- * Note: This function focuses solely on *data transformation* and *metadata updates*.
808
- * It does NOT handle structural IndexedDB changes like adding/removing physical indexes or object stores,
809
- * which still require an `onupgradeneeded` event (i.e., a database version upgrade).
810
- *
811
- * @param name - The name of the collection (IndexedDB object store) to migrate.
812
- * @param {Object} opts - Options for the new migration
813
- * @param {SchemaChange<any>[]} opts.changes - Array of schema changes
814
- * @param {string} opts.description - Description of the migration
815
- * @param {SchemaChange<any>[]} [opts.rollback] - Optional rollback changes
816
- * @param {DataTransform<any, any>} [opts.transform] - Optional data transform
817
- * @returns A Promise resolving to `true` if the migration completes successfully,
818
- * @throws {DatabaseError} If the collection does not exist, its schema metadata is missing,
819
- * or any IndexedDB operation/streaming fails critically.
858
+ * Migrates an existing collection's data and schema definition.
859
+ * Processes data in a streaming fashion to avoid loading the full collection
860
+ * into memory.
820
861
  */
821
- migrateCollection: (name: string, opts: CollectionMigrationOptions, batchSize?: number) => Promise<boolean>;
862
+ migrateCollection: <T>(name: string, opts: CollectionMigrationOptions, batchSize?: number) => Promise<Collection<T>>;
822
863
  /**
823
- * Subscribes to database-level events (e.g., "schemaAdded", "schemaDeleted", "schemaAccessed", "migrate").
824
- * @param event - The event type to subscribe to.
825
- * @param callback - The function to call when the event occurs.
826
- * @returns A promise resolving to an unsubscribe function.
864
+ * Executes a callback within a TransactionContext.
865
+ * Writes buffered inside the callback are flushed atomically on commit.
866
+ * If the callback throws, the buffer is discarded (no writes are flushed).
827
867
  */
828
- subscribe: (event: DatabaseEventType | "telemetry", callback: (event: DatabaseEvent | TelemetryEvent) => void) => Promise<() => void>;
868
+ transaction: (callback: (tx: TransactionContext) => Promise<void>) => Promise<void>;
829
869
  /**
830
- * Closes the connection to the database
870
+ * Subscribes to database-level events.
871
+ */
872
+ subscribe: (event: DatabaseEventType | "telemetry", callback: (event: DatabaseEvent | TelemetryEvent) => void) => () => void;
873
+ /**
874
+ * Releases in-memory references and event bus subscriptions.
875
+ * Does not delete any persisted data.
831
876
  */
832
877
  close: () => void;
878
+ clear: () => Promise<void>;
833
879
  /**
834
- * Ensures a collection exists; creates it if it doesn't.
835
- * Idempotent – safe to call multiple times.
836
- * @param schema - The schema definition for the collection.
837
- * @returns A promise that resolves when the collection exists.
838
- * @throws {DatabaseError} If validation fails or an unexpected error occurs.
839
- */
880
+ * Ensures a collection exists; creates it if it doesn't. Idempotent.
881
+ */
840
882
  ensureCollection: (schema: SchemaDefinition) => Promise<void>;
841
883
  /**
842
- * Ensures multiple collections exist; creates any that don't.
843
- * Idempotent – safe to call multiple times.
844
- * @param schemas - An array of schema definitions.
845
- * @returns A promise that resolves when all collections exist.
846
- * @throws {DatabaseError} If any schema validation fails or an unexpected error occurs.
884
+ * Ensures multiple collections exist; creates any that don't. Idempotent.
847
885
  */
848
886
  setupCollections: (schemas: SchemaDefinition[]) => Promise<void>;
849
887
  }
@@ -853,9 +891,6 @@ type CollectionMigrationOptions = {
853
891
  rollback?: SchemaChange<any>[];
854
892
  transform?: string | DataTransform<any, any>;
855
893
  };
856
- /**
857
- * Event payload for Database events.
858
- */
859
894
  type DatabaseEventType = "collection:create" | "collection:delete" | "collection:update" | "collection:read" | "migrate";
860
895
  type DatabaseEvent = {
861
896
  type: DatabaseEventType;
@@ -865,60 +900,17 @@ type DatabaseEvent = {
865
900
  type Document<T> = {
866
901
  readonly [K in keyof T]: T[K];
867
902
  } & {
868
- /**
869
- * Unique identifier for the document (assigned automatically if not provided).
870
- */
871
903
  $id?: string;
872
- /**
873
- * Timestamp of document creation (ISO string or Date).
874
- */
875
904
  $created?: string | Date;
876
- /**
877
- * Timestamp of last document update (ISO string or Date).
878
- */
879
905
  $updated?: string | Date;
880
- /**
881
- * Version number incremented on each change (used for optimistic concurrency control).
882
- */
883
906
  $version?: number;
884
- /**
885
- * Fetches the latest data from the database and updates the document instance.
886
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
887
- */
888
907
  read: () => Promise<boolean>;
889
- /**
890
- * Saves the current document state to the database.
891
- * Normally called automatically by `update()` or `delete()`, but can be used manually.
892
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
893
- */
894
908
  save: (tx?: TransactionContext) => Promise<boolean>;
895
- /**
896
- * Updates the document with the provided properties.
897
- * @param props - Partial object containing the fields to update.
898
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
899
- */
900
- update: (props: Partial<T>) => Promise<boolean>;
901
- /**
902
- * Deletes the document from the database.
903
- * @returns A promise resolving to `true` if successful, or `false` if an error occurs.
904
- */
905
- delete: () => Promise<boolean>;
906
- /**
907
- * Subscribes to document events (e.g., "update", "delete", "access").
908
- * @param event - The event type to subscribe to.
909
- * @param callback - The function to call when the event occurs.
910
- * @returns An unsubscribe function.
911
- */
909
+ update: (props: Partial<T>, tx?: TransactionContext) => Promise<boolean>;
910
+ delete: (tx?: TransactionContext) => Promise<boolean>;
912
911
  subscribe: (event: DocumentEventType | TelemetryEventType, callback: (event: DocumentEvent<T> | TelemetryEvent) => void) => () => void;
913
- /**
914
- * Returns a plain object containing only the user-defined data (without system fields like $id, $version, etc.).
915
- * @returns The current user data.
916
- */
917
912
  state(): T;
918
913
  };
919
- /**
920
- * Event payload for DocumentModel events.
921
- */
922
914
  type DocumentEventType = "document:create" | "document:write" | "document:update" | "document:delete" | "document:read";
923
915
  type DocumentEvent<T> = {
924
916
  type: DocumentEventType;
@@ -942,7 +934,7 @@ type TelemetryEvent = {
942
934
  document?: string;
943
935
  };
944
936
  result?: {
945
- type: 'array' | string;
937
+ type: "array" | string;
946
938
  size?: number;
947
939
  };
948
940
  error: {