monsqlize 2.0.0 → 2.0.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.
- package/CHANGELOG.md +461 -458
- package/README.md +7 -2
- package/changelogs/README.md +141 -138
- package/changelogs/v2.0.0.md +164 -164
- package/changelogs/v2.0.1.md +39 -0
- package/changelogs/v2.0.2.md +22 -0
- package/dist/cjs/index.cjs +329 -141
- package/dist/esm/index.mjs +329 -141
- package/dist/types/base.d.ts +81 -81
- package/dist/types/collection.d.ts +973 -973
- package/dist/types/expression.d.ts +115 -115
- package/dist/types/index.d.ts +23 -23
- package/dist/types/model.d.ts +489 -485
- package/dist/types/mongodb.d.ts +49 -49
- package/dist/types/monsqlize.d.ts +429 -429
- package/dist/types/pool.d.ts +84 -84
- package/dist/types/runtime.d.ts +315 -315
- package/dist/types/saga.d.ts +121 -121
- package/dist/types/slow-query-log.d.ts +126 -126
- package/dist/types/sync.d.ts +103 -103
- package/package.json +101 -99
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# v2.0.1 — 2026-06-03
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
v2.0.1 is a compatibility and documentation patch for the v2 TypeScript line. It preserves the v2.0.0 public package shape while tightening v1 smooth-upgrade behavior and aligning the published documentation with the current runtime.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Fixes
|
|
10
|
+
|
|
11
|
+
- **Model routing:** `definition.collection` is now used as the actual MongoDB collection name, with `definition.name` and the registered model name as fallbacks.
|
|
12
|
+
- **Model pool scope:** Model connection metadata now routes through the configured pool and database when creating scoped collections.
|
|
13
|
+
- **Model cache identity:** Model instance cache keys include pool, database, registered model name, and actual collection name to avoid cross-scope reuse.
|
|
14
|
+
- **Populate compatibility:** `relations.from` resolves registered Model names to their actual MongoDB collection names, while still allowing direct collection names when no registered Model exists.
|
|
15
|
+
- **Automatic indexes:** Model index creation is deduplicated per runtime / pool / database / collection / index fingerprint; pending and fulfilled tasks are reused, while failed tasks may retry.
|
|
16
|
+
- **Cache compatibility:** Runtime cache option normalization preserves v1 aliases and millisecond TTL semantics.
|
|
17
|
+
- **Pool compatibility:** Pool selector operation names accept v1-style string inputs.
|
|
18
|
+
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
## Documentation and Types
|
|
22
|
+
|
|
23
|
+
- Added `ModelDefinition.collection` and `ModelDefinition.name` to the public type surface.
|
|
24
|
+
- Documented the actual automatic-index flow: `connect()` only registers models; `ModelInstance` creation schedules per-index `createIndex()` calls; no `listIndexes()` preflight is performed.
|
|
25
|
+
- Updated the current release status, API index count, examples count, and advanced capability index entries.
|
|
26
|
+
- Kept historical changelog archive links unchanged; current published package links remain clean.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Validation
|
|
31
|
+
|
|
32
|
+
- `npm run build`
|
|
33
|
+
- `npm run type-check`
|
|
34
|
+
- `npm run lint`
|
|
35
|
+
- `npm run test:runtime`
|
|
36
|
+
- `npm run test:compatibility`
|
|
37
|
+
- `npm run check:sizes:strict`
|
|
38
|
+
- `npm run test:examples`
|
|
39
|
+
- `npm pack --json --dry-run`
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# v2.0.2 — 2026-06-09
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
v2.0.2 is a package metadata patch for deterministic installs. It keeps the runtime API unchanged while pinning direct dependency declarations to the exact versions already resolved by the lockfile.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Changes
|
|
10
|
+
|
|
11
|
+
- Pinned direct `dependencies`, `optionalDependencies` and `devDependencies` in `package.json` to exact versions.
|
|
12
|
+
- Kept peer metadata unchanged.
|
|
13
|
+
- Updated `.npmrc` so future dependency saves keep `package-lock.json` enabled and use exact versions.
|
|
14
|
+
- Added this release note to the packaged changelog set.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Validation
|
|
19
|
+
|
|
20
|
+
- `npm ci`
|
|
21
|
+
- `npm run release:preflight`
|
|
22
|
+
- `npm pack --dry-run --json`
|
package/dist/cjs/index.cjs
CHANGED
|
@@ -705,6 +705,13 @@ function serializeDocument(document) {
|
|
|
705
705
|
}
|
|
706
706
|
|
|
707
707
|
// src/capabilities/model/model-instance-helpers.ts
|
|
708
|
+
function resolveRegisteredCollectionName(registered, fallback) {
|
|
709
|
+
if (!registered) {
|
|
710
|
+
return fallback;
|
|
711
|
+
}
|
|
712
|
+
const definition = registered.definition;
|
|
713
|
+
return definition.collection ?? definition.name ?? registered.collectionName;
|
|
714
|
+
}
|
|
708
715
|
async function populateModelPath(context, docs, path2) {
|
|
709
716
|
const config = normalizePopulateConfig(path2);
|
|
710
717
|
if (docs.length === 0) {
|
|
@@ -728,7 +735,8 @@ async function populateModelPath(context, docs, path2) {
|
|
|
728
735
|
database: registered?.definition.connection?.database ?? context.dbName,
|
|
729
736
|
pool: registered?.definition.connection?.pool ?? context.poolName
|
|
730
737
|
};
|
|
731
|
-
const
|
|
738
|
+
const relatedCollectionName = resolveRegisteredCollectionName(registered, relation.from);
|
|
739
|
+
const relatedCollection = context.runtime.scopedCollection(relatedCollectionName, scope);
|
|
732
740
|
const relatedModel = Model.has(relation.from) ? context.runtime.scopedModel(relation.from, scope) : null;
|
|
733
741
|
const relatedDocs = await relatedCollection.find({
|
|
734
742
|
[relation.foreignField]: { $in: keys },
|
|
@@ -971,9 +979,85 @@ function forceDeleteManyDocuments(context, filter, options) {
|
|
|
971
979
|
}
|
|
972
980
|
|
|
973
981
|
// src/capabilities/model/model-instance-config.ts
|
|
982
|
+
var runtimeModelIndexTasks = /* @__PURE__ */ new WeakMap();
|
|
983
|
+
var fallbackModelIndexTasks = /* @__PURE__ */ new Map();
|
|
974
984
|
function toCompatDefinition(definition) {
|
|
975
985
|
return definition;
|
|
976
986
|
}
|
|
987
|
+
function stableIndexStringify(value) {
|
|
988
|
+
if (value instanceof Date) {
|
|
989
|
+
return JSON.stringify(value.toISOString());
|
|
990
|
+
}
|
|
991
|
+
if (Array.isArray(value)) {
|
|
992
|
+
return `[${value.map((item) => stableIndexStringify(item)).join(",")}]`;
|
|
993
|
+
}
|
|
994
|
+
if (value && typeof value === "object") {
|
|
995
|
+
const entries = Object.entries(value).filter(([, current]) => current !== void 0).sort(([left], [right]) => left.localeCompare(right));
|
|
996
|
+
return `{${entries.map(([key, current]) => `${JSON.stringify(key)}:${stableIndexStringify(current)}`).join(",")}}`;
|
|
997
|
+
}
|
|
998
|
+
return JSON.stringify(value) ?? "undefined";
|
|
999
|
+
}
|
|
1000
|
+
function getIndexTaskRegistry(runtime) {
|
|
1001
|
+
if (!runtime) {
|
|
1002
|
+
return fallbackModelIndexTasks;
|
|
1003
|
+
}
|
|
1004
|
+
let registry = runtimeModelIndexTasks.get(runtime);
|
|
1005
|
+
if (!registry) {
|
|
1006
|
+
registry = /* @__PURE__ */ new Map();
|
|
1007
|
+
runtimeModelIndexTasks.set(runtime, registry);
|
|
1008
|
+
}
|
|
1009
|
+
return registry;
|
|
1010
|
+
}
|
|
1011
|
+
function resolveIndexTaskScope(collection, options) {
|
|
1012
|
+
try {
|
|
1013
|
+
const namespace = collection.getNamespace();
|
|
1014
|
+
return {
|
|
1015
|
+
dbName: options?.dbName ?? namespace.db,
|
|
1016
|
+
poolName: options?.poolName ?? "default",
|
|
1017
|
+
collectionName: options?.collectionName ?? namespace.collection
|
|
1018
|
+
};
|
|
1019
|
+
} catch {
|
|
1020
|
+
return {
|
|
1021
|
+
dbName: options?.dbName ?? "default",
|
|
1022
|
+
poolName: options?.poolName ?? "default",
|
|
1023
|
+
collectionName: options?.collectionName ?? "unknown"
|
|
1024
|
+
};
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
function warnIndexFailure(runtime, taskKey, error) {
|
|
1028
|
+
const logger = runtime;
|
|
1029
|
+
logger?.logger?.warn?.("[MonSQLize] model index creation failed", {
|
|
1030
|
+
taskKey,
|
|
1031
|
+
error: error instanceof Error ? error.message : String(error)
|
|
1032
|
+
});
|
|
1033
|
+
}
|
|
1034
|
+
function scheduleIndexTask(collection, key, indexOptions, options) {
|
|
1035
|
+
const scope = resolveIndexTaskScope(collection, options);
|
|
1036
|
+
const indexFingerprint = stableIndexStringify({ key, options: indexOptions });
|
|
1037
|
+
const taskKey = `${scope.poolName}:${scope.dbName}:${scope.collectionName}:${indexFingerprint}`;
|
|
1038
|
+
const registry = getIndexTaskRegistry(options?.runtime);
|
|
1039
|
+
const existing = registry.get(taskKey);
|
|
1040
|
+
if (existing && existing.status !== "failed") {
|
|
1041
|
+
return;
|
|
1042
|
+
}
|
|
1043
|
+
const task = {
|
|
1044
|
+
status: "pending",
|
|
1045
|
+
promise: new Promise((resolve) => {
|
|
1046
|
+
setImmediate(() => {
|
|
1047
|
+
Promise.resolve().then(() => collection.createIndex(key, indexOptions)).then(() => {
|
|
1048
|
+
task.status = "fulfilled";
|
|
1049
|
+
resolve();
|
|
1050
|
+
}).catch((error) => {
|
|
1051
|
+
task.status = "failed";
|
|
1052
|
+
task.error = error;
|
|
1053
|
+
warnIndexFailure(options?.runtime, taskKey, error);
|
|
1054
|
+
resolve();
|
|
1055
|
+
});
|
|
1056
|
+
});
|
|
1057
|
+
})
|
|
1058
|
+
};
|
|
1059
|
+
registry.set(taskKey, task);
|
|
1060
|
+
}
|
|
977
1061
|
function getModelEnums(definition) {
|
|
978
1062
|
return toCompatDefinition(definition).enums ?? {};
|
|
979
1063
|
}
|
|
@@ -1106,31 +1190,27 @@ function initializeModelV1Methods(target, definition) {
|
|
|
1106
1190
|
return {};
|
|
1107
1191
|
}
|
|
1108
1192
|
}
|
|
1109
|
-
function scheduleModelIndexes(collection, definition, softDeleteConfig) {
|
|
1193
|
+
function scheduleModelIndexes(collection, definition, softDeleteConfig, options) {
|
|
1110
1194
|
if (softDeleteConfig?.enabled && softDeleteConfig.type === "timestamp" && softDeleteConfig.ttl) {
|
|
1111
1195
|
const softDeleteIndex = softDeleteConfig;
|
|
1112
|
-
|
|
1113
|
-
collection
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
});
|
|
1196
|
+
scheduleIndexTask(
|
|
1197
|
+
collection,
|
|
1198
|
+
{ [softDeleteIndex.field]: 1 },
|
|
1199
|
+
{ expireAfterSeconds: softDeleteIndex.ttl },
|
|
1200
|
+
options
|
|
1201
|
+
);
|
|
1119
1202
|
}
|
|
1120
1203
|
const indexes = toCompatDefinition(definition).indexes;
|
|
1121
1204
|
if (!Array.isArray(indexes) || indexes.length === 0) {
|
|
1122
1205
|
return;
|
|
1123
1206
|
}
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
continue;
|
|
1128
|
-
}
|
|
1129
|
-
const { key, ...indexOptions } = indexSpec;
|
|
1130
|
-
collection.createIndex(key, indexOptions).catch(() => {
|
|
1131
|
-
});
|
|
1207
|
+
for (const indexSpec of indexes) {
|
|
1208
|
+
if (!indexSpec?.key) {
|
|
1209
|
+
continue;
|
|
1132
1210
|
}
|
|
1133
|
-
|
|
1211
|
+
const { key, ...indexOptions } = indexSpec;
|
|
1212
|
+
scheduleIndexTask(collection, key, indexOptions, options);
|
|
1213
|
+
}
|
|
1134
1214
|
}
|
|
1135
1215
|
|
|
1136
1216
|
// src/capabilities/model/model-write-helpers.ts
|
|
@@ -1693,7 +1773,12 @@ var ModelInstance = class {
|
|
|
1693
1773
|
this.softDeleteConfig = this._softDeleteConfig;
|
|
1694
1774
|
this._versionConfig = resolveModelVersionConfig(options.definition);
|
|
1695
1775
|
this._v1HooksFactory = resolveModelHooksFactory(options.definition);
|
|
1696
|
-
scheduleModelIndexes(this.collection, options.definition, this._softDeleteConfig
|
|
1776
|
+
scheduleModelIndexes(this.collection, options.definition, this._softDeleteConfig, {
|
|
1777
|
+
runtime: this.runtime,
|
|
1778
|
+
dbName: options.dbName,
|
|
1779
|
+
poolName: options.poolName,
|
|
1780
|
+
collectionName: options.collectionName
|
|
1781
|
+
});
|
|
1697
1782
|
this._v1InstanceMethods = initializeModelV1Methods(this, options.definition);
|
|
1698
1783
|
}
|
|
1699
1784
|
/** v1 compat: expose relations map as _relations */
|
|
@@ -3113,10 +3198,19 @@ var HealthChecker = class {
|
|
|
3113
3198
|
};
|
|
3114
3199
|
|
|
3115
3200
|
// src/capabilities/pool/pool-selector.ts
|
|
3201
|
+
var POOL_STRATEGY_ALIASES = {
|
|
3202
|
+
"round-robin": "roundRobin",
|
|
3203
|
+
"least-connections": "leastConnections",
|
|
3204
|
+
random: "weighted"
|
|
3205
|
+
};
|
|
3206
|
+
function normalizePoolStrategy(strategy) {
|
|
3207
|
+
const value = strategy ?? "auto";
|
|
3208
|
+
return POOL_STRATEGY_ALIASES[value] ?? value;
|
|
3209
|
+
}
|
|
3116
3210
|
var PoolSelector = class {
|
|
3117
3211
|
constructor(options = {}) {
|
|
3118
3212
|
this._roundRobinIndex = /* @__PURE__ */ new Map();
|
|
3119
|
-
this._strategy = options.strategy
|
|
3213
|
+
this._strategy = normalizePoolStrategy(options.strategy);
|
|
3120
3214
|
this._logger = options.logger ?? console;
|
|
3121
3215
|
}
|
|
3122
3216
|
select(pools, context) {
|
|
@@ -3229,8 +3323,8 @@ var PoolSelector = class {
|
|
|
3229
3323
|
return pools[0].name;
|
|
3230
3324
|
}
|
|
3231
3325
|
setStrategy(strategy) {
|
|
3232
|
-
this._strategy = strategy;
|
|
3233
|
-
this._logger.info?.(`[PoolSelector] Strategy changed: ${
|
|
3326
|
+
this._strategy = normalizePoolStrategy(strategy);
|
|
3327
|
+
this._logger.info?.(`[PoolSelector] Strategy changed: ${this._strategy}`);
|
|
3234
3328
|
}
|
|
3235
3329
|
getStrategy() {
|
|
3236
3330
|
return this._strategy;
|
|
@@ -7424,6 +7518,92 @@ function createRuntimeAccessors(config) {
|
|
|
7424
7518
|
};
|
|
7425
7519
|
}
|
|
7426
7520
|
|
|
7521
|
+
// src/entry/runtime-compat-accessors.ts
|
|
7522
|
+
function asRuntimeCompatRecord(value) {
|
|
7523
|
+
return value;
|
|
7524
|
+
}
|
|
7525
|
+
function requireCompatDbInstance(value) {
|
|
7526
|
+
const dbInstance = asRuntimeCompatRecord(value).dbInstance;
|
|
7527
|
+
if (!dbInstance) {
|
|
7528
|
+
throw createError(ErrorCodes.NOT_CONNECTED, "Database is not connected. Call connect() first.");
|
|
7529
|
+
}
|
|
7530
|
+
return dbInstance;
|
|
7531
|
+
}
|
|
7532
|
+
function requireCompatPoolManagerRecord(value) {
|
|
7533
|
+
const poolManager = asRuntimeCompatRecord(value)._poolManager;
|
|
7534
|
+
if (!poolManager) {
|
|
7535
|
+
throw createError(ErrorCodes.NO_POOL_MANAGER, "No pool manager configured. Add pools to MonSQLize constructor options.");
|
|
7536
|
+
}
|
|
7537
|
+
return poolManager;
|
|
7538
|
+
}
|
|
7539
|
+
function resolvePoolClientFromRecord(poolManager, poolName) {
|
|
7540
|
+
const getPoolV1 = poolManager["_getPool"];
|
|
7541
|
+
const getPoolV2 = poolManager["getPool"];
|
|
7542
|
+
if (typeof getPoolV1 === "function") {
|
|
7543
|
+
return getPoolV1.call(poolManager, poolName) ?? null;
|
|
7544
|
+
}
|
|
7545
|
+
if (typeof getPoolV2 === "function") {
|
|
7546
|
+
try {
|
|
7547
|
+
return getPoolV2.call(poolManager, poolName) ?? null;
|
|
7548
|
+
} catch {
|
|
7549
|
+
return null;
|
|
7550
|
+
}
|
|
7551
|
+
}
|
|
7552
|
+
return null;
|
|
7553
|
+
}
|
|
7554
|
+
function assertCompatPoolExists(poolManager, poolName) {
|
|
7555
|
+
if (resolvePoolClientFromRecord(poolManager, poolName)) {
|
|
7556
|
+
return;
|
|
7557
|
+
}
|
|
7558
|
+
const getNames = poolManager["getPoolNames"];
|
|
7559
|
+
const available = typeof getNames === "function" ? getNames.call(poolManager) : [];
|
|
7560
|
+
const error = createError(ErrorCodes.POOL_NOT_FOUND, `Pool '${poolName}' not found. Available pools: [${available.join(", ")}]`);
|
|
7561
|
+
error["available"] = available;
|
|
7562
|
+
throw error;
|
|
7563
|
+
}
|
|
7564
|
+
function createPoolScope(runtime, poolName) {
|
|
7565
|
+
return {
|
|
7566
|
+
collection: (name) => runtime.scopedCollection(name, { pool: poolName }),
|
|
7567
|
+
model: (name) => runtime.scopedModel(name, { pool: poolName }),
|
|
7568
|
+
use: (dbName) => ({
|
|
7569
|
+
collection: (name) => runtime.scopedCollection(name, { pool: poolName, database: dbName }),
|
|
7570
|
+
model: (name) => runtime.scopedModel(name, { pool: poolName, database: dbName })
|
|
7571
|
+
})
|
|
7572
|
+
};
|
|
7573
|
+
}
|
|
7574
|
+
function getRegisteredModelMetadata(registered) {
|
|
7575
|
+
const definition = registered.definition;
|
|
7576
|
+
return {
|
|
7577
|
+
actualCollectionName: definition.collection ?? definition.name ?? registered.collectionName,
|
|
7578
|
+
connection: definition.connection
|
|
7579
|
+
};
|
|
7580
|
+
}
|
|
7581
|
+
function getRuntimeDatabaseName(value) {
|
|
7582
|
+
return asRuntimeCompatRecord(value).databaseName ?? "default";
|
|
7583
|
+
}
|
|
7584
|
+
function getCompatModelInstanceCache(value) {
|
|
7585
|
+
const record = asRuntimeCompatRecord(value);
|
|
7586
|
+
if (!record._modelInstances) {
|
|
7587
|
+
record._modelInstances = new MemoryCache({
|
|
7588
|
+
maxEntries: 1e5,
|
|
7589
|
+
enableStats: false
|
|
7590
|
+
});
|
|
7591
|
+
}
|
|
7592
|
+
return record._modelInstances;
|
|
7593
|
+
}
|
|
7594
|
+
function createCompatModelInstance(config) {
|
|
7595
|
+
return new ModelInstance(
|
|
7596
|
+
config.collection,
|
|
7597
|
+
config.runtime,
|
|
7598
|
+
{
|
|
7599
|
+
collectionName: config.collectionName,
|
|
7600
|
+
dbName: config.dbName,
|
|
7601
|
+
poolName: config.poolName,
|
|
7602
|
+
definition: config.definition
|
|
7603
|
+
}
|
|
7604
|
+
);
|
|
7605
|
+
}
|
|
7606
|
+
|
|
7427
7607
|
// src/entry/runtime-model.ts
|
|
7428
7608
|
function createRuntimeModelHost(config) {
|
|
7429
7609
|
return {
|
|
@@ -7438,19 +7618,20 @@ function createRuntimeModelInstance(host, name, scope) {
|
|
|
7438
7618
|
if (!registered) {
|
|
7439
7619
|
throw createError(ErrorCodes.MODEL_NOT_DEFINED, `Model '${name}' is not defined.`);
|
|
7440
7620
|
}
|
|
7441
|
-
const
|
|
7442
|
-
const
|
|
7443
|
-
const
|
|
7621
|
+
const { actualCollectionName, connection } = getRegisteredModelMetadata(registered);
|
|
7622
|
+
const databaseName = connection?.database ?? scope.database ?? resolveDatabaseName(host.options);
|
|
7623
|
+
const poolName = connection?.pool ?? scope.pool;
|
|
7624
|
+
const cacheKey = `${poolName ?? "default"}:${databaseName}:${registered.collectionName}:${actualCollectionName}`;
|
|
7444
7625
|
const revision = Model.getRevision(registered.collectionName);
|
|
7445
7626
|
const cached = host._modelInstances.get(cacheKey);
|
|
7446
7627
|
if (cached && cached.revision === revision) {
|
|
7447
7628
|
return cached.instance;
|
|
7448
7629
|
}
|
|
7449
7630
|
const instance = new ModelInstance(
|
|
7450
|
-
host.scopedCollection(
|
|
7631
|
+
host.scopedCollection(actualCollectionName, { database: databaseName, pool: poolName }),
|
|
7451
7632
|
host.runtime,
|
|
7452
7633
|
{
|
|
7453
|
-
collectionName:
|
|
7634
|
+
collectionName: actualCollectionName,
|
|
7454
7635
|
dbName: databaseName,
|
|
7455
7636
|
poolName,
|
|
7456
7637
|
definition: registered.definition
|
|
@@ -7533,92 +7714,6 @@ function createRuntimeCoreAccessors(runtime) {
|
|
|
7533
7714
|
});
|
|
7534
7715
|
}
|
|
7535
7716
|
|
|
7536
|
-
// src/entry/runtime-compat-accessors.ts
|
|
7537
|
-
function asRuntimeCompatRecord(value) {
|
|
7538
|
-
return value;
|
|
7539
|
-
}
|
|
7540
|
-
function requireCompatDbInstance(value) {
|
|
7541
|
-
const dbInstance = asRuntimeCompatRecord(value).dbInstance;
|
|
7542
|
-
if (!dbInstance) {
|
|
7543
|
-
throw createError(ErrorCodes.NOT_CONNECTED, "Database is not connected. Call connect() first.");
|
|
7544
|
-
}
|
|
7545
|
-
return dbInstance;
|
|
7546
|
-
}
|
|
7547
|
-
function requireCompatPoolManagerRecord(value) {
|
|
7548
|
-
const poolManager = asRuntimeCompatRecord(value)._poolManager;
|
|
7549
|
-
if (!poolManager) {
|
|
7550
|
-
throw createError(ErrorCodes.NO_POOL_MANAGER, "No pool manager configured. Add pools to MonSQLize constructor options.");
|
|
7551
|
-
}
|
|
7552
|
-
return poolManager;
|
|
7553
|
-
}
|
|
7554
|
-
function resolvePoolClientFromRecord(poolManager, poolName) {
|
|
7555
|
-
const getPoolV1 = poolManager["_getPool"];
|
|
7556
|
-
const getPoolV2 = poolManager["getPool"];
|
|
7557
|
-
if (typeof getPoolV1 === "function") {
|
|
7558
|
-
return getPoolV1.call(poolManager, poolName) ?? null;
|
|
7559
|
-
}
|
|
7560
|
-
if (typeof getPoolV2 === "function") {
|
|
7561
|
-
try {
|
|
7562
|
-
return getPoolV2.call(poolManager, poolName) ?? null;
|
|
7563
|
-
} catch {
|
|
7564
|
-
return null;
|
|
7565
|
-
}
|
|
7566
|
-
}
|
|
7567
|
-
return null;
|
|
7568
|
-
}
|
|
7569
|
-
function assertCompatPoolExists(poolManager, poolName) {
|
|
7570
|
-
if (resolvePoolClientFromRecord(poolManager, poolName)) {
|
|
7571
|
-
return;
|
|
7572
|
-
}
|
|
7573
|
-
const getNames = poolManager["getPoolNames"];
|
|
7574
|
-
const available = typeof getNames === "function" ? getNames.call(poolManager) : [];
|
|
7575
|
-
const error = createError(ErrorCodes.POOL_NOT_FOUND, `Pool '${poolName}' not found. Available pools: [${available.join(", ")}]`);
|
|
7576
|
-
error["available"] = available;
|
|
7577
|
-
throw error;
|
|
7578
|
-
}
|
|
7579
|
-
function createPoolScope(runtime, poolName) {
|
|
7580
|
-
return {
|
|
7581
|
-
collection: (name) => runtime.scopedCollection(name, { pool: poolName }),
|
|
7582
|
-
model: (name) => runtime.scopedModel(name, { pool: poolName }),
|
|
7583
|
-
use: (dbName) => ({
|
|
7584
|
-
collection: (name) => runtime.scopedCollection(name, { pool: poolName, database: dbName }),
|
|
7585
|
-
model: (name) => runtime.scopedModel(name, { pool: poolName, database: dbName })
|
|
7586
|
-
})
|
|
7587
|
-
};
|
|
7588
|
-
}
|
|
7589
|
-
function getRegisteredModelMetadata(registered) {
|
|
7590
|
-
const definition = registered.definition;
|
|
7591
|
-
return {
|
|
7592
|
-
actualCollectionName: definition.collection ?? definition.name ?? registered.collectionName,
|
|
7593
|
-
connection: definition.connection
|
|
7594
|
-
};
|
|
7595
|
-
}
|
|
7596
|
-
function getRuntimeDatabaseName(value) {
|
|
7597
|
-
return asRuntimeCompatRecord(value).databaseName ?? "default";
|
|
7598
|
-
}
|
|
7599
|
-
function getCompatModelInstanceCache(value) {
|
|
7600
|
-
const record = asRuntimeCompatRecord(value);
|
|
7601
|
-
if (!record._modelInstances) {
|
|
7602
|
-
record._modelInstances = new MemoryCache({
|
|
7603
|
-
maxEntries: 1e5,
|
|
7604
|
-
enableStats: false
|
|
7605
|
-
});
|
|
7606
|
-
}
|
|
7607
|
-
return record._modelInstances;
|
|
7608
|
-
}
|
|
7609
|
-
function createCompatModelInstance(config) {
|
|
7610
|
-
return new ModelInstance(
|
|
7611
|
-
config.collection,
|
|
7612
|
-
config.runtime,
|
|
7613
|
-
{
|
|
7614
|
-
collectionName: config.collectionName,
|
|
7615
|
-
dbName: config.dbName,
|
|
7616
|
-
poolName: config.poolName,
|
|
7617
|
-
definition: config.definition
|
|
7618
|
-
}
|
|
7619
|
-
);
|
|
7620
|
-
}
|
|
7621
|
-
|
|
7622
7717
|
// src/entry/runtime-admin-bridge.ts
|
|
7623
7718
|
var import_node_perf_hooks = require("node:perf_hooks");
|
|
7624
7719
|
function createLegacyCollectionBridge(config) {
|
|
@@ -9692,31 +9787,132 @@ function toOptionalNumber(value) {
|
|
|
9692
9787
|
function toOptionalBoolean(value) {
|
|
9693
9788
|
return typeof value === "boolean" ? value : void 0;
|
|
9694
9789
|
}
|
|
9790
|
+
function isObjectRecord(value) {
|
|
9791
|
+
return !!value && typeof value === "object" && !Array.isArray(value);
|
|
9792
|
+
}
|
|
9793
|
+
function buildMemoryCache(input, fallback = {}) {
|
|
9794
|
+
if (input instanceof MemoryCache) return input;
|
|
9795
|
+
if (isCacheLike(input)) return input;
|
|
9796
|
+
const opts = isObjectRecord(input) ? input : {};
|
|
9797
|
+
return new MemoryCache({
|
|
9798
|
+
maxEntries: toOptionalNumber(opts.maxEntries ?? opts.maxSize ?? fallback.maxEntries ?? fallback.maxSize),
|
|
9799
|
+
maxMemory: toOptionalNumber(opts.maxMemory ?? fallback.maxMemory),
|
|
9800
|
+
defaultTtl: toOptionalNumber(opts.defaultTtl ?? opts.ttl ?? fallback.defaultTtl ?? fallback.ttl),
|
|
9801
|
+
enableStats: toOptionalBoolean(opts.enableStats ?? fallback.enableStats),
|
|
9802
|
+
enableTags: toOptionalBoolean(opts.enableTags ?? fallback.enableTags),
|
|
9803
|
+
cleanupInterval: toOptionalNumber(opts.cleanupInterval ?? fallback.cleanupInterval),
|
|
9804
|
+
enabled: toOptionalBoolean(opts.enabled ?? fallback.enabled)
|
|
9805
|
+
});
|
|
9806
|
+
}
|
|
9807
|
+
function prefixKey(prefix, key) {
|
|
9808
|
+
if (!prefix || key.startsWith(prefix)) return key;
|
|
9809
|
+
return `${prefix}${key}`;
|
|
9810
|
+
}
|
|
9811
|
+
function unprefixKey(prefix, key) {
|
|
9812
|
+
if (!prefix || !key.startsWith(prefix)) return key;
|
|
9813
|
+
return key.slice(prefix.length);
|
|
9814
|
+
}
|
|
9815
|
+
function wrapRemoteCache(cache, options = {}) {
|
|
9816
|
+
const prefix = typeof options.prefix === "string" && options.prefix.length > 0 ? options.prefix : void 0;
|
|
9817
|
+
const defaultTtl = options.defaultTtl;
|
|
9818
|
+
if (!prefix && defaultTtl === void 0) return cache;
|
|
9819
|
+
const key = (value) => prefixKey(prefix, value);
|
|
9820
|
+
const keys = (values) => values.map(key);
|
|
9821
|
+
const resolveTtl = (ttl) => ttl ?? defaultTtl;
|
|
9822
|
+
return new Proxy(cache, {
|
|
9823
|
+
get(target, prop, receiver) {
|
|
9824
|
+
switch (prop) {
|
|
9825
|
+
case "get":
|
|
9826
|
+
return (cacheKey) => target.get(key(cacheKey));
|
|
9827
|
+
case "set":
|
|
9828
|
+
return (cacheKey, value, ttl) => target.set(key(cacheKey), value, resolveTtl(ttl));
|
|
9829
|
+
case "del":
|
|
9830
|
+
return (cacheKey) => target.del(key(cacheKey));
|
|
9831
|
+
case "exists":
|
|
9832
|
+
return (cacheKey) => target.exists(key(cacheKey));
|
|
9833
|
+
case "has":
|
|
9834
|
+
return (cacheKey) => target.has(key(cacheKey));
|
|
9835
|
+
case "getMany":
|
|
9836
|
+
return async (cacheKeys) => {
|
|
9837
|
+
const result = await target.getMany(keys(cacheKeys));
|
|
9838
|
+
return Object.fromEntries(
|
|
9839
|
+
Object.entries(result).map(([cacheKey, value]) => [unprefixKey(prefix, cacheKey), value])
|
|
9840
|
+
);
|
|
9841
|
+
};
|
|
9842
|
+
case "setMany":
|
|
9843
|
+
return (entries, ttl) => target.setMany(
|
|
9844
|
+
Object.fromEntries(
|
|
9845
|
+
Object.entries(entries).map(([cacheKey, value]) => [key(cacheKey), value])
|
|
9846
|
+
),
|
|
9847
|
+
resolveTtl(ttl)
|
|
9848
|
+
);
|
|
9849
|
+
case "delMany":
|
|
9850
|
+
return (cacheKeys) => target.delMany(keys(cacheKeys));
|
|
9851
|
+
case "delPattern":
|
|
9852
|
+
return (pattern) => target.delPattern(key(pattern));
|
|
9853
|
+
case "keys":
|
|
9854
|
+
return async (pattern) => {
|
|
9855
|
+
const result = await target.keys(pattern ? key(pattern) : void 0);
|
|
9856
|
+
return result.map((cacheKey) => unprefixKey(prefix, cacheKey));
|
|
9857
|
+
};
|
|
9858
|
+
default: {
|
|
9859
|
+
const value = Reflect.get(target, prop, receiver);
|
|
9860
|
+
return typeof value === "function" ? value.bind(target) : value;
|
|
9861
|
+
}
|
|
9862
|
+
}
|
|
9863
|
+
}
|
|
9864
|
+
});
|
|
9865
|
+
}
|
|
9866
|
+
function buildRedisCache(input) {
|
|
9867
|
+
if (!input || !isObjectRecord(input)) return void 0;
|
|
9868
|
+
const prefix = typeof input.prefix === "string" ? input.prefix : void 0;
|
|
9869
|
+
const defaultTtl = toOptionalNumber(input.defaultTtl ?? input.ttl);
|
|
9870
|
+
if (isCacheLike(input)) {
|
|
9871
|
+
return wrapRemoteCache(input, { prefix, defaultTtl });
|
|
9872
|
+
}
|
|
9873
|
+
if (input.enabled === false) return void 0;
|
|
9874
|
+
const embeddedCache = input.cache ?? input.adapter;
|
|
9875
|
+
if (isCacheLike(embeddedCache)) {
|
|
9876
|
+
return wrapRemoteCache(embeddedCache, { prefix, defaultTtl });
|
|
9877
|
+
}
|
|
9878
|
+
const redisTarget = input.url ?? input.uri ?? input.instance ?? input.client ?? input.redis;
|
|
9879
|
+
if (redisTarget === void 0 && input.enabled !== true) {
|
|
9880
|
+
return void 0;
|
|
9881
|
+
}
|
|
9882
|
+
const redisCache = createRedisCacheAdapter(redisTarget);
|
|
9883
|
+
return wrapRemoteCache(redisCache, { prefix, defaultTtl });
|
|
9884
|
+
}
|
|
9885
|
+
function isVextCacheShape(input) {
|
|
9886
|
+
return isObjectRecord(input.memory) || isObjectRecord(input.redis);
|
|
9887
|
+
}
|
|
9695
9888
|
function normalizeRuntimeCache(cache) {
|
|
9696
9889
|
if (cache instanceof MemoryCache) return cache;
|
|
9697
9890
|
if (isCacheLike(cache)) return cache;
|
|
9698
9891
|
const input = cache ?? {};
|
|
9699
|
-
if (input
|
|
9700
|
-
const
|
|
9701
|
-
const local =
|
|
9702
|
-
|
|
9703
|
-
|
|
9704
|
-
|
|
9705
|
-
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
|
|
9892
|
+
if (isVextCacheShape(input)) {
|
|
9893
|
+
const memoryInput = isObjectRecord(input.memory) ? input.memory : {};
|
|
9894
|
+
const local = buildMemoryCache(
|
|
9895
|
+
input.memory,
|
|
9896
|
+
{
|
|
9897
|
+
...input,
|
|
9898
|
+
enabled: memoryInput.enabled === false ? false : input.enabled
|
|
9899
|
+
}
|
|
9900
|
+
);
|
|
9901
|
+
const remote = buildRedisCache(input.redis);
|
|
9902
|
+
const policy = input.policy ?? {};
|
|
9903
|
+
return new MultiLevelCache({
|
|
9904
|
+
local,
|
|
9905
|
+
remote,
|
|
9906
|
+
writePolicy: policy.writePolicy ?? "both",
|
|
9907
|
+
backfillOnRemoteHit: policy.backfillLocalOnRemoteHit ?? true,
|
|
9908
|
+
remoteTimeoutMs: isObjectRecord(input.redis) ? toOptionalNumber(input.redis.timeoutMs) : void 0,
|
|
9909
|
+
publish: input.publish
|
|
9709
9910
|
});
|
|
9911
|
+
}
|
|
9912
|
+
if (input.multiLevel === true || input.local !== void 0 && typeof input.local === "object") {
|
|
9913
|
+
const local = buildMemoryCache(input.local);
|
|
9710
9914
|
const remoteInput = input.remote;
|
|
9711
|
-
const remote = isCacheLike(remoteInput) ? remoteInput : remoteInput ?
|
|
9712
|
-
maxEntries: toOptionalNumber(remoteInput.maxEntries ?? remoteInput.maxSize),
|
|
9713
|
-
maxMemory: toOptionalNumber(remoteInput.maxMemory),
|
|
9714
|
-
defaultTtl: toOptionalNumber(remoteInput.defaultTtl ?? remoteInput.ttl),
|
|
9715
|
-
enableStats: toOptionalBoolean(remoteInput.enableStats),
|
|
9716
|
-
enableTags: toOptionalBoolean(remoteInput.enableTags),
|
|
9717
|
-
cleanupInterval: toOptionalNumber(remoteInput.cleanupInterval),
|
|
9718
|
-
enabled: toOptionalBoolean(remoteInput.enabled)
|
|
9719
|
-
}) : void 0;
|
|
9915
|
+
const remote = isCacheLike(remoteInput) ? remoteInput : remoteInput ? buildMemoryCache(remoteInput) : void 0;
|
|
9720
9916
|
const policy = input.policy ?? {};
|
|
9721
9917
|
return new MultiLevelCache({
|
|
9722
9918
|
local,
|
|
@@ -9727,15 +9923,7 @@ function normalizeRuntimeCache(cache) {
|
|
|
9727
9923
|
publish: input.publish
|
|
9728
9924
|
});
|
|
9729
9925
|
}
|
|
9730
|
-
return
|
|
9731
|
-
maxEntries: toOptionalNumber(input.maxEntries ?? input.maxSize),
|
|
9732
|
-
maxMemory: toOptionalNumber(input.maxMemory),
|
|
9733
|
-
defaultTtl: toOptionalNumber(input.defaultTtl ?? input.ttl),
|
|
9734
|
-
enableStats: toOptionalBoolean(input.enableStats),
|
|
9735
|
-
enableTags: toOptionalBoolean(input.enableTags),
|
|
9736
|
-
cleanupInterval: toOptionalNumber(input.cleanupInterval),
|
|
9737
|
-
enabled: toOptionalBoolean(input.enabled)
|
|
9738
|
-
});
|
|
9926
|
+
return buildMemoryCache(input);
|
|
9739
9927
|
}
|
|
9740
9928
|
|
|
9741
9929
|
// src/capabilities/function-cache/index.ts
|