@web-ts-toolkit/access-router 0.52.0 → 0.53.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/index.js CHANGED
@@ -68,7 +68,38 @@ function assertPublicAdmission(input, kind = "envelope") {
68
68
  for (const key of ["filter", "match", "data"]) add(record2[key], "data", key);
69
69
  }
70
70
  }
71
+ function assertHydrationDefaults(defaults) {
72
+ if (defaults && typeof defaults === "object") {
73
+ const record2 = defaults;
74
+ if ("hydration" in record2)
75
+ throw new TypeError("defaults.hydration is unsupported; use model hydration configuration");
76
+ for (const bucket of [
77
+ "publicListOptions",
78
+ "publicReadOptions",
79
+ "findOptions",
80
+ "findOneOptions",
81
+ "findByIdOptions",
82
+ "createOptions",
83
+ "updateOneOptions",
84
+ "updateByIdOptions",
85
+ "upsertOptions",
86
+ "existsOptions",
87
+ "publicCreateOptions",
88
+ "publicUpdateOptions"
89
+ ]) {
90
+ const options = record2[bucket];
91
+ if (!options || typeof options !== "object" && typeof options !== "function") continue;
92
+ for (const key of ["lean", "hydration"]) {
93
+ if (!(key in options)) continue;
94
+ const method = bucket.slice(0, -"Options".length);
95
+ const migration = ["publicList", "publicRead", "find", "findOne", "findById"].includes(method) ? `use model hydration.${method} ('lean' or 'hydrated')` : "this method has a fixed fetch mode";
96
+ throw new TypeError(`defaults.${bucket}.${key} is unsupported; ${migration}`);
97
+ }
98
+ }
99
+ }
100
+ }
71
101
  function assertPublicDefaults(defaults) {
102
+ assertHydrationDefaults(defaults);
72
103
  assertPublicAdmission(defaults);
73
104
  if (defaults && typeof defaults === "object") {
74
105
  for (const value of Object.values(defaults)) assertPublicAdmission(value);
@@ -134,21 +165,43 @@ var init_public_admission = __esm({
134
165
  "includePermissions",
135
166
  "includeFieldPermissions",
136
167
  "includeCount",
137
- "populateAccess",
138
- "lean"
139
- ];
140
- readOptions = [
141
- "skim",
142
- "includePermissions",
143
- "includeFieldPermissions",
144
- "tryList",
145
- "populateAccess",
146
- "lean"
168
+ "populateAccess"
147
169
  ];
170
+ readOptions = ["skim", "includePermissions", "includeFieldPermissions", "tryList", "populateAccess"];
148
171
  requestAuthorization = Object.freeze({ outputFields: Object.freeze({ mode: "request" }) });
149
172
  }
150
173
  });
151
174
 
