@warlock.js/cascade 5.23.2 → 5.25.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +352 -329
- package/README.md +101 -101
- package/bin/cascade.js +0 -0
- package/cjs/index.cjs +208 -69
- package/cjs/index.cjs.map +1 -1
- package/esm/contracts/database-driver.contract.d.mts +22 -1
- package/esm/contracts/database-driver.contract.d.mts.map +1 -1
- package/esm/contracts/index.d.mts +1 -1
- package/esm/data-source/data-source-registry.d.mts +8 -6
- package/esm/data-source/data-source-registry.d.mts.map +1 -1
- package/esm/data-source/data-source-registry.mjs +7 -1
- package/esm/data-source/data-source-registry.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.d.mts +13 -0
- package/esm/drivers/mongodb/mongodb-driver.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-driver.mjs +71 -2
- package/esm/drivers/mongodb/mongodb-driver.mjs.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.d.mts.map +1 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs +2 -1
- package/esm/drivers/mongodb/mongodb-query-builder.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-driver.d.mts +9 -0
- package/esm/drivers/postgres/postgres-driver.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-driver.mjs +61 -5
- package/esm/drivers/postgres/postgres-driver.mjs.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.d.mts +1 -4
- package/esm/drivers/postgres/postgres-query-parser.d.mts.map +1 -1
- package/esm/drivers/postgres/postgres-query-parser.mjs +4 -5
- package/esm/drivers/postgres/postgres-query-parser.mjs.map +1 -1
- package/esm/drivers/postgres/types.d.mts +5 -0
- package/esm/drivers/postgres/types.d.mts.map +1 -1
- package/esm/errors/unsafe-filter.error.mjs.map +1 -1
- package/esm/errors/unsafe-raw-expression.error.mjs.map +1 -1
- package/esm/errors/unsupported-lock-for-update.error.d.mts +11 -0
- package/esm/errors/unsupported-lock-for-update.error.d.mts.map +1 -0
- package/esm/errors/unsupported-lock-for-update.error.mjs +16 -0
- package/esm/errors/unsupported-lock-for-update.error.mjs.map +1 -0
- package/esm/events/model-events.mjs.map +1 -1
- package/esm/index.d.mts +3 -2
- package/esm/index.mjs +2 -1
- package/esm/migration/migration-runner.mjs.map +1 -1
- package/esm/migration/sql-grammar.mjs.map +1 -1
- package/esm/model/generate-model-id.mjs +23 -0
- package/esm/model/generate-model-id.mjs.map +1 -0
- package/esm/model/methods/delete-methods.mjs.map +1 -1
- package/esm/model/methods/meta-methods.mjs.map +1 -1
- package/esm/model/methods/query-methods.mjs +25 -2
- package/esm/model/methods/query-methods.mjs.map +1 -1
- package/esm/model/methods/write-methods.mjs.map +1 -1
- package/esm/query-builder/query-builder.mjs +1 -1
- package/esm/query-builder/query-builder.mjs.map +1 -1
- package/esm/utils/sanitize-filter.mjs.map +1 -1
- package/esm/validation/plugins/database-rules-plugin.mjs.map +1 -1
- package/esm/writer/database-writer.d.mts +0 -33
- package/esm/writer/database-writer.d.mts.map +1 -1
- package/esm/writer/database-writer.mjs +4 -52
- package/esm/writer/database-writer.mjs.map +1 -1
- package/llms-full.txt +2835 -2783
- package/package.json +5 -5
- package/skills/aggregate-data/SKILL.md +165 -165
- package/skills/alter-migration/SKILL.md +531 -531
- package/skills/configure-delete-strategy/SKILL.md +130 -130
- package/skills/define-model/SKILL.md +205 -205
- package/skills/define-relations/SKILL.md +171 -171
- package/skills/manage-data-sources/SKILL.md +177 -140
- package/skills/manage-transactions/SKILL.md +233 -208
- package/skills/paginate-results/SKILL.md +122 -122
- package/skills/perform-atomic-ops/SKILL.md +156 -156
- package/skills/query-data/SKILL.md +213 -213
- package/skills/run-cascade-cli/SKILL.md +125 -125
- package/skills/search-by-vector/SKILL.md +127 -127
- package/skills/subscribe-to-model-events/SKILL.md +148 -148
- package/skills/track-changes/SKILL.md +127 -127
- package/skills/write-migration/SKILL.md +206 -206
|
@@ -12,6 +12,25 @@ import { SyncAdapterContract } from "./sync-adapter.contract.mjs";
|
|
|
12
12
|
type DriverEvent = "connected" | "disconnected" | string;
|
|
13
13
|
/** Listener signature for driver lifecycle events. */
|
|
14
14
|
type DriverEventListener = (...args: unknown[]) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Details of a database command after it has settled.
|
|
17
|
+
*
|
|
18
|
+
* `connection` is the driver name when emitted by a driver directly, and the
|
|
19
|
+
* registered data-source name when forwarded by `dataSourceRegistry`.
|
|
20
|
+
*/
|
|
21
|
+
type QueryEvent = {
|
|
22
|
+
connection: string;
|
|
23
|
+
driver: "postgres" | "mongodb";
|
|
24
|
+
sql?: string;
|
|
25
|
+
bindings?: unknown[];
|
|
26
|
+
collection?: string;
|
|
27
|
+
command?: string;
|
|
28
|
+
pipeline?: unknown;
|
|
29
|
+
durationMs: number;
|
|
30
|
+
startedAt: number;
|
|
31
|
+
rowCount?: number;
|
|
32
|
+
error?: unknown;
|
|
33
|
+
};
|
|
15
34
|
/** Representation of an opened transaction (manual pattern). */
|
|
16
35
|
interface DriverTransactionContract<TContext = unknown> {
|
|
17
36
|
/** Driver-specific transaction context (session, connection, ...). */
|
|
@@ -208,6 +227,8 @@ interface DriverContract {
|
|
|
208
227
|
getDirtyTracker(data: Record<string, unknown>): DatabaseDirtyTracker;
|
|
209
228
|
/** Register event listeners (connected/disconnected/custom). */
|
|
210
229
|
on(event: DriverEvent, listener: DriverEventListener): void;
|
|
230
|
+
/** Remove a previously registered event listener. */
|
|
231
|
+
off(event: DriverEvent, listener: DriverEventListener): void;
|
|
211
232
|
/** Insert a single document/row into the given table. */
|
|
212
233
|
insert(table: string, document: Record<string, unknown>, options?: Record<string, unknown>): Promise<InsertResult>;
|
|
213
234
|
/** Insert multiple documents/rows into the given table. */
|
|
@@ -507,5 +528,5 @@ type DropDatabaseOptions = {
|
|
|
507
528
|
ifExists?: boolean;
|
|
508
529
|
};
|
|
509
530
|
//#endregion
|
|
510
|
-
export { AtomicUpdate, AtomicUpdateOptions, CreateDatabaseOptions, DriverAtomicUpdateOptions, DriverContract, DriverEvent, DriverEventListener, DriverTransactionContract, DropDatabaseOptions, FindOneAndUpdateOptions, InsertResult, RawQueryResult, TransactionContext, UpdateOperations, UpdatePipeline, UpdateResult };
|
|
531
|
+
export { AtomicUpdate, AtomicUpdateOptions, CreateDatabaseOptions, DriverAtomicUpdateOptions, DriverContract, DriverEvent, DriverEventListener, DriverTransactionContract, DropDatabaseOptions, FindOneAndUpdateOptions, InsertResult, QueryEvent, RawQueryResult, TransactionContext, UpdateOperations, UpdatePipeline, UpdateResult };
|
|
511
532
|
//# sourceMappingURL=database-driver.contract.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database-driver.contract.d.mts","names":[],"sources":["../../../../../../../cascade/src/contracts/database-driver.contract.ts"],"mappings":";;;;;;;;;;;KASY,WAAA;;KAGA,mBAAA,OAA0B,IAAI;;
|
|
1
|
+
{"version":3,"file":"database-driver.contract.d.mts","names":[],"sources":["../../../../../../../cascade/src/contracts/database-driver.contract.ts"],"mappings":"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"}
|
|
@@ -2,7 +2,7 @@ import { DriverBlueprintContract, TableIndexInformation } from "./driver-bluepri
|
|
|
2
2
|
import { ColumnDefinition, ColumnType, ForeignKeyDefinition, FullTextIndexOptions, GeoIndexOptions, IndexDefinition, MigrationDriverContract, MigrationDriverFactory, VectorIndexOptions } from "./migration-driver.contract.mjs";
|
|
3
3
|
import { ChunkCallback, CursorPaginationOptions, CursorPaginationResult, DriverQuery, GroupByInput, HavingInput, JoinOptions, LeanDocument, LockForUpdateOptions, OrderDirection, PaginationOptions, PaginationResult, QueryBuilderContract, RawExpression, UnwindOptions, WhereCallback, WhereObject, WhereOperator } from "./query-builder.contract.mjs";
|
|
4
4
|
import { SyncAdapterContract, SyncInstruction } from "./sync-adapter.contract.mjs";
|
|
5
|
-
import { AtomicUpdate, AtomicUpdateOptions, CreateDatabaseOptions, DriverAtomicUpdateOptions, DriverContract, DriverEvent, DriverEventListener, DriverTransactionContract, DropDatabaseOptions, FindOneAndUpdateOptions, InsertResult, RawQueryResult, TransactionContext, UpdateOperations, UpdatePipeline, UpdateResult } from "./database-driver.contract.mjs";
|
|
5
|
+
import { AtomicUpdate, AtomicUpdateOptions, CreateDatabaseOptions, DriverAtomicUpdateOptions, DriverContract, DriverEvent, DriverEventListener, DriverTransactionContract, DropDatabaseOptions, FindOneAndUpdateOptions, InsertResult, QueryEvent, RawQueryResult, TransactionContext, UpdateOperations, UpdatePipeline, UpdateResult } from "./database-driver.contract.mjs";
|
|
6
6
|
import { GenerateIdOptions, IdGeneratorContract } from "./database-id-generator.contract.mjs";
|
|
7
7
|
import { RemoverContract, RemoverOptions, RemoverResult } from "./database-remover.contract.mjs";
|
|
8
8
|
import { RestorerContract, RestorerOptions, RestorerResult } from "./database-restorer.contract.mjs";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { QueryEvent } from "../contracts/database-driver.contract.mjs";
|
|
1
2
|
import { DataSource, DataSourceOptions } from "./data-source.mjs";
|
|
2
3
|
|
|
3
4
|
//#region ../cascade/src/data-source/data-source-registry.d.ts
|
|
@@ -8,19 +9,20 @@ import { DataSource, DataSourceOptions } from "./data-source.mjs";
|
|
|
8
9
|
* - `default-registered`: Emitted when a default data source is registered
|
|
9
10
|
* - `connected`: Emitted when a data source's driver connects
|
|
10
11
|
* - `disconnected`: Emitted when a data source's driver disconnects
|
|
12
|
+
* - `query`: Emitted when a registered driver's query settles
|
|
11
13
|
*/
|
|
12
|
-
type DataSourceRegistryEvent = "registered" | "default-registered" | "connected" | "disconnected";
|
|
14
|
+
type DataSourceRegistryEvent = "registered" | "default-registered" | "connected" | "disconnected" | "query";
|
|
13
15
|
/**
|
|
14
16
|
* Callback signature for registry events.
|
|
15
17
|
*/
|
|
16
|
-
type DataSourceRegistryListener = (
|
|
18
|
+
type DataSourceRegistryListener<E extends DataSourceRegistryEvent = DataSourceRegistryEvent> = (data: E extends "query" ? QueryEvent : DataSource) => void;
|
|
17
19
|
/** Maintains registry of named data sources. */
|
|
18
20
|
declare class DataSourceRegistry {
|
|
19
21
|
private readonly sources;
|
|
20
22
|
private defaultSource?;
|
|
21
23
|
private defaultIsExplicit;
|
|
22
24
|
private readonly events;
|
|
23
|
-
/** Replaced sources; their forwarded driver events are ignored
|
|
25
|
+
/** Replaced sources; their forwarded driver events are ignored. */
|
|
24
26
|
private readonly detached;
|
|
25
27
|
/** In-flight `getOrRegister` factories, so concurrent callers share one creation. */
|
|
26
28
|
private readonly pending;
|
|
@@ -100,7 +102,7 @@ declare class DataSourceRegistry {
|
|
|
100
102
|
* });
|
|
101
103
|
* ```
|
|
102
104
|
*/
|
|
103
|
-
on(event:
|
|
105
|
+
on<E extends DataSourceRegistryEvent>(event: E, listener: DataSourceRegistryListener<E>): void;
|
|
104
106
|
/**
|
|
105
107
|
* Listen for a data source registration event once.
|
|
106
108
|
*
|
|
@@ -109,14 +111,14 @@ declare class DataSourceRegistry {
|
|
|
109
111
|
* @param event - The event to listen for
|
|
110
112
|
* @param listener - Callback to execute when event fires
|
|
111
113
|
*/
|
|
112
|
-
once(event:
|
|
114
|
+
once<E extends DataSourceRegistryEvent>(event: E, listener: DataSourceRegistryListener<E>): void;
|
|
113
115
|
/**
|
|
114
116
|
* Remove a listener for a data source registration event.
|
|
115
117
|
*
|
|
116
118
|
* @param event - The event to stop listening for
|
|
117
119
|
* @param listener - The listener to remove
|
|
118
120
|
*/
|
|
119
|
-
off(event:
|
|
121
|
+
off<E extends DataSourceRegistryEvent>(event: E, listener: DataSourceRegistryListener<E>): void;
|
|
120
122
|
/** Retrieve a data source either by name or the default one. */
|
|
121
123
|
get(name?: string): DataSource;
|
|
122
124
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-source-registry.d.mts","names":[],"sources":["../../../../../../../cascade/src/data-source/data-source-registry.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"data-source-registry.d.mts","names":[],"sources":["../../../../../../../cascade/src/data-source/data-source-registry.ts"],"mappings":";;;;;;AAeA;;;;AAAmC;AAMnC;;KANY,uBAAA;;;;KAMA,0BAAA,WACA,uBAAA,GAA0B,uBAAA,KACjC,IAAA,EAAM,CAAA,mBAAoB,UAAA,GAAa,UAAA;;cAGtC,kBAAA;EAAA,iBACa,OAAA;EAAA,QACT,aAAA;EAAA,QACA,iBAAA;EAAA,iBACS,MAAA;EAPR;EAAA,iBASQ,QAAA;EATyB;EAAA,iBAWzB,OAAA;EAXmC;AAAA;AAAU;;;;;;;;;;;;;;;;;;;;;EAoCvD,QAAA,CACL,OAAA,EAAS,iBAAA,EACT,IAAA;IAAS,eAAA;IAA2B,OAAA;EAAA,IACnC,UAAA;EAqPmC;;;;EAlL/B,UAAA,CAAW,MAAA,EAAQ,UAAA;EAnGT;;;;;;EAqHV,aAAA,CACL,IAAA,UACA,OAAA,QAAe,iBAAA,GAAoB,OAAA,CAAQ,iBAAA,IAC1C,OAAA,CAAQ,UAAA;EAzF2B;;;EAoH/B,UAAA;EAhDmB;;;EAuDnB,KAAA;EAnCU;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAuEV,EAAA,WAAa,uBAAA,EAClB,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,0BAAA,CAA2B,CAAA;EA4BA;;;;;;;;EAfhC,IAAA,WAAe,uBAAA,EACpB,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,0BAAA,CAA2B,CAAA;EA2E5B;;;;AAA6C;;EAhEjD,GAAA,WAAc,uBAAA,EACnB,KAAA,EAAO,CAAA,EACP,QAAA,EAAU,0BAAA,CAA2B,CAAA;;EAMhC,GAAA,CAAI,IAAA,YAAgB,UAAA;;;;;;;;;;;;;;;;;EAmDpB,iBAAA,IAAqB,UAAA;AAAA;AAAA,cAKjB,kBAAA,EAAkB,kBAA2B"}
|
|
@@ -10,7 +10,7 @@ var DataSourceRegistry = class {
|
|
|
10
10
|
defaultSource;
|
|
11
11
|
defaultIsExplicit = false;
|
|
12
12
|
events = new EventEmitter();
|
|
13
|
-
/** Replaced sources; their forwarded driver events are ignored
|
|
13
|
+
/** Replaced sources; their forwarded driver events are ignored. */
|
|
14
14
|
detached = /* @__PURE__ */ new WeakSet();
|
|
15
15
|
/** In-flight `getOrRegister` factories, so concurrent callers share one creation. */
|
|
16
16
|
pending = /* @__PURE__ */ new Map();
|
|
@@ -61,6 +61,12 @@ var DataSourceRegistry = class {
|
|
|
61
61
|
source.driver.on("disconnected", () => {
|
|
62
62
|
if (!this.detached.has(source)) this.events.emit("disconnected", source);
|
|
63
63
|
});
|
|
64
|
+
source.driver.on("query", (event) => {
|
|
65
|
+
if (!this.detached.has(source)) this.events.emit("query", {
|
|
66
|
+
...event,
|
|
67
|
+
connection: source.name
|
|
68
|
+
});
|
|
69
|
+
});
|
|
64
70
|
return source;
|
|
65
71
|
}
|
|
66
72
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"data-source-registry.mjs","names":[],"sources":["../../../../../../../cascade/src/data-source/data-source-registry.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { databaseDataSourceContext } from \"../context/database-data-source-context\";\nimport { MissingDataSourceError } from \"../errors/missing-data-source.error\";\nimport { DataSource, type DataSourceOptions } from \"./data-source\";\n\n/**\n * Event types emitted by the DataSourceRegistry.\n *\n * - `registered`: Emitted when any data source is registered\n * - `default-registered`: Emitted when a default data source is registered\n * - `connected`: Emitted when a data source's driver connects\n * - `disconnected`: Emitted when a data source's driver disconnects\n */\nexport type DataSourceRegistryEvent =\n | \"registered\"\n | \"default-registered\"\n | \"connected\"\n | \"disconnected\";\n\n/**\n * Callback signature for registry events.\n */\nexport type DataSourceRegistryListener = (dataSource: DataSource) => void;\n\n/** Maintains registry of named data sources. */\nclass DataSourceRegistry {\n private readonly sources = new Map<string, DataSource>();\n private defaultSource?: DataSource;\n private defaultIsExplicit = false;\n private readonly events = new EventEmitter();\n /** Replaced sources; their forwarded driver events are ignored (drivers have no `off`). */\n private readonly detached = new WeakSet<DataSource>();\n /** In-flight `getOrRegister` factories, so concurrent callers share one creation. */\n private readonly pending = new Map<string, Promise<DataSource>>();\n\n /**\n * Register a new data source definition.\n *\n * Sets up event forwarding from the driver to the registry, allowing\n * centralized listening for connection state changes.\n *\n * **Emits:**\n * - `registered` - When the data source is registered\n * - `default-registered` - If this becomes the default data source\n * - `connected` - When the driver connects (forwarded from driver)\n * - `disconnected` - When the driver disconnects (forwarded from driver)\n *\n * The first registered source becomes the default. Later sources become the default\n * only when they explicitly claim it, and two explicit claims throw.\n *\n * @param options - Data source configuration\n * @param meta - `explicitDefault` tells whether the caller explicitly requested `isDefault: true`\n * (defaults to `options.isDefault`), as opposed to it being implied by being the first source.\n * `replace: true` also disconnects the previously registered source of the same name (in the\n * background). Either way the old source's events stop being forwarded and, if it was the\n * default, the new source takes its place.\n * @returns The registered data source instance\n */\n public register(\n options: DataSourceOptions,\n meta?: { explicitDefault?: boolean; replace?: boolean },\n ): DataSource {\n const source = new DataSource(options);\n const explicitDefault = meta?.explicitDefault ?? source.isDefault;\n\n if (\n explicitDefault &&\n this.defaultIsExplicit &&\n this.defaultSource &&\n this.defaultSource.name !== source.name\n ) {\n throw new Error(\n `Data source \"${source.name}\" cannot be the default: \"${this.defaultSource.name}\" is already the default data source.`,\n );\n }\n\n const previous = this.sources.get(source.name);\n\n this.sources.set(source.name, source);\n\n if (previous) {\n this.detached.add(previous);\n\n if (meta?.replace) {\n previous.driver.disconnect().catch(() => undefined);\n }\n }\n\n // A replaced default hands the default over to its replacement, otherwise get()\n // would keep returning the stale source.\n const replacesDefault = previous !== undefined && previous === this.defaultSource;\n const isNewDefault = explicitDefault || !this.defaultSource || replacesDefault;\n\n if (isNewDefault) {\n this.defaultSource = source;\n this.defaultIsExplicit = replacesDefault\n ? this.defaultIsExplicit || explicitDefault\n : explicitDefault;\n }\n\n // Emit registration events\n this.events.emit(\"registered\", source);\n\n if (isNewDefault) {\n this.events.emit(\"default-registered\", source);\n }\n\n source.driver.on(\"connected\", () => {\n if (!this.detached.has(source)) this.events.emit(\"connected\", source);\n });\n\n source.driver.on(\"disconnected\", () => {\n if (!this.detached.has(source)) this.events.emit(\"disconnected\", source);\n });\n\n return source;\n }\n\n /**\n * Remove a registered source (only if it is still the one registered under its name).\n * If it was the default, the registry has no default until another source claims it.\n */\n public unregister(source: DataSource): void {\n if (this.sources.get(source.name) !== source) return;\n\n this.sources.delete(source.name);\n this.detached.add(source);\n\n if (this.defaultSource === source) {\n this.defaultSource = undefined;\n this.defaultIsExplicit = false;\n }\n }\n\n /**\n * Return the registered source for `name`, or create and register it via `factory`.\n *\n * Concurrent callers for the same name share one in-flight factory call, so only one\n * driver/pool is created. A failed factory is not cached.\n */\n public getOrRegister(\n name: string,\n factory: () => DataSourceOptions | Promise<DataSourceOptions>,\n ): Promise<DataSource> {\n const existing = this.sources.get(name);\n\n if (existing) return Promise.resolve(existing);\n\n const inFlight = this.pending.get(name);\n\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n try {\n const options = await factory();\n\n return this.sources.get(name) ?? this.register({ ...options, name });\n } finally {\n this.pending.delete(name);\n }\n })();\n\n this.pending.set(name, promise);\n\n return promise;\n }\n\n /**\n * Determine whether a default data source is already registered.\n */\n public hasDefault(): boolean {\n return this.defaultSource !== undefined;\n }\n\n /**\n * Clean up all data sources and default one\n */\n public clear() {\n this.defaultSource = undefined;\n this.defaultIsExplicit = false;\n this.sources.clear();\n this.pending.clear();\n }\n\n /**\n * Listen for data source registry events.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n *\n * @example\n * ```typescript\n * // Listen for registration\n * dataSourceRegistry.on(\"registered\", (ds) => {\n * console.log(`Data source \"${ds.name}\" registered`);\n * console.log(`Driver: ${ds.driver.name}`); // e.g., \"mongodb\"\n * });\n *\n * // Listen for default data source\n * dataSourceRegistry.on(\"default-registered\", (ds) => {\n * console.log(`Default data source set to \"${ds.name}\"`);\n * });\n *\n * // Listen for connection events (forwarded from drivers)\n * dataSourceRegistry.on(\"connected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" connected`);\n * });\n *\n * dataSourceRegistry.on(\"disconnected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" disconnected`);\n * });\n * ```\n */\n public on(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.on(event, listener);\n }\n\n /**\n * Listen for a data source registration event once.\n *\n * The listener is automatically removed after being called once.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n */\n public once(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.once(event, listener);\n }\n\n /**\n * Remove a listener for a data source registration event.\n *\n * @param event - The event to stop listening for\n * @param listener - The listener to remove\n */\n public off(event: DataSourceRegistryEvent, listener: DataSourceRegistryListener): void {\n this.events.off(event, listener);\n }\n\n /** Retrieve a data source either by name or the default one. */\n public get(name?: string): DataSource {\n const contextSource = name == null ? databaseDataSourceContext.getDataSource() : null;\n\n if (contextSource) {\n if (contextSource instanceof DataSource) {\n return contextSource;\n }\n\n const override = this.sources.get(contextSource);\n\n if (!override) {\n throw new MissingDataSourceError(\n `Data source \"${contextSource}\" is not registered (context override).`,\n contextSource,\n );\n }\n\n return override;\n }\n\n if (name != null) {\n const source = this.sources.get(name);\n if (!source) {\n throw new MissingDataSourceError(`Data source \"${name}\" is not registered.`, name);\n }\n return source;\n }\n\n if (!this.defaultSource) {\n throw new MissingDataSourceError(\"No default data source registered.\");\n }\n\n return this.defaultSource;\n }\n\n /**\n * Get all registered data sources.\n *\n * Useful for operations that need to iterate over all sources,\n * such as shutting down all connections.\n *\n * @returns Array of all registered data sources\n *\n * @example\n * ```typescript\n * // Shutdown all data sources\n * for (const dataSource of dataSourceRegistry.getAllDataSources()) {\n * await dataSource.driver.disconnect();\n * }\n * ```\n */\n public getAllDataSources(): DataSource[] {\n return Array.from(this.sources.values());\n }\n}\n\nexport const dataSourceRegistry = new DataSourceRegistry();\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"data-source-registry.mjs","names":[],"sources":["../../../../../../../cascade/src/data-source/data-source-registry.ts"],"sourcesContent":["import { EventEmitter } from \"node:events\";\nimport { databaseDataSourceContext } from \"../context/database-data-source-context\";\nimport { MissingDataSourceError } from \"../errors/missing-data-source.error\";\nimport { DataSource, type DataSourceOptions } from \"./data-source\";\nimport type { QueryEvent } from \"../contracts/database-driver.contract\";\n\n/**\n * Event types emitted by the DataSourceRegistry.\n *\n * - `registered`: Emitted when any data source is registered\n * - `default-registered`: Emitted when a default data source is registered\n * - `connected`: Emitted when a data source's driver connects\n * - `disconnected`: Emitted when a data source's driver disconnects\n * - `query`: Emitted when a registered driver's query settles\n */\nexport type DataSourceRegistryEvent =\n \"registered\" | \"default-registered\" | \"connected\" | \"disconnected\" | \"query\";\n\n/**\n * Callback signature for registry events.\n */\nexport type DataSourceRegistryListener<\n E extends DataSourceRegistryEvent = DataSourceRegistryEvent,\n> = (data: E extends \"query\" ? QueryEvent : DataSource) => void;\n\n/** Maintains registry of named data sources. */\nclass DataSourceRegistry {\n private readonly sources = new Map<string, DataSource>();\n private defaultSource?: DataSource;\n private defaultIsExplicit = false;\n private readonly events = new EventEmitter();\n /** Replaced sources; their forwarded driver events are ignored. */\n private readonly detached = new WeakSet<DataSource>();\n /** In-flight `getOrRegister` factories, so concurrent callers share one creation. */\n private readonly pending = new Map<string, Promise<DataSource>>();\n\n /**\n * Register a new data source definition.\n *\n * Sets up event forwarding from the driver to the registry, allowing\n * centralized listening for connection state changes.\n *\n * **Emits:**\n * - `registered` - When the data source is registered\n * - `default-registered` - If this becomes the default data source\n * - `connected` - When the driver connects (forwarded from driver)\n * - `disconnected` - When the driver disconnects (forwarded from driver)\n *\n * The first registered source becomes the default. Later sources become the default\n * only when they explicitly claim it, and two explicit claims throw.\n *\n * @param options - Data source configuration\n * @param meta - `explicitDefault` tells whether the caller explicitly requested `isDefault: true`\n * (defaults to `options.isDefault`), as opposed to it being implied by being the first source.\n * `replace: true` also disconnects the previously registered source of the same name (in the\n * background). Either way the old source's events stop being forwarded and, if it was the\n * default, the new source takes its place.\n * @returns The registered data source instance\n */\n public register(\n options: DataSourceOptions,\n meta?: { explicitDefault?: boolean; replace?: boolean },\n ): DataSource {\n const source = new DataSource(options);\n const explicitDefault = meta?.explicitDefault ?? source.isDefault;\n\n if (\n explicitDefault &&\n this.defaultIsExplicit &&\n this.defaultSource &&\n this.defaultSource.name !== source.name\n ) {\n throw new Error(\n `Data source \"${source.name}\" cannot be the default: \"${this.defaultSource.name}\" is already the default data source.`,\n );\n }\n\n const previous = this.sources.get(source.name);\n\n this.sources.set(source.name, source);\n\n if (previous) {\n this.detached.add(previous);\n\n if (meta?.replace) {\n previous.driver.disconnect().catch(() => undefined);\n }\n }\n\n // A replaced default hands the default over to its replacement, otherwise get()\n // would keep returning the stale source.\n const replacesDefault = previous !== undefined && previous === this.defaultSource;\n const isNewDefault = explicitDefault || !this.defaultSource || replacesDefault;\n\n if (isNewDefault) {\n this.defaultSource = source;\n this.defaultIsExplicit = replacesDefault\n ? this.defaultIsExplicit || explicitDefault\n : explicitDefault;\n }\n\n // Emit registration events\n this.events.emit(\"registered\", source);\n\n if (isNewDefault) {\n this.events.emit(\"default-registered\", source);\n }\n\n source.driver.on(\"connected\", () => {\n if (!this.detached.has(source)) this.events.emit(\"connected\", source);\n });\n\n source.driver.on(\"disconnected\", () => {\n if (!this.detached.has(source)) this.events.emit(\"disconnected\", source);\n });\n\n source.driver.on(\"query\", (event) => {\n if (!this.detached.has(source)) {\n this.events.emit(\"query\", { ...(event as QueryEvent), connection: source.name });\n }\n });\n\n return source;\n }\n\n /**\n * Remove a registered source (only if it is still the one registered under its name).\n * If it was the default, the registry has no default until another source claims it.\n */\n public unregister(source: DataSource): void {\n if (this.sources.get(source.name) !== source) return;\n\n this.sources.delete(source.name);\n this.detached.add(source);\n\n if (this.defaultSource === source) {\n this.defaultSource = undefined;\n this.defaultIsExplicit = false;\n }\n }\n\n /**\n * Return the registered source for `name`, or create and register it via `factory`.\n *\n * Concurrent callers for the same name share one in-flight factory call, so only one\n * driver/pool is created. A failed factory is not cached.\n */\n public getOrRegister(\n name: string,\n factory: () => DataSourceOptions | Promise<DataSourceOptions>,\n ): Promise<DataSource> {\n const existing = this.sources.get(name);\n\n if (existing) return Promise.resolve(existing);\n\n const inFlight = this.pending.get(name);\n\n if (inFlight) return inFlight;\n\n const promise = (async () => {\n try {\n const options = await factory();\n\n return this.sources.get(name) ?? this.register({ ...options, name });\n } finally {\n this.pending.delete(name);\n }\n })();\n\n this.pending.set(name, promise);\n\n return promise;\n }\n\n /**\n * Determine whether a default data source is already registered.\n */\n public hasDefault(): boolean {\n return this.defaultSource !== undefined;\n }\n\n /**\n * Clean up all data sources and default one\n */\n public clear() {\n this.defaultSource = undefined;\n this.defaultIsExplicit = false;\n this.sources.clear();\n this.pending.clear();\n }\n\n /**\n * Listen for data source registry events.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n *\n * @example\n * ```typescript\n * // Listen for registration\n * dataSourceRegistry.on(\"registered\", (ds) => {\n * console.log(`Data source \"${ds.name}\" registered`);\n * console.log(`Driver: ${ds.driver.name}`); // e.g., \"mongodb\"\n * });\n *\n * // Listen for default data source\n * dataSourceRegistry.on(\"default-registered\", (ds) => {\n * console.log(`Default data source set to \"${ds.name}\"`);\n * });\n *\n * // Listen for connection events (forwarded from drivers)\n * dataSourceRegistry.on(\"connected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" connected`);\n * });\n *\n * dataSourceRegistry.on(\"disconnected\", (ds) => {\n * console.log(`${ds.driver.name} data source \"${ds.name}\" disconnected`);\n * });\n * ```\n */\n public on<E extends DataSourceRegistryEvent>(\n event: E,\n listener: DataSourceRegistryListener<E>,\n ): void {\n this.events.on(event, listener);\n }\n\n /**\n * Listen for a data source registration event once.\n *\n * The listener is automatically removed after being called once.\n *\n * @param event - The event to listen for\n * @param listener - Callback to execute when event fires\n */\n public once<E extends DataSourceRegistryEvent>(\n event: E,\n listener: DataSourceRegistryListener<E>,\n ): void {\n this.events.once(event, listener);\n }\n\n /**\n * Remove a listener for a data source registration event.\n *\n * @param event - The event to stop listening for\n * @param listener - The listener to remove\n */\n public off<E extends DataSourceRegistryEvent>(\n event: E,\n listener: DataSourceRegistryListener<E>,\n ): void {\n this.events.off(event, listener);\n }\n\n /** Retrieve a data source either by name or the default one. */\n public get(name?: string): DataSource {\n const contextSource = name == null ? databaseDataSourceContext.getDataSource() : null;\n\n if (contextSource) {\n if (contextSource instanceof DataSource) {\n return contextSource;\n }\n\n const override = this.sources.get(contextSource);\n\n if (!override) {\n throw new MissingDataSourceError(\n `Data source \"${contextSource}\" is not registered (context override).`,\n contextSource,\n );\n }\n\n return override;\n }\n\n if (name != null) {\n const source = this.sources.get(name);\n if (!source) {\n throw new MissingDataSourceError(`Data source \"${name}\" is not registered.`, name);\n }\n return source;\n }\n\n if (!this.defaultSource) {\n throw new MissingDataSourceError(\"No default data source registered.\");\n }\n\n return this.defaultSource;\n }\n\n /**\n * Get all registered data sources.\n *\n * Useful for operations that need to iterate over all sources,\n * such as shutting down all connections.\n *\n * @returns Array of all registered data sources\n *\n * @example\n * ```typescript\n * // Shutdown all data sources\n * for (const dataSource of dataSourceRegistry.getAllDataSources()) {\n * await dataSource.driver.disconnect();\n * }\n * ```\n */\n public getAllDataSources(): DataSource[] {\n return Array.from(this.sources.values());\n }\n}\n\nexport const dataSourceRegistry = new DataSourceRegistry();\n"],"mappings":"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"}
|
|
@@ -30,6 +30,7 @@ declare class MongoDbDriver implements DriverContract {
|
|
|
30
30
|
private readonly transactionOptions;
|
|
31
31
|
private idGeneratorInstance?;
|
|
32
32
|
private _blueprint?;
|
|
33
|
+
private readonly monitoredCommands;
|
|
33
34
|
get blueprint(): DriverBlueprintContract;
|
|
34
35
|
/**
|
|
35
36
|
* The name of this driver.
|
|
@@ -120,6 +121,8 @@ declare class MongoDbDriver implements DriverContract {
|
|
|
120
121
|
* Subscribe to driver lifecycle events.
|
|
121
122
|
*/
|
|
122
123
|
on(event: DriverEvent, listener: DriverEventListener): void;
|
|
124
|
+
/** Remove a previously registered driver event listener. */
|
|
125
|
+
off(event: DriverEvent, listener: DriverEventListener): void;
|
|
123
126
|
/**
|
|
124
127
|
* Insert a single document into the given collection.
|
|
125
128
|
*/
|
|
@@ -263,6 +266,16 @@ declare class MongoDbDriver implements DriverContract {
|
|
|
263
266
|
* Emit a driver lifecycle event.
|
|
264
267
|
*/
|
|
265
268
|
private emit;
|
|
269
|
+
private commandStarted;
|
|
270
|
+
private commandSucceeded;
|
|
271
|
+
private commandFailed;
|
|
272
|
+
/**
|
|
273
|
+
* Emit a `query` event. It runs inside the MongoDB client's own monitoring
|
|
274
|
+
* callback, and an observer must never break the client, so a throwing
|
|
275
|
+
* listener is swallowed here.
|
|
276
|
+
*/
|
|
277
|
+
private emitQueryEvent;
|
|
278
|
+
private ignoredCommand;
|
|
266
279
|
/**
|
|
267
280
|
* Ensure MongoDB is running as a replica set (required for transactions).
|
|
268
281
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mongodb-driver.d.mts","names":[],"sources":["../../../../../../../../cascade/src/drivers/mongodb/mongodb-driver.ts"],"mappings":";;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"mongodb-driver.d.mts","names":[],"sources":["../../../../../../../../cascade/src/drivers/mongodb/mongodb-driver.ts"],"mappings":"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"}
|
|
@@ -87,6 +87,7 @@ var MongoDbDriver = class {
|
|
|
87
87
|
transactionOptions;
|
|
88
88
|
idGeneratorInstance;
|
|
89
89
|
_blueprint;
|
|
90
|
+
monitoredCommands = /* @__PURE__ */ new Map();
|
|
90
91
|
get blueprint() {
|
|
91
92
|
if (!this._blueprint) this._blueprint = new MongoDBBlueprint(this.database);
|
|
92
93
|
return this._blueprint;
|
|
@@ -214,13 +215,18 @@ var MongoDbDriver = class {
|
|
|
214
215
|
log.warn("database.mongodb", "connection", "Disconnected from database");
|
|
215
216
|
}
|
|
216
217
|
});
|
|
218
|
+
client.on("commandStarted", (event) => this.commandStarted(event));
|
|
219
|
+
client.on("commandSucceeded", (event) => this.commandSucceeded(event));
|
|
220
|
+
client.on("commandFailed", (event) => this.commandFailed(event));
|
|
217
221
|
if (this.config.logging) {
|
|
218
222
|
const ignoredCommands = [
|
|
219
223
|
"isMaster",
|
|
220
224
|
"hello",
|
|
221
225
|
"ping",
|
|
222
226
|
"saslStart",
|
|
223
|
-
"saslContinue"
|
|
227
|
+
"saslContinue",
|
|
228
|
+
"endSessions",
|
|
229
|
+
"buildInfo"
|
|
224
230
|
];
|
|
225
231
|
client.on("commandStarted", (event) => {
|
|
226
232
|
if (ignoredCommands.includes(event.commandName)) return;
|
|
@@ -277,6 +283,10 @@ var MongoDbDriver = class {
|
|
|
277
283
|
on(event, listener) {
|
|
278
284
|
this.events.on(event, listener);
|
|
279
285
|
}
|
|
286
|
+
/** Remove a previously registered driver event listener. */
|
|
287
|
+
off(event, listener) {
|
|
288
|
+
this.events.off(event, listener);
|
|
289
|
+
}
|
|
280
290
|
/**
|
|
281
291
|
* Insert a single document into the given collection.
|
|
282
292
|
*/
|
|
@@ -593,7 +603,7 @@ var MongoDbDriver = class {
|
|
|
593
603
|
*/
|
|
594
604
|
buildClientOptions() {
|
|
595
605
|
const baseOptions = { ...this.config.clientOptions ?? {} };
|
|
596
|
-
if (
|
|
606
|
+
if (baseOptions.monitorCommands === void 0) baseOptions.monitorCommands = true;
|
|
597
607
|
if (this.config.username && !baseOptions.auth) baseOptions.auth = {
|
|
598
608
|
username: this.config.username,
|
|
599
609
|
password: this.config.password
|
|
@@ -607,6 +617,65 @@ var MongoDbDriver = class {
|
|
|
607
617
|
emit(event, ...args) {
|
|
608
618
|
this.events.emit(event, ...args);
|
|
609
619
|
}
|
|
620
|
+
commandStarted(event) {
|
|
621
|
+
if (this.ignoredCommand(event.commandName) || this.events.listenerCount("query") === 0) return;
|
|
622
|
+
const started = performance.now();
|
|
623
|
+
const { lsid: _lsid, $clusterTime: _clusterTime, $db: _database, ...pipeline } = event.command;
|
|
624
|
+
const collection = event.command[event.commandName];
|
|
625
|
+
this.monitoredCommands.set(event.requestId, {
|
|
626
|
+
connection: this.name,
|
|
627
|
+
driver: "mongodb",
|
|
628
|
+
command: event.commandName,
|
|
629
|
+
collection: typeof collection === "string" ? collection : void 0,
|
|
630
|
+
pipeline,
|
|
631
|
+
started,
|
|
632
|
+
startedAt: performance.timeOrigin + started
|
|
633
|
+
});
|
|
634
|
+
}
|
|
635
|
+
commandSucceeded(event) {
|
|
636
|
+
const command = this.monitoredCommands.get(event.requestId);
|
|
637
|
+
if (!command) return;
|
|
638
|
+
this.monitoredCommands.delete(event.requestId);
|
|
639
|
+
const { started, ...query } = command;
|
|
640
|
+
const rowCount = event.reply?.n ?? event.reply?.cursor?.firstBatch?.length;
|
|
641
|
+
this.emitQueryEvent({
|
|
642
|
+
...query,
|
|
643
|
+
durationMs: performance.now() - started,
|
|
644
|
+
...typeof rowCount === "number" ? { rowCount } : {}
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
commandFailed(event) {
|
|
648
|
+
const command = this.monitoredCommands.get(event.requestId);
|
|
649
|
+
if (!command) return;
|
|
650
|
+
this.monitoredCommands.delete(event.requestId);
|
|
651
|
+
const { started, ...query } = command;
|
|
652
|
+
this.emitQueryEvent({
|
|
653
|
+
...query,
|
|
654
|
+
durationMs: performance.now() - started,
|
|
655
|
+
error: event.failure
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Emit a `query` event. It runs inside the MongoDB client's own monitoring
|
|
660
|
+
* callback, and an observer must never break the client, so a throwing
|
|
661
|
+
* listener is swallowed here.
|
|
662
|
+
*/
|
|
663
|
+
emitQueryEvent(event) {
|
|
664
|
+
try {
|
|
665
|
+
this.emit("query", event);
|
|
666
|
+
} catch {}
|
|
667
|
+
}
|
|
668
|
+
ignoredCommand(command) {
|
|
669
|
+
return [
|
|
670
|
+
"isMaster",
|
|
671
|
+
"hello",
|
|
672
|
+
"ping",
|
|
673
|
+
"saslStart",
|
|
674
|
+
"saslContinue",
|
|
675
|
+
"endSessions",
|
|
676
|
+
"buildInfo"
|
|
677
|
+
].includes(command);
|
|
678
|
+
}
|
|
610
679
|
/**
|
|
611
680
|
* Ensure MongoDB is running as a replica set (required for transactions).
|
|
612
681
|
*
|