@web-ts-toolkit/access-router 0.4.0 → 0.5.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
@@ -36,6 +36,7 @@ __export(index_exports, {
36
36
  acl: () => acl,
37
37
  combineRoutes: () => combineRoutes,
38
38
  createAccessRuntime: () => createAccessRuntime,
39
+ createOpenApiRouter: () => createOpenApiRouter,
39
40
  default: () => index_default,
40
41
  defineRequestSchema: () => defineRequestSchema,
41
42
  fromAjv: () => fromAjv,
@@ -66,19 +67,19 @@ __export(index_exports, {
66
67
  setModelOptions: () => setModelOptions
67
68
  });
68
69
  module.exports = __toCommonJS(index_exports);
69
- var import_utils22 = require("@web-ts-toolkit/utils");
70
+ var import_utils27 = require("@web-ts-toolkit/utils");
70
71
 
71
72
  // src/middleware.ts
72
73
  var import_express_json_router2 = __toESM(require("@web-ts-toolkit/express-json-router"));
73
- var import_utils17 = require("@web-ts-toolkit/utils");
74
+ var import_utils20 = require("@web-ts-toolkit/utils");
74
75
 
75
76
  // src/core.ts
76
- var import_utils16 = require("@web-ts-toolkit/utils");
77
+ var import_utils19 = require("@web-ts-toolkit/utils");
77
78
 
78
79
  // src/runtime.ts
79
- var import_mongoose2 = __toESM(require("mongoose"));
80
+ var import_mongoose3 = __toESM(require("mongoose"));
80
81
  var import_mongoose_schema_jsonschema = __toESM(require("mongoose-schema-jsonschema"));
81
- var import_utils7 = require("@web-ts-toolkit/utils");
82
+ var import_utils10 = require("@web-ts-toolkit/utils");
82
83
 
83
84
  // src/helpers/collection.ts
84
85
  var import_sift = __toESM(require("sift"));
@@ -97,20 +98,11 @@ var findElementById = (collection, id) => {
97
98
  };
98
99
 
99
100
  // src/helpers/document.ts
100
- var import_utils4 = require("@web-ts-toolkit/utils");
101
-
102
- // src/lib.ts
103
101
  var import_mongoose = require("mongoose");
104
- var import_utils2 = require("@web-ts-toolkit/utils");
105
- var isSchema = (val) => val instanceof import_mongoose.Schema;
106
- var isObjectIdType = (val) => val === "ObjectId" || val === import_mongoose.Schema.Types.ObjectId;
107
- var isReference = (val) => (0, import_utils2.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
108
- var isDocument = function isDocument2(doc) {
109
- return doc instanceof import_mongoose.Document;
110
- };
102
+ var import_utils3 = require("@web-ts-toolkit/utils");
111
103
 
112
104
  // src/helpers/query.ts
113
- var import_utils3 = require("@web-ts-toolkit/utils");
105
+ var import_utils2 = require("@web-ts-toolkit/utils");
114
106
  function genPagination({
115
107
  skip,
116
108
  limit,
@@ -119,10 +111,10 @@ function genPagination({
119
111
  }, hardLimit) {
120
112
  let _skip = 0;
121
113
  let _limit = Number(limit ?? pageSize);
122
- if ((0, import_utils3.isNaN)(_limit) || _limit > hardLimit) _limit = hardLimit;
123
- if (!(0, import_utils3.isNil)(skip)) {
114
+ if ((0, import_utils2.isNaN)(_limit) || _limit > hardLimit) _limit = hardLimit;
115
+ if (!(0, import_utils2.isNil)(skip)) {
124
116
  _skip = Number(skip);
125
- } else if (!(0, import_utils3.isNil)(page)) {
117
+ } else if (!(0, import_utils2.isNil)(page)) {
126
118
  const npage = Number(page);
127
119
  if (npage > 1) _skip = (npage - 1) * _limit;
128
120
  }
@@ -137,9 +129,9 @@ function parseSortString(sortString) {
137
129
  }
138
130
  }
139
131
  function normalizeSelect(select) {
140
- if (Array.isArray(select)) return (0, import_utils3.flattenDeep)(select.map(normalizeSelect));
141
- if ((0, import_utils3.isPlainObject)(select)) {
142
- return (0, import_utils3.reduce)(
132
+ if (Array.isArray(select)) return (0, import_utils2.flattenDeep)(select.map(normalizeSelect));
133
+ if ((0, import_utils2.isPlainObject)(select)) {
134
+ return (0, import_utils2.reduce)(
143
135
  select,
144
136
  (ret, val, key) => {
145
137
  if (val === 1) ret.push(key);
@@ -149,23 +141,27 @@ function normalizeSelect(select) {
149
141
  []
150
142
  );
151
143
  }
152
- if ((0, import_utils3.isString)(select)) return select.split(" ").map((v) => v.trim());
144
+ if ((0, import_utils2.isString)(select)) return select.split(" ").map((v) => v.trim());
153
145
  return [];
154
146
  }
155
147
 
156
148
  // src/helpers/document.ts
157
- function getDocValue(doc, path, defalutValue) {
149
+ var import_utils4 = require("@web-ts-toolkit/utils");
150
+ function isDocument(doc) {
151
+ return doc instanceof import_mongoose.Document;
152
+ }
153
+ function getDocValue(doc, path, defaultValue) {
158
154
  if (isDocument(doc)) {
159
- return (0, import_utils4.get)(doc._doc, path, defalutValue);
160
- } else if ((0, import_utils4.isPlainObject)(doc)) {
161
- return (0, import_utils4.get)(doc, path, defalutValue);
155
+ return (0, import_utils3.get)(doc._doc, path, defaultValue);
156
+ } else if ((0, import_utils3.isPlainObject)(doc)) {
157
+ return (0, import_utils3.get)(doc, path, defaultValue);
162
158
  }
163
159
  }
164
160
  function setDocValue(doc, path, value) {
165
161
  if (isDocument(doc)) {
166
- (0, import_utils4.set)(doc._doc, path, value);
167
- } else if ((0, import_utils4.isPlainObject)(doc)) {
168
- (0, import_utils4.set)(doc, path, value);
162
+ (0, import_utils3.set)(doc._doc, path, value);
163
+ } else if ((0, import_utils3.isPlainObject)(doc)) {
164
+ (0, import_utils3.set)(doc, path, value);
169
165
  }
170
166
  }
171
167
  function getDocPermissions(modelName, doc) {
@@ -177,10 +173,10 @@ function toObject(doc) {
177
173
  }
178
174
  function pickDocFields(doc, fields = []) {
179
175
  if (isDocument(doc)) {
180
- doc._doc = (0, import_utils4.pick)(doc._doc, fields);
176
+ doc._doc = (0, import_utils3.pick)(doc._doc, fields);
181
177
  return doc;
182
178
  } else {
183
- return (0, import_utils4.pick)(doc, fields);
179
+ return (0, import_utils3.pick)(doc, fields);
184
180
  }
185
181
  }
186
182
  async function populateDoc(doc, target) {
@@ -253,35 +249,47 @@ function handleResultError(result) {
253
249
  }
254
250
 
255
251
  // src/helpers/index.ts
252
+ var import_utils6 = require("@web-ts-toolkit/utils");
253
+
254
+ // src/lib.ts
255
+ var import_mongoose2 = require("mongoose");
256
256
  var import_utils5 = require("@web-ts-toolkit/utils");
257
+ var isSchema = (val) => val instanceof import_mongoose2.Schema;
258
+ var isObjectIdType = (val) => val === "ObjectId" || val === import_mongoose2.Schema.Types.ObjectId;
259
+ var isReference = (val) => (0, import_utils5.isPlainObject)(val) && !!val.ref && isObjectIdType(val.type);
260
+ var isDocument2 = function isDocument3(doc) {
261
+ return doc instanceof import_mongoose2.Document;
262
+ };
263
+
264
+ // src/helpers/index.ts
257
265
  function recurseObject(obj) {
258
266
  if (isSchema(obj)) {
259
267
  return buildRefs(obj.tree);
260
268
  }
261
- if (!(0, import_utils5.isObject)(obj)) return null;
269
+ if (!(0, import_utils6.isObject)(obj)) return null;
262
270
  if (isReference(obj)) {
263
271
  return obj.ref;
264
272
  }
265
273
  let ret = null;
266
- (0, import_utils5.forEach)(obj, (val) => {
274
+ (0, import_utils6.forEach)(obj, (val) => {
267
275
  ret = recurseObject(val);
268
- if (!(0, import_utils5.isEmpty)(ret)) {
276
+ if (!(0, import_utils6.isEmpty)(ret)) {
269
277
  return false;
270
278
  }
271
279
  });
272
280
  return ret;
273
281
  }
274
282
  function buildRefs(schema) {
275
- if (!(0, import_utils5.isObject)(schema)) return {};
283
+ if (!(0, import_utils6.isObject)(schema)) return {};
276
284
  const references = {};
277
- (0, import_utils5.forEach)(schema, (val, key) => {
285
+ (0, import_utils6.forEach)(schema, (val, key) => {
278
286
  const paths = recurseObject(val);
279
- if (!(0, import_utils5.isEmpty)(paths)) {
287
+ if (!(0, import_utils6.isEmpty)(paths)) {
280
288
  references[key] = paths;
281
289
  }
282
- const target = (0, import_utils5.isObject)(val) && "type" in val ? val.type ?? val : val;
283
- if ((0, import_utils5.isArray)(target) && target.length > 0) {
284
- if (isSchema(target[0]) || (0, import_utils5.isPlainObject)(target[0])) {
290
+ const target = (0, import_utils6.isObject)(val) && "type" in val ? val.type ?? val : val;
291
+ if ((0, import_utils6.isArray)(target) && target.length > 0) {
292
+ if (isSchema(target[0]) || (0, import_utils6.isPlainObject)(target[0])) {
285
293
  return;
286
294
  }
287
295
  }
@@ -289,12 +297,12 @@ function buildRefs(schema) {
289
297
  return references;
290
298
  }
291
299
  function buildSubPaths(schema) {
292
- if (!(0, import_utils5.isObject)(schema)) return [];
300
+ if (!(0, import_utils6.isObject)(schema)) return [];
293
301
  const subPaths = [];
294
- (0, import_utils5.forEach)(schema, (val, key) => {
295
- const target = (0, import_utils5.isObject)(val) && "type" in val ? val.type ?? val : val;
296
- if ((0, import_utils5.isArray)(target) && target.length > 0) {
297
- if (isSchema(target[0]) || (0, import_utils5.isPlainObject)(target[0]) && !isReference(target[0])) {
302
+ (0, import_utils6.forEach)(schema, (val, key) => {
303
+ const target = (0, import_utils6.isObject)(val) && "type" in val ? val.type ?? val : val;
304
+ if ((0, import_utils6.isArray)(target) && target.length > 0) {
305
+ if (isSchema(target[0]) || (0, import_utils6.isPlainObject)(target[0]) && !isReference(target[0])) {
298
306
  subPaths.push(key);
299
307
  }
300
308
  }
@@ -302,11 +310,11 @@ function buildSubPaths(schema) {
302
310
  return subPaths;
303
311
  }
304
312
  async function iterateQuery(query, handler) {
305
- if (!(0, import_utils5.isPlainObject)(query)) return query;
306
- if (!handler) return import_utils5.noop;
313
+ if (!(0, import_utils6.isPlainObject)(query)) return query;
314
+ if (!handler) return query;
307
315
  const queryObject = query;
308
- return (0, import_utils5.mapValuesAsync)(queryObject, async (val, key) => {
309
- if ((0, import_utils5.isPlainObject)(val)) {
316
+ return (0, import_utils6.mapValuesAsync)(queryObject, async (val, key) => {
317
+ if ((0, import_utils6.isPlainObject)(val)) {
310
318
  const plainValue = val;
311
319
  if (plainValue.$$sq) {
312
320
  return handler(0 /* SubQuery */, plainValue.$$sq, key);
@@ -316,7 +324,7 @@ async function iterateQuery(query, handler) {
316
324
  return iterateQuery(val, handler);
317
325
  }
318
326
  }
319
- if ((0, import_utils5.isArray)(val)) {
327
+ if ((0, import_utils6.isArray)(val)) {
320
328
  return Promise.all(val.map((v) => iterateQuery(v, handler)));
321
329
  }
322
330
  return val;
@@ -325,13 +333,259 @@ async function iterateQuery(query, handler) {
325
333
  var createValidator = (fn) => {
326
334
  const stringHandler = (key) => key.trim().split(" ").every((v) => fn(v));
327
335
  const arrayHandler = (arr) => arr.some((item) => {
328
- if ((0, import_utils5.isString)(item)) return stringHandler(item);
329
- else if ((0, import_utils5.isArray)(item)) return arrayHandler(item);
336
+ if ((0, import_utils6.isString)(item)) return stringHandler(item);
337
+ else if ((0, import_utils6.isArray)(item)) return arrayHandler(item);
330
338
  else return false;
331
339
  });
332
340
  return { stringHandler, arrayHandler };
333
341
  };
334
342
 
343
+ // src/openapi/build-spec.ts
344
+ var import_utils8 = require("@web-ts-toolkit/utils");
345
+
346
+ // src/openapi/responses.ts
347
+ var json = (schema) => ({
348
+ content: {
349
+ "application/json": {
350
+ schema
351
+ }
352
+ }
353
+ });
354
+ var problemJson = {
355
+ content: {
356
+ "application/problem+json": {
357
+ schema: {
358
+ type: "object",
359
+ properties: {
360
+ type: { type: "string" },
361
+ title: { type: "string" },
362
+ status: { type: "number" },
363
+ detail: { type: "string" },
364
+ errors: { type: "array", items: {} }
365
+ },
366
+ additionalProperties: true
367
+ }
368
+ }
369
+ }
370
+ };
371
+ var genericDataSchema = { type: "object", additionalProperties: true };
372
+ var genericListSchema = { type: "array", items: genericDataSchema };
373
+ var openApiResponses = {
374
+ single(description = "Success") {
375
+ return {
376
+ 200: { description, ...json(genericDataSchema) },
377
+ 400: { description: "Bad Request", ...problemJson },
378
+ 401: { description: "Unauthorized", ...problemJson },
379
+ 404: { description: "Not Found", ...problemJson }
380
+ };
381
+ },
382
+ list(description = "Success") {
383
+ return {
384
+ 200: { description, ...json(genericListSchema) },
385
+ 400: { description: "Bad Request", ...problemJson },
386
+ 401: { description: "Unauthorized", ...problemJson }
387
+ };
388
+ },
389
+ create(description = "Created") {
390
+ return {
391
+ 201: { description, ...json(genericDataSchema) },
392
+ 400: { description: "Bad Request", ...problemJson },
393
+ 401: { description: "Unauthorized", ...problemJson }
394
+ };
395
+ },
396
+ delete(description = "Deleted") {
397
+ return {
398
+ 200: { description, ...json(genericDataSchema) },
399
+ 400: { description: "Bad Request", ...problemJson },
400
+ 401: { description: "Unauthorized", ...problemJson },
401
+ 404: { description: "Not Found", ...problemJson }
402
+ };
403
+ },
404
+ batch(description = "Success") {
405
+ return {
406
+ 200: { description, ...json(genericListSchema) },
407
+ 400: { description: "Bad Request", ...problemJson },
408
+ 401: { description: "Unauthorized", ...problemJson }
409
+ };
410
+ }
411
+ };
412
+
413
+ // src/openapi/schemas.ts
414
+ var import_zod = require("zod");
415
+ var import_utils7 = require("@web-ts-toolkit/utils");
416
+ var fallbackObjectSchema = { type: "object", additionalProperties: true };
417
+ function patchOpenApiObjectSchema(source, properties) {
418
+ return {
419
+ kind: "objectProperties",
420
+ source,
421
+ properties
422
+ };
423
+ }
424
+ function defineOpenApiSchemaResolver(resolve) {
425
+ return {
426
+ kind: "schemaResolver",
427
+ resolve
428
+ };
429
+ }
430
+ function getNestedOpenApiSchemaDataSource(source) {
431
+ return (0, import_utils7.isPlainObject)(source) && "data" in source ? source.data : void 0;
432
+ }
433
+ function unwrapNestedOpenApiSchemaSource(source, fallback) {
434
+ if ((0, import_utils7.isPlainObject)(source) && ("default" in source || "data" in source)) {
435
+ return source.default ?? fallback;
436
+ }
437
+ return source ?? fallback;
438
+ }
439
+ function isOpenApiSchemaPatch(source) {
440
+ return (0, import_utils7.isPlainObject)(source) && source.kind === "objectProperties";
441
+ }
442
+ function isOpenApiSchemaResolver(source) {
443
+ return (0, import_utils7.isPlainObject)(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
444
+ }
445
+ function isJsonSchemaLike(source) {
446
+ return (0, import_utils7.isPlainObject)(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
447
+ }
448
+ function hasOpenApiSchema(source) {
449
+ return (0, import_utils7.isPlainObject)(source) && isJsonSchemaLike(source.openapi);
450
+ }
451
+ function toOpenApiSchema(source) {
452
+ if (!source) return void 0;
453
+ const resolvedSource = isOpenApiSchemaResolver(source) ? source.resolve() : source;
454
+ if (!resolvedSource) return void 0;
455
+ if (isOpenApiSchemaPatch(resolvedSource)) {
456
+ const schema = toOpenApiSchema(resolvedSource.source) ?? { ...fallbackObjectSchema };
457
+ const properties = (0, import_utils7.isPlainObject)(schema.properties) ? { ...schema.properties } : {};
458
+ for (const [key, value] of Object.entries(resolvedSource.properties)) {
459
+ properties[key] = toOpenApiSchema(value) ?? fallbackObjectSchema;
460
+ }
461
+ return {
462
+ ...schema,
463
+ type: schema.type ?? "object",
464
+ properties
465
+ };
466
+ }
467
+ if (hasOpenApiSchema(resolvedSource)) {
468
+ return resolvedSource.openapi;
469
+ }
470
+ if (isJsonSchemaLike(resolvedSource)) {
471
+ return resolvedSource;
472
+ }
473
+ try {
474
+ return import_zod.z.toJSONSchema(resolvedSource);
475
+ } catch {
476
+ return fallbackObjectSchema;
477
+ }
478
+ }
479
+
480
+ // src/openapi/build-spec.ts
481
+ var openApiMediaType = "application/json";
482
+ var normalizePath = (path) => {
483
+ if (!path) return "/";
484
+ return path.startsWith("/") ? path : `/${path}`;
485
+ };
486
+ var toOpenApiPath = (path) => normalizePath(path).replace(/:([A-Za-z0-9_]+)/g, "{$1}");
487
+ var schemaToQueryParameters = (schema) => {
488
+ const jsonSchema = toOpenApiSchema(schema);
489
+ if (!jsonSchema || jsonSchema.type !== "object") return [];
490
+ const properties = (0, import_utils8.isPlainObject)(jsonSchema.properties) ? jsonSchema.properties : {};
491
+ const required = new Set(
492
+ (0, import_utils8.isArray)(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
493
+ );
494
+ return Object.entries(properties).map(([name, value]) => ({
495
+ name,
496
+ in: "query",
497
+ required: required.has(name),
498
+ schema: value
499
+ }));
500
+ };
501
+ var schemaToPathParameters = (path, pathParams) => {
502
+ const names = [...toOpenApiPath(path).matchAll(/\{([^}]+)\}/g)].map((item) => item[1]);
503
+ return names.map((name) => ({
504
+ name,
505
+ in: "path",
506
+ required: true,
507
+ schema: (pathParams && name in pathParams ? toOpenApiSchema(pathParams[name]) : void 0) ?? { type: "string" }
508
+ }));
509
+ };
510
+ var getDefaultResponses = (route) => {
511
+ if (route.operationId === "root.query") return openApiResponses.batch();
512
+ if (route.method === "delete") return openApiResponses.delete();
513
+ if (route.operationId?.toLowerCase().includes("create")) return openApiResponses.create();
514
+ if (route.operationId?.toLowerCase().includes("list")) return openApiResponses.list();
515
+ if (route.operationId?.toLowerCase().includes("distinct")) return openApiResponses.list();
516
+ return openApiResponses.single();
517
+ };
518
+ var buildOperation = (route) => {
519
+ const queryParameters = schemaToQueryParameters(route.query);
520
+ const pathParameters = schemaToPathParameters(route.path, route.pathParams);
521
+ const bodySchema = toOpenApiSchema(route.body);
522
+ const responses = route.responses ?? getDefaultResponses(route);
523
+ const operation = {
524
+ operationId: route.operationId,
525
+ summary: route.summary,
526
+ description: route.description,
527
+ tags: route.tags,
528
+ deprecated: route.deprecated,
529
+ responses
530
+ };
531
+ const parameters = [...pathParameters, ...queryParameters];
532
+ if (parameters.length) {
533
+ operation.parameters = parameters;
534
+ }
535
+ if (bodySchema) {
536
+ operation.requestBody = {
537
+ required: true,
538
+ content: {
539
+ [openApiMediaType]: {
540
+ schema: bodySchema
541
+ }
542
+ }
543
+ };
544
+ }
545
+ if (route.acl) {
546
+ operation["x-access-router-acl"] = route.acl;
547
+ }
548
+ return operation;
549
+ };
550
+ function buildOpenApiSpec(routes, options) {
551
+ const paths = {};
552
+ const { servers, ...info } = options;
553
+ for (const route of routes) {
554
+ const path = toOpenApiPath(route.path);
555
+ if (!paths[path]) {
556
+ paths[path] = {};
557
+ }
558
+ paths[path][route.method] = buildOperation(route);
559
+ }
560
+ return {
561
+ openapi: "3.1.0",
562
+ info,
563
+ servers,
564
+ paths
565
+ };
566
+ }
567
+
568
+ // src/openapi/registry.ts
569
+ var OpenApiRegistry = class {
570
+ constructor() {
571
+ this.routes = [];
572
+ }
573
+ register(route) {
574
+ const existingIndex = this.routes.findIndex((item) => item.method === route.method && item.path === route.path);
575
+ if (existingIndex === -1) {
576
+ this.routes.push(route);
577
+ return;
578
+ }
579
+ this.routes[existingIndex] = route;
580
+ }
581
+ getRoutes() {
582
+ return [...this.routes];
583
+ }
584
+ getSpec(info) {
585
+ return buildOpenApiSpec(this.routes, info);
586
+ }
587
+ };
588
+
335
589
  // src/logger-default.ts
336
590
  var import_node_util = __toESM(require("util"));
337
591
  var import_winston = require("winston");
@@ -359,7 +613,7 @@ var defaultLogger = (0, import_winston.createLogger)({
359
613
  });
360
614
 
361
615
  // src/options/manager.ts
362
- var import_utils6 = require("@web-ts-toolkit/utils");
616
+ var import_utils9 = require("@web-ts-toolkit/utils");
363
617
  var getNestedOption = (manager, key, defaultValue) => {
364
618
  const keys2 = String(key).split(".");
365
619
  if (keys2.length === 1) {
@@ -396,26 +650,26 @@ var OptionsManager = class {
396
650
  return this;
397
651
  }
398
652
  get(key, defaultValue) {
399
- return (0, import_utils6.get)(this.currentOptions, key, defaultValue);
653
+ return (0, import_utils9.get)(this.currentOptions, key, defaultValue);
400
654
  }
401
655
  set(key, value) {
402
- (0, import_utils6.set)(this.currentOptions, key, value);
656
+ (0, import_utils9.set)(this.currentOptions, key, value);
403
657
  }
404
658
  fetch() {
405
659
  return { ...this.currentOptions };
406
660
  }
407
661
  assign(options) {
408
- (0, import_utils6.assign)(this.currentOptions, options);
662
+ (0, import_utils9.assign)(this.currentOptions, options);
409
663
  }
410
664
  onchange(key, func) {
411
- (0, import_utils6.set)(this.listeners, key, func);
665
+ (0, import_utils9.set)(this.listeners, key, func);
412
666
  return this;
413
667
  }
414
668
  };
415
669
 
416
670
  // src/runtime.ts
417
- (0, import_mongoose_schema_jsonschema.default)(import_mongoose2.default);
418
- var pluralize = import_mongoose2.default.pluralize();
671
+ (0, import_mongoose_schema_jsonschema.default)(import_mongoose3.default);
672
+ var pluralize = import_mongoose3.default.pluralize();
419
673
  var FIELD_ACCESS_KEYS = ["list", "create", "read", "update"];
420
674
  var defaultModelOptions = {
421
675
  basePath: null,
@@ -426,44 +680,44 @@ var defaultDataOptions = {
426
680
  queryRouteSegment: "__query"
427
681
  };
428
682
  var normalizeBasePath = (name, value) => {
429
- if ((0, import_utils7.isNil)(value)) {
683
+ if ((0, import_utils10.isNil)(value)) {
430
684
  return `/${pluralize(name)}`;
431
685
  }
432
- return (0, import_utils7.isString)(value) ? (0, import_utils7.addLeadingSlash)(value) : "";
686
+ return (0, import_utils10.isString)(value) ? (0, import_utils10.addLeadingSlash)(value) : "";
433
687
  };
434
688
  var hasModelPermission = (value, modelPermissionPrefix) => {
435
689
  if (!modelPermissionPrefix) {
436
690
  return true;
437
691
  }
438
- if ((0, import_utils7.isString)(value)) {
692
+ if ((0, import_utils10.isString)(value)) {
439
693
  return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
440
694
  }
441
- if ((0, import_utils7.isArray)(value)) {
695
+ if ((0, import_utils10.isArray)(value)) {
442
696
  return value.some((item) => {
443
- if ((0, import_utils7.isString)(item) || (0, import_utils7.isArray)(item)) {
697
+ if ((0, import_utils10.isString)(item) || (0, import_utils10.isArray)(item)) {
444
698
  return hasModelPermission(item, modelPermissionPrefix);
445
699
  }
446
700
  return true;
447
701
  });
448
702
  }
449
- return (0, import_utils7.isFunction)(value);
703
+ return (0, import_utils10.isFunction)(value);
450
704
  };
451
705
  var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
452
706
  const schemaKeys = Object.keys(permissionSchema);
453
707
  const globalPermissionKeys = {};
454
708
  const modelPermissionKeys = {};
455
- (0, import_utils7.forEach)(schemaKeys, (schemaKey) => {
709
+ (0, import_utils10.forEach)(schemaKeys, (schemaKey) => {
456
710
  const schemaRule = permissionSchema[schemaKey];
457
- const ruleEntries = (0, import_utils7.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
711
+ const ruleEntries = (0, import_utils10.isPlainObject)(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
458
712
  for (let x = 0; x < ruleEntries.length; x++) {
459
713
  const [accessKey, value] = ruleEntries[x];
460
- if (!(0, import_utils7.isArray)(globalPermissionKeys[accessKey])) {
714
+ if (!(0, import_utils10.isArray)(globalPermissionKeys[accessKey])) {
461
715
  globalPermissionKeys[accessKey] = [];
462
716
  }
463
- if (!(0, import_utils7.isArray)(modelPermissionKeys[accessKey])) {
717
+ if (!(0, import_utils10.isArray)(modelPermissionKeys[accessKey])) {
464
718
  modelPermissionKeys[accessKey] = [];
465
719
  }
466
- if ((0, import_utils7.isBoolean)(value)) {
720
+ if ((0, import_utils10.isBoolean)(value)) {
467
721
  globalPermissionKeys[accessKey].push(schemaKey);
468
722
  return;
469
723
  }
@@ -504,6 +758,16 @@ var AccessRuntime = class {
504
758
  this.modelRefs = {};
505
759
  this.modelSubs = {};
506
760
  this.modelAtts = {};
761
+ this.openApiRegistry = new OpenApiRegistry();
762
+ }
763
+ registerOpenApiRoute(route) {
764
+ this.openApiRegistry.register(route);
765
+ }
766
+ getOpenApiRoutes() {
767
+ return this.openApiRegistry.getRoutes();
768
+ }
769
+ getOpenApiSpec(info) {
770
+ return this.openApiRegistry.getSpec(info);
507
771
  }
508
772
  setGlobalOptions(options) {
509
773
  this.globalOptions.assign(options);
@@ -530,7 +794,7 @@ var AccessRuntime = class {
530
794
  return this.defaultModelOptions.get(key, defaultValue);
531
795
  }
532
796
  createModelOptions(modelName) {
533
- const model = import_mongoose2.default.model(modelName);
797
+ const model = import_mongoose3.default.model(modelName);
534
798
  const manager = new OptionsManager({
535
799
  ...defaultModelOptions,
536
800
  modelName
@@ -547,7 +811,7 @@ var AccessRuntime = class {
547
811
  }).onchange("basePath", function(newval, key, target) {
548
812
  target[key] = normalizeBasePath(
549
813
  modelName,
550
- (0, import_utils7.isString)(newval) || (0, import_utils7.isNil)(newval) ? newval : void 0
814
+ (0, import_utils10.isString)(newval) || (0, import_utils10.isNil)(newval) ? newval : void 0
551
815
  );
552
816
  }).build();
553
817
  this.modelJsonSchemas[modelName] = model.jsonSchema();
@@ -605,7 +869,7 @@ var AccessRuntime = class {
605
869
  manager.onchange("basePath", function(newval, key, target) {
606
870
  target[key] = normalizeBasePath(
607
871
  dataName,
608
- (0, import_utils7.isString)(newval) || (0, import_utils7.isNil)(newval) ? newval : void 0
872
+ (0, import_utils10.isString)(newval) || (0, import_utils10.isNil)(newval) ? newval : void 0
609
873
  );
610
874
  }).build();
611
875
  return manager;
@@ -646,7 +910,7 @@ var AccessRuntime = class {
646
910
  if (modelName in this.modelRefs && modelName in this.modelSubs && modelName in this.modelAtts) {
647
911
  return;
648
912
  }
649
- const model = import_mongoose2.default.models[modelName];
913
+ const model = import_mongoose3.default.models[modelName];
650
914
  if (!model) {
651
915
  this.modelRefs[modelName] = this.modelRefs[modelName] ?? {};
652
916
  this.modelSubs[modelName] = this.modelSubs[modelName] ?? [];
@@ -656,26 +920,26 @@ var AccessRuntime = class {
656
920
  const schema = model.schema;
657
921
  this.modelRefs[modelName] = buildRefs(schema.tree);
658
922
  this.modelSubs[modelName] = buildSubPaths(schema.tree);
659
- this.modelAtts[modelName] = (0, import_utils7.keys)(schema.obj);
923
+ this.modelAtts[modelName] = (0, import_utils10.keys)(schema.obj);
660
924
  }
661
925
  getModelRef(modelName, refPath) {
662
926
  this.ensureModelMeta(modelName);
663
- return (0, import_utils7.get)(this.modelRefs, `${modelName}.${refPath}`, null);
927
+ return (0, import_utils10.get)(this.modelRefs, `${modelName}.${refPath}`, null);
664
928
  }
665
929
  getModelSub(modelName) {
666
930
  this.ensureModelMeta(modelName);
667
- return (0, import_utils7.get)(this.modelSubs, modelName, []);
931
+ return (0, import_utils10.get)(this.modelSubs, modelName, []);
668
932
  }
669
933
  getModelAtt(modelName) {
670
934
  this.ensureModelMeta(modelName);
671
- return (0, import_utils7.get)(this.modelAtts, modelName, []);
935
+ return (0, import_utils10.get)(this.modelAtts, modelName, []);
672
936
  }
673
937
  };
674
938
  var defaultRuntime = new AccessRuntime();
675
939
 
676
940
  // src/runtime-context.ts
677
941
  var import_node_async_hooks = require("async_hooks");
678
- var import_mongoose3 = __toESM(require("mongoose"));
942
+ var import_mongoose4 = __toESM(require("mongoose"));
679
943
  var ACCESS_RUNTIME = /* @__PURE__ */ Symbol("access-runtime");
680
944
  var runtimeStorage = new import_node_async_hooks.AsyncLocalStorage();
681
945
  function runWithRuntime(runtime, callback) {
@@ -685,13 +949,13 @@ function getActiveRuntime() {
685
949
  return runtimeStorage.getStore() ?? null;
686
950
  }
687
951
  function attachRuntimeToModel(modelName, runtime) {
688
- const model = import_mongoose3.default.models[modelName];
952
+ const model = import_mongoose4.default.models[modelName];
689
953
  if (model) {
690
954
  model[ACCESS_RUNTIME] = runtime;
691
955
  }
692
956
  }
693
957
  function getRuntimeForModelName(modelName) {
694
- const model = import_mongoose3.default.models[modelName];
958
+ const model = import_mongoose4.default.models[modelName];
695
959
  return model?.[ACCESS_RUNTIME] ?? null;
696
960
  }
697
961
 
@@ -768,16 +1032,16 @@ var getModelSub = (modelName) => {
768
1032
  };
769
1033
 
770
1034
  // src/services/base.ts
771
- var import_utils8 = require("@web-ts-toolkit/utils");
1035
+ var import_utils11 = require("@web-ts-toolkit/utils");
772
1036
  function validateClientFilter(filter2) {
773
1037
  const errors = [];
774
1038
  const blockedOperators = /* @__PURE__ */ new Set(["$where", "$expr", "$function", "$accumulator"]);
775
1039
  const visit = (value, path) => {
776
- if ((0, import_utils8.isArray)(value)) {
1040
+ if ((0, import_utils11.isArray)(value)) {
777
1041
  value.forEach((item, index) => visit(item, `${path}[${index}]`));
778
1042
  return;
779
1043
  }
780
- if (!(0, import_utils8.isPlainObject)(value)) return;
1044
+ if (!(0, import_utils11.isPlainObject)(value)) return;
781
1045
  Object.entries(value).forEach(([key, child]) => {
782
1046
  const nextPath = path ? `${path}.${key}` : key;
783
1047
  if (blockedOperators.has(key)) {
@@ -872,17 +1136,17 @@ var Base = class {
872
1136
  return validateClientFilter(filter2);
873
1137
  }
874
1138
  processInclude(include) {
875
- const includes = (0, import_utils8.compact)((0, import_utils8.castArray)(include)).filter(({ model, op, path, localField, foreignField }) => {
1139
+ const includes = (0, import_utils11.compact)((0, import_utils11.castArray)(include)).filter(({ model, op, path, localField, foreignField }) => {
876
1140
  return model && op && path && localField && foreignField;
877
1141
  });
878
1142
  let includeLocalFields = [];
879
1143
  let includePaths = [];
880
- (0, import_utils8.forEach)(includes, (inc) => {
1144
+ (0, import_utils11.forEach)(includes, (inc) => {
881
1145
  includeLocalFields.push(inc.localField);
882
1146
  includePaths.push(inc.path);
883
1147
  });
884
- includeLocalFields = (0, import_utils8.uniq)((0, import_utils8.compact)(includeLocalFields));
885
- includePaths = (0, import_utils8.uniq)((0, import_utils8.compact)(includePaths));
1148
+ includeLocalFields = (0, import_utils11.uniq)((0, import_utils11.compact)(includeLocalFields));
1149
+ includePaths = (0, import_utils11.uniq)((0, import_utils11.compact)(includePaths));
886
1150
  return {
887
1151
  includes,
888
1152
  includeLocalFields,
@@ -891,9 +1155,9 @@ var Base = class {
891
1155
  }
892
1156
  async includeDocs(docs, include) {
893
1157
  if (!include) return docs;
894
- const includes = (0, import_utils8.compact)((0, import_utils8.castArray)(include));
1158
+ const includes = (0, import_utils11.compact)((0, import_utils11.castArray)(include));
895
1159
  if (includes.length === 0) return docs;
896
- const isSingle = !(0, import_utils8.isArray)(docs);
1160
+ const isSingle = !(0, import_utils11.isArray)(docs);
897
1161
  if (isSingle) docs = [docs];
898
1162
  for (let x = 0; x < includes.length; x++) {
899
1163
  const include2 = includes[x];
@@ -910,10 +1174,10 @@ var Base = class {
910
1174
  const svc = this.req.macl.getPublicService(model);
911
1175
  if (!svc) return docs;
912
1176
  const includeLocalValues = [];
913
- (0, import_utils8.forEach)(docs, (doc, i) => {
914
- includeLocalValues.push((0, import_utils8.get)(doc, localField));
1177
+ (0, import_utils11.forEach)(docs, (doc, i) => {
1178
+ includeLocalValues.push((0, import_utils11.get)(doc, localField));
915
1179
  });
916
- const filter2 = { ..._filters ?? {}, [foreignField]: { $in: (0, import_utils8.flatten)(includeLocalValues) } };
1180
+ const filter2 = { ..._filters ?? {}, [foreignField]: { $in: (0, import_utils11.flatten)(includeLocalValues) } };
917
1181
  const result = await svc.find(filter2, args, {
918
1182
  ...options,
919
1183
  lean: true,
@@ -923,8 +1187,8 @@ var Base = class {
923
1187
  if (!result.success) return docs;
924
1188
  for (let y = 0; y < docs.length; y++) {
925
1189
  const doc = docs[y];
926
- const localValue = (0, import_utils8.get)(doc, localField);
927
- const filterFn = (row) => (0, import_utils8.intersectionBy)((0, import_utils8.castArray)(localValue), (0, import_utils8.castArray)((0, import_utils8.get)(row, foreignField)), String).length > 0;
1190
+ const localValue = (0, import_utils11.get)(doc, localField);
1191
+ const filterFn = (row) => (0, import_utils11.intersectionBy)((0, import_utils11.castArray)(localValue), (0, import_utils11.castArray)((0, import_utils11.get)(row, foreignField)), String).length > 0;
928
1192
  const matches = result.data.filter(filterFn);
929
1193
  setDocValue(doc, path, op === "list" ? matches : matches[0]);
930
1194
  }
@@ -936,7 +1200,7 @@ var Base = class {
936
1200
  if (!svc) return docs;
937
1201
  for (let y = 0; y < docs.length; y++) {
938
1202
  const doc = docs[y];
939
- const localValue = (0, import_utils8.get)(doc, localField);
1203
+ const localValue = (0, import_utils11.get)(doc, localField);
940
1204
  const filter2 = { ..._filters ?? {}, [foreignField]: localValue };
941
1205
  const result = await svc.count(filter2);
942
1206
  if (!result.success) continue;
@@ -978,28 +1242,45 @@ var Base = class {
978
1242
  if (!result.success) return null;
979
1243
  let ret = result.data;
980
1244
  if (sqOptions.path) {
981
- ret = (0, import_utils8.isArray)(ret) ? (0, import_utils8.flatten)(ret.map((v) => (0, import_utils8.get)(v, sqOptions.path))) : (0, import_utils8.get)(ret, sqOptions.path);
1245
+ ret = (0, import_utils11.isArray)(ret) ? (0, import_utils11.flatten)(ret.map((v) => (0, import_utils11.get)(v, sqOptions.path))) : (0, import_utils11.get)(ret, sqOptions.path);
982
1246
  }
983
1247
  if (sqOptions.compact) {
984
- ret = (0, import_utils8.compact)((0, import_utils8.castArray)(ret));
1248
+ ret = (0, import_utils11.compact)((0, import_utils11.castArray)(ret));
985
1249
  }
986
1250
  return ret;
987
1251
  }
988
- async handleDate(val, key) {
1252
+ handleDate(val, key) {
1253
+ if (val instanceof Date) return val;
1254
+ if (typeof val === "string" || typeof val === "number") return new Date(val);
989
1255
  return /* @__PURE__ */ new Date();
990
1256
  }
991
1257
  };
992
1258
 
993
1259
  // src/services/service.ts
994
- var import_utils10 = require("@web-ts-toolkit/utils");
1260
+ var import_utils13 = require("@web-ts-toolkit/utils");
995
1261
  var import_deep_diff = __toESM(require("deep-diff"));
996
1262
 
997
1263
  // src/model.ts
998
- var import_mongoose4 = __toESM(require("mongoose"));
1264
+ var import_mongoose5 = __toESM(require("mongoose"));
1265
+
1266
+ // src/logger.ts
1267
+ var passthrough = (level) => (...args) => {
1268
+ const globalLogger = getGlobalOption("logger");
1269
+ const target = globalLogger?.[level] ?? defaultLogger[level];
1270
+ return target.apply(globalLogger ?? defaultLogger, args);
1271
+ };
1272
+ var logger = {
1273
+ debug: passthrough("debug"),
1274
+ info: passthrough("info"),
1275
+ warn: passthrough("warn"),
1276
+ error: passthrough("error")
1277
+ };
1278
+
1279
+ // src/model.ts
999
1280
  var Model = class {
1000
1281
  constructor(modelName) {
1001
1282
  this.modelName = modelName;
1002
- this.model = import_mongoose4.default.model(modelName);
1283
+ this.model = import_mongoose5.default.model(modelName);
1003
1284
  if (!this.model) return;
1004
1285
  this.model.schema.set("optimisticConcurrency", true);
1005
1286
  const currVersionKey = this.model.schema.get("versionKey");
@@ -1025,12 +1306,15 @@ var Model = class {
1025
1306
  if (lean) builder.lean();
1026
1307
  return builder;
1027
1308
  }
1028
- // See https://github.com/Automattic/mongoose/blob/65b2d12a8f85f86136cfaf32947f338ba0c5f451/lib/query.js#L3011
1029
- validateSort(sort, logError = console.error) {
1309
+ validateSort(sort, logError = logger.error) {
1030
1310
  const validSortOrders = [1, -1, "asc", "ascending", "desc", "descending"];
1311
+ const fieldPathPattern = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/;
1312
+ const isValidFieldPath = (field) => fieldPathPattern.test(field);
1031
1313
  if (sort === null || sort === void 0) return true;
1032
1314
  if (typeof sort === "string") {
1033
- if (!/^[a-zA-Z0-9\s-]+/.test(sort)) {
1315
+ const fields = sort.trim().split(/\s+/).filter(Boolean);
1316
+ const isValid = fields.every((field) => isValidFieldPath(field.startsWith("-") ? field.slice(1) : field));
1317
+ if (!isValid) {
1034
1318
  logError("Invalid sort string:", sort);
1035
1319
  return false;
1036
1320
  }
@@ -1043,8 +1327,8 @@ var Model = class {
1043
1327
  return false;
1044
1328
  }
1045
1329
  const [key, order] = pair;
1046
- if (typeof key !== "string") {
1047
- logError("Invalid sort array key: must be string", key);
1330
+ if (typeof key !== "string" || !isValidFieldPath(key)) {
1331
+ logError("Invalid sort array key: must be a field path string", key);
1048
1332
  return false;
1049
1333
  }
1050
1334
  if (!validSortOrders.includes(order)) {
@@ -1056,7 +1340,11 @@ var Model = class {
1056
1340
  return isValid;
1057
1341
  }
1058
1342
  if (typeof sort === "object" && !(sort instanceof Map)) {
1059
- const isValid = Object.values(sort).every((order) => {
1343
+ const isValid = Object.entries(sort).every(([key, order]) => {
1344
+ if (!isValidFieldPath(key)) {
1345
+ logError("Invalid sort object key: must be a field path string", key);
1346
+ return false;
1347
+ }
1060
1348
  if (!validSortOrders.includes(order)) {
1061
1349
  logError('Invalid sort object value: must be 1, -1, "asc", or "desc"', order);
1062
1350
  return false;
@@ -1066,7 +1354,11 @@ var Model = class {
1066
1354
  return isValid;
1067
1355
  }
1068
1356
  if (sort instanceof Map) {
1069
- const isValid = Array.from(sort.values()).every((order) => {
1357
+ const isValid = Array.from(sort.entries()).every(([key, order]) => {
1358
+ if (!isValidFieldPath(key)) {
1359
+ logError("Invalid sort Map key: must be a field path string", key);
1360
+ return false;
1361
+ }
1070
1362
  if (!validSortOrders.includes(order)) {
1071
1363
  logError('Invalid sort Map value: must be 1, -1, "asc", or "desc"', order);
1072
1364
  return false;
@@ -1089,9 +1381,6 @@ var Model = class {
1089
1381
  if (lean) builder.lean();
1090
1382
  return builder;
1091
1383
  }
1092
- findOneAndDelete(filter2) {
1093
- return this.model.findOneAndDelete(filter2);
1094
- }
1095
1384
  exists(filter2) {
1096
1385
  if (!filter2) return null;
1097
1386
  return this.findOne(filter2).select("_id").lean();
@@ -1100,10 +1389,6 @@ var Model = class {
1100
1389
  countDocuments(filter2 = {}) {
1101
1390
  return this.model.countDocuments(filter2);
1102
1391
  }
1103
- // see https://mongoosejs.com/docs/api.html#model_Model.estimatedDocumentCount
1104
- estimatedDocumentCount() {
1105
- return this.model.estimatedDocumentCount();
1106
- }
1107
1392
  // see https://mongoosejs.com/docs/api.html#model_Model.distinct
1108
1393
  distinct(field, conditions = {}) {
1109
1394
  return this.model.distinct(field, conditions);
@@ -1111,40 +1396,27 @@ var Model = class {
1111
1396
  };
1112
1397
  var model_default = Model;
1113
1398
 
1114
- // src/logger.ts
1115
- var passthrough = (level) => (...args) => {
1116
- const globalLogger = getGlobalOption("logger");
1117
- const target = globalLogger?.[level] ?? defaultLogger[level];
1118
- return target.apply(globalLogger ?? defaultLogger, args);
1119
- };
1120
- var logger = {
1121
- debug: passthrough("debug"),
1122
- info: passthrough("info"),
1123
- warn: passthrough("warn"),
1124
- error: passthrough("error")
1125
- };
1126
-
1127
1399
  // src/services/model-subdocument-service.ts
1128
- var import_utils9 = require("@web-ts-toolkit/utils");
1400
+ var import_utils12 = require("@web-ts-toolkit/utils");
1129
1401
  async function listSub(service, id, sub, options) {
1130
1402
  const { filter: ft, select } = options ?? {};
1131
1403
  const parentDoc = await getParentDoc(service, id, sub, null, { access: "read" });
1132
1404
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1133
- let result = (0, import_utils9.get)(parentDoc, sub);
1405
+ let result = (0, import_utils12.get)(parentDoc, sub);
1134
1406
  const [subFilter, subSelect] = await Promise.all([
1135
1407
  service.genFilter(`subs.${sub}.list`, ft),
1136
1408
  service.genQuerySelect("list", select, false, [sub, "sub"])
1137
1409
  ]);
1138
1410
  if (subFilter === false) return { success: false, code: "forbidden" /* Forbidden */ };
1139
1411
  result = filterCollection(result, subFilter);
1140
- if (subSelect) result = result.map((v) => (0, import_utils9.pick)(toObject(v), subSelect.concat("_id")));
1412
+ if (subSelect) result = result.map((v) => (0, import_utils12.pick)(toObject(v), subSelect.concat("_id")));
1141
1413
  return { success: true, kind: "list", code: "success" /* Success */, data: result, count: result.length };
1142
1414
  }
1143
1415
  async function readSub(service, id, sub, subId, options) {
1144
1416
  const { select, populate } = options ?? {};
1145
1417
  const parentDoc = await getParentDoc(service, id, sub, { populate }, { access: "read" });
1146
1418
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1147
- const result = (0, import_utils9.get)(parentDoc, sub);
1419
+ const result = (0, import_utils12.get)(parentDoc, sub);
1148
1420
  const [subFilter, subSelect] = await Promise.all([
1149
1421
  service.genFilter(`subs.${sub}.read`, { _id: subId }),
1150
1422
  service.genQuerySelect("read", select, false, [sub, "sub"])
@@ -1152,13 +1424,13 @@ async function readSub(service, id, sub, subId, options) {
1152
1424
  if (subFilter === false) return { success: false, code: "forbidden" /* Forbidden */ };
1153
1425
  let subdoc = findElement(result, subFilter);
1154
1426
  if (!subdoc) return { success: false, code: "not_found" /* NotFound */ };
1155
- if (subSelect) subdoc = (0, import_utils9.pick)(toObject(subdoc), subSelect.concat(["_id"]));
1427
+ if (subSelect) subdoc = (0, import_utils12.pick)(toObject(subdoc), subSelect.concat(["_id"]));
1156
1428
  return { success: true, kind: "single", code: "success" /* Success */, data: subdoc };
1157
1429
  }
1158
1430
  async function updateSub(service, id, sub, subId, data) {
1159
1431
  const parentDoc = await getParentDoc(service, id, sub, null, { access: "update" });
1160
1432
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1161
- const result = (0, import_utils9.get)(parentDoc, sub);
1433
+ const result = (0, import_utils12.get)(parentDoc, sub);
1162
1434
  const [subFilter, subReadSelect, subUpdateSelect] = await Promise.all([
1163
1435
  service.genFilter(`subs.${sub}.update`, { _id: subId }),
1164
1436
  service.genQuerySelect("read", null, false, [sub, "sub"]),
@@ -1167,16 +1439,16 @@ async function updateSub(service, id, sub, subId, data) {
1167
1439
  if (subFilter === false) return { success: false, code: "forbidden" /* Forbidden */ };
1168
1440
  let subdoc = findElement(result, subFilter);
1169
1441
  if (!subdoc) return { success: false, code: "not_found" /* NotFound */ };
1170
- const allowedData = (0, import_utils9.pick)(data, subUpdateSelect);
1442
+ const allowedData = (0, import_utils12.pick)(data, subUpdateSelect);
1171
1443
  Object.assign(subdoc, allowedData);
1172
1444
  await parentDoc.save();
1173
- if (subReadSelect) subdoc = (0, import_utils9.pick)(toObject(subdoc), subReadSelect.concat(["_id"]));
1445
+ if (subReadSelect) subdoc = (0, import_utils12.pick)(toObject(subdoc), subReadSelect.concat(["_id"]));
1174
1446
  return { success: true, kind: "single", code: "success" /* Success */, data: subdoc };
1175
1447
  }
1176
1448
  async function bulkUpdateSub(service, id, sub, data) {
1177
1449
  const parentDoc = await getParentDoc(service, id, sub, null, { access: "update" });
1178
1450
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1179
- let result = (0, import_utils9.get)(parentDoc, sub);
1451
+ let result = (0, import_utils12.get)(parentDoc, sub);
1180
1452
  const [subFilter, subReadSelect, subUpdateSelect] = await Promise.all([
1181
1453
  service.genFilter(`subs.${sub}.update`, { _id: { $in: data.map((v) => v._id) } }),
1182
1454
  service.genQuerySelect("read", null, false, [sub, "sub"]),
@@ -1184,35 +1456,35 @@ async function bulkUpdateSub(service, id, sub, data) {
1184
1456
  ]);
1185
1457
  if (subFilter === false) return { success: false, code: "forbidden" /* Forbidden */ };
1186
1458
  result = filterCollection(result, subFilter);
1187
- (0, import_utils9.forEach)(result, (subdoc) => {
1459
+ (0, import_utils12.forEach)(result, (subdoc) => {
1188
1460
  const tdata = findElementById(data, subdoc._id);
1189
1461
  if (!tdata) return;
1190
- const allowedData = (0, import_utils9.pick)(tdata, subUpdateSelect);
1462
+ const allowedData = (0, import_utils12.pick)(tdata, subUpdateSelect);
1191
1463
  Object.assign(subdoc, allowedData);
1192
1464
  });
1193
1465
  await parentDoc.save();
1194
- if (subReadSelect) result = result.map((v) => (0, import_utils9.pick)(toObject(v), subReadSelect.concat(["_id"])));
1466
+ if (subReadSelect) result = result.map((v) => (0, import_utils12.pick)(toObject(v), subReadSelect.concat(["_id"])));
1195
1467
  return { success: true, kind: "list", code: "success" /* Success */, data: result, count: result.length };
1196
1468
  }
1197
1469
  async function createSub(service, id, sub, data, options) {
1198
1470
  const { addFirst } = options ?? {};
1199
1471
  const parentDoc = await getParentDoc(service, id, sub, null, { access: "update" });
1200
1472
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1201
- let result = (0, import_utils9.get)(parentDoc, sub);
1473
+ let result = (0, import_utils12.get)(parentDoc, sub);
1202
1474
  const [subCreateSelect, subReadSelect] = await Promise.all([
1203
1475
  service.genQuerySelect("create", null, false, [sub, "sub"]),
1204
1476
  service.genQuerySelect("read", null, false, [sub, "sub"])
1205
1477
  ]);
1206
- const allowedData = (0, import_utils9.pick)(data, subCreateSelect);
1478
+ const allowedData = (0, import_utils12.pick)(data, subCreateSelect);
1207
1479
  addFirst === true ? result.unshift(allowedData) : result.push(allowedData);
1208
1480
  await parentDoc.save();
1209
- if (subReadSelect) result = result.map((v) => (0, import_utils9.pick)(toObject(v), subReadSelect.concat(["_id"])));
1481
+ if (subReadSelect) result = result.map((v) => (0, import_utils12.pick)(toObject(v), subReadSelect.concat(["_id"])));
1210
1482
  return { success: true, kind: "list", code: "created" /* Created */, data: result, count: result.length };
1211
1483
  }
1212
1484
  async function deleteSub(service, id, sub, subId) {
1213
1485
  const parentDoc = await getParentDoc(service, id, sub, null, { access: "update" });
1214
1486
  if (!parentDoc) return { success: false, code: "not_found" /* NotFound */ };
1215
- const result = (0, import_utils9.get)(parentDoc, sub);
1487
+ const result = (0, import_utils12.get)(parentDoc, sub);
1216
1488
  const subFilter = await service.genFilter(`subs.${sub}.delete`, { _id: subId });
1217
1489
  if (subFilter === false) return { success: false, code: "forbidden" /* Forbidden */ };
1218
1490
  const subdoc = findElement(result, subFilter);
@@ -1347,7 +1619,7 @@ function resolveExistsOptions(service, options = {}) {
1347
1619
 
1348
1620
  // src/services/service.ts
1349
1621
  var assertModelDocument = (value, modelName, hookName) => {
1350
- if (isDocument(value)) {
1622
+ if (isDocument2(value)) {
1351
1623
  return value;
1352
1624
  }
1353
1625
  throw new Error(`${hookName} hook for model=${modelName} must return a Mongoose document instance`);
@@ -1441,7 +1713,7 @@ var Service = class extends Base {
1441
1713
  genPagination({ skip, limit, page, pageSize }, this.options.listHardLimit)
1442
1714
  ]);
1443
1715
  const finalSelect = normalizeSelect(_select);
1444
- const filteredPopulate = (0, import_utils10.isArray)(finalSelect) && (0, import_utils10.isArray)(_populate) ? _populate.filter((p) => finalSelect.includes(p.path.split(".")[0])) : _populate;
1716
+ const filteredPopulate = (0, import_utils13.isArray)(finalSelect) && (0, import_utils13.isArray)(_populate) ? _populate.filter((p) => finalSelect.includes(p.path.split(".")[0])) : _populate;
1445
1717
  const { includes, includeLocalFields, includePaths } = this.processInclude(include);
1446
1718
  const query = {
1447
1719
  filter: _filter,
@@ -1463,7 +1735,7 @@ var Service = class extends Base {
1463
1735
  originalDocumentSnapshot: toObject(doc),
1464
1736
  resolvedQuery: query
1465
1737
  }));
1466
- const _decorate = (0, import_utils10.isFunction)(decorate) ? decorate : (v) => v;
1738
+ const _decorate = (0, import_utils13.isFunction)(decorate) ? decorate : (v) => v;
1467
1739
  docs = await this.includeDocs(docs, includes);
1468
1740
  const fieldPermissionAccess = includePermissions ? await this.getFieldPermissionAccess(docs.map((doc) => doc._id)) : void 0;
1469
1741
  docs = await Promise.all(
@@ -1515,16 +1787,16 @@ var Service = class extends Base {
1515
1787
  resolvedQuery: resolvedPopulate.length > 0 ? { populate: resolvedPopulate } : {}
1516
1788
  };
1517
1789
  const allowedFields = await this.genAllowedFields(item, "create");
1518
- const allowedData = (0, import_utils10.pick)(item, allowedFields);
1790
+ const allowedData = (0, import_utils13.pick)(item, allowedFields);
1519
1791
  context.allowedFields = allowedFields;
1520
1792
  context.allowedData = allowedData;
1521
1793
  const validated = await this.validate(allowedData, "create", context);
1522
- if ((0, import_utils10.isBoolean)(validated)) {
1794
+ if ((0, import_utils13.isBoolean)(validated)) {
1523
1795
  if (!validated) {
1524
1796
  validationError = { success: false, code: "bad_request" /* BadRequest */ };
1525
1797
  return;
1526
1798
  }
1527
- } else if ((0, import_utils10.isArray)(validated)) {
1799
+ } else if ((0, import_utils13.isArray)(validated)) {
1528
1800
  if (validated.length > 0) {
1529
1801
  validationError = { success: false, code: "bad_request" /* BadRequest */, errors: validated };
1530
1802
  return;
@@ -1537,7 +1809,7 @@ var Service = class extends Base {
1537
1809
  })
1538
1810
  );
1539
1811
  if (validationError) return validationError;
1540
- const _decorate = (0, import_utils10.isFunction)(decorate) ? decorate : (v) => v;
1812
+ const _decorate = (0, import_utils13.isFunction)(decorate) ? decorate : (v) => v;
1541
1813
  const createdDocs = await this.model.create(items);
1542
1814
  const docs = await Promise.all(
1543
1815
  createdDocs.map(async (doc, index) => {
@@ -1608,13 +1880,13 @@ var Service = class extends Base {
1608
1880
  context.docPermissions = this.getDocPermissions(doc);
1609
1881
  context.currentDocument = doc;
1610
1882
  const allowedFields = await this.genAllowedFields(doc, "update");
1611
- const allowedData = (0, import_utils10.pick)(data, allowedFields);
1883
+ const allowedData = (0, import_utils13.pick)(data, allowedFields);
1612
1884
  context.allowedFields = allowedFields;
1613
1885
  context.allowedData = allowedData;
1614
1886
  const validated = await this.validate(allowedData, "update", context);
1615
- if ((0, import_utils10.isBoolean)(validated)) {
1887
+ if ((0, import_utils13.isBoolean)(validated)) {
1616
1888
  if (!validated) return { success: false, code: "bad_request" /* BadRequest */ };
1617
- } else if ((0, import_utils10.isArray)(validated)) {
1889
+ } else if ((0, import_utils13.isArray)(validated)) {
1618
1890
  if (validated.length > 0) return { success: false, code: "bad_request" /* BadRequest */, errors: validated };
1619
1891
  }
1620
1892
  const prepared = await this.prepare(allowedData, "update", context);
@@ -1627,10 +1899,10 @@ var Service = class extends Base {
1627
1899
  const diffExcludeFields = [this.options.documentPermissionField, "__v"];
1628
1900
  this.asServiceHookContext(context).diff = (d) => {
1629
1901
  context.changes = (0, import_deep_diff.default)(
1630
- (0, import_utils10.omit)(context.originalDocumentSnapshot, diffExcludeFields),
1631
- (0, import_utils10.omit)(d.toObject({ virtuals: false }), diffExcludeFields)
1902
+ (0, import_utils13.omit)(context.originalDocumentSnapshot, diffExcludeFields),
1903
+ (0, import_utils13.omit)(d.toObject({ virtuals: false }), diffExcludeFields)
1632
1904
  ) || [];
1633
- context.modifiedPaths = (0, import_utils10.uniq)(context.changes.map((di) => di.path.length > 0 ? di.path[0] : ""));
1905
+ context.modifiedPaths = (0, import_utils13.uniq)(context.changes.map((di) => di.path.length > 0 ? di.path[0] : ""));
1634
1906
  };
1635
1907
  doc = assertModelDocument(await this.afterPersist(doc, "update", context), this.modelName, "afterPersist");
1636
1908
  context.currentDocument = doc;
@@ -1646,7 +1918,7 @@ var Service = class extends Base {
1646
1918
  if (_populate) await populateDoc(doc, _populate);
1647
1919
  doc = await this.trimOutputFields(doc, "read", this.baseFieldsExt);
1648
1920
  let outputDoc = doc;
1649
- if ((0, import_utils10.isFunction)(decorate)) outputDoc = await decorate(outputDoc, context);
1921
+ if ((0, import_utils13.isFunction)(decorate)) outputDoc = await decorate(outputDoc, context);
1650
1922
  if (!includePermissions) outputDoc = this.addEmptyPermissions(outputDoc);
1651
1923
  return { success: true, kind: "single", code: "success" /* Success */, data: outputDoc, input: prepared };
1652
1924
  }
@@ -1810,7 +2082,7 @@ var Service = class extends Base {
1810
2082
  return resolveExistsOptions(this, options);
1811
2083
  }
1812
2084
  async getFieldPermissionAccess(ids) {
1813
- const uniqueIds = (0, import_utils10.uniq)(ids.map((id) => String(id)).filter(Boolean));
2085
+ const uniqueIds = (0, import_utils13.uniq)(ids.map((id) => String(id)).filter(Boolean));
1814
2086
  if (uniqueIds.length === 0) {
1815
2087
  return {
1816
2088
  readIds: /* @__PURE__ */ new Set(),
@@ -1840,7 +2112,7 @@ var Service = class extends Base {
1840
2112
  return updateSub(this, id, sub, subId, data);
1841
2113
  }
1842
2114
  async bulkUpdateSub(id, sub, data) {
1843
- return bulkUpdateSub(this, id, sub, (0, import_utils10.castArray)(data));
2115
+ return bulkUpdateSub(this, id, sub, (0, import_utils13.castArray)(data));
1844
2116
  }
1845
2117
  async createSub(id, sub, data, options) {
1846
2118
  return createSub(this, id, sub, data, options);
@@ -1854,7 +2126,7 @@ var Service = class extends Base {
1854
2126
  };
1855
2127
 
1856
2128
  // src/services/public-service.ts
1857
- var import_utils11 = require("@web-ts-toolkit/utils");
2129
+ var import_utils14 = require("@web-ts-toolkit/utils");
1858
2130
  var PublicService = class extends Service {
1859
2131
  async _list(filter2, args, options) {
1860
2132
  const { select, populate, include, sort, skip, limit, page, pageSize, tasks } = this.resolvePublicListArgs(args);
@@ -1893,7 +2165,7 @@ var PublicService = class extends Service {
1893
2165
  doc = toObject(doc);
1894
2166
  doc = await this.decorate(doc, "create", context);
1895
2167
  doc = this.runTasks(doc, tasks);
1896
- if (select) doc = (0, import_utils11.pick)(doc, [...normalizeSelect(select), ...this.baseFieldsExt]);
2168
+ if (select) doc = (0, import_utils14.pick)(doc, [...normalizeSelect(select), ...this.baseFieldsExt]);
1897
2169
  return doc;
1898
2170
  }
1899
2171
  );
@@ -1988,8 +2260,8 @@ var PublicService = class extends Service {
1988
2260
  doc = toObject(doc);
1989
2261
  doc = await this.decorate(doc, "update", context);
1990
2262
  doc = this.runTasks(doc, tasks);
1991
- if (select) doc = (0, import_utils11.pick)(doc, [...normalizeSelect(select), ...this.baseFieldsExt]);
1992
- else if (!returningAll) doc = (0, import_utils11.pick)(doc, [...Object.keys(data), "_id"]);
2263
+ if (select) doc = (0, import_utils14.pick)(doc, [...normalizeSelect(select), ...this.baseFieldsExt]);
2264
+ else if (!returningAll) doc = (0, import_utils14.pick)(doc, [...Object.keys(data), "_id"]);
1993
2265
  return doc;
1994
2266
  }
1995
2267
  );
@@ -2111,7 +2383,7 @@ var PublicService = class extends Service {
2111
2383
  };
2112
2384
 
2113
2385
  // src/services/data-service.ts
2114
- var import_utils12 = require("@web-ts-toolkit/utils");
2386
+ var import_utils15 = require("@web-ts-toolkit/utils");
2115
2387
  var DataService = class {
2116
2388
  constructor(req, dataName) {
2117
2389
  this.req = req;
@@ -2133,7 +2405,7 @@ var DataService = class {
2133
2405
  let doc = await findElement(this.data, _filter);
2134
2406
  if (!doc) return { success: false, code: "not_found" /* NotFound */, query };
2135
2407
  doc = await this.trimOutputFields(doc, access);
2136
- if (_select.length > 0) doc = (0, import_utils12.pick)(doc, _select);
2408
+ if (_select.length > 0) doc = (0, import_utils15.pick)(doc, _select);
2137
2409
  return { success: true, kind: "single", code: "success" /* Success */, data: doc, query };
2138
2410
  }
2139
2411
  async findById(id, args, options) {
@@ -2169,13 +2441,13 @@ var DataService = class {
2169
2441
  docs = await Promise.all(
2170
2442
  docs.map(async (doc) => {
2171
2443
  doc = await this.trimOutputFields(doc, "list");
2172
- if (_select.length > 0) doc = (0, import_utils12.pick)(doc, _select);
2444
+ if (_select.length > 0) doc = (0, import_utils15.pick)(doc, _select);
2173
2445
  return doc;
2174
2446
  })
2175
2447
  );
2176
2448
  if (sort) {
2177
2449
  const { sortKey, sortOrder } = parseSortString(sort);
2178
- docs = (0, import_utils12.orderBy)(docs, [sortKey], [sortOrder]);
2450
+ docs = (0, import_utils15.orderBy)(docs, [sortKey], [sortOrder]);
2179
2451
  }
2180
2452
  docs = docs.slice(query.skip, query.limit && query.skip + query.limit);
2181
2453
  return {
@@ -2218,29 +2490,29 @@ var DataService = class {
2218
2490
  };
2219
2491
 
2220
2492
  // src/processors.ts
2221
- var import_utils13 = require("@web-ts-toolkit/utils");
2493
+ var import_utils16 = require("@web-ts-toolkit/utils");
2222
2494
  var copyAndDepopulate = (docObject, operations, options = { mutable: true, idField: "_id" }) => {
2223
- const obj = (0, import_utils13.get)(options, "mutable", true) ? docObject : (0, import_utils13.cloneDeep)(docObject);
2224
- const idField = (0, import_utils13.get)(options, "idField", "_id");
2225
- (0, import_utils13.forEach)((0, import_utils13.castArray)(operations), (op) => {
2495
+ const obj = (0, import_utils16.get)(options, "mutable", true) ? docObject : (0, import_utils16.cloneDeep)(docObject);
2496
+ const idField = (0, import_utils16.get)(options, "idField", "_id");
2497
+ (0, import_utils16.forEach)((0, import_utils16.castArray)(operations), (op) => {
2226
2498
  if (!op.src || !op.dest) return;
2227
2499
  let targets = [obj];
2228
2500
  const segs = op.src.split(".");
2229
- (0, import_utils13.forEach)(segs, (seg, ind) => {
2501
+ (0, import_utils16.forEach)(segs, (seg, ind) => {
2230
2502
  if (segs.length === ind + 1) {
2231
- (0, import_utils13.forEach)(targets, (target) => {
2503
+ (0, import_utils16.forEach)(targets, (target) => {
2232
2504
  const targetObject = target;
2233
- (0, import_utils13.set)(targetObject, op.dest, (0, import_utils13.get)(targetObject, seg));
2234
- (0, import_utils13.set)(
2505
+ (0, import_utils16.set)(targetObject, op.dest, (0, import_utils16.get)(targetObject, seg));
2506
+ (0, import_utils16.set)(
2235
2507
  targetObject,
2236
2508
  seg,
2237
- (0, import_utils13.isArray)(targetObject[seg]) ? (0, import_utils13.map)(targetObject[seg], idField) : (0, import_utils13.get)(targetObject, `${seg}.${idField}`)
2509
+ (0, import_utils16.isArray)(targetObject[seg]) ? (0, import_utils16.map)(targetObject[seg], idField) : (0, import_utils16.get)(targetObject, `${seg}.${idField}`)
2238
2510
  );
2239
2511
  });
2240
2512
  } else {
2241
2513
  targets = targets.reduce((ret, target) => {
2242
2514
  const targetObject = target;
2243
- if ((0, import_utils13.isArray)(targetObject[seg])) ret.push(...targetObject[seg]);
2515
+ if ((0, import_utils16.isArray)(targetObject[seg])) ret.push(...targetObject[seg]);
2244
2516
  else ret.push(targetObject[seg]);
2245
2517
  return ret;
2246
2518
  }, []);
@@ -2288,7 +2560,7 @@ var Cache = class {
2288
2560
  };
2289
2561
 
2290
2562
  // src/core-shared.ts
2291
- var import_utils14 = require("@web-ts-toolkit/utils");
2563
+ var import_utils17 = require("@web-ts-toolkit/utils");
2292
2564
 
2293
2565
  // src/permission.ts
2294
2566
  var Permission = class {
@@ -2326,10 +2598,10 @@ var permission_default = Permission;
2326
2598
 
2327
2599
  // src/core-shared.ts
2328
2600
  function isAndFilter(filter2) {
2329
- return !!filter2 && (0, import_utils14.isPlainObject)(filter2) && Object.keys(filter2).length === 1 && (0, import_utils14.isArray)(filter2.$and);
2601
+ return !!filter2 && (0, import_utils17.isPlainObject)(filter2) && Object.keys(filter2).length === 1 && (0, import_utils17.isArray)(filter2.$and);
2330
2602
  }
2331
2603
  function isMergeableClause(filter2) {
2332
- return !!filter2 && (0, import_utils14.isPlainObject)(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
2604
+ return !!filter2 && (0, import_utils17.isPlainObject)(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
2333
2605
  }
2334
2606
  function optimizeAndFilter(clausesInput) {
2335
2607
  const clauses = [];
@@ -2344,7 +2616,7 @@ function optimizeAndFilter(clausesInput) {
2344
2616
  }
2345
2617
  }
2346
2618
  const dedupedClauses = clauses.filter(
2347
- (clause, index) => clauses.findIndex((item) => (0, import_utils14.isEqual)(item, clause)) === index
2619
+ (clause, index) => clauses.findIndex((item) => (0, import_utils17.isEqual)(item, clause)) === index
2348
2620
  );
2349
2621
  const mergedClause = {};
2350
2622
  const remainingClauses = [];
@@ -2356,7 +2628,7 @@ function optimizeAndFilter(clausesInput) {
2356
2628
  }
2357
2629
  let canMerge = true;
2358
2630
  for (const [key, value] of Object.entries(clause)) {
2359
- if (Object.prototype.hasOwnProperty.call(mergedClause, key) && !(0, import_utils14.isEqual)(mergedClause[key], value)) {
2631
+ if (Object.prototype.hasOwnProperty.call(mergedClause, key) && !(0, import_utils17.isEqual)(mergedClause[key], value)) {
2360
2632
  canMerge = false;
2361
2633
  break;
2362
2634
  }
@@ -2367,24 +2639,24 @@ function optimizeAndFilter(clausesInput) {
2367
2639
  }
2368
2640
  Object.assign(mergedClause, clause);
2369
2641
  }
2370
- const finalClauses = (0, import_utils14.isEmpty)(mergedClause) ? remainingClauses : [mergedClause, ...remainingClauses];
2642
+ const finalClauses = (0, import_utils17.isEmpty)(mergedClause) ? remainingClauses : [mergedClause, ...remainingClauses];
2371
2643
  if (finalClauses.length === 0) return null;
2372
2644
  if (finalClauses.length === 1) return finalClauses[0];
2373
2645
  return { $and: finalClauses };
2374
2646
  }
2375
2647
  function normalizeFilter(filter2) {
2376
2648
  if (filter2 === false) return false;
2377
- if (!filter2 || !(0, import_utils14.isPlainObject)(filter2) || (0, import_utils14.isEmpty)(filter2)) return null;
2649
+ if (!filter2 || !(0, import_utils17.isPlainObject)(filter2) || (0, import_utils17.isEmpty)(filter2)) return null;
2378
2650
  if (!isAndFilter(filter2)) {
2379
2651
  return filter2;
2380
2652
  }
2381
2653
  return optimizeAndFilter(filter2.$and);
2382
2654
  }
2383
2655
  async function resolveIdentifierFilter(req, idField, resolveIdFilter, id) {
2384
- if ((0, import_utils14.isFunction)(resolveIdFilter)) {
2656
+ if ((0, import_utils17.isFunction)(resolveIdFilter)) {
2385
2657
  return await resolveIdFilter.call(req, id);
2386
2658
  }
2387
- if ((0, import_utils14.isString)(idField)) {
2659
+ if ((0, import_utils17.isString)(idField)) {
2388
2660
  return { [idField]: id };
2389
2661
  }
2390
2662
  return { _id: id };
@@ -2400,11 +2672,11 @@ async function resolveAccessFilter({
2400
2672
  }) {
2401
2673
  let nextFilter = normalizeFilter(filter2);
2402
2674
  const overrideFilterFn = getOption(`overrideFilter.${access}`, null);
2403
- if ((0, import_utils14.isFunction)(overrideFilterFn)) {
2675
+ if ((0, import_utils17.isFunction)(overrideFilterFn)) {
2404
2676
  nextFilter = normalizeFilter(await overrideFilterFn.call(req, nextFilter, permissions));
2405
2677
  }
2406
2678
  const baseFilterFn = getOption(`baseFilter.${access}`, null);
2407
- if (!(0, import_utils14.isFunction)(baseFilterFn)) return nextFilter || {};
2679
+ if (!(0, import_utils17.isFunction)(baseFilterFn)) return nextFilter || {};
2408
2680
  const baseFilter = normalizeFilter(
2409
2681
  cache.has(cacheKey) ? cache.get(cacheKey) : await baseFilterFn.call(req, permissions)
2410
2682
  );
@@ -2424,33 +2696,33 @@ async function setRequestPermissions(req) {
2424
2696
  const requestPermissionField = getGlobalOption("requestPermissionField");
2425
2697
  if (req[requestPermissionField]) return;
2426
2698
  const globalPermissions = getGlobalOption("globalPermissions");
2427
- if (!(0, import_utils14.isFunction)(globalPermissions)) return;
2699
+ if (!(0, import_utils17.isFunction)(globalPermissions)) return;
2428
2700
  const permissions = await globalPermissions.call(req, req);
2429
- if ((0, import_utils14.isPlainObject)(permissions)) req[requestPermissionField] = permissions;
2430
- else if ((0, import_utils14.isArray)(permissions)) req[requestPermissionField] = (0, import_utils14.arrayToRecord)(permissions);
2431
- else if ((0, import_utils14.isString)(permissions)) req[requestPermissionField] = { [permissions]: true };
2701
+ if ((0, import_utils17.isPlainObject)(permissions)) req[requestPermissionField] = permissions;
2702
+ else if ((0, import_utils17.isArray)(permissions)) req[requestPermissionField] = (0, import_utils17.arrayToRecord)(permissions);
2703
+ else if ((0, import_utils17.isString)(permissions)) req[requestPermissionField] = { [permissions]: true };
2432
2704
  }
2433
2705
  async function evaluateRouteGuard(req, permissions, routeGuard) {
2434
2706
  const phas = (key) => permissions.has(key);
2435
2707
  const { stringHandler, arrayHandler } = createValidator(phas);
2436
- if ((0, import_utils14.isBoolean)(routeGuard)) {
2708
+ if ((0, import_utils17.isBoolean)(routeGuard)) {
2437
2709
  return routeGuard === true;
2438
2710
  }
2439
- if ((0, import_utils14.isString)(routeGuard)) {
2711
+ if ((0, import_utils17.isString)(routeGuard)) {
2440
2712
  return stringHandler(routeGuard);
2441
2713
  }
2442
- if ((0, import_utils14.isArray)(routeGuard)) {
2714
+ if ((0, import_utils17.isArray)(routeGuard)) {
2443
2715
  return arrayHandler(routeGuard);
2444
2716
  }
2445
- if ((0, import_utils14.isFunction)(routeGuard)) {
2717
+ if ((0, import_utils17.isFunction)(routeGuard)) {
2446
2718
  return routeGuard.call(req, permissions);
2447
2719
  }
2448
2720
  return false;
2449
2721
  }
2450
2722
  async function callHookChain(req, hook, doc, permissions, context) {
2451
- const hooks = (0, import_utils14.castArray)(hook);
2723
+ const hooks = (0, import_utils17.castArray)(hook);
2452
2724
  for (let x = 0; x < hooks.length; x++) {
2453
- if ((0, import_utils14.isFunction)(hooks[x])) {
2725
+ if ((0, import_utils17.isFunction)(hooks[x])) {
2454
2726
  doc = await hooks[x].call(req, doc, permissions, context);
2455
2727
  }
2456
2728
  }
@@ -2473,13 +2745,13 @@ async function collectSchemaFields({
2473
2745
  if (baseFields.includes(key)) continue;
2474
2746
  const val = permissionSchema[key];
2475
2747
  const value = val && val[access] || val;
2476
- if ((0, import_utils14.isBoolean)(value)) {
2748
+ if ((0, import_utils17.isBoolean)(value)) {
2477
2749
  if (value) fields.push(key);
2478
- } else if ((0, import_utils14.isString)(value)) {
2750
+ } else if ((0, import_utils17.isString)(value)) {
2479
2751
  if (stringHandler(value)) fields.push(key);
2480
- } else if ((0, import_utils14.isArray)(value)) {
2752
+ } else if ((0, import_utils17.isArray)(value)) {
2481
2753
  if (arrayHandler(value)) fields.push(key);
2482
- } else if ((0, import_utils14.isFunction)(value)) {
2754
+ } else if ((0, import_utils17.isFunction)(value)) {
2483
2755
  if (await value.call(req, ...functionArgs)) fields.push(key);
2484
2756
  }
2485
2757
  }
@@ -2568,7 +2840,7 @@ async function runDecorateAllHook({
2568
2840
  }
2569
2841
 
2570
2842
  // src/acl/select-resolution.ts
2571
- var import_utils15 = require("@web-ts-toolkit/utils");
2843
+ var import_utils18 = require("@web-ts-toolkit/utils");
2572
2844
  async function collectAllowedFieldsForRequest({
2573
2845
  req,
2574
2846
  permissionSchema,
@@ -2636,15 +2908,15 @@ async function resolveSelectForRequest({
2636
2908
  const excludeall = normalizedSelect.every((v) => v.startsWith("-"));
2637
2909
  if (excludeall) {
2638
2910
  normalizedSelect = normalizedSelect.map((v) => v.substring(1));
2639
- fields = (0, import_utils15.difference)(fields, normalizedSelect);
2911
+ fields = (0, import_utils18.difference)(fields, normalizedSelect);
2640
2912
  if (excludeid) fields.push("-_id");
2641
2913
  } else {
2642
- fields = (0, import_utils15.intersection)(normalizedSelect, fields.concat(excludeid ? "-_id" : "_id"));
2914
+ fields = (0, import_utils18.intersection)(normalizedSelect, fields.concat(excludeid ? "-_id" : "_id"));
2643
2915
  }
2644
2916
  }
2645
2917
  return fields.concat(alwaysSelectFields);
2646
2918
  }
2647
- return (0, import_utils15.intersection)(normalizedSelect, fields);
2919
+ return (0, import_utils18.intersection)(normalizedSelect, fields);
2648
2920
  }
2649
2921
 
2650
2922
  // src/core.ts
@@ -2658,10 +2930,10 @@ var Core = class {
2658
2930
  getIdentifier(modelName) {
2659
2931
  const resolveIdFilter = getModelOption(modelName, "resolveIdFilter");
2660
2932
  const idField = getModelOption(modelName, "idField");
2661
- if ((0, import_utils16.isFunction)(resolveIdFilter)) {
2933
+ if ((0, import_utils19.isFunction)(resolveIdFilter)) {
2662
2934
  return null;
2663
2935
  }
2664
- if ((0, import_utils16.isString)(idField)) {
2936
+ if ((0, import_utils19.isString)(idField)) {
2665
2937
  return idField;
2666
2938
  }
2667
2939
  return "_id";
@@ -2739,11 +3011,11 @@ var Core = class {
2739
3011
  async genPopulate(modelName, access = "read", _populate = null) {
2740
3012
  if (!_populate) return [];
2741
3013
  let populate = Array.isArray(_populate) ? _populate : [_populate];
2742
- populate = (0, import_utils16.compact)(
3014
+ populate = (0, import_utils19.compact)(
2743
3015
  await Promise.all(
2744
3016
  populate.map(async (p) => {
2745
- const populateAccess = !(0, import_utils16.isString)(p) && p.access ? p.access : access;
2746
- const ret = (0, import_utils16.isString)(p) ? { path: p } : {
3017
+ const populateAccess = !(0, import_utils19.isString)(p) && p.access ? p.access : access;
3018
+ const ret = (0, import_utils19.isString)(p) ? { path: p } : {
2747
3019
  path: p.path,
2748
3020
  select: normalizeSelect(p.select)
2749
3021
  };
@@ -2763,10 +3035,10 @@ var Core = class {
2763
3035
  }
2764
3036
  async validate(modelName, allowedData, access, context) {
2765
3037
  const validate = getModelOption(modelName, `validate.${access}`, null);
2766
- if ((0, import_utils16.isFunction)(validate)) {
3038
+ if ((0, import_utils19.isFunction)(validate)) {
2767
3039
  const permissions = this.getGlobalPermissions();
2768
3040
  return validate.call(this.req, allowedData, permissions, context);
2769
- } else if ((0, import_utils16.isBoolean)(validate) || (0, import_utils16.isArray)(validate)) {
3041
+ } else if ((0, import_utils19.isBoolean)(validate) || (0, import_utils19.isArray)(validate)) {
2770
3042
  return validate;
2771
3043
  } else {
2772
3044
  return true;
@@ -2791,7 +3063,7 @@ var Core = class {
2791
3063
  const changeOptions = getModelOption(modelName, `onChange`, {});
2792
3064
  for (let x = 0; x < context.modifiedPaths.length; x++) {
2793
3065
  const mpath = context.modifiedPaths[x];
2794
- if ((0, import_utils16.isFunction)(changeOptions[mpath])) {
3066
+ if ((0, import_utils19.isFunction)(changeOptions[mpath])) {
2795
3067
  await changeOptions[mpath].call(
2796
3068
  this.req,
2797
3069
  context.originalDocumentSnapshot[mpath],
@@ -2815,7 +3087,7 @@ var Core = class {
2815
3087
  async genDocPermissions(modelName, doc, access, context) {
2816
3088
  const docPermissionsFn = getModelOption(modelName, `docPermissions.${access}`, null);
2817
3089
  let docPermissions = {};
2818
- if ((0, import_utils16.isFunction)(docPermissionsFn)) {
3090
+ if ((0, import_utils19.isFunction)(docPermissionsFn)) {
2819
3091
  const permissions = this.getGlobalPermissions();
2820
3092
  try {
2821
3093
  docPermissions = await docPermissionsFn.call(this.req, doc, permissions, context);
@@ -2863,7 +3135,7 @@ var Core = class {
2863
3135
  readExists ? this.genAllowedFields(modelName, doc, "read") : [],
2864
3136
  updateExists ? this.genAllowedFields(modelName, doc, "update") : []
2865
3137
  ]);
2866
- const viewObj = (0, import_utils16.reduce)(
3138
+ const viewObj = (0, import_utils19.reduce)(
2867
3139
  views,
2868
3140
  (ret, view) => {
2869
3141
  ret[view] = true;
@@ -2871,7 +3143,7 @@ var Core = class {
2871
3143
  },
2872
3144
  {}
2873
3145
  );
2874
- const editObj = (0, import_utils16.reduce)(
3146
+ const editObj = (0, import_utils19.reduce)(
2875
3147
  edits,
2876
3148
  (ret, view) => {
2877
3149
  ret[view] = true;
@@ -2895,9 +3167,9 @@ var Core = class {
2895
3167
  return runDecorateAllHook({ req: this.req, hook: decorateAll, docs, permissions, context });
2896
3168
  }
2897
3169
  runTasks(modelName, docObject, task) {
2898
- const tasks = (0, import_utils16.compact)((0, import_utils16.castArray)(task));
3170
+ const tasks = (0, import_utils19.compact)((0, import_utils19.castArray)(task));
2899
3171
  if (tasks.length === 0) return docObject;
2900
- (0, import_utils16.forEach)(tasks, (task2) => {
3172
+ (0, import_utils19.forEach)(tasks, (task2) => {
2901
3173
  const { type, args, options } = task2;
2902
3174
  switch (type) {
2903
3175
  case "COPY_AND_DEPOPULATE":
@@ -2928,9 +3200,9 @@ var Core = class {
2928
3200
  }
2929
3201
  const [, field, op] = keys2;
2930
3202
  const subOption = getExactModelOption(modelName, `operationAccess.${access}`);
2931
- if ((0, import_utils16.isUndefined)(subOption)) {
3203
+ if ((0, import_utils19.isUndefined)(subOption)) {
2932
3204
  const subFieldOption = getExactModelOption(modelName, `operationAccess.subs.${field}`);
2933
- if ((0, import_utils16.isUndefined)(subFieldOption)) {
3205
+ if ((0, import_utils19.isUndefined)(subFieldOption)) {
2934
3206
  const opOption = getModelOption(modelName, `operationAccess.${op}`);
2935
3207
  return this.canActivate(opOption);
2936
3208
  }
@@ -2980,25 +3252,25 @@ function guard(condition) {
2980
3252
  const permissions = req[PERMISSIONS];
2981
3253
  let cond = condition;
2982
3254
  let phas = (key) => permissions.has(key);
2983
- if ((0, import_utils17.isPlainObject)(condition)) {
3255
+ if ((0, import_utils20.isPlainObject)(condition)) {
2984
3256
  const { modelName, id, condition: _cond } = condition;
2985
3257
  const svc = req.macl.getPublicService(modelName);
2986
3258
  const select = getModelOption(modelName, `alwaysSelectFields.read`, void 0);
2987
- let _id = (0, import_utils17.isString)(id) ? id : null;
2988
- if ((0, import_utils17.isPlainObject)(id)) {
3259
+ let _id = (0, import_utils20.isString)(id) ? id : null;
3260
+ if ((0, import_utils20.isPlainObject)(id)) {
2989
3261
  const { type = "param", key } = id;
2990
3262
  if (type === "param") {
2991
3263
  const paramValue = req.params[key];
2992
- _id = (0, import_utils17.isArray)(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
3264
+ _id = (0, import_utils20.isArray)(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
2993
3265
  } else if (type === "query") {
2994
3266
  const _qval = req.query[key];
2995
- if ((0, import_utils17.isArray)(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
3267
+ if ((0, import_utils20.isArray)(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
2996
3268
  else _id = _qval;
2997
3269
  } else {
2998
3270
  _id = null;
2999
3271
  }
3000
3272
  }
3001
- if (!(0, import_utils17.isString)(_id) || !_id) {
3273
+ if (!(0, import_utils20.isString)(_id) || !_id) {
3002
3274
  return next(new import_express_json_router2.default.clientErrors.BadRequestError());
3003
3275
  }
3004
3276
  const result = await svc._read(_id, { select });
@@ -3010,11 +3282,11 @@ function guard(condition) {
3010
3282
  cond = _cond;
3011
3283
  }
3012
3284
  const { stringHandler, arrayHandler } = createValidator(phas);
3013
- if ((0, import_utils17.isString)(cond)) {
3285
+ if ((0, import_utils20.isString)(cond)) {
3014
3286
  if (stringHandler(cond)) return next();
3015
- } else if ((0, import_utils17.isArray)(cond)) {
3287
+ } else if ((0, import_utils20.isArray)(cond)) {
3016
3288
  if (arrayHandler(cond)) return next();
3017
- } else if ((0, import_utils17.isFunction)(cond)) {
3289
+ } else if ((0, import_utils20.isFunction)(cond)) {
3018
3290
  const result = await cond.call(req, permissions);
3019
3291
  if (!!result) return next();
3020
3292
  }
@@ -3023,11 +3295,11 @@ function guard(condition) {
3023
3295
  }
3024
3296
 
3025
3297
  // src/routers/index.ts
3026
- var import_express = __toESM(require("express"));
3298
+ var import_express2 = __toESM(require("express"));
3027
3299
 
3028
3300
  // src/routers/model-router.ts
3029
3301
  var import_express_json_router5 = __toESM(require("@web-ts-toolkit/express-json-router"));
3030
- var import_utils19 = require("@web-ts-toolkit/utils");
3302
+ var import_utils24 = require("@web-ts-toolkit/utils");
3031
3303
 
3032
3304
  // src/routers/router-mutation.ts
3033
3305
  var MODEL_BUILD_TIME_OPTION_KEYS = /* @__PURE__ */ new Set([
@@ -3119,88 +3391,88 @@ function formatModelUpsertResponse(result) {
3119
3391
  var import_express_json_router4 = __toESM(require("@web-ts-toolkit/express-json-router"));
3120
3392
 
3121
3393
  // src/validation/common.ts
3122
- var import_zod = require("zod");
3123
- var stringOrStringArray = import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.string())]);
3124
- var queryBooleanString = import_zod.z.enum(["true", "false"]);
3125
- var positiveIntegerString = import_zod.z.string().regex(/^\d+$/, "Expected a non-negative integer");
3126
- var nonNegativeIntegerSchema = import_zod.z.number().int().min(0);
3127
- var unknownRecord = import_zod.z.record(import_zod.z.string(), import_zod.z.unknown());
3128
- var projectionObjectSchema = import_zod.z.record(import_zod.z.string(), import_zod.z.union([import_zod.z.literal(1), import_zod.z.literal(-1)]));
3129
- var projectionSchema = import_zod.z.union([import_zod.z.string(), import_zod.z.array(import_zod.z.string()), projectionObjectSchema]);
3130
- var sortOrderSchema = import_zod.z.union([
3131
- import_zod.z.literal(-1),
3132
- import_zod.z.literal(1),
3133
- import_zod.z.literal("asc"),
3134
- import_zod.z.literal("ascending"),
3135
- import_zod.z.literal("desc"),
3136
- import_zod.z.literal("descending")
3394
+ var import_zod2 = require("zod");
3395
+ var stringOrStringArray = import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.string())]);
3396
+ var queryBooleanString = import_zod2.z.enum(["true", "false"]);
3397
+ var positiveIntegerString = import_zod2.z.string().regex(/^\d+$/, "Expected a non-negative integer");
3398
+ var nonNegativeIntegerSchema = import_zod2.z.number().int().min(0);
3399
+ var unknownRecord = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown());
3400
+ var projectionObjectSchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.union([import_zod2.z.literal(1), import_zod2.z.literal(-1)]));
3401
+ var projectionSchema = import_zod2.z.union([import_zod2.z.string(), import_zod2.z.array(import_zod2.z.string()), projectionObjectSchema]);
3402
+ var sortOrderSchema = import_zod2.z.union([
3403
+ import_zod2.z.literal(-1),
3404
+ import_zod2.z.literal(1),
3405
+ import_zod2.z.literal("asc"),
3406
+ import_zod2.z.literal("ascending"),
3407
+ import_zod2.z.literal("desc"),
3408
+ import_zod2.z.literal("descending")
3137
3409
  ]);
3138
- var sortSchema = import_zod.z.union([
3139
- import_zod.z.string(),
3140
- import_zod.z.record(import_zod.z.string(), sortOrderSchema),
3141
- import_zod.z.array(import_zod.z.tuple([import_zod.z.string(), sortOrderSchema])),
3142
- import_zod.z.null()
3410
+ var sortSchema = import_zod2.z.union([
3411
+ import_zod2.z.string(),
3412
+ import_zod2.z.record(import_zod2.z.string(), sortOrderSchema),
3413
+ import_zod2.z.array(import_zod2.z.tuple([import_zod2.z.string(), sortOrderSchema])),
3414
+ import_zod2.z.null()
3143
3415
  ]);
3144
- var populateSchema = import_zod.z.union([
3145
- import_zod.z.string(),
3146
- import_zod.z.array(
3147
- import_zod.z.union([
3148
- import_zod.z.string(),
3149
- import_zod.z.object({
3150
- path: import_zod.z.string().min(1),
3416
+ var populateSchema = import_zod2.z.union([
3417
+ import_zod2.z.string(),
3418
+ import_zod2.z.array(
3419
+ import_zod2.z.union([
3420
+ import_zod2.z.string(),
3421
+ import_zod2.z.object({
3422
+ path: import_zod2.z.string().min(1),
3151
3423
  select: projectionSchema.optional(),
3152
- match: import_zod.z.unknown().optional(),
3153
- access: import_zod.z.enum(["list", "read"]).optional()
3424
+ match: import_zod2.z.unknown().optional(),
3425
+ access: import_zod2.z.enum(["list", "read"]).optional()
3154
3426
  }).passthrough()
3155
3427
  ])
3156
3428
  ),
3157
- import_zod.z.object({
3158
- path: import_zod.z.string().min(1),
3429
+ import_zod2.z.object({
3430
+ path: import_zod2.z.string().min(1),
3159
3431
  select: projectionSchema.optional(),
3160
- match: import_zod.z.unknown().optional(),
3161
- access: import_zod.z.enum(["list", "read"]).optional()
3432
+ match: import_zod2.z.unknown().optional(),
3433
+ access: import_zod2.z.enum(["list", "read"]).optional()
3162
3434
  }).passthrough()
3163
3435
  ]);
3164
- var subPopulateSchema = import_zod.z.union([
3165
- import_zod.z.string(),
3166
- import_zod.z.array(
3167
- import_zod.z.union([
3168
- import_zod.z.string(),
3169
- import_zod.z.object({
3170
- path: import_zod.z.string().min(1),
3436
+ var subPopulateSchema = import_zod2.z.union([
3437
+ import_zod2.z.string(),
3438
+ import_zod2.z.array(
3439
+ import_zod2.z.union([
3440
+ import_zod2.z.string(),
3441
+ import_zod2.z.object({
3442
+ path: import_zod2.z.string().min(1),
3171
3443
  select: projectionSchema.optional()
3172
3444
  }).passthrough()
3173
3445
  ])
3174
3446
  ),
3175
- import_zod.z.object({
3176
- path: import_zod.z.string().min(1),
3447
+ import_zod2.z.object({
3448
+ path: import_zod2.z.string().min(1),
3177
3449
  select: projectionSchema.optional()
3178
3450
  }).passthrough()
3179
3451
  ]);
3180
- var includeItemSchema = import_zod.z.object({
3181
- model: import_zod.z.string().min(1),
3182
- op: import_zod.z.enum(["list", "read", "count"]),
3183
- path: import_zod.z.string().min(1),
3184
- filter: import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()).optional(),
3185
- localField: import_zod.z.string().min(1),
3186
- foreignField: import_zod.z.string().min(1),
3187
- args: import_zod.z.unknown().optional(),
3188
- options: import_zod.z.unknown().optional()
3452
+ var includeItemSchema = import_zod2.z.object({
3453
+ model: import_zod2.z.string().min(1),
3454
+ op: import_zod2.z.enum(["list", "read", "count"]),
3455
+ path: import_zod2.z.string().min(1),
3456
+ filter: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
3457
+ localField: import_zod2.z.string().min(1),
3458
+ foreignField: import_zod2.z.string().min(1),
3459
+ args: import_zod2.z.unknown().optional(),
3460
+ options: import_zod2.z.unknown().optional()
3189
3461
  }).passthrough();
3190
- var includeSchema = import_zod.z.union([includeItemSchema, import_zod.z.array(includeItemSchema)]);
3191
- var fieldsSchema = import_zod.z.array(import_zod.z.string().min(1));
3192
- var taskSchema = import_zod.z.object({
3193
- type: import_zod.z.string().min(1),
3194
- args: import_zod.z.unknown(),
3462
+ var includeSchema = import_zod2.z.union([includeItemSchema, import_zod2.z.array(includeItemSchema)]);
3463
+ var fieldsSchema = import_zod2.z.array(import_zod2.z.string().min(1));
3464
+ var taskSchema = import_zod2.z.object({
3465
+ type: import_zod2.z.string().min(1),
3466
+ args: import_zod2.z.unknown(),
3195
3467
  options: unknownRecord.optional()
3196
3468
  });
3197
- var tasksSchema = import_zod.z.union([taskSchema, import_zod.z.array(taskSchema)]);
3198
- var objectOrArraySchema = import_zod.z.union([import_zod.z.record(import_zod.z.string(), import_zod.z.unknown()), import_zod.z.array(import_zod.z.unknown())]);
3469
+ var tasksSchema = import_zod2.z.union([taskSchema, import_zod2.z.array(taskSchema)]);
3470
+ var objectOrArraySchema = import_zod2.z.union([import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()), import_zod2.z.array(import_zod2.z.unknown())]);
3199
3471
  function rejectKeys(body, ctx, keys2) {
3200
3472
  for (const key of keys2) {
3201
3473
  if (key in body) {
3202
3474
  ctx.addIssue({
3203
- code: import_zod.z.ZodIssueCode.custom,
3475
+ code: import_zod2.z.ZodIssueCode.custom,
3204
3476
  message: `Unsupported field: ${key}`,
3205
3477
  path: [key]
3206
3478
  });
@@ -3289,8 +3561,11 @@ function toRequestSchemaValidator(schema) {
3289
3561
  if (isRequestSchemaValidator(schema)) return schema;
3290
3562
  return schema.validate;
3291
3563
  }
3292
- function defineRequestSchema(validator) {
3293
- return validator;
3564
+ function defineRequestSchema(validator, options = {}) {
3565
+ return {
3566
+ validate: validator,
3567
+ openapi: options.openapi
3568
+ };
3294
3569
  }
3295
3570
  function fromZod(schema) {
3296
3571
  return (value) => {
@@ -3570,8 +3845,8 @@ function buildPointer(path) {
3570
3845
  }
3571
3846
 
3572
3847
  // src/validation/model-router.ts
3573
- var import_zod2 = require("zod");
3574
- var listQuerySchema = import_zod2.z.object({
3848
+ var import_zod3 = require("zod");
3849
+ var listQuerySchema = import_zod3.z.object({
3575
3850
  skip: positiveIntegerString.optional(),
3576
3851
  limit: positiveIntegerString.optional(),
3577
3852
  page: positiveIntegerString.optional(),
@@ -3581,122 +3856,122 @@ var listQuerySchema = import_zod2.z.object({
3581
3856
  include_count: queryBooleanString.optional(),
3582
3857
  include_extra_headers: queryBooleanString.optional()
3583
3858
  }).passthrough();
3584
- var createQuerySchema = import_zod2.z.object({
3859
+ var createQuerySchema = import_zod3.z.object({
3585
3860
  include_permissions: queryBooleanString.optional()
3586
3861
  }).passthrough();
3587
- var readQuerySchema = import_zod2.z.object({
3862
+ var readQuerySchema = import_zod3.z.object({
3588
3863
  include_permissions: queryBooleanString.optional(),
3589
3864
  try_list: queryBooleanString.optional()
3590
3865
  }).passthrough();
3591
- var updateQuerySchema = import_zod2.z.object({
3866
+ var updateQuerySchema = import_zod3.z.object({
3592
3867
  returning_all: queryBooleanString.optional(),
3593
3868
  include_permissions: queryBooleanString.optional()
3594
3869
  }).passthrough();
3595
- var upsertQuerySchema = import_zod2.z.object({
3870
+ var upsertQuerySchema = import_zod3.z.object({
3596
3871
  returning_all: queryBooleanString.optional(),
3597
3872
  include_permissions: queryBooleanString.optional()
3598
3873
  }).passthrough();
3599
- var listBodySchema = import_zod2.z.object({
3874
+ var listBodySchema = import_zod3.z.object({
3600
3875
  filter: objectOrArraySchema.optional(),
3601
3876
  select: projectionSchema.optional(),
3602
3877
  sort: sortSchema.optional(),
3603
3878
  populate: populateSchema.optional(),
3604
3879
  include: includeSchema.optional(),
3605
3880
  tasks: tasksSchema.optional(),
3606
- skip: import_zod2.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3607
- limit: import_zod2.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3608
- page: import_zod2.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3609
- pageSize: import_zod2.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3610
- options: import_zod2.z.object({
3611
- skim: import_zod2.z.boolean().optional(),
3612
- includePermissions: import_zod2.z.boolean().optional(),
3613
- includeCount: import_zod2.z.boolean().optional(),
3614
- includeExtraHeaders: import_zod2.z.boolean().optional(),
3615
- populateAccess: import_zod2.z.unknown().optional()
3881
+ skip: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3882
+ limit: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3883
+ page: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3884
+ pageSize: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3885
+ options: import_zod3.z.object({
3886
+ skim: import_zod3.z.boolean().optional(),
3887
+ includePermissions: import_zod3.z.boolean().optional(),
3888
+ includeCount: import_zod3.z.boolean().optional(),
3889
+ includeExtraHeaders: import_zod3.z.boolean().optional(),
3890
+ populateAccess: import_zod3.z.unknown().optional()
3616
3891
  }).passthrough().optional()
3617
3892
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
3618
- var countBodySchema = import_zod2.z.object({
3893
+ var countBodySchema = import_zod3.z.object({
3619
3894
  filter: objectOrArraySchema.optional(),
3620
- options: import_zod2.z.object({
3621
- access: import_zod2.z.unknown().optional()
3895
+ options: import_zod3.z.object({
3896
+ access: import_zod3.z.unknown().optional()
3622
3897
  }).passthrough().optional()
3623
3898
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access"]));
3624
- var readFilterBodySchema = import_zod2.z.object({
3899
+ var readFilterBodySchema = import_zod3.z.object({
3625
3900
  filter: objectOrArraySchema.optional(),
3626
3901
  select: projectionSchema.optional(),
3627
3902
  sort: sortSchema.optional(),
3628
3903
  populate: populateSchema.optional(),
3629
3904
  include: includeSchema.optional(),
3630
3905
  tasks: tasksSchema.optional(),
3631
- options: import_zod2.z.object({
3632
- skim: import_zod2.z.boolean().optional(),
3633
- includePermissions: import_zod2.z.boolean().optional(),
3634
- tryList: import_zod2.z.boolean().optional(),
3635
- populateAccess: import_zod2.z.unknown().optional()
3906
+ options: import_zod3.z.object({
3907
+ skim: import_zod3.z.boolean().optional(),
3908
+ includePermissions: import_zod3.z.boolean().optional(),
3909
+ tryList: import_zod3.z.boolean().optional(),
3910
+ populateAccess: import_zod3.z.unknown().optional()
3636
3911
  }).passthrough().optional()
3637
3912
  }).passthrough();
3638
- var readByIdBodySchema = import_zod2.z.object({
3913
+ var readByIdBodySchema = import_zod3.z.object({
3639
3914
  select: projectionSchema.optional(),
3640
3915
  populate: populateSchema.optional(),
3641
3916
  include: includeSchema.optional(),
3642
3917
  tasks: tasksSchema.optional(),
3643
- options: import_zod2.z.object({
3644
- skim: import_zod2.z.boolean().optional(),
3645
- includePermissions: import_zod2.z.boolean().optional(),
3646
- tryList: import_zod2.z.boolean().optional(),
3647
- populateAccess: import_zod2.z.unknown().optional()
3918
+ options: import_zod3.z.object({
3919
+ skim: import_zod3.z.boolean().optional(),
3920
+ includePermissions: import_zod3.z.boolean().optional(),
3921
+ tryList: import_zod3.z.boolean().optional(),
3922
+ populateAccess: import_zod3.z.unknown().optional()
3648
3923
  }).passthrough().optional()
3649
3924
  }).passthrough();
3650
- var advancedCreateBodySchema = import_zod2.z.object({
3651
- data: import_zod2.z.unknown(),
3925
+ var advancedCreateBodySchema = import_zod3.z.object({
3926
+ data: import_zod3.z.unknown(),
3652
3927
  select: projectionSchema.optional(),
3653
3928
  populate: populateSchema.optional(),
3654
3929
  tasks: tasksSchema.optional(),
3655
- options: import_zod2.z.object({
3656
- includePermissions: import_zod2.z.boolean().optional(),
3657
- populateAccess: import_zod2.z.unknown().optional()
3930
+ options: import_zod3.z.object({
3931
+ includePermissions: import_zod3.z.boolean().optional(),
3932
+ populateAccess: import_zod3.z.unknown().optional()
3658
3933
  }).passthrough().optional()
3659
3934
  }).passthrough();
3660
- var createBodySchema = import_zod2.z.union([
3661
- import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),
3662
- import_zod2.z.array(import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()))
3935
+ var createBodySchema = import_zod3.z.union([
3936
+ import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()),
3937
+ import_zod3.z.array(import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()))
3663
3938
  ]);
3664
- var updateBodySchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown());
3665
- var advancedUpdateBodySchema = import_zod2.z.object({
3666
- data: import_zod2.z.unknown(),
3939
+ var updateBodySchema = import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown());
3940
+ var advancedUpdateBodySchema = import_zod3.z.object({
3941
+ data: import_zod3.z.unknown(),
3667
3942
  select: projectionSchema.optional(),
3668
3943
  populate: populateSchema.optional(),
3669
3944
  tasks: tasksSchema.optional(),
3670
- options: import_zod2.z.object({
3671
- returningAll: import_zod2.z.boolean().optional(),
3672
- includePermissions: import_zod2.z.boolean().optional(),
3673
- populateAccess: import_zod2.z.unknown().optional()
3945
+ options: import_zod3.z.object({
3946
+ returningAll: import_zod3.z.boolean().optional(),
3947
+ includePermissions: import_zod3.z.boolean().optional(),
3948
+ populateAccess: import_zod3.z.unknown().optional()
3674
3949
  }).passthrough().optional()
3675
3950
  }).passthrough();
3676
- var upsertBodySchema = import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown());
3677
- var advancedUpsertBodySchema = import_zod2.z.object({
3678
- data: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),
3951
+ var upsertBodySchema = import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown());
3952
+ var advancedUpsertBodySchema = import_zod3.z.object({
3953
+ data: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()),
3679
3954
  select: projectionSchema.optional(),
3680
3955
  populate: populateSchema.optional(),
3681
3956
  tasks: tasksSchema.optional(),
3682
- options: import_zod2.z.object({
3683
- returningAll: import_zod2.z.boolean().optional(),
3684
- includePermissions: import_zod2.z.boolean().optional(),
3685
- populateAccess: import_zod2.z.unknown().optional()
3957
+ options: import_zod3.z.object({
3958
+ returningAll: import_zod3.z.boolean().optional(),
3959
+ includePermissions: import_zod3.z.boolean().optional(),
3960
+ populateAccess: import_zod3.z.unknown().optional()
3686
3961
  }).passthrough().optional()
3687
3962
  }).passthrough();
3688
- var distinctBodySchema = import_zod2.z.object({
3963
+ var distinctBodySchema = import_zod3.z.object({
3689
3964
  filter: objectOrArraySchema.optional()
3690
3965
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
3691
- var subListBodySchema = import_zod2.z.object({
3692
- filter: import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()).optional(),
3966
+ var subListBodySchema = import_zod3.z.object({
3967
+ filter: import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()).optional(),
3693
3968
  select: fieldsSchema.optional()
3694
3969
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
3695
- var subMutationBodySchema = import_zod2.z.union([
3696
- import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()),
3697
- import_zod2.z.array(import_zod2.z.record(import_zod2.z.string(), import_zod2.z.unknown()))
3970
+ var subMutationBodySchema = import_zod3.z.union([
3971
+ import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()),
3972
+ import_zod3.z.array(import_zod3.z.record(import_zod3.z.string(), import_zod3.z.unknown()))
3698
3973
  ]);
3699
- var subReadBodySchema = import_zod2.z.object({
3974
+ var subReadBodySchema = import_zod3.z.object({
3700
3975
  select: fieldsSchema.optional(),
3701
3976
  populate: subPopulateSchema.optional()
3702
3977
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
@@ -3709,54 +3984,54 @@ var requestSchemas = {
3709
3984
  };
3710
3985
 
3711
3986
  // src/validation/data-router.ts
3712
- var import_zod3 = require("zod");
3713
- var dataListBodySchema = import_zod3.z.object({
3987
+ var import_zod4 = require("zod");
3988
+ var dataListBodySchema = import_zod4.z.object({
3714
3989
  filter: objectOrArraySchema.optional(),
3715
3990
  select: projectionSchema.optional(),
3716
- sort: import_zod3.z.string().optional(),
3717
- skip: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3718
- limit: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3719
- page: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3720
- pageSize: import_zod3.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3721
- options: import_zod3.z.object({
3722
- includeCount: import_zod3.z.boolean().optional(),
3723
- includeExtraHeaders: import_zod3.z.boolean().optional()
3991
+ sort: import_zod4.z.string().optional(),
3992
+ skip: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3993
+ limit: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3994
+ page: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3995
+ pageSize: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3996
+ options: import_zod4.z.object({
3997
+ includeCount: import_zod4.z.boolean().optional(),
3998
+ includeExtraHeaders: import_zod4.z.boolean().optional()
3724
3999
  }).passthrough().optional()
3725
4000
  }).passthrough();
3726
- var dataReadFilterBodySchema = import_zod3.z.object({
4001
+ var dataReadFilterBodySchema = import_zod4.z.object({
3727
4002
  filter: objectOrArraySchema.optional(),
3728
4003
  select: projectionSchema.optional()
3729
4004
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
3730
- var dataReadByIdBodySchema = import_zod3.z.object({
4005
+ var dataReadByIdBodySchema = import_zod4.z.object({
3731
4006
  select: projectionSchema.optional()
3732
4007
  }).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
3733
4008
 
3734
4009
  // src/validation/root-router.ts
3735
- var import_zod4 = require("zod");
4010
+ var import_zod5 = require("zod");
3736
4011
  var rootEntryBaseSchema = {
3737
- target: import_zod4.z.enum(["model", "data"]),
3738
- name: import_zod4.z.string().min(1),
3739
- order: import_zod4.z.number().int().optional()
4012
+ target: import_zod5.z.enum(["model", "data"]),
4013
+ name: import_zod5.z.string().min(1),
4014
+ order: import_zod5.z.number().int().optional()
3740
4015
  };
3741
- var rootModelListArgsSchema = import_zod4.z.object({
4016
+ var rootModelListArgsSchema = import_zod5.z.object({
3742
4017
  select: projectionSchema.optional(),
3743
4018
  populate: populateSchema.optional(),
3744
4019
  include: includeSchema.optional(),
3745
4020
  sort: sortSchema.optional(),
3746
- skip: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3747
- limit: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3748
- page: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3749
- pageSize: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4021
+ skip: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4022
+ limit: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4023
+ page: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4024
+ pageSize: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3750
4025
  tasks: tasksSchema.optional()
3751
4026
  }).passthrough();
3752
- var rootModelListOptionsSchema = import_zod4.z.object({
3753
- skim: import_zod4.z.boolean().optional(),
3754
- includePermissions: import_zod4.z.boolean().optional(),
3755
- includeCount: import_zod4.z.boolean().optional(),
3756
- populateAccess: import_zod4.z.unknown().optional(),
3757
- lean: import_zod4.z.boolean().optional()
4027
+ var rootModelListOptionsSchema = import_zod5.z.object({
4028
+ skim: import_zod5.z.boolean().optional(),
4029
+ includePermissions: import_zod5.z.boolean().optional(),
4030
+ includeCount: import_zod5.z.boolean().optional(),
4031
+ populateAccess: import_zod5.z.unknown().optional(),
4032
+ lean: import_zod5.z.boolean().optional()
3758
4033
  }).passthrough();
3759
- var rootModelReadArgsSchema = import_zod4.z.object({
4034
+ var rootModelReadArgsSchema = import_zod5.z.object({
3760
4035
  select: projectionSchema.optional(),
3761
4036
  populate: populateSchema.optional(),
3762
4037
  include: includeSchema.optional(),
@@ -3765,228 +4040,244 @@ var rootModelReadArgsSchema = import_zod4.z.object({
3765
4040
  var rootModelReadFilterArgsSchema = rootModelReadArgsSchema.extend({
3766
4041
  sort: sortSchema.optional()
3767
4042
  });
3768
- var rootModelReadOptionsSchema = import_zod4.z.object({
3769
- skim: import_zod4.z.boolean().optional(),
3770
- includePermissions: import_zod4.z.boolean().optional(),
3771
- tryList: import_zod4.z.boolean().optional(),
3772
- populateAccess: import_zod4.z.unknown().optional(),
3773
- lean: import_zod4.z.boolean().optional()
4043
+ var rootModelReadOptionsSchema = import_zod5.z.object({
4044
+ skim: import_zod5.z.boolean().optional(),
4045
+ includePermissions: import_zod5.z.boolean().optional(),
4046
+ tryList: import_zod5.z.boolean().optional(),
4047
+ populateAccess: import_zod5.z.unknown().optional(),
4048
+ lean: import_zod5.z.boolean().optional()
3774
4049
  }).passthrough();
3775
- var rootModelCreateArgsSchema = import_zod4.z.object({
4050
+ var rootModelCreateArgsSchema = import_zod5.z.object({
3776
4051
  select: projectionSchema.optional(),
3777
4052
  populate: populateSchema.optional(),
3778
4053
  tasks: tasksSchema.optional()
3779
4054
  }).passthrough();
3780
- var rootModelCreateOptionsSchema = import_zod4.z.object({
3781
- skim: import_zod4.z.boolean().optional(),
3782
- includePermissions: import_zod4.z.boolean().optional(),
3783
- populateAccess: import_zod4.z.unknown().optional()
4055
+ var rootModelCreateOptionsSchema = import_zod5.z.object({
4056
+ skim: import_zod5.z.boolean().optional(),
4057
+ includePermissions: import_zod5.z.boolean().optional(),
4058
+ populateAccess: import_zod5.z.unknown().optional()
3784
4059
  }).passthrough();
3785
- var rootModelUpdateArgsSchema = import_zod4.z.object({
4060
+ var rootModelUpdateArgsSchema = import_zod5.z.object({
3786
4061
  select: projectionSchema.optional(),
3787
4062
  populate: populateSchema.optional(),
3788
4063
  tasks: tasksSchema.optional()
3789
4064
  }).passthrough();
3790
- var rootModelUpdateOptionsSchema = import_zod4.z.object({
3791
- skim: import_zod4.z.boolean().optional(),
3792
- returningAll: import_zod4.z.boolean().optional(),
3793
- includePermissions: import_zod4.z.boolean().optional(),
3794
- populateAccess: import_zod4.z.unknown().optional()
4065
+ var rootModelUpdateOptionsSchema = import_zod5.z.object({
4066
+ skim: import_zod5.z.boolean().optional(),
4067
+ returningAll: import_zod5.z.boolean().optional(),
4068
+ includePermissions: import_zod5.z.boolean().optional(),
4069
+ populateAccess: import_zod5.z.unknown().optional()
3795
4070
  }).passthrough();
3796
4071
  var rootModelUpsertArgsSchema = rootModelUpdateArgsSchema;
3797
4072
  var rootModelUpsertOptionsSchema = rootModelUpdateOptionsSchema;
3798
- var rootModelSubListArgsSchema = import_zod4.z.object({
4073
+ var rootModelSubListArgsSchema = import_zod5.z.object({
3799
4074
  select: fieldsSchema.optional()
3800
4075
  }).passthrough();
3801
- var rootModelSubReadArgsSchema = import_zod4.z.object({
4076
+ var rootModelSubReadArgsSchema = import_zod5.z.object({
3802
4077
  select: fieldsSchema.optional(),
3803
4078
  populate: subPopulateSchema.optional()
3804
4079
  }).passthrough();
3805
- var rootModelCountOptionsSchema = import_zod4.z.object({
3806
- access: import_zod4.z.unknown().optional()
4080
+ var rootModelCountOptionsSchema = import_zod5.z.object({
4081
+ access: import_zod5.z.unknown().optional()
3807
4082
  }).passthrough();
3808
- var rootDataListArgsSchema = import_zod4.z.object({
4083
+ var rootDataListArgsSchema = import_zod5.z.object({
3809
4084
  select: projectionSchema.optional(),
3810
- sort: import_zod4.z.string().optional(),
3811
- skip: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3812
- limit: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3813
- page: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
3814
- pageSize: import_zod4.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional()
4085
+ sort: import_zod5.z.string().optional(),
4086
+ skip: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4087
+ limit: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4088
+ page: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
4089
+ pageSize: import_zod5.z.union([nonNegativeIntegerSchema, positiveIntegerString]).optional()
3815
4090
  }).passthrough();
3816
- var rootDataListOptionsSchema = import_zod4.z.object({
3817
- includeCount: import_zod4.z.boolean().optional()
4091
+ var rootDataListOptionsSchema = import_zod5.z.object({
4092
+ includeCount: import_zod5.z.boolean().optional()
3818
4093
  }).passthrough();
3819
- var rootDataReadArgsSchema = import_zod4.z.object({
4094
+ var rootDataReadArgsSchema = import_zod5.z.object({
3820
4095
  select: projectionSchema.optional()
3821
4096
  }).passthrough();
3822
- var rootModelQueryEntrySchema = import_zod4.z.union([
3823
- import_zod4.z.object({ ...rootEntryBaseSchema, target: import_zod4.z.literal("model"), op: import_zod4.z.literal("new") }).passthrough(),
3824
- import_zod4.z.object({
4097
+ var rootModelQueryEntrySchema = import_zod5.z.union([
4098
+ import_zod5.z.object({ ...rootEntryBaseSchema, target: import_zod5.z.literal("model"), op: import_zod5.z.literal("new") }).passthrough(),
4099
+ import_zod5.z.object({
3825
4100
  ...rootEntryBaseSchema,
3826
- target: import_zod4.z.literal("model"),
3827
- op: import_zod4.z.literal("list"),
4101
+ target: import_zod5.z.literal("model"),
4102
+ op: import_zod5.z.literal("list"),
3828
4103
  filter: objectOrArraySchema.optional(),
3829
4104
  args: rootModelListArgsSchema.optional(),
3830
4105
  options: rootModelListOptionsSchema.optional()
3831
4106
  }).passthrough(),
3832
- import_zod4.z.object({
4107
+ import_zod5.z.object({
3833
4108
  ...rootEntryBaseSchema,
3834
- target: import_zod4.z.literal("model"),
3835
- op: import_zod4.z.literal("read"),
3836
- id: import_zod4.z.string().min(1),
4109
+ target: import_zod5.z.literal("model"),
4110
+ op: import_zod5.z.literal("read"),
4111
+ id: import_zod5.z.string().min(1),
3837
4112
  args: rootModelReadArgsSchema.optional(),
3838
4113
  options: rootModelReadOptionsSchema.optional()
3839
4114
  }).passthrough(),
3840
- import_zod4.z.object({
4115
+ import_zod5.z.object({
3841
4116
  ...rootEntryBaseSchema,
3842
- target: import_zod4.z.literal("model"),
3843
- op: import_zod4.z.literal("read"),
4117
+ target: import_zod5.z.literal("model"),
4118
+ op: import_zod5.z.literal("read"),
3844
4119
  filter: objectOrArraySchema,
3845
4120
  args: rootModelReadFilterArgsSchema.optional(),
3846
4121
  options: rootModelReadOptionsSchema.optional()
3847
4122
  }).passthrough(),
3848
- import_zod4.z.object({
4123
+ import_zod5.z.object({
3849
4124
  ...rootEntryBaseSchema,
3850
- target: import_zod4.z.literal("model"),
3851
- op: import_zod4.z.literal("create"),
3852
- data: import_zod4.z.unknown(),
4125
+ target: import_zod5.z.literal("model"),
4126
+ op: import_zod5.z.literal("create"),
4127
+ data: import_zod5.z.unknown(),
3853
4128
  args: rootModelCreateArgsSchema.optional(),
3854
4129
  options: rootModelCreateOptionsSchema.optional()
3855
4130
  }).passthrough(),
3856
- import_zod4.z.object({
4131
+ import_zod5.z.object({
3857
4132
  ...rootEntryBaseSchema,
3858
- target: import_zod4.z.literal("model"),
3859
- op: import_zod4.z.literal("update"),
3860
- id: import_zod4.z.string().min(1),
3861
- data: import_zod4.z.unknown(),
4133
+ target: import_zod5.z.literal("model"),
4134
+ op: import_zod5.z.literal("update"),
4135
+ id: import_zod5.z.string().min(1),
4136
+ data: import_zod5.z.unknown(),
3862
4137
  args: rootModelUpdateArgsSchema.optional(),
3863
4138
  options: rootModelUpdateOptionsSchema.optional()
3864
4139
  }).passthrough(),
3865
- import_zod4.z.object({
4140
+ import_zod5.z.object({
3866
4141
  ...rootEntryBaseSchema,
3867
- target: import_zod4.z.literal("model"),
3868
- op: import_zod4.z.literal("upsert"),
3869
- data: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()),
4142
+ target: import_zod5.z.literal("model"),
4143
+ op: import_zod5.z.literal("upsert"),
4144
+ data: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()),
3870
4145
  args: rootModelUpsertArgsSchema.optional(),
3871
4146
  options: rootModelUpsertOptionsSchema.optional()
3872
4147
  }).passthrough(),
3873
- import_zod4.z.object({ ...rootEntryBaseSchema, target: import_zod4.z.literal("model"), op: import_zod4.z.literal("delete"), id: import_zod4.z.string().min(1) }).passthrough(),
3874
- import_zod4.z.object({
4148
+ import_zod5.z.object({ ...rootEntryBaseSchema, target: import_zod5.z.literal("model"), op: import_zod5.z.literal("delete"), id: import_zod5.z.string().min(1) }).passthrough(),
4149
+ import_zod5.z.object({
3875
4150
  ...rootEntryBaseSchema,
3876
- target: import_zod4.z.literal("model"),
3877
- op: import_zod4.z.literal("subList"),
3878
- id: import_zod4.z.string().min(1),
3879
- sub: import_zod4.z.string().min(1),
3880
- filter: import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()).optional(),
4151
+ target: import_zod5.z.literal("model"),
4152
+ op: import_zod5.z.literal("subList"),
4153
+ id: import_zod5.z.string().min(1),
4154
+ sub: import_zod5.z.string().min(1),
4155
+ filter: import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()).optional(),
3881
4156
  args: rootModelSubListArgsSchema.optional()
3882
4157
  }).passthrough(),
3883
- import_zod4.z.object({
4158
+ import_zod5.z.object({
3884
4159
  ...rootEntryBaseSchema,
3885
- target: import_zod4.z.literal("model"),
3886
- op: import_zod4.z.literal("subRead"),
3887
- id: import_zod4.z.string().min(1),
3888
- sub: import_zod4.z.string().min(1),
3889
- subId: import_zod4.z.string().min(1),
4160
+ target: import_zod5.z.literal("model"),
4161
+ op: import_zod5.z.literal("subRead"),
4162
+ id: import_zod5.z.string().min(1),
4163
+ sub: import_zod5.z.string().min(1),
4164
+ subId: import_zod5.z.string().min(1),
3890
4165
  args: rootModelSubReadArgsSchema.optional()
3891
4166
  }).passthrough(),
3892
- import_zod4.z.object({
4167
+ import_zod5.z.object({
3893
4168
  ...rootEntryBaseSchema,
3894
- target: import_zod4.z.literal("model"),
3895
- op: import_zod4.z.literal("subCreate"),
3896
- id: import_zod4.z.string().min(1),
3897
- sub: import_zod4.z.string().min(1),
3898
- data: import_zod4.z.union([import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()), import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()))])
4169
+ target: import_zod5.z.literal("model"),
4170
+ op: import_zod5.z.literal("subCreate"),
4171
+ id: import_zod5.z.string().min(1),
4172
+ sub: import_zod5.z.string().min(1),
4173
+ data: import_zod5.z.union([import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()), import_zod5.z.array(import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()))])
3899
4174
  }).passthrough(),
3900
- import_zod4.z.object({
4175
+ import_zod5.z.object({
3901
4176
  ...rootEntryBaseSchema,
3902
- target: import_zod4.z.literal("model"),
3903
- op: import_zod4.z.literal("subUpdate"),
3904
- id: import_zod4.z.string().min(1),
3905
- sub: import_zod4.z.string().min(1),
3906
- subId: import_zod4.z.string().min(1),
3907
- data: import_zod4.z.union([import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()), import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()))])
4177
+ target: import_zod5.z.literal("model"),
4178
+ op: import_zod5.z.literal("subUpdate"),
4179
+ id: import_zod5.z.string().min(1),
4180
+ sub: import_zod5.z.string().min(1),
4181
+ subId: import_zod5.z.string().min(1),
4182
+ data: import_zod5.z.union([import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()), import_zod5.z.array(import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()))])
3908
4183
  }).passthrough(),
3909
- import_zod4.z.object({
4184
+ import_zod5.z.object({
3910
4185
  ...rootEntryBaseSchema,
3911
- target: import_zod4.z.literal("model"),
3912
- op: import_zod4.z.literal("subBulkUpdate"),
3913
- id: import_zod4.z.string().min(1),
3914
- sub: import_zod4.z.string().min(1),
3915
- data: import_zod4.z.union([import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()), import_zod4.z.array(import_zod4.z.record(import_zod4.z.string(), import_zod4.z.unknown()))])
4186
+ target: import_zod5.z.literal("model"),
4187
+ op: import_zod5.z.literal("subBulkUpdate"),
4188
+ id: import_zod5.z.string().min(1),
4189
+ sub: import_zod5.z.string().min(1),
4190
+ data: import_zod5.z.union([import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()), import_zod5.z.array(import_zod5.z.record(import_zod5.z.string(), import_zod5.z.unknown()))])
3916
4191
  }).passthrough(),
3917
- import_zod4.z.object({
4192
+ import_zod5.z.object({
3918
4193
  ...rootEntryBaseSchema,
3919
- target: import_zod4.z.literal("model"),
3920
- op: import_zod4.z.literal("subDelete"),
3921
- id: import_zod4.z.string().min(1),
3922
- sub: import_zod4.z.string().min(1),
3923
- subId: import_zod4.z.string().min(1)
4194
+ target: import_zod5.z.literal("model"),
4195
+ op: import_zod5.z.literal("subDelete"),
4196
+ id: import_zod5.z.string().min(1),
4197
+ sub: import_zod5.z.string().min(1),
4198
+ subId: import_zod5.z.string().min(1)
3924
4199
  }).passthrough(),
3925
- import_zod4.z.object({
4200
+ import_zod5.z.object({
3926
4201
  ...rootEntryBaseSchema,
3927
- target: import_zod4.z.literal("model"),
3928
- op: import_zod4.z.literal("distinct"),
3929
- field: import_zod4.z.string().min(1),
4202
+ target: import_zod5.z.literal("model"),
4203
+ op: import_zod5.z.literal("distinct"),
4204
+ field: import_zod5.z.string().min(1),
3930
4205
  filter: objectOrArraySchema.optional()
3931
4206
  }).passthrough(),
3932
- import_zod4.z.object({
4207
+ import_zod5.z.object({
3933
4208
  ...rootEntryBaseSchema,
3934
- target: import_zod4.z.literal("model"),
3935
- op: import_zod4.z.literal("count"),
4209
+ target: import_zod5.z.literal("model"),
4210
+ op: import_zod5.z.literal("count"),
3936
4211
  filter: objectOrArraySchema.optional(),
3937
4212
  options: rootModelCountOptionsSchema.optional()
3938
4213
  }).passthrough()
3939
4214
  ]);
3940
- var rootDataQueryEntrySchema = import_zod4.z.union([
3941
- import_zod4.z.object({
4215
+ var rootDataQueryEntrySchema = import_zod5.z.union([
4216
+ import_zod5.z.object({
3942
4217
  ...rootEntryBaseSchema,
3943
- target: import_zod4.z.literal("data"),
3944
- op: import_zod4.z.literal("list"),
4218
+ target: import_zod5.z.literal("data"),
4219
+ op: import_zod5.z.literal("list"),
3945
4220
  filter: objectOrArraySchema.optional(),
3946
4221
  args: rootDataListArgsSchema.optional(),
3947
4222
  options: rootDataListOptionsSchema.optional()
3948
4223
  }).passthrough(),
3949
- import_zod4.z.object({
4224
+ import_zod5.z.object({
3950
4225
  ...rootEntryBaseSchema,
3951
- target: import_zod4.z.literal("data"),
3952
- op: import_zod4.z.literal("read"),
3953
- id: import_zod4.z.string().min(1),
4226
+ target: import_zod5.z.literal("data"),
4227
+ op: import_zod5.z.literal("read"),
4228
+ id: import_zod5.z.string().min(1),
3954
4229
  args: rootDataReadArgsSchema.optional()
3955
4230
  }).passthrough(),
3956
- import_zod4.z.object({
4231
+ import_zod5.z.object({
3957
4232
  ...rootEntryBaseSchema,
3958
- target: import_zod4.z.literal("data"),
3959
- op: import_zod4.z.literal("read"),
4233
+ target: import_zod5.z.literal("data"),
4234
+ op: import_zod5.z.literal("read"),
3960
4235
  filter: objectOrArraySchema,
3961
4236
  args: rootDataReadArgsSchema.optional()
3962
4237
  }).passthrough()
3963
4238
  ]);
3964
- var rootQuerySchema = import_zod4.z.array(import_zod4.z.union([rootModelQueryEntrySchema, rootDataQueryEntrySchema]));
4239
+ var rootQuerySchema = import_zod5.z.array(import_zod5.z.union([rootModelQueryEntrySchema, rootDataQueryEntrySchema]));
3965
4240
 
3966
4241
  // src/routers/shared.ts
3967
- var parseBooleanString = (str, defaultValue) => str ? str === "true" : defaultValue;
4242
+ var import_utils21 = require("@web-ts-toolkit/utils");
3968
4243
 
3969
4244
  // src/routers/model-router-collection-routes.ts
3970
4245
  function setModelCollectionRoutes(context) {
3971
4246
  const { router, options } = context;
4247
+ const getAdvancedCreateOpenApiBody = () => {
4248
+ const advancedCreateSchema = context.getRequestSchema("requestSchemas.advancedCreate");
4249
+ const dataSchema = context.getRequestSchema("requestSchemas.advancedCreate.data") ?? getNestedOpenApiSchemaDataSource(advancedCreateSchema);
4250
+ const bodySchema = unwrapNestedOpenApiSchemaSource(
4251
+ context.getRequestSchema("requestSchemas.advancedCreate.default") ?? advancedCreateSchema,
4252
+ advancedCreateBodySchema
4253
+ );
4254
+ return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
4255
+ };
3972
4256
  router.get("", async (req) => {
3973
4257
  await context.assertAllowed(req, "list");
3974
4258
  const { skip, limit, page, page_size, skim, include_permissions, include_count, include_extra_headers } = parseQuery(requestSchemas.listQuery, req.query);
3975
4259
  const svc = context.getPublicService(req);
3976
- const includeCount = parseBooleanString(include_count);
3977
- const includeExtraHeaders = parseBooleanString(include_extra_headers);
4260
+ const includeCount = (0, import_utils21.parseBooleanString)(include_count);
4261
+ const includeExtraHeaders = (0, import_utils21.parseBooleanString)(include_extra_headers);
3978
4262
  const result = await svc._list(
3979
4263
  {},
3980
4264
  { skip, limit, page, pageSize: page_size },
3981
4265
  {
3982
- skim: parseBooleanString(skim),
3983
- includePermissions: parseBooleanString(include_permissions),
4266
+ skim: (0, import_utils21.parseBooleanString)(skim),
4267
+ includePermissions: (0, import_utils21.parseBooleanString)(include_permissions),
3984
4268
  includeCount
3985
4269
  }
3986
4270
  );
3987
4271
  handleResultError(result);
3988
4272
  return formatModelListResponse(req, result, includeCount, includeExtraHeaders);
3989
4273
  });
4274
+ context.registerOpenApiRoute({
4275
+ method: "get",
4276
+ path: "",
4277
+ operationId: `${context.modelName}.list`,
4278
+ summary: `List ${context.modelName} documents`,
4279
+ query: requestSchemas.listQuery
4280
+ });
3990
4281
  router.post(`/${options.queryRouteSegment}`, async (req) => {
3991
4282
  await context.assertAllowed(req, "list");
3992
4283
  const body = await parseBodyWithSchema(
@@ -4012,6 +4303,13 @@ function setModelCollectionRoutes(context) {
4012
4303
  handleResultError(result);
4013
4304
  return formatModelListResponse(req, result, includeCount, includeExtraHeaders);
4014
4305
  });
4306
+ context.registerOpenApiRoute({
4307
+ method: "post",
4308
+ path: `/${options.queryRouteSegment}`,
4309
+ operationId: `${context.modelName}.listAdvanced`,
4310
+ summary: `Advanced list ${context.modelName} documents`,
4311
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.advancedList") ?? listBodySchema)
4312
+ });
4015
4313
  router.post("", async (req) => {
4016
4314
  await context.assertAllowed(req, "create");
4017
4315
  const { include_permissions } = parseQuery(requestSchemas.createQuery, req.query);
@@ -4021,10 +4319,18 @@ function setModelCollectionRoutes(context) {
4021
4319
  context.getRequestSchema("requestSchemas.create")
4022
4320
  );
4023
4321
  const svc = context.getPublicService(req);
4024
- const result = await svc._create(data, {}, { includePermissions: parseBooleanString(include_permissions) });
4322
+ const result = await svc._create(data, {}, { includePermissions: (0, import_utils21.parseBooleanString)(include_permissions) });
4025
4323
  handleResultError(result);
4026
4324
  return formatModelCreatedResponse(result);
4027
4325
  });
4326
+ context.registerOpenApiRoute({
4327
+ method: "post",
4328
+ path: "",
4329
+ operationId: `${context.modelName}.create`,
4330
+ summary: `Create a ${context.modelName} document`,
4331
+ query: requestSchemas.createQuery,
4332
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.create") ?? createBodySchema)
4333
+ });
4028
4334
  router.post(`/${options.mutationRouteSegment}`, async (req) => {
4029
4335
  await context.assertAllowed(req, "create");
4030
4336
  const { include_permissions } = parseQuery(requestSchemas.createQuery, req.query);
@@ -4047,24 +4353,56 @@ function setModelCollectionRoutes(context) {
4047
4353
  data,
4048
4354
  { select, populate, tasks },
4049
4355
  {
4050
- includePermissions: includePermissions ?? parseBooleanString(include_permissions),
4356
+ includePermissions: includePermissions ?? (0, import_utils21.parseBooleanString)(include_permissions),
4051
4357
  populateAccess
4052
4358
  }
4053
4359
  );
4054
4360
  handleResultError(result);
4055
4361
  return formatModelCreatedResponse(result);
4056
4362
  });
4363
+ context.registerOpenApiRoute({
4364
+ method: "post",
4365
+ path: `/${options.mutationRouteSegment}`,
4366
+ operationId: `${context.modelName}.createAdvanced`,
4367
+ summary: `Advanced create a ${context.modelName} document`,
4368
+ query: requestSchemas.createQuery,
4369
+ body: defineOpenApiSchemaResolver(getAdvancedCreateOpenApiBody)
4370
+ });
4057
4371
  router.get("/new", async (req) => {
4058
4372
  const svc = context.getPublicService(req);
4059
4373
  const result = await svc._new();
4060
4374
  handleResultError(result);
4061
4375
  return unwrapServiceData(result);
4062
4376
  });
4377
+ context.registerOpenApiRoute({
4378
+ method: "get",
4379
+ path: "/new",
4380
+ operationId: `${context.modelName}.new`,
4381
+ summary: `Get a new ${context.modelName} document template`
4382
+ });
4063
4383
  }
4064
4384
 
4065
4385
  // src/routers/model-router-document-routes.ts
4066
4386
  function setModelDocumentRoutes(context) {
4067
4387
  const { router, options, modelName } = context;
4388
+ const getAdvancedUpdateOpenApiBody = () => {
4389
+ const advancedUpdateSchema = context.getRequestSchema("requestSchemas.advancedUpdate");
4390
+ const dataSchema = context.getRequestSchema("requestSchemas.advancedUpdate.data") ?? getNestedOpenApiSchemaDataSource(advancedUpdateSchema);
4391
+ const bodySchema = unwrapNestedOpenApiSchemaSource(
4392
+ context.getRequestSchema("requestSchemas.advancedUpdate.default") ?? advancedUpdateSchema,
4393
+ advancedUpdateBodySchema
4394
+ );
4395
+ return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
4396
+ };
4397
+ const getAdvancedUpsertOpenApiBody = () => {
4398
+ const advancedUpsertSchema = context.getRequestSchema("requestSchemas.advancedUpsert");
4399
+ const dataSchema = context.getRequestSchema("requestSchemas.advancedUpsert.data") ?? getNestedOpenApiSchemaDataSource(advancedUpsertSchema);
4400
+ const bodySchema = unwrapNestedOpenApiSchemaSource(
4401
+ context.getRequestSchema("requestSchemas.advancedUpsert.default") ?? advancedUpsertSchema,
4402
+ advancedUpsertBodySchema
4403
+ );
4404
+ return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
4405
+ };
4068
4406
  router.get("/count", async (req) => {
4069
4407
  await context.assertAllowed(req, "count");
4070
4408
  const svc = context.getPublicService(req);
@@ -4072,6 +4410,12 @@ function setModelDocumentRoutes(context) {
4072
4410
  handleResultError(result);
4073
4411
  return unwrapServiceData(result);
4074
4412
  });
4413
+ context.registerOpenApiRoute({
4414
+ method: "get",
4415
+ path: "/count",
4416
+ operationId: `${modelName}.count`,
4417
+ summary: `Count ${modelName} documents`
4418
+ });
4075
4419
  router.post("/count", async (req) => {
4076
4420
  await context.assertAllowed(req, "count");
4077
4421
  const { filter: filter2, options: countOptions = {} } = await parseBodyWithSchema(
@@ -4087,6 +4431,13 @@ function setModelDocumentRoutes(context) {
4087
4431
  handleResultError(result);
4088
4432
  return unwrapServiceData(result);
4089
4433
  });
4434
+ context.registerOpenApiRoute({
4435
+ method: "post",
4436
+ path: "/count",
4437
+ operationId: `${modelName}.countWithFilter`,
4438
+ summary: `Count ${modelName} documents with a filter`,
4439
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.count") ?? countBodySchema)
4440
+ });
4090
4441
  router.get(`/:${options.idParam}`, async (req) => {
4091
4442
  await context.assertAllowed(req, "read");
4092
4443
  const id = parsePathParam(req.params[options.idParam], options.idParam);
@@ -4096,13 +4447,20 @@ function setModelDocumentRoutes(context) {
4096
4447
  id,
4097
4448
  {},
4098
4449
  {
4099
- includePermissions: parseBooleanString(include_permissions),
4100
- tryList: parseBooleanString(try_list)
4450
+ includePermissions: (0, import_utils21.parseBooleanString)(include_permissions),
4451
+ tryList: (0, import_utils21.parseBooleanString)(try_list)
4101
4452
  }
4102
4453
  );
4103
4454
  handleResultError(result);
4104
4455
  return unwrapServiceData(result);
4105
4456
  });
4457
+ context.registerOpenApiRoute({
4458
+ method: "get",
4459
+ path: `/:${options.idParam}`,
4460
+ operationId: `${modelName}.read`,
4461
+ summary: `Read a ${modelName} document`,
4462
+ query: requestSchemas.readQuery
4463
+ });
4106
4464
  router.post(`/${options.queryRouteSegment}/__filter`, async (req) => {
4107
4465
  await context.assertAllowed(req, "read");
4108
4466
  const body = await parseBodyWithSchema(
@@ -4122,6 +4480,15 @@ function setModelDocumentRoutes(context) {
4122
4480
  handleResultError(result);
4123
4481
  return unwrapServiceData(result);
4124
4482
  });
4483
+ context.registerOpenApiRoute({
4484
+ method: "post",
4485
+ path: `/${options.queryRouteSegment}/__filter`,
4486
+ operationId: `${modelName}.readByFilterAdvanced`,
4487
+ summary: `Read a ${modelName} document by filter`,
4488
+ body: defineOpenApiSchemaResolver(
4489
+ () => context.getRequestSchema("requestSchemas.advancedReadFilter") ?? readFilterBodySchema
4490
+ )
4491
+ });
4125
4492
  router.post(`/${options.queryRouteSegment}/:${options.idParam}`, async (req) => {
4126
4493
  await context.assertAllowed(req, "read");
4127
4494
  const id = parsePathParam(req.params[options.idParam], options.idParam);
@@ -4142,6 +4509,15 @@ function setModelDocumentRoutes(context) {
4142
4509
  handleResultError(result);
4143
4510
  return unwrapServiceData(result);
4144
4511
  });
4512
+ context.registerOpenApiRoute({
4513
+ method: "post",
4514
+ path: `/${options.queryRouteSegment}/:${options.idParam}`,
4515
+ operationId: `${modelName}.readAdvanced`,
4516
+ summary: `Read a ${modelName} document with advanced options`,
4517
+ body: defineOpenApiSchemaResolver(
4518
+ () => context.getRequestSchema("requestSchemas.advancedRead") ?? readByIdBodySchema
4519
+ )
4520
+ });
4145
4521
  router.patch(`/:${options.idParam}`, async (req) => {
4146
4522
  await context.assertAllowed(req, "update");
4147
4523
  const id = parsePathParam(req.params[options.idParam], options.idParam);
@@ -4157,13 +4533,21 @@ function setModelDocumentRoutes(context) {
4157
4533
  data,
4158
4534
  {},
4159
4535
  {
4160
- returningAll: parseBooleanString(returning_all),
4161
- includePermissions: parseBooleanString(include_permissions)
4536
+ returningAll: (0, import_utils21.parseBooleanString)(returning_all),
4537
+ includePermissions: (0, import_utils21.parseBooleanString)(include_permissions)
4162
4538
  }
4163
4539
  );
4164
4540
  handleResultError(result);
4165
4541
  return unwrapServiceData(result);
4166
4542
  });
4543
+ context.registerOpenApiRoute({
4544
+ method: "patch",
4545
+ path: `/:${options.idParam}`,
4546
+ operationId: `${modelName}.update`,
4547
+ summary: `Update a ${modelName} document`,
4548
+ query: requestSchemas.updateQuery,
4549
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.update") ?? updateBodySchema)
4550
+ });
4167
4551
  router.patch(`/${options.mutationRouteSegment}/:${options.idParam}`, async (req) => {
4168
4552
  await context.assertAllowed(req, "update");
4169
4553
  const id = parsePathParam(req.params[options.idParam], options.idParam);
@@ -4188,14 +4572,22 @@ function setModelDocumentRoutes(context) {
4188
4572
  data,
4189
4573
  { select, populate, tasks },
4190
4574
  {
4191
- returningAll: returningAll ?? parseBooleanString(returning_all),
4192
- includePermissions: includePermissions ?? parseBooleanString(include_permissions),
4575
+ returningAll: returningAll ?? (0, import_utils21.parseBooleanString)(returning_all),
4576
+ includePermissions: includePermissions ?? (0, import_utils21.parseBooleanString)(include_permissions),
4193
4577
  populateAccess
4194
4578
  }
4195
4579
  );
4196
4580
  handleResultError(result);
4197
4581
  return unwrapServiceData(result);
4198
4582
  });
4583
+ context.registerOpenApiRoute({
4584
+ method: "patch",
4585
+ path: `/${options.mutationRouteSegment}/:${options.idParam}`,
4586
+ operationId: `${modelName}.updateAdvanced`,
4587
+ summary: `Advanced update a ${modelName} document`,
4588
+ query: requestSchemas.updateQuery,
4589
+ body: defineOpenApiSchemaResolver(getAdvancedUpdateOpenApiBody)
4590
+ });
4199
4591
  router.put(`/`, async (req) => {
4200
4592
  await context.assertAllowed(req, "upsert");
4201
4593
  const svc = context.getPublicService(req);
@@ -4209,13 +4601,21 @@ function setModelDocumentRoutes(context) {
4209
4601
  body,
4210
4602
  {},
4211
4603
  {
4212
- returningAll: parseBooleanString(returning_all),
4213
- includePermissions: parseBooleanString(include_permissions)
4604
+ returningAll: (0, import_utils21.parseBooleanString)(returning_all),
4605
+ includePermissions: (0, import_utils21.parseBooleanString)(include_permissions)
4214
4606
  }
4215
4607
  );
4216
4608
  handleResultError(result);
4217
4609
  return formatModelUpsertResponse(result);
4218
4610
  });
4611
+ context.registerOpenApiRoute({
4612
+ method: "put",
4613
+ path: "/",
4614
+ operationId: `${modelName}.upsert`,
4615
+ summary: `Upsert a ${modelName} document`,
4616
+ query: requestSchemas.upsertQuery,
4617
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.upsert") ?? upsertBodySchema)
4618
+ });
4219
4619
  router.put(`/${options.mutationRouteSegment}`, async (req) => {
4220
4620
  await context.assertAllowed(req, "upsert");
4221
4621
  const svc = context.getPublicService(req);
@@ -4238,14 +4638,22 @@ function setModelDocumentRoutes(context) {
4238
4638
  data,
4239
4639
  { select, populate, tasks },
4240
4640
  {
4241
- returningAll: returningAll ?? parseBooleanString(returning_all),
4242
- includePermissions: includePermissions ?? parseBooleanString(include_permissions),
4641
+ returningAll: returningAll ?? (0, import_utils21.parseBooleanString)(returning_all),
4642
+ includePermissions: includePermissions ?? (0, import_utils21.parseBooleanString)(include_permissions),
4243
4643
  populateAccess
4244
4644
  }
4245
4645
  );
4246
4646
  handleResultError(result);
4247
4647
  return formatModelUpsertResponse(result);
4248
4648
  });
4649
+ context.registerOpenApiRoute({
4650
+ method: "put",
4651
+ path: `/${options.mutationRouteSegment}`,
4652
+ operationId: `${modelName}.upsertAdvanced`,
4653
+ summary: `Advanced upsert a ${modelName} document`,
4654
+ query: requestSchemas.upsertQuery,
4655
+ body: defineOpenApiSchemaResolver(getAdvancedUpsertOpenApiBody)
4656
+ });
4249
4657
  router.delete(`/:${options.idParam}`, async (req) => {
4250
4658
  await context.assertAllowed(req, "delete");
4251
4659
  const id = parsePathParam(req.params[options.idParam], options.idParam);
@@ -4254,6 +4662,12 @@ function setModelDocumentRoutes(context) {
4254
4662
  handleResultError(result);
4255
4663
  return unwrapServiceData(result);
4256
4664
  });
4665
+ context.registerOpenApiRoute({
4666
+ method: "delete",
4667
+ path: `/:${options.idParam}`,
4668
+ operationId: `${modelName}.delete`,
4669
+ summary: `Delete a ${modelName} document`
4670
+ });
4257
4671
  router.get("/distinct/:field", async (req) => {
4258
4672
  await context.assertAllowed(req, "distinct");
4259
4673
  const field = parsePathParam(req.params.field, "field");
@@ -4262,6 +4676,12 @@ function setModelDocumentRoutes(context) {
4262
4676
  handleResultError(result);
4263
4677
  return unwrapServiceData(result);
4264
4678
  });
4679
+ context.registerOpenApiRoute({
4680
+ method: "get",
4681
+ path: "/distinct/:field",
4682
+ operationId: `${modelName}.distinct`,
4683
+ summary: `Get distinct values for a ${modelName} field`
4684
+ });
4265
4685
  router.post("/distinct/:field", async (req) => {
4266
4686
  await context.assertAllowed(req, "distinct");
4267
4687
  const field = parsePathParam(req.params.field, "field");
@@ -4275,10 +4695,17 @@ function setModelDocumentRoutes(context) {
4275
4695
  handleResultError(result);
4276
4696
  return unwrapServiceData(result);
4277
4697
  });
4698
+ context.registerOpenApiRoute({
4699
+ method: "post",
4700
+ path: "/distinct/:field",
4701
+ operationId: `${modelName}.distinctWithFilter`,
4702
+ summary: `Get distinct values for a ${modelName} field with a filter`,
4703
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.distinct") ?? distinctBodySchema)
4704
+ });
4278
4705
  }
4279
4706
 
4280
4707
  // src/routers/model-router-subdocument-routes.ts
4281
- var import_utils18 = require("@web-ts-toolkit/utils");
4708
+ var import_utils22 = require("@web-ts-toolkit/utils");
4282
4709
  function setModelSubDocumentRoutes(context) {
4283
4710
  const subs = getModelSub(context.modelName);
4284
4711
  for (let x = 0; x < subs.length; x++) {
@@ -4291,6 +4718,12 @@ function setModelSubDocumentRoutes(context) {
4291
4718
  handleResultError(result);
4292
4719
  return unwrapServiceData(result);
4293
4720
  });
4721
+ context.registerOpenApiRoute({
4722
+ method: "get",
4723
+ path: `/:${context.options.idParam}/${sub}`,
4724
+ operationId: `${context.modelName}.${sub}.list`,
4725
+ summary: `List ${sub} subdocuments`
4726
+ });
4294
4727
  context.router.post(
4295
4728
  `/:${context.options.idParam}/${sub}/${context.options.queryRouteSegment}`,
4296
4729
  async (req) => {
@@ -4307,6 +4740,13 @@ function setModelSubDocumentRoutes(context) {
4307
4740
  return unwrapServiceData(result);
4308
4741
  }
4309
4742
  );
4743
+ context.registerOpenApiRoute({
4744
+ method: "post",
4745
+ path: `/:${context.options.idParam}/${sub}/${context.options.queryRouteSegment}`,
4746
+ operationId: `${context.modelName}.${sub}.listAdvanced`,
4747
+ summary: `Advanced list ${sub} subdocuments`,
4748
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.subList") ?? subListBodySchema)
4749
+ });
4310
4750
  context.router.patch(`/:${context.options.idParam}/${sub}`, async (req) => {
4311
4751
  await context.assertAllowed(req, `subs.${sub}.update`);
4312
4752
  const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
@@ -4320,6 +4760,15 @@ function setModelSubDocumentRoutes(context) {
4320
4760
  handleResultError(result);
4321
4761
  return unwrapServiceData(result);
4322
4762
  });
4763
+ context.registerOpenApiRoute({
4764
+ method: "patch",
4765
+ path: `/:${context.options.idParam}/${sub}`,
4766
+ operationId: `${context.modelName}.${sub}.bulkUpdate`,
4767
+ summary: `Bulk update ${sub} subdocuments`,
4768
+ body: defineOpenApiSchemaResolver(
4769
+ () => context.getRequestSchema("requestSchemas.subBulkUpdate") ?? subMutationBodySchema
4770
+ )
4771
+ });
4323
4772
  context.router.get(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
4324
4773
  await context.assertAllowed(req, `subs.${sub}.read`);
4325
4774
  const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
@@ -4329,6 +4778,12 @@ function setModelSubDocumentRoutes(context) {
4329
4778
  handleResultError(result);
4330
4779
  return unwrapServiceData(result);
4331
4780
  });
4781
+ context.registerOpenApiRoute({
4782
+ method: "get",
4783
+ path: `/:${context.options.idParam}/${sub}/:subId`,
4784
+ operationId: `${context.modelName}.${sub}.read`,
4785
+ summary: `Read a ${sub} subdocument`
4786
+ });
4332
4787
  context.router.post(
4333
4788
  `/:${context.options.idParam}/${sub}/:subId/${context.options.queryRouteSegment}`,
4334
4789
  async (req) => {
@@ -4341,13 +4796,20 @@ function setModelSubDocumentRoutes(context) {
4341
4796
  context.getRequestSchema("requestSchemas.subRead")
4342
4797
  );
4343
4798
  const populate = body.populate;
4344
- const normalizedPopulate = Array.isArray(populate) ? populate.map((item) => (0, import_utils18.isString)(item) ? { path: item } : item) : (0, import_utils18.isString)(populate) ? { path: populate } : populate ?? [];
4799
+ const normalizedPopulate = Array.isArray(populate) ? populate.map((item) => (0, import_utils22.isString)(item) ? { path: item } : item) : (0, import_utils22.isString)(populate) ? { path: populate } : populate ?? [];
4345
4800
  const svc = context.getPublicService(req);
4346
4801
  const result = await svc.readSub(id, sub, subId, { select: body.select ?? [], populate: normalizedPopulate });
4347
4802
  handleResultError(result);
4348
4803
  return unwrapServiceData(result);
4349
4804
  }
4350
4805
  );
4806
+ context.registerOpenApiRoute({
4807
+ method: "post",
4808
+ path: `/:${context.options.idParam}/${sub}/:subId/${context.options.queryRouteSegment}`,
4809
+ operationId: `${context.modelName}.${sub}.readAdvanced`,
4810
+ summary: `Advanced read a ${sub} subdocument`,
4811
+ body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.subRead") ?? subReadBodySchema)
4812
+ });
4351
4813
  context.router.patch(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
4352
4814
  await context.assertAllowed(req, `subs.${sub}.update`);
4353
4815
  const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
@@ -4362,6 +4824,15 @@ function setModelSubDocumentRoutes(context) {
4362
4824
  handleResultError(result);
4363
4825
  return unwrapServiceData(result);
4364
4826
  });
4827
+ context.registerOpenApiRoute({
4828
+ method: "patch",
4829
+ path: `/:${context.options.idParam}/${sub}/:subId`,
4830
+ operationId: `${context.modelName}.${sub}.update`,
4831
+ summary: `Update a ${sub} subdocument`,
4832
+ body: defineOpenApiSchemaResolver(
4833
+ () => context.getRequestSchema("requestSchemas.subUpdate") ?? subMutationBodySchema
4834
+ )
4835
+ });
4365
4836
  context.router.post(`/:${context.options.idParam}/${sub}`, async (req) => {
4366
4837
  await context.assertAllowed(req, `subs.${sub}.create`);
4367
4838
  const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
@@ -4375,6 +4846,15 @@ function setModelSubDocumentRoutes(context) {
4375
4846
  handleResultError(result);
4376
4847
  return formatModelCreatedResponse(result);
4377
4848
  });
4849
+ context.registerOpenApiRoute({
4850
+ method: "post",
4851
+ path: `/:${context.options.idParam}/${sub}`,
4852
+ operationId: `${context.modelName}.${sub}.create`,
4853
+ summary: `Create a ${sub} subdocument`,
4854
+ body: defineOpenApiSchemaResolver(
4855
+ () => context.getRequestSchema("requestSchemas.subCreate") ?? subMutationBodySchema
4856
+ )
4857
+ });
4378
4858
  context.router.delete(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
4379
4859
  await context.assertAllowed(req, `subs.${sub}.delete`);
4380
4860
  const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
@@ -4384,14 +4864,30 @@ function setModelSubDocumentRoutes(context) {
4384
4864
  handleResultError(result);
4385
4865
  return unwrapServiceData(result);
4386
4866
  });
4867
+ context.registerOpenApiRoute({
4868
+ method: "delete",
4869
+ path: `/:${context.options.idParam}/${sub}/:subId`,
4870
+ operationId: `${context.modelName}.${sub}.delete`,
4871
+ summary: `Delete a ${sub} subdocument`
4872
+ });
4387
4873
  }
4388
4874
  }
4389
4875
 
4876
+ // src/openapi/route-registration.ts
4877
+ var import_utils23 = require("@web-ts-toolkit/utils");
4878
+ function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
4879
+ runtime.registerOpenApiRoute({
4880
+ ...route,
4881
+ path: (0, import_utils23.normalizeUrlPath)(basePath + route.path),
4882
+ tags: route.tags ?? [defaultTag]
4883
+ });
4884
+ }
4885
+
4390
4886
  // src/routers/model-router.ts
4391
4887
  var clientErrors2 = import_express_json_router5.default.clientErrors;
4392
4888
  function setOption(parentKey, optionKey, option) {
4393
- const key = (0, import_utils19.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
4394
- const value = (0, import_utils19.isUndefined)(option) ? optionKey : option;
4889
+ const key = (0, import_utils24.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
4890
+ const value = (0, import_utils24.isUndefined)(option) ? optionKey : option;
4395
4891
  assertMutableRouterOption("model", key);
4396
4892
  this.runtime.setModelOption(this.modelName, key, value);
4397
4893
  return this;
@@ -4552,7 +5048,7 @@ var ModelRouter = class {
4552
5048
  this.runtime.setModelOptions(modelName, initialOptions);
4553
5049
  attachRuntimeToModel(modelName, this.runtime);
4554
5050
  this.options = this.runtime.getModelOptions(modelName);
4555
- this.fullBasePath = (0, import_utils19.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
5051
+ this.fullBasePath = (0, import_utils24.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
4556
5052
  this.modelName = modelName;
4557
5053
  this.router = new import_express_json_router5.default(this.options.basePath, createSetCore(this.runtime), accessRouterResponseHandler);
4558
5054
  this.model = new model_default(modelName);
@@ -4577,6 +5073,9 @@ var ModelRouter = class {
4577
5073
  const allowed = await req.macl.isAllowed(this.modelName, access);
4578
5074
  if (!allowed) throw new clientErrors2.UnauthorizedError();
4579
5075
  }
5076
+ registerOpenApiRoute(route) {
5077
+ registerOpenApiRoute(this.runtime, this.fullBasePath, this.modelName, route);
5078
+ }
4580
5079
  ///////////////////////
4581
5080
  // Collection Routes //
4582
5081
  ///////////////////////
@@ -4587,7 +5086,8 @@ var ModelRouter = class {
4587
5086
  options: this.options,
4588
5087
  getRequestSchema: this.getRequestSchema.bind(this),
4589
5088
  getPublicService: this.getPublicService.bind(this),
4590
- assertAllowed: this.assertAllowed.bind(this)
5089
+ assertAllowed: this.assertAllowed.bind(this),
5090
+ registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
4591
5091
  });
4592
5092
  }
4593
5093
  /////////////////////
@@ -4600,7 +5100,8 @@ var ModelRouter = class {
4600
5100
  options: this.options,
4601
5101
  getRequestSchema: this.getRequestSchema.bind(this),
4602
5102
  getPublicService: this.getPublicService.bind(this),
4603
- assertAllowed: this.assertAllowed.bind(this)
5103
+ assertAllowed: this.assertAllowed.bind(this),
5104
+ registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
4604
5105
  });
4605
5106
  }
4606
5107
  /////////////////////////
@@ -4613,18 +5114,19 @@ var ModelRouter = class {
4613
5114
  options: this.options,
4614
5115
  getRequestSchema: this.getRequestSchema.bind(this),
4615
5116
  getPublicService: this.getPublicService.bind(this),
4616
- assertAllowed: this.assertAllowed.bind(this)
5117
+ assertAllowed: this.assertAllowed.bind(this),
5118
+ registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
4617
5119
  });
4618
5120
  }
4619
5121
  logEndpoints() {
4620
5122
  runWithRuntime(this.runtime, () => {
4621
- (0, import_utils19.forEach)(this.router.endpoints, ({ method, path }) => {
4622
- logger.info(`${(0, import_utils19.padEnd)(method, 6)} ${(0, import_utils19.normalizeUrlPath)(this.options.parentPath + path)}`);
5123
+ (0, import_utils24.forEach)(this.router.endpoints, ({ method, path }) => {
5124
+ logger.info(`${(0, import_utils24.padEnd)(method, 6)} ${(0, import_utils24.normalizeUrlPath)(this.options.parentPath + path)}`);
4623
5125
  });
4624
5126
  });
4625
5127
  }
4626
5128
  set(keyOrOptions, value) {
4627
- if (arguments.length === 2 && (0, import_utils19.isString)(keyOrOptions)) {
5129
+ if (arguments.length === 2 && (0, import_utils24.isString)(keyOrOptions)) {
4628
5130
  assertMutableRouterOption("model", keyOrOptions);
4629
5131
  this.runtime.setModelOption(
4630
5132
  this.modelName,
@@ -4632,7 +5134,7 @@ var ModelRouter = class {
4632
5134
  value
4633
5135
  );
4634
5136
  }
4635
- if (arguments.length === 1 && (0, import_utils19.isPlainObject)(keyOrOptions)) {
5137
+ if (arguments.length === 1 && (0, import_utils24.isPlainObject)(keyOrOptions)) {
4636
5138
  assertMutableRouterOptions("model", keyOrOptions);
4637
5139
  this.runtime.setModelOptions(this.modelName, keyOrOptions);
4638
5140
  }
@@ -4655,7 +5157,7 @@ var ModelRouter = class {
4655
5157
 
4656
5158
  // src/routers/root-router.ts
4657
5159
  var import_express_json_router6 = __toESM(require("@web-ts-toolkit/express-json-router"));
4658
- var import_utils20 = require("@web-ts-toolkit/utils");
5160
+ var import_utils25 = require("@web-ts-toolkit/utils");
4659
5161
 
4660
5162
  // src/core-data.ts
4661
5163
  var DataCore = class {
@@ -4828,7 +5330,7 @@ var createErrorResult = (code, detail) => ({
4828
5330
  code,
4829
5331
  errors: [{ detail }]
4830
5332
  });
4831
- var normalizeSubPopulate = (populate) => Array.isArray(populate) ? populate.map((item) => (0, import_utils20.isString)(item) ? { path: item } : item) : (0, import_utils20.isString)(populate) ? { path: populate } : populate ?? [];
5333
+ var normalizeSubPopulate = (populate) => Array.isArray(populate) ? populate.map((item) => (0, import_utils25.isString)(item) ? { path: item } : item) : (0, import_utils25.isString)(populate) ? { path: populate } : populate ?? [];
4832
5334
  var RootRouter = class {
4833
5335
  constructor(options = { basePath: "", operationAccess: true }, runtime = defaultRuntime) {
4834
5336
  this.modelOperations = {
@@ -4901,6 +5403,9 @@ var RootRouter = class {
4901
5403
  );
4902
5404
  this.setRoutes();
4903
5405
  }
5406
+ registerOpenApiRoute(route) {
5407
+ registerOpenApiRoute(this.runtime, (0, import_utils25.normalizeUrlPath)(this.basename), "root", route);
5408
+ }
4904
5409
  wrapResult(index, item, result) {
4905
5410
  return {
4906
5411
  index,
@@ -4960,7 +5465,7 @@ var RootRouter = class {
4960
5465
  groupItemsByOrder(items) {
4961
5466
  return items.reduce((acc, item, index) => {
4962
5467
  let order = 0;
4963
- if ((0, import_utils20.isNumber)(item.order)) {
5468
+ if ((0, import_utils25.isNumber)(item.order)) {
4964
5469
  order = item.order < 0 ? 0 : item.order;
4965
5470
  }
4966
5471
  if (!acc[order]) {
@@ -4984,7 +5489,14 @@ var RootRouter = class {
4984
5489
  const arrResult = await Promise.all(groupedItems[x].map(({ item, index }) => this.processOp(req, item, index)));
4985
5490
  results.push(...arrResult);
4986
5491
  }
4987
- return (0, import_utils20.orderBy)(results, ["index"], ["asc"]);
5492
+ return (0, import_utils25.orderBy)(results, ["index"], ["asc"]);
5493
+ });
5494
+ this.registerOpenApiRoute({
5495
+ method: "post",
5496
+ path: "",
5497
+ operationId: "root.query",
5498
+ summary: "Execute batched model and data operations",
5499
+ body: rootQuerySchema
4988
5500
  });
4989
5501
  }
4990
5502
  get routes() {
@@ -4994,11 +5506,11 @@ var RootRouter = class {
4994
5506
 
4995
5507
  // src/routers/data-router.ts
4996
5508
  var import_express_json_router7 = __toESM(require("@web-ts-toolkit/express-json-router"));
4997
- var import_utils21 = require("@web-ts-toolkit/utils");
5509
+ var import_utils26 = require("@web-ts-toolkit/utils");
4998
5510
  var clientErrors4 = import_express_json_router7.default.clientErrors;
4999
5511
  function setOption2(parentKey, optionKey, option) {
5000
- const key = (0, import_utils21.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
5001
- const value = (0, import_utils21.isUndefined)(option) ? optionKey : option;
5512
+ const key = (0, import_utils26.isUndefined)(option) ? parentKey : `${parentKey}.${optionKey}`;
5513
+ const value = (0, import_utils26.isUndefined)(option) ? optionKey : option;
5002
5514
  assertMutableRouterOption("data", key);
5003
5515
  this.runtime.setDataOption(this.dataName, key, value);
5004
5516
  return this;
@@ -5034,7 +5546,7 @@ var DataRouter = class {
5034
5546
  this.runtime = runtime;
5035
5547
  this.runtime.setDataOptions(dataName, initialOptions);
5036
5548
  this.options = this.runtime.getDataOptions(dataName);
5037
- this.fullBasePath = (0, import_utils21.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
5549
+ this.fullBasePath = (0, import_utils26.normalizeUrlPath)(this.options.parentPath + this.options.basePath);
5038
5550
  this.dataName = dataName;
5039
5551
  this.router = new import_express_json_router7.default(this.options.basePath, createSetDataCore(this.runtime), accessRouterResponseHandler);
5040
5552
  this.setCollectionRoutes();
@@ -5053,6 +5565,9 @@ var DataRouter = class {
5053
5565
  const allowed = await req.dacl.isAllowed(this.dataName, access);
5054
5566
  if (!allowed) throw new clientErrors4.UnauthorizedError();
5055
5567
  }
5568
+ registerOpenApiRoute(route) {
5569
+ registerOpenApiRoute(this.runtime, this.fullBasePath, this.dataName, route);
5570
+ }
5056
5571
  ///////////////////////
5057
5572
  // Collection Routes //
5058
5573
  ///////////////////////
@@ -5064,8 +5579,8 @@ var DataRouter = class {
5064
5579
  req.query
5065
5580
  );
5066
5581
  const svc = this.getService(req);
5067
- const includeCount = parseBooleanString(include_count);
5068
- const includeExtraHeaders = parseBooleanString(include_extra_headers);
5582
+ const includeCount = (0, import_utils21.parseBooleanString)(include_count);
5583
+ const includeExtraHeaders = (0, import_utils21.parseBooleanString)(include_extra_headers);
5069
5584
  const result = await svc.find(
5070
5585
  {},
5071
5586
  { skip, limit, page, pageSize: page_size },
@@ -5077,6 +5592,13 @@ var DataRouter = class {
5077
5592
  const decoratedResult = await decorateDataListResult(svc, result);
5078
5593
  return formatListResponse(req, decoratedResult, includeCount, includeExtraHeaders);
5079
5594
  });
5595
+ this.registerOpenApiRoute({
5596
+ method: "get",
5597
+ path: "",
5598
+ operationId: `${this.dataName}.list`,
5599
+ summary: `List ${this.dataName} records`,
5600
+ query: requestSchemas.listQuery
5601
+ });
5080
5602
  this.router.post(`/${this.options.queryRouteSegment}`, async (req) => {
5081
5603
  await this.assertAllowed(req, "list");
5082
5604
  let {
@@ -5100,6 +5622,15 @@ var DataRouter = class {
5100
5622
  const decoratedResult = await decorateDataListResult(svc, result);
5101
5623
  return formatListResponse(req, decoratedResult, includeCount, includeExtraHeaders);
5102
5624
  });
5625
+ this.registerOpenApiRoute({
5626
+ method: "post",
5627
+ path: `/${this.options.queryRouteSegment}`,
5628
+ operationId: `${this.dataName}.listAdvanced`,
5629
+ summary: `Advanced list ${this.dataName} records`,
5630
+ body: defineOpenApiSchemaResolver(
5631
+ () => this.getRequestSchema("requestSchemas.advancedList") ?? dataListBodySchema
5632
+ )
5633
+ });
5103
5634
  }
5104
5635
  /////////////////////
5105
5636
  // Document Routes //
@@ -5114,6 +5645,12 @@ var DataRouter = class {
5114
5645
  const decoratedResult = await decorateDataSingleResult(svc, result);
5115
5646
  return decoratedResult.data;
5116
5647
  });
5648
+ this.registerOpenApiRoute({
5649
+ method: "get",
5650
+ path: `/:${this.options.idParam}`,
5651
+ operationId: `${this.dataName}.read`,
5652
+ summary: `Read a ${this.dataName} record`
5653
+ });
5117
5654
  this.router.post(`/${this.options.queryRouteSegment}/__filter`, async (req) => {
5118
5655
  await this.assertAllowed(req, "read");
5119
5656
  let { filter: filter2, select } = await parseBodyWithSchema(
@@ -5127,6 +5664,15 @@ var DataRouter = class {
5127
5664
  const decoratedResult = await decorateDataSingleResult(svc, result);
5128
5665
  return decoratedResult.data;
5129
5666
  });
5667
+ this.registerOpenApiRoute({
5668
+ method: "post",
5669
+ path: `/${this.options.queryRouteSegment}/__filter`,
5670
+ operationId: `${this.dataName}.readByFilter`,
5671
+ summary: `Read a ${this.dataName} record by filter`,
5672
+ body: defineOpenApiSchemaResolver(
5673
+ () => this.getRequestSchema("requestSchemas.advancedReadFilter") ?? dataReadFilterBodySchema
5674
+ )
5675
+ });
5130
5676
  this.router.post(`/${this.options.queryRouteSegment}/:${this.options.idParam}`, async (req) => {
5131
5677
  await this.assertAllowed(req, "read");
5132
5678
  const id = parsePathParam(req.params[this.options.idParam], this.options.idParam);
@@ -5141,13 +5687,22 @@ var DataRouter = class {
5141
5687
  const decoratedResult = await decorateDataSingleResult(svc, result);
5142
5688
  return decoratedResult.data;
5143
5689
  });
5690
+ this.registerOpenApiRoute({
5691
+ method: "post",
5692
+ path: `/${this.options.queryRouteSegment}/:${this.options.idParam}`,
5693
+ operationId: `${this.dataName}.readAdvanced`,
5694
+ summary: `Advanced read a ${this.dataName} record`,
5695
+ body: defineOpenApiSchemaResolver(
5696
+ () => this.getRequestSchema("requestSchemas.advancedRead") ?? dataReadByIdBodySchema
5697
+ )
5698
+ });
5144
5699
  }
5145
5700
  set(keyOrOptions, value) {
5146
- if (arguments.length === 2 && (0, import_utils21.isString)(keyOrOptions)) {
5701
+ if (arguments.length === 2 && (0, import_utils26.isString)(keyOrOptions)) {
5147
5702
  assertMutableRouterOption("data", keyOrOptions);
5148
5703
  this.runtime.setDataOption(this.dataName, keyOrOptions, value);
5149
5704
  }
5150
- if (arguments.length === 1 && (0, import_utils21.isPlainObject)(keyOrOptions)) {
5705
+ if (arguments.length === 1 && (0, import_utils26.isPlainObject)(keyOrOptions)) {
5151
5706
  assertMutableRouterOptions("data", keyOrOptions);
5152
5707
  this.runtime.setDataOptions(this.dataName, keyOrOptions);
5153
5708
  }
@@ -5170,6 +5725,62 @@ var DataRouter = class {
5170
5725
 
5171
5726
  // src/routers/index.ts
5172
5727
  var import_express_json_router8 = __toESM(require("@web-ts-toolkit/express-json-router"));
5728
+
5729
+ // src/openapi/router.ts
5730
+ var import_express = __toESM(require("express"));
5731
+ var import_node_path = require("path");
5732
+ var escapeHtml = (value) => value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
5733
+ var renderDocsHtml = (specPath, title, cssUrl, bundleUrl) => `<!doctype html>
5734
+ <html lang="en">
5735
+ <head>
5736
+ <meta charset="utf-8" />
5737
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
5738
+ <title>${escapeHtml(title)}</title>
5739
+ <link rel="stylesheet" href="${escapeHtml(cssUrl)}" />
5740
+ </head>
5741
+ <body>
5742
+ <div id="swagger-ui"></div>
5743
+ <script src="${escapeHtml(bundleUrl)}"></script>
5744
+ <script>
5745
+ window.ui = SwaggerUIBundle({
5746
+ url: ${JSON.stringify(specPath)},
5747
+ dom_id: '#swagger-ui',
5748
+ deepLinking: true,
5749
+ presets: [SwaggerUIBundle.presets.apis],
5750
+ layout: 'BaseLayout',
5751
+ });
5752
+ </script>
5753
+ </body>
5754
+ </html>`;
5755
+ var getRelativeSpecPath = (docsPath, jsonPath) => {
5756
+ const docsDir = import_node_path.posix.dirname(docsPath.startsWith("/") ? docsPath : `/${docsPath}`);
5757
+ const normalizedJsonPath = jsonPath.startsWith("/") ? jsonPath : `/${jsonPath}`;
5758
+ return import_node_path.posix.relative(docsDir, normalizedJsonPath) || import_node_path.posix.basename(normalizedJsonPath);
5759
+ };
5760
+ function createOpenApiRouter(runtime, options = {}) {
5761
+ const router = import_express.default.Router();
5762
+ const jsonPath = options.jsonPath ?? "/openapi.json";
5763
+ const docsPath = options.docsPath ?? "/docs";
5764
+ const swaggerUiCssUrl = options.swaggerUiCssUrl ?? "https://unpkg.com/swagger-ui-dist@5/swagger-ui.css";
5765
+ const swaggerUiBundleUrl = options.swaggerUiBundleUrl ?? "https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js";
5766
+ const info = {
5767
+ title: options.title ?? "Access Router API",
5768
+ version: options.version ?? "0.0.0",
5769
+ description: options.description,
5770
+ servers: options.servers
5771
+ };
5772
+ router.get(jsonPath, (_req, res) => {
5773
+ res.json(runtime.getOpenApiSpec(info));
5774
+ });
5775
+ if (docsPath !== false) {
5776
+ router.get(docsPath, (_req, res) => {
5777
+ res.type("html").send(renderDocsHtml(getRelativeSpecPath(docsPath, jsonPath), info.title, swaggerUiCssUrl, swaggerUiBundleUrl));
5778
+ });
5779
+ }
5780
+ return router;
5781
+ }
5782
+
5783
+ // src/routers/index.ts
5173
5784
  var hasRoutes = (input) => {
5174
5785
  return typeof input === "object" && input !== null && "routes" in input;
5175
5786
  };
@@ -5177,7 +5788,7 @@ var resolveRoutes = (input) => {
5177
5788
  return hasRoutes(input) ? input.routes : input;
5178
5789
  };
5179
5790
  function combineRoutes(...inputs) {
5180
- const router = import_express.default.Router();
5791
+ const router = import_express2.default.Router();
5181
5792
  inputs.forEach((input) => {
5182
5793
  router.use(resolveRoutes(input));
5183
5794
  });
@@ -5189,7 +5800,7 @@ var accessRouterResponseHandler = import_express_json_router8.default.createHand
5189
5800
  });
5190
5801
  accessRouterResponseHandler.errorMessageProvider = function(error) {
5191
5802
  const errorLike = error;
5192
- console.error(error);
5803
+ logger.error(error);
5193
5804
  return errorLike.message || errorLike._message || String(error);
5194
5805
  };
5195
5806
 
@@ -5211,17 +5822,20 @@ function createRuntimeApi(runtime) {
5211
5822
  wtt2.runtime = runtime;
5212
5823
  wtt2.createRouter = function(modelName, options) {
5213
5824
  const resolvedModelName = typeof modelName === "string" ? modelName : modelName && "modelName" in modelName ? modelName.modelName : modelName;
5214
- return (0, import_utils22.isUndefined)(options) ? new RootRouter(modelName, runtime) : new ModelRouter(resolvedModelName, options, runtime);
5825
+ return (0, import_utils27.isUndefined)(options) ? new RootRouter(modelName, runtime) : new ModelRouter(resolvedModelName, options, runtime);
5215
5826
  };
5216
5827
  wtt2.createDataRouter = function(dataName, options) {
5217
5828
  return new DataRouter(dataName, options, runtime);
5218
5829
  };
5830
+ wtt2.createOpenApiRouter = function(options) {
5831
+ return createOpenApiRouter(runtime, options);
5832
+ };
5219
5833
  wtt2.combineRoutes = combineRoutes;
5220
5834
  wtt2.set = function(keyOrOptions, value) {
5221
- if (arguments.length === 2 && (0, import_utils22.isString)(keyOrOptions)) {
5835
+ if (arguments.length === 2 && (0, import_utils27.isString)(keyOrOptions)) {
5222
5836
  return runtime.setGlobalOption(keyOrOptions, value);
5223
5837
  }
5224
- if (arguments.length === 1 && (0, import_utils22.isPlainObject)(keyOrOptions)) {
5838
+ if (arguments.length === 1 && (0, import_utils27.isPlainObject)(keyOrOptions)) {
5225
5839
  return runtime.setGlobalOptions(keyOrOptions);
5226
5840
  }
5227
5841
  };
@@ -5259,6 +5873,7 @@ var index_default = acl;
5259
5873
  acl,
5260
5874
  combineRoutes,
5261
5875
  createAccessRuntime,
5876
+ createOpenApiRouter,
5262
5877
  defineRequestSchema,
5263
5878
  fromAjv,
5264
5879
  fromArkType,