@classytic/mongokit 3.0.3 → 3.0.5
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/dist/actions/index.d.ts +2 -2
- package/dist/{index-CMCrkd2v.d.ts → index-BljuCDFC.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +712 -23
- package/dist/pagination/PaginationEngine.d.ts +1 -1
- package/dist/plugins/index.d.ts +34 -2
- package/dist/plugins/index.js +148 -12
- package/dist/queryParser-CxzCjzXd.d.ts +303 -0
- package/dist/{types-B3dPUKjs.d.ts → types-CHIDluaP.d.ts} +53 -20
- package/dist/utils/index.d.ts +4 -111
- package/dist/utils/index.js +86 -16
- package/package.json +1 -1
- package/dist/memory-cache-Bn_-Kk-0.d.ts +0 -142
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import mongoose4 from 'mongoose';
|
|
2
2
|
|
|
3
3
|
var __defProp = Object.defineProperty;
|
|
4
4
|
var __export = (target, all) => {
|
|
@@ -521,12 +521,12 @@ function validateCursorVersion(cursorVersion, expectedVersion) {
|
|
|
521
521
|
}
|
|
522
522
|
function serializeValue(value) {
|
|
523
523
|
if (value instanceof Date) return value.toISOString();
|
|
524
|
-
if (value instanceof
|
|
524
|
+
if (value instanceof mongoose4.Types.ObjectId) return value.toString();
|
|
525
525
|
return value;
|
|
526
526
|
}
|
|
527
527
|
function getValueType(value) {
|
|
528
528
|
if (value instanceof Date) return "date";
|
|
529
|
-
if (value instanceof
|
|
529
|
+
if (value instanceof mongoose4.Types.ObjectId) return "objectid";
|
|
530
530
|
if (typeof value === "boolean") return "boolean";
|
|
531
531
|
if (typeof value === "number") return "number";
|
|
532
532
|
if (typeof value === "string") return "string";
|
|
@@ -537,7 +537,7 @@ function rehydrateValue(serialized, type) {
|
|
|
537
537
|
case "date":
|
|
538
538
|
return new Date(serialized);
|
|
539
539
|
case "objectid":
|
|
540
|
-
return new
|
|
540
|
+
return new mongoose4.Types.ObjectId(serialized);
|
|
541
541
|
case "boolean":
|
|
542
542
|
return Boolean(serialized);
|
|
543
543
|
case "number":
|
|
@@ -1001,7 +1001,7 @@ var Repository = class {
|
|
|
1001
1001
|
const hasCursorParam = "cursor" in params || "after" in params;
|
|
1002
1002
|
const hasExplicitSort = params.sort !== void 0;
|
|
1003
1003
|
const useKeyset = !hasPageParam && (hasCursorParam || hasExplicitSort);
|
|
1004
|
-
const filters = params.filters || {};
|
|
1004
|
+
const filters = context.filters || params.filters || {};
|
|
1005
1005
|
const search = params.search;
|
|
1006
1006
|
const sort = params.sort || "-createdAt";
|
|
1007
1007
|
const limit = params.limit || params.pagination?.limit || this._pagination.config.defaultLimit;
|
|
@@ -1109,7 +1109,7 @@ var Repository = class {
|
|
|
1109
1109
|
* Execute callback within a transaction
|
|
1110
1110
|
*/
|
|
1111
1111
|
async withTransaction(callback) {
|
|
1112
|
-
const session = await
|
|
1112
|
+
const session = await mongoose4.startSession();
|
|
1113
1113
|
session.startTransaction();
|
|
1114
1114
|
try {
|
|
1115
1115
|
const result = await callback(session);
|
|
@@ -1172,11 +1172,11 @@ var Repository = class {
|
|
|
1172
1172
|
* Handle errors with proper HTTP status codes
|
|
1173
1173
|
*/
|
|
1174
1174
|
_handleError(error) {
|
|
1175
|
-
if (error instanceof
|
|
1175
|
+
if (error instanceof mongoose4.Error.ValidationError) {
|
|
1176
1176
|
const messages = Object.values(error.errors).map((err) => err.message);
|
|
1177
1177
|
return createError(400, `Validation Error: ${messages.join(", ")}`);
|
|
1178
1178
|
}
|
|
1179
|
-
if (error instanceof
|
|
1179
|
+
if (error instanceof mongoose4.Error.CastError) {
|
|
1180
1180
|
return createError(400, `Invalid ${error.path}: ${error.value}`);
|
|
1181
1181
|
}
|
|
1182
1182
|
if (error.status && error.message) return error;
|
|
@@ -1329,12 +1329,45 @@ function auditLogPlugin(logger) {
|
|
|
1329
1329
|
}
|
|
1330
1330
|
|
|
1331
1331
|
// src/plugins/soft-delete.plugin.ts
|
|
1332
|
+
function buildDeletedFilter(deletedField, filterMode, includeDeleted) {
|
|
1333
|
+
if (includeDeleted) {
|
|
1334
|
+
return {};
|
|
1335
|
+
}
|
|
1336
|
+
if (filterMode === "exists") {
|
|
1337
|
+
return { [deletedField]: { $exists: false } };
|
|
1338
|
+
}
|
|
1339
|
+
return { [deletedField]: null };
|
|
1340
|
+
}
|
|
1341
|
+
function buildGetDeletedFilter(deletedField, filterMode) {
|
|
1342
|
+
if (filterMode === "exists") {
|
|
1343
|
+
return { [deletedField]: { $exists: true, $ne: null } };
|
|
1344
|
+
}
|
|
1345
|
+
return { [deletedField]: { $ne: null } };
|
|
1346
|
+
}
|
|
1332
1347
|
function softDeletePlugin(options = {}) {
|
|
1333
1348
|
const deletedField = options.deletedField || "deletedAt";
|
|
1334
1349
|
const deletedByField = options.deletedByField || "deletedBy";
|
|
1350
|
+
const filterMode = options.filterMode || "null";
|
|
1351
|
+
const addRestoreMethod = options.addRestoreMethod !== false;
|
|
1352
|
+
const addGetDeletedMethod = options.addGetDeletedMethod !== false;
|
|
1353
|
+
const ttlDays = options.ttlDays;
|
|
1335
1354
|
return {
|
|
1336
1355
|
name: "softDelete",
|
|
1337
1356
|
apply(repo) {
|
|
1357
|
+
if (ttlDays !== void 0 && ttlDays > 0) {
|
|
1358
|
+
const ttlSeconds = ttlDays * 24 * 60 * 60;
|
|
1359
|
+
repo.Model.collection.createIndex(
|
|
1360
|
+
{ [deletedField]: 1 },
|
|
1361
|
+
{
|
|
1362
|
+
expireAfterSeconds: ttlSeconds,
|
|
1363
|
+
partialFilterExpression: { [deletedField]: { $type: "date" } }
|
|
1364
|
+
}
|
|
1365
|
+
).catch((err) => {
|
|
1366
|
+
if (!err.message.includes("already exists")) {
|
|
1367
|
+
console.warn(`[softDeletePlugin] Failed to create TTL index: ${err.message}`);
|
|
1368
|
+
}
|
|
1369
|
+
});
|
|
1370
|
+
}
|
|
1338
1371
|
repo.on("before:delete", async (context) => {
|
|
1339
1372
|
if (options.soft !== false) {
|
|
1340
1373
|
const updateData = {
|
|
@@ -1348,23 +1381,126 @@ function softDeletePlugin(options = {}) {
|
|
|
1348
1381
|
}
|
|
1349
1382
|
});
|
|
1350
1383
|
repo.on("before:getAll", (context) => {
|
|
1351
|
-
if (
|
|
1352
|
-
const
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1384
|
+
if (options.soft !== false) {
|
|
1385
|
+
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
1386
|
+
if (Object.keys(deleteFilter).length > 0) {
|
|
1387
|
+
const existingFilters = context.filters || {};
|
|
1388
|
+
context.filters = {
|
|
1389
|
+
...existingFilters,
|
|
1390
|
+
...deleteFilter
|
|
1391
|
+
};
|
|
1392
|
+
}
|
|
1358
1393
|
}
|
|
1359
1394
|
});
|
|
1360
1395
|
repo.on("before:getById", (context) => {
|
|
1361
|
-
if (
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1396
|
+
if (options.soft !== false) {
|
|
1397
|
+
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
1398
|
+
if (Object.keys(deleteFilter).length > 0) {
|
|
1399
|
+
context.query = {
|
|
1400
|
+
...context.query || {},
|
|
1401
|
+
...deleteFilter
|
|
1402
|
+
};
|
|
1403
|
+
}
|
|
1404
|
+
}
|
|
1405
|
+
});
|
|
1406
|
+
repo.on("before:getByQuery", (context) => {
|
|
1407
|
+
if (options.soft !== false) {
|
|
1408
|
+
const deleteFilter = buildDeletedFilter(deletedField, filterMode, !!context.includeDeleted);
|
|
1409
|
+
if (Object.keys(deleteFilter).length > 0) {
|
|
1410
|
+
context.query = {
|
|
1411
|
+
...context.query || {},
|
|
1412
|
+
...deleteFilter
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1366
1415
|
}
|
|
1367
1416
|
});
|
|
1417
|
+
if (addRestoreMethod) {
|
|
1418
|
+
const restoreMethod = async function(id, restoreOptions = {}) {
|
|
1419
|
+
const updateData = {
|
|
1420
|
+
[deletedField]: null,
|
|
1421
|
+
[deletedByField]: null
|
|
1422
|
+
};
|
|
1423
|
+
const result = await this.Model.findByIdAndUpdate(id, { $set: updateData }, {
|
|
1424
|
+
new: true,
|
|
1425
|
+
session: restoreOptions.session
|
|
1426
|
+
});
|
|
1427
|
+
if (!result) {
|
|
1428
|
+
const error = new Error(`Document with id '${id}' not found`);
|
|
1429
|
+
error.status = 404;
|
|
1430
|
+
throw error;
|
|
1431
|
+
}
|
|
1432
|
+
await this.emitAsync("after:restore", { id, result });
|
|
1433
|
+
return result;
|
|
1434
|
+
};
|
|
1435
|
+
if (typeof repo.registerMethod === "function") {
|
|
1436
|
+
repo.registerMethod("restore", restoreMethod);
|
|
1437
|
+
} else {
|
|
1438
|
+
repo.restore = restoreMethod.bind(repo);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
if (addGetDeletedMethod) {
|
|
1442
|
+
const getDeletedMethod = async function(params = {}, getDeletedOptions = {}) {
|
|
1443
|
+
const deletedFilter = buildGetDeletedFilter(deletedField, filterMode);
|
|
1444
|
+
const combinedFilters = {
|
|
1445
|
+
...params.filters || {},
|
|
1446
|
+
...deletedFilter
|
|
1447
|
+
};
|
|
1448
|
+
const page = params.page || 1;
|
|
1449
|
+
const limit = params.limit || 20;
|
|
1450
|
+
const skip = (page - 1) * limit;
|
|
1451
|
+
let sortSpec = { [deletedField]: -1 };
|
|
1452
|
+
if (params.sort) {
|
|
1453
|
+
if (typeof params.sort === "string") {
|
|
1454
|
+
const sortOrder = params.sort.startsWith("-") ? -1 : 1;
|
|
1455
|
+
const sortField = params.sort.startsWith("-") ? params.sort.substring(1) : params.sort;
|
|
1456
|
+
sortSpec = { [sortField]: sortOrder };
|
|
1457
|
+
} else {
|
|
1458
|
+
sortSpec = params.sort;
|
|
1459
|
+
}
|
|
1460
|
+
}
|
|
1461
|
+
let query = this.Model.find(combinedFilters).sort(sortSpec).skip(skip).limit(limit);
|
|
1462
|
+
if (getDeletedOptions.session) {
|
|
1463
|
+
query = query.session(getDeletedOptions.session);
|
|
1464
|
+
}
|
|
1465
|
+
if (getDeletedOptions.select) {
|
|
1466
|
+
const selectValue = Array.isArray(getDeletedOptions.select) ? getDeletedOptions.select.join(" ") : getDeletedOptions.select;
|
|
1467
|
+
query = query.select(selectValue);
|
|
1468
|
+
}
|
|
1469
|
+
if (getDeletedOptions.populate) {
|
|
1470
|
+
const populateSpec = getDeletedOptions.populate;
|
|
1471
|
+
if (typeof populateSpec === "string") {
|
|
1472
|
+
query = query.populate(populateSpec.split(",").map((p) => p.trim()));
|
|
1473
|
+
} else if (Array.isArray(populateSpec)) {
|
|
1474
|
+
query = query.populate(populateSpec);
|
|
1475
|
+
} else {
|
|
1476
|
+
query = query.populate(populateSpec);
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
if (getDeletedOptions.lean !== false) {
|
|
1480
|
+
query = query.lean();
|
|
1481
|
+
}
|
|
1482
|
+
const [docs, total] = await Promise.all([
|
|
1483
|
+
query.exec(),
|
|
1484
|
+
this.Model.countDocuments(combinedFilters)
|
|
1485
|
+
]);
|
|
1486
|
+
const pages = Math.ceil(total / limit);
|
|
1487
|
+
return {
|
|
1488
|
+
method: "offset",
|
|
1489
|
+
docs,
|
|
1490
|
+
page,
|
|
1491
|
+
limit,
|
|
1492
|
+
total,
|
|
1493
|
+
pages,
|
|
1494
|
+
hasNext: page < pages,
|
|
1495
|
+
hasPrev: page > 1
|
|
1496
|
+
};
|
|
1497
|
+
};
|
|
1498
|
+
if (typeof repo.registerMethod === "function") {
|
|
1499
|
+
repo.registerMethod("getDeleted", getDeletedMethod);
|
|
1500
|
+
} else {
|
|
1501
|
+
repo.getDeleted = getDeletedMethod.bind(repo);
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1368
1504
|
}
|
|
1369
1505
|
};
|
|
1370
1506
|
}
|
|
@@ -2071,7 +2207,7 @@ function cascadePlugin(options) {
|
|
|
2071
2207
|
}
|
|
2072
2208
|
const isSoftDelete = context.softDeleted === true;
|
|
2073
2209
|
const cascadeDelete = async (relation) => {
|
|
2074
|
-
const RelatedModel =
|
|
2210
|
+
const RelatedModel = mongoose4.models[relation.model];
|
|
2075
2211
|
if (!RelatedModel) {
|
|
2076
2212
|
logger?.warn?.(`Cascade delete skipped: model '${relation.model}' not found`, {
|
|
2077
2213
|
parentModel: context.model,
|
|
@@ -2162,7 +2298,7 @@ function cascadePlugin(options) {
|
|
|
2162
2298
|
}
|
|
2163
2299
|
const isSoftDelete = context.softDeleted === true;
|
|
2164
2300
|
const cascadeDeleteMany = async (relation) => {
|
|
2165
|
-
const RelatedModel =
|
|
2301
|
+
const RelatedModel = mongoose4.models[relation.model];
|
|
2166
2302
|
if (!RelatedModel) {
|
|
2167
2303
|
logger?.warn?.(`Cascade deleteMany skipped: model '${relation.model}' not found`, {
|
|
2168
2304
|
parentModel: context.model
|
|
@@ -2278,6 +2414,559 @@ function createMemoryCache(maxEntries = 1e3) {
|
|
|
2278
2414
|
}
|
|
2279
2415
|
};
|
|
2280
2416
|
}
|
|
2417
|
+
function isMongooseSchema(value) {
|
|
2418
|
+
return value instanceof mongoose4.Schema;
|
|
2419
|
+
}
|
|
2420
|
+
function isPlainObject(value) {
|
|
2421
|
+
return Object.prototype.toString.call(value) === "[object Object]";
|
|
2422
|
+
}
|
|
2423
|
+
function isObjectIdType(t) {
|
|
2424
|
+
return t === mongoose4.Schema.Types.ObjectId || t === mongoose4.Types.ObjectId;
|
|
2425
|
+
}
|
|
2426
|
+
function buildCrudSchemasFromMongooseSchema(mongooseSchema, options = {}) {
|
|
2427
|
+
const tree = mongooseSchema?.obj || {};
|
|
2428
|
+
const jsonCreate = buildJsonSchemaForCreate(tree, options);
|
|
2429
|
+
const jsonUpdate = buildJsonSchemaForUpdate(jsonCreate, options);
|
|
2430
|
+
const jsonParams = {
|
|
2431
|
+
type: "object",
|
|
2432
|
+
properties: { id: { type: "string", pattern: "^[0-9a-fA-F]{24}$" } },
|
|
2433
|
+
required: ["id"]
|
|
2434
|
+
};
|
|
2435
|
+
const jsonQuery = buildJsonSchemaForQuery(tree, options);
|
|
2436
|
+
return { createBody: jsonCreate, updateBody: jsonUpdate, params: jsonParams, listQuery: jsonQuery };
|
|
2437
|
+
}
|
|
2438
|
+
function buildCrudSchemasFromModel(mongooseModel, options = {}) {
|
|
2439
|
+
if (!mongooseModel || !mongooseModel.schema) {
|
|
2440
|
+
throw new Error("Invalid mongoose model");
|
|
2441
|
+
}
|
|
2442
|
+
return buildCrudSchemasFromMongooseSchema(mongooseModel.schema, options);
|
|
2443
|
+
}
|
|
2444
|
+
function getImmutableFields(options = {}) {
|
|
2445
|
+
const immutable = [];
|
|
2446
|
+
const fieldRules = options?.fieldRules || {};
|
|
2447
|
+
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
2448
|
+
if (rules.immutable || rules.immutableAfterCreate) {
|
|
2449
|
+
immutable.push(field);
|
|
2450
|
+
}
|
|
2451
|
+
});
|
|
2452
|
+
(options?.update?.omitFields || []).forEach((f) => {
|
|
2453
|
+
if (!immutable.includes(f)) immutable.push(f);
|
|
2454
|
+
});
|
|
2455
|
+
return immutable;
|
|
2456
|
+
}
|
|
2457
|
+
function getSystemManagedFields(options = {}) {
|
|
2458
|
+
const systemManaged = [];
|
|
2459
|
+
const fieldRules = options?.fieldRules || {};
|
|
2460
|
+
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
2461
|
+
if (rules.systemManaged) {
|
|
2462
|
+
systemManaged.push(field);
|
|
2463
|
+
}
|
|
2464
|
+
});
|
|
2465
|
+
return systemManaged;
|
|
2466
|
+
}
|
|
2467
|
+
function isFieldUpdateAllowed(fieldName, options = {}) {
|
|
2468
|
+
const immutableFields = getImmutableFields(options);
|
|
2469
|
+
const systemManagedFields = getSystemManagedFields(options);
|
|
2470
|
+
return !immutableFields.includes(fieldName) && !systemManagedFields.includes(fieldName);
|
|
2471
|
+
}
|
|
2472
|
+
function validateUpdateBody(body = {}, options = {}) {
|
|
2473
|
+
const violations = [];
|
|
2474
|
+
const immutableFields = getImmutableFields(options);
|
|
2475
|
+
const systemManagedFields = getSystemManagedFields(options);
|
|
2476
|
+
Object.keys(body).forEach((field) => {
|
|
2477
|
+
if (immutableFields.includes(field)) {
|
|
2478
|
+
violations.push({ field, reason: "Field is immutable" });
|
|
2479
|
+
} else if (systemManagedFields.includes(field)) {
|
|
2480
|
+
violations.push({ field, reason: "Field is system-managed" });
|
|
2481
|
+
}
|
|
2482
|
+
});
|
|
2483
|
+
return {
|
|
2484
|
+
valid: violations.length === 0,
|
|
2485
|
+
violations
|
|
2486
|
+
};
|
|
2487
|
+
}
|
|
2488
|
+
function jsonTypeFor(def, options, seen) {
|
|
2489
|
+
if (Array.isArray(def)) {
|
|
2490
|
+
if (def[0] === mongoose4.Schema.Types.Mixed) {
|
|
2491
|
+
return { type: "array", items: { type: "object", additionalProperties: true } };
|
|
2492
|
+
}
|
|
2493
|
+
return { type: "array", items: jsonTypeFor(def[0] ?? String, options, seen) };
|
|
2494
|
+
}
|
|
2495
|
+
if (isPlainObject(def) && "type" in def) {
|
|
2496
|
+
const typedDef = def;
|
|
2497
|
+
if (typedDef.enum && Array.isArray(typedDef.enum) && typedDef.enum.length) {
|
|
2498
|
+
return { type: "string", enum: typedDef.enum.map(String) };
|
|
2499
|
+
}
|
|
2500
|
+
if (Array.isArray(typedDef.type)) {
|
|
2501
|
+
const inner = typedDef.type[0] !== void 0 ? typedDef.type[0] : String;
|
|
2502
|
+
if (inner === mongoose4.Schema.Types.Mixed) {
|
|
2503
|
+
return { type: "array", items: { type: "object", additionalProperties: true } };
|
|
2504
|
+
}
|
|
2505
|
+
return { type: "array", items: jsonTypeFor(inner, options, seen) };
|
|
2506
|
+
}
|
|
2507
|
+
if (typedDef.type === String) return { type: "string" };
|
|
2508
|
+
if (typedDef.type === Number) return { type: "number" };
|
|
2509
|
+
if (typedDef.type === Boolean) return { type: "boolean" };
|
|
2510
|
+
if (typedDef.type === Date) {
|
|
2511
|
+
const mode = options?.dateAs || "datetime";
|
|
2512
|
+
return mode === "date" ? { type: "string", format: "date" } : { type: "string", format: "date-time" };
|
|
2513
|
+
}
|
|
2514
|
+
if (typedDef.type === Map || typedDef.type === mongoose4.Schema.Types.Map) {
|
|
2515
|
+
const ofSchema = jsonTypeFor(typedDef.of || String, options, seen);
|
|
2516
|
+
return { type: "object", additionalProperties: ofSchema };
|
|
2517
|
+
}
|
|
2518
|
+
if (typedDef.type === mongoose4.Schema.Types.Mixed) {
|
|
2519
|
+
return { type: "object", additionalProperties: true };
|
|
2520
|
+
}
|
|
2521
|
+
if (isObjectIdType(typedDef.type)) {
|
|
2522
|
+
return { type: "string", pattern: "^[0-9a-fA-F]{24}$" };
|
|
2523
|
+
}
|
|
2524
|
+
if (isMongooseSchema(typedDef.type)) {
|
|
2525
|
+
const obj = typedDef.type.obj;
|
|
2526
|
+
if (obj && typeof obj === "object") {
|
|
2527
|
+
if (seen.has(obj)) return { type: "object", additionalProperties: true };
|
|
2528
|
+
seen.add(obj);
|
|
2529
|
+
return convertTreeToJsonSchema(obj, options, seen);
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2532
|
+
}
|
|
2533
|
+
if (def === String) return { type: "string" };
|
|
2534
|
+
if (def === Number) return { type: "number" };
|
|
2535
|
+
if (def === Boolean) return { type: "boolean" };
|
|
2536
|
+
if (def === Date) {
|
|
2537
|
+
const mode = options?.dateAs || "datetime";
|
|
2538
|
+
return mode === "date" ? { type: "string", format: "date" } : { type: "string", format: "date-time" };
|
|
2539
|
+
}
|
|
2540
|
+
if (isObjectIdType(def)) return { type: "string", pattern: "^[0-9a-fA-F]{24}$" };
|
|
2541
|
+
if (isPlainObject(def)) {
|
|
2542
|
+
if (seen.has(def)) return { type: "object", additionalProperties: true };
|
|
2543
|
+
seen.add(def);
|
|
2544
|
+
return convertTreeToJsonSchema(def, options, seen);
|
|
2545
|
+
}
|
|
2546
|
+
return {};
|
|
2547
|
+
}
|
|
2548
|
+
function convertTreeToJsonSchema(tree, options, seen = /* @__PURE__ */ new WeakSet()) {
|
|
2549
|
+
if (!tree || typeof tree !== "object") {
|
|
2550
|
+
return { type: "object", properties: {} };
|
|
2551
|
+
}
|
|
2552
|
+
if (seen.has(tree)) {
|
|
2553
|
+
return { type: "object", additionalProperties: true };
|
|
2554
|
+
}
|
|
2555
|
+
seen.add(tree);
|
|
2556
|
+
const properties = {};
|
|
2557
|
+
const required = [];
|
|
2558
|
+
for (const [key, val] of Object.entries(tree || {})) {
|
|
2559
|
+
if (key === "__v" || key === "_id" || key === "id") continue;
|
|
2560
|
+
const cfg = isPlainObject(val) && "type" in val ? val : { };
|
|
2561
|
+
properties[key] = jsonTypeFor(val, options, seen);
|
|
2562
|
+
if (cfg.required === true) required.push(key);
|
|
2563
|
+
}
|
|
2564
|
+
const schema = { type: "object", properties };
|
|
2565
|
+
if (required.length) schema.required = required;
|
|
2566
|
+
return schema;
|
|
2567
|
+
}
|
|
2568
|
+
function buildJsonSchemaForCreate(tree, options) {
|
|
2569
|
+
const base = convertTreeToJsonSchema(tree, options, /* @__PURE__ */ new WeakSet());
|
|
2570
|
+
const fieldsToOmit = /* @__PURE__ */ new Set(["createdAt", "updatedAt", "__v"]);
|
|
2571
|
+
(options?.create?.omitFields || []).forEach((f) => fieldsToOmit.add(f));
|
|
2572
|
+
const fieldRules = options?.fieldRules || {};
|
|
2573
|
+
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
2574
|
+
if (rules.systemManaged) {
|
|
2575
|
+
fieldsToOmit.add(field);
|
|
2576
|
+
}
|
|
2577
|
+
});
|
|
2578
|
+
fieldsToOmit.forEach((field) => {
|
|
2579
|
+
if (base.properties?.[field]) {
|
|
2580
|
+
delete base.properties[field];
|
|
2581
|
+
}
|
|
2582
|
+
if (base.required) {
|
|
2583
|
+
base.required = base.required.filter((k) => k !== field);
|
|
2584
|
+
}
|
|
2585
|
+
});
|
|
2586
|
+
const reqOv = options?.create?.requiredOverrides || {};
|
|
2587
|
+
const optOv = options?.create?.optionalOverrides || {};
|
|
2588
|
+
base.required = base.required || [];
|
|
2589
|
+
for (const [k, v] of Object.entries(reqOv)) {
|
|
2590
|
+
if (v && !base.required.includes(k)) base.required.push(k);
|
|
2591
|
+
}
|
|
2592
|
+
for (const [k, v] of Object.entries(optOv)) {
|
|
2593
|
+
if (v && base.required) base.required = base.required.filter((x) => x !== k);
|
|
2594
|
+
}
|
|
2595
|
+
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
2596
|
+
if (rules.optional && base.required) {
|
|
2597
|
+
base.required = base.required.filter((x) => x !== field);
|
|
2598
|
+
}
|
|
2599
|
+
});
|
|
2600
|
+
const schemaOverrides = options?.create?.schemaOverrides || {};
|
|
2601
|
+
for (const [k, override] of Object.entries(schemaOverrides)) {
|
|
2602
|
+
if (base.properties?.[k]) {
|
|
2603
|
+
base.properties[k] = override;
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
if (options?.strictAdditionalProperties === true) {
|
|
2607
|
+
base.additionalProperties = false;
|
|
2608
|
+
}
|
|
2609
|
+
return base;
|
|
2610
|
+
}
|
|
2611
|
+
function buildJsonSchemaForUpdate(createJson, options) {
|
|
2612
|
+
const clone = JSON.parse(JSON.stringify(createJson));
|
|
2613
|
+
delete clone.required;
|
|
2614
|
+
const fieldsToOmit = /* @__PURE__ */ new Set();
|
|
2615
|
+
(options?.update?.omitFields || []).forEach((f) => fieldsToOmit.add(f));
|
|
2616
|
+
const fieldRules = options?.fieldRules || {};
|
|
2617
|
+
Object.entries(fieldRules).forEach(([field, rules]) => {
|
|
2618
|
+
if (rules.immutable || rules.immutableAfterCreate) {
|
|
2619
|
+
fieldsToOmit.add(field);
|
|
2620
|
+
}
|
|
2621
|
+
});
|
|
2622
|
+
fieldsToOmit.forEach((field) => {
|
|
2623
|
+
if (clone.properties?.[field]) {
|
|
2624
|
+
delete clone.properties[field];
|
|
2625
|
+
}
|
|
2626
|
+
});
|
|
2627
|
+
if (options?.strictAdditionalProperties === true) {
|
|
2628
|
+
clone.additionalProperties = false;
|
|
2629
|
+
}
|
|
2630
|
+
return clone;
|
|
2631
|
+
}
|
|
2632
|
+
function buildJsonSchemaForQuery(_tree, options) {
|
|
2633
|
+
const basePagination = {
|
|
2634
|
+
type: "object",
|
|
2635
|
+
properties: {
|
|
2636
|
+
page: { type: "string" },
|
|
2637
|
+
limit: { type: "string" },
|
|
2638
|
+
sort: { type: "string" },
|
|
2639
|
+
populate: { type: "string" },
|
|
2640
|
+
search: { type: "string" },
|
|
2641
|
+
select: { type: "string" },
|
|
2642
|
+
lean: { type: "string" },
|
|
2643
|
+
includeDeleted: { type: "string" }
|
|
2644
|
+
},
|
|
2645
|
+
additionalProperties: true
|
|
2646
|
+
};
|
|
2647
|
+
const filterable = options?.query?.filterableFields || {};
|
|
2648
|
+
for (const [k, v] of Object.entries(filterable)) {
|
|
2649
|
+
if (basePagination.properties) {
|
|
2650
|
+
basePagination.properties[k] = v && typeof v === "object" && "type" in v ? v : { type: "string" };
|
|
2651
|
+
}
|
|
2652
|
+
}
|
|
2653
|
+
return basePagination;
|
|
2654
|
+
}
|
|
2655
|
+
var QueryParser = class {
|
|
2656
|
+
options;
|
|
2657
|
+
operators = {
|
|
2658
|
+
eq: "$eq",
|
|
2659
|
+
ne: "$ne",
|
|
2660
|
+
gt: "$gt",
|
|
2661
|
+
gte: "$gte",
|
|
2662
|
+
lt: "$lt",
|
|
2663
|
+
lte: "$lte",
|
|
2664
|
+
in: "$in",
|
|
2665
|
+
nin: "$nin",
|
|
2666
|
+
like: "$regex",
|
|
2667
|
+
contains: "$regex",
|
|
2668
|
+
regex: "$regex",
|
|
2669
|
+
exists: "$exists",
|
|
2670
|
+
size: "$size",
|
|
2671
|
+
type: "$type"
|
|
2672
|
+
};
|
|
2673
|
+
/**
|
|
2674
|
+
* Dangerous MongoDB operators that should never be accepted from user input
|
|
2675
|
+
* Security: Prevent NoSQL injection attacks
|
|
2676
|
+
*/
|
|
2677
|
+
dangerousOperators;
|
|
2678
|
+
/**
|
|
2679
|
+
* Regex pattern characters that can cause catastrophic backtracking (ReDoS)
|
|
2680
|
+
*/
|
|
2681
|
+
dangerousRegexPatterns = /(\{[0-9,]+\}|\*\+|\+\+|\?\+|(\([^)]*\))\1|\(\?[^)]*\)|[\[\]].*[\[\]])/;
|
|
2682
|
+
constructor(options = {}) {
|
|
2683
|
+
this.options = {
|
|
2684
|
+
maxRegexLength: options.maxRegexLength ?? 500,
|
|
2685
|
+
maxSearchLength: options.maxSearchLength ?? 200,
|
|
2686
|
+
maxFilterDepth: options.maxFilterDepth ?? 10,
|
|
2687
|
+
additionalDangerousOperators: options.additionalDangerousOperators ?? []
|
|
2688
|
+
};
|
|
2689
|
+
this.dangerousOperators = [
|
|
2690
|
+
"$where",
|
|
2691
|
+
"$function",
|
|
2692
|
+
"$accumulator",
|
|
2693
|
+
"$expr",
|
|
2694
|
+
...this.options.additionalDangerousOperators
|
|
2695
|
+
];
|
|
2696
|
+
}
|
|
2697
|
+
/**
|
|
2698
|
+
* Parse query parameters into MongoDB query format
|
|
2699
|
+
*/
|
|
2700
|
+
parseQuery(query) {
|
|
2701
|
+
const {
|
|
2702
|
+
page,
|
|
2703
|
+
limit = 20,
|
|
2704
|
+
sort = "-createdAt",
|
|
2705
|
+
populate,
|
|
2706
|
+
search,
|
|
2707
|
+
after,
|
|
2708
|
+
cursor,
|
|
2709
|
+
...filters
|
|
2710
|
+
} = query || {};
|
|
2711
|
+
const parsed = {
|
|
2712
|
+
filters: this._parseFilters(filters),
|
|
2713
|
+
limit: parseInt(String(limit), 10),
|
|
2714
|
+
sort: this._parseSort(sort),
|
|
2715
|
+
populate,
|
|
2716
|
+
search: this._sanitizeSearch(search)
|
|
2717
|
+
};
|
|
2718
|
+
if (after || cursor) {
|
|
2719
|
+
parsed.after = after || cursor;
|
|
2720
|
+
} else if (page !== void 0) {
|
|
2721
|
+
parsed.page = parseInt(String(page), 10);
|
|
2722
|
+
} else {
|
|
2723
|
+
parsed.page = 1;
|
|
2724
|
+
}
|
|
2725
|
+
const orGroup = this._parseOr(query);
|
|
2726
|
+
if (orGroup) {
|
|
2727
|
+
parsed.filters = { ...parsed.filters, $or: orGroup };
|
|
2728
|
+
}
|
|
2729
|
+
parsed.filters = this._enhanceWithBetween(parsed.filters);
|
|
2730
|
+
return parsed;
|
|
2731
|
+
}
|
|
2732
|
+
/**
|
|
2733
|
+
* Parse sort parameter
|
|
2734
|
+
* Converts string like '-createdAt' to { createdAt: -1 }
|
|
2735
|
+
* Handles multiple sorts: '-createdAt,name' → { createdAt: -1, name: 1 }
|
|
2736
|
+
*/
|
|
2737
|
+
_parseSort(sort) {
|
|
2738
|
+
if (!sort) return void 0;
|
|
2739
|
+
if (typeof sort === "object") return sort;
|
|
2740
|
+
const sortObj = {};
|
|
2741
|
+
const fields = sort.split(",").map((s) => s.trim());
|
|
2742
|
+
for (const field of fields) {
|
|
2743
|
+
if (field.startsWith("-")) {
|
|
2744
|
+
sortObj[field.substring(1)] = -1;
|
|
2745
|
+
} else {
|
|
2746
|
+
sortObj[field] = 1;
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
return sortObj;
|
|
2750
|
+
}
|
|
2751
|
+
/**
|
|
2752
|
+
* Parse standard filter parameter (filter[field]=value)
|
|
2753
|
+
*/
|
|
2754
|
+
_parseFilters(filters) {
|
|
2755
|
+
const parsedFilters = {};
|
|
2756
|
+
const regexFields = {};
|
|
2757
|
+
for (const [key, value] of Object.entries(filters)) {
|
|
2758
|
+
if (this.dangerousOperators.includes(key) || key.startsWith("$") && !["$or", "$and"].includes(key)) {
|
|
2759
|
+
console.warn(`[mongokit] Blocked dangerous operator: ${key}`);
|
|
2760
|
+
continue;
|
|
2761
|
+
}
|
|
2762
|
+
if (["page", "limit", "sort", "populate", "search", "select", "lean", "includeDeleted"].includes(key)) {
|
|
2763
|
+
continue;
|
|
2764
|
+
}
|
|
2765
|
+
const operatorMatch = key.match(/^(.+)\[(.+)\]$/);
|
|
2766
|
+
if (operatorMatch) {
|
|
2767
|
+
const [, , operator] = operatorMatch;
|
|
2768
|
+
if (this.dangerousOperators.includes("$" + operator)) {
|
|
2769
|
+
console.warn(`[mongokit] Blocked dangerous operator: ${operator}`);
|
|
2770
|
+
continue;
|
|
2771
|
+
}
|
|
2772
|
+
this._handleOperatorSyntax(parsedFilters, regexFields, operatorMatch, value);
|
|
2773
|
+
continue;
|
|
2774
|
+
}
|
|
2775
|
+
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
2776
|
+
this._handleBracketSyntax(key, value, parsedFilters);
|
|
2777
|
+
} else {
|
|
2778
|
+
parsedFilters[key] = this._convertValue(value);
|
|
2779
|
+
}
|
|
2780
|
+
}
|
|
2781
|
+
return parsedFilters;
|
|
2782
|
+
}
|
|
2783
|
+
/**
|
|
2784
|
+
* Handle operator syntax: field[operator]=value
|
|
2785
|
+
*/
|
|
2786
|
+
_handleOperatorSyntax(filters, regexFields, operatorMatch, value) {
|
|
2787
|
+
const [, field, operator] = operatorMatch;
|
|
2788
|
+
if (operator.toLowerCase() === "options" && regexFields[field]) {
|
|
2789
|
+
const fieldValue = filters[field];
|
|
2790
|
+
if (typeof fieldValue === "object" && fieldValue !== null && "$regex" in fieldValue) {
|
|
2791
|
+
fieldValue.$options = value;
|
|
2792
|
+
}
|
|
2793
|
+
return;
|
|
2794
|
+
}
|
|
2795
|
+
if (operator.toLowerCase() === "contains" || operator.toLowerCase() === "like") {
|
|
2796
|
+
const safeRegex = this._createSafeRegex(value);
|
|
2797
|
+
if (safeRegex) {
|
|
2798
|
+
filters[field] = { $regex: safeRegex };
|
|
2799
|
+
regexFields[field] = true;
|
|
2800
|
+
}
|
|
2801
|
+
return;
|
|
2802
|
+
}
|
|
2803
|
+
const mongoOperator = this._toMongoOperator(operator);
|
|
2804
|
+
if (this.dangerousOperators.includes(mongoOperator)) {
|
|
2805
|
+
console.warn(`[mongokit] Blocked dangerous operator in field[${operator}]: ${mongoOperator}`);
|
|
2806
|
+
return;
|
|
2807
|
+
}
|
|
2808
|
+
if (mongoOperator === "$eq") {
|
|
2809
|
+
filters[field] = value;
|
|
2810
|
+
} else if (mongoOperator === "$regex") {
|
|
2811
|
+
filters[field] = { $regex: value };
|
|
2812
|
+
regexFields[field] = true;
|
|
2813
|
+
} else {
|
|
2814
|
+
if (typeof filters[field] !== "object" || filters[field] === null || Array.isArray(filters[field])) {
|
|
2815
|
+
filters[field] = {};
|
|
2816
|
+
}
|
|
2817
|
+
let processedValue;
|
|
2818
|
+
const op = operator.toLowerCase();
|
|
2819
|
+
if (["gt", "gte", "lt", "lte", "size"].includes(op)) {
|
|
2820
|
+
processedValue = parseFloat(String(value));
|
|
2821
|
+
if (isNaN(processedValue)) return;
|
|
2822
|
+
} else if (op === "in" || op === "nin") {
|
|
2823
|
+
processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
2824
|
+
} else {
|
|
2825
|
+
processedValue = this._convertValue(value);
|
|
2826
|
+
}
|
|
2827
|
+
filters[field][mongoOperator] = processedValue;
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
/**
|
|
2831
|
+
* Handle bracket syntax with object value
|
|
2832
|
+
*/
|
|
2833
|
+
_handleBracketSyntax(field, operators, parsedFilters) {
|
|
2834
|
+
if (!parsedFilters[field]) {
|
|
2835
|
+
parsedFilters[field] = {};
|
|
2836
|
+
}
|
|
2837
|
+
for (const [operator, value] of Object.entries(operators)) {
|
|
2838
|
+
if (operator === "between") {
|
|
2839
|
+
parsedFilters[field].between = value;
|
|
2840
|
+
continue;
|
|
2841
|
+
}
|
|
2842
|
+
if (this.operators[operator]) {
|
|
2843
|
+
const mongoOperator = this.operators[operator];
|
|
2844
|
+
let processedValue;
|
|
2845
|
+
if (["gt", "gte", "lt", "lte", "size"].includes(operator)) {
|
|
2846
|
+
processedValue = parseFloat(String(value));
|
|
2847
|
+
if (isNaN(processedValue)) continue;
|
|
2848
|
+
} else if (operator === "in" || operator === "nin") {
|
|
2849
|
+
processedValue = Array.isArray(value) ? value : String(value).split(",").map((v) => v.trim());
|
|
2850
|
+
} else if (operator === "like" || operator === "contains") {
|
|
2851
|
+
const safeRegex = this._createSafeRegex(value);
|
|
2852
|
+
if (!safeRegex) continue;
|
|
2853
|
+
processedValue = safeRegex;
|
|
2854
|
+
} else {
|
|
2855
|
+
processedValue = this._convertValue(value);
|
|
2856
|
+
}
|
|
2857
|
+
parsedFilters[field][mongoOperator] = processedValue;
|
|
2858
|
+
}
|
|
2859
|
+
}
|
|
2860
|
+
}
|
|
2861
|
+
/**
|
|
2862
|
+
* Convert operator to MongoDB format
|
|
2863
|
+
*/
|
|
2864
|
+
_toMongoOperator(operator) {
|
|
2865
|
+
const op = operator.toLowerCase();
|
|
2866
|
+
return op.startsWith("$") ? op : "$" + op;
|
|
2867
|
+
}
|
|
2868
|
+
/**
|
|
2869
|
+
* Create a safe regex pattern with protection against ReDoS attacks
|
|
2870
|
+
* @param pattern - The pattern string from user input
|
|
2871
|
+
* @param flags - Regex flags (default: 'i' for case-insensitive)
|
|
2872
|
+
* @returns A safe RegExp or null if pattern is invalid/dangerous
|
|
2873
|
+
*/
|
|
2874
|
+
_createSafeRegex(pattern, flags = "i") {
|
|
2875
|
+
if (pattern === null || pattern === void 0) {
|
|
2876
|
+
return null;
|
|
2877
|
+
}
|
|
2878
|
+
const patternStr = String(pattern);
|
|
2879
|
+
if (patternStr.length > this.options.maxRegexLength) {
|
|
2880
|
+
console.warn(`[mongokit] Regex pattern too long (${patternStr.length} > ${this.options.maxRegexLength}), truncating`);
|
|
2881
|
+
return new RegExp(this._escapeRegex(patternStr.substring(0, this.options.maxRegexLength)), flags);
|
|
2882
|
+
}
|
|
2883
|
+
if (this.dangerousRegexPatterns.test(patternStr)) {
|
|
2884
|
+
console.warn("[mongokit] Potentially dangerous regex pattern detected, escaping");
|
|
2885
|
+
return new RegExp(this._escapeRegex(patternStr), flags);
|
|
2886
|
+
}
|
|
2887
|
+
try {
|
|
2888
|
+
return new RegExp(patternStr, flags);
|
|
2889
|
+
} catch {
|
|
2890
|
+
return new RegExp(this._escapeRegex(patternStr), flags);
|
|
2891
|
+
}
|
|
2892
|
+
}
|
|
2893
|
+
/**
|
|
2894
|
+
* Escape special regex characters for literal matching
|
|
2895
|
+
*/
|
|
2896
|
+
_escapeRegex(str) {
|
|
2897
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Sanitize text search query for MongoDB $text search
|
|
2901
|
+
* @param search - Raw search input from user
|
|
2902
|
+
* @returns Sanitized search string or undefined
|
|
2903
|
+
*/
|
|
2904
|
+
_sanitizeSearch(search) {
|
|
2905
|
+
if (search === null || search === void 0 || search === "") {
|
|
2906
|
+
return void 0;
|
|
2907
|
+
}
|
|
2908
|
+
let searchStr = String(search).trim();
|
|
2909
|
+
if (!searchStr) {
|
|
2910
|
+
return void 0;
|
|
2911
|
+
}
|
|
2912
|
+
if (searchStr.length > this.options.maxSearchLength) {
|
|
2913
|
+
console.warn(`[mongokit] Search query too long (${searchStr.length} > ${this.options.maxSearchLength}), truncating`);
|
|
2914
|
+
searchStr = searchStr.substring(0, this.options.maxSearchLength);
|
|
2915
|
+
}
|
|
2916
|
+
return searchStr;
|
|
2917
|
+
}
|
|
2918
|
+
/**
|
|
2919
|
+
* Convert values based on operator type
|
|
2920
|
+
*/
|
|
2921
|
+
_convertValue(value) {
|
|
2922
|
+
if (value === null || value === void 0) return value;
|
|
2923
|
+
if (Array.isArray(value)) return value.map((v) => this._convertValue(v));
|
|
2924
|
+
if (typeof value === "object") return value;
|
|
2925
|
+
const stringValue = String(value);
|
|
2926
|
+
if (stringValue === "true") return true;
|
|
2927
|
+
if (stringValue === "false") return false;
|
|
2928
|
+
if (mongoose4.Types.ObjectId.isValid(stringValue) && stringValue.length === 24) {
|
|
2929
|
+
return stringValue;
|
|
2930
|
+
}
|
|
2931
|
+
return stringValue;
|
|
2932
|
+
}
|
|
2933
|
+
/**
|
|
2934
|
+
* Parse $or conditions
|
|
2935
|
+
*/
|
|
2936
|
+
_parseOr(query) {
|
|
2937
|
+
const orArray = [];
|
|
2938
|
+
const raw = query?.or || query?.OR || query?.$or;
|
|
2939
|
+
if (!raw) return void 0;
|
|
2940
|
+
const items = Array.isArray(raw) ? raw : typeof raw === "object" ? Object.values(raw) : [];
|
|
2941
|
+
for (const item of items) {
|
|
2942
|
+
if (typeof item === "object" && item) {
|
|
2943
|
+
orArray.push(this._parseFilters(item));
|
|
2944
|
+
}
|
|
2945
|
+
}
|
|
2946
|
+
return orArray.length ? orArray : void 0;
|
|
2947
|
+
}
|
|
2948
|
+
/**
|
|
2949
|
+
* Enhance filters with between operator
|
|
2950
|
+
*/
|
|
2951
|
+
_enhanceWithBetween(filters) {
|
|
2952
|
+
const output = { ...filters };
|
|
2953
|
+
for (const [key, value] of Object.entries(filters || {})) {
|
|
2954
|
+
if (value && typeof value === "object" && "between" in value) {
|
|
2955
|
+
const between = value.between;
|
|
2956
|
+
const [from, to] = String(between).split(",").map((s) => s.trim());
|
|
2957
|
+
const fromDate = from ? new Date(from) : void 0;
|
|
2958
|
+
const toDate = to ? new Date(to) : void 0;
|
|
2959
|
+
const range = {};
|
|
2960
|
+
if (fromDate && !isNaN(fromDate.getTime())) range.$gte = fromDate;
|
|
2961
|
+
if (toDate && !isNaN(toDate.getTime())) range.$lte = toDate;
|
|
2962
|
+
output[key] = range;
|
|
2963
|
+
}
|
|
2964
|
+
}
|
|
2965
|
+
return output;
|
|
2966
|
+
}
|
|
2967
|
+
};
|
|
2968
|
+
var defaultQueryParser = new QueryParser();
|
|
2969
|
+
var queryParser_default = defaultQueryParser;
|
|
2281
2970
|
|
|
2282
2971
|
// src/actions/index.ts
|
|
2283
2972
|
var actions_exports = {};
|
|
@@ -2333,4 +3022,4 @@ var index_default = Repository;
|
|
|
2333
3022
|
* ```
|
|
2334
3023
|
*/
|
|
2335
3024
|
|
|
2336
|
-
export { PaginationEngine, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, cachePlugin, cascadePlugin, createError, createFieldPreset, createMemoryCache, createRepository, index_default as default, fieldFilterPlugin, filterResponseData, getFieldsForUser, getMongooseProjection, immutableField, methodRegistryPlugin, mongoOperationsPlugin, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validationChainPlugin };
|
|
3025
|
+
export { PaginationEngine, QueryParser, Repository, actions_exports as actions, aggregateHelpersPlugin, auditLogPlugin, autoInject, batchOperationsPlugin, blockIf, buildCrudSchemasFromModel, buildCrudSchemasFromMongooseSchema, cachePlugin, cascadePlugin, createError, createFieldPreset, createMemoryCache, createRepository, index_default as default, fieldFilterPlugin, filterResponseData, getFieldsForUser, getImmutableFields, getMongooseProjection, getSystemManagedFields, immutableField, isFieldUpdateAllowed, methodRegistryPlugin, mongoOperationsPlugin, queryParser_default as queryParser, requireField, softDeletePlugin, subdocumentPlugin, timestampPlugin, uniqueField, validateUpdateBody, validationChainPlugin };
|