@asaidimu/utils-database 3.0.0 → 3.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/README.md CHANGED
@@ -83,7 +83,7 @@ const db = await DatabaseConnection(
83
83
  enableTelemetry: true,
84
84
  predicates: {}, // custom validation predicates (optional)
85
85
  },
86
- createIndexedDbStore
86
+ createIndexedDbStore,
87
87
  );
88
88
  ```
89
89
 
@@ -171,7 +171,7 @@ await db.migrateCollection(
171
171
  },
172
172
  description: "Add active flag",
173
173
  },
174
- 100 // batch size (optional)
174
+ 100, // batch size (optional)
175
175
  );
176
176
  ```
177
177
 
@@ -199,7 +199,9 @@ const unsubDoc = doc.subscribe("document:update", (event) => {
199
199
 
200
200
  // Telemetry (when enableTelemetry: true)
201
201
  db.subscribe("telemetry", (event) => {
202
- console.log(`${event.method} took ${event.metadata.performance.durationMs}ms`);
202
+ console.log(
203
+ `${event.method} took ${event.metadata.performance.durationMs}ms`,
204
+ );
203
205
  });
204
206
  ```
205
207
 
@@ -291,10 +293,10 @@ For migrations: `migrateCollection` streams documents from the store, passes the
291
293
 
292
294
  ### Available Scripts
293
295
 
294
- | Command | Description |
295
- | ----------------- | -------------------------------------------------- |
296
- | `npm test` | Run tests once (Vitest) |
297
- | `npm run test:watch` | Run tests in watch mode |
296
+ | Command | Description |
297
+ | ---------------------- | ------------------------------------------------- |
298
+ | `npm test` | Run tests once (Vitest) |
299
+ | `npm run test:watch` | Run tests in watch mode |
298
300
  | `npm run test:browser` | Run tests in a real browser (Vitest browser mode) |
299
301
 
300
302
  ### Testing
@@ -323,12 +325,12 @@ Use the [GitHub issue tracker](https://github.com/asaidimu/erp-utils/issues) to
323
325
 
324
326
  ### Troubleshooting
325
327
 
326
- | Error | Likely cause & solution |
327
- | --------------------------------- | --------------------------------------------------------- |
328
- | `SCHEMA_NOT_FOUND` | The collection was not created. Call `createCollection` first. |
329
- | `CONFLICT` | Another operation updated the document. Re‑fetch and retry. |
330
- | `TRANSACTION_FAILED` | One of the batched writes failed. Check individual operations. |
331
- | `INVALID_DATA` | The document does not match the schema. Review validation errors. |
328
+ | Error | Likely cause & solution |
329
+ | -------------------- | ----------------------------------------------------------------- |
330
+ | `SCHEMA_NOT_FOUND` | The collection was not created. Call `createCollection` first. |
331
+ | `CONFLICT` | Another operation updated the document. Re‑fetch and retry. |
332
+ | `TRANSACTION_FAILED` | One of the batched writes failed. Check individual operations. |
333
+ | `INVALID_DATA` | The document does not match the schema. Review validation errors. |
332
334
 
333
335
  ### FAQ
334
336
 
@@ -355,6 +357,7 @@ This project is licensed under the **MIT License**. See the [LICENSE](https://gi
355
357
  ### Acknowledgments
356
358
 
357
359
  Built with ❤️ using:
360
+
358
361
  - [`@asaidimu/anansi`](https://github.com/asaidimu/anansi) – schema validation and migrations.
359
362
  - [`@standard-schema/spec`](https://github.com/standard-schema/standard-schema) – Standard Schema interoperability.
360
363
  - [`uuid`](https://github.com/uuidjs/uuid) – for v7 UUIDs.
package/index.d.mts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { QueryFilter, PaginationOptions } from '@asaidimu/query';
2
2
  import { IndexDefinition, SchemaDefinition, SchemaChange, DataTransform, PredicateMap } from '@asaidimu/anansi';
3
+ import { EventBus } from '@core/events';
3
4
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
5
 
5
6
  /**
@@ -740,6 +741,23 @@ declare const createIndexedDbStore: <T extends Record<string, any>>(config: Stor
740
741
 
741
742
  declare function DatabaseConnection(config: Omit<DatabaseConfig, "keyPath">, createStore: <T extends Record<string, any>>(config: StoreConfig, indexes: IndexDefinition[]) => Store<T>): Promise<Database>;
742
743
 
744
+ interface MiddlewareContext {
745
+ collection?: string;
746
+ documentId?: string;
747
+ operation: string;
748
+ args: any[];
749
+ eventBus?: EventBus<any>;
750
+ }
751
+ type MaybePromise<T> = T | Promise<T>;
752
+ type MiddlewareNext = () => MaybePromise<any>;
753
+ type Middleware = (ctx: MiddlewareContext, next: MiddlewareNext) => MaybePromise<any>;
754
+ declare class Pipeline {
755
+ private middlewares;
756
+ use(middleware: Middleware): void;
757
+ execute(ctx: MiddlewareContext, finalOperation: () => MaybePromise<any>): MaybePromise<any>;
758
+ wrap<T extends object>(target: T, baseContext: Partial<MiddlewareContext>): T;
759
+ }
760
+
743
761
  interface MutexOptions {
744
762
  /**
745
763
  * Maximum number of pending requests allowed in the queue.
@@ -807,76 +825,6 @@ declare class Mutex {
807
825
  pending(): number;
808
826
  }
809
827
 
810
- /**
811
- * Interface defining the shape of the EventBus.
812
- * @template TEventMap - A record mapping event names to their respective payload types.
813
- */
814
- interface EventBus<TEventMap extends Record<string, any>> {
815
- /**
816
- * Subscribes to a specific event by name.
817
- * @param eventName - The name of the event to subscribe to.
818
- * @param callback - The function to call when the event is emitted.
819
- * @returns A function to unsubscribe from the event.
820
- */
821
- subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
822
- /**
823
- * Subscribes to an event and automatically unsubscribes after it fires once.
824
- * @param eventName - The name of the event to subscribe to.
825
- * @param callback - The function to call when the event is emitted.
826
- * @returns A function to cancel the one-shot subscription before it fires.
827
- */
828
- once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
829
- /**
830
- * Emits an event with a payload to all subscribed listeners.
831
- * @param event - An object containing the event name and payload.
832
- */
833
- emit: <TEventName extends keyof TEventMap>(event: {
834
- name: TEventName;
835
- payload: TEventMap[TEventName];
836
- }) => void;
837
- /**
838
- * Retrieves metrics about event bus usage.
839
- * @returns An object containing various metrics.
840
- */
841
- metrics: () => EventMetrics;
842
- /**
843
- * Clears all subscriptions and resets metrics.
844
- * After calling clear(), the bus is fully reset and can be reused —
845
- * cross-tab communication is re-established if it was previously enabled.
846
- */
847
- clear: () => void;
848
- }
849
- /**
850
- * Interface defining the metrics tracked by the EventBus.
851
- */
852
- interface EventMetrics {
853
- /** Total number of events emitted (both sync and deferred paths). */
854
- totalEvents: number;
855
- /** Number of active subscriptions across all event names. */
856
- activeSubscriptions: number;
857
- /** Map of event names to their emission counts. */
858
- eventCounts: Map<string, number>;
859
- /** Average duration of event dispatch in milliseconds. */
860
- averageEmitDuration: number;
861
- }
862
-
863
- interface MiddlewareContext {
864
- collection?: string;
865
- documentId?: string;
866
- operation: string;
867
- args: any[];
868
- eventBus?: EventBus<any>;
869
- }
870
- type MaybePromise<T> = T | Promise<T>;
871
- type MiddlewareNext = () => MaybePromise<any>;
872
- type Middleware = (ctx: MiddlewareContext, next: MiddlewareNext) => MaybePromise<any>;
873
- declare class Pipeline {
874
- private middlewares;
875
- use(middleware: Middleware): void;
876
- execute(ctx: MiddlewareContext, finalOperation: () => MaybePromise<any>): MaybePromise<any>;
877
- wrap<T extends object>(target: T, baseContext: Partial<MiddlewareContext>): T;
878
- }
879
-
880
828
  interface DocumentOptions<T extends Record<string, any>> {
881
829
  /**
882
830
  * The already-persisted initial state of the document.
package/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { QueryFilter, PaginationOptions } from '@asaidimu/query';
2
2
  import { IndexDefinition, SchemaDefinition, SchemaChange, DataTransform, PredicateMap } from '@asaidimu/anansi';
3
+ import { EventBus } from '@core/events';
3
4
  import { StandardSchemaV1 } from '@standard-schema/spec';
4
5
 
5
6
  /**
@@ -740,6 +741,23 @@ declare const createIndexedDbStore: <T extends Record<string, any>>(config: Stor
740
741
 
741
742
  declare function DatabaseConnection(config: Omit<DatabaseConfig, "keyPath">, createStore: <T extends Record<string, any>>(config: StoreConfig, indexes: IndexDefinition[]) => Store<T>): Promise<Database>;
742
743
 
744
+ interface MiddlewareContext {
745
+ collection?: string;
746
+ documentId?: string;
747
+ operation: string;
748
+ args: any[];
749
+ eventBus?: EventBus<any>;
750
+ }
751
+ type MaybePromise<T> = T | Promise<T>;
752
+ type MiddlewareNext = () => MaybePromise<any>;
753
+ type Middleware = (ctx: MiddlewareContext, next: MiddlewareNext) => MaybePromise<any>;
754
+ declare class Pipeline {
755
+ private middlewares;
756
+ use(middleware: Middleware): void;
757
+ execute(ctx: MiddlewareContext, finalOperation: () => MaybePromise<any>): MaybePromise<any>;
758
+ wrap<T extends object>(target: T, baseContext: Partial<MiddlewareContext>): T;
759
+ }
760
+
743
761
  interface MutexOptions {
744
762
  /**
745
763
  * Maximum number of pending requests allowed in the queue.
@@ -807,76 +825,6 @@ declare class Mutex {
807
825
  pending(): number;
808
826
  }
809
827
 
810
- /**
811
- * Interface defining the shape of the EventBus.
812
- * @template TEventMap - A record mapping event names to their respective payload types.
813
- */
814
- interface EventBus<TEventMap extends Record<string, any>> {
815
- /**
816
- * Subscribes to a specific event by name.
817
- * @param eventName - The name of the event to subscribe to.
818
- * @param callback - The function to call when the event is emitted.
819
- * @returns A function to unsubscribe from the event.
820
- */
821
- subscribe: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
822
- /**
823
- * Subscribes to an event and automatically unsubscribes after it fires once.
824
- * @param eventName - The name of the event to subscribe to.
825
- * @param callback - The function to call when the event is emitted.
826
- * @returns A function to cancel the one-shot subscription before it fires.
827
- */
828
- once: <TEventName extends keyof TEventMap>(eventName: TEventName, callback: (payload: TEventMap[TEventName]) => void) => () => void;
829
- /**
830
- * Emits an event with a payload to all subscribed listeners.
831
- * @param event - An object containing the event name and payload.
832
- */
833
- emit: <TEventName extends keyof TEventMap>(event: {
834
- name: TEventName;
835
- payload: TEventMap[TEventName];
836
- }) => void;
837
- /**
838
- * Retrieves metrics about event bus usage.
839
- * @returns An object containing various metrics.
840
- */
841
- metrics: () => EventMetrics;
842
- /**
843
- * Clears all subscriptions and resets metrics.
844
- * After calling clear(), the bus is fully reset and can be reused —
845
- * cross-tab communication is re-established if it was previously enabled.
846
- */
847
- clear: () => void;
848
- }
849
- /**
850
- * Interface defining the metrics tracked by the EventBus.
851
- */
852
- interface EventMetrics {
853
- /** Total number of events emitted (both sync and deferred paths). */
854
- totalEvents: number;
855
- /** Number of active subscriptions across all event names. */
856
- activeSubscriptions: number;
857
- /** Map of event names to their emission counts. */
858
- eventCounts: Map<string, number>;
859
- /** Average duration of event dispatch in milliseconds. */
860
- averageEmitDuration: number;
861
- }
862
-
863
- interface MiddlewareContext {
864
- collection?: string;
865
- documentId?: string;
866
- operation: string;
867
- args: any[];
868
- eventBus?: EventBus<any>;
869
- }
870
- type MaybePromise<T> = T | Promise<T>;
871
- type MiddlewareNext = () => MaybePromise<any>;
872
- type Middleware = (ctx: MiddlewareContext, next: MiddlewareNext) => MaybePromise<any>;
873
- declare class Pipeline {
874
- private middlewares;
875
- use(middleware: Middleware): void;
876
- execute(ctx: MiddlewareContext, finalOperation: () => MaybePromise<any>): MaybePromise<any>;
877
- wrap<T extends object>(target: T, baseContext: Partial<MiddlewareContext>): T;
878
- }
879
-
880
828
  interface DocumentOptions<T extends Record<string, any>> {
881
829
  /**
882
830
  * The already-persisted initial state of the document.