@web-ts-toolkit/access-router 0.37.0 → 0.39.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/advanced.js CHANGED
@@ -128,47 +128,51 @@ var import_express_json_router = __toESM(require("@web-ts-toolkit/express-json-r
128
128
  // src/runtime.ts
129
129
  var import_mongoose2 = __toESM(require("mongoose"));
130
130
  var import_mongoose_schema_jsonschema = __toESM(require("mongoose-schema-jsonschema"));
131
- var import_utils7 = require("@web-ts-toolkit/utils");
131
+ var import_utils8 = require("@web-ts-toolkit/utils");
132
+
133
+ // src/helpers/query.ts
134
+ var import_utils = require("@web-ts-toolkit/utils");
135
+ var DEFAULT_LIST_HARD_LIMIT = 1e3;
132
136
 
133
137
  // src/helpers/index.ts
134
- var import_utils2 = require("@web-ts-toolkit/utils");
138
+ var import_utils3 = require("@web-ts-toolkit/utils");
135
139
 
136
140
  // src/lib.ts
137
141
  var import_mongoose = require("mongoose");
138
- var import_utils = require("@web-ts-toolkit/utils");
142
+ var import_utils2 = require("@web-ts-toolkit/utils");
139
143
  var isSchema = (val) => val instanceof import_mongoose.Schema;
140
144
  var isObjectIdType = (val) => val === "ObjectId" || val === import_mongoose.Schema.Types.ObjectId;
141
- var isReference = (val) => (0, import_utils.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
145
+ var isReference = (val) => (0, import_utils2.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
142
146
 
143
147
  // src/helpers/index.ts
144
148
  function recurseObject(obj) {
145
149
  if (isSchema(obj)) {
146
150
  return buildRefs(obj.tree);
147
151
  }
148
- if (!(0, import_utils2.isObject)(obj)) return null;
152
+ if (!(0, import_utils3.isObject)(obj)) return null;
149
153
  if (isReference(obj)) {
150
154
  return obj.ref;
151
155
  }
152
156
  let ret = null;
153
- (0, import_utils2.forEach)(obj, (val) => {
157
+ (0, import_utils3.forEach)(obj, (val) => {
154
158
  ret = recurseObject(val);
155
- if (!(0, import_utils2.isEmpty)(ret)) {
159
+ if (!(0, import_utils3.isEmpty)(ret)) {
156
160
  return false;
157
161
  }
158
162
  });
159
163
  return ret;
160
164
  }
161
165
  function buildRefs(schema) {
162
- if (!(0, import_utils2.isObject)(schema)) return {};
166
+ if (!(0, import_utils3.isObject)(schema)) return {};
163
167
  const references = {};
164
- (0, import_utils2.forEach)(schema, (val, key) => {
168
+ (0, import_utils3.forEach)(schema, (val, key) => {
165
169
  const paths = recurseObject(val);
166
- if (!(0, import_utils2.isEmpty)(paths)) {
170
+ if (!(0, import_utils3.isEmpty)(paths)) {
167
171
  references[key] = paths;
168
172
  }
169
- const target = (0, import_utils2.isObject)(val) && "type" in val ? val.type ?? val : val;
170
- if ((0, import_utils2.isArray)(target) && target.length > 0) {
171
- if (isSchema(target[0]) || (0, import_utils2.isPlainObject)(target[0])) {
173
+ const target = (0, import_utils3.isObject)(val) && "type" in val ? val.type ?? val : val;
174
+ if ((0, import_utils3.isArray)(target) && target.length > 0) {
175
+ if (isSchema(target[0]) || (0, import_utils3.isPlainObject)(target[0])) {
172
176
  return;
173
177
  }
174
178
  }
@@ -176,12 +180,12 @@ function buildRefs(schema) {
176
180
  return references;
177
181
  }
178
182
  function buildSubPaths(schema) {
179
- if (!(0, import_utils2.isObject)(schema)) return [];
183
+ if (!(0, import_utils3.isObject)(schema)) return [];
180
184
  const subPaths = [];
181
- (0, import_utils2.forEach)(schema, (val, key) => {
182
- const target = (0, import_utils2.isObject)(val) && "type" in val ? val.type ?? val : val;
183
- if ((0, import_utils2.isArray)(target) && target.length > 0) {
184
- if (isSchema(target[0]) || (0, import_utils2.isPlainObject)(target[0]) && !isReference(target[0])) {
185
+ (0, import_utils3.forEach)(schema, (val, key) => {
186
+ const target = (0, import_utils3.isObject)(val) && "type" in val ? val.type ?? val : val;
187
+ if ((0, import_utils3.isArray)(target) && target.length > 0) {
188
+ if (isSchema(target[0]) || (0, import_utils3.isPlainObject)(target[0]) && !isReference(target[0])) {
185
189
  subPaths.push(key);
186
190
  }
187
191
  }
@@ -190,7 +194,7 @@ function buildSubPaths(schema) {
190
194
  }
191
195
 
192
196
  // src/openapi/build-spec.ts
193
- var import_utils4 = require("@web-ts-toolkit/utils");
197
+ var import_utils5 = require("@web-ts-toolkit/utils");
194
198
 
195
199
  // src/openapi/responses.ts
196
200
  var json = (schema) => ({
@@ -261,19 +265,19 @@ var openApiResponses = {
261
265
 
262
266
  // src/openapi/schemas.ts
263
267
  var import_zod = require("zod");
264
- var import_utils3 = require("@web-ts-toolkit/utils");
268
+ var import_utils4 = require("@web-ts-toolkit/utils");
265
269
  var fallbackObjectSchema = { type: "object", additionalProperties: true };
266
270
  function isOpenApiSchemaPatch(source) {
267
- return (0, import_utils3.isPlainObject)(source) && source.kind === "objectProperties";
271
+ return (0, import_utils4.isPlainObject)(source) && source.kind === "objectProperties";
268
272
  }
269
273
  function isOpenApiSchemaResolver(source) {
270
- return (0, import_utils3.isPlainObject)(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
274
+ return (0, import_utils4.isPlainObject)(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
271
275
  }
272
276
  function isJsonSchemaLike(source) {
273
- return (0, import_utils3.isPlainObject)(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
277
+ return (0, import_utils4.isPlainObject)(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
274
278
  }
275
279
  function hasOpenApiSchema(source) {
276
- return (0, import_utils3.isPlainObject)(source) && isJsonSchemaLike(source.openapi);
280
+ return (0, import_utils4.isPlainObject)(source) && isJsonSchemaLike(source.openapi);
277
281
  }
278
282
  function toOpenApiSchema(source) {
279
283
  if (!source) return void 0;
@@ -281,7 +285,7 @@ function toOpenApiSchema(source) {
281
285
  if (!resolvedSource) return void 0;
282
286
  if (isOpenApiSchemaPatch(resolvedSource)) {
283
287
  const schema = toOpenApiSchema(resolvedSource.source) ?? { ...fallbackObjectSchema };
284
- const properties = (0, import_utils3.isPlainObject)(schema.properties) ? { ...schema.properties } : {};
288
+ const properties = (0, import_utils4.isPlainObject)(schema.properties) ? { ...schema.properties } : {};
285
289
  for (const [key, value] of Object.entries(resolvedSource.properties)) {
286
290
  properties[key] = toOpenApiSchema(value) ?? fallbackObjectSchema;
287
291
  }
@@ -314,9 +318,9 @@ var toOpenApiPath = (path) => normalizePath(path).replace(/:([A-Za-z0-9_]+)/g, "
314
318
  var schemaToQueryParameters = (schema) => {
315
319
  const jsonSchema = toOpenApiSchema(schema);
316
320
  if (!jsonSchema || jsonSchema.type !== "object") return [];
317
- const properties = (0, import_utils4.isPlainObject)(jsonSchema.properties) ? jsonSchema.properties : {};
321
+ const properties = (0, import_utils5.isPlainObject)(jsonSchema.properties) ? jsonSchema.properties : {};
318
322
  const required = new Set(
319
- (0, import_utils4.isArray)(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
323
+ (0, import_utils5.isArray)(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
320
324
  );
321
325
  return Object.entries(properties).map(([name, value]) => ({
322
326
  name,
@@ -407,7 +411,7 @@ var OpenApiCollisionError = class extends Error {
407
411
  };
408
412
 
409
413
  // src/openapi/registry.ts
410
- var isPlainObject5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
414
+ var isPlainObject6 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
411
415
  var stableKey = (value) => {
412
416
  if (value === null || typeof value === "undefined") return "null";
413
417
  if (typeof value === "function") return "[Function]";
@@ -442,7 +446,7 @@ var OpenApiRegistry = class {
442
446
  this.routes[existingIndex] = route;
443
447
  return;
444
448
  }
445
- if (descriptorsEqual(existing, route) && (route.idempotent || isPlainObject5(existing) && existing.idempotent)) {
449
+ if (descriptorsEqual(existing, route) && (route.idempotent || isPlainObject6(existing) && existing.idempotent)) {
446
450
  return;
447
451
  }
448
452
  if (this.options.rejectConflicts) {
@@ -520,7 +524,43 @@ var defaultLogger = (0, import_winston.createLogger)({
520
524
  });
521
525
 
522
526
  // src/options/manager.ts
523
- var import_utils5 = require("@web-ts-toolkit/utils");
527
+ var import_utils6 = require("@web-ts-toolkit/utils");
528
+ var toPath = (key) => {
529
+ if (Array.isArray(key)) return key;
530
+ return typeof key === "string" ? key.split(".") : [key];
531
+ };
532
+ var cloneConfigValue = (value) => {
533
+ if (Array.isArray(value)) {
534
+ return value.map((item) => cloneConfigValue(item));
535
+ }
536
+ if (!value || typeof value !== "object") {
537
+ return value;
538
+ }
539
+ if (Object.getPrototypeOf(value) !== Object.prototype) {
540
+ return value;
541
+ }
542
+ return Object.fromEntries(
543
+ Object.entries(value).map(([entryKey, entryValue]) => [
544
+ entryKey,
545
+ cloneConfigValue(entryValue)
546
+ ])
547
+ );
548
+ };
549
+ var freezeConfigValue = (value) => {
550
+ if (!value || typeof value !== "object") {
551
+ return value;
552
+ }
553
+ if (Object.isFrozen(value)) {
554
+ return value;
555
+ }
556
+ if (Array.isArray(value) || Object.getPrototypeOf(value) === Object.prototype) {
557
+ for (const nestedValue of Object.values(value)) {
558
+ freezeConfigValue(nestedValue);
559
+ }
560
+ return Object.freeze(value);
561
+ }
562
+ return value;
563
+ };
524
564
  var getNestedOption = (manager, key, defaultValue) => {
525
565
  const keys2 = String(key).split(".");
526
566
  if (keys2.length === 1) {
@@ -538,8 +578,9 @@ var getNestedOption = (manager, key, defaultValue) => {
538
578
  return option;
539
579
  };
540
580
  var OptionsManager = class {
541
- constructor(defaultOptions) {
581
+ constructor(defaultOptions, options = {}) {
542
582
  this.defaultOptions = defaultOptions;
583
+ this.preserveKeys = new Set(options.preserveKeys ?? []);
543
584
  this.listeners = {};
544
585
  const _this = this;
545
586
  this.currentOptions = new Proxy({}, {
@@ -557,25 +598,46 @@ var OptionsManager = class {
557
598
  return this;
558
599
  }
559
600
  get(key, defaultValue) {
560
- return (0, import_utils5.get)(this.currentOptions, key, defaultValue);
601
+ return (0, import_utils6.get)(this.currentOptions, key, defaultValue);
561
602
  }
562
603
  set(key, value) {
563
- (0, import_utils5.set)(this.currentOptions, key, value);
604
+ const path = toPath(key);
605
+ if (path.length <= 1) {
606
+ (0, import_utils6.set)(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneConfigValue(value));
607
+ return;
608
+ }
609
+ const [rootKey, ...nestedPath] = path;
610
+ const currentRoot = (0, import_utils6.get)(this.currentOptions, [rootKey], void 0);
611
+ const nextRoot = cloneConfigValue(currentRoot ?? {});
612
+ (0, import_utils6.set)(nextRoot, nestedPath, cloneConfigValue(value));
613
+ (0, import_utils6.set)(this.currentOptions, [rootKey], nextRoot);
564
614
  }
565
615
  fetch() {
566
- return { ...this.currentOptions };
616
+ const cloned = cloneConfigValue(this.currentOptions);
617
+ for (const key of this.preserveKeys) {
618
+ if (key in this.currentOptions) {
619
+ cloned[key] = this.currentOptions[key];
620
+ }
621
+ }
622
+ return freezeConfigValue(cloned);
567
623
  }
568
624
  assign(options) {
569
- (0, import_utils5.assign)(this.currentOptions, options);
625
+ const cloned = cloneConfigValue(options);
626
+ for (const key of this.preserveKeys) {
627
+ if (key in options) {
628
+ cloned[key] = options[key];
629
+ }
630
+ }
631
+ (0, import_utils6.assign)(this.currentOptions, cloned);
570
632
  }
571
633
  onchange(key, func) {
572
- (0, import_utils5.set)(this.listeners, key, func);
634
+ (0, import_utils6.set)(this.listeners, key, func);
573
635
  return this;
574
636
  }
575
637
  };
576
638
 
577
639
  // src/request-complexity.ts
578
- var import_utils6 = require("@web-ts-toolkit/utils");
640
+ var import_utils7 = require("@web-ts-toolkit/utils");
579
641
  var defaultRequestComplexity = {
580
642
  maxDepth: 8,
581
643
  maxNodes: 500,
@@ -584,7 +646,8 @@ var defaultRequestComplexity = {
584
646
  maxBulkItems: 100,
585
647
  maxIncludeCount: 10,
586
648
  maxSubQueryCount: 10,
587
- maxBulkConcurrency: 10
649
+ maxBulkConcurrency: 10,
650
+ maxHookConcurrency: 10
588
651
  };
589
652
  var normalizePositiveInteger = (value, fallback) => {
590
653
  return Number.isSafeInteger(value) && Number(value) > 0 ? Number(value) : fallback;
@@ -600,6 +663,10 @@ var resolveRequestComplexity = (options) => ({
600
663
  maxBulkConcurrency: normalizePositiveInteger(
601
664
  options?.maxBulkConcurrency,
602
665
  defaultRequestComplexity.maxBulkConcurrency
666
+ ),
667
+ maxHookConcurrency: normalizePositiveInteger(
668
+ options?.maxHookConcurrency,
669
+ defaultRequestComplexity.maxHookConcurrency
603
670
  )
604
671
  });
605
672
  function validateRequestComplexity(value, options, scope = "request") {
@@ -626,7 +693,7 @@ function validateRequestComplexity(value, options, scope = "request") {
626
693
  pushError(`Request exceeds maximum depth of ${limits.maxDepth}`, path);
627
694
  return;
628
695
  }
629
- if ((0, import_utils6.isArray)(current)) {
696
+ if ((0, import_utils7.isArray)(current)) {
630
697
  if (parentKey === "$and" || parentKey === "$or" || parentKey === "$nor") {
631
698
  logicalClauses += current.length;
632
699
  if (logicalClauses > limits.maxLogicalClauses) {
@@ -646,14 +713,14 @@ function validateRequestComplexity(value, options, scope = "request") {
646
713
  }
647
714
  return;
648
715
  }
649
- if (!(0, import_utils6.isPlainObject)(current)) return;
716
+ if (!(0, import_utils7.isPlainObject)(current)) return;
650
717
  for (const [key, child] of Object.entries(current)) {
651
718
  if (key === "__proto__" || key === "prototype" || key === "constructor") {
652
719
  pushError(`Unsupported key: ${key}`, path.concat(key));
653
720
  return;
654
721
  }
655
722
  if (scope === "request" && key === "include") {
656
- includeCount += (0, import_utils6.isArray)(child) ? child.length : 1;
723
+ includeCount += (0, import_utils7.isArray)(child) ? child.length : 1;
657
724
  if (includeCount > limits.maxIncludeCount) {
658
725
  pushError(`Request exceeds maximum include count of ${limits.maxIncludeCount}`, path.concat(key));
659
726
  return;
@@ -693,47 +760,48 @@ var defaultModelOptions = {
693
760
  var defaultDataOptions = {
694
761
  basePath: null,
695
762
  parentPath: "/",
696
- queryRouteSegment: "__query"
763
+ queryRouteSegment: "__query",
764
+ listHardLimit: DEFAULT_LIST_HARD_LIMIT
697
765
  };
698
766
  var normalizeBasePath = (name, value) => {
699
- if ((0, import_utils7.isNil)(value)) {
767
+ if ((0, import_utils8.isNil)(value)) {
700
768
  return `/${pluralize(name)}`;
701
769
  }
702
- return (0, import_utils7.isString)(value) ? (0, import_utils7.addLeadingSlash)(value) : "";
770
+ return (0, import_utils8.isString)(value) ? (0, import_utils8.addLeadingSlash)(value) : "";
703
771
  };
704
772
  var hasModelPermission = (value, modelPermissionPrefix) => {
705
773
  if (!modelPermissionPrefix) {
706
774
  return true;
707
775
  }
708
- if ((0, import_utils7.isString)(value)) {
776
+ if ((0, import_utils8.isString)(value)) {
709
777
  return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
710
778
  }
711
- if ((0, import_utils7.isArray)(value)) {
779
+ if ((0, import_utils8.isArray)(value)) {
712
780
  return value.some((item) => {
713
- if ((0, import_utils7.isString)(item) || (0, import_utils7.isArray)(item)) {
781
+ if ((0, import_utils8.isString)(item) || (0, import_utils8.isArray)(item)) {
714
782
  return hasModelPermission(item, modelPermissionPrefix);
715
783
  }
716
784
  return true;
717
785
  });
718
786
  }
719
- return (0, import_utils7.isFunction)(value);
787
+ return (0, import_utils8.isFunction)(value);
720
788
  };
721
789
  var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
722
790
  const schemaKeys = Object.keys(permissionSchema);
723
791
  const globalPermissionKeys = {};
724
792
  const modelPermissionKeys = {};
725
- (0, import_utils7.forEach)(schemaKeys, (schemaKey) => {
793
+ (0, import_utils8.forEach)(schemaKeys, (schemaKey) => {
726
794
  const schemaRule = permissionSchema[schemaKey];
727
- const ruleEntries = (0, import_utils7.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
795
+ const ruleEntries = (0, import_utils8.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
728
796
  for (let x = 0; x < ruleEntries.length; x++) {
729
797
  const [accessKey, value] = ruleEntries[x];
730
- if (!(0, import_utils7.isArray)(globalPermissionKeys[accessKey])) {
798
+ if (!(0, import_utils8.isArray)(globalPermissionKeys[accessKey])) {
731
799
  globalPermissionKeys[accessKey] = [];
732
800
  }
733
- if (!(0, import_utils7.isArray)(modelPermissionKeys[accessKey])) {
801
+ if (!(0, import_utils8.isArray)(modelPermissionKeys[accessKey])) {
734
802
  modelPermissionKeys[accessKey] = [];
735
803
  }
736
- if ((0, import_utils7.isBoolean)(value)) {
804
+ if ((0, import_utils8.isBoolean)(value)) {
737
805
  globalPermissionKeys[accessKey].push(schemaKey);
738
806
  return;
739
807
  }
@@ -750,17 +818,30 @@ var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
750
818
  modelPermissionKeys
751
819
  };
752
820
  };
821
+ var refreshPermissionMetadata = (target) => {
822
+ const permissionSchema = target.permissionSchema ?? {};
823
+ const { schemaKeys, globalPermissionKeys, modelPermissionKeys } = classifyPermissionSchema(
824
+ permissionSchema,
825
+ target.modelPermissionPrefix ?? ""
826
+ );
827
+ target._permissionSchemaKeys = schemaKeys;
828
+ target._globalPermissionKeys = globalPermissionKeys;
829
+ target._modelPermissionKeys = modelPermissionKeys;
830
+ };
753
831
  var AccessRuntime = class {
754
- constructor() {
755
- this.globalOptions = new OptionsManager({
756
- requestPermissionField: "_permissions",
757
- globalPermissions: () => ({}),
758
- requireRegisteredPopulateModels: true,
759
- logger: defaultLogger,
760
- requestComplexity: defaultRequestComplexity
761
- }).build();
832
+ constructor(options = {}) {
833
+ this.globalOptions = new OptionsManager(
834
+ {
835
+ requestPermissionField: "_permissions",
836
+ globalPermissions: () => ({}),
837
+ requireRegisteredPopulateModels: true,
838
+ logger: defaultLogger,
839
+ requestComplexity: defaultRequestComplexity
840
+ },
841
+ { preserveKeys: ["logger"] }
842
+ ).build();
762
843
  this.defaultModelOptions = new OptionsManager({
763
- listHardLimit: 1e3,
844
+ listHardLimit: DEFAULT_LIST_HARD_LIMIT,
764
845
  documentPermissionField: "_permissions",
765
846
  idParam: "id",
766
847
  idField: "_id",
@@ -778,6 +859,7 @@ var AccessRuntime = class {
778
859
  this.modelAtts = {};
779
860
  this.modelInstances = {};
780
861
  this.openApiRegistry = new OpenApiRegistry();
862
+ this.allowGlobalModelLookup = options.allowGlobalModelLookup ?? false;
781
863
  ensureMongooseJsonSchemaInitialized();
782
864
  }
783
865
  registerModelInstance(modelName, model) {
@@ -793,13 +875,16 @@ var AccessRuntime = class {
793
875
  this.modelInstances[modelName] = model;
794
876
  }
795
877
  hasModelInstance(modelName) {
796
- return modelName in this.modelInstances;
878
+ return modelName in this.modelInstances || this.allowGlobalModelLookup && modelName in import_mongoose2.default.models;
797
879
  }
798
880
  getModelInstance(modelName) {
799
881
  const registered = this.modelInstances[modelName];
800
882
  if (registered) return registered;
883
+ if (!this.allowGlobalModelLookup) return null;
801
884
  const global = import_mongoose2.default.models[modelName];
802
- return global ?? null;
885
+ if (!global) return null;
886
+ this.registerModelInstance(modelName, global);
887
+ return global;
803
888
  }
804
889
  registerOpenApiRoute(route) {
805
890
  this.openApiRegistry.register(route);
@@ -848,24 +933,24 @@ var AccessRuntime = class {
848
933
  return this.defaultModelOptions.get(key, defaultValue);
849
934
  }
850
935
  createModelOptions(modelName) {
851
- const model = this.getModelInstance(modelName) ?? import_mongoose2.default.model(modelName);
936
+ const model = this.getModelInstance(modelName);
937
+ if (!model) {
938
+ throw new Error(
939
+ `Runtime model registry missing model "${modelName}". Pass a mongoose.Model instance to createRouter() or register it with registerModelInstance() before using this isolated runtime.`
940
+ );
941
+ }
852
942
  const manager = new OptionsManager({
853
943
  ...defaultModelOptions,
854
944
  modelName
855
945
  });
856
- manager.onchange("permissionSchema", function(newval, key, target) {
857
- const permissionSchema = newval ?? {};
858
- const { schemaKeys, globalPermissionKeys, modelPermissionKeys } = classifyPermissionSchema(
859
- permissionSchema,
860
- target.modelPermissionPrefix ?? ""
861
- );
862
- target._permissionSchemaKeys = schemaKeys;
863
- target._globalPermissionKeys = globalPermissionKeys;
864
- target._modelPermissionKeys = modelPermissionKeys;
946
+ manager.onchange("permissionSchema", function(_newval, _key, target) {
947
+ refreshPermissionMetadata(target);
948
+ }).onchange("modelPermissionPrefix", function(_newval, _key, target) {
949
+ refreshPermissionMetadata(target);
865
950
  }).onchange("basePath", function(newval, key, target) {
866
951
  target[key] = normalizeBasePath(
867
952
  modelName,
868
- (0, import_utils7.isString)(newval) || (0, import_utils7.isNil)(newval) ? newval : void 0
953
+ (0, import_utils8.isString)(newval) || (0, import_utils8.isNil)(newval) ? newval : void 0
869
954
  );
870
955
  }).build();
871
956
  this.modelJsonSchemas[modelName] = model.jsonSchema();
@@ -923,7 +1008,7 @@ var AccessRuntime = class {
923
1008
  manager.onchange("basePath", function(newval, key, target) {
924
1009
  target[key] = normalizeBasePath(
925
1010
  dataName,
926
- (0, import_utils7.isString)(newval) || (0, import_utils7.isNil)(newval) ? newval : void 0
1011
+ (0, import_utils8.isString)(newval) || (0, import_utils8.isNil)(newval) ? newval : void 0
927
1012
  );
928
1013
  }).build();
929
1014
  return manager;
@@ -974,23 +1059,23 @@ var AccessRuntime = class {
974
1059
  const schema = model.schema;
975
1060
  this.modelRefs[modelName] = buildRefs(schema.tree);
976
1061
  this.modelSubs[modelName] = buildSubPaths(schema.tree);
977
- this.modelAtts[modelName] = (0, import_utils7.keys)(schema.obj);
1062
+ this.modelAtts[modelName] = (0, import_utils8.keys)(schema.obj);
978
1063
  }
979
1064
  getModelRef(modelName, refPath) {
980
1065
  this.ensureModelMeta(modelName);
981
- const value = (0, import_utils7.get)(this.modelRefs, `${modelName}.${refPath}`, null);
982
- return (0, import_utils7.isString)(value) ? value : null;
1066
+ const value = (0, import_utils8.get)(this.modelRefs, `${modelName}.${refPath}`, null);
1067
+ return (0, import_utils8.isString)(value) ? value : null;
983
1068
  }
984
1069
  getModelSub(modelName) {
985
1070
  this.ensureModelMeta(modelName);
986
- return (0, import_utils7.get)(this.modelSubs, modelName, []);
1071
+ return (0, import_utils8.get)(this.modelSubs, modelName, []);
987
1072
  }
988
1073
  getModelAtt(modelName) {
989
1074
  this.ensureModelMeta(modelName);
990
- return (0, import_utils7.get)(this.modelAtts, modelName, []);
1075
+ return (0, import_utils8.get)(this.modelAtts, modelName, []);
991
1076
  }
992
1077
  };
993
- var defaultRuntime = new AccessRuntime();
1078
+ var defaultRuntime = new AccessRuntime({ allowGlobalModelLookup: true });
994
1079
 
995
1080
  // src/runtime-context.ts
996
1081
  var import_node_async_hooks = require("async_hooks");
@@ -1074,7 +1159,7 @@ var includeItemSchema = import_zod2.z.object({
1074
1159
  filter: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
1075
1160
  localField: import_zod2.z.string().min(1),
1076
1161
  foreignField: import_zod2.z.string().min(1),
1077
- args: import_zod2.z.unknown().optional(),
1162
+ args: import_zod2.z.unknown().optional().describe("Forwarded to list/read includes. Count includes ignore pagination fields so counts remain exact."),
1078
1163
  options: import_zod2.z.unknown().optional()
1079
1164
  }).passthrough();
1080
1165
  var includeSchema = import_zod2.z.union([includeItemSchema, import_zod2.z.array(includeItemSchema)]);
@@ -1611,7 +1696,7 @@ var import_zod4 = require("zod");
1611
1696
  var dataListBodySchema = import_zod4.z.object({
1612
1697
  filter: objectOrArraySchema.optional(),
1613
1698
  select: projectionSchema.optional(),
1614
- sort: import_zod4.z.string().optional(),
1699
+ sort: sortSchema.optional(),
1615
1700
  skip: import_zod4.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
1616
1701
  limit: import_zod4.z.union([positiveIntegerSchema, positiveIntegerString]).optional(),
1617
1702
  page: import_zod4.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
@@ -1703,7 +1788,7 @@ var rootModelSubReadArgsSchema = import_zod5.z.object({
1703
1788
  var rootModelCountOptionsSchema = import_zod5.z.object({}).strict().optional();
1704
1789
  var rootDataListArgsSchema = import_zod5.z.object({
1705
1790
  select: projectionSchema.optional(),
1706
- sort: import_zod5.z.string().optional(),
1791
+ sort: sortSchema.optional(),
1707
1792
  skip: import_zod5.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
1708
1793
  limit: import_zod5.z.union([positiveIntegerSchema, positiveIntegerString]).optional(),
1709
1794
  page: import_zod5.z.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),