@web-ts-toolkit/access-router 0.55.0 → 0.57.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 +218 -56
- package/advanced.d.mts +1 -1
- package/advanced.d.ts +1 -1
- package/advanced.js +100 -61
- package/advanced.mjs +67 -28
- package/index.d.mts +2 -2
- package/index.d.ts +2 -2
- package/index.js +624 -533
- package/index.mjs +361 -270
- package/llms.txt +3 -2
- package/package.json +3 -3
- package/{parsers-BrVRL2fg.d.mts → parsers-CngKnVjW.d.mts} +93 -14
- package/{parsers-BrVRL2fg.d.ts → parsers-CngKnVjW.d.ts} +93 -14
package/advanced.js
CHANGED
|
@@ -260,7 +260,7 @@ function normalizeHydrationUpdate(current, key, value) {
|
|
|
260
260
|
|
|
261
261
|
// src/runtime.ts
|
|
262
262
|
var import_mongoose_schema_jsonschema = __toESM(require("mongoose-schema-jsonschema"));
|
|
263
|
-
var
|
|
263
|
+
var import_utils13 = require("@web-ts-toolkit/utils");
|
|
264
264
|
|
|
265
265
|
// src/helpers/query.ts
|
|
266
266
|
var import_utils2 = require("@web-ts-toolkit/utils");
|
|
@@ -1237,7 +1237,7 @@ function resolveSnapshotDescriptor(scopeVirtuals, virtualName, access) {
|
|
|
1237
1237
|
}
|
|
1238
1238
|
|
|
1239
1239
|
// src/acl/virtual-populate-dependencies.ts
|
|
1240
|
-
var
|
|
1240
|
+
var import_utils12 = require("@web-ts-toolkit/utils");
|
|
1241
1241
|
|
|
1242
1242
|
// src/acl/authorization-snapshot.ts
|
|
1243
1243
|
var import_node_util3 = require("util");
|
|
@@ -1445,6 +1445,25 @@ function captureAuthorizationFieldCatalog(schema, virtuals, documentPermissionFi
|
|
|
1445
1445
|
});
|
|
1446
1446
|
}
|
|
1447
1447
|
|
|
1448
|
+
// src/acl/populate-target-configuration.ts
|
|
1449
|
+
var import_utils11 = require("@web-ts-toolkit/utils");
|
|
1450
|
+
function capturePopulateTargetConfiguration(runtime, modelName, source, proposedOptions) {
|
|
1451
|
+
const label = `Populate target "${modelName}" for ${source}`;
|
|
1452
|
+
if (!proposedOptions && !runtime.hasModel(modelName))
|
|
1453
|
+
authorizationError(
|
|
1454
|
+
`${label} must be configured first in this runtime; register its Mongoose model and setModelOptions with an object permissionSchema`
|
|
1455
|
+
);
|
|
1456
|
+
const model = runtime.getModelInstance(modelName);
|
|
1457
|
+
if (!model) authorizationError(`${label} requires an actual registered Mongoose model in this runtime`);
|
|
1458
|
+
const options = proposedOptions ?? runtime.getModelOptions(modelName);
|
|
1459
|
+
const permissionSchema = options.permissionSchema === void 0 ? runtime.getDefaultModelOption("permissionSchema") : options.permissionSchema;
|
|
1460
|
+
if (!(0, import_utils11.isPlainObject)(permissionSchema))
|
|
1461
|
+
authorizationError(
|
|
1462
|
+
`${label} requires an effective object permissionSchema; configure the model or runtime model defaults ({} explicitly closes business fields)`
|
|
1463
|
+
);
|
|
1464
|
+
return { model, options: { ...options, permissionSchema } };
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1448
1467
|
// src/acl/virtual-populate-dependencies.ts
|
|
1449
1468
|
var elementType = (type) => type.$embeddedSchemaType ?? type.embeddedSchemaType ?? type.caster;
|
|
1450
1469
|
var join = (prefix, path) => prefix ? `${prefix}.${path}` : path;
|
|
@@ -1456,7 +1475,7 @@ var fail = (label, message) => {
|
|
|
1456
1475
|
var varyingSchema = (schema) => Object.keys(schema.discriminators ?? {}).length > 0 || schema.discriminatorMapping?.isRoot === false;
|
|
1457
1476
|
var varyingModel = (model) => !!model.baseModelName || Object.keys(model.discriminators ?? {}).length > 0 || varyingSchema(model.schema);
|
|
1458
1477
|
function record(value, label) {
|
|
1459
|
-
if (!(0,
|
|
1478
|
+
if (!(0, import_utils12.isPlainObject)(value)) return fail(label, "entries must be plain { path, select? } objects");
|
|
1460
1479
|
for (const key of Reflect.ownKeys(value)) {
|
|
1461
1480
|
const property = Object.getOwnPropertyDescriptor(value, key);
|
|
1462
1481
|
if (typeof key !== "string" || !property.enumerable || !("value" in property))
|
|
@@ -1544,7 +1563,9 @@ function normalizeSelection(select, catalog, label) {
|
|
|
1544
1563
|
includeId: selection.includes("_id")
|
|
1545
1564
|
};
|
|
1546
1565
|
}
|
|
1547
|
-
function captureVirtualPopulateDependencies(runtime, modelName, options) {
|
|
1566
|
+
function captureVirtualPopulateDependencies(runtime, modelName, options, globalOptions = runtime.getGlobalOptions()) {
|
|
1567
|
+
const requireOperationAccessForPopulateDependencies = globalOptions.requireOperationAccessForPopulateDependencies !== false;
|
|
1568
|
+
const requireOperationAccessForPopulateQueries = globalOptions.requireOperationAccessForPopulateQueries !== false;
|
|
1548
1569
|
const model = runtime.getModelInstance(modelName);
|
|
1549
1570
|
const targets = /* @__PURE__ */ new Map();
|
|
1550
1571
|
const scopes = [];
|
|
@@ -1584,15 +1605,23 @@ function captureVirtualPopulateDependencies(runtime, modelName, options) {
|
|
|
1584
1605
|
label,
|
|
1585
1606
|
`target "${ref}" requires a registered same-connection non-discriminator ObjectId model bound to the source ref`
|
|
1586
1607
|
);
|
|
1587
|
-
const
|
|
1608
|
+
const { options: targetOptions } = capturePopulateTargetConfiguration(
|
|
1609
|
+
runtime,
|
|
1610
|
+
ref,
|
|
1611
|
+
`dependsOnPopulate virtual "${label}"`,
|
|
1612
|
+
ref === modelName ? options : void 0
|
|
1613
|
+
);
|
|
1588
1614
|
const defaults = runtime.getDefaultModelOptions();
|
|
1589
|
-
const readOption = (key) => resolveNestedOption((path2, fallback) => (0,
|
|
1615
|
+
const readOption = (key) => resolveNestedOption((path2, fallback) => (0, import_utils12.get)(targetOptions, path2, fallback), key, (0, import_utils12.get)(defaults, key));
|
|
1590
1616
|
const documentPermissionField = targetOptions.documentPermissionField ?? defaults.documentPermissionField;
|
|
1591
1617
|
const catalog = captureAuthorizationFieldCatalog(targetModel.schema, void 0, documentPermissionField);
|
|
1592
1618
|
const configuration = copyAuthorizationValue(
|
|
1593
1619
|
{
|
|
1594
1620
|
catalog,
|
|
1595
1621
|
documentPermissionField,
|
|
1622
|
+
requireOperationAccessForPopulateDependencies,
|
|
1623
|
+
requireOperationAccessForPopulateQueries,
|
|
1624
|
+
permissionSchema: targetOptions.permissionSchema,
|
|
1596
1625
|
operationAccess: { read: readOption("operationAccess.read") },
|
|
1597
1626
|
baseFilter: { read: readOption("baseFilter.read") },
|
|
1598
1627
|
overrideFilter: { read: readOption("overrideFilter.read") },
|
|
@@ -1641,13 +1670,13 @@ function captureVirtualPopulateDependencies(runtime, modelName, options) {
|
|
|
1641
1670
|
);
|
|
1642
1671
|
continue;
|
|
1643
1672
|
}
|
|
1644
|
-
if (!(0,
|
|
1673
|
+
if (!(0, import_utils12.isPlainObject)(raw)) continue;
|
|
1645
1674
|
const entry = raw;
|
|
1646
1675
|
const label = join(sourcePrefix, name);
|
|
1647
1676
|
captureList(entry.dependsOnPopulate, label);
|
|
1648
1677
|
if (!("get" in entry))
|
|
1649
1678
|
for (const access of accesses) {
|
|
1650
|
-
if ((0,
|
|
1679
|
+
if ((0, import_utils12.isPlainObject)(entry[access]))
|
|
1651
1680
|
captureList(entry[access].dependsOnPopulate, `${label}.${access}`);
|
|
1652
1681
|
}
|
|
1653
1682
|
const byAccess = {};
|
|
@@ -1693,44 +1722,44 @@ var defaultDataOptions = {
|
|
|
1693
1722
|
listHardLimit: DEFAULT_LIST_HARD_LIMIT
|
|
1694
1723
|
};
|
|
1695
1724
|
var normalizeBasePath = (name, value) => {
|
|
1696
|
-
if ((0,
|
|
1725
|
+
if ((0, import_utils13.isNil)(value)) {
|
|
1697
1726
|
return `/${pluralize(name)}`;
|
|
1698
1727
|
}
|
|
1699
|
-
return (0,
|
|
1728
|
+
return (0, import_utils13.isString)(value) ? (0, import_utils13.addLeadingSlash)(value) : "";
|
|
1700
1729
|
};
|
|
1701
1730
|
var hasModelPermission = (value, modelPermissionPrefix) => {
|
|
1702
1731
|
if (!modelPermissionPrefix) {
|
|
1703
1732
|
return true;
|
|
1704
1733
|
}
|
|
1705
|
-
if ((0,
|
|
1734
|
+
if ((0, import_utils13.isString)(value)) {
|
|
1706
1735
|
return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
|
|
1707
1736
|
}
|
|
1708
|
-
if ((0,
|
|
1737
|
+
if ((0, import_utils13.isArray)(value)) {
|
|
1709
1738
|
return value.some((item) => {
|
|
1710
|
-
if ((0,
|
|
1739
|
+
if ((0, import_utils13.isString)(item) || (0, import_utils13.isArray)(item)) {
|
|
1711
1740
|
return hasModelPermission(item, modelPermissionPrefix);
|
|
1712
1741
|
}
|
|
1713
1742
|
return true;
|
|
1714
1743
|
});
|
|
1715
1744
|
}
|
|
1716
|
-
return (0,
|
|
1745
|
+
return (0, import_utils13.isFunction)(value);
|
|
1717
1746
|
};
|
|
1718
1747
|
var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
|
|
1719
1748
|
const schemaKeys = Object.keys(permissionSchema);
|
|
1720
1749
|
const globalPermissionKeys = {};
|
|
1721
1750
|
const modelPermissionKeys = {};
|
|
1722
|
-
(0,
|
|
1751
|
+
(0, import_utils13.forEach)(schemaKeys, (schemaKey) => {
|
|
1723
1752
|
const schemaRule = permissionSchema[schemaKey];
|
|
1724
|
-
const ruleEntries = (0,
|
|
1753
|
+
const ruleEntries = (0, import_utils13.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
|
|
1725
1754
|
for (let x = 0; x < ruleEntries.length; x++) {
|
|
1726
1755
|
const [accessKey, value] = ruleEntries[x];
|
|
1727
|
-
if (!(0,
|
|
1756
|
+
if (!(0, import_utils13.isArray)(globalPermissionKeys[accessKey])) {
|
|
1728
1757
|
globalPermissionKeys[accessKey] = [];
|
|
1729
1758
|
}
|
|
1730
|
-
if (!(0,
|
|
1759
|
+
if (!(0, import_utils13.isArray)(modelPermissionKeys[accessKey])) {
|
|
1731
1760
|
modelPermissionKeys[accessKey] = [];
|
|
1732
1761
|
}
|
|
1733
|
-
if ((0,
|
|
1762
|
+
if ((0, import_utils13.isBoolean)(value)) {
|
|
1734
1763
|
globalPermissionKeys[accessKey].push(schemaKey);
|
|
1735
1764
|
continue;
|
|
1736
1765
|
}
|
|
@@ -1762,13 +1791,13 @@ var VIRTUAL_UNSUPPORTED_ACCESSES = ["delete", "distinct", "count"];
|
|
|
1762
1791
|
var VIRTUAL_RESERVED_NAMES = /* @__PURE__ */ new Set(["_id", "__v", "id"]);
|
|
1763
1792
|
var VIRTUAL_DANGEROUS_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
|
|
1764
1793
|
var VIRTUAL_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
1765
|
-
var isVirtualContainerValue2 = (value) => (0,
|
|
1794
|
+
var isVirtualContainerValue2 = (value) => (0, import_utils13.isPlainObject)(value) && "sub" in value;
|
|
1766
1795
|
var virtualFullPath = (prefix, name) => prefix ? `${prefix}.${name}` : name;
|
|
1767
1796
|
var virtualPathsOverlap = (virtualPath, permissionField) => {
|
|
1768
1797
|
if (!virtualPath || !permissionField) return false;
|
|
1769
1798
|
try {
|
|
1770
|
-
if ((0,
|
|
1771
|
-
if ((0,
|
|
1799
|
+
if ((0, import_utils13.get)((0, import_utils13.set)({}, virtualPath, true), permissionField) !== void 0) return true;
|
|
1800
|
+
if ((0, import_utils13.get)((0, import_utils13.set)({}, permissionField, true), virtualPath) !== void 0) return true;
|
|
1772
1801
|
} catch {
|
|
1773
1802
|
return false;
|
|
1774
1803
|
}
|
|
@@ -1829,12 +1858,12 @@ var cloneVirtualsForValidation = (value) => {
|
|
|
1829
1858
|
};
|
|
1830
1859
|
var validateVirtualDependsOn = (dependsOn, entryLabel, storedFields, siblingVirtualNames) => {
|
|
1831
1860
|
if (dependsOn === void 0) return [];
|
|
1832
|
-
if (!(0,
|
|
1861
|
+
if (!(0, import_utils13.isArray)(dependsOn)) {
|
|
1833
1862
|
throw new Error(`Virtual ${entryLabel}: dependsOn must be an array of top-level persisted field names`);
|
|
1834
1863
|
}
|
|
1835
1864
|
const list = dependsOn;
|
|
1836
1865
|
for (const dep of list) {
|
|
1837
|
-
if (!(0,
|
|
1866
|
+
if (!(0, import_utils13.isString)(dep) || dep.length === 0) {
|
|
1838
1867
|
throw new Error(`Virtual ${entryLabel}: dependsOn entries must be non-empty strings`);
|
|
1839
1868
|
}
|
|
1840
1869
|
if (dep.includes(".")) {
|
|
@@ -1856,12 +1885,12 @@ var validateVirtualDependsOn = (dependsOn, entryLabel, storedFields, siblingVirt
|
|
|
1856
1885
|
return list;
|
|
1857
1886
|
};
|
|
1858
1887
|
var validateVirtualLeafValue = (value, entryLabel, storedFields, siblingVirtualNames, sharedDependsOn) => {
|
|
1859
|
-
if ((0,
|
|
1860
|
-
if (!(0,
|
|
1888
|
+
if ((0, import_utils13.isFunction)(value)) return;
|
|
1889
|
+
if (!(0, import_utils13.isPlainObject)(value)) {
|
|
1861
1890
|
throw new Error(`Virtual ${entryLabel}: descriptor must be a getter function or { get, dependsOn }`);
|
|
1862
1891
|
}
|
|
1863
1892
|
const record2 = value;
|
|
1864
|
-
if (!(0,
|
|
1893
|
+
if (!(0, import_utils13.isFunction)(record2.get)) {
|
|
1865
1894
|
throw new Error(`Virtual ${entryLabel}: descriptor.get must be a callable getter function`);
|
|
1866
1895
|
}
|
|
1867
1896
|
validateVirtualDependsOn(record2.dependsOn ?? sharedDependsOn, entryLabel, storedFields, siblingVirtualNames);
|
|
@@ -1903,7 +1932,7 @@ var validateVirtualsScope = (scope, documentPermissionField) => {
|
|
|
1903
1932
|
`Virtual ${scopeLabel}${name}: scope-container must only hold "sub" (embedded container "${name}" is not a virtual-leaf collision)`
|
|
1904
1933
|
);
|
|
1905
1934
|
}
|
|
1906
|
-
if (!(0,
|
|
1935
|
+
if (!(0, import_utils13.isPlainObject)(record3.sub)) {
|
|
1907
1936
|
throw new Error(`Virtual ${scopeLabel}${name}: scope-container "sub" must be a plain object`);
|
|
1908
1937
|
}
|
|
1909
1938
|
continue;
|
|
@@ -1913,8 +1942,8 @@ var validateVirtualsScope = (scope, documentPermissionField) => {
|
|
|
1913
1942
|
`Virtual ${scopeLabel}${name}: collides with a stored path (inspected actual Mongoose schema/child scope; getModelAtt alone is insufficient)`
|
|
1914
1943
|
);
|
|
1915
1944
|
}
|
|
1916
|
-
if ((0,
|
|
1917
|
-
if (!(0,
|
|
1945
|
+
if ((0, import_utils13.isFunction)(raw)) continue;
|
|
1946
|
+
if (!(0, import_utils13.isPlainObject)(raw)) {
|
|
1918
1947
|
throw new Error(
|
|
1919
1948
|
`Virtual ${scopeLabel}${name}: malformed descriptor (expected getter, { get, dependsOn }, or per-access record)`
|
|
1920
1949
|
);
|
|
@@ -1968,7 +1997,7 @@ var validateVirtualsScope = (scope, documentPermissionField) => {
|
|
|
1968
1997
|
};
|
|
1969
1998
|
var validateVirtualsTree = (model, virtuals, documentPermissionField, modelName) => {
|
|
1970
1999
|
if (virtuals === void 0 || virtuals === null) return;
|
|
1971
|
-
if (!(0,
|
|
2000
|
+
if (!(0, import_utils13.isPlainObject)(virtuals)) {
|
|
1972
2001
|
throw new Error(`Virtuals for model "${modelName}": virtuals must be a plain object mapping names to descriptors`);
|
|
1973
2002
|
}
|
|
1974
2003
|
const rootSchema = model?.schema ?? null;
|
|
@@ -2020,7 +2049,8 @@ var AccessRuntime = class {
|
|
|
2020
2049
|
{
|
|
2021
2050
|
requestPermissionField: "_permissions",
|
|
2022
2051
|
globalPermissions: () => ({}),
|
|
2023
|
-
|
|
2052
|
+
requireOperationAccessForPopulateQueries: true,
|
|
2053
|
+
requireOperationAccessForPopulateDependencies: true,
|
|
2024
2054
|
logger: defaultLogger,
|
|
2025
2055
|
requestComplexity: defaultRequestComplexity
|
|
2026
2056
|
},
|
|
@@ -2075,7 +2105,7 @@ var AccessRuntime = class {
|
|
|
2075
2105
|
}
|
|
2076
2106
|
registerOpenApiRoute(route) {
|
|
2077
2107
|
this.openApiRegistry.register(
|
|
2078
|
-
this.openApiPathPrefix ? { ...route, path: (0,
|
|
2108
|
+
this.openApiPathPrefix ? { ...route, path: (0, import_utils13.normalizeUrlPath)(`${this.openApiPathPrefix}/${route.path}`) } : route
|
|
2079
2109
|
);
|
|
2080
2110
|
}
|
|
2081
2111
|
/**
|
|
@@ -2086,7 +2116,7 @@ var AccessRuntime = class {
|
|
|
2086
2116
|
*/
|
|
2087
2117
|
withOpenApiPathPrefix(prefix, build) {
|
|
2088
2118
|
const previous = this.openApiPathPrefix;
|
|
2089
|
-
this.openApiPathPrefix = (0,
|
|
2119
|
+
this.openApiPathPrefix = (0, import_utils13.normalizeUrlPath)(`${previous}/${prefix}`);
|
|
2090
2120
|
try {
|
|
2091
2121
|
return build();
|
|
2092
2122
|
} finally {
|
|
@@ -2193,9 +2223,18 @@ var AccessRuntime = class {
|
|
|
2193
2223
|
}
|
|
2194
2224
|
/** Shallowly replace supplied global values; nested objects such as requestComplexity are not deep-merged. */
|
|
2195
2225
|
setGlobalOptions(options) {
|
|
2196
|
-
|
|
2226
|
+
const next = { ...options };
|
|
2227
|
+
if ("requireOperationAccessForPopulateQueries" in next)
|
|
2228
|
+
next.requireOperationAccessForPopulateQueries = next.requireOperationAccessForPopulateQueries !== false;
|
|
2229
|
+
if ("requireOperationAccessForPopulateDependencies" in next)
|
|
2230
|
+
next.requireOperationAccessForPopulateDependencies = next.requireOperationAccessForPopulateDependencies !== false;
|
|
2231
|
+
this.globalOptions.assign(next);
|
|
2197
2232
|
}
|
|
2198
2233
|
setGlobalOption(key, value) {
|
|
2234
|
+
if (key === "requireOperationAccessForPopulateQueries" || key === "requireOperationAccessForPopulateDependencies") {
|
|
2235
|
+
this.globalOptions.set(key, value !== false);
|
|
2236
|
+
return;
|
|
2237
|
+
}
|
|
2199
2238
|
this.globalOptions.set(key, value);
|
|
2200
2239
|
}
|
|
2201
2240
|
getGlobalOptions() {
|
|
@@ -2222,7 +2261,7 @@ var AccessRuntime = class {
|
|
|
2222
2261
|
if (keyStr === "defaults") assertPublicDefaults(value);
|
|
2223
2262
|
else if (keyStr.startsWith("defaults.")) {
|
|
2224
2263
|
const proposed = {};
|
|
2225
|
-
(0,
|
|
2264
|
+
(0, import_utils13.set)(proposed, keyStr.slice("defaults.".length), value);
|
|
2226
2265
|
assertPublicDefaults(proposed);
|
|
2227
2266
|
}
|
|
2228
2267
|
this.defaultModelOptions.set(key, value);
|
|
@@ -2251,7 +2290,7 @@ var AccessRuntime = class {
|
|
|
2251
2290
|
}).onchange("basePath", function(newval, key, target) {
|
|
2252
2291
|
target[key] = normalizeBasePath(
|
|
2253
2292
|
modelName,
|
|
2254
|
-
(0,
|
|
2293
|
+
(0, import_utils13.isString)(newval) || (0, import_utils13.isNil)(newval) ? newval : void 0
|
|
2255
2294
|
);
|
|
2256
2295
|
}).build();
|
|
2257
2296
|
this.modelJsonSchemas[modelName] = model.jsonSchema();
|
|
@@ -2295,7 +2334,7 @@ var AccessRuntime = class {
|
|
|
2295
2334
|
if (keyStr === "defaults") assertPublicDefaults(value);
|
|
2296
2335
|
else if (keyStr.startsWith("defaults.")) {
|
|
2297
2336
|
const proposed = {};
|
|
2298
|
-
(0,
|
|
2337
|
+
(0, import_utils13.set)(proposed, keyStr.slice("defaults.".length), value);
|
|
2299
2338
|
assertPublicDefaults(proposed);
|
|
2300
2339
|
}
|
|
2301
2340
|
const manager = this.modelOptions[modelName];
|
|
@@ -2316,15 +2355,15 @@ var AccessRuntime = class {
|
|
|
2316
2355
|
const segments = nestedPath.split(".");
|
|
2317
2356
|
let cursor = cloned;
|
|
2318
2357
|
for (let i = 0; i < segments.length - 1; i++) {
|
|
2319
|
-
if (!(0,
|
|
2358
|
+
if (!(0, import_utils13.isPlainObject)(cursor)) break;
|
|
2320
2359
|
cursor = cursor[segments[i]];
|
|
2321
2360
|
}
|
|
2322
|
-
if ((0,
|
|
2361
|
+
if ((0, import_utils13.isPlainObject)(cursor)) {
|
|
2323
2362
|
delete cursor[segments[segments.length - 1]];
|
|
2324
2363
|
}
|
|
2325
2364
|
proposedVirtuals = cloned;
|
|
2326
2365
|
} else {
|
|
2327
|
-
(0,
|
|
2366
|
+
(0, import_utils13.set)(cloned, nestedPath, value);
|
|
2328
2367
|
proposedVirtuals = cloned;
|
|
2329
2368
|
}
|
|
2330
2369
|
}
|
|
@@ -2425,7 +2464,7 @@ var AccessRuntime = class {
|
|
|
2425
2464
|
manager.onchange("basePath", function(newval, key, target) {
|
|
2426
2465
|
target[key] = normalizeBasePath(
|
|
2427
2466
|
dataName,
|
|
2428
|
-
(0,
|
|
2467
|
+
(0, import_utils13.isString)(newval) || (0, import_utils13.isNil)(newval) ? newval : void 0
|
|
2429
2468
|
);
|
|
2430
2469
|
}).build();
|
|
2431
2470
|
return manager;
|
|
@@ -2485,20 +2524,20 @@ var AccessRuntime = class {
|
|
|
2485
2524
|
const schema = model.schema;
|
|
2486
2525
|
this.modelRefs[modelName] = buildRefs(schema.tree);
|
|
2487
2526
|
this.modelSubs[modelName] = buildSubPaths(schema.tree);
|
|
2488
|
-
this.modelAtts[modelName] = (0,
|
|
2527
|
+
this.modelAtts[modelName] = (0, import_utils13.keys)(schema.obj);
|
|
2489
2528
|
}
|
|
2490
2529
|
getModelRef(modelName, refPath) {
|
|
2491
2530
|
this.ensureModelMeta(modelName);
|
|
2492
|
-
const value = (0,
|
|
2493
|
-
return (0,
|
|
2531
|
+
const value = (0, import_utils13.get)(this.modelRefs, `${modelName}.${refPath}`, null);
|
|
2532
|
+
return (0, import_utils13.isString)(value) ? value : null;
|
|
2494
2533
|
}
|
|
2495
2534
|
getModelSub(modelName) {
|
|
2496
2535
|
this.ensureModelMeta(modelName);
|
|
2497
|
-
return (0,
|
|
2536
|
+
return (0, import_utils13.get)(this.modelSubs, modelName, []);
|
|
2498
2537
|
}
|
|
2499
2538
|
getModelAtt(modelName) {
|
|
2500
2539
|
this.ensureModelMeta(modelName);
|
|
2501
|
-
return (0,
|
|
2540
|
+
return (0, import_utils13.get)(this.modelAtts, modelName, []);
|
|
2502
2541
|
}
|
|
2503
2542
|
};
|
|
2504
2543
|
var defaultRuntime = new AccessRuntime({ allowGlobalModelLookup: true });
|
|
@@ -2518,7 +2557,7 @@ var getGlobalOption = (key, defaultValue) => {
|
|
|
2518
2557
|
|
|
2519
2558
|
// src/validation/common.ts
|
|
2520
2559
|
var import_zod2 = require("zod");
|
|
2521
|
-
var
|
|
2560
|
+
var import_utils15 = require("@web-ts-toolkit/utils");
|
|
2522
2561
|
|
|
2523
2562
|
// src/validation/public-admission-schema.ts
|
|
2524
2563
|
var admissions = /* @__PURE__ */ new WeakMap();
|
|
@@ -2540,7 +2579,7 @@ function assertTransformedPublicAdmission(schema, value) {
|
|
|
2540
2579
|
}
|
|
2541
2580
|
|
|
2542
2581
|
// src/correlated-includes.ts
|
|
2543
|
-
var
|
|
2582
|
+
var import_utils14 = require("@web-ts-toolkit/utils");
|
|
2544
2583
|
var PARENT_MARKER_KEY = "$parent";
|
|
2545
2584
|
var ESCAPE_WRAPPER_KEY = "$escape";
|
|
2546
2585
|
var SUBQUERY_PAYLOAD_KEYS = /* @__PURE__ */ new Set(["$$sq", "$$date"]);
|
|
@@ -2551,10 +2590,10 @@ var FIELD_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
|
|
|
2551
2590
|
var ARRAY_INDEX_SEGMENT_PATTERN = /^(0|[1-9]\d*)$/;
|
|
2552
2591
|
var ownKeys = (value) => Object.keys(value);
|
|
2553
2592
|
function isParentRefMarker(value) {
|
|
2554
|
-
return (0,
|
|
2593
|
+
return (0, import_utils14.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === PARENT_MARKER_KEY;
|
|
2555
2594
|
}
|
|
2556
2595
|
function isEscapedParentRef(value) {
|
|
2557
|
-
return (0,
|
|
2596
|
+
return (0, import_utils14.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === ESCAPE_WRAPPER_KEY;
|
|
2558
2597
|
}
|
|
2559
2598
|
function hasMarkerKey(value) {
|
|
2560
2599
|
return ownKeys(value).includes(PARENT_MARKER_KEY) || ownKeys(value).includes(ESCAPE_WRAPPER_KEY);
|
|
@@ -2573,12 +2612,12 @@ function containsParentMarkerShape(value) {
|
|
|
2573
2612
|
const seen = /* @__PURE__ */ new Set();
|
|
2574
2613
|
const visit = (current) => {
|
|
2575
2614
|
if (isParentRefMarker(current) || isEscapedParentRef(current)) return true;
|
|
2576
|
-
if ((0,
|
|
2615
|
+
if ((0, import_utils14.isArray)(current)) {
|
|
2577
2616
|
if (seen.has(current)) return false;
|
|
2578
2617
|
seen.add(current);
|
|
2579
2618
|
return current.some(visit);
|
|
2580
2619
|
}
|
|
2581
|
-
if ((0,
|
|
2620
|
+
if ((0, import_utils14.isPlainObject)(current)) {
|
|
2582
2621
|
if (seen.has(current)) return false;
|
|
2583
2622
|
seen.add(current);
|
|
2584
2623
|
if (hasMarkerKey(current)) return true;
|
|
@@ -2608,7 +2647,7 @@ function scanTemplateValueNode(value, path, issues) {
|
|
|
2608
2647
|
}
|
|
2609
2648
|
return;
|
|
2610
2649
|
}
|
|
2611
|
-
if ((0,
|
|
2650
|
+
if ((0, import_utils14.isPlainObject)(value)) {
|
|
2612
2651
|
if (hasMarkerKey(value)) {
|
|
2613
2652
|
issues.push({
|
|
2614
2653
|
message: 'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }',
|
|
@@ -2619,7 +2658,7 @@ function scanTemplateValueNode(value, path, issues) {
|
|
|
2619
2658
|
scanTemplateObjectEntries(value, path, issues);
|
|
2620
2659
|
return;
|
|
2621
2660
|
}
|
|
2622
|
-
if ((0,
|
|
2661
|
+
if ((0, import_utils14.isArray)(value)) {
|
|
2623
2662
|
value.forEach((item, index) => scanTemplateValueNode(item, [...path, index], issues));
|
|
2624
2663
|
}
|
|
2625
2664
|
}
|
|
@@ -2660,7 +2699,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
2660
2699
|
continue;
|
|
2661
2700
|
}
|
|
2662
2701
|
if (LOGICAL_CLAUSE_KEYS.has(key)) {
|
|
2663
|
-
if (!(0,
|
|
2702
|
+
if (!(0, import_utils14.isArray)(child)) {
|
|
2664
2703
|
scanTemplateValueNode(child, childPath, issues);
|
|
2665
2704
|
continue;
|
|
2666
2705
|
}
|
|
@@ -2673,7 +2712,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
2673
2712
|
});
|
|
2674
2713
|
return;
|
|
2675
2714
|
}
|
|
2676
|
-
if ((0,
|
|
2715
|
+
if ((0, import_utils14.isPlainObject)(clause)) {
|
|
2677
2716
|
scanTemplateObjectEntries(clause, clausePath, issues);
|
|
2678
2717
|
}
|
|
2679
2718
|
});
|
|
@@ -2684,7 +2723,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
|
|
|
2684
2723
|
}
|
|
2685
2724
|
function validateCorrelatedFilterTemplate(filter) {
|
|
2686
2725
|
const issues = [];
|
|
2687
|
-
if (!(0,
|
|
2726
|
+
if (!(0, import_utils14.isPlainObject)(filter)) {
|
|
2688
2727
|
issues.push({ message: "Correlated include filter must be an object", path: [] });
|
|
2689
2728
|
return issues;
|
|
2690
2729
|
}
|
|
@@ -2812,7 +2851,7 @@ var correlatedFilterSchema = import_zod2.z.record(import_zod2.z.string(), import
|
|
|
2812
2851
|
}
|
|
2813
2852
|
});
|
|
2814
2853
|
var correlatedEmptyOptionsSchema = import_zod2.z.unknown().refine(
|
|
2815
|
-
(value) => value === void 0 || (0,
|
|
2854
|
+
(value) => value === void 0 || (0, import_utils15.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
2816
2855
|
"Correlated include options must be absent or empty"
|
|
2817
2856
|
).optional();
|
|
2818
2857
|
var correlatedPathSchema = import_zod2.z.string().min(1).superRefine((path, ctx) => {
|
|
@@ -2849,7 +2888,7 @@ var correlatedListArgsSchema = import_zod2.z.object({
|
|
|
2849
2888
|
include: import_zod2.z.lazy(() => correlatedNestedIncludeSchema).optional()
|
|
2850
2889
|
}).strict().superRefine((args, ctx) => checkArgsMarkers(args.select, args.sort, ctx));
|
|
2851
2890
|
var correlatedCountArgsSchema = import_zod2.z.unknown().refine(
|
|
2852
|
-
(value) => value === void 0 || (0,
|
|
2891
|
+
(value) => value === void 0 || (0, import_utils15.isPlainObject)(value) && Object.keys(value).length === 0,
|
|
2853
2892
|
"Count includes accept no args"
|
|
2854
2893
|
).optional();
|
|
2855
2894
|
var correlatedReadByIdSchema = import_zod2.z.object({
|
|
@@ -2902,7 +2941,7 @@ var correlatedNestedIncludeSchema = import_zod2.z.union([includeItemSchema, impo
|
|
|
2902
2941
|
var rejectDuplicateCorrelatedPaths = (items, ctx) => {
|
|
2903
2942
|
const seen = /* @__PURE__ */ new Set();
|
|
2904
2943
|
items.forEach((item, index) => {
|
|
2905
|
-
if ((0,
|
|
2944
|
+
if ((0, import_utils15.isPlainObject)(item) && item.mode === "correlated" && typeof item.path === "string") {
|
|
2906
2945
|
if (seen.has(item.path)) {
|
|
2907
2946
|
ctx.addIssue({
|
|
2908
2947
|
code: import_zod2.z.ZodIssueCode.custom,
|