175
+ // src/options/hydration.ts
176
+ function normalizeHydration(value, path = "hydration") {
177
+ if (value === void 0) return void 0;
178
+ if (value === null || typeof value !== "object" || ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
179
+ throw new TypeError(`${path} must be a plain record of model hydration modes`);
180
+ const result2 = {};
181
+ for (const key of Reflect.ownKeys(value)) {
182
+ if (typeof key !== "string" || !methods.includes(key))
183
+ throw new TypeError(`${path}.${String(key)} is not a supported hydration method`);
184
+ const mode = value[key];
185
+ if (mode !== void 0 && mode !== "lean" && mode !== "hydrated")
186
+ throw new TypeError(`${path}.${key} must be 'lean', 'hydrated', or undefined`);
187
+ result2[key] = mode;
188
+ }
189
+ return Object.freeze(result2);
190
+ }
191
+ function normalizeHydrationUpdate(current, key, value) {
192
+ if (key === "hydration") return normalizeHydration(value);
193
+ const method = key.slice("hydration.".length);
194
+ if (!methods.includes(method))
195
+ throw new TypeError(`${key} is not a supported hydration method`);
196
+ return normalizeHydration({ ...normalizeHydration(current), [method]: value });
197
+ }
198
+ var methods;
199
+ var init_hydration = __esm({
200
+ "src/options/hydration.ts"() {
201
+ methods = ["publicList", "publicRead", "find", "findOne", "findById"];
202
+ }
203
+ });
204
+
152
205
  // src/helpers/collection.ts
153
206
  var import_sift, import_utils2, filterCollection, findElement, findElementById;
154
207
  var init_collection = __esm({
@@ -278,6 +331,50 @@ var init_concurrency = __esm({
278
331
  }
279
332
  });
280
333
 
334
+ // src/output/permissions-alias.ts
335
+ function attachPermissionsAlias(output, field) {
336
+ if ("permissions" in output) return;
337
+ const metadata = (0, import_utils3.get)(output, field);
338
+ if (metadata === void 0) return;
339
+ Object.defineProperty(output, "permissions", {
340
+ value: metadata,
341
+ enumerable: false,
342
+ writable: true,
343
+ configurable: true
344
+ });
345
+ aliases.set(output, field);
346
+ }
347
+ function removeGeneratedPermissionsAlias(output) {
348
+ const field = aliases.get(output);
349
+ if (field && Object.getOwnPropertyDescriptor(output, "permissions")?.value === (0, import_utils3.get)(output, field)) {
350
+ delete output.permissions;
351
+ }
352
+ aliases.delete(output);
353
+ }
354
+ function copyPermissionsAlias(source, target) {
355
+ if (source && typeof source === "object" && target && typeof target === "object") {
356
+ const field = aliases.get(source);
357
+ if (field && Object.getOwnPropertyDescriptor(source, "permissions")?.value === (0, import_utils3.get)(source, field))
358
+ attachPermissionsAlias(target, field);
359
+ }
360
+ return target;
361
+ }
362
+ function copyPermissionsAliasGraph(source, target, seen = /* @__PURE__ */ new WeakSet()) {
363
+ if (!source || !target || typeof source !== "object" || typeof target !== "object" || seen.has(target)) return;
364
+ seen.add(target);
365
+ copyPermissionsAlias(source, target);
366
+ for (const key of Object.keys(target)) {
367
+ copyPermissionsAliasGraph(source[key], target[key], seen);
368
+ }
369
+ }
370
+ var import_utils3, aliases;
371
+ var init_permissions_alias = __esm({
372
+ "src/output/permissions-alias.ts"() {
373
+ import_utils3 = require("@web-ts-toolkit/utils");
374
+ aliases = /* @__PURE__ */ new WeakMap();
375
+ }
376
+ });
377
+
281
378
  // src/helpers/query.ts
282
379
  function genPagination({
283
380
  skip,
@@ -312,9 +409,9 @@ function parseSelectParam(select) {
312
409
  return fields.length > 0 ? fields : void 0;
313
410
  }
314
411
  function normalizeSelect(select) {
315
- if (Array.isArray(select)) return (0, import_utils3.flattenDeep)(select.map(normalizeSelect));
316
- if ((0, import_utils3.isPlainObject)(select)) {
317
- return (0, import_utils3.reduce)(
412
+ if (Array.isArray(select)) return (0, import_utils4.flattenDeep)(select.map(normalizeSelect));
413
+ if ((0, import_utils4.isPlainObject)(select)) {
414
+ return (0, import_utils4.reduce)(
318
415
  select,
319
416
  (ret, val, key) => {
320
417
  if (val === 1) ret.push(key);
@@ -324,17 +421,17 @@ function normalizeSelect(select) {
324
421
  []
325
422
  );
326
423
  }
327
- if ((0, import_utils3.isString)(select))
424
+ if ((0, import_utils4.isString)(select))
328
425
  return String(select).split(/[\s,]+/).map((v) => v.trim()).filter(Boolean);
329
426
  return [];
330
427
  }
331
- var import_utils3, DEFAULT_LIST_HARD_LIMIT, normalizeSafeInteger;
428
+ var import_utils4, DEFAULT_LIST_HARD_LIMIT, normalizeSafeInteger;
332
429
  var init_query = __esm({
333
430
  "src/helpers/query.ts"() {
334
- import_utils3 = require("@web-ts-toolkit/utils");
431
+ import_utils4 = require("@web-ts-toolkit/utils");
335
432
  DEFAULT_LIST_HARD_LIMIT = 1e3;
336
433
  normalizeSafeInteger = (value, min) => {
337
- if ((0, import_utils3.isNil)(value)) return null;
434
+ if ((0, import_utils4.isNil)(value)) return null;
338
435
  const parsed = Number(value);
339
436
  if (!Number.isSafeInteger(parsed) || parsed < min) return null;
340
437
  return parsed;
@@ -348,57 +445,49 @@ function isDocument(doc) {
348
445
  }
349
446
  function getDocValue(doc, path, defaultValue) {
350
447
  if (isDocument(doc)) {
351
- return (0, import_utils4.get)(doc._doc, path, defaultValue);
352
- } else if ((0, import_utils4.isPlainObject)(doc)) {
353
- return (0, import_utils4.get)(doc, path, defaultValue);
448
+ return (0, import_utils5.get)(doc._doc, path, defaultValue);
449
+ } else if ((0, import_utils5.isPlainObject)(doc)) {
450
+ return (0, import_utils5.get)(doc, path, defaultValue);
354
451
  }
355
452
  }
356
453
  function setDocValue(doc, path, value) {
357
454
  if (isDocument(doc)) {
358
- (0, import_utils4.set)(doc._doc, path, value);
359
- } else if ((0, import_utils4.isPlainObject)(doc)) {
360
- (0, import_utils4.set)(doc, path, value);
455
+ (0, import_utils5.set)(doc._doc, path, value);
456
+ } else if ((0, import_utils5.isPlainObject)(doc)) {
457
+ (0, import_utils5.set)(doc, path, value);
361
458
  }
362
459
  }
363
460
  function getDocPermissions(modelName, doc) {
364
461
  const docPermissionField = getModelOption(modelName, "documentPermissionField");
365
462
  const permissions = getDocValue(doc, docPermissionField, {});
366
- return (0, import_utils4.isPlainObject)(permissions) ? permissions : {};
367
- }
368
- function stripUnexposedDocPermissions(modelName, doc) {
369
- const exposed = getModelOption(modelName, "exposedDocPermissionKeys");
370
- if (exposed === void 0) return;
371
- const docPermissionField = getModelOption(modelName, "documentPermissionField");
372
- const current = getDocValue(doc, docPermissionField, void 0);
373
- if (!(0, import_utils4.isPlainObject)(current)) return;
374
- const keep = /* @__PURE__ */ new Set(["_view", "_edit", ...exposed]);
375
- setDocValue(doc, docPermissionField, Object.fromEntries(Object.entries(current).filter(([key]) => keep.has(key))));
463
+ return (0, import_utils5.isPlainObject)(permissions) ? permissions : {};
376
464
  }
377
465
  function toObject(doc) {
378
466
  return isDocument(doc) ? doc.toObject() : doc;
379
467
  }
380
468
  function pickDocFields(doc, fields = []) {
381
469
  if (isDocument(doc)) {
382
- doc._doc = (0, import_utils4.pick)(doc._doc, fields);
470
+ doc._doc = (0, import_utils5.pick)(doc._doc, fields);
383
471
  return doc;
384
472
  } else {
385
- return (0, import_utils4.pick)(doc, fields);
473
+ return (0, import_utils5.pick)(doc, fields);
386
474
  }
387
475
  }
388
476
  async function populateDoc(doc, target) {
389
477
  let p = doc.populate(target);
390
- if ((0, import_utils5.isPromise)(p)) return p;
478
+ if ((0, import_utils6.isPromise)(p)) return p;
391
479
  return "execPopulate" in p && p.execPopulate?.();
392
480
  }
393
- var import_mongoose, import_utils4, import_utils5, isMongooseDocument, cloneIsolatedLeaf, deepIsolateValue, isolateDocForOutput, retainedAssociations, retainRawAssociation, getRetainedAssociations, normalizeSubPopulate, genSubPopulate;
481
+ var import_mongoose, import_utils5, import_utils6, isMongooseDocument, cloneIsolatedLeaf, deepIsolateValue, isolateDocForOutput, retainedAssociations, retainRawAssociation, getRetainedAssociations, normalizeSubPopulate, genSubPopulate;
394
482
  var init_document = __esm({
395
483
  "src/helpers/document.ts"() {
396
484
  import_mongoose = require("mongoose");
485
+ init_permissions_alias();
397
486
  init_public_admission();
398
- import_utils4 = require("@web-ts-toolkit/utils");
487
+ import_utils5 = require("@web-ts-toolkit/utils");
399
488
  init_options();
400
489
  init_query();
401
- import_utils5 = require("@web-ts-toolkit/utils");
490
+ import_utils6 = require("@web-ts-toolkit/utils");
402
491
  isMongooseDocument = (doc) => isDocument(doc);
403
492
  cloneIsolatedLeaf = (value) => {
404
493
  if (value === null || value === void 0) return value;
@@ -486,7 +575,7 @@ var init_document = __esm({
486
575
  for (const [key, entry] of value) out.set(deepIsolateValue(key, seen), deepIsolateValue(entry, seen));
487
576
  return out;
488
577
  }
489
- if ((0, import_utils4.isPlainObject)(value)) {
578
+ if ((0, import_utils5.isPlainObject)(value)) {
490
579
  if (seen.has(value)) return seen.get(value);
491
580
  const out = {};
492
581
  seen.set(value, out);
@@ -498,6 +587,7 @@ var init_document = __esm({
498
587
  configurable: true
499
588
  });
500
589
  }
590
+ copyPermissionsAlias(value, out);
501
591
  return out;
502
592
  }
503
593
  return value;
@@ -532,13 +622,13 @@ var init_document = __esm({
532
622
  const entry = retainedAssociations.get(output);
533
623
  return entry ? { ...entry } : void 0;
534
624
  };
535
- normalizeSubPopulate = (populate) => (0, import_utils5.isArray)(populate) ? populate.map((item) => (0, import_utils5.isString)(item) ? { path: item } : item) : (0, import_utils5.isString)(populate) ? { path: populate } : populate ?? [];
625
+ normalizeSubPopulate = (populate) => (0, import_utils6.isArray)(populate) ? populate.map((item) => (0, import_utils6.isString)(item) ? { path: item } : item) : (0, import_utils6.isString)(populate) ? { path: populate } : populate ?? [];
536
626
  genSubPopulate = (sub, popul) => {
537
627
  assertPublicAdmission(popul, "populate");
538
628
  if (!popul) return [];
539
- let populate = (0, import_utils5.isArray)(popul) ? popul : [popul];
629
+ let populate = (0, import_utils6.isArray)(popul) ? popul : [popul];
540
630
  populate = populate.map((p) => {
541
- const ret = (0, import_utils5.isString)(p) ? { path: `${sub}.${p}` } : {
631
+ const ret = (0, import_utils6.isString)(p) ? { path: `${sub}.${p}` } : {
542
632
  path: `${sub}.${p.path}`,
543
633
  select: normalizeSelect(p.select)
544
634
  };
@@ -718,14 +808,14 @@ var init_sort_policy = __esm({
718
808
  });
719
809
 
720
810
  // src/lib.ts
721
- var import_mongoose2, import_utils6, isSchema, isObjectIdType, isReference, isDocument2;
811
+ var import_mongoose2, import_utils7, isSchema, isObjectIdType, isReference, isDocument2;
722
812
  var init_lib = __esm({
723
813
  "src/lib.ts"() {
724
814
  import_mongoose2 = require("mongoose");
725
- import_utils6 = require("@web-ts-toolkit/utils");
815
+ import_utils7 = require("@web-ts-toolkit/utils");
726
816
  isSchema = (val) => val instanceof import_mongoose2.Schema;
727
817
  isObjectIdType = (val) => val === "ObjectId" || val === import_mongoose2.Schema.Types.ObjectId;
728
- isReference = (val) => (0, import_utils6.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
818
+ isReference = (val) => (0, import_utils7.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
729
819
  isDocument2 = function isDocument3(doc) {
730
820
  return doc instanceof import_mongoose2.Document;
731
821
  };
@@ -737,30 +827,30 @@ function recurseObject(obj) {
737
827
  if (isSchema(obj)) {
738
828
  return buildRefs(obj.tree);
739
829
  }
740
- if (!(0, import_utils7.isObject)(obj)) return null;
830
+ if (!(0, import_utils8.isObject)(obj)) return null;
741
831
  if (isReference(obj)) {
742
832
  return obj.ref;
743
833
  }
744
834
  let ret = null;
745
- (0, import_utils7.forEach)(obj, (val) => {
835
+ (0, import_utils8.forEach)(obj, (val) => {
746
836
  ret = recurseObject(val);
747
- if (!(0, import_utils7.isEmpty)(ret)) {
837
+ if (!(0, import_utils8.isEmpty)(ret)) {
748
838
  return false;
749
839
  }
750
840
  });
751
841
  return ret;
752
842
  }
753
843
  function buildRefs(schema) {
754
- if (!(0, import_utils7.isObject)(schema)) return {};
844
+ if (!(0, import_utils8.isObject)(schema)) return {};
755
845
  const references = {};
756
- (0, import_utils7.forEach)(schema, (val, key) => {
846
+ (0, import_utils8.forEach)(schema, (val, key) => {
757
847
  const paths = recurseObject(val);
758
- if (!(0, import_utils7.isEmpty)(paths)) {
848
+ if (!(0, import_utils8.isEmpty)(paths)) {
759
849
  references[key] = paths;
760
850
  }
761
- const target = (0, import_utils7.isObject)(val) && "type" in val ? val.type ?? val : val;
762
- if ((0, import_utils7.isArray)(target) && target.length > 0) {
763
- if (isSchema(target[0]) || (0, import_utils7.isPlainObject)(target[0])) {
851
+ const target = (0, import_utils8.isObject)(val) && "type" in val ? val.type ?? val : val;
852
+ if ((0, import_utils8.isArray)(target) && target.length > 0) {
853
+ if (isSchema(target[0]) || (0, import_utils8.isPlainObject)(target[0])) {
764
854
  return;
765
855
  }
766
856
  }
@@ -768,12 +858,12 @@ function buildRefs(schema) {
768
858
  return references;
769
859
  }
770
860
  function buildSubPaths(schema) {
771
- if (!(0, import_utils7.isObject)(schema)) return [];
861
+ if (!(0, import_utils8.isObject)(schema)) return [];
772
862
  const subPaths = [];
773
- (0, import_utils7.forEach)(schema, (val, key) => {
774
- const target = (0, import_utils7.isObject)(val) && "type" in val ? val.type ?? val : val;
775
- if ((0, import_utils7.isArray)(target) && target.length > 0) {
776
- if (isSchema(target[0]) || (0, import_utils7.isPlainObject)(target[0]) && !isReference(target[0])) {
863
+ (0, import_utils8.forEach)(schema, (val, key) => {
864
+ const target = (0, import_utils8.isObject)(val) && "type" in val ? val.type ?? val : val;
865
+ if ((0, import_utils8.isArray)(target) && target.length > 0) {
866
+ if (isSchema(target[0]) || (0, import_utils8.isPlainObject)(target[0]) && !isReference(target[0])) {
777
867
  subPaths.push(key);
778
868
  }
779
869
  }
@@ -781,12 +871,12 @@ function buildSubPaths(schema) {
781
871
  return subPaths;
782
872
  }
783
873
  async function iterateQuery(query, handler, scheduler, scheduled = false) {
784
- if (!(0, import_utils7.isPlainObject)(query)) return query;
874
+ if (!(0, import_utils8.isPlainObject)(query)) return query;
785
875
  if (!handler) return query;
786
876
  const queryObject = query;
787
877
  const entries = Object.entries(queryObject);
788
878
  const mapEntry = async ([key, val]) => {
789
- if ((0, import_utils7.isPlainObject)(val)) {
879
+ if ((0, import_utils8.isPlainObject)(val)) {
790
880
  const plainValue = val;
791
881
  if (plainValue.$$sq) {
792
882
  return scheduled || !scheduler ? handler(0 /* SubQuery */, plainValue.$$sq, key) : scheduler.run(() => Promise.resolve(handler(0 /* SubQuery */, plainValue.$$sq, key)));
@@ -796,7 +886,7 @@ async function iterateQuery(query, handler, scheduler, scheduled = false) {
796
886
  return iterateQuery(val, handler, scheduler, scheduled);
797
887
  }
798
888
  }
799
- if ((0, import_utils7.isArray)(val)) {
889
+ if ((0, import_utils8.isArray)(val)) {
800
890
  const items = val;
801
891
  if (scheduler && !scheduled) {
802
892
  return scheduler.map(items, (v) => iterateQuery(v, handler, scheduler, true));
@@ -808,7 +898,7 @@ async function iterateQuery(query, handler, scheduler, scheduled = false) {
808
898
  const values = scheduler && !scheduled ? await scheduler.map(entries, mapEntry) : await Promise.all(entries.map(mapEntry));
809
899
  return Object.fromEntries(entries.map(([key], index) => [key, values[index]]));
810
900
  }
811
- var import_utils7, createValidator;
901
+ var import_utils8, createValidator;
812
902
  var init_helpers = __esm({
813
903
  "src/helpers/index.ts"() {
814
904
  init_collection();
@@ -817,13 +907,13 @@ var init_helpers = __esm({
817
907
  init_errors();
818
908
  init_query();
819
909
  init_sort_policy();
820
- import_utils7 = require("@web-ts-toolkit/utils");
910
+ import_utils8 = require("@web-ts-toolkit/utils");
821
911
  init_lib();
822
912
  createValidator = (fn) => {
823
913
  const stringHandler = (key) => key.trim().split(" ").every((v) => fn(v));
824
914
  const arrayHandler = (arr) => arr.some((item) => {
825
- if ((0, import_utils7.isString)(item)) return stringHandler(item);
826
- else if ((0, import_utils7.isArray)(item)) return arrayHandler(item);
915
+ if ((0, import_utils8.isString)(item)) return stringHandler(item);
916
+ else if ((0, import_utils8.isArray)(item)) return arrayHandler(item);
827
917
  else return false;
828
918
  });
829
919
  return { stringHandler, arrayHandler };
@@ -918,25 +1008,25 @@ function defineOpenApiSchemaResolver(resolve) {
918
1008
  };
919
1009
  }
920
1010
  function getNestedOpenApiSchemaDataSource(source) {
921
- return (0, import_utils8.isPlainObject)(source) && "data" in source ? source.data : void 0;
1011
+ return (0, import_utils9.isPlainObject)(source) && "data" in source ? source.data : void 0;
922
1012
  }
923
1013
  function unwrapNestedOpenApiSchemaSource(source, fallback) {
924
- if ((0, import_utils8.isPlainObject)(source) && ("default" in source || "data" in source)) {
1014
+ if ((0, import_utils9.isPlainObject)(source) && ("default" in source || "data" in source)) {
925
1015
  return source.default ?? fallback;
926
1016
  }
927
1017
  return source ?? fallback;
928
1018
  }
929
1019
  function isOpenApiSchemaPatch(source) {
930
- return (0, import_utils8.isPlainObject)(source) && source.kind === "objectProperties";
1020
+ return (0, import_utils9.isPlainObject)(source) && source.kind === "objectProperties";
931
1021
  }
932
1022
  function isOpenApiSchemaResolver(source) {
933
- return (0, import_utils8.isPlainObject)(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
1023
+ return (0, import_utils9.isPlainObject)(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
934
1024
  }
935
1025
  function isJsonSchemaLike(source) {
936
- return (0, import_utils8.isPlainObject)(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
1026
+ return (0, import_utils9.isPlainObject)(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
937
1027
  }
938
1028
  function hasOpenApiSchema(source) {
939
- return (0, import_utils8.isPlainObject)(source) && isJsonSchemaLike(source.openapi);
1029
+ return (0, import_utils9.isPlainObject)(source) && isJsonSchemaLike(source.openapi);
940
1030
  }
941
1031
  function toOpenApiSchema(source) {
942
1032
  if (!source) return void 0;
@@ -944,7 +1034,7 @@ function toOpenApiSchema(source) {
944
1034
  if (!resolvedSource) return void 0;
945
1035
  if (isOpenApiSchemaPatch(resolvedSource)) {
946
1036
  const schema = toOpenApiSchema(resolvedSource.source) ?? { ...fallbackObjectSchema };
947
- const properties = (0, import_utils8.isPlainObject)(schema.properties) ? { ...schema.properties } : {};
1037
+ const properties = (0, import_utils9.isPlainObject)(schema.properties) ? { ...schema.properties } : {};
948
1038
  for (const [key, value] of Object.entries(resolvedSource.properties)) {
949
1039
  properties[key] = toOpenApiSchema(value) ?? fallbackObjectSchema;
950
1040
  }
@@ -966,11 +1056,11 @@ function toOpenApiSchema(source) {
966
1056
  return fallbackObjectSchema;
967
1057
  }
968
1058
  }
969
- var import_zod, import_utils8, fallbackObjectSchema;
1059
+ var import_zod, import_utils9, fallbackObjectSchema;
970
1060
  var init_schemas = __esm({
971
1061
  "src/openapi/schemas.ts"() {
972
1062
  import_zod = require("zod");
973
- import_utils8 = require("@web-ts-toolkit/utils");
1063
+ import_utils9 = require("@web-ts-toolkit/utils");
974
1064
  fallbackObjectSchema = { type: "object", additionalProperties: true };
975
1065
  }
976
1066
  });
@@ -993,10 +1083,10 @@ function buildOpenApiSpec(routes, options) {
993
1083
  paths
994
1084
  };
995
1085
  }
996
- var import_utils9, openApiMediaType, normalizePath, toOpenApiPath, schemaToQueryParameters, schemaToPathParameters, getDefaultResponses, buildOperation;
1086
+ var import_utils10, openApiMediaType, normalizePath, toOpenApiPath, schemaToQueryParameters, schemaToPathParameters, getDefaultResponses, buildOperation;
997
1087
  var init_build_spec = __esm({
998
1088
  "src/openapi/build-spec.ts"() {
999
- import_utils9 = require("@web-ts-toolkit/utils");
1089
+ import_utils10 = require("@web-ts-toolkit/utils");
1000
1090
  init_responses();
1001
1091
  init_schemas();
1002
1092
  openApiMediaType = "application/json";
@@ -1008,9 +1098,9 @@ var init_build_spec = __esm({
1008
1098
  schemaToQueryParameters = (schema) => {
1009
1099
  const jsonSchema = toOpenApiSchema(schema);
1010
1100
  if (!jsonSchema || jsonSchema.type !== "object") return [];
1011
- const properties = (0, import_utils9.isPlainObject)(jsonSchema.properties) ? jsonSchema.properties : {};
1101
+ const properties = (0, import_utils10.isPlainObject)(jsonSchema.properties) ? jsonSchema.properties : {};
1012
1102
  const required = new Set(
1013
- (0, import_utils9.isArray)(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
1103
+ (0, import_utils10.isArray)(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
1014
1104
  );
1015
1105
  return Object.entries(properties).map(([name, value]) => ({
1016
1106
  name,
@@ -1227,10 +1317,10 @@ var init_logger_default = __esm({
1227
1317
  });
1228
1318
 
1229
1319
  // src/options/manager.ts
1230
- var import_utils10, toPath, cloneConfigValue, cloneForRead, freezeConfigValue, cloneAndFreezeForStore, getNestedOption, resolveNestedOption, OptionsManager;
1320
+ var import_utils11, toPath, cloneConfigValue, cloneForRead, freezeConfigValue, cloneAndFreezeForStore, getNestedOption, resolveNestedOption, OptionsManager;
1231
1321
  var init_manager = __esm({
1232
1322
  "src/options/manager.ts"() {
1233
- import_utils10 = require("@web-ts-toolkit/utils");
1323
+ import_utils11 = require("@web-ts-toolkit/utils");
1234
1324
  toPath = (key) => {
1235
1325
  if (Array.isArray(key)) return key;
1236
1326
  return typeof key === "string" ? key.split(".") : [key];
@@ -1337,20 +1427,20 @@ var init_manager = __esm({
1337
1427
  return this;
1338
1428
  }
1339
1429
  get(key, defaultValue) {
1340
- return (0, import_utils10.get)(this.currentOptions, key, defaultValue);
1430
+ return (0, import_utils11.get)(this.currentOptions, key, defaultValue);
1341
1431
  }
1342
1432
  set(key, value) {
1343
1433
  const path = toPath(key);
1344
1434
  if (path.length <= 1) {
1345
- (0, import_utils10.set)(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneAndFreezeForStore(value));
1435
+ (0, import_utils11.set)(this.currentOptions, path, this.preserveKeys.has(String(path[0])) ? value : cloneAndFreezeForStore(value));
1346
1436
  return;
1347
1437
  }
1348
1438
  const [rootKey, ...nestedPath] = path;
1349
- const currentRoot = (0, import_utils10.get)(this.currentOptions, [rootKey], void 0);
1350
- const baseRoot = (0, import_utils10.isPlainObject)(currentRoot) ? currentRoot : {};
1439
+ const currentRoot = (0, import_utils11.get)(this.currentOptions, [rootKey], void 0);
1440
+ const baseRoot = (0, import_utils11.isPlainObject)(currentRoot) ? currentRoot : {};
1351
1441
  const nextRoot = cloneConfigValue(baseRoot);
1352
- (0, import_utils10.set)(nextRoot, nestedPath, cloneForRead(value));
1353
- (0, import_utils10.set)(this.currentOptions, [rootKey], freezeConfigValue(nextRoot));
1442
+ (0, import_utils11.set)(nextRoot, nestedPath, cloneForRead(value));
1443
+ (0, import_utils11.set)(this.currentOptions, [rootKey], freezeConfigValue(nextRoot));
1354
1444
  }
1355
1445
  fetch() {
1356
1446
  const cloned = cloneForRead(this.currentOptions);
@@ -1368,10 +1458,10 @@ var init_manager = __esm({
1368
1458
  cloned[key] = options[key];
1369
1459
  }
1370
1460
  }
1371
- (0, import_utils10.assign)(this.currentOptions, freezeConfigValue(cloned));
1461
+ (0, import_utils11.assign)(this.currentOptions, freezeConfigValue(cloned));
1372
1462
  }
1373
1463
  onchange(key, func) {
1374
- (0, import_utils10.set)(this.listeners, key, func);
1464
+ (0, import_utils11.set)(this.listeners, key, func);
1375
1465
  return this;
1376
1466
  }
1377
1467
  snapshot() {
@@ -1397,7 +1487,7 @@ var init_manager = __esm({
1397
1487
  cloned[key] = snap[key];
1398
1488
  }
1399
1489
  }
1400
- (0, import_utils10.assign)(current, freezeConfigValue(cloned));
1490
+ (0, import_utils11.assign)(current, freezeConfigValue(cloned));
1401
1491
  }
1402
1492
  };
1403
1493
  }
@@ -1597,10 +1687,10 @@ var init_data_values = __esm({
1597
1687
  });
1598
1688
 
1599
1689
  // src/options/data-manager.ts
1600
- var import_utils11, admitData, DataOptionsManager;
1690
+ var import_utils12, admitData, DataOptionsManager;
1601
1691
  var init_data_manager = __esm({
1602
1692
  "src/options/data-manager.ts"() {
1603
- import_utils11 = require("@web-ts-toolkit/utils");
1693
+ import_utils12 = require("@web-ts-toolkit/utils");
1604
1694
  init_manager();
1605
1695
  init_data_values();
1606
1696
  admitData = (options) => {
@@ -1618,7 +1708,7 @@ var init_data_manager = __esm({
1618
1708
  super.set("data", createDataSnapshot(value));
1619
1709
  } else if (path.startsWith("data.")) {
1620
1710
  const next = copyDataValue(getOwnedDataSnapshot(super.get("data")));
1621
- (0, import_utils11.set)(next, path.slice("data.".length), value);
1711
+ (0, import_utils12.set)(next, path.slice("data.".length), value);
1622
1712
  super.set("data", createDataSnapshot(next));
1623
1713
  } else {
1624
1714
  super.set(key, value);
@@ -1656,7 +1746,7 @@ function validateRequestComplexity(value, options, scope2 = "request") {
1656
1746
  pushError(`Request exceeds maximum depth of ${limits.maxDepth}`, path);
1657
1747
  return;
1658
1748
  }
1659
- if ((0, import_utils12.isArray)(current)) {
1749
+ if ((0, import_utils13.isArray)(current)) {
1660
1750
  if (parentKey === "$and" || parentKey === "$or" || parentKey === "$nor") {
1661
1751
  logicalClauses += current.length;
1662
1752
  if (logicalClauses > limits.maxLogicalClauses) {
@@ -1676,14 +1766,14 @@ function validateRequestComplexity(value, options, scope2 = "request") {
1676
1766
  }
1677
1767
  return;
1678
1768
  }
1679
- if (!(0, import_utils12.isPlainObject)(current)) return;
1769
+ if (!(0, import_utils13.isPlainObject)(current)) return;
1680
1770
  for (const [key, child] of Object.entries(current)) {
1681
1771
  if (key === "__proto__" || key === "prototype" || key === "constructor") {
1682
1772
  pushError(`Unsupported key: ${key}`, path.concat(key));
1683
1773
  return;
1684
1774
  }
1685
1775
  if (scope2 === "request" && key === "include") {
1686
- includeCount += (0, import_utils12.isArray)(child) ? child.length : 1;
1776
+ includeCount += (0, import_utils13.isArray)(child) ? child.length : 1;
1687
1777
  if (includeCount > limits.maxIncludeCount) {
1688
1778
  pushError(`Request exceeds maximum include count of ${limits.maxIncludeCount}`, path.concat(key));
1689
1779
  return;
@@ -1706,10 +1796,10 @@ function validateRequestComplexity(value, options, scope2 = "request") {
1706
1796
  visit(value, [], 0);
1707
1797
  return errors;
1708
1798
  }
1709
- var import_utils12, defaultRequestComplexity, normalizePositiveInteger, resolveRequestComplexity;
1799
+ var import_utils13, defaultRequestComplexity, normalizePositiveInteger, resolveRequestComplexity;
1710
1800
  var init_request_complexity = __esm({
1711
1801
  "src/request-complexity.ts"() {
1712
- import_utils12 = require("@web-ts-toolkit/utils");
1802
+ import_utils13 = require("@web-ts-toolkit/utils");
1713
1803
  defaultRequestComplexity = {
1714
1804
  maxDepth: 8,
1715
1805
  maxNodes: 500,
@@ -1755,13 +1845,14 @@ var init_request_complexity = __esm({
1755
1845
  });
1756
1846
 
1757
1847
  // src/runtime.ts
1758
- var import_mongoose3, import_mongoose_schema_jsonschema, import_utils13, mongooseJsonSchemaInitialized, ensureMongooseJsonSchemaInitialized, pluralize, FIELD_ACCESS_KEYS, defaultModelOptions, defaultDataOptions, normalizeBasePath, hasModelPermission, classifyPermissionSchema, refreshPermissionMetadata, VIRTUAL_SUPPORTED_ACCESSES, VIRTUAL_UNSUPPORTED_ACCESSES, VIRTUAL_RESERVED_NAMES, VIRTUAL_DANGEROUS_SEGMENTS, VIRTUAL_NAME_PATTERN, isVirtualContainerValue, virtualFullPath, virtualPathsOverlap, collectStoredTopLevel, getChildSchemaForField, getNestedChildFields, cloneVirtualsForValidation, validateVirtualDependsOn, validateVirtualLeafValue, validateVirtualsScope, validateVirtualsTree, getScopeVirtualsObject, toVirtualDescriptor, AccessRuntime, defaultRuntime;
1848
+ var import_mongoose3, import_mongoose_schema_jsonschema, import_utils14, mongooseJsonSchemaInitialized, ensureMongooseJsonSchemaInitialized, pluralize, FIELD_ACCESS_KEYS, defaultModelOptions, defaultDataOptions, normalizeBasePath, hasModelPermission, classifyPermissionSchema, refreshPermissionMetadata, VIRTUAL_SUPPORTED_ACCESSES, VIRTUAL_UNSUPPORTED_ACCESSES, VIRTUAL_RESERVED_NAMES, VIRTUAL_DANGEROUS_SEGMENTS, VIRTUAL_NAME_PATTERN, isVirtualContainerValue, virtualFullPath, virtualPathsOverlap, collectStoredTopLevel, getChildSchemaForField, getNestedChildFields, cloneVirtualsForValidation, validateVirtualDependsOn, validateVirtualLeafValue, validateVirtualsScope, validateVirtualsTree, getScopeVirtualsObject, toVirtualDescriptor, AccessRuntime, defaultRuntime;
1759
1849
  var init_runtime = __esm({
1760
1850
  "src/runtime.ts"() {
1761
1851
  import_mongoose3 = __toESM(require("mongoose"));
1762
1852
  init_public_admission();
1853
+ init_hydration();
1763
1854
  import_mongoose_schema_jsonschema = __toESM(require("mongoose-schema-jsonschema"));
1764
- import_utils13 = require("@web-ts-toolkit/utils");
1855
+ import_utils14 = require("@web-ts-toolkit/utils");
1765
1856
  init_helpers();
1766
1857
  init_registry();
1767
1858
  init_logger_default();
@@ -1788,44 +1879,44 @@ var init_runtime = __esm({
1788
1879
  listHardLimit: DEFAULT_LIST_HARD_LIMIT
1789
1880
  };
1790
1881
  normalizeBasePath = (name, value) => {
1791
- if ((0, import_utils13.isNil)(value)) {
1882
+ if ((0, import_utils14.isNil)(value)) {
1792
1883
  return `/${pluralize(name)}`;
1793
1884
  }
1794
- return (0, import_utils13.isString)(value) ? (0, import_utils13.addLeadingSlash)(value) : "";
1885
+ return (0, import_utils14.isString)(value) ? (0, import_utils14.addLeadingSlash)(value) : "";
1795
1886
  };
1796
1887
  hasModelPermission = (value, modelPermissionPrefix) => {
1797
1888
  if (!modelPermissionPrefix) {
1798
1889
  return true;
1799
1890
  }
1800
- if ((0, import_utils13.isString)(value)) {
1891
+ if ((0, import_utils14.isString)(value)) {
1801
1892
  return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
1802
1893
  }
1803
- if ((0, import_utils13.isArray)(value)) {
1894
+ if ((0, import_utils14.isArray)(value)) {
1804
1895
  return value.some((item) => {
1805
- if ((0, import_utils13.isString)(item) || (0, import_utils13.isArray)(item)) {
1896
+ if ((0, import_utils14.isString)(item) || (0, import_utils14.isArray)(item)) {
1806
1897
  return hasModelPermission(item, modelPermissionPrefix);
1807
1898
  }
1808
1899
  return true;
1809
1900
  });
1810
1901
  }
1811
- return (0, import_utils13.isFunction)(value);
1902
+ return (0, import_utils14.isFunction)(value);
1812
1903
  };
1813
1904
  classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
1814
1905
  const schemaKeys = Object.keys(permissionSchema);
1815
1906
  const globalPermissionKeys = {};
1816
1907
  const modelPermissionKeys = {};
1817
- (0, import_utils13.forEach)(schemaKeys, (schemaKey) => {
1908
+ (0, import_utils14.forEach)(schemaKeys, (schemaKey) => {
1818
1909
  const schemaRule = permissionSchema[schemaKey];
1819
- const ruleEntries = (0, import_utils13.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
1910
+ const ruleEntries = (0, import_utils14.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
1820
1911
  for (let x = 0; x < ruleEntries.length; x++) {
1821
1912
  const [accessKey, value] = ruleEntries[x];
1822
- if (!(0, import_utils13.isArray)(globalPermissionKeys[accessKey])) {
1913
+ if (!(0, import_utils14.isArray)(globalPermissionKeys[accessKey])) {
1823
1914
  globalPermissionKeys[accessKey] = [];
1824
1915
  }
1825
- if (!(0, import_utils13.isArray)(modelPermissionKeys[accessKey])) {
1916
+ if (!(0, import_utils14.isArray)(modelPermissionKeys[accessKey])) {
1826
1917
  modelPermissionKeys[accessKey] = [];
1827
1918
  }
1828
- if ((0, import_utils13.isBoolean)(value)) {
1919
+ if ((0, import_utils14.isBoolean)(value)) {
1829
1920
  globalPermissionKeys[accessKey].push(schemaKey);
1830
1921
  continue;
1831
1922
  }
@@ -1857,13 +1948,13 @@ var init_runtime = __esm({
1857
1948
  VIRTUAL_RESERVED_NAMES = /* @__PURE__ */ new Set(["_id", "__v", "id"]);
1858
1949
  VIRTUAL_DANGEROUS_SEGMENTS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
1859
1950
  VIRTUAL_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
1860
- isVirtualContainerValue = (value) => (0, import_utils13.isPlainObject)(value) && "sub" in value;
1951
+ isVirtualContainerValue = (value) => (0, import_utils14.isPlainObject)(value) && "sub" in value;
1861
1952
  virtualFullPath = (prefix, name) => prefix ? `${prefix}.${name}` : name;
1862
1953
  virtualPathsOverlap = (virtualPath, permissionField) => {
1863
1954
  if (!virtualPath || !permissionField) return false;
1864
1955
  try {
1865
- if ((0, import_utils13.get)((0, import_utils13.set)({}, virtualPath, true), permissionField) !== void 0) return true;
1866
- if ((0, import_utils13.get)((0, import_utils13.set)({}, permissionField, true), virtualPath) !== void 0) return true;
1956
+ if ((0, import_utils14.get)((0, import_utils14.set)({}, virtualPath, true), permissionField) !== void 0) return true;
1957
+ if ((0, import_utils14.get)((0, import_utils14.set)({}, permissionField, true), virtualPath) !== void 0) return true;
1867
1958
  } catch {
1868
1959
  return false;
1869
1960
  }
@@ -1924,12 +2015,12 @@ var init_runtime = __esm({
1924
2015
  };
1925
2016
  validateVirtualDependsOn = (dependsOn, entryLabel, storedFields, siblingVirtualNames) => {
1926
2017
  if (dependsOn === void 0) return [];
1927
- if (!(0, import_utils13.isArray)(dependsOn)) {
2018
+ if (!(0, import_utils14.isArray)(dependsOn)) {
1928
2019
  throw new Error(`Virtual ${entryLabel}: dependsOn must be an array of top-level persisted field names`);
1929
2020
  }
1930
2021
  const list = dependsOn;
1931
2022
  for (const dep of list) {
1932
- if (!(0, import_utils13.isString)(dep) || dep.length === 0) {
2023
+ if (!(0, import_utils14.isString)(dep) || dep.length === 0) {
1933
2024
  throw new Error(`Virtual ${entryLabel}: dependsOn entries must be non-empty strings`);
1934
2025
  }
1935
2026
  if (dep.includes(".")) {
@@ -1951,12 +2042,12 @@ var init_runtime = __esm({
1951
2042
  return list;
1952
2043
  };
1953
2044
  validateVirtualLeafValue = (value, entryLabel, storedFields, siblingVirtualNames, sharedDependsOn) => {
1954
- if ((0, import_utils13.isFunction)(value)) return;
1955
- if (!(0, import_utils13.isPlainObject)(value)) {
2045
+ if ((0, import_utils14.isFunction)(value)) return;
2046
+ if (!(0, import_utils14.isPlainObject)(value)) {
1956
2047
  throw new Error(`Virtual ${entryLabel}: descriptor must be a getter function or { get, dependsOn }`);
1957
2048
  }
1958
2049
  const record2 = value;
1959
- if (!(0, import_utils13.isFunction)(record2.get)) {
2050
+ if (!(0, import_utils14.isFunction)(record2.get)) {
1960
2051
  throw new Error(`Virtual ${entryLabel}: descriptor.get must be a callable getter function`);
1961
2052
  }
1962
2053
  validateVirtualDependsOn(record2.dependsOn ?? sharedDependsOn, entryLabel, storedFields, siblingVirtualNames);
@@ -1996,7 +2087,7 @@ var init_runtime = __esm({
1996
2087
  `Virtual ${scopeLabel}${name}: scope-container must only hold "sub" (embedded container "${name}" is not a virtual-leaf collision)`
1997
2088
  );
1998
2089
  }
1999
- if (!(0, import_utils13.isPlainObject)(record3.sub)) {
2090
+ if (!(0, import_utils14.isPlainObject)(record3.sub)) {
2000
2091
  throw new Error(`Virtual ${scopeLabel}${name}: scope-container "sub" must be a plain object`);
2001
2092
  }
2002
2093
  continue;
@@ -2006,8 +2097,8 @@ var init_runtime = __esm({
2006
2097
  `Virtual ${scopeLabel}${name}: collides with a stored path (inspected actual Mongoose schema/child scope; getModelAtt alone is insufficient)`
2007
2098
  );
2008
2099
  }
2009
- if ((0, import_utils13.isFunction)(raw)) continue;
2010
- if (!(0, import_utils13.isPlainObject)(raw)) {
2100
+ if ((0, import_utils14.isFunction)(raw)) continue;
2101
+ if (!(0, import_utils14.isPlainObject)(raw)) {
2011
2102
  throw new Error(
2012
2103
  `Virtual ${scopeLabel}${name}: malformed descriptor (expected getter, { get, dependsOn }, or per-access record)`
2013
2104
  );
@@ -2061,7 +2152,7 @@ var init_runtime = __esm({
2061
2152
  };
2062
2153
  validateVirtualsTree = (model, virtuals, documentPermissionField, modelName) => {
2063
2154
  if (virtuals === void 0 || virtuals === null) return;
2064
- if (!(0, import_utils13.isPlainObject)(virtuals)) {
2155
+ if (!(0, import_utils14.isPlainObject)(virtuals)) {
2065
2156
  throw new Error(`Virtuals for model "${modelName}": virtuals must be a plain object mapping names to descriptors`);
2066
2157
  }
2067
2158
  const rootSchema = model?.schema ?? null;
@@ -2108,27 +2199,27 @@ var init_runtime = __esm({
2108
2199
  visitContainers(rootVirtuals, rootSchema, "");
2109
2200
  };
2110
2201
  getScopeVirtualsObject = (rootVirtuals, scopePath) => {
2111
- if (!rootVirtuals || !(0, import_utils13.isPlainObject)(rootVirtuals)) return null;
2202
+ if (!rootVirtuals || !(0, import_utils14.isPlainObject)(rootVirtuals)) return null;
2112
2203
  if (!scopePath || scopePath.length === 0) return rootVirtuals;
2113
2204
  let current = rootVirtuals;
2114
2205
  for (let i = 0; i < scopePath.length; i += 2) {
2115
2206
  const field = scopePath[i];
2116
2207
  const subMarker = scopePath[i + 1];
2117
2208
  if (!field || subMarker !== "sub") return null;
2118
- if (!(0, import_utils13.isPlainObject)(current)) return null;
2209
+ if (!(0, import_utils14.isPlainObject)(current)) return null;
2119
2210
  const container = current[field];
2120
2211
  if (!isVirtualContainerValue(container)) return null;
2121
2212
  current = container.sub;
2122
- if (!(0, import_utils13.isPlainObject)(current)) return null;
2213
+ if (!(0, import_utils14.isPlainObject)(current)) return null;
2123
2214
  }
2124
2215
  return current;
2125
2216
  };
2126
2217
  toVirtualDescriptor = (leaf, sharedDependsOn) => {
2127
- if ((0, import_utils13.isFunction)(leaf))
2218
+ if ((0, import_utils14.isFunction)(leaf))
2128
2219
  return { get: leaf, dependsOn: sharedDependsOn ?? [] };
2129
- if (!(0, import_utils13.isPlainObject)(leaf)) return null;
2220
+ if (!(0, import_utils14.isPlainObject)(leaf)) return null;
2130
2221
  const record2 = leaf;
2131
- if (!(0, import_utils13.isFunction)(record2.get)) return null;
2222
+ if (!(0, import_utils14.isFunction)(record2.get)) return null;
2132
2223
  const dependsOn = record2.dependsOn ?? sharedDependsOn ?? [];
2133
2224
  return { get: record2.get, dependsOn };
2134
2225
  };
@@ -2193,7 +2284,7 @@ var init_runtime = __esm({
2193
2284
  }
2194
2285
  registerOpenApiRoute(route) {
2195
2286
  this.openApiRegistry.register(
2196
- this.openApiPathPrefix ? { ...route, path: (0, import_utils13.normalizeUrlPath)(`${this.openApiPathPrefix}/${route.path}`) } : route
2287
+ this.openApiPathPrefix ? { ...route, path: (0, import_utils14.normalizeUrlPath)(`${this.openApiPathPrefix}/${route.path}`) } : route
2197
2288
  );
2198
2289
  }
2199
2290
  /**
@@ -2204,7 +2295,7 @@ var init_runtime = __esm({
2204
2295
  */
2205
2296
  withOpenApiPathPrefix(prefix, build) {
2206
2297
  const previous = this.openApiPathPrefix;
2207
- this.openApiPathPrefix = (0, import_utils13.normalizeUrlPath)(`${previous}/${prefix}`);
2298
+ this.openApiPathPrefix = (0, import_utils14.normalizeUrlPath)(`${previous}/${prefix}`);
2208
2299
  try {
2209
2300
  return build();
2210
2301
  } finally {
@@ -2324,9 +2415,25 @@ var init_runtime = __esm({
2324
2415
  }
2325
2416
  /** Update model starting defaults shallowly; already-stored model values are not broadcast-replaced. */
2326
2417
  setDefaultModelOptions(options) {
2418
+ assertPublicDefaults(options.defaults);
2419
+ if ("hydration" in options) options = { ...options, hydration: normalizeHydration(options.hydration) };
2327
2420
  this.defaultModelOptions.assign(options);
2328
2421
  }
2329
2422
  setDefaultModelOption(key, value) {
2423
+ const keyStr = String(key);
2424
+ if (keyStr === "hydration" || keyStr.startsWith("hydration.")) {
2425
+ this.defaultModelOptions.set(
2426
+ "hydration",
2427
+ normalizeHydrationUpdate(this.getDefaultModelOptions().hydration, keyStr, value)
2428
+ );
2429
+ return;
2430
+ }
2431
+ if (keyStr === "defaults") assertPublicDefaults(value);
2432
+ else if (keyStr.startsWith("defaults.")) {
2433
+ const proposed = {};
2434
+ (0, import_utils14.set)(proposed, keyStr.slice("defaults.".length), value);
2435
+ assertPublicDefaults(proposed);
2436
+ }
2330
2437
  this.defaultModelOptions.set(key, value);
2331
2438
  }
2332
2439
  getDefaultModelOptions() {
@@ -2353,7 +2460,7 @@ var init_runtime = __esm({
2353
2460
  }).onchange("basePath", function(newval, key, target) {
2354
2461
  target[key] = normalizeBasePath(
2355
2462
  modelName,
2356
- (0, import_utils13.isString)(newval) || (0, import_utils13.isNil)(newval) ? newval : void 0
2463
+ (0, import_utils14.isString)(newval) || (0, import_utils14.isNil)(newval) ? newval : void 0
2357
2464
  );
2358
2465
  }).build();
2359
2466
  this.modelJsonSchemas[modelName] = model.jsonSchema();
@@ -2376,6 +2483,7 @@ var init_runtime = __esm({
2376
2483
  */
2377
2484
  setModelOptions(modelName, options) {
2378
2485
  assertPublicDefaults(options.defaults);
2486
+ if ("hydration" in options) options = { ...options, hydration: normalizeHydration(options.hydration) };
2379
2487
  const manager = this.getOrCreateModelOptions(modelName);
2380
2488
  const defaultOptions = this.getDefaultModelOptions();
2381
2489
  const currentModelOptions = manager.fetch();
@@ -2386,14 +2494,19 @@ var init_runtime = __esm({
2386
2494
  manager.assign({ ...defaultOptions, ...currentModelOptions, ...options });
2387
2495
  }
2388
2496
  setModelOption(modelName, key, value) {
2389
- const manager = this.getOrCreateModelOptions(modelName);
2390
2497
  const keyStr = String(key);
2498
+ if (keyStr === "hydration" || keyStr.startsWith("hydration.")) {
2499
+ const hydration = normalizeHydrationUpdate(this.modelOptions[modelName]?.get("hydration"), keyStr, value);
2500
+ this.getOrCreateModelOptions(modelName).set("hydration", hydration);
2501
+ return;
2502
+ }
2391
2503
  if (keyStr === "defaults") assertPublicDefaults(value);
2392
2504
  else if (keyStr.startsWith("defaults.")) {
2393
2505
  const proposed = {};
2394
- (0, import_utils13.set)(proposed, keyStr.slice("defaults.".length), value);
2506
+ (0, import_utils14.set)(proposed, keyStr.slice("defaults.".length), value);
2395
2507
  assertPublicDefaults(proposed);
2396
2508
  }
2509
+ const manager = this.getOrCreateModelOptions(modelName);
2397
2510
  if (keyStr === "virtuals" || keyStr.startsWith("virtuals.") || keyStr === "documentPermissionField") {
2398
2511
  const model = this.getModelInstance(modelName);
2399
2512
  const currentVirtuals = manager.get("virtuals");
@@ -2411,15 +2524,15 @@ var init_runtime = __esm({
2411
2524
  const segments = nestedPath.split(".");
2412
2525
  let cursor = cloned;
2413
2526
  for (let i = 0; i < segments.length - 1; i++) {
2414
- if (!(0, import_utils13.isPlainObject)(cursor)) break;
2527
+ if (!(0, import_utils14.isPlainObject)(cursor)) break;
2415
2528
  cursor = cursor[segments[i]];
2416
2529
  }
2417
- if ((0, import_utils13.isPlainObject)(cursor)) {
2530
+ if ((0, import_utils14.isPlainObject)(cursor)) {
2418
2531
  delete cursor[segments[segments.length - 1]];
2419
2532
  }
2420
2533
  proposedVirtuals = cloned;
2421
2534
  } else {
2422
- (0, import_utils13.set)(cloned, nestedPath, value);
2535
+ (0, import_utils14.set)(cloned, nestedPath, value);
2423
2536
  proposedVirtuals = cloned;
2424
2537
  }
2425
2538
  }
@@ -2497,8 +2610,8 @@ var init_runtime = __esm({
2497
2610
  if (!scopeVirtuals || !(virtualName in scopeVirtuals)) return void 0;
2498
2611
  const entry = scopeVirtuals[virtualName];
2499
2612
  if (entry === void 0 || isVirtualContainerValue(entry)) return void 0;
2500
- if ((0, import_utils13.isFunction)(entry)) return { get: entry, dependsOn: [] };
2501
- if (!(0, import_utils13.isPlainObject)(entry)) return void 0;
2613
+ if ((0, import_utils14.isFunction)(entry)) return { get: entry, dependsOn: [] };
2614
+ if (!(0, import_utils14.isPlainObject)(entry)) return void 0;
2502
2615
  const record2 = entry;
2503
2616
  if ("get" in record2) {
2504
2617
  const descriptor = toVirtualDescriptor(entry, void 0);
@@ -2534,7 +2647,7 @@ var init_runtime = __esm({
2534
2647
  manager.onchange("basePath", function(newval, key, target) {
2535
2648
  target[key] = normalizeBasePath(
2536
2649
  dataName,
2537
- (0, import_utils13.isString)(newval) || (0, import_utils13.isNil)(newval) ? newval : void 0
2650
+ (0, import_utils14.isString)(newval) || (0, import_utils14.isNil)(newval) ? newval : void 0
2538
2651
  );
2539
2652
  }).build();
2540
2653
  return manager;
@@ -2594,20 +2707,20 @@ var init_runtime = __esm({
2594
2707
  const schema = model.schema;
2595
2708
  this.modelRefs[modelName] = buildRefs(schema.tree);
2596
2709
  this.modelSubs[modelName] = buildSubPaths(schema.tree);
2597
- this.modelAtts[modelName] = (0, import_utils13.keys)(schema.obj);
2710
+ this.modelAtts[modelName] = (0, import_utils14.keys)(schema.obj);
2598
2711
  }
2599
2712
  getModelRef(modelName, refPath) {
2600
2713
  this.ensureModelMeta(modelName);
2601
- const value = (0, import_utils13.get)(this.modelRefs, `${modelName}.${refPath}`, null);
2602
- return (0, import_utils13.isString)(value) ? value : null;
2714
+ const value = (0, import_utils14.get)(this.modelRefs, `${modelName}.${refPath}`, null);
2715
+ return (0, import_utils14.isString)(value) ? value : null;
2603
2716
  }
2604
2717
  getModelSub(modelName) {
2605
2718
  this.ensureModelMeta(modelName);
2606
- return (0, import_utils13.get)(this.modelSubs, modelName, []);
2719
+ return (0, import_utils14.get)(this.modelSubs, modelName, []);
2607
2720
  }
2608
2721
  getModelAtt(modelName) {
2609
2722
  this.ensureModelMeta(modelName);
2610
- return (0, import_utils13.get)(this.modelAtts, modelName, []);
2723
+ return (0, import_utils14.get)(this.modelAtts, modelName, []);
2611
2724
  }
2612
2725
  };
2613
2726
  defaultRuntime = new AccessRuntime({ allowGlobalModelLookup: true });
@@ -2783,10 +2896,10 @@ var init_options = __esm({
2783
2896
  });
2784
2897
 
2785
2898
  // src/permission.ts
2786
- var import_utils14, Permission, permission_default;
2899
+ var import_utils15, Permission, permission_default;
2787
2900
  var init_permission = __esm({
2788
2901
  "src/permission.ts"() {
2789
- import_utils14 = require("@web-ts-toolkit/utils");
2902
+ import_utils15 = require("@web-ts-toolkit/utils");
2790
2903
  Permission = class {
2791
2904
  constructor(permissions) {
2792
2905
  this.permissions = { ...permissions };
@@ -2802,7 +2915,7 @@ var init_permission = __esm({
2802
2915
  return [permissionOrPermissions].concat(permissions);
2803
2916
  }
2804
2917
  hasKey(permission) {
2805
- return (0, import_utils14.hasOwn)(this.permissions, permission);
2918
+ return (0, import_utils15.hasOwn)(this.permissions, permission);
2806
2919
  }
2807
2920
  has(permission) {
2808
2921
  return this.permissions[permission] === true;
@@ -3872,36 +3985,36 @@ function planVirtualProjection(args) {
3872
3985
  relatedPlans
3873
3986
  };
3874
3987
  }
3875
- var import_utils17, isVirtualContainerValue2, getScopeVirtualsObject2, toSnapshotDescriptor, resolveSnapshotDescriptor, getScopedPermissionSchema, resolveAlwaysSelectForAccess, stripVirtualsFromNormalizedSelect, snapshotVirtualPaths, stripLeadingDash, dbPrefixForScope, toDbPath;
3988
+ var import_utils18, isVirtualContainerValue2, getScopeVirtualsObject2, toSnapshotDescriptor, resolveSnapshotDescriptor, getScopedPermissionSchema, resolveAlwaysSelectForAccess, stripVirtualsFromNormalizedSelect, snapshotVirtualPaths, stripLeadingDash, dbPrefixForScope, toDbPath;
3876
3989
  var init_virtual_projection = __esm({
3877
3990
  "src/acl/virtual-projection.ts"() {
3878
- import_utils17 = require("@web-ts-toolkit/utils");
3991
+ import_utils18 = require("@web-ts-toolkit/utils");
3879
3992
  init_query();
3880
3993
  init_field_authorization();
3881
3994
  init_output_projection();
3882
- isVirtualContainerValue2 = (value) => (0, import_utils17.isPlainObject)(value) && "sub" in value;
3995
+ isVirtualContainerValue2 = (value) => (0, import_utils18.isPlainObject)(value) && "sub" in value;
3883
3996
  getScopeVirtualsObject2 = (rootVirtuals, scopePath) => {
3884
- if (!rootVirtuals || !(0, import_utils17.isPlainObject)(rootVirtuals)) return null;
3997
+ if (!rootVirtuals || !(0, import_utils18.isPlainObject)(rootVirtuals)) return null;
3885
3998
  if (!scopePath || scopePath.length === 0) return rootVirtuals;
3886
3999
  let current = rootVirtuals;
3887
4000
  for (let i = 0; i < scopePath.length; i += 2) {
3888
4001
  const field = scopePath[i];
3889
4002
  const subMarker = scopePath[i + 1];
3890
4003
  if (!field || subMarker !== "sub") return null;
3891
- if (!(0, import_utils17.isPlainObject)(current)) return null;
4004
+ if (!(0, import_utils18.isPlainObject)(current)) return null;
3892
4005
  const container = current[field];
3893
4006
  if (!isVirtualContainerValue2(container)) return null;
3894
4007
  current = container.sub;
3895
- if (!(0, import_utils17.isPlainObject)(current)) return null;
4008
+ if (!(0, import_utils18.isPlainObject)(current)) return null;
3896
4009
  }
3897
4010
  return current;
3898
4011
  };
3899
4012
  toSnapshotDescriptor = (leaf, sharedDependsOn) => {
3900
- if ((0, import_utils17.isFunction)(leaf))
4013
+ if ((0, import_utils18.isFunction)(leaf))
3901
4014
  return { get: leaf, dependsOn: sharedDependsOn ?? [] };
3902
- if (!(0, import_utils17.isPlainObject)(leaf)) return null;
4015
+ if (!(0, import_utils18.isPlainObject)(leaf)) return null;
3903
4016
  const record2 = leaf;
3904
- if (!(0, import_utils17.isFunction)(record2.get)) return null;
4017
+ if (!(0, import_utils18.isFunction)(record2.get)) return null;
3905
4018
  const dependsOn = record2.dependsOn ?? sharedDependsOn ?? [];
3906
4019
  return { get: record2.get, dependsOn: [...dependsOn] };
3907
4020
  };
@@ -3909,8 +4022,8 @@ var init_virtual_projection = __esm({
3909
4022
  if (!scopeVirtuals || !(virtualName in scopeVirtuals)) return void 0;
3910
4023
  const entry = scopeVirtuals[virtualName];
3911
4024
  if (entry === void 0 || isVirtualContainerValue2(entry)) return void 0;
3912
- if ((0, import_utils17.isFunction)(entry)) return { get: entry, dependsOn: [] };
3913
- if (!(0, import_utils17.isPlainObject)(entry)) return void 0;
4025
+ if ((0, import_utils18.isFunction)(entry)) return { get: entry, dependsOn: [] };
4026
+ if (!(0, import_utils18.isPlainObject)(entry)) return void 0;
3914
4027
  const record2 = entry;
3915
4028
  if ("get" in record2) {
3916
4029
  return toSnapshotDescriptor(entry, void 0) ?? void 0;
@@ -3929,20 +4042,20 @@ var init_virtual_projection = __esm({
3929
4042
  return void 0;
3930
4043
  };
3931
4044
  getScopedPermissionSchema = (root, scopePath) => {
3932
- if (!root || !(0, import_utils17.isPlainObject)(root)) return null;
4045
+ if (!root || !(0, import_utils18.isPlainObject)(root)) return null;
3933
4046
  if (scopePath.length === 0) return root;
3934
- const scoped = (0, import_utils17.get)(root, scopePath.join("."));
3935
- return (0, import_utils17.isPlainObject)(scoped) ? scoped : null;
4047
+ const scoped = (0, import_utils18.get)(root, scopePath.join("."));
4048
+ return (0, import_utils18.isPlainObject)(scoped) ? scoped : null;
3936
4049
  };
3937
4050
  resolveAlwaysSelectForAccess = (raw, access) => {
3938
4051
  if (!raw) return [];
3939
- if ((0, import_utils17.isArray)(raw)) return [...raw];
3940
- if ((0, import_utils17.isPlainObject)(raw)) {
4052
+ if ((0, import_utils18.isArray)(raw)) return [...raw];
4053
+ if ((0, import_utils18.isPlainObject)(raw)) {
3941
4054
  const record2 = raw;
3942
4055
  const exact = record2[access];
3943
- if ((0, import_utils17.isArray)(exact)) return [...exact];
4056
+ if ((0, import_utils18.isArray)(exact)) return [...exact];
3944
4057
  const def = record2.default;
3945
- if ((0, import_utils17.isArray)(def)) return [...def];
4058
+ if ((0, import_utils18.isArray)(def)) return [...def];
3946
4059
  return [];
3947
4060
  }
3948
4061
  return [];
@@ -4182,12 +4295,11 @@ var init_output_projection = __esm({
4182
4295
 
4183
4296
  // src/acl/model-output-planning.ts
4184
4297
  function getCapturedAuthorizationOption(configuration, key) {
4185
- return resolveNestedOption((path, fallback) => (0, import_utils18.get)(configuration, path, fallback), key);
4298
+ return resolveNestedOption((path, fallback) => (0, import_utils19.get)(configuration, path, fallback), key);
4186
4299
  }
4187
- function captureModelAuthorizationConfiguration(runtime, modelName) {
4300
+ function captureModelAuthorizationConfiguration(runtime, modelName, options = runtime.getModelOptions(modelName)) {
4188
4301
  const model = runtime.getModelInstance(modelName);
4189
4302
  if (!model) return authorizationError(`unknown receiving model: ${modelName}`);
4190
- const options = runtime.getModelOptions(modelName);
4191
4303
  const virtuals = options.virtuals;
4192
4304
  return {
4193
4305
  catalog: captureAuthorizationFieldCatalog(model.schema, virtuals, options.documentPermissionField),
@@ -4205,7 +4317,8 @@ function captureModelAuthorizationConfiguration(runtime, modelName) {
4205
4317
  baseFilter: options.baseFilter,
4206
4318
  idField: options.idField,
4207
4319
  resolveIdFilter: options.resolveIdFilter,
4208
- operationAccess: options.operationAccess
4320
+ operationAccess: options.operationAccess,
4321
+ hydration: options.hydration
4209
4322
  };
4210
4323
  }
4211
4324
  function planModelOutputForHelper(args) {
@@ -4230,10 +4343,10 @@ function planModelOutputForHelper(args) {
4230
4343
  requestedSelect: args.select
4231
4344
  });
4232
4345
  }
4233
- var import_utils18;
4346
+ var import_utils19;
4234
4347
  var init_model_output_planning = __esm({
4235
4348
  "src/acl/model-output-planning.ts"() {
4236
- import_utils18 = require("@web-ts-toolkit/utils");
4349
+ import_utils19 = require("@web-ts-toolkit/utils");
4237
4350
  init_manager();
4238
4351
  init_field_catalog();
4239
4352
  init_authorization_snapshot();
@@ -4244,10 +4357,10 @@ var init_model_output_planning = __esm({
4244
4357
 
4245
4358
  // src/core-shared.ts
4246
4359
  function isAndFilter(filter2) {
4247
- return !!filter2 && (0, import_utils19.isPlainObject)(filter2) && Object.keys(filter2).length === 1 && (0, import_utils19.isArray)(filter2.$and);
4360
+ return !!filter2 && (0, import_utils20.isPlainObject)(filter2) && Object.keys(filter2).length === 1 && (0, import_utils20.isArray)(filter2.$and);
4248
4361
  }
4249
4362
  function isMergeableClause(filter2) {
4250
- return !!filter2 && (0, import_utils19.isPlainObject)(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
4363
+ return !!filter2 && (0, import_utils20.isPlainObject)(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
4251
4364
  }
4252
4365
  function optimizeAndFilter(clausesInput) {
4253
4366
  const clauses = [];
@@ -4264,11 +4377,11 @@ function optimizeAndFilter(clausesInput) {
4264
4377
  const dedupeKey = (value) => {
4265
4378
  if (value instanceof RegExp) return `regexp:${JSON.stringify([value.source, value.flags])}`;
4266
4379
  if (value instanceof Date) return `date:${value.getTime()}`;
4267
- if ((0, import_utils19.isArray)(value)) {
4380
+ if ((0, import_utils20.isArray)(value)) {
4268
4381
  const entries = Array.from(value, dedupeKey);
4269
4382
  return entries.every((entry) => entry !== void 0) ? `array:${JSON.stringify(entries)}` : void 0;
4270
4383
  }
4271
- if ((0, import_utils19.isPlainObject)(value)) {
4384
+ if ((0, import_utils20.isPlainObject)(value)) {
4272
4385
  const entries = Object.keys(value).sort().map((key) => [key, dedupeKey(value[key])]);
4273
4386
  return entries.every(([, entry]) => entry !== void 0) ? `object:${JSON.stringify(entries)}` : void 0;
4274
4387
  }
@@ -4298,7 +4411,7 @@ function optimizeAndFilter(clausesInput) {
4298
4411
  }
4299
4412
  let canMerge = true;
4300
4413
  for (const [key, value] of Object.entries(clause)) {
4301
- if ((0, import_utils19.hasOwn)(mergedClause, key) && !(0, import_node_util4.isDeepStrictEqual)(mergedClause[key], value)) {
4414
+ if ((0, import_utils20.hasOwn)(mergedClause, key) && !(0, import_node_util4.isDeepStrictEqual)(mergedClause[key], value)) {
4302
4415
  canMerge = false;
4303
4416
  break;
4304
4417
  }
@@ -4309,24 +4422,24 @@ function optimizeAndFilter(clausesInput) {
4309
4422
  }
4310
4423
  Object.assign(mergedClause, clause);
4311
4424
  }
4312
- const finalClauses = (0, import_utils19.isEmpty)(mergedClause) ? remainingClauses : [mergedClause, ...remainingClauses];
4425
+ const finalClauses = (0, import_utils20.isEmpty)(mergedClause) ? remainingClauses : [mergedClause, ...remainingClauses];
4313
4426
  if (finalClauses.length === 0) return null;
4314
4427
  if (finalClauses.length === 1) return finalClauses[0];
4315
4428
  return { $and: finalClauses };
4316
4429
  }
4317
4430
  function normalizeFilter(filter2) {
4318
4431
  if (filter2 === false) return false;
4319
- if (!filter2 || !(0, import_utils19.isPlainObject)(filter2) || (0, import_utils19.isEmpty)(filter2)) return null;
4432
+ if (!filter2 || !(0, import_utils20.isPlainObject)(filter2) || (0, import_utils20.isEmpty)(filter2)) return null;
4320
4433
  if (!isAndFilter(filter2)) {
4321
4434
  return filter2;
4322
4435
  }
4323
4436
  return optimizeAndFilter(filter2.$and);
4324
4437
  }
4325
4438
  async function resolveIdentifierFilter(req, idField, resolveIdFilter, id) {
4326
- if ((0, import_utils19.isFunction)(resolveIdFilter)) {
4439
+ if ((0, import_utils20.isFunction)(resolveIdFilter)) {
4327
4440
  return await resolveIdFilter.call(req, id);
4328
4441
  }
4329
- if ((0, import_utils19.isString)(idField)) {
4442
+ if ((0, import_utils20.isString)(idField)) {
4330
4443
  return { [idField]: id };
4331
4444
  }
4332
4445
  return { _id: id };
@@ -4350,7 +4463,7 @@ async function resolveAccessFilterParts({
4350
4463
  }
4351
4464
  const overrideFilterFn = getOption(`overrideFilter.${access}`, null);
4352
4465
  const baseFilterFn = rows.mode === "request" ? getOption(`baseFilter.${access}`, null) : null;
4353
- if (nextFilter !== false && (0, import_utils19.isFunction)(overrideFilterFn)) {
4466
+ if (nextFilter !== false && (0, import_utils20.isFunction)(overrideFilterFn)) {
4354
4467
  nextFilter = normalizeFilter(await overrideFilterFn.call(req, nextFilter, permissions));
4355
4468
  }
4356
4469
  if (nextFilter === false) return { transformed: false, scope: {}, filter: false };
@@ -4358,7 +4471,7 @@ async function resolveAccessFilterParts({
4358
4471
  const scope2 = rows.mode === "scope" ? rows.filter : {};
4359
4472
  return { transformed: nextFilter ?? {}, scope: scope2, filter: intersectFilters(nextFilter, scope2) };
4360
4473
  }
4361
- if (!(0, import_utils19.isFunction)(baseFilterFn)) return { transformed: nextFilter ?? {}, scope: {}, filter: nextFilter ?? {} };
4474
+ if (!(0, import_utils20.isFunction)(baseFilterFn)) return { transformed: nextFilter ?? {}, scope: {}, filter: nextFilter ?? {} };
4362
4475
  const cached = cache.get(cacheKey);
4363
4476
  const reusable = cached?.resolver === baseFilterFn;
4364
4477
  const baseFilter = normalizeFilter(
@@ -4393,34 +4506,34 @@ async function setRequestPermissions(req) {
4393
4506
  if (owner === activeRuntime) return;
4394
4507
  if (hasFieldValue && owner === void 0) return;
4395
4508
  const globalPermissions = getGlobalOption("globalPermissions");
4396
- const permissions = (0, import_utils19.isFunction)(globalPermissions) ? await globalPermissions.call(req, req) : void 0;
4397
- if ((0, import_utils19.isPlainObject)(permissions)) req[requestPermissionField] = permissions;
4398
- else if ((0, import_utils19.isArray)(permissions)) req[requestPermissionField] = (0, import_utils19.arrayToRecord)(permissions);
4399
- else if ((0, import_utils19.isString)(permissions)) req[requestPermissionField] = { [permissions]: true };
4509
+ const permissions = (0, import_utils20.isFunction)(globalPermissions) ? await globalPermissions.call(req, req) : void 0;
4510
+ if ((0, import_utils20.isPlainObject)(permissions)) req[requestPermissionField] = permissions;
4511
+ else if ((0, import_utils20.isArray)(permissions)) req[requestPermissionField] = (0, import_utils20.arrayToRecord)(permissions);
4512
+ else if ((0, import_utils20.isString)(permissions)) req[requestPermissionField] = { [permissions]: true };
4400
4513
  else req[requestPermissionField] = {};
4401
4514
  owners.set(requestPermissionField, activeRuntime);
4402
4515
  }
4403
4516
  async function evaluateRouteGuard(req, permissions, routeGuard) {
4404
4517
  const phas = (key) => permissions.has(key);
4405
4518
  const { stringHandler, arrayHandler } = createValidator(phas);
4406
- if ((0, import_utils19.isBoolean)(routeGuard)) {
4519
+ if ((0, import_utils20.isBoolean)(routeGuard)) {
4407
4520
  return routeGuard === true;
4408
4521
  }
4409
- if ((0, import_utils19.isString)(routeGuard)) {
4522
+ if ((0, import_utils20.isString)(routeGuard)) {
4410
4523
  return stringHandler(routeGuard);
4411
4524
  }
4412
- if ((0, import_utils19.isArray)(routeGuard)) {
4525
+ if ((0, import_utils20.isArray)(routeGuard)) {
4413
4526
  return arrayHandler(routeGuard);
4414
4527
  }
4415
- if ((0, import_utils19.isFunction)(routeGuard)) {
4528
+ if ((0, import_utils20.isFunction)(routeGuard)) {
4416
4529
  return routeGuard.call(req, permissions);
4417
4530
  }
4418
4531
  return false;
4419
4532
  }
4420
4533
  async function callHookChain(req, hook, doc, permissions, context) {
4421
- const hooks = (0, import_utils19.castArray)(hook);
4534
+ const hooks = (0, import_utils20.castArray)(hook);
4422
4535
  for (let x = 0; x < hooks.length; x++) {
4423
- if ((0, import_utils19.isFunction)(hooks[x])) {
4536
+ if ((0, import_utils20.isFunction)(hooks[x])) {
4424
4537
  doc = await hooks[x].call(req, doc, permissions, context);
4425
4538
  }
4426
4539
  }
@@ -4440,22 +4553,22 @@ async function collectSchemaFields({
4440
4553
  for (let x = 0; x < keys2.length; x++) {
4441
4554
  const key = keys2[x];
4442
4555
  const value = extractScopedOutputRule(permissionSchema, key, access);
4443
- if ((0, import_utils19.isBoolean)(value)) {
4556
+ if ((0, import_utils20.isBoolean)(value)) {
4444
4557
  if (value) fields.push(key);
4445
- } else if ((0, import_utils19.isString)(value)) {
4558
+ } else if ((0, import_utils20.isString)(value)) {
4446
4559
  if (stringHandler(value)) fields.push(key);
4447
- } else if ((0, import_utils19.isArray)(value)) {
4560
+ } else if ((0, import_utils20.isArray)(value)) {
4448
4561
  if (arrayHandler(value)) fields.push(key);
4449
- } else if ((0, import_utils19.isFunction)(value)) {
4562
+ } else if ((0, import_utils20.isFunction)(value)) {
4450
4563
  if (await value.call(req, ...functionArgs)) fields.push(key);
4451
4564
  }
4452
4565
  }
4453
4566
  return fields;
4454
4567
  }
4455
- var import_utils19, import_node_util4, permissionFieldOwners;
4568
+ var import_utils20, import_node_util4, permissionFieldOwners;
4456
4569
  var init_core_shared = __esm({
4457
4570
  "src/core-shared.ts"() {
4458
- import_utils19 = require("@web-ts-toolkit/utils");
4571
+ import_utils20 = require("@web-ts-toolkit/utils");
4459
4572
  import_node_util4 = require("util");
4460
4573
  init_helpers();
4461
4574
  init_options();
@@ -4683,7 +4796,7 @@ async function resolveOutputDocumentAuthorization(args) {
4683
4796
  try {
4684
4797
  const run = () => hook.call(this, doc, permissions, args.context);
4685
4798
  const grants = await getRequestWorkState(binding.request, binding.runtime).hookGate.run(run);
4686
- return (0, import_utils23.isPlainObject)(grants) ? grants : {};
4799
+ return (0, import_utils24.isPlainObject)(grants) ? grants : {};
4687
4800
  } catch (error2) {
4688
4801
  warn("docPermissions hook failed; applying empty document permissions", {
4689
4802
  modelName: binding.modelName,
@@ -4798,7 +4911,7 @@ function copyOutputValue(value, plan, path) {
4798
4911
  const visit = (input, current) => {
4799
4912
  if (Array.isArray(input)) return input.map((entry) => visit(entry, current));
4800
4913
  if (input instanceof Map) return visit(Object.fromEntries(input), current);
4801
- if (!(0, import_utils23.isPlainObject)(input)) return deepIsolateValue(input);
4914
+ if (!(0, import_utils24.isPlainObject)(input)) return deepIsolateValue(input);
4802
4915
  const output = {};
4803
4916
  for (const [key, entry] of Object.entries(input)) {
4804
4917
  const child = `${current}.${key}`;
@@ -4814,7 +4927,7 @@ function copyOutputValue(value, plan, path) {
4814
4927
  }
4815
4928
  function copyAuthorizedReference(value, plan, path) {
4816
4929
  if (Array.isArray(value)) return value.map((entry) => copyAuthorizedReference(entry, plan, path));
4817
- if (!(0, import_utils23.isPlainObject)(value)) return deepIsolateValue(value);
4930
+ if (!(0, import_utils24.isPlainObject)(value)) return deepIsolateValue(value);
4818
4931
  const handle = getAssociatedDocumentAuthorization(value, plan.authorization);
4819
4932
  if (handle) {
4820
4933
  const copy = deepIsolateValue(value);
@@ -4831,8 +4944,8 @@ function retainOutputMetadata(output, source, configuration, scope2) {
4831
4944
  if (scope2.length || configuration.stripPermissionsField) return;
4832
4945
  const parts = (configuration.documentPermissionField ?? "_permissions").split(".");
4833
4946
  let value = source;
4834
- for (const part of parts) value = (0, import_utils23.isPlainObject)(value) ? value[part] : void 0;
4835
- if (!(0, import_utils23.isPlainObject)(value)) return;
4947
+ for (const part of parts) value = (0, import_utils24.isPlainObject)(value) ? value[part] : void 0;
4948
+ if (!(0, import_utils24.isPlainObject)(value)) return;
4836
4949
  const keys2 = configuration.exposedDocPermissionKeys;
4837
4950
  const metadata = Object.fromEntries(
4838
4951
  Object.entries(value).filter(
@@ -4842,12 +4955,13 @@ function retainOutputMetadata(output, source, configuration, scope2) {
4842
4955
  const copy = { ...output };
4843
4956
  let target = copy;
4844
4957
  for (const part of parts.slice(0, -1)) {
4845
- target[part] = (0, import_utils23.isPlainObject)(target[part]) ? { ...target[part] } : {};
4958
+ target[part] = (0, import_utils24.isPlainObject)(target[part]) ? { ...target[part] } : {};
4846
4959
  target = target[part];
4847
4960
  }
4848
4961
  target[parts[parts.length - 1]] = deepIsolateValue(metadata);
4849
4962
  transferDocumentAuthorizationGraph(output[parts[0]], copy[parts[0]]);
4850
4963
  output[parts[0]] = copy[parts[0]];
4964
+ attachPermissionsAlias(output, parts.join("."));
4851
4965
  }
4852
4966
  function helperPlan(authorization, binding) {
4853
4967
  const { configuration, authorization: policy, access } = readServiceAuthorization(authorization, binding);
@@ -4883,7 +4997,7 @@ async function filterExistingOutput(source, plan, handle, associated) {
4883
4997
  for (const entry of value2) values.push(await one(entry) ?? null);
4884
4998
  return values;
4885
4999
  }
4886
- if (!(0, import_utils23.isPlainObject)(value2)) return value2 === null ? null : void 0;
5000
+ if (!(0, import_utils24.isPlainObject)(value2)) return value2 === null ? null : void 0;
4887
5001
  const childHandle = associated ? getAssociatedDocumentAuthorization(value2) : void 0;
4888
5002
  let child = scoped;
4889
5003
  if (childHandle) {
@@ -4963,7 +5077,7 @@ async function filterModelOutputForHelper(args) {
4963
5077
  const plan = helperPlan(normalized.authorization, binding);
4964
5078
  if (args.doc == null) return { output: args.doc, fields: [] };
4965
5079
  const source = isolateDocForOutput(args.doc);
4966
- if (!(0, import_utils23.isPlainObject)(source)) return authorizationError("output helper requires one plain or hydrated document");
5080
+ if (!(0, import_utils24.isPlainObject)(source)) return authorizationError("output helper requires one plain or hydrated document");
4967
5081
  const knownOutput = !!args.doc && typeof args.doc === "object" && isKnownAuthorizationOutput(args.doc);
4968
5082
  const handle = await resolveOutputDocumentAuthorization({
4969
5083
  authorization: normalized.authorization,
@@ -4974,10 +5088,11 @@ async function filterModelOutputForHelper(args) {
4974
5088
  });
4975
5089
  return filterExistingOutput(source, plan, handle, false);
4976
5090
  }
4977
- var import_utils23, unresolvedDocuments, owningDocuments;
5091
+ var import_utils24, unresolvedDocuments, owningDocuments;
4978
5092
  var init_output_field_filter = __esm({
4979
5093
  "src/acl/output-field-filter.ts"() {
4980
- import_utils23 = require("@web-ts-toolkit/utils");
5094
+ import_utils24 = require("@web-ts-toolkit/utils");
5095
+ init_permissions_alias();
4981
5096
  init_document();
4982
5097
  init_request_work();
4983
5098
  init_logger_helpers();
@@ -5069,8 +5184,8 @@ async function finalizeSingleDoc(args, input) {
5069
5184
  const limit = args.resolvedLimit;
5070
5185
  const gate = args.sharedGate;
5071
5186
  const isolated = isolateDocForOutput(input);
5072
- const output = (0, import_utils24.isPlainObject)(isolated) ? isolated : {};
5073
- if (captured && (0, import_utils24.isPlainObject)(input))
5187
+ const output = (0, import_utils25.isPlainObject)(isolated) ? isolated : {};
5188
+ if (captured && (0, import_utils25.isPlainObject)(input))
5074
5189
  for (const key of Object.keys(output)) {
5075
5190
  transferDocumentAuthorizationGraph(input[key], output[key]);
5076
5191
  }
@@ -5125,7 +5240,7 @@ async function finalizeSingleDoc(args, input) {
5125
5240
  );
5126
5241
  continue;
5127
5242
  }
5128
- if (captured && !(0, import_utils24.isPlainObject)(rawContainer) && !Array.isArray(rawContainer)) {
5243
+ if (captured && !(0, import_utils25.isPlainObject)(rawContainer) && !Array.isArray(rawContainer)) {
5129
5244
  delete output[containerName];
5130
5245
  continue;
5131
5246
  }
@@ -5147,7 +5262,7 @@ async function finalizeSingleDoc(args, input) {
5147
5262
  };
5148
5263
  const finalizeOneChild = async (rawChild) => {
5149
5264
  if (captured && Array.isArray(rawChild)) return mapWithConcurrencyLimit(rawChild, limit, finalizeOneChild);
5150
- if (!(0, import_utils24.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return captured ? null : deepIsolateValue(rawChild);
5265
+ if (!(0, import_utils25.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return captured ? null : deepIsolateValue(rawChild);
5151
5266
  if (args.traversal?.finalizeEmbeddedChildren) {
5152
5267
  return args.traversal.finalizeEmbeddedChildren({
5153
5268
  containerName,
@@ -5167,7 +5282,7 @@ async function finalizeSingleDoc(args, input) {
5167
5282
  if (Array.isArray(rawContainer)) {
5168
5283
  const finalized = await mapWithConcurrencyLimit(rawContainer, limit, (entry) => finalizeOneChild(entry));
5169
5284
  output[containerName] = finalized;
5170
- } else if ((0, import_utils24.isPlainObject)(rawContainer)) {
5285
+ } else if ((0, import_utils25.isPlainObject)(rawContainer)) {
5171
5286
  output[containerName] = await finalizeOneChild(rawContainer);
5172
5287
  }
5173
5288
  }
@@ -5175,7 +5290,7 @@ async function finalizeSingleDoc(args, input) {
5175
5290
  for (const target of relatedTargets) {
5176
5291
  let rawRelated;
5177
5292
  try {
5178
- rawRelated = target.path.includes(".") ? (0, import_utils24.get)(output, target.path) : output[target.path];
5293
+ rawRelated = target.path.includes(".") ? (0, import_utils25.get)(output, target.path) : output[target.path];
5179
5294
  } catch {
5180
5295
  continue;
5181
5296
  }
@@ -5204,7 +5319,7 @@ async function finalizeSingleDoc(args, input) {
5204
5319
  related: target.plan.relatedPlans?.length ? (args.related ?? []).filter((entry) => entry.path.startsWith(`${target.path}.`)) : []
5205
5320
  };
5206
5321
  const finalizeOneRelated = async (rawChild) => {
5207
- if (!(0, import_utils24.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return rawChild;
5322
+ if (!(0, import_utils25.isPlainObject)(rawChild) && !Array.isArray(rawChild)) return rawChild;
5208
5323
  if (typeof rawChild?._bsontype === "string") return rawChild;
5209
5324
  if (args.traversal?.finalizeRelatedValue) {
5210
5325
  return args.traversal.finalizeRelatedValue({ path: target.path, target, rawValue: rawChild, parentArgs: args });
@@ -5214,13 +5329,13 @@ async function finalizeSingleDoc(args, input) {
5214
5329
  let finalized;
5215
5330
  if (Array.isArray(rawRelated)) {
5216
5331
  finalized = await mapWithConcurrencyLimit(rawRelated, limit, (entry) => finalizeOneRelated(entry));
5217
- } else if ((0, import_utils24.isPlainObject)(rawRelated)) {
5332
+ } else if ((0, import_utils25.isPlainObject)(rawRelated)) {
5218
5333
  finalized = await finalizeOneRelated(rawRelated);
5219
5334
  } else {
5220
5335
  continue;
5221
5336
  }
5222
5337
  try {
5223
- if (target.path.includes(".")) (0, import_utils24.set)(output, target.path, finalized);
5338
+ if (target.path.includes(".")) (0, import_utils25.set)(output, target.path, finalized);
5224
5339
  else output[target.path] = finalized;
5225
5340
  } catch {
5226
5341
  }
@@ -5390,10 +5505,10 @@ async function finalizeModelOutputs(args) {
5390
5505
  return finalizeSingleDoc(internal, input);
5391
5506
  });
5392
5507
  }
5393
- var import_utils24, isVirtualContainerValue3, getScopeVirtualsObject3, getScopeVirtualNames, getScopedPermissionSchema2, resolveGlobalPermissions, resolveDocPermissions, isAbsentDependency, __finalizeInternals;
5508
+ var import_utils25, isVirtualContainerValue3, getScopeVirtualsObject3, getScopeVirtualNames, getScopedPermissionSchema2, resolveGlobalPermissions, resolveDocPermissions, isAbsentDependency, __finalizeInternals;
5394
5509
  var init_finalize_model_output = __esm({
5395
5510
  "src/output/finalize-model-output.ts"() {
5396
- import_utils24 = require("@web-ts-toolkit/utils");
5511
+ import_utils25 = require("@web-ts-toolkit/utils");
5397
5512
  init_document();
5398
5513
  init_concurrency();
5399
5514
  init_request_work();
@@ -5404,20 +5519,20 @@ var init_finalize_model_output = __esm({
5404
5519
  init_output_field_filter();
5405
5520
  init_field_authorization();
5406
5521
  init_field_catalog();
5407
- isVirtualContainerValue3 = (value) => (0, import_utils24.isPlainObject)(value) && "sub" in value;
5522
+ isVirtualContainerValue3 = (value) => (0, import_utils25.isPlainObject)(value) && "sub" in value;
5408
5523
  getScopeVirtualsObject3 = (rootVirtuals, scopePath) => {
5409
- if (!rootVirtuals || !(0, import_utils24.isPlainObject)(rootVirtuals)) return null;
5524
+ if (!rootVirtuals || !(0, import_utils25.isPlainObject)(rootVirtuals)) return null;
5410
5525
  if (scopePath.length === 0) return rootVirtuals;
5411
5526
  let current = rootVirtuals;
5412
5527
  for (let i = 0; i < scopePath.length; i += 2) {
5413
5528
  const field = scopePath[i];
5414
5529
  const subMarker = scopePath[i + 1];
5415
5530
  if (!field || subMarker !== "sub") return null;
5416
- if (!(0, import_utils24.isPlainObject)(current)) return null;
5531
+ if (!(0, import_utils25.isPlainObject)(current)) return null;
5417
5532
  const container = current[field];
5418
5533
  if (!isVirtualContainerValue3(container)) return null;
5419
5534
  current = container.sub;
5420
- if (!(0, import_utils24.isPlainObject)(current)) return null;
5535
+ if (!(0, import_utils25.isPlainObject)(current)) return null;
5421
5536
  }
5422
5537
  return current;
5423
5538
  };
@@ -5430,11 +5545,11 @@ var init_finalize_model_output = __esm({
5430
5545
  return Object.entries(scopeVirtuals).filter(([, v]) => v !== void 0 && !isVirtualContainerValue3(v)).map(([k]) => k);
5431
5546
  };
5432
5547
  getScopedPermissionSchema2 = (root, scopePath) => {
5433
- if (!root || !(0, import_utils24.isPlainObject)(root)) return null;
5548
+ if (!root || !(0, import_utils25.isPlainObject)(root)) return null;
5434
5549
  if (scopePath.length === 0) return root;
5435
5550
  try {
5436
- const scoped = (0, import_utils24.get)(root, scopePath.join("."));
5437
- return (0, import_utils24.isPlainObject)(scoped) ? scoped : null;
5551
+ const scoped = (0, import_utils25.get)(root, scopePath.join("."));
5552
+ return (0, import_utils25.isPlainObject)(scoped) ? scoped : null;
5438
5553
  } catch {
5439
5554
  return null;
5440
5555
  }
@@ -5493,7 +5608,7 @@ var init_finalize_model_output = __esm({
5493
5608
  const grants = await args.sharedGate.run(
5494
5609
  () => hook.call(args.request, isolatedForHook, globalPerms, scopeContext)
5495
5610
  );
5496
- const normalized = (0, import_utils24.isPlainObject)(grants) ? grants : {};
5611
+ const normalized = (0, import_utils25.isPlainObject)(grants) ? grants : {};
5497
5612
  scopeContext.docPermissions = normalized;
5498
5613
  return normalized;
5499
5614
  }
@@ -5565,15 +5680,15 @@ __export(index_exports, {
5565
5680
  setModelOptions: () => setModelOptions
5566
5681
  });
5567
5682
  module.exports = __toCommonJS(index_exports);
5568
- var import_utils42 = require("@web-ts-toolkit/utils");
5683
+ var import_utils43 = require("@web-ts-toolkit/utils");
5569
5684
 
5570
5685
  // src/middleware.ts
5571
5686
  var import_express_json_router5 = __toESM(require("@web-ts-toolkit/express-json-router"));
5572
- var import_utils35 = require("@web-ts-toolkit/utils");
5687
+ var import_utils36 = require("@web-ts-toolkit/utils");
5573
5688
 
5574
5689
  // src/core.ts
5575
5690
  init_public_admission();
5576
- var import_utils34 = require("@web-ts-toolkit/utils");
5691
+ var import_utils35 = require("@web-ts-toolkit/utils");
5577
5692
  init_options();
5578
5693
 
5579
5694
  // src/meta.ts
@@ -5598,13 +5713,13 @@ var getModelRef = (modelName, refPath) => {
5598
5713
  };
5599
5714
 
5600
5715
  // src/services/base.ts
5601
- var import_utils20 = require("@web-ts-toolkit/utils");
5716
+ var import_utils21 = require("@web-ts-toolkit/utils");
5602
5717
  init_options();
5603
5718
  init_helpers();
5604
5719
  init_document();
5605
5720
 
5606
5721
  // src/output/include-output.ts
5607
- var import_utils15 = require("@web-ts-toolkit/utils");
5722
+ var import_utils16 = require("@web-ts-toolkit/utils");
5608
5723
  init_document_authorization();
5609
5724
  init_document();
5610
5725
  var outputs2 = /* @__PURE__ */ new WeakMap();
@@ -5621,7 +5736,7 @@ function attachIncludeOutput(doc, path, value) {
5621
5736
  const state = stateFor(doc);
5622
5737
  if (!state) throw new Error("Include attachment requires a prepared output row");
5623
5738
  state.attachments.push({ path, value });
5624
- (0, import_utils15.set)(doc, path, deepIsolateValue(value));
5739
+ (0, import_utils16.set)(doc, path, deepIsolateValue(value));
5625
5740
  }
5626
5741
  function getIncludeSource(doc) {
5627
5742
  return stateFor(doc)?.source ?? doc;
@@ -5636,7 +5751,7 @@ function restoreIncludeOutput(doc, output) {
5636
5751
  for (const { path, value } of attachments) {
5637
5752
  const copy = deepIsolateValue(value);
5638
5753
  if (copy !== null && typeof copy === "object") origins.set(copy, value);
5639
- (0, import_utils15.set)(output, path, copy);
5754
+ (0, import_utils16.set)(output, path, copy);
5640
5755
  }
5641
5756
  return origins;
5642
5757
  }
@@ -5763,7 +5878,7 @@ function requestFieldScope(options) {
5763
5878
  init_public_admission();
5764
5879
 
5765
5880
  // src/correlated-includes.ts
5766
- var import_utils16 = require("@web-ts-toolkit/utils");
5881
+ var import_utils17 = require("@web-ts-toolkit/utils");
5767
5882
  init_request_complexity();
5768
5883
  init_sort_policy();
5769
5884
  var PARENT_MARKER_KEY = "$parent";
@@ -5776,10 +5891,10 @@ var FIELD_SEGMENT_PATTERN = /^[A-Za-z_][A-Za-z0-9_$]*$/;
5776
5891
  var ARRAY_INDEX_SEGMENT_PATTERN = /^(0|[1-9]\d*)$/;
5777
5892
  var ownKeys = (value) => Object.keys(value);
5778
5893
  function isParentRefMarker(value) {
5779
- return (0, import_utils16.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === PARENT_MARKER_KEY;
5894
+ return (0, import_utils17.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === PARENT_MARKER_KEY;
5780
5895
  }
5781
5896
  function isEscapedParentRef(value) {
5782
- return (0, import_utils16.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === ESCAPE_WRAPPER_KEY;
5897
+ return (0, import_utils17.isPlainObject)(value) && ownKeys(value).length === 1 && ownKeys(value)[0] === ESCAPE_WRAPPER_KEY;
5783
5898
  }
5784
5899
  function hasMarkerKey(value) {
5785
5900
  return ownKeys(value).includes(PARENT_MARKER_KEY) || ownKeys(value).includes(ESCAPE_WRAPPER_KEY);
@@ -5798,12 +5913,12 @@ function containsParentMarkerShape(value) {
5798
5913
  const seen = /* @__PURE__ */ new Set();
5799
5914
  const visit = (current) => {
5800
5915
  if (isParentRefMarker(current) || isEscapedParentRef(current)) return true;
5801
- if ((0, import_utils16.isArray)(current)) {
5916
+ if ((0, import_utils17.isArray)(current)) {
5802
5917
  if (seen.has(current)) return false;
5803
5918
  seen.add(current);
5804
5919
  return current.some(visit);
5805
5920
  }
5806
- if ((0, import_utils16.isPlainObject)(current)) {
5921
+ if ((0, import_utils17.isPlainObject)(current)) {
5807
5922
  if (seen.has(current)) return false;
5808
5923
  seen.add(current);
5809
5924
  if (hasMarkerKey(current)) return true;
@@ -5833,7 +5948,7 @@ function scanTemplateValueNode(value, path, issues) {
5833
5948
  }
5834
5949
  return;
5835
5950
  }
5836
- if ((0, import_utils16.isPlainObject)(value)) {
5951
+ if ((0, import_utils17.isPlainObject)(value)) {
5837
5952
  if (hasMarkerKey(value)) {
5838
5953
  issues.push({
5839
5954
  message: 'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }',
@@ -5844,7 +5959,7 @@ function scanTemplateValueNode(value, path, issues) {
5844
5959
  scanTemplateObjectEntries(value, path, issues);
5845
5960
  return;
5846
5961
  }
5847
- if ((0, import_utils16.isArray)(value)) {
5962
+ if ((0, import_utils17.isArray)(value)) {
5848
5963
  value.forEach((item, index) => scanTemplateValueNode(item, [...path, index], issues));
5849
5964
  }
5850
5965
  }
@@ -5885,7 +6000,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
5885
6000
  continue;
5886
6001
  }
5887
6002
  if (LOGICAL_CLAUSE_KEYS.has(key)) {
5888
- if (!(0, import_utils16.isArray)(child)) {
6003
+ if (!(0, import_utils17.isArray)(child)) {
5889
6004
  scanTemplateValueNode(child, childPath, issues);
5890
6005
  continue;
5891
6006
  }
@@ -5898,7 +6013,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
5898
6013
  });
5899
6014
  return;
5900
6015
  }
5901
- if ((0, import_utils16.isPlainObject)(clause)) {
6016
+ if ((0, import_utils17.isPlainObject)(clause)) {
5902
6017
  scanTemplateObjectEntries(clause, clausePath, issues);
5903
6018
  }
5904
6019
  });
@@ -5909,7 +6024,7 @@ function scanTemplateObjectEntries(obj, basePath, issues) {
5909
6024
  }
5910
6025
  function validateCorrelatedFilterTemplate(filter2) {
5911
6026
  const issues = [];
5912
- if (!(0, import_utils16.isPlainObject)(filter2)) {
6027
+ if (!(0, import_utils17.isPlainObject)(filter2)) {
5913
6028
  issues.push({ message: "Correlated include filter must be an object", path: [] });
5914
6029
  return issues;
5915
6030
  }
@@ -5952,13 +6067,13 @@ function collectFilterReferencePaths(filter2) {
5952
6067
  return;
5953
6068
  }
5954
6069
  if (isEscapedParentRef(value)) return;
5955
- if ((0, import_utils16.isArray)(value)) {
6070
+ if ((0, import_utils17.isArray)(value)) {
5956
6071
  if (seen.has(value)) return;
5957
6072
  seen.add(value);
5958
6073
  value.forEach(visitValue);
5959
6074
  return;
5960
6075
  }
5961
- if ((0, import_utils16.isPlainObject)(value)) {
6076
+ if ((0, import_utils17.isPlainObject)(value)) {
5962
6077
  if (seen.has(value)) return;
5963
6078
  seen.add(value);
5964
6079
  for (const [key, child] of Object.entries(value)) {
@@ -6004,7 +6119,7 @@ function getOwnPathValue(parent, path) {
6004
6119
  return current;
6005
6120
  }
6006
6121
  function cloneSubstitutedValue(value) {
6007
- if ((0, import_utils16.isPlainObject)(value) || (0, import_utils16.isArray)(value)) return (0, import_utils16.cloneDeep)(value);
6122
+ if ((0, import_utils17.isPlainObject)(value) || (0, import_utils17.isArray)(value)) return (0, import_utils17.cloneDeep)(value);
6008
6123
  return value;
6009
6124
  }
6010
6125
  function literalParentRefObject(path) {
@@ -6045,7 +6160,7 @@ function resolveObjectEntries(obj, parent) {
6045
6160
  continue;
6046
6161
  }
6047
6162
  if (LOGICAL_CLAUSE_KEYS.has(key)) {
6048
- if (!(0, import_utils16.isArray)(child)) {
6163
+ if (!(0, import_utils17.isArray)(child)) {
6049
6164
  out[key] = resolveValueNode(child, parent, false);
6050
6165
  continue;
6051
6166
  }
@@ -6053,7 +6168,7 @@ function resolveObjectEntries(obj, parent) {
6053
6168
  if (isParentRefMarker(clause) || isEscapedParentRef(clause)) {
6054
6169
  throw new CorrelatedReferenceError(`Unsupported $parent reference as a direct ${key} clause`);
6055
6170
  }
6056
- if (!(0, import_utils16.isPlainObject)(clause)) return cloneSubstitutedValue(clause);
6171
+ if (!(0, import_utils17.isPlainObject)(clause)) return cloneSubstitutedValue(clause);
6057
6172
  return resolveObjectEntries(clause, parent);
6058
6173
  });
6059
6174
  continue;
@@ -6082,10 +6197,10 @@ function resolveValueNode(template, parent, bare) {
6082
6197
  }
6083
6198
  const value = getOwnPathValue(parent, path);
6084
6199
  if (value === void 0 || value === null) throw UNRESOLVABLE;
6085
- if (bare && (0, import_utils16.isPlainObject)(value)) return { $eq: (0, import_utils16.cloneDeep)(value) };
6200
+ if (bare && (0, import_utils17.isPlainObject)(value)) return { $eq: (0, import_utils17.cloneDeep)(value) };
6086
6201
  return cloneSubstitutedValue(value);
6087
6202
  }
6088
- if ((0, import_utils16.isPlainObject)(template)) {
6203
+ if ((0, import_utils17.isPlainObject)(template)) {
6089
6204
  if (hasMarkerKey(template)) {
6090
6205
  throw new CorrelatedReferenceError(
6091
6206
  'Malformed $parent reference: objects carrying $parent must be exactly { "$parent": "<field>" }'
@@ -6093,7 +6208,7 @@ function resolveValueNode(template, parent, bare) {
6093
6208
  }
6094
6209
  return resolveObjectEntries(template, parent);
6095
6210
  }
6096
- if ((0, import_utils16.isArray)(template)) {
6211
+ if ((0, import_utils17.isArray)(template)) {
6097
6212
  return template.map((item) => resolveValueNode(item, parent, false));
6098
6213
  }
6099
6214
  return template;
@@ -6127,7 +6242,7 @@ function resolveCorrelatedIdTemplate(id, parent) {
6127
6242
  }
6128
6243
  function resolveCorrelatedFilterTemplate(filter2, parent) {
6129
6244
  try {
6130
- if (!(0, import_utils16.isPlainObject)(filter2) || isParentRefMarker(filter2) || isEscapedParentRef(filter2)) {
6245
+ if (!(0, import_utils17.isPlainObject)(filter2) || isParentRefMarker(filter2) || isEscapedParentRef(filter2)) {
6131
6246
  throw new CorrelatedReferenceError("Correlated include filter must be an object");
6132
6247
  }
6133
6248
  return { status: "resolved", filter: resolveObjectEntries(filter2, parent) };
@@ -6142,7 +6257,7 @@ function validateExpandedCorrelatedOperands(expanded, limits) {
6142
6257
  var MAX_NESTED_INCLUDE_DEPTH = 10;
6143
6258
  function validateCorrelatedArgsShape(args, op, depth) {
6144
6259
  if (args === void 0) return [];
6145
- if (!(0, import_utils16.isPlainObject)(args)) return ["Correlated include args must be an object"];
6260
+ if (!(0, import_utils17.isPlainObject)(args)) return ["Correlated include args must be an object"];
6146
6261
  const record2 = args;
6147
6262
  const allowed = op === "list" ? /* @__PURE__ */ new Set(["select", "sort", "skip", "limit", "page", "pageSize", "include"]) : /* @__PURE__ */ new Set(["select", "sort", "include"]);
6148
6263
  for (const key of Object.keys(record2)) {
@@ -6164,7 +6279,7 @@ function validateCorrelatedArgsShape(args, op, depth) {
6164
6279
  return [];
6165
6280
  }
6166
6281
  function validateCorrelatedIncludeShape(entry, depth = 0) {
6167
- if (!(0, import_utils16.isPlainObject)(entry)) return ["Correlated include must be an object"];
6282
+ if (!(0, import_utils17.isPlainObject)(entry)) return ["Correlated include must be an object"];
6168
6283
  const record2 = entry;
6169
6284
  if (record2.mode !== "correlated") return ['Correlated include mode must be "correlated"'];
6170
6285
  if (typeof record2.model !== "string" || record2.model.length === 0)
@@ -6177,7 +6292,7 @@ function validateCorrelatedIncludeShape(entry, depth = 0) {
6177
6292
  if ("localField" in record2 || "foreignField" in record2) {
6178
6293
  return ["Correlated includes must not carry localField or foreignField"];
6179
6294
  }
6180
- if (record2.options !== void 0 && !((0, import_utils16.isPlainObject)(record2.options) && Object.keys(record2.options).length === 0)) {
6295
+ if (record2.options !== void 0 && !((0, import_utils17.isPlainObject)(record2.options) && Object.keys(record2.options).length === 0)) {
6181
6296
  return ["Correlated include options must be absent or empty"];
6182
6297
  }
6183
6298
  const hasId = record2.id !== void 0;
@@ -6199,7 +6314,7 @@ function validateCorrelatedIncludeShape(entry, depth = 0) {
6199
6314
  return validateCorrelatedArgsShape(record2.args, record2.op, depth);
6200
6315
  }
6201
6316
  function isCorrelatedInclude(value) {
6202
- return (0, import_utils16.isPlainObject)(value) && value.mode === "correlated";
6317
+ return (0, import_utils17.isPlainObject)(value) && value.mode === "correlated";
6203
6318
  }
6204
6319
 
6205
6320
  // src/services/base.ts
@@ -6346,7 +6461,7 @@ function snapshotGroups(sources, valueOf, multipleKeys) {
6346
6461
  if (sources.length > MAX_GROUPS) invalid(`groups exceed ${MAX_GROUPS}`);
6347
6462
  const budget = new KeyBudget();
6348
6463
  const values = [];
6349
- const aliases = [];
6464
+ const aliases2 = [];
6350
6465
  const indices = /* @__PURE__ */ new Map();
6351
6466
  const groups = [];
6352
6467
  for (const source of sources) {
@@ -6357,7 +6472,7 @@ function snapshotGroups(sources, valueOf, multipleKeys) {
6357
6472
  if (index === void 0) {
6358
6473
  index = values.length;
6359
6474
  indices.set(alias, index);
6360
- aliases.push(alias);
6475
+ aliases2.push(alias);
6361
6476
  values.push(snapshot);
6362
6477
  }
6363
6478
  group.add(index);
@@ -6377,7 +6492,7 @@ function snapshotGroups(sources, valueOf, multipleKeys) {
6377
6492
  }
6378
6493
  return Object.freeze({
6379
6494
  values: Object.freeze(values),
6380
- aliases: Object.freeze(aliases),
6495
+ aliases: Object.freeze(aliases2),
6381
6496
  groups: Object.freeze((multipleKeys ? groups : values.map((_, i) => [i])).map((group) => Object.freeze(group)))
6382
6497
  });
6383
6498
  }
@@ -6427,7 +6542,7 @@ function getServiceExecutors(receiver) {
6427
6542
  if (!registered) authorizationError("unregistered service receiver");
6428
6543
  return registered;
6429
6544
  }
6430
- function createServiceExecution(receiver, access, authorization, applicability = "service", relatedTargets = [], parent, configuration, requestPermissions) {
6545
+ function createServiceExecution(receiver, access, authorization, applicability = "service", relatedTargets = [], parent, configuration, requestPermissions, hydration = access.operation === "list" ? "find" : "findOne") {
6431
6546
  const registered = getServiceExecutors(receiver);
6432
6547
  const receiving = registered.binding();
6433
6548
  const binding = Object.freeze({ ...receiving, scopePath: Object.freeze([...receiving.scopePath ?? []]) });
@@ -6449,11 +6564,23 @@ function createServiceExecution(receiver, access, authorization, applicability =
6449
6564
  binding,
6450
6565
  authorization: call,
6451
6566
  access: readServiceAuthorization(call, binding).access,
6452
- family: execution
6567
+ family: execution,
6568
+ hydration: resolveHydration(readServiceAuthorization(call, binding).configuration, hydration)
6453
6569
  })
6454
6570
  );
6455
6571
  return execution;
6456
6572
  }
6573
+ function resolveHydration(configuration, source) {
6574
+ if (source === "lean" || source === "hydrated") return source;
6575
+ return configuration.hydration?.[source] ?? (source === "publicList" ? "lean" : "hydrated");
6576
+ }
6577
+ function withExecutionHydration(receiver, parent, source) {
6578
+ const record2 = readServiceExecution(receiver, parent);
6579
+ const { configuration } = readServiceAuthorization(record2.authorization, record2.binding);
6580
+ const execution = Object.freeze(/* @__PURE__ */ Object.create(null));
6581
+ executions.set(execution, Object.freeze({ ...record2, hydration: resolveHydration(configuration, source) }));
6582
+ return execution;
6583
+ }
6457
6584
  function readServiceExecution(receiver, execution) {
6458
6585
  const record2 = executions.get(execution);
6459
6586
  if (!record2 || record2.receiver !== receiver) authorizationError("invalid execution receiver/call");
@@ -6658,20 +6785,20 @@ var copyAuthorizedOutput = (value) => {
6658
6785
  transferDocumentAuthorizationGraph(value, copy);
6659
6786
  return copy;
6660
6787
  };
6661
- var isVirtualContainerValueForGuard = (value) => (0, import_utils20.isPlainObject)(value) && "sub" in value;
6788
+ var isVirtualContainerValueForGuard = (value) => (0, import_utils21.isPlainObject)(value) && "sub" in value;
6662
6789
  var getScopeVirtualsForGuard = (rootVirtuals, scopePath) => {
6663
- if (!rootVirtuals || !(0, import_utils20.isPlainObject)(rootVirtuals)) return null;
6790
+ if (!rootVirtuals || !(0, import_utils21.isPlainObject)(rootVirtuals)) return null;
6664
6791
  if (scopePath.length === 0) return rootVirtuals;
6665
6792
  let current = rootVirtuals;
6666
6793
  for (let i = 0; i < scopePath.length; i += 2) {
6667
6794
  const field = scopePath[i];
6668
6795
  const subMarker = scopePath[i + 1];
6669
6796
  if (!field || subMarker !== "sub") return null;
6670
- if (!(0, import_utils20.isPlainObject)(current)) return null;
6797
+ if (!(0, import_utils21.isPlainObject)(current)) return null;
6671
6798
  const container = current[field];
6672
6799
  if (!isVirtualContainerValueForGuard(container)) return null;
6673
6800
  current = container.sub;
6674
- if (!(0, import_utils20.isPlainObject)(current)) return null;
6801
+ if (!(0, import_utils21.isPlainObject)(current)) return null;
6675
6802
  }
6676
6803
  return current;
6677
6804
  };
@@ -6737,7 +6864,7 @@ var sanitizeSubScopeVirtualKeys = (data, snapshot, sub) => {
6737
6864
  for (const entry of value) stripScope(entry, currentScope);
6738
6865
  return;
6739
6866
  }
6740
- if (!(0, import_utils20.isPlainObject)(value)) return;
6867
+ if (!(0, import_utils21.isPlainObject)(value)) return;
6741
6868
  const record2 = value;
6742
6869
  const leaves = getScopeVirtualLeafNames(snapshot, currentScope);
6743
6870
  for (const leaf of leaves) {
@@ -6750,7 +6877,7 @@ var sanitizeSubScopeVirtualKeys = (data, snapshot, sub) => {
6750
6877
  for (const key of Object.keys(record2)) {
6751
6878
  if (leaves.has(key) || containers.has(key)) continue;
6752
6879
  const child = record2[key];
6753
- if (Array.isArray(child) || (0, import_utils20.isPlainObject)(child)) {
6880
+ if (Array.isArray(child) || (0, import_utils21.isPlainObject)(child)) {
6754
6881
  stripScope(child, currentScope);
6755
6882
  }
6756
6883
  }
@@ -6762,7 +6889,7 @@ var LOGICAL_FILTER_KEYS = /* @__PURE__ */ new Set(["$and", "$or", "$nor"]);
6762
6889
  var isOperatorKey = (key) => key.startsWith("$");
6763
6890
  var REMOVED_VIRTUAL_FILTER = /* @__PURE__ */ Symbol("removed virtual filter clause");
6764
6891
  var rewriteFilterObject = (value, visit) => {
6765
- if (!(0, import_utils20.isPlainObject)(value)) return value;
6892
+ if (!(0, import_utils21.isPlainObject)(value)) return value;
6766
6893
  let changed = false;
6767
6894
  const entries = [];
6768
6895
  for (const [key, child] of Object.entries(value)) {
@@ -6793,7 +6920,7 @@ var resolveVirtualFilterField = (path, scope2) => {
6793
6920
  if (!Object.hasOwn(scope2, segment) || scope2[segment] === void 0) return null;
6794
6921
  const definition = scope2[segment];
6795
6922
  if (!isVirtualContainerValueForGuard(definition)) return REMOVED_VIRTUAL_FILTER;
6796
- scope2 = (0, import_utils20.isPlainObject)(definition.sub) ? definition.sub : null;
6923
+ scope2 = (0, import_utils21.isPlainObject)(definition.sub) ? definition.sub : null;
6797
6924
  inContainer = true;
6798
6925
  }
6799
6926
  return scope2;
@@ -6805,7 +6932,7 @@ var stripVirtualFilterOperator = (key, value, scope2) => {
6805
6932
  }
6806
6933
  if (key === "$all") {
6807
6934
  return rewriteFilterClauses(value, (entry) => {
6808
- if (!(0, import_utils20.isPlainObject)(entry) || Object.keys(entry).length !== 1 || !Object.hasOwn(entry, "$elemMatch")) return entry;
6935
+ if (!(0, import_utils21.isPlainObject)(entry) || Object.keys(entry).length !== 1 || !Object.hasOwn(entry, "$elemMatch")) return entry;
6809
6936
  return rewriteFilterObject(entry, (operator, operand) => stripVirtualFilterOperator(operator, operand, scope2));
6810
6937
  });
6811
6938
  }
@@ -6820,7 +6947,7 @@ var stripVirtualFilterQuery = (value, scope2, element = false) => {
6820
6947
  if (isOperatorKey(key)) return element ? stripVirtualFilterOperator(key, child, scope2) : child;
6821
6948
  const fieldScope = resolveVirtualFilterField(key, scope2);
6822
6949
  if (fieldScope === REMOVED_VIRTUAL_FILTER) return REMOVED_VIRTUAL_FILTER;
6823
- if (!fieldScope || !(0, import_utils20.isPlainObject)(child)) return child;
6950
+ if (!fieldScope || !(0, import_utils21.isPlainObject)(child)) return child;
6824
6951
  if (Object.keys(child).some(isOperatorKey)) {
6825
6952
  return rewriteFilterObject(
6826
6953
  child,
@@ -6842,9 +6969,9 @@ var stripSubVirtualKeysFromFilter = (filter2, snapshot, sub) => {
6842
6969
  function getCorrelatedTemplateDepth(includes) {
6843
6970
  let max = 0;
6844
6971
  const visit = (entries, depth) => {
6845
- const list = (0, import_utils20.castArray)(entries).filter(Boolean);
6972
+ const list = (0, import_utils21.castArray)(entries).filter(Boolean);
6846
6973
  for (const entry of list) {
6847
- if (!(0, import_utils20.isPlainObject)(entry)) continue;
6974
+ if (!(0, import_utils21.isPlainObject)(entry)) continue;
6848
6975
  max = Math.max(max, depth);
6849
6976
  const nested = entry.args?.include;
6850
6977
  if (nested !== void 0) {
@@ -6869,11 +6996,11 @@ function validateClientFilter(filter2) {
6869
6996
  }
6870
6997
  const blockedOperators = /* @__PURE__ */ new Set(["$where", "$expr", "$function", "$accumulator"]);
6871
6998
  const visit = (value, path) => {
6872
- if ((0, import_utils20.isArray)(value)) {
6999
+ if ((0, import_utils21.isArray)(value)) {
6873
7000
  value.forEach((item, index) => visit(item, `${path}[${index}]`));
6874
7001
  return;
6875
7002
  }
6876
- if (!(0, import_utils20.isPlainObject)(value)) return;
7003
+ if (!(0, import_utils21.isPlainObject)(value)) return;
6877
7004
  Object.entries(value).forEach(([key, child]) => {
6878
7005
  const nextPath = path ? `${path}.${key}` : key;
6879
7006
  if (blockedOperators.has(key)) {
@@ -7042,24 +7169,32 @@ var Base = class {
7042
7169
  relatedExecution(svc, include, parentAuthorization) {
7043
7170
  const op = include.op;
7044
7171
  if (!parentAuthorization)
7045
- return createServiceExecution(svc, {
7046
- operation: op,
7047
- rowAccess: op,
7048
- virtualAccess: op,
7049
- outputAccess: op,
7050
- docPermissionsAccess: op
7051
- });
7052
- return createRelatedExecution(
7172
+ return withExecutionHydration(
7173
+ svc,
7174
+ createServiceExecution(svc, {
7175
+ operation: op,
7176
+ rowAccess: op,
7177
+ virtualAccess: op,
7178
+ outputAccess: op,
7179
+ docPermissionsAccess: op
7180
+ }),
7181
+ "lean"
7182
+ );
7183
+ return withExecutionHydration(
7053
7184
  svc,
7054
- { operation: op, rowAccess: op, virtualAccess: op, outputAccess: op, docPermissionsAccess: op },
7055
- parentAuthorization,
7056
- this.relatedBinding(),
7057
- include.path
7185
+ createRelatedExecution(
7186
+ svc,
7187
+ { operation: op, rowAccess: op, virtualAccess: op, outputAccess: op, docPermissionsAccess: op },
7188
+ parentAuthorization,
7189
+ this.relatedBinding(),
7190
+ include.path
7191
+ ),
7192
+ "lean"
7058
7193
  );
7059
7194
  }
7060
7195
  processInclude(include) {
7061
7196
  assertPublicAdmission(include, "include");
7062
- const items = (0, import_utils20.compact)((0, import_utils20.castArray)(include));
7197
+ const items = (0, import_utils21.compact)((0, import_utils21.castArray)(include));
7063
7198
  const legacy = [];
7064
7199
  const correlated = [];
7065
7200
  const correlatedReferenceFields = [];
@@ -7094,23 +7229,23 @@ var Base = class {
7094
7229
  this.assertIncludeOutputPaths([...legacy, ...correlated]);
7095
7230
  let includeLocalFields = [];
7096
7231
  let includePaths = [];
7097
- (0, import_utils20.forEach)(legacy, (inc) => {
7232
+ (0, import_utils21.forEach)(legacy, (inc) => {
7098
7233
  includeLocalFields.push(inc.localField);
7099
7234
  includePaths.push(inc.path);
7100
7235
  });
7101
- includeLocalFields = (0, import_utils20.uniq)((0, import_utils20.compact)(includeLocalFields));
7102
- includePaths = (0, import_utils20.uniq)((0, import_utils20.compact)(includePaths));
7236
+ includeLocalFields = (0, import_utils21.uniq)((0, import_utils21.compact)(includeLocalFields));
7237
+ includePaths = (0, import_utils21.uniq)((0, import_utils21.compact)(includePaths));
7103
7238
  return {
7104
7239
  includes: legacy,
7105
7240
  correlatedIncludes: correlated,
7106
7241
  includeLocalFields,
7107
7242
  includePaths,
7108
- correlatedReferenceFields: (0, import_utils20.uniq)((0, import_utils20.compact)(correlatedReferenceFields))
7243
+ correlatedReferenceFields: (0, import_utils21.uniq)((0, import_utils21.compact)(correlatedReferenceFields))
7109
7244
  };
7110
7245
  }
7111
7246
  validateIncludeOutputPath(path, modelName) {
7112
7247
  const permissionField = getModelOption(modelName, "documentPermissionField");
7113
- if ((0, import_utils20.get)((0, import_utils20.set)({}, path, true), permissionField) !== void 0 || (0, import_utils20.get)((0, import_utils20.set)({}, permissionField, true), path) !== void 0) {
7248
+ if ((0, import_utils21.get)((0, import_utils21.set)({}, path, true), permissionField) !== void 0 || (0, import_utils21.get)((0, import_utils21.set)({}, permissionField, true), path) !== void 0) {
7114
7249
  this.throwClientRequestError(
7115
7250
  "bad_request" /* BadRequest */,
7116
7251
  `Include output path ${path} overlaps document permission field ${permissionField} on model ${modelName}`
@@ -7135,9 +7270,9 @@ var Base = class {
7135
7270
  const walk = (node, prefix) => {
7136
7271
  for (const [key, value] of Object.entries(node)) {
7137
7272
  if (value === void 0) continue;
7138
- if ((0, import_utils20.isPlainObject)(value) && "sub" in value) {
7273
+ if ((0, import_utils21.isPlainObject)(value) && "sub" in value) {
7139
7274
  const sub = value.sub;
7140
- if ((0, import_utils20.isPlainObject)(sub)) walk(sub, prefix ? `${prefix}.${key}` : key);
7275
+ if ((0, import_utils21.isPlainObject)(sub)) walk(sub, prefix ? `${prefix}.${key}` : key);
7141
7276
  continue;
7142
7277
  }
7143
7278
  out.push(prefix ? `${prefix}.${key}` : key);
@@ -7190,7 +7325,7 @@ var Base = class {
7190
7325
  this.throwClientRequestError("bad_request" /* BadRequest */, `Model ${modelName} not found`);
7191
7326
  }
7192
7327
  for (const entry of entries) {
7193
- if (!(0, import_utils20.isPlainObject)(entry)) continue;
7328
+ if (!(0, import_utils21.isPlainObject)(entry)) continue;
7194
7329
  const models = visited.get(entry) ?? /* @__PURE__ */ new Set();
7195
7330
  if (models.has(modelName)) continue;
7196
7331
  models.add(modelName);
@@ -7200,13 +7335,13 @@ var Base = class {
7200
7335
  }
7201
7336
  if ((entry.op === "read" || entry.op === "list") && typeof entry.model === "string") {
7202
7337
  const nested = entry.args?.include;
7203
- if (nested) pending.push({ entries: (0, import_utils20.compact)((0, import_utils20.castArray)(nested)), modelName: entry.model });
7338
+ if (nested) pending.push({ entries: (0, import_utils21.compact)((0, import_utils21.castArray)(nested)), modelName: entry.model });
7204
7339
  }
7205
7340
  }
7206
7341
  }
7207
7342
  }
7208
7343
  getForeignKeyValues(value) {
7209
- return (0, import_utils20.flatten)((0, import_utils20.castArray)(value));
7344
+ return (0, import_utils21.flatten)((0, import_utils21.castArray)(value));
7210
7345
  }
7211
7346
  getForeignKey(value) {
7212
7347
  return String(value);
@@ -7214,7 +7349,7 @@ var Base = class {
7214
7349
  buildForeignKeyIndex(rows, foreignField) {
7215
7350
  const index = /* @__PURE__ */ new Map();
7216
7351
  for (const row of rows) {
7217
- for (const value of this.getForeignKeyValues((0, import_utils20.get)(row, foreignField))) {
7352
+ for (const value of this.getForeignKeyValues((0, import_utils21.get)(row, foreignField))) {
7218
7353
  const key = this.getForeignKey(value);
7219
7354
  const values = index.get(key);
7220
7355
  if (values) values.push(row);
@@ -7250,9 +7385,9 @@ var Base = class {
7250
7385
  async includeDocs(docs, include, parentAuthorization) {
7251
7386
  assertPublicAdmission(include, "include");
7252
7387
  if (!include) return docs;
7253
- const includes = (0, import_utils20.compact)((0, import_utils20.castArray)(include));
7388
+ const includes = (0, import_utils21.compact)((0, import_utils21.castArray)(include));
7254
7389
  if (includes.length === 0) return docs;
7255
- const isSingle = !(0, import_utils20.isArray)(docs);
7390
+ const isSingle = !(0, import_utils21.isArray)(docs);
7256
7391
  let docList = (isSingle ? [docs] : docs).map(prepareIncludeOutput);
7257
7392
  for (let x = 0; x < includes.length; x++) {
7258
7393
  const include2 = includes[x];
@@ -7282,7 +7417,7 @@ var Base = class {
7282
7417
  const svc = await this.getAuthorizedTargetService(model, "read", path, parentAuthorization);
7283
7418
  for (let y = 0; y < docs.length; y++) {
7284
7419
  const doc = docs[y];
7285
- const localValue = (0, import_utils20.get)(doc, localField);
7420
+ const localValue = (0, import_utils21.get)(doc, localField);
7286
7421
  const execution = this.relatedExecution(svc, include, parentAuthorization);
7287
7422
  const prepared = await prepareModelQuery(
7288
7423
  svc,
@@ -7296,7 +7431,6 @@ var Base = class {
7296
7431
  skim,
7297
7432
  populateAccess,
7298
7433
  access: "read",
7299
- lean: true,
7300
7434
  includePermissions: false,
7301
7435
  includeFieldPermissions: false
7302
7436
  });
@@ -7318,15 +7452,15 @@ var Base = class {
7318
7452
  const { model, op, path, localField, foreignField, filter: _filters, args = {}, options = {} } = include;
7319
7453
  const svc = await this.getAuthorizedTargetService(model, op, path, parentAuthorization);
7320
7454
  const includeLocalValues = [];
7321
- (0, import_utils20.forEach)(docs, (doc) => {
7322
- includeLocalValues.push(...this.getForeignKeyValues((0, import_utils20.get)(doc, localField)));
7455
+ (0, import_utils21.forEach)(docs, (doc) => {
7456
+ includeLocalValues.push(...this.getForeignKeyValues((0, import_utils21.get)(doc, localField)));
7323
7457
  });
7324
7458
  const execution = this.relatedExecution(svc, include, parentAuthorization);
7325
7459
  const prepared = await prepareModelQuery(
7326
7460
  svc,
7327
7461
  execution,
7328
7462
  { kind: "client-read", filter: _filters ?? {} },
7329
- { [foreignField]: { $in: (0, import_utils20.flatten)(includeLocalValues) } },
7463
+ { [foreignField]: { $in: (0, import_utils21.flatten)(includeLocalValues) } },
7330
7464
  true
7331
7465
  );
7332
7466
  const trustedArgs = this.sanitizeIncludeArgs(args, "list");
@@ -7335,7 +7469,6 @@ var Base = class {
7335
7469
  ...requestOnlyServiceOptions({
7336
7470
  skim,
7337
7471
  populateAccess,
7338
- lean: true,
7339
7472
  includePermissions: false,
7340
7473
  includeFieldPermissions: false,
7341
7474
  includeCount: false
@@ -7370,7 +7503,7 @@ var Base = class {
7370
7503
  }
7371
7504
  for (let y = 0; y < docs.length; y++) {
7372
7505
  const doc = docs[y];
7373
- const matches = this.getIndexedMatches(index, (0, import_utils20.get)(doc, localField));
7506
+ const matches = this.getIndexedMatches(index, (0, import_utils21.get)(doc, localField));
7374
7507
  const isolated = matches.map((m) => copyAuthorizedOutput(m));
7375
7508
  attachIncludeOutput(doc, path, op === "list" ? isolated : isolated[0]);
7376
7509
  }
@@ -7379,7 +7512,7 @@ var Base = class {
7379
7512
  async includeDocsCount(docs, include, parentAuthorization) {
7380
7513
  const { model, path, localField, foreignField, filter: _filters } = include;
7381
7514
  const svc = await this.getAuthorizedTargetService(model, "count", path, parentAuthorization);
7382
- const groups = prepareCountGroups(docs, (doc) => (0, import_utils20.get)(doc, localField));
7515
+ const groups = prepareCountGroups(docs, (doc) => (0, import_utils21.get)(doc, localField));
7383
7516
  const execution = this.relatedExecution(svc, include, parentAuthorization);
7384
7517
  const prepared = await prepareModelQuery(
7385
7518
  svc,
@@ -7433,7 +7566,7 @@ var Base = class {
7433
7566
  }
7434
7567
  const state = this.getCorrelatedExecState();
7435
7568
  docs = docs.map(prepareIncludeOutput);
7436
- const resolvedSnapshots = snapshots ?? docs.map((doc) => (0, import_utils20.cloneDeep)(toObject(getIncludeSource(doc))));
7569
+ const resolvedSnapshots = snapshots ?? docs.map((doc) => (0, import_utils21.cloneDeep)(toObject(getIncludeSource(doc))));
7437
7570
  for (const include of correlatedIncludes) {
7438
7571
  switch (include.op) {
7439
7572
  case "read":
@@ -7510,7 +7643,6 @@ var Base = class {
7510
7643
  },
7511
7644
  requestOnlyServiceOptions({
7512
7645
  access: "read",
7513
- lean: true,
7514
7646
  includePermissions: false,
7515
7647
  includeFieldPermissions: false
7516
7648
  })
@@ -7585,7 +7717,6 @@ var Base = class {
7585
7717
  },
7586
7718
  requestOnlyServiceOptions({
7587
7719
  access: "read",
7588
- lean: true,
7589
7720
  includePermissions: false,
7590
7721
  includeFieldPermissions: false
7591
7722
  })
@@ -7670,7 +7801,6 @@ var Base = class {
7670
7801
  },
7671
7802
  requestOnlyServiceOptions({
7672
7803
  includeCount: false,
7673
- lean: true,
7674
7804
  includePermissions: false,
7675
7805
  includeFieldPermissions: false
7676
7806
  })
@@ -7785,10 +7915,10 @@ var Base = class {
7785
7915
  }
7786
7916
  let ret = result2.data;
7787
7917
  if (sqOptions.path) {
7788
- ret = (0, import_utils20.isArray)(ret) ? (0, import_utils20.flatten)(ret.map((v) => (0, import_utils20.get)(v, sqOptions.path))) : (0, import_utils20.get)(ret, sqOptions.path);
7918
+ ret = (0, import_utils21.isArray)(ret) ? (0, import_utils21.flatten)(ret.map((v) => (0, import_utils21.get)(v, sqOptions.path))) : (0, import_utils21.get)(ret, sqOptions.path);
7789
7919
  }
7790
7920
  if (sqOptions.compact) {
7791
- ret = (0, import_utils20.compact)((0, import_utils20.castArray)(ret));
7921
+ ret = (0, import_utils21.compact)((0, import_utils21.castArray)(ret));
7792
7922
  }
7793
7923
  return ret;
7794
7924
  }
@@ -7800,11 +7930,11 @@ var Base = class {
7800
7930
  };
7801
7931
 
7802
7932
  // src/services/service.ts
7803
- var import_utils30 = require("@web-ts-toolkit/utils");
7933
+ var import_utils31 = require("@web-ts-toolkit/utils");
7804
7934
  var import_just_diff = require("just-diff");
7805
7935
 
7806
7936
  // src/model.ts
7807
- var import_utils21 = require("@web-ts-toolkit/utils");
7937
+ var import_utils22 = require("@web-ts-toolkit/utils");
7808
7938
  init_runtime_context();
7809
7939
  init_runtime();
7810
7940
  function admitModelPersistence(adapter, scheduler) {
@@ -7880,7 +8010,7 @@ var Model = class {
7880
8010
  }
7881
8011
  /** Cast a copy using this model's query schema/setters, without executing query middleware or persistence. */
7882
8012
  castFilter(filter2) {
7883
- const query = this.mongooseModel.countDocuments((0, import_utils21.cloneDeep)(filter2));
8013
+ const query = this.mongooseModel.countDocuments((0, import_utils22.cloneDeep)(filter2));
7884
8014
  return query.cast(this.mongooseModel);
7885
8015
  }
7886
8016
  // see https://mongoosejs.com/docs/api.html#model_Model.distinct
@@ -7894,7 +8024,7 @@ var Model = class {
7894
8024
  var model_default = Model;
7895
8025
 
7896
8026
  // src/acl/distinct-field-authorization.ts
7897
- var import_utils22 = require("@web-ts-toolkit/utils");
8027
+ var import_utils23 = require("@web-ts-toolkit/utils");
7898
8028
  init_field_authorization();
7899
8029
  init_field_catalog();
7900
8030
  var schemaVariants = (schema) => Object.values(schema.discriminators ?? {});
@@ -7976,8 +8106,8 @@ function isDistinctFieldAuthorized(args) {
7976
8106
  if (path !== field && !path.startsWith(`${field}.`) && !field.startsWith(`${path}.`)) continue;
7977
8107
  if (path.startsWith(`${field}.`) && (!eligible(path) || !schemaShape(schema, path) || !granted(path)))
7978
8108
  return false;
7979
- if ((0, import_utils22.isPlainObject)(raw) && raw.sub !== void 0) {
7980
- if (!(0, import_utils22.isPlainObject)(raw.sub) || !declaredRulesSafe(raw.sub, path, next)) return false;
8109
+ if ((0, import_utils23.isPlainObject)(raw) && raw.sub !== void 0) {
8110
+ if (!(0, import_utils23.isPlainObject)(raw.sub) || !declaredRulesSafe(raw.sub, path, next)) return false;
7981
8111
  }
7982
8112
  }
7983
8113
  return true;
@@ -8155,6 +8285,7 @@ function copySubdocumentParent(parent) {
8155
8285
  init_permission();
8156
8286
  init_core_shared();
8157
8287
  init_finalize_model_output();
8288
+ init_permissions_alias();
8158
8289
 
8159
8290
  // src/acl/populate-target.ts
8160
8291
  var POPULATE_TARGET_PLAN = /* @__PURE__ */ Symbol("accessRouter.populateTargetPlan");
@@ -8179,7 +8310,7 @@ function getPopulateTargetMeta(entry) {
8179
8310
  init_document();
8180
8311
 
8181
8312
  // src/helpers/apply-update.ts
8182
- var import_utils25 = require("@web-ts-toolkit/utils");
8313
+ var import_utils26 = require("@web-ts-toolkit/utils");
8183
8314
  init_lib();
8184
8315
  function applyUpdate(target, data, allowedFields) {
8185
8316
  const wholeFields = /* @__PURE__ */ new Set();
@@ -8195,17 +8326,17 @@ function applyUpdate(target, data, allowedFields) {
8195
8326
  }
8196
8327
  };
8197
8328
  for (const field of allowedFields) {
8198
- collectBoundary((0, import_utils25.set)({}, field, true));
8329
+ collectBoundary((0, import_utils26.set)({}, field, true));
8199
8330
  }
8200
8331
  const apply = (values, prefix = "") => {
8201
8332
  for (const [key, value] of Object.entries(values)) {
8202
8333
  const path = prefix ? `${prefix}.${key}` : key;
8203
- if (partialContainers.has(path) && !wholeFields.has(path) && ((0, import_utils25.isPlainObject)(value) || Array.isArray(value))) {
8334
+ if (partialContainers.has(path) && !wholeFields.has(path) && ((0, import_utils26.isPlainObject)(value) || Array.isArray(value))) {
8204
8335
  apply(value, path);
8205
8336
  } else if (isDocument2(target)) {
8206
8337
  target.set(path, value);
8207
8338
  } else {
8208
- (0, import_utils25.set)(target, path, value);
8339
+ (0, import_utils26.set)(target, path, value);
8209
8340
  }
8210
8341
  }
8211
8342
  };
@@ -8213,7 +8344,7 @@ function applyUpdate(target, data, allowedFields) {
8213
8344
  }
8214
8345
 
8215
8346
  // src/acl/model-input-admission.ts
8216
- var import_utils27 = require("@web-ts-toolkit/utils");
8347
+ var import_utils28 = require("@web-ts-toolkit/utils");
8217
8348
  var import_mongoose7 = require("mongoose");
8218
8349
  init_document();
8219
8350
  init_request_work();
@@ -8221,7 +8352,7 @@ init_logger_helpers();
8221
8352
  init_request_complexity();
8222
8353
 
8223
8354
  // src/acl/select-resolution.ts
8224
- var import_utils26 = require("@web-ts-toolkit/utils");
8355
+ var import_utils27 = require("@web-ts-toolkit/utils");
8225
8356
  init_core_shared();
8226
8357
  init_helpers();
8227
8358
  async function collectAllowedFieldsForRequest({
@@ -8295,15 +8426,15 @@ async function resolveSelectForRequest({
8295
8426
  const excludeall = normalizedSelect.every((v) => v.startsWith("-"));
8296
8427
  if (excludeall) {
8297
8428
  normalizedSelect = normalizedSelect.map((v) => v.substring(1));
8298
- fields = (0, import_utils26.difference)(fields, normalizedSelect);
8429
+ fields = (0, import_utils27.difference)(fields, normalizedSelect);
8299
8430
  if (excludeid) fields.push("-_id");
8300
8431
  } else {
8301
- fields = (0, import_utils26.intersection)(normalizedSelect, fields.concat(excludeid ? "-_id" : "_id"));
8432
+ fields = (0, import_utils27.intersection)(normalizedSelect, fields.concat(excludeid ? "-_id" : "_id"));
8302
8433
  }
8303
8434
  }
8304
8435
  return fields.concat(strippedAlways);
8305
8436
  }
8306
- return (0, import_utils26.intersection)(normalizedSelect, fields);
8437
+ return (0, import_utils27.intersection)(normalizedSelect, fields);
8307
8438
  }
8308
8439
  function stripVirtuals(fields, virtualNames) {
8309
8440
  const set13 = virtualNames instanceof Set ? virtualNames : new Set(virtualNames ?? []);
@@ -8334,7 +8465,7 @@ init_field_catalog();
8334
8465
  init_service_authorization();
8335
8466
  var own = (value, key) => Object.prototype.hasOwnProperty.call(value, key);
8336
8467
  var inside = (path, root) => path === root || path.startsWith(`${root}.`);
8337
- var record = (value) => (0, import_utils27.isPlainObject)(value);
8468
+ var record = (value) => (0, import_utils28.isPlainObject)(value);
8338
8469
  function inputValue(value) {
8339
8470
  if (typeof value === "function" || typeof value === "symbol") {
8340
8471
  authorizationError("input values must be persisted data, not functions or symbols");
@@ -8403,7 +8534,7 @@ function requestBoundaries(fields) {
8403
8534
  else visit(value, path);
8404
8535
  }
8405
8536
  };
8406
- for (const field of fields) visit((0, import_utils27.set)({}, field, true));
8537
+ for (const field of fields) visit((0, import_utils28.set)({}, field, true));
8407
8538
  return [...new Set(result2)];
8408
8539
  }
8409
8540
  function ownValue(data, parts) {
@@ -8533,7 +8664,7 @@ function admitModelInput(args) {
8533
8664
  if (forbidden(catalog, path, requested)) continue;
8534
8665
  const supplied = ownValue(data, parts);
8535
8666
  if (!supplied) continue;
8536
- (0, import_utils27.set)(allowedData, field, copyInputValue(supplied.value, path, catalog, scopedRequests, logicalPath(field)));
8667
+ (0, import_utils28.set)(allowedData, field, copyInputValue(supplied.value, path, catalog, scopedRequests, logicalPath(field)));
8537
8668
  selected.push(field);
8538
8669
  }
8539
8670
  return { allowedData, allowedFields };
@@ -8545,7 +8676,7 @@ async function requestInputFields(args) {
8545
8676
  const prefix = configuration.modelPermissionPrefix ?? "";
8546
8677
  return collectModelRequestFields({
8547
8678
  req: args.binding.request,
8548
- permissionSchema: args.scopePath ? (0, import_utils27.get)(configuration.permissionSchema, [args.scopePath, "sub"]) : configuration.permissionSchema,
8679
+ permissionSchema: args.scopePath ? (0, import_utils28.get)(configuration.permissionSchema, [args.scopePath, "sub"]) : configuration.permissionSchema,
8549
8680
  access: args.access,
8550
8681
  permissions,
8551
8682
  grants,
@@ -8589,13 +8720,13 @@ init_logger_helpers();
8589
8720
  init_lib();
8590
8721
 
8591
8722
  // src/services/model-subdocument-service.ts
8592
- var import_utils29 = require("@web-ts-toolkit/utils");
8723
+ var import_utils30 = require("@web-ts-toolkit/utils");
8593
8724
  init_helpers();
8594
8725
  init_document();
8595
8726
  init_public_admission();
8596
8727
 
8597
8728
  // src/acl/subdocument-authorization.ts
8598
- var import_utils28 = require("@web-ts-toolkit/utils");
8729
+ var import_utils29 = require("@web-ts-toolkit/utils");
8599
8730
  init_helpers();
8600
8731
  init_document();
8601
8732
  init_core_shared();
@@ -8782,8 +8913,8 @@ async function subdocumentGateAllowed(service, gate) {
8782
8913
  let guard2;
8783
8914
  if (access.startsWith("subs.")) {
8784
8915
  const [, sub, op] = access.split(".");
8785
- guard2 = (0, import_utils28.get)(configuration, `operationAccess.${access}`);
8786
- if (guard2 === void 0) guard2 = (0, import_utils28.get)(configuration, `operationAccess.subs.${sub}`);
8916
+ guard2 = (0, import_utils29.get)(configuration, `operationAccess.${access}`);
8917
+ if (guard2 === void 0) guard2 = (0, import_utils29.get)(configuration, `operationAccess.subs.${sub}`);
8787
8918
  if (guard2 === void 0) guard2 = getCapturedAuthorizationOption(configuration, `operationAccess.${op}`);
8788
8919
  } else guard2 = getCapturedAuthorizationOption(configuration, `operationAccess.${access}`);
8789
8920
  return evaluateRouteGuard(
@@ -8855,8 +8986,7 @@ async function mutationParent(service, id, call) {
8855
8986
  const parent = await service.findRawParentDoc({
8856
8987
  filter: filter2,
8857
8988
  select: parentSelection(service, call),
8858
- populate: [],
8859
- lean: false
8989
+ populate: []
8860
8990
  });
8861
8991
  return parent ? { parent } : { error: denied2("not_found" /* NotFound */) };
8862
8992
  }
@@ -8905,18 +9035,17 @@ async function visibleMutationRows(service, call, parentId, rows) {
8905
9035
  const identity = { _id: parentId };
8906
9036
  const filter2 = await subdocumentRows(service, visibility.parent, identity, identity);
8907
9037
  if (filter2 === false) return [];
8908
- const parent = await service.findRawParentDoc({
9038
+ const parent = await getServiceExecutors(service).subdocumentVisibility({
8909
9039
  filter: filter2,
8910
9040
  select: parentSelection(service, call),
8911
- populate: [],
8912
- lean: true
9041
+ populate: []
8913
9042
  });
8914
9043
  if (!parent) return [];
8915
9044
  const selected = call.method === "create" ? {} : { _id: { $in: rows.map((row) => row._id) } };
8916
9045
  const read = await subdocumentRows(service, visibility.child, selected, selected, call.sub);
8917
9046
  const list = visibility.list ? await subdocumentRows(service, visibility.list, {}, {}, call.sub) : {};
8918
9047
  if (read === false || list === false) return [];
8919
- const visible = filterCollection((0, import_utils29.get)(parent, call.sub), intersectFilters(read, list));
9048
+ const visible = filterCollection((0, import_utils30.get)(parent, call.sub), intersectFilters(read, list));
8920
9049
  return await finalizeSubdocumentRows(service, call.output, parent, visible);
8921
9050
  } catch {
8922
9051
  return [];
@@ -8937,11 +9066,10 @@ async function listSub(service, id, sub, options) {
8937
9066
  const parent = await service.findRawParentDoc({
8938
9067
  filter: filter2,
8939
9068
  select: parentSelection(service, call),
8940
- populate: [],
8941
- lean: false
9069
+ populate: []
8942
9070
  });
8943
9071
  if (!parent) return denied2("not_found" /* NotFound */);
8944
- const rows = filterCollection((0, import_utils29.get)(parent, sub), childFilter);
9072
+ const rows = filterCollection((0, import_utils30.get)(parent, sub), childFilter);
8945
9073
  const data = await finalizeSubdocumentRows(service, call.output, parent, rows);
8946
9074
  return { success: true, kind: "list", code: "success" /* Success */, data, count: data.length };
8947
9075
  });
@@ -8960,11 +9088,10 @@ async function readSub(service, id, sub, subId, options) {
8960
9088
  const parent = await service.findRawParentDoc({
8961
9089
  filter: filter2,
8962
9090
  select: parentSelection(service, call),
8963
- populate: entries,
8964
- lean: false
9091
+ populate: entries
8965
9092
  });
8966
9093
  if (!parent) return denied2("not_found" /* NotFound */);
8967
- const row = findElement((0, import_utils29.get)(copySubdocumentParent(parent), sub), childFilter);
9094
+ const row = findElement((0, import_utils30.get)(copySubdocumentParent(parent), sub), childFilter);
8968
9095
  if (!row) return denied2("not_found" /* NotFound */);
8969
9096
  await service.finalizePopulateForSubParent({ [sub]: [row] }, entries, "subRead");
8970
9097
  const data = await finalizeSubdocumentRows(service, call.output, parent, [row]);
@@ -8984,7 +9111,7 @@ async function updateSub(service, persist, id, sub, subId, data, options) {
8984
9111
  const identity = { _id: subId };
8985
9112
  const filter2 = await subdocumentRows(service, call.child, identity, identity, sub);
8986
9113
  if (filter2 === false) return denied2();
8987
- const row = findElement((0, import_utils29.get)(parent, sub), filter2);
9114
+ const row = findElement((0, import_utils30.get)(parent, sub), filter2);
8988
9115
  if (!row) return denied2("not_found" /* NotFound */);
8989
9116
  const original = isolateDocForOutput(row);
8990
9117
  const admit = await inputAdmission(service, call, parent);
@@ -9011,7 +9138,7 @@ async function bulkUpdateSub(service, persist, id, sub, data, options) {
9011
9138
  const selected = { _id: { $in: data.map((row) => row._id) } };
9012
9139
  const filter2 = await subdocumentRows(service, call.child, selected, selected, sub);
9013
9140
  if (filter2 === false) return denied2();
9014
- const rows = filterCollection((0, import_utils29.get)(parent, sub), filter2);
9141
+ const rows = filterCollection((0, import_utils30.get)(parent, sub), filter2);
9015
9142
  const originals = rows.map((row) => isolateDocForOutput(row));
9016
9143
  const admit = await inputAdmission(service, call, parent);
9017
9144
  for (const [index, row] of rows.entries()) {
@@ -9039,7 +9166,7 @@ async function createSub(service, persist, id, sub, data, options) {
9039
9166
  const lookup = await mutationParent(service, id, call);
9040
9167
  if ("error" in lookup) return lookup.error;
9041
9168
  const { parent } = lookup;
9042
- const rows = (0, import_utils29.get)(parent, sub);
9169
+ const rows = (0, import_utils30.get)(parent, sub);
9043
9170
  const admit = await inputAdmission(service, call, parent);
9044
9171
  const allowed = (Array.isArray(data) ? data : [data]).map((row) => admit(row).allowedData);
9045
9172
  if (options?.addFirst) rows.unshift(...allowed);
@@ -9060,7 +9187,7 @@ async function deleteSub(service, persist, id, sub, subId, options) {
9060
9187
  const identity = { _id: subId };
9061
9188
  const filter2 = await subdocumentRows(service, call.child, identity, identity, sub);
9062
9189
  if (filter2 === false) return denied2();
9063
- const row = findElement((0, import_utils29.get)(parent, sub), filter2);
9190
+ const row = findElement((0, import_utils30.get)(parent, sub), filter2);
9064
9191
  if (!row) return denied2("not_found" /* NotFound */);
9065
9192
  await ("deleteOne" in row ? row.deleteOne?.() : row.remove?.());
9066
9193
  await persist(() => parent.save());
@@ -9069,7 +9196,7 @@ async function deleteSub(service, persist, id, sub, subId, options) {
9069
9196
  }
9070
9197
  async function getParentDoc(service, id, sub, args, options) {
9071
9198
  assertPublicAdmission({ args, options });
9072
- const { access = "read", lean = false } = options ?? {};
9199
+ const { access = "read" } = options ?? {};
9073
9200
  const identity = deepIsolateValue(await service.genIDFilter(id));
9074
9201
  const filter2 = intersectFilters(identity, await service.genFilter(access, deepIsolateValue(identity)));
9075
9202
  if (filter2 === false) return null;
@@ -9077,8 +9204,7 @@ async function getParentDoc(service, id, sub, args, options) {
9077
9204
  return service.findRawParentDoc({
9078
9205
  filter: filter2,
9079
9206
  select: access === "read" ? "" : sub,
9080
- populate,
9081
- lean
9207
+ populate
9082
9208
  });
9083
9209
  }
9084
9210
 
@@ -9108,8 +9234,7 @@ function resolveFindOneOptions(service, options = {}) {
9108
9234
  includePermissions,
9109
9235
  includeFieldPermissions: options.includeFieldPermissions ?? service.defaults.findOneOptions?.includeFieldPermissions ?? includePermissions,
9110
9236
  access: options.access ?? service.defaults.findOneOptions?.access ?? "read",
9111
- populateAccess: options.populateAccess ?? service.defaults.findOneOptions?.populateAccess,
9112
- lean: options.lean ?? service.defaults.findOneOptions?.lean ?? false
9237
+ populateAccess: options.populateAccess ?? service.defaults.findOneOptions?.populateAccess
9113
9238
  });
9114
9239
  }
9115
9240
  function resolveFindByIdArgs(service, args = {}) {
@@ -9126,8 +9251,7 @@ function resolveFindByIdOptions(service, options = {}) {
9126
9251
  includePermissions,
9127
9252
  includeFieldPermissions: options.includeFieldPermissions ?? service.defaults.findByIdOptions?.includeFieldPermissions ?? includePermissions,
9128
9253
  access: options.access ?? service.defaults.findByIdOptions?.access ?? "read",
9129
- populateAccess: options.populateAccess ?? service.defaults.findByIdOptions?.populateAccess,
9130
- lean: options.lean ?? service.defaults.findByIdOptions?.lean ?? false
9254
+ populateAccess: options.populateAccess ?? service.defaults.findByIdOptions?.populateAccess
9131
9255
  });
9132
9256
  }
9133
9257
  function resolveFindArgs(service, args = {}) {
@@ -9149,8 +9273,7 @@ function resolveFindOptions(service, options = {}) {
9149
9273
  includePermissions,
9150
9274
  includeFieldPermissions: options.includeFieldPermissions ?? service.defaults.findOptions?.includeFieldPermissions ?? includePermissions,
9151
9275
  includeCount: options.includeCount ?? service.defaults.findOptions?.includeCount ?? false,
9152
- populateAccess: options.populateAccess ?? service.defaults.findOptions?.populateAccess ?? "read",
9153
- lean: options.lean ?? service.defaults.findOptions?.lean ?? false
9276
+ populateAccess: options.populateAccess ?? service.defaults.findOptions?.populateAccess ?? "read"
9154
9277
  });
9155
9278
  }
9156
9279
  function resolveCreateArgs(service, args = {}) {
@@ -9264,7 +9387,7 @@ var Service = class extends Base {
9264
9387
  model: this.model.mongooseModel,
9265
9388
  modelName: this.modelName
9266
9389
  }),
9267
- configuration: () => this.requestRuntime.getModelInstance(this.modelName) ? captureModelAuthorizationConfiguration(this.requestRuntime, this.modelName) : { catalog: { paths: [] }, ...this.options },
9390
+ configuration: () => this.requestRuntime.getModelInstance(this.modelName) ? captureModelAuthorizationConfiguration(this.requestRuntime, this.modelName, this.options) : { catalog: { paths: [] }, ...this.options },
9268
9391
  permissions: () => this.requestCore.getPermissions?.() ?? new permission_default({}),
9269
9392
  parse: (filter2) => this.parseClientData(filter2, this.getCorrelatedExecState().scheduler),
9270
9393
  validate: (filter2, expanded) => {
@@ -9308,26 +9431,37 @@ var Service = class extends Base {
9308
9431
  data: await this.model.countDocuments(filter2),
9309
9432
  query: { filter: filter2 }
9310
9433
  }),
9311
- groupedCount: (filter2, field, input) => this.countPreparedByFieldValueGroups(field, input, filter2)
9434
+ groupedCount: (filter2, field, input) => this.countPreparedByFieldValueGroups(field, input, filter2),
9435
+ subdocumentVisibility: ({ filter: filter2, select, populate }) => this.model.findOne({ filter: filter2, select, populate, lean: true })
9312
9436
  });
9313
9437
  }
9314
9438
  get options() {
9315
9439
  return modelServiceOptions(this, () => this.getModelRouterOptions(this.modelName));
9316
9440
  }
9441
+ /**
9442
+ * Presentation/query defaults for this service instance; an explicit assignment
9443
+ * replaces the runtime defaults bag, not a per-bucket merge. Fetch mode belongs
9444
+ * to the owning model's hydration configuration and affects all its services.
9445
+ * Legacy method-option lean/hydration keys throw on assignment and before calls
9446
+ * if an assigned JavaScript bag is later mutated.
9447
+ */
9317
9448
  get defaults() {
9318
9449
  return this.defaultsOverride ?? this.options.defaults ?? {};
9319
9450
  }
9320
9451
  set defaults(value) {
9452
+ assertHydrationDefaults(value);
9321
9453
  this.defaultsOverride = value;
9322
9454
  }
9323
9455
  get baseFieldsExt() {
9324
9456
  return this.baseFields.concat(this.options.documentPermissionField);
9325
9457
  }
9458
+ /** Raw hydrated parent/null. Fetch mode is fixed, independent of model read settings. */
9326
9459
  findRawParentDoc(args) {
9327
9460
  return this.model.findOne({
9328
- ...args,
9329
9461
  filter: args.filter,
9330
- populate: args.populate
9462
+ select: args.select,
9463
+ populate: args.populate,
9464
+ lean: false
9331
9465
  });
9332
9466
  }
9333
9467
  createModelAdapter(modelName) {
@@ -9432,23 +9566,34 @@ var Service = class extends Base {
9432
9566
  }
9433
9567
  });
9434
9568
  const output = deepIsolateValue(finalized);
9569
+ removeGeneratedPermissionsAlias(output);
9435
9570
  const includeOrigins = restoreIncludeOutput(args.doc, output);
9436
9571
  const field = configuration.documentPermissionField ?? "_permissions";
9437
9572
  unsetDocPath(output, field);
9438
9573
  if (!configuration.stripPermissionsField) {
9439
- (0, import_utils30.set)(output, field, args.includePermissions || args.includeFieldPermissions ? deepIsolateValue(grants) : {});
9574
+ (0, import_utils31.set)(output, field, args.includePermissions || args.includeFieldPermissions ? deepIsolateValue(grants) : {});
9440
9575
  if (args.includeFieldPermissions && !configuration.disableFieldPermissions) {
9441
9576
  const rowAccess = this.asServiceHookContext(context).fieldPermissionAccess ?? await this.getFieldPermissionAccess([snapshot._id]);
9442
9577
  const id = String(snapshot._id);
9443
9578
  const views = rowAccess.readIds?.has(id) ? await requestOutputFieldPaths(handle, binding, "read") : [];
9444
9579
  const edits = rowAccess.updateIds?.has(id) ? await requestOutputFieldPaths(handle, binding, "update") : [];
9445
9580
  const map2 = (paths) => paths.length ? Object.fromEntries(paths.map((path) => [path, true])) : { $: "_" };
9446
- (0, import_utils30.set)(output, `${field}._view`, map2(views));
9447
- (0, import_utils30.set)(output, `${field}._edit`, map2(edits));
9448
- } else if (!args.includePermissions) this.addEmptyPermissions(output);
9449
- stripUnexposedDocPermissions(this.modelName, output);
9581
+ (0, import_utils31.set)(output, `${field}._view`, map2(views));
9582
+ (0, import_utils31.set)(output, `${field}._edit`, map2(edits));
9583
+ } else if (!args.includePermissions) (0, import_utils31.set)(output, field, { _view: { $: "_" }, _edit: { $: "_" } });
9584
+ const exposed = configuration.exposedDocPermissionKeys;
9585
+ if (exposed) {
9586
+ const metadata = (0, import_utils31.get)(output, field);
9587
+ (0, import_utils31.set)(
9588
+ output,
9589
+ field,
9590
+ Object.fromEntries(
9591
+ Object.entries(metadata).filter(([key]) => key === "_view" || key === "_edit" || exposed.includes(key))
9592
+ )
9593
+ );
9594
+ }
9595
+ attachPermissionsAlias(output, field);
9450
9596
  }
9451
- this.preservePermissionsVirtual(getIncludeOriginal(args.doc), output, args.lean);
9452
9597
  transferDocumentAuthorizationGraph(finalized, output, includeOrigins);
9453
9598
  return {
9454
9599
  data: output,
@@ -9663,36 +9808,6 @@ var Service = class extends Base {
9663
9808
  stripVirtualsFromFilterForSnapshot(filter2, snapshot) {
9664
9809
  return stripVirtualKeysFromFilter(filter2, snapshot);
9665
9810
  }
9666
- /**
9667
- * Preserve the `permissions` Mongoose virtual (from `permissionsPlugin`) for
9668
- * hydrated outputs. `isolateDocForOutput` uses `toObject({ virtuals: false })`
9669
- * so Mongoose getter virtuals never leak into package-virtual planning;
9670
- * `lean: true` therefore drops them (explicit parity rule). For `lean: false`
9671
- * (hydrated Mongoose documents) the historical contract exposes
9672
- * `doc.permissions` as an alias of the document-permission field. The shared
9673
- * finalizer keeps only the document-permission field, so restore the alias
9674
- * here for backward compatibility when the input was hydrated and the
9675
- * virtual existed. Lean outputs stay without the virtual. Models without
9676
- * the plugin never had the virtual and stay unchanged.
9677
- */
9678
- preservePermissionsVirtual(originalDoc, finalized, lean) {
9679
- try {
9680
- if (lean) return;
9681
- if (!isDocument2(originalDoc)) return;
9682
- const schema = originalDoc.schema;
9683
- if (!schema?.virtualpath("permissions")) return;
9684
- const docField = this.options?.documentPermissionField ?? "_permissions";
9685
- if (docField in finalized && !("permissions" in finalized)) {
9686
- Object.defineProperty(finalized, "permissions", {
9687
- value: finalized[docField],
9688
- enumerable: false,
9689
- writable: true,
9690
- configurable: true
9691
- });
9692
- }
9693
- } catch {
9694
- }
9695
- }
9696
9811
  /**
9697
9812
  * VIRT-05 populate + association helpers.
9698
9813
  *
@@ -9729,7 +9844,7 @@ var Service = class extends Base {
9729
9844
  return docs.map((doc) => {
9730
9845
  try {
9731
9846
  const plain = toObject(doc);
9732
- const val = (0, import_utils30.get)(plain, associationField);
9847
+ const val = (0, import_utils31.get)(plain, associationField);
9733
9848
  return deepIsolateValue(val);
9734
9849
  } catch {
9735
9850
  return void 0;
@@ -9826,7 +9941,7 @@ var Service = class extends Base {
9826
9941
  if (this.isScalarPopulateValue(rawTarget)) return rawTarget;
9827
9942
  const isDoc = (() => {
9828
9943
  try {
9829
- if ((0, import_utils30.isPlainObject)(rawTarget)) return true;
9944
+ if ((0, import_utils31.isPlainObject)(rawTarget)) return true;
9830
9945
  const maybe = rawTarget;
9831
9946
  if (maybe && typeof maybe === "object" && "_doc" in maybe) return true;
9832
9947
  if (maybe && typeof maybe.toObject === "function") return true;
@@ -9914,7 +10029,7 @@ var Service = class extends Base {
9914
10029
  child = getDocValue(current, key);
9915
10030
  if (child === void 0) {
9916
10031
  try {
9917
- child = (0, import_utils30.get)(current, key);
10032
+ child = (0, import_utils31.get)(current, key);
9918
10033
  } catch {
9919
10034
  return;
9920
10035
  }
@@ -10050,7 +10165,7 @@ var Service = class extends Base {
10050
10165
  async findOnePrepared(execution, filter2, args, options) {
10051
10166
  if (filter2 === false) return { success: false, kind: "error", code: "forbidden" /* Forbidden */, query: { filter: filter2 } };
10052
10167
  const { select: requestedSelect, sort, populate, include } = this.resolveFindOneArgs(args);
10053
- const { includePermissions, includeFieldPermissions, access, populateAccess, lean } = this.resolveFindOneOptions(options);
10168
+ const { includePermissions, includeFieldPermissions, access, populateAccess } = this.resolveFindOneOptions(options);
10054
10169
  const state = readServiceExecution(this, execution);
10055
10170
  const virtualSnapshot = readServiceAuthorization(state.authorization, state.binding).configuration;
10056
10171
  let processedInclude;
@@ -10112,7 +10227,7 @@ var Service = class extends Base {
10112
10227
  return { success: false, kind: "error", code: "bad_request" /* BadRequest */, errors: sortErrors, query };
10113
10228
  }
10114
10229
  }
10115
- let doc = await this.model.findOne({ ...query, select: dbSelect, lean });
10230
+ let doc = await this.model.findOne({ ...query, select: dbSelect, lean: state.hydration === "lean" });
10116
10231
  if (!doc) {
10117
10232
  this.completeOp("findOne", startedAt, "not_found" /* NotFound */, _filter);
10118
10233
  return { success: false, kind: "error", code: "not_found" /* NotFound */, query };
@@ -10126,7 +10241,7 @@ var Service = class extends Base {
10126
10241
  originalDocumentSnapshot: toObject(doc),
10127
10242
  resolvedQuery: query
10128
10243
  };
10129
- const correlatedSnapshots = [(0, import_utils30.cloneDeep)(toObject(doc))];
10244
+ const correlatedSnapshots = [(0, import_utils31.cloneDeep)(toObject(doc))];
10130
10245
  try {
10131
10246
  doc = await this.includeDocs(doc, includes, state.authorization);
10132
10247
  if (correlatedIncludes.length > 0) {
@@ -10175,7 +10290,6 @@ var Service = class extends Base {
10175
10290
  context,
10176
10291
  includePermissions,
10177
10292
  includeFieldPermissions,
10178
- lean,
10179
10293
  sharedGate: findOneGate
10180
10294
  });
10181
10295
  } catch (error2) {
@@ -10200,7 +10314,7 @@ var Service = class extends Base {
10200
10314
  try {
10201
10315
  this.admitServiceCall(args, options);
10202
10316
  const { select, populate, include } = this.resolveFindByIdArgs(args);
10203
- const { skim, includePermissions, includeFieldPermissions, access, populateAccess, lean } = this.resolveFindByIdOptions(options);
10317
+ const { skim, includePermissions, includeFieldPermissions, access, populateAccess } = this.resolveFindByIdOptions(options);
10204
10318
  const execution = createServiceExecution(
10205
10319
  this,
10206
10320
  {
@@ -10212,7 +10326,11 @@ var Service = class extends Base {
10212
10326
  },
10213
10327
  options?.authorization,
10214
10328
  "service",
10215
- this.captureRelated(args, this.defaults.findByIdArgs)
10329
+ this.captureRelated(args, this.defaults.findByIdArgs),
10330
+ void 0,
10331
+ void 0,
10332
+ void 0,
10333
+ "findById"
10216
10334
  );
10217
10335
  const filter2 = readModelIdentifier(this, execution, await resolveModelIdentifier(this, execution, id));
10218
10336
  const query = await prepareModelQuery(this, execution, { kind: "client-read", filter: filter2 });
@@ -10225,7 +10343,7 @@ var Service = class extends Base {
10225
10343
  populate,
10226
10344
  include
10227
10345
  },
10228
- { skim, includePermissions, includeFieldPermissions, access, populateAccess, lean }
10346
+ { skim, includePermissions, includeFieldPermissions, access, populateAccess }
10229
10347
  );
10230
10348
  } catch (error2) {
10231
10349
  const result2 = this.getClientRequestErrorResult(error2);
@@ -10271,7 +10389,7 @@ var Service = class extends Base {
10271
10389
  page,
10272
10390
  pageSize
10273
10391
  } = this.resolveFindArgs(args);
10274
- const { includePermissions, includeFieldPermissions, includeCount, populateAccess, lean } = this.resolveFindOptions(options);
10392
+ const { includePermissions, includeFieldPermissions, includeCount, populateAccess } = this.resolveFindOptions(options);
10275
10393
  let processedInclude;
10276
10394
  try {
10277
10395
  processedInclude = this.processInclude(include);
@@ -10302,7 +10420,7 @@ var Service = class extends Base {
10302
10420
  const findAssociationField = this.getAssociationFieldFromOptions(options);
10303
10421
  const withAssocSelect = findAssociationField && !finalSelect.includes(findAssociationField) ? [...finalSelect, findAssociationField] : finalSelect;
10304
10422
  const dbSelect = this.buildDbSelectForAssociation(withAssocSelect, findAssociationField);
10305
- const filteredPopulate = (0, import_utils30.isArray)(withAssocSelect) && (0, import_utils30.isArray)(_populate) ? _populate.filter(
10423
+ const filteredPopulate = (0, import_utils31.isArray)(withAssocSelect) && (0, import_utils31.isArray)(_populate) ? _populate.filter(
10306
10424
  (p) => withAssocSelect.some(
10307
10425
  (field) => field === p.path || field.startsWith(`${p.path}.`) || p.path.startsWith(`${field}.`)
10308
10426
  )
@@ -10346,10 +10464,10 @@ var Service = class extends Base {
10346
10464
  ...query,
10347
10465
  select: dbSelect,
10348
10466
  hardLimit: this.options.listHardLimit,
10349
- lean
10467
+ lean: state.hydration === "lean"
10350
10468
  });
10351
10469
  const capturedAssociation = findAssociationField ? this.captureAssociationValues(docs, findAssociationField) : void 0;
10352
- const correlatedSnapshots = docs.map((doc) => (0, import_utils30.cloneDeep)(toObject(doc)));
10470
+ const correlatedSnapshots = docs.map((doc) => (0, import_utils31.cloneDeep)(toObject(doc)));
10353
10471
  try {
10354
10472
  docs = await this.includeDocs(docs, includes, state.authorization);
10355
10473
  if (correlatedIncludes.length > 0) {
@@ -10421,7 +10539,6 @@ var Service = class extends Base {
10421
10539
  context: contexts[i],
10422
10540
  includePermissions,
10423
10541
  includeFieldPermissions,
10424
- lean,
10425
10542
  sharedGate,
10426
10543
  privateAssociationField
10427
10544
  });
@@ -10543,12 +10660,12 @@ var Service = class extends Base {
10543
10660
  context.allowedFields = allowedFields;
10544
10661
  context.allowedData = allowedData;
10545
10662
  const validated = await this.validate(allowedData, "create", context);
10546
- if ((0, import_utils30.isBoolean)(validated)) {
10663
+ if ((0, import_utils31.isBoolean)(validated)) {
10547
10664
  if (!validated) {
10548
10665
  validationErrors.push({ index, errors: [] });
10549
10666
  return void 0;
10550
10667
  }
10551
- } else if ((0, import_utils30.isArray)(validated)) {
10668
+ } else if ((0, import_utils31.isArray)(validated)) {
10552
10669
  if (validated.length > 0) {
10553
10670
  validationErrors.push({
10554
10671
  index,
@@ -10611,7 +10728,6 @@ var Service = class extends Base {
10611
10728
  context: contexts[index],
10612
10729
  includePermissions,
10613
10730
  includeFieldPermissions,
10614
- lean: false,
10615
10731
  sharedGate: createGate
10616
10732
  });
10617
10733
  outputContexts[index] = output.context;
@@ -10674,8 +10790,7 @@ var Service = class extends Base {
10674
10790
  doc: data,
10675
10791
  plan: newPlan,
10676
10792
  context: newContext,
10677
- includePermissions,
10678
- lean: false
10793
+ includePermissions
10679
10794
  });
10680
10795
  return {
10681
10796
  success: true,
@@ -10751,7 +10866,7 @@ var Service = class extends Base {
10751
10866
  }
10752
10867
  let doc = await this.model.findOne({
10753
10868
  filter: _filter,
10754
- select: (0, import_utils30.uniq)([...updatePlan.persistedFetchSelection, ...inputFetchPaths(captured.configuration.catalog)]).map(
10869
+ select: (0, import_utils31.uniq)([...updatePlan.persistedFetchSelection, ...inputFetchPaths(captured.configuration.catalog)]).map(
10755
10870
  (path) => `+${path}`
10756
10871
  )
10757
10872
  });
@@ -10790,12 +10905,12 @@ var Service = class extends Base {
10790
10905
  context.allowedFields = allowedFields;
10791
10906
  context.allowedData = allowedData;
10792
10907
  const validated = await this.validate(allowedData, "update", context);
10793
- if ((0, import_utils30.isBoolean)(validated)) {
10908
+ if ((0, import_utils31.isBoolean)(validated)) {
10794
10909
  if (!validated) {
10795
10910
  this.completeOp("updateOne", startedAt, "bad_request" /* BadRequest */, _filter);
10796
10911
  return { success: false, kind: "error", code: "bad_request" /* BadRequest */ };
10797
10912
  }
10798
- } else if ((0, import_utils30.isArray)(validated)) {
10913
+ } else if ((0, import_utils31.isArray)(validated)) {
10799
10914
  if (validated.length > 0) {
10800
10915
  this.completeOp("updateOne", startedAt, "bad_request" /* BadRequest */, _filter);
10801
10916
  return { success: false, kind: "error", code: "bad_request" /* BadRequest */, errors: validated };
@@ -10815,10 +10930,10 @@ var Service = class extends Base {
10815
10930
  const diffExcludeFields = [this.options.documentPermissionField, "__v"];
10816
10931
  this.asServiceHookContext(context).diff = (d) => {
10817
10932
  context.changes = (0, import_just_diff.diff)(
10818
- (0, import_utils30.omit)(context.originalDocumentSnapshot, diffExcludeFields),
10819
- (0, import_utils30.omit)(d.toObject({ virtuals: false }), diffExcludeFields)
10933
+ (0, import_utils31.omit)(context.originalDocumentSnapshot, diffExcludeFields),
10934
+ (0, import_utils31.omit)(d.toObject({ virtuals: false }), diffExcludeFields)
10820
10935
  ) || [];
10821
- context.modifiedPaths = (0, import_utils30.uniq)(context.changes.map((di) => di.path.length > 0 ? String(di.path[0]) : ""));
10936
+ context.modifiedPaths = (0, import_utils31.uniq)(context.changes.map((di) => di.path.length > 0 ? String(di.path[0]) : ""));
10822
10937
  };
10823
10938
  doc = assertModelDocument(await this.afterPersist(doc, "update", context), this.modelName, "afterPersist");
10824
10939
  context.currentDocument = doc;
@@ -10843,8 +10958,7 @@ var Service = class extends Base {
10843
10958
  plan: updatePlan,
10844
10959
  context,
10845
10960
  includePermissions,
10846
- includeFieldPermissions,
10847
- lean: false
10961
+ includeFieldPermissions
10848
10962
  });
10849
10963
  const outputDoc = decorate ? await this.hookGate.run(() => decorate(output.data, output.context)) : output.data;
10850
10964
  this.completeOp("updateOne", startedAt, "success" /* Success */, _filter);
@@ -11363,7 +11477,7 @@ var Service = class extends Base {
11363
11477
  return resolveExistsOptions(this, options);
11364
11478
  }
11365
11479
  async getFieldPermissionAccess(ids) {
11366
- const uniqueIds = (0, import_utils30.compact)((0, import_utils30.uniqBy)(ids, (id) => String(id)).map((id) => String(id)));
11480
+ const uniqueIds = (0, import_utils31.compact)((0, import_utils31.uniqBy)(ids, (id) => String(id)).map((id) => String(id)));
11367
11481
  if (uniqueIds.length === 0) {
11368
11482
  return {
11369
11483
  readIds: /* @__PURE__ */ new Set(),
@@ -11409,7 +11523,7 @@ var Service = class extends Base {
11409
11523
  * (direct/root-entry 200); count measures visible rows, not all updated rows.
11410
11524
  */
11411
11525
  async bulkUpdateSub(id, sub, data, options) {
11412
- return bulkUpdateSub(this, this.persist, id, sub, (0, import_utils30.castArray)(data), options);
11526
+ return bulkUpdateSub(this, this.persist, id, sub, (0, import_utils31.castArray)(data), options);
11413
11527
  }
11414
11528
  /**
11415
11529
  * Append/prepend admitted rows, then return the visible full array (including when
@@ -11426,14 +11540,16 @@ var Service = class extends Base {
11426
11540
  async deleteSub(id, sub, subId, options) {
11427
11541
  return deleteSub(this, this.persist, id, sub, subId, options);
11428
11542
  }
11543
+ /** Raw hydrated parent/null, with row policy and populate; no finalized permission metadata. */
11429
11544
  async getParentDoc(id, sub, args, options) {
11430
11545
  return getParentDoc(this, id, sub, args, options);
11431
11546
  }
11432
11547
  };
11433
11548
 
11434
11549
  // src/services/public-service.ts
11435
- var import_utils31 = require("@web-ts-toolkit/utils");
11550
+ var import_utils32 = require("@web-ts-toolkit/utils");
11436
11551
  init_helpers();
11552
+ init_permissions_alias();
11437
11553
  init_public_admission();
11438
11554
  var PublicService = class extends Service {
11439
11555
  /** Public dispatch stays request-only even for JS callers and transformed envelopes. */
@@ -11471,36 +11587,61 @@ var PublicService = class extends Service {
11471
11587
  const admission = this.admitPublicCall({ args, options, filter: filter2 });
11472
11588
  if (admission) return admission;
11473
11589
  const { select, populate, include, sort, skip, limit, page, pageSize, tasks } = this.resolvePublicListArgs(args);
11474
- const { skim, includePermissions, includeFieldPermissions, includeCount, populateAccess, lean } = this.resolvePublicListOptions(options);
11475
- const result2 = await this.find(
11476
- filter2,
11477
- { select, populate, include, sort, skip, limit, page, pageSize },
11478
- requestOnlyServiceOptions({
11479
- skim,
11480
- includePermissions,
11481
- includeFieldPermissions,
11482
- includeCount,
11483
- populateAccess,
11484
- lean
11485
- }),
11486
- async (doc, context) => {
11487
- doc = toObject(doc);
11488
- return this.decorate(doc, "list", context);
11590
+ const { skim, includePermissions, includeFieldPermissions, includeCount, populateAccess } = this.resolvePublicListOptions(options);
11591
+ try {
11592
+ const execution = withExecutionHydration(
11593
+ this,
11594
+ createServiceExecution(
11595
+ this,
11596
+ {
11597
+ operation: "list",
11598
+ rowAccess: "list",
11599
+ virtualAccess: "list",
11600
+ outputAccess: "list",
11601
+ docPermissionsAccess: "list"
11602
+ },
11603
+ requestOnlyServiceOptions({}).authorization,
11604
+ "service",
11605
+ this.captureRelated({ populate, include }, this.defaults.findArgs)
11606
+ ),
11607
+ "publicList"
11608
+ );
11609
+ const query = await prepareModelQuery(this, execution, { kind: "client-read", filter: filter2 });
11610
+ const result2 = await executePreparedFind(
11611
+ this,
11612
+ execution,
11613
+ query,
11614
+ { select, populate, include, sort, skip, limit, page, pageSize },
11615
+ requestOnlyServiceOptions({
11616
+ skim,
11617
+ includePermissions,
11618
+ includeFieldPermissions,
11619
+ includeCount,
11620
+ populateAccess
11621
+ }),
11622
+ async (doc, context) => {
11623
+ doc = toObject(doc);
11624
+ return this.decorate(doc, "list", context);
11625
+ }
11626
+ );
11627
+ if (!result2.success) {
11628
+ return result2;
11489
11629
  }
11490
- );
11491
- if (!result2.success) {
11492
- return result2;
11630
+ const docs = await this.decorateAll(result2.data, "list", {
11631
+ mongooseModel: this.model.mongooseModel,
11632
+ modelName: this.modelName,
11633
+ operation: "list",
11634
+ resolvedQuery: result2.query
11635
+ });
11636
+ const transformedDocs = docs.map(
11637
+ (row) => this.runTasks(row, tasks)
11638
+ );
11639
+ return { ...result2, data: transformedDocs };
11640
+ } catch (error2) {
11641
+ const result2 = this.getClientRequestErrorResult(error2);
11642
+ if (result2) return result2;
11643
+ throw error2;
11493
11644
  }
11494
- const docs = await this.decorateAll(result2.data, "list", {
11495
- mongooseModel: this.model.mongooseModel,
11496
- modelName: this.modelName,
11497
- operation: "list",
11498
- resolvedQuery: result2.query
11499
- });
11500
- const transformedDocs = docs.map(
11501
- (row) => this.runTasks(row, tasks)
11502
- );
11503
- return { ...result2, data: transformedDocs };
11504
11645
  }
11505
11646
  async _create(data, args, options) {
11506
11647
  const admission = this.admitPublicCall({ args, options, data });
@@ -11516,7 +11657,7 @@ var PublicService = class extends Service {
11516
11657
  let d = toObject(doc);
11517
11658
  d = await this.decorate(d, "create", context);
11518
11659
  d = this.runTasks(d, tasks);
11519
- if (select) d = (0, import_utils31.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]);
11660
+ if (select) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
11520
11661
  return d;
11521
11662
  }
11522
11663
  );
@@ -11537,21 +11678,25 @@ var PublicService = class extends Service {
11537
11678
  const admission = this.admitPublicCall({ args, options });
11538
11679
  if (admission) return admission;
11539
11680
  const { select, populate, include, tasks } = this.resolvePublicReadArgs(args);
11540
- const { skim, includePermissions, includeFieldPermissions, tryList, populateAccess, lean } = this.resolvePublicReadOptions(options);
11681
+ const { skim, includePermissions, includeFieldPermissions, tryList, populateAccess } = this.resolvePublicReadOptions(options);
11541
11682
  try {
11542
11683
  let access = "read";
11543
- let execution = createServiceExecution(
11684
+ let execution = withExecutionHydration(
11544
11685
  this,
11545
- {
11546
- operation: "read",
11547
- rowAccess: access,
11548
- virtualAccess: access,
11549
- outputAccess: access,
11550
- docPermissionsAccess: access
11551
- },
11552
- requestOnlyServiceOptions({}).authorization,
11553
- "service",
11554
- this.captureRelated({ populate, include }, this.defaults.findOneArgs)
11686
+ createServiceExecution(
11687
+ this,
11688
+ {
11689
+ operation: "read",
11690
+ rowAccess: access,
11691
+ virtualAccess: access,
11692
+ outputAccess: access,
11693
+ docPermissionsAccess: access
11694
+ },
11695
+ requestOnlyServiceOptions({}).authorization,
11696
+ "service",
11697
+ this.captureRelated({ populate, include }, this.defaults.findOneArgs)
11698
+ ),
11699
+ "publicRead"
11555
11700
  );
11556
11701
  const identifier = await resolveModelIdentifier(this, execution, id);
11557
11702
  const query = await prepareModelQuery(this, execution, {
@@ -11563,7 +11708,7 @@ var PublicService = class extends Service {
11563
11708
  execution,
11564
11709
  query,
11565
11710
  { select, populate, include },
11566
- requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess, lean })
11711
+ requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess })
11567
11712
  );
11568
11713
  if (!result2.success && (result2.code === "bad_request" /* BadRequest */ || result2.code === "forbidden" /* Forbidden */)) return result2;
11569
11714
  if (tryList && (!result2.success || !result2.data)) {
@@ -11593,8 +11738,7 @@ var PublicService = class extends Service {
11593
11738
  includePermissions,
11594
11739
  includeFieldPermissions,
11595
11740
  access,
11596
- populateAccess,
11597
- lean
11741
+ populateAccess
11598
11742
  })
11599
11743
  );
11600
11744
  }
@@ -11615,43 +11759,79 @@ var PublicService = class extends Service {
11615
11759
  const admission = this.admitPublicCall({ args, options, filter: filter2 });
11616
11760
  if (admission) return admission;
11617
11761
  const { select, sort, populate, include, tasks } = this.resolvePublicReadFilterArgs(args);
11618
- const { skim, includePermissions, includeFieldPermissions, tryList, populateAccess, lean } = this.resolvePublicReadOptions(options);
11762
+ const { skim, includePermissions, includeFieldPermissions, tryList, populateAccess } = this.resolvePublicReadOptions(options);
11619
11763
  let access = "read";
11620
- let result2 = await this.findOne(
11621
- filter2,
11622
- {
11623
- select,
11624
- sort,
11625
- populate,
11626
- include
11627
- },
11628
- requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess, lean })
11629
- );
11630
- if (!result2.success && (result2.code === "bad_request" /* BadRequest */ || result2.code === "forbidden" /* Forbidden */)) return result2;
11631
- if (tryList && (!result2.success || !result2.data)) {
11632
- const listAllowed = await this.requestCore.isAllowed(this.modelName, "list");
11633
- if (!listAllowed) {
11634
- return { success: false, kind: "error", code: "unauthorized" /* Unauthorized */, errors: ["Unauthorized"] };
11635
- }
11636
- access = "list";
11637
- result2 = await this.findOne(
11638
- filter2,
11764
+ try {
11765
+ let execution = withExecutionHydration(
11766
+ this,
11767
+ createServiceExecution(
11768
+ this,
11769
+ {
11770
+ operation: "read",
11771
+ rowAccess: access,
11772
+ virtualAccess: access,
11773
+ outputAccess: access,
11774
+ docPermissionsAccess: access
11775
+ },
11776
+ requestOnlyServiceOptions({}).authorization,
11777
+ "service",
11778
+ this.captureRelated({ populate, include }, this.defaults.findOneArgs)
11779
+ ),
11780
+ "publicRead"
11781
+ );
11782
+ const query = await prepareModelQuery(this, execution, { kind: "client-read", filter: filter2 });
11783
+ let result2 = await executePreparedFindOne(
11784
+ this,
11785
+ execution,
11786
+ query,
11639
11787
  {
11640
11788
  select,
11641
11789
  sort,
11642
11790
  populate,
11643
11791
  include
11644
11792
  },
11645
- requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess, lean })
11793
+ requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess })
11646
11794
  );
11795
+ if (!result2.success && (result2.code === "bad_request" /* BadRequest */ || result2.code === "forbidden" /* Forbidden */)) return result2;
11796
+ if (tryList && (!result2.success || !result2.data)) {
11797
+ const listAllowed = await this.requestCore.isAllowed(this.modelName, "list");
11798
+ if (!listAllowed) {
11799
+ return { success: false, kind: "error", code: "unauthorized" /* Unauthorized */, errors: ["Unauthorized"] };
11800
+ }
11801
+ access = "list";
11802
+ execution = deriveServiceExecution(this, execution, {
11803
+ operation: "read",
11804
+ rowAccess: access,
11805
+ virtualAccess: access,
11806
+ outputAccess: access,
11807
+ docPermissionsAccess: access
11808
+ });
11809
+ const fallback = await prepareModelQuery(this, execution, { kind: "client-read", filter: filter2 });
11810
+ result2 = await executePreparedFindOne(
11811
+ this,
11812
+ execution,
11813
+ fallback,
11814
+ {
11815
+ select,
11816
+ sort,
11817
+ populate,
11818
+ include
11819
+ },
11820
+ requestOnlyServiceOptions({ skim, includePermissions, includeFieldPermissions, access, populateAccess })
11821
+ );
11822
+ }
11823
+ if (!result2.success) {
11824
+ return result2;
11825
+ }
11826
+ let doc = toObject(result2.data);
11827
+ doc = await this.decorate(doc, access, result2.context);
11828
+ doc = this.runTasks(doc, tasks);
11829
+ return { ...result2, data: doc };
11830
+ } catch (error2) {
11831
+ const result2 = this.getClientRequestErrorResult(error2);
11832
+ if (result2) return result2;
11833
+ throw error2;
11647
11834
  }
11648
- if (!result2.success) {
11649
- return result2;
11650
- }
11651
- let doc = toObject(result2.data);
11652
- doc = await this.decorate(doc, access, result2.context);
11653
- doc = this.runTasks(doc, tasks);
11654
- return { ...result2, data: doc };
11655
11835
  }
11656
11836
  async _update(id, data, args, options) {
11657
11837
  const admission = this.admitPublicCall({ args, options, data });
@@ -11672,8 +11852,8 @@ var PublicService = class extends Service {
11672
11852
  let d = toObject(doc);
11673
11853
  d = await this.decorate(d, "update", context);
11674
11854
  d = this.runTasks(d, tasks);
11675
- if (select) d = (0, import_utils31.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]);
11676
- else if (!returningAll) d = (0, import_utils31.pick)(d, [...Object.keys(data), "_id"]);
11855
+ if (select) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
11856
+ else if (!returningAll) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...Object.keys(data), "_id"]));
11677
11857
  return d;
11678
11858
  }
11679
11859
  );
@@ -11753,8 +11933,8 @@ var PublicService = class extends Service {
11753
11933
  let d = toObject(doc);
11754
11934
  d = await this.decorate(d, "update", context);
11755
11935
  d = this.runTasks(d, tasks2);
11756
- if (select2) d = (0, import_utils31.pick)(d, [...normalizeSelect(select2), ...this.baseFieldsExt]);
11757
- else if (!returningAll) d = (0, import_utils31.pick)(d, [...Object.keys(otherData), "_id"]);
11936
+ if (select2) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...normalizeSelect(select2), ...this.baseFieldsExt]));
11937
+ else if (!returningAll) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...Object.keys(otherData), "_id"]));
11758
11938
  return d;
11759
11939
  }
11760
11940
  );
@@ -11783,7 +11963,7 @@ var PublicService = class extends Service {
11783
11963
  let d = toObject(doc);
11784
11964
  d = await this.decorate(d, "create", context);
11785
11965
  d = this.runTasks(d, tasks);
11786
- if (select) d = (0, import_utils31.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]);
11966
+ if (select) d = copyPermissionsAlias(d, (0, import_utils32.pick)(d, [...normalizeSelect(select), ...this.baseFieldsExt]));
11787
11967
  return d;
11788
11968
  }
11789
11969
  );
@@ -11844,8 +12024,7 @@ var PublicService = class extends Service {
11844
12024
  includePermissions,
11845
12025
  includeFieldPermissions: options.includeFieldPermissions ?? this.defaults.publicListOptions?.includeFieldPermissions ?? includePermissions,
11846
12026
  includeCount: options.includeCount ?? this.defaults.publicListOptions?.includeCount ?? false,
11847
- populateAccess: options.populateAccess ?? this.defaults.publicListOptions?.populateAccess ?? "read",
11848
- lean: options.lean ?? this.defaults.publicListOptions?.lean ?? true
12027
+ populateAccess: options.populateAccess ?? this.defaults.publicListOptions?.populateAccess ?? "read"
11849
12028
  };
11850
12029
  }
11851
12030
  resolvePublicCreateArgs(args = {}) {
@@ -11886,8 +12065,7 @@ var PublicService = class extends Service {
11886
12065
  includePermissions,
11887
12066
  includeFieldPermissions: options.includeFieldPermissions ?? this.defaults.publicReadOptions?.includeFieldPermissions ?? includePermissions,
11888
12067
  tryList: options.tryList ?? this.defaults.publicReadOptions?.tryList ?? true,
11889
- populateAccess: options.populateAccess ?? this.defaults.publicReadOptions?.populateAccess,
11890
- lean: options.lean ?? this.defaults.publicReadOptions?.lean ?? false
12068
+ populateAccess: options.populateAccess ?? this.defaults.publicReadOptions?.populateAccess
11891
12069
  };
11892
12070
  }
11893
12071
  resolvePublicUpdateArgs(args = {}) {
@@ -11913,7 +12091,7 @@ var PublicService = class extends Service {
11913
12091
  init_options();
11914
12092
  init_data_values();
11915
12093
  init_helpers();
11916
- var import_utils32 = require("@web-ts-toolkit/utils");
12094
+ var import_utils33 = require("@web-ts-toolkit/utils");
11917
12095
  init_request_complexity();
11918
12096
  init_runtime_context();
11919
12097
  init_runtime();
@@ -11942,7 +12120,7 @@ var DataService = class {
11942
12120
  let doc = await findElement(this.data, _filter);
11943
12121
  if (!doc) return { success: false, kind: "error", code: "not_found" /* NotFound */, query };
11944
12122
  doc = await this.trimOutputFields(doc, access);
11945
- if (_select.length > 0) doc = (0, import_utils32.pick)(doc, _select);
12123
+ if (_select.length > 0) doc = (0, import_utils33.pick)(doc, _select);
11946
12124
  return {
11947
12125
  success: true,
11948
12126
  kind: "single",
@@ -11988,13 +12166,13 @@ var DataService = class {
11988
12166
  const totalCount = docs.length;
11989
12167
  if (sort) {
11990
12168
  const normalizedSort = normalizeSortForOrderBy(sort);
11991
- docs = (0, import_utils32.orderBy)(docs, normalizedSort.fields, normalizedSort.orders);
12169
+ docs = (0, import_utils33.orderBy)(docs, normalizedSort.fields, normalizedSort.orders);
11992
12170
  }
11993
12171
  const pagedDocs = docs.slice(query.skip, query.limit && query.skip + query.limit);
11994
12172
  const { maxHookConcurrency } = this.getRequestComplexity();
11995
12173
  const trimmed = await mapWithConcurrencyLimit(pagedDocs, maxHookConcurrency, async (doc) => {
11996
12174
  doc = await this.trimOutputFields(doc, "list");
11997
- if (_select.length > 0) doc = (0, import_utils32.pick)(doc, _select);
12175
+ if (_select.length > 0) doc = (0, import_utils33.pick)(doc, _select);
11998
12176
  return copyDataValue(doc);
11999
12177
  });
12000
12178
  if (!hasExplicitLimit && trimmed.length === totalCount) {
@@ -12069,7 +12247,13 @@ var DataService = class {
12069
12247
  init_helpers();
12070
12248
 
12071
12249
  // src/processors.ts
12072
- var import_utils33 = require("@web-ts-toolkit/utils");
12250
+ var import_utils34 = require("@web-ts-toolkit/utils");
12251
+ init_permissions_alias();
12252
+ function cloneProcessorValue(value) {
12253
+ const copy = (0, import_utils34.cloneDeep)(value);
12254
+ copyPermissionsAliasGraph(value, copy);
12255
+ return copy;
12256
+ }
12073
12257
  var UNSAFE_PATH_KEYS = /* @__PURE__ */ new Set(["__proto__", "prototype", "constructor"]);
12074
12258
  var DEFAULT_MAX_SLICE = 1e3;
12075
12259
  var DEFAULT_MASK_REPLACEMENT = "***";
@@ -12104,10 +12288,10 @@ function resolveLeafParents(obj, src) {
12104
12288
  for (let ind = 0; ind < segs.length - 1; ind += 1) {
12105
12289
  const seg = segs[ind];
12106
12290
  targets = targets.reduce((ret, target) => {
12107
- if (!(0, import_utils33.isPlainObject)(target)) return ret;
12291
+ if (!(0, import_utils34.isPlainObject)(target)) return ret;
12108
12292
  const targetObject = target;
12109
12293
  const next = targetObject[seg];
12110
- if ((0, import_utils33.isArray)(next)) {
12294
+ if ((0, import_utils34.isArray)(next)) {
12111
12295
  for (const item of next) {
12112
12296
  ret.push(item);
12113
12297
  }
@@ -12117,8 +12301,8 @@ function resolveLeafParents(obj, src) {
12117
12301
  }
12118
12302
  const leaf = segs[segs.length - 1];
12119
12303
  const pairs = [];
12120
- (0, import_utils33.forEach)(targets, (target) => {
12121
- if (!(0, import_utils33.isPlainObject)(target)) return;
12304
+ (0, import_utils34.forEach)(targets, (target) => {
12305
+ if (!(0, import_utils34.isPlainObject)(target)) return;
12122
12306
  pairs.push({ parent: target, leaf });
12123
12307
  });
12124
12308
  return pairs;
@@ -12126,8 +12310,8 @@ function resolveLeafParents(obj, src) {
12126
12310
  var copyAndDepopulate = (docObject, operations, options = { mutable: true, idField: "_id" }) => {
12127
12311
  const mutable = options.mutable !== false;
12128
12312
  const idField = options.idField ?? "_id";
12129
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12130
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12313
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12314
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12131
12315
  if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
12132
12316
  const src = op.src;
12133
12317
  const dest = op.dest;
@@ -12136,19 +12320,19 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
12136
12320
  assertSafePath(dest);
12137
12321
  let targets = [obj];
12138
12322
  const segs = src.split(".");
12139
- (0, import_utils33.forEach)(segs, (seg, ind) => {
12323
+ (0, import_utils34.forEach)(segs, (seg, ind) => {
12140
12324
  if (segs.length === ind + 1) {
12141
- (0, import_utils33.forEach)(targets, (target) => {
12142
- if (!(0, import_utils33.isPlainObject)(target)) return;
12325
+ (0, import_utils34.forEach)(targets, (target) => {
12326
+ if (!(0, import_utils34.isPlainObject)(target)) return;
12143
12327
  const targetObject = target;
12144
12328
  const leaf = targetObject[seg];
12145
12329
  const sourceForDest = leaf;
12146
12330
  let depopulated;
12147
- if ((0, import_utils33.isArray)(leaf)) {
12331
+ if ((0, import_utils34.isArray)(leaf)) {
12148
12332
  if (leaf.length === 0) {
12149
12333
  depopulated = [];
12150
- } else if (leaf.every((item) => (0, import_utils33.isPlainObject)(item))) {
12151
- depopulated = (0, import_utils33.map)(leaf, idField).map((id, i) => {
12334
+ } else if (leaf.every((item) => (0, import_utils34.isPlainObject)(item))) {
12335
+ depopulated = (0, import_utils34.map)(leaf, idField).map((id, i) => {
12152
12336
  if (id === void 0) {
12153
12337
  failMissingId(`${src}[${i}]`);
12154
12338
  }
@@ -12157,8 +12341,8 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
12157
12341
  } else {
12158
12342
  return;
12159
12343
  }
12160
- } else if ((0, import_utils33.isPlainObject)(leaf)) {
12161
- const id = (0, import_utils33.get)(leaf, idField);
12344
+ } else if ((0, import_utils34.isPlainObject)(leaf)) {
12345
+ const id = (0, import_utils34.get)(leaf, idField);
12162
12346
  if (id === void 0) {
12163
12347
  failMissingId(src);
12164
12348
  }
@@ -12166,15 +12350,15 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
12166
12350
  } else {
12167
12351
  return;
12168
12352
  }
12169
- (0, import_utils33.set)(targetObject, dest, sourceForDest);
12170
- (0, import_utils33.set)(targetObject, seg, depopulated);
12353
+ (0, import_utils34.set)(targetObject, dest, sourceForDest);
12354
+ (0, import_utils34.set)(targetObject, seg, depopulated);
12171
12355
  });
12172
12356
  } else {
12173
12357
  targets = targets.reduce((ret, target) => {
12174
- if (!(0, import_utils33.isPlainObject)(target)) return ret;
12358
+ if (!(0, import_utils34.isPlainObject)(target)) return ret;
12175
12359
  const targetObject = target;
12176
12360
  const next = targetObject[seg];
12177
- if ((0, import_utils33.isArray)(next)) {
12361
+ if ((0, import_utils34.isArray)(next)) {
12178
12362
  for (const item of next) {
12179
12363
  ret.push(item);
12180
12364
  }
@@ -12188,8 +12372,8 @@ var copyAndDepopulate = (docObject, operations, options = { mutable: true, idFie
12188
12372
  };
12189
12373
  var copyPaths = (docObject, operations, options = { mutable: true }) => {
12190
12374
  const mutable = options.mutable !== false;
12191
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12192
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12375
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12376
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12193
12377
  if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
12194
12378
  const src = op.src;
12195
12379
  const dest = op.dest;
@@ -12197,17 +12381,17 @@ var copyPaths = (docObject, operations, options = { mutable: true }) => {
12197
12381
  assertSafePath(src, "copyPaths");
12198
12382
  assertSafePath(dest, "copyPaths");
12199
12383
  if (src === dest) return;
12200
- (0, import_utils33.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12201
- if (!(0, import_utils33.hasOwn)(parent, leaf)) return;
12202
- (0, import_utils33.set)(parent, dest, (0, import_utils33.cloneDeep)(parent[leaf]));
12384
+ (0, import_utils34.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12385
+ if (!(0, import_utils34.hasOwn)(parent, leaf)) return;
12386
+ (0, import_utils34.set)(parent, dest, cloneProcessorValue(parent[leaf]));
12203
12387
  });
12204
12388
  });
12205
12389
  return obj;
12206
12390
  };
12207
12391
  var movePaths = (docObject, operations, options = { mutable: true }) => {
12208
12392
  const mutable = options.mutable !== false;
12209
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12210
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12393
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12394
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12211
12395
  if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
12212
12396
  const src = op.src;
12213
12397
  const dest = op.dest;
@@ -12215,10 +12399,10 @@ var movePaths = (docObject, operations, options = { mutable: true }) => {
12215
12399
  assertSafePath(src, "movePaths");
12216
12400
  assertSafePath(dest, "movePaths");
12217
12401
  if (src === dest) return;
12218
- (0, import_utils33.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12219
- if (!(0, import_utils33.hasOwn)(parent, leaf)) return;
12220
- const value = (0, import_utils33.cloneDeep)(parent[leaf]);
12221
- (0, import_utils33.set)(parent, dest, value);
12402
+ (0, import_utils34.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12403
+ if (!(0, import_utils34.hasOwn)(parent, leaf)) return;
12404
+ const value = cloneProcessorValue(parent[leaf]);
12405
+ (0, import_utils34.set)(parent, dest, value);
12222
12406
  if (dest === leaf || dest.startsWith(`${leaf}.`)) return;
12223
12407
  delete parent[leaf];
12224
12408
  });
@@ -12229,8 +12413,8 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
12229
12413
  const mutable = options.mutable !== false;
12230
12414
  const maxSlice = options.maxSlice ?? DEFAULT_MAX_SLICE;
12231
12415
  assertNonNegativeSafeInteger(maxSlice, "maxSlice", "sliceArrays");
12232
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12233
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12416
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12417
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12234
12418
  if (!op || typeof op.src !== "string") return;
12235
12419
  const src = op.src;
12236
12420
  if (src.length === 0) return;
@@ -12247,15 +12431,15 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
12247
12431
  assertNonNegativeSafeInteger(op.limit, "limit", "sliceArrays");
12248
12432
  limit = Math.min(op.limit, maxSlice);
12249
12433
  }
12250
- (0, import_utils33.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12434
+ (0, import_utils34.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12251
12435
  const leafValue = parent[leaf];
12252
- if (!(0, import_utils33.isArray)(leafValue)) return;
12436
+ if (!(0, import_utils34.isArray)(leafValue)) return;
12253
12437
  const end = typeof limit === "undefined" ? void 0 : skip + limit;
12254
12438
  const window = leafValue.slice(skip, end);
12255
12439
  if (typeof rawDest === "undefined") {
12256
- (0, import_utils33.set)(parent, leaf, window);
12440
+ (0, import_utils34.set)(parent, leaf, window);
12257
12441
  } else {
12258
- (0, import_utils33.set)(parent, rawDest, window);
12442
+ (0, import_utils34.set)(parent, rawDest, window);
12259
12443
  }
12260
12444
  });
12261
12445
  });
@@ -12263,44 +12447,44 @@ var sliceArrays = (docObject, operations, options = { mutable: true, maxSlice: D
12263
12447
  };
12264
12448
  var countPaths = (docObject, operations, options = { mutable: true }) => {
12265
12449
  const mutable = options.mutable !== false;
12266
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12267
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12450
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12451
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12268
12452
  if (!op || typeof op.src !== "string" || typeof op.dest !== "string") return;
12269
12453
  const src = op.src;
12270
12454
  const dest = op.dest;
12271
12455
  if (src.length === 0 || dest.length === 0) return;
12272
12456
  assertSafePath(src, "countPaths");
12273
12457
  assertSafePath(dest, "countPaths");
12274
- (0, import_utils33.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12275
- if (!(0, import_utils33.hasOwn)(parent, leaf)) return;
12458
+ (0, import_utils34.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12459
+ if (!(0, import_utils34.hasOwn)(parent, leaf)) return;
12276
12460
  const leafValue = parent[leaf];
12277
12461
  let count;
12278
- if ((0, import_utils33.isArray)(leafValue)) {
12462
+ if ((0, import_utils34.isArray)(leafValue)) {
12279
12463
  count = leafValue.length;
12280
- } else if ((0, import_utils33.isPlainObject)(leafValue)) {
12464
+ } else if ((0, import_utils34.isPlainObject)(leafValue)) {
12281
12465
  count = Object.keys(leafValue).length;
12282
12466
  } else if (leafValue === null || typeof leafValue === "undefined") {
12283
12467
  count = 0;
12284
12468
  } else {
12285
12469
  count = 1;
12286
12470
  }
12287
- (0, import_utils33.set)(parent, dest, count);
12471
+ (0, import_utils34.set)(parent, dest, count);
12288
12472
  });
12289
12473
  });
12290
12474
  return obj;
12291
12475
  };
12292
12476
  var maskPaths = (docObject, operations, options = { mutable: true }) => {
12293
12477
  const mutable = options.mutable !== false;
12294
- const obj = mutable ? docObject : (0, import_utils33.cloneDeep)(docObject);
12295
- (0, import_utils33.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12478
+ const obj = mutable ? docObject : cloneProcessorValue(docObject);
12479
+ (0, import_utils34.forEach)(Array.isArray(operations) ? operations : [], (op) => {
12296
12480
  if (!op || typeof op.src !== "string") return;
12297
12481
  const src = op.src;
12298
12482
  if (src.length === 0) return;
12299
12483
  assertSafePath(src, "maskPaths");
12300
12484
  const replacement = Object.prototype.hasOwnProperty.call(op, "replacement") ? op.replacement : DEFAULT_MASK_REPLACEMENT;
12301
- (0, import_utils33.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12302
- if (!(0, import_utils33.hasOwn)(parent, leaf)) return;
12303
- (0, import_utils33.set)(parent, leaf, replacement);
12485
+ (0, import_utils34.forEach)(resolveLeafParents(obj, src), ({ parent, leaf }) => {
12486
+ if (!(0, import_utils34.hasOwn)(parent, leaf)) return;
12487
+ (0, import_utils34.set)(parent, leaf, replacement);
12304
12488
  });
12305
12489
  });
12306
12490
  return obj;
@@ -12400,10 +12584,10 @@ var Core = class {
12400
12584
  getIdentifier(modelName) {
12401
12585
  const resolveIdFilter = getModelOption(modelName, "resolveIdFilter");
12402
12586
  const idField = getModelOption(modelName, "idField");
12403
- if ((0, import_utils34.isFunction)(resolveIdFilter)) {
12587
+ if ((0, import_utils35.isFunction)(resolveIdFilter)) {
12404
12588
  return null;
12405
12589
  }
12406
- if ((0, import_utils34.isString)(idField)) {
12590
+ if ((0, import_utils35.isString)(idField)) {
12407
12591
  return idField;
12408
12592
  }
12409
12593
  return "_id";
@@ -12524,15 +12708,15 @@ var Core = class {
12524
12708
  if (!_populate) return [];
12525
12709
  let populate = Array.isArray(_populate) ? _populate : [_populate];
12526
12710
  for (const p of populate) {
12527
- if (!(0, import_utils34.isString)(p)) assertPopulateAccess(p.access);
12711
+ if (!(0, import_utils35.isString)(p)) assertPopulateAccess(p.access);
12528
12712
  }
12529
- populate = (0, import_utils34.compact)(
12713
+ populate = (0, import_utils35.compact)(
12530
12714
  await Promise.all(
12531
12715
  populate.map(async (p) => {
12532
- const populateAccess = !(0, import_utils34.isString)(p) && p.access ? p.access : access;
12716
+ const populateAccess = !(0, import_utils35.isString)(p) && p.access ? p.access : access;
12533
12717
  assertPopulateAccess(populateAccess);
12534
- const originalSelect = (0, import_utils34.isString)(p) ? void 0 : p.select;
12535
- const ret = (0, import_utils34.isString)(p) ? { path: p } : {
12718
+ const originalSelect = (0, import_utils35.isString)(p) ? void 0 : p.select;
12719
+ const ret = (0, import_utils35.isString)(p) ? { path: p } : {
12536
12720
  path: p.path,
12537
12721
  select: normalizeSelect(p.select)
12538
12722
  };
@@ -12560,7 +12744,7 @@ var Core = class {
12560
12744
  }
12561
12745
  ret.select = await this.requestPopulateSelect(refModelName, populateAccess, ret.select);
12562
12746
  const hookInputs = getModelOption(refModelName, `alwaysSelectFields.${populateAccess}`, []);
12563
- ret.select = (0, import_utils34.uniq)([...ret.select, ...stripVirtuals(hookInputs, runtime.getVirtualNames(refModelName))]);
12747
+ ret.select = (0, import_utils35.uniq)([...ret.select, ...stripVirtuals(hookInputs, runtime.getVirtualNames(refModelName))]);
12564
12748
  const filter2 = await this.genFilter(refModelName, populateAccess, null);
12565
12749
  if (filter2 === false) return null;
12566
12750
  ret.match = filter2;
@@ -12596,7 +12780,7 @@ var Core = class {
12596
12780
  internalFetch: { baseFields: ["_id"] },
12597
12781
  globalPermissions: globalForPlan
12598
12782
  });
12599
- const merged = (0, import_utils34.uniq)([...normalizeSelect(ret.select), ...targetPlan.virtualOnlyDeps ?? []]).filter(
12783
+ const merged = (0, import_utils35.uniq)([...normalizeSelect(ret.select), ...targetPlan.virtualOnlyDeps ?? []]).filter(
12600
12784
  (t) => t !== "-_id" && !t.includes(".sub.")
12601
12785
  );
12602
12786
  if (!merged.includes("_id")) merged.push("_id");
@@ -12620,10 +12804,10 @@ var Core = class {
12620
12804
  }
12621
12805
  async validate(modelName, allowedData, access, context) {
12622
12806
  const validate = getModelOption(modelName, `validate.${access}`, null);
12623
- if ((0, import_utils34.isFunction)(validate)) {
12807
+ if ((0, import_utils35.isFunction)(validate)) {
12624
12808
  const permissions = this.getGlobalPermissions();
12625
12809
  return validate.call(this.req, allowedData, permissions, context);
12626
- } else if ((0, import_utils34.isBoolean)(validate) || (0, import_utils34.isArray)(validate)) {
12810
+ } else if ((0, import_utils35.isBoolean)(validate) || (0, import_utils35.isArray)(validate)) {
12627
12811
  return validate;
12628
12812
  } else {
12629
12813
  return true;
@@ -12648,7 +12832,7 @@ var Core = class {
12648
12832
  const changeOptions = getModelOption(modelName, `onChange`, {});
12649
12833
  for (let x = 0; x < context.modifiedPaths.length; x++) {
12650
12834
  const mpath = context.modifiedPaths[x];
12651
- if ((0, import_utils34.isFunction)(changeOptions[mpath])) {
12835
+ if ((0, import_utils35.isFunction)(changeOptions[mpath])) {
12652
12836
  await changeOptions[mpath].call(
12653
12837
  this.req,
12654
12838
  context.originalDocumentSnapshot[mpath],
@@ -12672,7 +12856,7 @@ var Core = class {
12672
12856
  async genDocPermissions(modelName, doc, access, context) {
12673
12857
  const docPermissionsFn = getModelOption(modelName, `docPermissions.${access}`, null);
12674
12858
  let docPermissions = {};
12675
- if ((0, import_utils34.isFunction)(docPermissionsFn)) {
12859
+ if ((0, import_utils35.isFunction)(docPermissionsFn)) {
12676
12860
  const permissions = this.getGlobalPermissions();
12677
12861
  try {
12678
12862
  docPermissions = await getRequestWorkState(this.req, this.requestRuntime).hookGate.run(
@@ -12756,7 +12940,7 @@ var Core = class {
12756
12940
  readExists ? requestFields("read") : [],
12757
12941
  updateExists ? requestFields("update") : []
12758
12942
  ]);
12759
- const viewObj = (0, import_utils34.reduce)(
12943
+ const viewObj = (0, import_utils35.reduce)(
12760
12944
  views,
12761
12945
  (ret, view) => {
12762
12946
  ret[view] = true;
@@ -12764,7 +12948,7 @@ var Core = class {
12764
12948
  },
12765
12949
  {}
12766
12950
  );
12767
- const editObj = (0, import_utils34.reduce)(
12951
+ const editObj = (0, import_utils35.reduce)(
12768
12952
  edits,
12769
12953
  (ret, view) => {
12770
12954
  ret[view] = true;
@@ -12795,9 +12979,9 @@ var Core = class {
12795
12979
  });
12796
12980
  }
12797
12981
  runTasks(modelName, docObject, task) {
12798
- const tasks = (0, import_utils34.compact)((0, import_utils34.castArray)(task));
12982
+ const tasks = (0, import_utils35.compact)((0, import_utils35.castArray)(task));
12799
12983
  if (tasks.length === 0) return docObject;
12800
- (0, import_utils34.forEach)(tasks, (task2) => {
12984
+ (0, import_utils35.forEach)(tasks, (task2) => {
12801
12985
  const { type, args, options } = task2;
12802
12986
  switch (type) {
12803
12987
  case "COPY_AND_DEPOPULATE":
@@ -12865,9 +13049,9 @@ var Core = class {
12865
13049
  }
12866
13050
  const [, field, op] = keys2;
12867
13051
  const subOption = getExactModelOption(modelName, `operationAccess.${access}`);
12868
- if ((0, import_utils34.isUndefined)(subOption)) {
13052
+ if ((0, import_utils35.isUndefined)(subOption)) {
12869
13053
  const subFieldOption = getExactModelOption(modelName, `operationAccess.subs.${field}`);
12870
- if ((0, import_utils34.isUndefined)(subFieldOption)) {
13054
+ if ((0, import_utils35.isUndefined)(subFieldOption)) {
12871
13055
  const opOption = getModelOption(modelName, `operationAccess.${op}`);
12872
13056
  return this.canActivate(opOption);
12873
13057
  }
@@ -12933,25 +13117,25 @@ function guard(condition) {
12933
13117
  const permissions = req[PERMISSIONS];
12934
13118
  let cond = condition;
12935
13119
  let phas = (key) => permissions.has(key);
12936
- if ((0, import_utils35.isPlainObject)(condition)) {
13120
+ if ((0, import_utils36.isPlainObject)(condition)) {
12937
13121
  const { modelName, id, condition: _cond } = condition;
12938
13122
  const svc = req.macl.getPublicService(modelName);
12939
13123
  const select = getModelOption(modelName, `alwaysSelectFields.read`, void 0);
12940
- let _id = (0, import_utils35.isString)(id) ? id : null;
12941
- if ((0, import_utils35.isPlainObject)(id)) {
13124
+ let _id = (0, import_utils36.isString)(id) ? id : null;
13125
+ if ((0, import_utils36.isPlainObject)(id)) {
12942
13126
  const { type = "param", key } = id;
12943
13127
  if (type === "param") {
12944
13128
  const paramValue = req.params[key];
12945
- _id = (0, import_utils35.isArray)(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
13129
+ _id = (0, import_utils36.isArray)(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
12946
13130
  } else if (type === "query") {
12947
13131
  const _qval = req.query[key];
12948
- if ((0, import_utils35.isArray)(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
13132
+ if ((0, import_utils36.isArray)(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
12949
13133
  else _id = _qval;
12950
13134
  } else {
12951
13135
  _id = null;
12952
13136
  }
12953
13137
  }
12954
- if (!(0, import_utils35.isString)(_id) || !_id) {
13138
+ if (!(0, import_utils36.isString)(_id) || !_id) {
12955
13139
  return next(new import_express_json_router5.default.clientErrors.BadRequestError());
12956
13140
  }
12957
13141
  const result2 = await svc._read(_id, { select });
@@ -12963,11 +13147,11 @@ function guard(condition) {
12963
13147
  cond = _cond;
12964
13148
  }
12965
13149
  const { stringHandler, arrayHandler } = createValidator(phas);
12966
- if ((0, import_utils35.isString)(cond)) {
13150
+ if ((0, import_utils36.isString)(cond)) {
12967
13151
  if (stringHandler(cond)) return next();
12968
- } else if ((0, import_utils35.isArray)(cond)) {
13152
+ } else if ((0, import_utils36.isArray)(cond)) {
12969
13153
  if (arrayHandler(cond)) return next();
12970
- } else if ((0, import_utils35.isFunction)(cond)) {
13154
+ } else if ((0, import_utils36.isFunction)(cond)) {
12971
13155
  const result2 = await cond.call(req, permissions);
12972
13156
  if (!!result2) return next();
12973
13157
  }
@@ -12980,7 +13164,7 @@ var import_express2 = __toESM(require("express"));
12980
13164
 
12981
13165
  // src/routers/model-router.ts
12982
13166
  var import_express_json_router8 = __toESM(require("@web-ts-toolkit/express-json-router"));
12983
- var import_utils39 = require("@web-ts-toolkit/utils");
13167
+ var import_utils40 = require("@web-ts-toolkit/utils");
12984
13168
  init_logger_helpers();
12985
13169
  init_runtime();
12986
13170
  init_runtime_context();
@@ -13114,7 +13298,7 @@ init_request_complexity();
13114
13298
 
13115
13299
  // src/validation/common.ts
13116
13300
  var import_zod2 = require("zod");
13117
- var import_utils36 = require("@web-ts-toolkit/utils");
13301
+ var import_utils37 = require("@web-ts-toolkit/utils");
13118
13302
 
13119
13303
  // src/validation/public-admission-schema.ts
13120
13304
  init_public_admission();
@@ -13243,7 +13427,7 @@ var correlatedFilterSchema = import_zod2.z.record(import_zod2.z.string(), import
13243
13427
  }
13244
13428
  });
13245
13429
  var correlatedEmptyOptionsSchema = import_zod2.z.unknown().refine(
13246
- (value) => value === void 0 || (0, import_utils36.isPlainObject)(value) && Object.keys(value).length === 0,
13430
+ (value) => value === void 0 || (0, import_utils37.isPlainObject)(value) && Object.keys(value).length === 0,
13247
13431
  "Correlated include options must be absent or empty"
13248
13432
  ).optional();
13249
13433
  var correlatedPathSchema = import_zod2.z.string().min(1).superRefine((path, ctx) => {
@@ -13280,7 +13464,7 @@ var correlatedListArgsSchema = import_zod2.z.object({
13280
13464
  include: import_zod2.z.lazy(() => correlatedNestedIncludeSchema).optional()
13281
13465
  }).strict().superRefine((args, ctx) => checkArgsMarkers(args.select, args.sort, ctx));
13282
13466
  var correlatedCountArgsSchema = import_zod2.z.unknown().refine(
13283
- (value) => value === void 0 || (0, import_utils36.isPlainObject)(value) && Object.keys(value).length === 0,
13467
+ (value) => value === void 0 || (0, import_utils37.isPlainObject)(value) && Object.keys(value).length === 0,
13284
13468
  "Count includes accept no args"
13285
13469
  ).optional();
13286
13470
  var correlatedReadByIdSchema = import_zod2.z.object({
@@ -13333,7 +13517,7 @@ var correlatedNestedIncludeSchema = import_zod2.z.union([includeItemSchema, impo
13333
13517
  var rejectDuplicateCorrelatedPaths = (items, ctx) => {
13334
13518
  const seen = /* @__PURE__ */ new Set();
13335
13519
  items.forEach((item, index) => {
13336
- if ((0, import_utils36.isPlainObject)(item) && item.mode === "correlated" && typeof item.path === "string") {
13520
+ if ((0, import_utils37.isPlainObject)(item) && item.mode === "correlated" && typeof item.path === "string") {
13337
13521
  if (seen.has(item.path)) {
13338
13522
  ctx.addIssue({
13339
13523
  code: import_zod2.z.ZodIssueCode.custom,
@@ -14077,8 +14261,7 @@ var rootModelListOptionsSchema = import_zod5.z.object({
14077
14261
  includePermissions: import_zod5.z.boolean().optional(),
14078
14262
  includeFieldPermissions: import_zod5.z.boolean().optional(),
14079
14263
  includeCount: import_zod5.z.boolean().optional(),
14080
- populateAccess: populateAccessSchema.optional(),
14081
- lean: import_zod5.z.boolean().optional()
14264
+ populateAccess: populateAccessSchema.optional()
14082
14265
  }).passthrough();
14083
14266
  var rootModelReadArgsSchema = import_zod5.z.object({
14084
14267
  select: projectionSchema.optional(),
@@ -14094,8 +14277,7 @@ var rootModelReadOptionsSchema = import_zod5.z.object({
14094
14277
  includePermissions: import_zod5.z.boolean().optional(),
14095
14278
  includeFieldPermissions: import_zod5.z.boolean().optional(),
14096
14279
  tryList: import_zod5.z.boolean().optional(),
14097
- populateAccess: populateAccessSchema.optional(),
14098
- lean: import_zod5.z.boolean().optional()
14280
+ populateAccess: populateAccessSchema.optional()
14099
14281
  }).passthrough();
14100
14282
  var rootModelCreateArgsSchema = import_zod5.z.object({
14101
14283
  select: projectionSchema.optional(),
@@ -14308,7 +14490,7 @@ var rootQuerySchema = publicBoundarySchema(
14308
14490
  init_helpers();
14309
14491
 
14310
14492
  // src/routers/shared.ts
14311
- var import_utils37 = require("@web-ts-toolkit/utils");
14493
+ var import_utils38 = require("@web-ts-toolkit/utils");
14312
14494
 
14313
14495
  // src/routers/model-router-collection-routes.ts
14314
14496
  init_schemas();
@@ -14339,15 +14521,15 @@ function setModelCollectionRoutes(context) {
14339
14521
  sort
14340
14522
  } = parseQuery(requestSchemas.listQuery, req.query);
14341
14523
  const svc = context.getPublicService(req);
14342
- const includeCount = (0, import_utils37.parseBooleanString)(include_count);
14343
- const includeExtraHeaders = (0, import_utils37.parseBooleanString)(include_extra_headers);
14524
+ const includeCount = (0, import_utils38.parseBooleanString)(include_count);
14525
+ const includeExtraHeaders = (0, import_utils38.parseBooleanString)(include_extra_headers);
14344
14526
  const result2 = await svc._list(
14345
14527
  {},
14346
14528
  { select: parseSelectParam(select), sort, skip, limit, page, pageSize: page_size },
14347
14529
  {
14348
- skim: (0, import_utils37.parseBooleanString)(skim),
14349
- includePermissions: (0, import_utils37.parseBooleanString)(include_permissions),
14350
- includeFieldPermissions: (0, import_utils37.parseBooleanString)(include_field_permissions),
14530
+ skim: (0, import_utils38.parseBooleanString)(skim),
14531
+ includePermissions: (0, import_utils38.parseBooleanString)(include_permissions),
14532
+ includeFieldPermissions: (0, import_utils38.parseBooleanString)(include_field_permissions),
14351
14533
  includeCount
14352
14534
  }
14353
14535
  );
@@ -14407,8 +14589,8 @@ function setModelCollectionRoutes(context) {
14407
14589
  data,
14408
14590
  {},
14409
14591
  {
14410
- includePermissions: (0, import_utils37.parseBooleanString)(include_permissions),
14411
- includeFieldPermissions: (0, import_utils37.parseBooleanString)(include_field_permissions)
14592
+ includePermissions: (0, import_utils38.parseBooleanString)(include_permissions),
14593
+ includeFieldPermissions: (0, import_utils38.parseBooleanString)(include_field_permissions)
14412
14594
  }
14413
14595
  );
14414
14596
  handleResultError(result2);
@@ -14446,8 +14628,8 @@ function setModelCollectionRoutes(context) {
14446
14628
  finalData,
14447
14629
  { select: finalSelect, populate: finalPopulate, tasks: finalTasks },
14448
14630
  {
14449
- includePermissions: includePermissions ?? (0, import_utils37.parseBooleanString)(include_permissions),
14450
- includeFieldPermissions: includeFieldPermissions ?? (0, import_utils37.parseBooleanString)(include_field_permissions),
14631
+ includePermissions: includePermissions ?? (0, import_utils38.parseBooleanString)(include_permissions),
14632
+ includeFieldPermissions: includeFieldPermissions ?? (0, import_utils38.parseBooleanString)(include_field_permissions),
14451
14633
  populateAccess
14452
14634
  }
14453
14635
  );
@@ -14544,9 +14726,9 @@ function setModelDocumentRoutes(context) {
14544
14726
  id,
14545
14727
  { select: parseSelectParam(select) },
14546
14728
  {
14547
- includePermissions: (0, import_utils37.parseBooleanString)(include_permissions),
14548
- includeFieldPermissions: (0, import_utils37.parseBooleanString)(include_field_permissions),
14549
- tryList: (0, import_utils37.parseBooleanString)(try_list)
14729
+ includePermissions: (0, import_utils38.parseBooleanString)(include_permissions),
14730
+ includeFieldPermissions: (0, import_utils38.parseBooleanString)(include_field_permissions),
14731
+ tryList: (0, import_utils38.parseBooleanString)(try_list)
14550
14732
  }
14551
14733
  );
14552
14734
  handleResultError(result2);
@@ -14646,9 +14828,9 @@ function setModelDocumentRoutes(context) {
14646
14828
  data,
14647
14829
  { select: parseSelectParam(select) },
14648
14830
  {
14649
- returningAll: (0, import_utils37.parseBooleanString)(returning_all),
14650
- includePermissions: (0, import_utils37.parseBooleanString)(include_permissions),
14651
- includeFieldPermissions: (0, import_utils37.parseBooleanString)(include_field_permissions)
14831
+ returningAll: (0, import_utils38.parseBooleanString)(returning_all),
14832
+ includePermissions: (0, import_utils38.parseBooleanString)(include_permissions),
14833
+ includeFieldPermissions: (0, import_utils38.parseBooleanString)(include_field_permissions)
14652
14834
  }
14653
14835
  );
14654
14836
  handleResultError(result2);
@@ -14697,9 +14879,9 @@ function setModelDocumentRoutes(context) {
14697
14879
  finalData,
14698
14880
  { select: finalSelect, populate: finalPopulate, tasks: finalTasks },
14699
14881
  {
14700
- returningAll: returningAll ?? (0, import_utils37.parseBooleanString)(returning_all),
14701
- includePermissions: includePermissions ?? (0, import_utils37.parseBooleanString)(include_permissions),
14702
- includeFieldPermissions: includeFieldPermissions ?? (0, import_utils37.parseBooleanString)(include_field_permissions),
14882
+ returningAll: returningAll ?? (0, import_utils38.parseBooleanString)(returning_all),
14883
+ includePermissions: includePermissions ?? (0, import_utils38.parseBooleanString)(include_permissions),
14884
+ includeFieldPermissions: includeFieldPermissions ?? (0, import_utils38.parseBooleanString)(include_field_permissions),
14703
14885
  populateAccess
14704
14886
  }
14705
14887
  );
@@ -14730,9 +14912,9 @@ function setModelDocumentRoutes(context) {
14730
14912
  body,
14731
14913
  {},
14732
14914
  {
14733
- returningAll: (0, import_utils37.parseBooleanString)(returning_all),
14734
- includePermissions: (0, import_utils37.parseBooleanString)(include_permissions),
14735
- includeFieldPermissions: (0, import_utils37.parseBooleanString)(include_field_permissions)
14915
+ returningAll: (0, import_utils38.parseBooleanString)(returning_all),
14916
+ includePermissions: (0, import_utils38.parseBooleanString)(include_permissions),
14917
+ includeFieldPermissions: (0, import_utils38.parseBooleanString)(include_field_permissions)
14736
14918
  }
14737
14919
  );
14738
14920
  handleResultError(result2);
@@ -14779,9 +14961,9 @@ function setModelDocumentRoutes(context) {
14779
14961
  finalData,
14780
14962
  { select: finalSelect, populate: finalPopulate, tasks: finalTasks },
14781
14963
  {
14782
- returningAll: returningAll ?? (0, import_utils37.parseBooleanString)(returning_all),
14783
- includePermissions: includePermissions ?? (0, import_utils37.parseBooleanString)(include_permissions),
14784
- includeFieldPermissions: includeFieldPermissions ?? (0, import_utils37.parseBooleanString)(include_field_permissions),
14964
+ returningAll: returningAll ?? (0, import_utils38.parseBooleanString)(returning_all),
14965
+ includePermissions: includePermissions ?? (0, import_utils38.parseBooleanString)(include_permissions),
14966
+ includeFieldPermissions: includeFieldPermissions ?? (0, import_utils38.parseBooleanString)(include_field_permissions),
14785
14967
  populateAccess
14786
14968
  }
14787
14969
  );
@@ -15021,11 +15203,11 @@ function setModelSubDocumentRoutes(context) {
15021
15203
  }
15022
15204
 
15023
15205
  // src/openapi/route-registration.ts
15024
- var import_utils38 = require("@web-ts-toolkit/utils");
15206
+ var import_utils39 = require("@web-ts-toolkit/utils");
15025
15207
  function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
15026
15208
  runtime.registerOpenApiRoute({
15027
15209
  ...route,
15028
- path: (0, import_utils38.normalizeUrlPath)(basePath + route.path),
15210
+ path: (0, import_utils39.normalizeUrlPath)(basePath + route.path),
15029
15211
  tags: route.tags ?? [defaultTag]
15030
15212
  });
15031
15213
  }
@@ -15033,8 +15215,8 @@ function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
15033
15215
  // src/routers/model-router.ts
15034
15216
  var clientErrors2 = import_express_json_router8.default.clientErrors;
15035
15217
  function setOption(parentKey, optionKey, option) {
15036
- const key = (0, import_utils39.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
15037
- const value = (0, import_utils39.isUndefined)(option) ? optionKey : option;
15218
+ const key = (0, import_utils40.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
15219
+ const value = (0, import_utils40.isUndefined)(option) ? optionKey : option;
15038
15220
  assertMutableRouterOption("model", key);
15039
15221
  this.runtime.setModelOption(
15040
15222
  this.modelName,
@@ -15233,7 +15415,7 @@ var ModelRouter = class _ModelRouter {
15233
15415
  this.runtime = runtime;
15234
15416
  this.runtime.setModelOptions(modelName, initialOptions);
15235
15417
  this.options = this.runtime.getModelOptions(modelName);
15236
- this.fullBasePath = (0, import_utils39.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
15418
+ this.fullBasePath = (0, import_utils40.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
15237
15419
  this.modelName = modelName;
15238
15420
  this.router = new import_express_json_router8.default(this.options.basePath, createSetCore(this.runtime), accessRouterResponseHandler);
15239
15421
  this.model = new model_default(modelName, this.runtime);
@@ -15319,13 +15501,13 @@ var ModelRouter = class _ModelRouter {
15319
15501
  }
15320
15502
  logEndpoints() {
15321
15503
  runWithRuntime(this.runtime, () => {
15322
- (0, import_utils39.forEach)(this.router.getEndpoints(), ({ method, path }) => {
15323
- logInfoMessage(`${(0, import_utils39.padEnd)(method, 6)} ${(0, import_utils39.normalizeUrlPath)(this.options.parentPath + path)}`);
15504
+ (0, import_utils40.forEach)(this.router.getEndpoints(), ({ method, path }) => {
15505
+ logInfoMessage(`${(0, import_utils40.padEnd)(method, 6)} ${(0, import_utils40.normalizeUrlPath)(this.options.parentPath + path)}`);
15324
15506
  });
15325
15507
  });
15326
15508
  }
15327
15509
  set(keyOrOptions, value) {
15328
- if (arguments.length === 2 && (0, import_utils39.isString)(keyOrOptions)) {
15510
+ if (arguments.length === 2 && (0, import_utils40.isString)(keyOrOptions)) {
15329
15511
  assertMutableRouterOption("model", keyOrOptions);
15330
15512
  this.runtime.setModelOption(
15331
15513
  this.modelName,
@@ -15333,7 +15515,7 @@ var ModelRouter = class _ModelRouter {
15333
15515
  value
15334
15516
  );
15335
15517
  }
15336
- if (arguments.length === 1 && (0, import_utils39.isPlainObject)(keyOrOptions)) {
15518
+ if (arguments.length === 1 && (0, import_utils40.isPlainObject)(keyOrOptions)) {
15337
15519
  assertMutableRouterOptions("model", keyOrOptions);
15338
15520
  this.runtime.setModelOptions(
15339
15521
  this.modelName,
@@ -15361,7 +15543,7 @@ var ModelRouter = class _ModelRouter {
15361
15543
 
15362
15544
  // src/routers/root-router.ts
15363
15545
  var import_express_json_router9 = __toESM(require("@web-ts-toolkit/express-json-router"));
15364
- var import_utils40 = require("@web-ts-toolkit/utils");
15546
+ var import_utils41 = require("@web-ts-toolkit/utils");
15365
15547
 
15366
15548
  // src/core-data.ts
15367
15549
  init_options();
@@ -15667,7 +15849,7 @@ var RootRouter = class {
15667
15849
  this.setRoutes();
15668
15850
  }
15669
15851
  registerOpenApiRoute(route) {
15670
- registerOpenApiRoute(this.runtime, (0, import_utils40.normalizeUrlPath)(this.basename), "root", route);
15852
+ registerOpenApiRoute(this.runtime, (0, import_utils41.normalizeUrlPath)(this.basename), "root", route);
15671
15853
  }
15672
15854
  wrapResult(index, item, result2) {
15673
15855
  return {
@@ -15727,8 +15909,8 @@ var RootRouter = class {
15727
15909
  const presentation = ["skim", "includePermissions", "includeFieldPermissions"];
15728
15910
  const optionKeys = {
15729
15911
  new: presentation,
15730
- list: [...presentation, "includeCount", "populateAccess", "lean"],
15731
- read: [...presentation, "populateAccess", "lean", "tryList"],
15912
+ list: [...presentation, "includeCount", "populateAccess"],
15913
+ read: [...presentation, "populateAccess", "tryList"],
15732
15914
  create: [...presentation, "populateAccess"],
15733
15915
  update: [...presentation, "populateAccess", "returningAll"],
15734
15916
  upsert: [...presentation, "populateAccess", "returningAll"]
@@ -15776,7 +15958,7 @@ var RootRouter = class {
15776
15958
  groupItemsByOrder(items) {
15777
15959
  const groups = /* @__PURE__ */ new Map();
15778
15960
  items.forEach((item, index) => {
15779
- const order = (0, import_utils40.isNumber)(item.order) ? item.order : 0;
15961
+ const order = (0, import_utils41.isNumber)(item.order) ? item.order : 0;
15780
15962
  const group = groups.get(order);
15781
15963
  if (group) {
15782
15964
  group.push({ index, item });
@@ -15847,7 +16029,7 @@ var RootRouter = class {
15847
16029
  const arrResult = await this.runGroup(req, groupedItems[x]);
15848
16030
  results.push(...arrResult);
15849
16031
  }
15850
- return (0, import_utils40.orderBy)(results, ["index"], ["asc"]);
16032
+ return (0, import_utils41.orderBy)(results, ["index"], ["asc"]);
15851
16033
  });
15852
16034
  this.registerOpenApiRoute({
15853
16035
  method: "post",
@@ -15865,14 +16047,14 @@ var RootRouter = class {
15865
16047
 
15866
16048
  // src/routers/data-router.ts
15867
16049
  var import_express_json_router10 = __toESM(require("@web-ts-toolkit/express-json-router"));
15868
- var import_utils41 = require("@web-ts-toolkit/utils");
16050
+ var import_utils42 = require("@web-ts-toolkit/utils");
15869
16051
  init_runtime();
15870
16052
  init_helpers();
15871
16053
  init_schemas();
15872
16054
  var clientErrors4 = import_express_json_router10.default.clientErrors;
15873
16055
  function setOption2(parentKey, optionKey, option) {
15874
- const key = (0, import_utils41.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
15875
- const value = (0, import_utils41.isUndefined)(option) ? optionKey : option;
16056
+ const key = (0, import_utils42.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
16057
+ const value = (0, import_utils42.isUndefined)(option) ? optionKey : option;
15876
16058
  assertMutableRouterOption("data", key);
15877
16059
  this.runtime.setDataOption(this.dataName, key, value);
15878
16060
  return this;
@@ -15921,7 +16103,7 @@ var DataRouter = class {
15921
16103
  this.runtime = runtime;
15922
16104
  this.runtime.setDataOptions(dataName, initialOptions);
15923
16105
  this.options = this.runtime.getDataOptions(dataName);
15924
- this.fullBasePath = (0, import_utils41.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
16106
+ this.fullBasePath = (0, import_utils42.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
15925
16107
  this.dataName = dataName;
15926
16108
  this.router = new import_express_json_router10.default(this.options.basePath, createSetDataCore(this.runtime), accessRouterResponseHandler);
15927
16109
  this.setCollectionRoutes();
@@ -15954,8 +16136,8 @@ var DataRouter = class {
15954
16136
  req.query
15955
16137
  );
15956
16138
  const svc = this.getService(req);
15957
- const includeCount = (0, import_utils37.parseBooleanString)(include_count);
15958
- const includeExtraHeaders = (0, import_utils37.parseBooleanString)(include_extra_headers);
16139
+ const includeCount = (0, import_utils38.parseBooleanString)(include_count);
16140
+ const includeExtraHeaders = (0, import_utils38.parseBooleanString)(include_extra_headers);
15959
16141
  const result2 = await svc.find(
15960
16142
  {},
15961
16143
  { select: parseSelectParam(select), sort, skip, limit, page, pageSize: page_size },
@@ -16073,7 +16255,7 @@ var DataRouter = class {
16073
16255
  });
16074
16256
  }
16075
16257
  set(keyOrOptions, value) {
16076
- if (arguments.length === 2 && (0, import_utils41.isString)(keyOrOptions)) {
16258
+ if (arguments.length === 2 && (0, import_utils42.isString)(keyOrOptions)) {
16077
16259
  assertMutableRouterOption("data", keyOrOptions);
16078
16260
  this.runtime.setDataOption(
16079
16261
  this.dataName,
@@ -16081,7 +16263,7 @@ var DataRouter = class {
16081
16263
  value
16082
16264
  );
16083
16265
  }
16084
- if (arguments.length === 1 && (0, import_utils41.isPlainObject)(keyOrOptions)) {
16266
+ if (arguments.length === 1 && (0, import_utils42.isPlainObject)(keyOrOptions)) {
16085
16267
  assertMutableRouterOptions("data", keyOrOptions);
16086
16268
  this.runtime.setDataOptions(this.dataName, keyOrOptions);
16087
16269
  }
@@ -16216,7 +16398,7 @@ function createRuntimeApi(runtime) {
16216
16398
  const wtt2 = runtimeMiddleware;
16217
16399
  wtt2.runtime = runtime;
16218
16400
  wtt2.createRouter = function(modelName, options) {
16219
- if ((0, import_utils42.isUndefined)(options)) {
16401
+ if ((0, import_utils43.isUndefined)(options)) {
16220
16402
  return new RootRouter(modelName, runtime);
16221
16403
  }
16222
16404
  if (typeof modelName === "string") {
@@ -16237,10 +16419,10 @@ function createRuntimeApi(runtime) {
16237
16419
  };
16238
16420
  wtt2.combineRoutes = combineRoutes;
16239
16421
  wtt2.set = function(keyOrOptions, value) {
16240
- if (arguments.length === 2 && (0, import_utils42.isString)(keyOrOptions)) {
16422
+ if (arguments.length === 2 && (0, import_utils43.isString)(keyOrOptions)) {
16241
16423
  return runtime.setGlobalOption(keyOrOptions, value);
16242
16424
  }
16243
- if (arguments.length === 1 && (0, import_utils42.isPlainObject)(keyOrOptions)) {
16425
+ if (arguments.length === 1 && (0, import_utils43.isPlainObject)(keyOrOptions)) {
16244
16426
  return runtime.setGlobalOptions(keyOrOptions);
16245
16427
  }
16246
16428
  };