@web-ts-toolkit/access-router 0.43.0 → 0.45.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/README.md +97 -2
- package/advanced.d.mts +655 -19
- package/advanced.d.ts +655 -19
- package/advanced.js +478 -29
- package/advanced.mjs +478 -29
- package/index.d.mts +18 -10
- package/index.d.ts +18 -10
- package/index.js +1699 -262
- package/index.mjs +1576 -137
- package/llms.txt +19 -0
- package/package.json +18 -6
- package/{parsers-PMWujHUV.d.mts → parsers-DppKW-Fd.d.mts} +146 -26
- package/{parsers-PMWujHUV.d.ts → parsers-DppKW-Fd.d.ts} +146 -26
- package/processors.d.mts +151 -1
- package/processors.d.ts +151 -1
- package/processors.js +175 -8
- package/processors.mjs +170 -8
package/advanced.js
CHANGED
|
@@ -134,6 +134,12 @@ var import_utils8 = require("@web-ts-toolkit/utils");
|
|
|
134
134
|
var import_utils = require("@web-ts-toolkit/utils");
|
|
135
135
|
var DEFAULT_LIST_HARD_LIMIT = 1e3;
|
|
136
136
|
|
|
137
|
+
// src/helpers/sort-policy.ts
|
|
138
|
+
var fieldPathPattern = /^[A-Za-z_][A-Za-z0-9_$]*(\.[A-Za-z_][A-Za-z0-9_$]*)*$/;
|
|
139
|
+
function isValidFieldPath(field) {
|
|
140
|
+
return typeof field === "string" && fieldPathPattern.test(field);
|
|
141
|
+
}
|
|
142
|
+
|
|
137
143
|
// src/helpers/index.ts
|
|
138
144
|
var import_utils3 = require("@web-ts-toolkit/utils");
|
|
139
145
|
|
|
@@ -557,6 +563,29 @@ var cloneConfigValue = (value) => {
|
|
|
557
563
|
])
|
|
558
564
|
);
|
|
559
565
|
};
|
|
566
|
+
var cloneForRead = (value) => {
|
|
567
|
+
if (Array.isArray(value)) {
|
|
568
|
+
if (Object.isFrozen(value)) {
|
|
569
|
+
return value;
|
|
570
|
+
}
|
|
571
|
+
return value.map((item) => cloneForRead(item));
|
|
572
|
+
}
|
|
573
|
+
if (!value || typeof value !== "object") {
|
|
574
|
+
return value;
|
|
575
|
+
}
|
|
576
|
+
if (Object.getPrototypeOf(value) !== Object.prototype) {
|
|
577
|
+
return value;
|
|
578
|
+
}
|
|
579
|
+
if (Object.isFrozen(value)) {
|
|
580
|
+
return value;
|
|
581
|
+
}
|
|
582
|
+
return Object.fromEntries(
|
|
583
|
+
Object.entries(value).map(([entryKey, entryValue]) => [
|
|
584
|
+
entryKey,
|
|
585
|
+
cloneForRead(entryValue)
|
|
586
|
+
])
|
|
587
|
+
);
|
|
588
|
+
};
|
|
560
589
|
var freezeConfigValue = (value) => {
|
|
561
590
|
if (!value || typeof value !== "object") {
|
|
562
591
|
return value;
|
|
@@ -572,6 +601,7 @@ var freezeConfigValue = (value) => {
|
|
|
572
601
|
}
|
|
573
602
|
return value;
|
|
574
603
|
};
|
|
604
|
+
var cloneAndFreezeForStore = (value) => freezeConfigValue(cloneForRead(value));
|
|
575
605
|
var getNestedOption = (manager, key, defaultValue) => {
|
|
576
606
|
const keys2 = String(key).split(".");
|
|
577
607
|
if (keys2.length === 1) {
|
|
@@ -601,6 +631,14 @@ var OptionsManager = class {
|
|
|
601
631
|
target[keystr] = value;
|
|
602
632
|
_this.listeners[keystr] && _this.listeners[keystr].call(_this, value, keystr, target, oldvalue);
|
|
603
633
|
return true;
|
|
634
|
+
},
|
|
635
|
+
defineProperty(target, key, descriptor) {
|
|
636
|
+
const keystr = String(key);
|
|
637
|
+
const oldvalue = target[keystr];
|
|
638
|
+
const result = Reflect.defineProperty(target, key, descriptor);
|
|
639
|
+
const newValue = target[keystr];
|
|
640
|
+
_this.listeners[keystr] && _this.listeners[keystr].call(_this, newValue, keystr, target, oldvalue);
|
|
641
|
+
return result;
|
|
604
642
|
}
|
|
605
643
|
});
|
|
606
644
|
}
|
|
@@ -614,18 +652,18 @@ var OptionsManager = class {
|
|
|
614
652
|
set(key, value) {
|
|
615
653
|
const path = toPath(key);
|
|
616
654
|
if (path.length <= 1) {
|
|
617
|
-
(0, import_utils6.set)(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value :
|
|
655
|
+
(0, import_utils6.set)(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneAndFreezeForStore(value));
|
|
618
656
|
return;
|
|
619
657
|
}
|
|
620
658
|
const [rootKey, ...nestedPath] = path;
|
|
621
659
|
const currentRoot = (0, import_utils6.get)(this.currentOptions, [rootKey], void 0);
|
|
622
660
|
const baseRoot = (0, import_utils6.isPlainObject)(currentRoot) ? currentRoot : {};
|
|
623
661
|
const nextRoot = cloneConfigValue(baseRoot);
|
|
624
|
-
(0, import_utils6.set)(nextRoot, nestedPath,
|
|
625
|
-
(0, import_utils6.set)(this.currentOptions, [rootKey], nextRoot);
|
|
662
|
+
(0, import_utils6.set)(nextRoot, nestedPath, cloneForRead(value));
|
|
663
|
+
(0, import_utils6.set)(this.currentOptions, [rootKey], freezeConfigValue(nextRoot));
|
|
626
664
|
}
|
|
627
665
|
fetch() {
|
|
628
|
-
const cloned =
|
|
666
|
+
const cloned = cloneForRead(this.currentOptions);
|
|
629
667
|
for (const key of this.preserveKeys) {
|
|
630
668
|
if (key in this.currentOptions) {
|
|
631
669
|
cloned[key] = this.currentOptions[key];
|
|
@@ -634,20 +672,20 @@ var OptionsManager = class {
|
|
|
634
672
|
return freezeConfigValue(cloned);
|
|
635
673
|
}
|
|
636
674
|
assign(options) {
|
|
637
|
-
const cloned =
|
|
675
|
+
const cloned = cloneForRead(options);
|
|
638
676
|
for (const key of this.preserveKeys) {
|
|
639
677
|
if (key in options) {
|
|
640
678
|
cloned[key] = options[key];
|
|
641
679
|
}
|
|
642
680
|
}
|
|
643
|
-
(0, import_utils6.assign)(this.currentOptions, cloned);
|
|
681
|
+
(0, import_utils6.assign)(this.currentOptions, freezeConfigValue(cloned));
|
|
644
682
|
}
|
|
645
683
|
onchange(key, func) {
|
|
646
684
|
(0, import_utils6.set)(this.listeners, key, func);
|
|
647
685
|
return this;
|
|
648
686
|
}
|
|
649
687
|
snapshot() {
|
|
650
|
-
const cloned =
|
|
688
|
+
const cloned = cloneForRead(this.currentOptions);
|
|
651
689
|
for (const key of this.preserveKeys) {
|
|
652
690
|
if (key in this.currentOptions) {
|
|
653
691
|
cloned[key] = this.currentOptions[key];
|
|
@@ -663,13 +701,13 @@ var OptionsManager = class {
|
|
|
663
701
|
delete current[key];
|
|
664
702
|
}
|
|
665
703
|
}
|
|
666
|
-
const cloned =
|
|
704
|
+
const cloned = cloneForRead(snap);
|
|
667
705
|
for (const key of this.preserveKeys) {
|
|
668
706
|
if (key in snap) {
|
|
669
707
|
cloned[key] = snap[key];
|
|
670
708
|
}
|
|
671
709
|
}
|
|
672
|
-
(0, import_utils6.assign)(current, cloned);
|
|
710
|
+
(0, import_utils6.assign)(current, freezeConfigValue(cloned));
|
|
673
711
|
}
|
|
674
712
|
};
|
|
675
713
|
|
|
@@ -684,7 +722,9 @@ var defaultRequestComplexity = {
|
|
|
684
722
|
maxIncludeCount: 10,
|
|
685
723
|
maxSubQueryCount: 10,
|
|
686
724
|
maxBulkConcurrency: 10,
|
|
687
|
-
maxHookConcurrency: 10
|
|
725
|
+
maxHookConcurrency: 10,
|
|
726
|
+
maxCorrelatedQueries: 100,
|
|
727
|
+
maxCorrelatedDepth: 5
|
|
688
728
|
};
|
|
689
729
|
var normalizePositiveInteger = (value, fallback) => {
|
|
690
730
|
return Number.isSafeInteger(value) && Number(value) > 0 ? Number(value) : fallback;
|
|
@@ -704,6 +744,14 @@ var resolveRequestComplexity = (options) => ({
|
|
|
704
744
|
maxHookConcurrency: normalizePositiveInteger(
|
|
705
745
|
options?.maxHookConcurrency,
|
|
706
746
|
defaultRequestComplexity.maxHookConcurrency
|
|
747
|
+
),
|
|
748
|
+
maxCorrelatedQueries: normalizePositiveInteger(
|
|
749
|
+
options?.maxCorrelatedQueries,
|
|
750
|
+
defaultRequestComplexity.maxCorrelatedQueries
|
|
751
|
+
),
|
|
752
|
+
maxCorrelatedDepth: normalizePositiveInteger(
|
|
753
|
+
options?.maxCorrelatedDepth,
|
|
754
|
+
defaultRequestComplexity.maxCorrelatedDepth
|
|
707
755
|
)
|
|
708
756
|
});
|
|
709
757
|
function validateRequestComplexity(value, options, scope = "request") {
|
|
@@ -1139,8 +1187,7 @@ var AccessRuntime = class {
|
|
|
1139
1187
|
}
|
|
1140
1188
|
setDataOptions(dataName, options) {
|
|
1141
1189
|
const manager = this.getOrCreateDataOptions(dataName);
|
|
1142
|
-
|
|
1143
|
-
manager.assign({ ...currentDataOptions, ...options });
|
|
1190
|
+
manager.assign(options);
|
|
1144
1191
|
}
|
|
1145
1192
|
setDataOption(dataName, key, value) {
|
|
1146
1193
|
const manager = this.getOrCreateDataOptions(dataName);
|
|
@@ -1150,6 +1197,11 @@ var AccessRuntime = class {
|
|
|
1150
1197
|
const manager = this.getOrCreateDataOptions(dataName);
|
|
1151
1198
|
return manager.fetch();
|
|
1152
1199
|
}
|
|
1200
|
+
getDataSnapshot(dataName) {
|
|
1201
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
1202
|
+
const snapshot = manager.get("data");
|
|
1203
|
+
return snapshot ?? [];
|
|
1204
|
+
}
|
|
1153
1205
|
getDataOption(dataName, key, defaultValue) {
|
|
1154
1206
|
const manager = this.getOrCreateDataOptions(dataName);
|
|
1155
1207
|
return getNestedOption(manager, key, defaultValue);
|
|
@@ -1208,6 +1260,175 @@ var getGlobalOption = (key, defaultValue) => {
|
|
|
1208
1260
|
|
|
1209
1261
|
// src/validation/common.ts
|
|
1210
1262
|
var import_zod2 = require("zod");
|
|
1263
|
+
var import_utils10 = require("@web-ts-toolkit/utils");
|
|
1264
|
+
|
|
1265
|
+
// src/correlated-includes.ts
|
|
1266
|
+
var import_utils9 = require("@web-ts-toolkit/utils");
|
|
1267
|
+
var PARENT_MARKER_KEY = "$parent";
|
|
1268
|
+
var ESCAPE_WRAPPER_KEY = "$escape";
|
|
1269
|
+
var SUBQUERY_PAYLOAD_KEYS = /* @__PURE__ */ new Set(["$$sq", "$$date"]);
|
|
1270
|
+
var MARKER_FORBIDDEN_OPERATOR_KEYS = /* @__PURE__ */ new Set(["$text", "$where", "$comment"]);
|
|
1271
|
+
var LOGICAL_CLAUSE_KEYS = /* @__PURE__ */ new Set(["$and", "$or", "$nor"]);
|
|
1272
|
+
var DANGEROUS_PATH_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
1273
|
+
var FIELD_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
1274
|
+
var ARRAY_INDEX_SEGMENT_PATTERN = /^(0|[1-9]\d*)$/;
|
|
1275
|
+
var ownKeys = (value) => Object.keys(value);
|
|
1276
|
+
function isParentRefMarker(value) {
|
|
1277
|
+
return (0, import_utils9.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === PARENT_MARKER_KEY;
|
|
1278
|
+
}
|
|
1279
|
+
function isEscapedParentRef(value) {
|
|
1280
|
+
return (0, import_utils9.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === ESCAPE_WRAPPER_KEY;
|
|
1281
|
+
}
|
|
1282
|
+
function hasMarkerKey(value) {
|
|
1283
|
+
return ownKeys(value).includes(PARENT_MARKER_KEY) || ownKeys(value).includes(ESCAPE_WRAPPER_KEY);
|
|
1284
|
+
}
|
|
1285
|
+
function isValidParentRefPath(path) {
|
|
1286
|
+
if (typeof path !== "string" || path.length === 0) return false;
|
|
1287
|
+
const segments = path.split(".");
|
|
1288
|
+
return segments.every(
|
|
1289
|
+
(segment) => (FIELD_SEGMENT_PATTERN.test(segment) || ARRAY_INDEX_SEGMENT_PATTERN.test(segment)) && !DANGEROUS_PATH_SEGMENTS.has(segment)
|
|
1290
|
+
);
|
|
1291
|
+
}
|
|
1292
|
+
function isValidCorrelatedOutputPath(path) {
|
|
1293
|
+
return typeof path === "string" && path.length > 0 && isValidFieldPath(path) && path !== "_id" && !path.startsWith("$");
|
|
1294
|
+
}
|
|
1295
|
+
function containsParentMarkerShape(value) {
|
|
1296
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1297
|
+
const visit = (current) => {
|
|
1298
|
+
if (isParentRefMarker(current) || isEscapedParentRef(current)) return true;
|
|
1299
|
+
if ((0, import_utils9.isArray)(current)) {
|
|
1300
|
+
if (seen.has(current)) return false;
|
|
1301
|
+
seen.add(current);
|
|
1302
|
+
return current.some(visit);
|
|
1303
|
+
}
|
|
1304
|
+
if ((0, import_utils9.isPlainObject)(current)) {
|
|
1305
|
+
if (seen.has(current)) return false;
|
|
1306
|
+
seen.add(current);
|
|
1307
|
+
if (hasMarkerKey(current)) return true;
|
|
1308
|
+
return Object.values(current).some(visit);
|
|
1309
|
+
}
|
|
1310
|
+
return false;
|
|
1311
|
+
};
|
|
1312
|
+
return visit(value);
|
|
1313
|
+
}
|
|
1314
|
+
function scanTemplateValueNode(value, path, issues) {
|
|
1315
|
+
if (isEscapedParentRef(value)) {
|
|
1316
|
+
const inner = value.$escape;
|
|
1317
|
+
if (!isParentRefMarker(inner) || typeof inner.$parent !== "string" || (inner.$parent?.length ?? 0) === 0) {
|
|
1318
|
+
issues.push({
|
|
1319
|
+
message: 'Invalid $escape payload: expected { "$escape": { "$parent": "<field>" } }',
|
|
1320
|
+
path
|
|
1321
|
+
});
|
|
1322
|
+
}
|
|
1323
|
+
return;
|
|
1324
|
+
}
|
|
1325
|
+
if (isParentRefMarker(value)) {
|
|
1326
|
+
if (!isValidParentRefPath(value.$parent)) {
|
|
1327
|
+
issues.push({
|
|
1328
|
+
message: `Invalid $parent reference path at ${path.length === 0 ? "#" : path.join(".")}`,
|
|
1329
|
+
path
|
|
1330
|
+
});
|
|
1331
|
+
}
|
|
1332
|
+
return;
|
|
1333
|
+
}
|
|
1334
|
+
if ((0, import_utils9.isPlainObject)(value)) {
|
|
1335
|
+
if (hasMarkerKey(value)) {
|
|
1336
|
+
issues.push({
|
|
1337
|
+
message: 'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }',
|
|
1338
|
+
path
|
|
1339
|
+
});
|
|
1340
|
+
return;
|
|
1341
|
+
}
|
|
1342
|
+
scanTemplateObjectEntries(value, path, issues);
|
|
1343
|
+
return;
|
|
1344
|
+
}
|
|
1345
|
+
if ((0, import_utils9.isArray)(value)) {
|
|
1346
|
+
value.forEach((item, index) => scanTemplateValueNode(item, [...path, index], issues));
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
1350
|
+
for (const [key, child] of Object.entries(obj)) {
|
|
1351
|
+
const childPath = [...basePath, key];
|
|
1352
|
+
if (key === PARENT_MARKER_KEY) {
|
|
1353
|
+
issues.push({ message: "$parent is never a field name in correlated templates", path: childPath });
|
|
1354
|
+
continue;
|
|
1355
|
+
}
|
|
1356
|
+
if (SUBQUERY_PAYLOAD_KEYS.has(key)) {
|
|
1357
|
+
if (containsParentMarkerShape(child)) {
|
|
1358
|
+
issues.push({
|
|
1359
|
+
message: `Unsupported $parent reference inside ${key}: markers are not resolved in subquery payloads`,
|
|
1360
|
+
path: childPath
|
|
1361
|
+
});
|
|
1362
|
+
}
|
|
1363
|
+
continue;
|
|
1364
|
+
}
|
|
1365
|
+
if (MARKER_FORBIDDEN_OPERATOR_KEYS.has(key)) {
|
|
1366
|
+
if (containsParentMarkerShape(child)) {
|
|
1367
|
+
issues.push({
|
|
1368
|
+
message: `Unsupported $parent reference inside ${key}: markers are not resolved in ${key} values`,
|
|
1369
|
+
path: childPath
|
|
1370
|
+
});
|
|
1371
|
+
}
|
|
1372
|
+
continue;
|
|
1373
|
+
}
|
|
1374
|
+
if (key === "$elemMatch") {
|
|
1375
|
+
if (isParentRefMarker(child) || isEscapedParentRef(child)) {
|
|
1376
|
+
issues.push({
|
|
1377
|
+
message: "Unsupported $parent reference as a direct $elemMatch value",
|
|
1378
|
+
path: childPath
|
|
1379
|
+
});
|
|
1380
|
+
continue;
|
|
1381
|
+
}
|
|
1382
|
+
scanTemplateValueNode(child, childPath, issues);
|
|
1383
|
+
continue;
|
|
1384
|
+
}
|
|
1385
|
+
if (LOGICAL_CLAUSE_KEYS.has(key)) {
|
|
1386
|
+
if (!(0, import_utils9.isArray)(child)) {
|
|
1387
|
+
scanTemplateValueNode(child, childPath, issues);
|
|
1388
|
+
continue;
|
|
1389
|
+
}
|
|
1390
|
+
child.forEach((clause, index) => {
|
|
1391
|
+
const clausePath = [...childPath, index];
|
|
1392
|
+
if (isParentRefMarker(clause) || isEscapedParentRef(clause)) {
|
|
1393
|
+
issues.push({
|
|
1394
|
+
message: `Unsupported $parent reference as a direct ${key} clause: clauses must be filter objects`,
|
|
1395
|
+
path: clausePath
|
|
1396
|
+
});
|
|
1397
|
+
return;
|
|
1398
|
+
}
|
|
1399
|
+
if ((0, import_utils9.isPlainObject)(clause)) {
|
|
1400
|
+
scanTemplateObjectEntries(clause, clausePath, issues);
|
|
1401
|
+
}
|
|
1402
|
+
});
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
scanTemplateValueNode(child, childPath, issues);
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
function validateCorrelatedFilterTemplate(filter) {
|
|
1409
|
+
const issues = [];
|
|
1410
|
+
if (!(0, import_utils9.isPlainObject)(filter)) {
|
|
1411
|
+
issues.push({ message: "Correlated include filter must be an object", path: [] });
|
|
1412
|
+
return issues;
|
|
1413
|
+
}
|
|
1414
|
+
if (isParentRefMarker(filter) || isEscapedParentRef(filter)) {
|
|
1415
|
+
issues.push({ message: "Correlated include filter must not itself be a $parent reference", path: [] });
|
|
1416
|
+
return issues;
|
|
1417
|
+
}
|
|
1418
|
+
scanTemplateObjectEntries(filter, [], issues);
|
|
1419
|
+
return issues;
|
|
1420
|
+
}
|
|
1421
|
+
function findArgsMarkerIssue(value, where) {
|
|
1422
|
+
if (value !== void 0 && containsParentMarkerShape(value)) {
|
|
1423
|
+
return {
|
|
1424
|
+
message: `Unsupported $parent reference in ${where}: references are only supported in filter and id positions`,
|
|
1425
|
+
path: []
|
|
1426
|
+
};
|
|
1427
|
+
}
|
|
1428
|
+
return null;
|
|
1429
|
+
}
|
|
1430
|
+
|
|
1431
|
+
// src/validation/common.ts
|
|
1211
1432
|
var stringOrStringArray = import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.string())]);
|
|
1212
1433
|
var safeIntegerString = (min, message) => import_zod2.z.string().regex(/^\d+$/, message).refine((value) => Number.isSafeInteger(Number(value)), "Expected a safe integer").refine((value) => Number(value) >= min, message);
|
|
1213
1434
|
var queryBooleanString = import_zod2.z.enum(["true", "false"]);
|
|
@@ -1268,7 +1489,8 @@ var subPopulateSchema = import_zod2.z.union([
|
|
|
1268
1489
|
select: projectionSchema.optional()
|
|
1269
1490
|
}).passthrough()
|
|
1270
1491
|
]);
|
|
1271
|
-
var
|
|
1492
|
+
var legacyIncludeItemSchema = import_zod2.z.object({
|
|
1493
|
+
mode: import_zod2.z.enum(["legacy"]).optional(),
|
|
1272
1494
|
model: import_zod2.z.string().min(1),
|
|
1273
1495
|
op: import_zod2.z.enum(["list", "read", "count"]),
|
|
1274
1496
|
path: import_zod2.z.string().min(1),
|
|
@@ -1277,8 +1499,139 @@ var includeItemSchema = import_zod2.z.object({
|
|
|
1277
1499
|
foreignField: import_zod2.z.string().min(1),
|
|
1278
1500
|
args: import_zod2.z.unknown().optional().describe("Forwarded to list/read includes. Count includes ignore pagination fields so counts remain exact."),
|
|
1279
1501
|
options: import_zod2.z.unknown().optional()
|
|
1280
|
-
}).passthrough()
|
|
1281
|
-
|
|
1502
|
+
}).passthrough().superRefine((entry, ctx) => {
|
|
1503
|
+
if (entry.filter !== void 0 && containsParentMarkerShape(entry.filter)) {
|
|
1504
|
+
ctx.addIssue({
|
|
1505
|
+
code: import_zod2.z.ZodIssueCode.custom,
|
|
1506
|
+
message: 'Legacy includes must not contain $parent markers; use a correlated include (mode: "correlated")',
|
|
1507
|
+
path: ["filter"]
|
|
1508
|
+
});
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
var parentRefSchema = import_zod2.z.object({ $parent: import_zod2.z.string().min(1) }).strict().superRefine((value, ctx) => {
|
|
1512
|
+
if (!isValidParentRefPath(value.$parent)) {
|
|
1513
|
+
ctx.addIssue({
|
|
1514
|
+
code: import_zod2.z.ZodIssueCode.custom,
|
|
1515
|
+
message: `Invalid $parent reference path: ${value.$parent}`,
|
|
1516
|
+
path: ["$parent"]
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
});
|
|
1520
|
+
var correlatedIdSchema = import_zod2.z.union([import_zod2.z.string().min(1), parentRefSchema]);
|
|
1521
|
+
var correlatedFilterSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).superRefine((filter, ctx) => {
|
|
1522
|
+
for (const issue of validateCorrelatedFilterTemplate(filter)) {
|
|
1523
|
+
ctx.addIssue({
|
|
1524
|
+
code: import_zod2.z.ZodIssueCode.custom,
|
|
1525
|
+
message: issue.message,
|
|
1526
|
+
path: issue.path.map(String)
|
|
1527
|
+
});
|
|
1528
|
+
}
|
|
1529
|
+
});
|
|
1530
|
+
var correlatedEmptyOptionsSchema = import_zod2.z.unknown().refine(
|
|
1531
|
+
(value) => value === void 0 || (0, import_utils10.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
1532
|
+
"Correlated include options must be absent or empty"
|
|
1533
|
+
).optional();
|
|
1534
|
+
var correlatedPathSchema = import_zod2.z.string().min(1).superRefine((path, ctx) => {
|
|
1535
|
+
if (!isValidCorrelatedOutputPath(path)) {
|
|
1536
|
+
ctx.addIssue({
|
|
1537
|
+
code: import_zod2.z.ZodIssueCode.custom,
|
|
1538
|
+
message: `Invalid correlated include output path: ${path}`,
|
|
1539
|
+
path: []
|
|
1540
|
+
});
|
|
1541
|
+
}
|
|
1542
|
+
});
|
|
1543
|
+
var checkArgsMarkers = (select, sort, ctx) => {
|
|
1544
|
+
const selectIssue = findArgsMarkerIssue(select, "args.select");
|
|
1545
|
+
if (selectIssue) {
|
|
1546
|
+
ctx.addIssue({ code: import_zod2.z.ZodIssueCode.custom, message: selectIssue.message, path: ["select"] });
|
|
1547
|
+
}
|
|
1548
|
+
const sortIssue = findArgsMarkerIssue(sort, "args.sort");
|
|
1549
|
+
if (sortIssue) {
|
|
1550
|
+
ctx.addIssue({ code: import_zod2.z.ZodIssueCode.custom, message: sortIssue.message, path: ["sort"] });
|
|
1551
|
+
}
|
|
1552
|
+
};
|
|
1553
|
+
var correlatedReadArgsSchema = import_zod2.z.object({
|
|
1554
|
+
select: projectionSchema.optional(),
|
|
1555
|
+
sort: sortSchema.optional(),
|
|
1556
|
+
include: import_zod2.z.lazy(() => correlatedNestedIncludeSchema).optional()
|
|
1557
|
+
}).strict().superRefine((args, ctx) => checkArgsMarkers(args.select, args.sort, ctx));
|
|
1558
|
+
var correlatedListArgsSchema = import_zod2.z.object({
|
|
1559
|
+
select: projectionSchema.optional(),
|
|
1560
|
+
sort: sortSchema.optional(),
|
|
1561
|
+
skip: import_zod2.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1562
|
+
limit: import_zod2.z.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1563
|
+
page: import_zod2.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1564
|
+
pageSize: import_zod2.z.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1565
|
+
include: import_zod2.z.lazy(() => correlatedNestedIncludeSchema).optional()
|
|
1566
|
+
}).strict().superRefine((args, ctx) => checkArgsMarkers(args.select, args.sort, ctx));
|
|
1567
|
+
var correlatedCountArgsSchema = import_zod2.z.unknown().refine(
|
|
1568
|
+
(value) => value === void 0 || (0, import_utils10.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
1569
|
+
"Count includes accept no args"
|
|
1570
|
+
).optional();
|
|
1571
|
+
var correlatedReadByIdSchema = import_zod2.z.object({
|
|
1572
|
+
mode: import_zod2.z.literal("correlated"),
|
|
1573
|
+
model: import_zod2.z.string().min(1),
|
|
1574
|
+
op: import_zod2.z.literal("read"),
|
|
1575
|
+
path: correlatedPathSchema,
|
|
1576
|
+
id: correlatedIdSchema,
|
|
1577
|
+
args: correlatedReadArgsSchema.optional(),
|
|
1578
|
+
options: correlatedEmptyOptionsSchema
|
|
1579
|
+
}).strict();
|
|
1580
|
+
var correlatedReadByFilterSchema = import_zod2.z.object({
|
|
1581
|
+
mode: import_zod2.z.literal("correlated"),
|
|
1582
|
+
model: import_zod2.z.string().min(1),
|
|
1583
|
+
op: import_zod2.z.literal("read"),
|
|
1584
|
+
path: correlatedPathSchema,
|
|
1585
|
+
filter: correlatedFilterSchema,
|
|
1586
|
+
args: correlatedReadArgsSchema.optional(),
|
|
1587
|
+
options: correlatedEmptyOptionsSchema
|
|
1588
|
+
}).strict();
|
|
1589
|
+
var correlatedListSchema = import_zod2.z.object({
|
|
1590
|
+
mode: import_zod2.z.literal("correlated"),
|
|
1591
|
+
model: import_zod2.z.string().min(1),
|
|
1592
|
+
op: import_zod2.z.literal("list"),
|
|
1593
|
+
path: correlatedPathSchema,
|
|
1594
|
+
filter: correlatedFilterSchema,
|
|
1595
|
+
args: correlatedListArgsSchema.optional(),
|
|
1596
|
+
options: correlatedEmptyOptionsSchema
|
|
1597
|
+
}).strict();
|
|
1598
|
+
var correlatedCountSchema = import_zod2.z.object({
|
|
1599
|
+
mode: import_zod2.z.literal("correlated"),
|
|
1600
|
+
model: import_zod2.z.string().min(1),
|
|
1601
|
+
op: import_zod2.z.literal("count"),
|
|
1602
|
+
path: correlatedPathSchema,
|
|
1603
|
+
filter: correlatedFilterSchema,
|
|
1604
|
+
args: correlatedCountArgsSchema,
|
|
1605
|
+
options: correlatedEmptyOptionsSchema
|
|
1606
|
+
}).strict();
|
|
1607
|
+
var includeItemSchema = import_zod2.z.union([
|
|
1608
|
+
legacyIncludeItemSchema,
|
|
1609
|
+
correlatedReadByIdSchema,
|
|
1610
|
+
correlatedReadByFilterSchema,
|
|
1611
|
+
correlatedListSchema,
|
|
1612
|
+
correlatedCountSchema
|
|
1613
|
+
]);
|
|
1614
|
+
var correlatedNestedIncludeSchema = import_zod2.z.union([includeItemSchema, import_zod2.z.array(includeItemSchema)]);
|
|
1615
|
+
var rejectDuplicateCorrelatedPaths = (items, ctx) => {
|
|
1616
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1617
|
+
items.forEach((item, index) => {
|
|
1618
|
+
if ((0, import_utils10.isPlainObject)(item) && item.mode === "correlated" && typeof item.path === "string") {
|
|
1619
|
+
if (seen.has(item.path)) {
|
|
1620
|
+
ctx.addIssue({
|
|
1621
|
+
code: import_zod2.z.ZodIssueCode.custom,
|
|
1622
|
+
message: `Duplicate correlated include output path: ${item.path}`,
|
|
1623
|
+
path: [index, "path"]
|
|
1624
|
+
});
|
|
1625
|
+
} else {
|
|
1626
|
+
seen.add(item.path);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
});
|
|
1630
|
+
};
|
|
1631
|
+
var includeSchema = import_zod2.z.union([
|
|
1632
|
+
includeItemSchema,
|
|
1633
|
+
import_zod2.z.array(includeItemSchema).superRefine(rejectDuplicateCorrelatedPaths)
|
|
1634
|
+
]);
|
|
1282
1635
|
var fieldsSchema = import_zod2.z.array(import_zod2.z.string().min(1));
|
|
1283
1636
|
var taskSchema = import_zod2.z.object({
|
|
1284
1637
|
type: import_zod2.z.string().min(1),
|
|
@@ -1395,8 +1748,9 @@ function defineRequestSchema(validator, options = {}) {
|
|
|
1395
1748
|
};
|
|
1396
1749
|
}
|
|
1397
1750
|
function fromZod(schema) {
|
|
1398
|
-
return (value) => {
|
|
1399
|
-
const
|
|
1751
|
+
return async (value) => {
|
|
1752
|
+
const candidate = schema;
|
|
1753
|
+
const result = typeof candidate.safeParseAsync === "function" ? await candidate.safeParseAsync.call(schema, value) : schema.safeParse(value);
|
|
1400
1754
|
if (result.success) {
|
|
1401
1755
|
return {
|
|
1402
1756
|
success: true,
|
|
@@ -1433,6 +1787,9 @@ function fromYup(schema) {
|
|
|
1433
1787
|
data
|
|
1434
1788
|
};
|
|
1435
1789
|
} catch (error) {
|
|
1790
|
+
if (!isYupValidationError(error)) {
|
|
1791
|
+
throw error;
|
|
1792
|
+
}
|
|
1436
1793
|
return {
|
|
1437
1794
|
success: false,
|
|
1438
1795
|
issues: normalizeYupIssues(error)
|
|
@@ -1457,8 +1814,32 @@ function fromJoi(schema) {
|
|
|
1457
1814
|
}
|
|
1458
1815
|
function fromAjv(validator) {
|
|
1459
1816
|
return async (value) => {
|
|
1460
|
-
const
|
|
1461
|
-
if (
|
|
1817
|
+
const outcome = validator(value);
|
|
1818
|
+
if (isThenable(outcome)) {
|
|
1819
|
+
try {
|
|
1820
|
+
const data = await outcome;
|
|
1821
|
+
if (data === false) {
|
|
1822
|
+
return {
|
|
1823
|
+
success: false,
|
|
1824
|
+
issues: normalizeAjvIssues(validator.errors ?? [])
|
|
1825
|
+
};
|
|
1826
|
+
}
|
|
1827
|
+
return {
|
|
1828
|
+
success: true,
|
|
1829
|
+
data: data === true ? value : data
|
|
1830
|
+
};
|
|
1831
|
+
} catch (error) {
|
|
1832
|
+
if (!isAjvValidationError(error)) {
|
|
1833
|
+
throw error;
|
|
1834
|
+
}
|
|
1835
|
+
return {
|
|
1836
|
+
success: false,
|
|
1837
|
+
issues: normalizeAjvIssues(error.errors ?? [])
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
}
|
|
1841
|
+
const errorsSnapshot = validator.errors ? [...validator.errors] : [];
|
|
1842
|
+
if (outcome) {
|
|
1462
1843
|
return {
|
|
1463
1844
|
success: true,
|
|
1464
1845
|
data: value
|
|
@@ -1466,7 +1847,7 @@ function fromAjv(validator) {
|
|
|
1466
1847
|
}
|
|
1467
1848
|
return {
|
|
1468
1849
|
success: false,
|
|
1469
|
-
issues: normalizeAjvIssues(
|
|
1850
|
+
issues: normalizeAjvIssues(errorsSnapshot)
|
|
1470
1851
|
};
|
|
1471
1852
|
};
|
|
1472
1853
|
}
|
|
@@ -1487,6 +1868,25 @@ function fromValibot(schema, safeParse) {
|
|
|
1487
1868
|
}
|
|
1488
1869
|
function fromArkType(type) {
|
|
1489
1870
|
return async (value) => {
|
|
1871
|
+
if (isStandardSchema(type)) {
|
|
1872
|
+
const result2 = await type["~standard"].validate(value);
|
|
1873
|
+
if (isArkTypeErrors(result2)) {
|
|
1874
|
+
return {
|
|
1875
|
+
success: false,
|
|
1876
|
+
issues: normalizeArkTypeIssues(result2)
|
|
1877
|
+
};
|
|
1878
|
+
}
|
|
1879
|
+
if (isStandardSchemaFailure(result2)) {
|
|
1880
|
+
return {
|
|
1881
|
+
success: false,
|
|
1882
|
+
issues: normalizeArkTypeStandardIssues(result2.issues)
|
|
1883
|
+
};
|
|
1884
|
+
}
|
|
1885
|
+
return {
|
|
1886
|
+
success: true,
|
|
1887
|
+
data: result2.value
|
|
1888
|
+
};
|
|
1889
|
+
}
|
|
1490
1890
|
const result = await type(value);
|
|
1491
1891
|
if (!isArkTypeErrors(result)) {
|
|
1492
1892
|
return {
|
|
@@ -1539,6 +1939,9 @@ function fromVine(validator) {
|
|
|
1539
1939
|
data: output
|
|
1540
1940
|
};
|
|
1541
1941
|
} catch (error) {
|
|
1942
|
+
if (!isVineValidationError(error)) {
|
|
1943
|
+
throw error;
|
|
1944
|
+
}
|
|
1542
1945
|
return {
|
|
1543
1946
|
success: false,
|
|
1544
1947
|
issues: normalizeVineError(error)
|
|
@@ -1599,6 +2002,13 @@ function normalizeArkTypeIssues(issues) {
|
|
|
1599
2002
|
}));
|
|
1600
2003
|
return normalized.length ? normalized : [{ message: issues.summary ?? "Validation failed" }];
|
|
1601
2004
|
}
|
|
2005
|
+
function normalizeArkTypeStandardIssues(issues) {
|
|
2006
|
+
const normalized = issues.map((issue) => ({
|
|
2007
|
+
message: issue.message ?? issue.problem ?? "Validation failed",
|
|
2008
|
+
path: issue.path?.flatMap((segment) => normalizePathSegment(segment))
|
|
2009
|
+
}));
|
|
2010
|
+
return normalized.length ? normalized : [{ message: "Validation failed" }];
|
|
2011
|
+
}
|
|
1602
2012
|
function normalizeIoTsIssues(issues) {
|
|
1603
2013
|
return issues.map((issue) => ({
|
|
1604
2014
|
message: issue.message ?? "Validation failed",
|
|
@@ -1633,25 +2043,64 @@ function normalizeVineField(message) {
|
|
|
1633
2043
|
}
|
|
1634
2044
|
return path.length ? path : void 0;
|
|
1635
2045
|
}
|
|
2046
|
+
function decodeAjvSegment(segment) {
|
|
2047
|
+
return segment.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
2048
|
+
}
|
|
2049
|
+
function encodePointerSegment(segment) {
|
|
2050
|
+
return encodeURIComponent(segment.replace(/~/g, "~0").replace(/\//g, "~1"));
|
|
2051
|
+
}
|
|
1636
2052
|
function parseAjvPath(issue) {
|
|
1637
|
-
const
|
|
1638
|
-
|
|
1639
|
-
|
|
2053
|
+
const raw = issue.instancePath;
|
|
2054
|
+
const base = raw == null || raw === "" ? [] : (raw.startsWith("/") ? raw.slice(1) : raw).split("/").map(decodeAjvSegment);
|
|
2055
|
+
const missing = issue.params?.missingProperty;
|
|
2056
|
+
if (typeof missing === "string") {
|
|
2057
|
+
return [...base, missing];
|
|
1640
2058
|
}
|
|
1641
|
-
return
|
|
2059
|
+
return base;
|
|
1642
2060
|
}
|
|
1643
2061
|
function parsePathString(path) {
|
|
1644
2062
|
if (!path) return void 0;
|
|
1645
2063
|
return path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
|
|
1646
2064
|
}
|
|
1647
2065
|
function isYupValidationError(error) {
|
|
1648
|
-
|
|
2066
|
+
if (typeof error !== "object" || error === null || !("message" in error)) {
|
|
2067
|
+
return false;
|
|
2068
|
+
}
|
|
2069
|
+
const candidate = error;
|
|
2070
|
+
return candidate.name === "ValidationError" && typeof candidate.message === "string" && Array.isArray(candidate.errors) && Array.isArray(candidate.inner);
|
|
1649
2071
|
}
|
|
1650
2072
|
function isArkTypeErrors(value) {
|
|
1651
|
-
|
|
2073
|
+
if (typeof value !== "object" || value === null) {
|
|
2074
|
+
return false;
|
|
2075
|
+
}
|
|
2076
|
+
const record = value;
|
|
2077
|
+
return record.arkKind === "errors" || record[" arkKind"] === "errors";
|
|
2078
|
+
}
|
|
2079
|
+
function isThenable(value) {
|
|
2080
|
+
return typeof value === "object" && value !== null && "then" in value && typeof value.then === "function";
|
|
2081
|
+
}
|
|
2082
|
+
function isAjvValidationError(error) {
|
|
2083
|
+
if (typeof error !== "object" || error === null || !("errors" in error)) {
|
|
2084
|
+
return false;
|
|
2085
|
+
}
|
|
2086
|
+
const errors = error.errors;
|
|
2087
|
+
return errors == null || Array.isArray(errors);
|
|
1652
2088
|
}
|
|
1653
2089
|
function isVineValidationError(error) {
|
|
1654
|
-
|
|
2090
|
+
if (typeof error !== "object" || error === null || !("messages" in error)) {
|
|
2091
|
+
return false;
|
|
2092
|
+
}
|
|
2093
|
+
const candidate = error;
|
|
2094
|
+
if (!Array.isArray(candidate.messages) || candidate.messages.length === 0) {
|
|
2095
|
+
return false;
|
|
2096
|
+
}
|
|
2097
|
+
const hasDiscriminator = candidate.code === "E_VALIDATION_ERROR" || candidate.name === "ValidationError";
|
|
2098
|
+
if (!hasDiscriminator) {
|
|
2099
|
+
return false;
|
|
2100
|
+
}
|
|
2101
|
+
return candidate.messages.every(
|
|
2102
|
+
(message) => typeof message === "object" && message !== null && typeof message.message === "string" && typeof message.field === "string"
|
|
2103
|
+
);
|
|
1655
2104
|
}
|
|
1656
2105
|
function formatIssue(issue, key, location = "pointer") {
|
|
1657
2106
|
const path = (issue.path ?? []).map(String);
|
|
@@ -1668,7 +2117,7 @@ function formatIssue(issue, key, location = "pointer") {
|
|
|
1668
2117
|
};
|
|
1669
2118
|
}
|
|
1670
2119
|
function buildPointer(path) {
|
|
1671
|
-
return path.length === 0 ? "#" : `#/${path.join("/")}`;
|
|
2120
|
+
return path.length === 0 ? "#" : `#/${path.map(encodePointerSegment).join("/")}`;
|
|
1672
2121
|
}
|
|
1673
2122
|
|
|
1674
2123
|
// src/validation/model-router.ts
|
|
@@ -1719,7 +2168,7 @@ var listBodySchema = import_zod3.z.object({
|
|
|
1719
2168
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
|
|
1720
2169
|
var countBodySchema = import_zod3.z.object({
|
|
1721
2170
|
filter: objectOrArraySchema.optional()
|
|
1722
|
-
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access", "options"]));
|
|
2171
|
+
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access", "options", "include"]));
|
|
1723
2172
|
var readFilterBodySchema = import_zod3.z.object({
|
|
1724
2173
|
filter: objectOrArraySchema.optional(),
|
|
1725
2174
|
select: projectionSchema.optional(),
|