@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/README.md +59 -7
- package/advanced.d.mts +38 -39
- package/advanced.d.ts +38 -39
- package/advanced.js +5 -5
- package/advanced.mjs +5 -4
- package/index.d.mts +81 -3
- package/index.d.ts +81 -3
- package/index.js +1158 -543
- package/index.mjs +988 -383
- package/package.json +12 -8
- package/{parsers-CsyGHYQR.d.mts → parsers-Ce1grlLx.d.mts} +16 -14
- package/{parsers-CsyGHYQR.d.ts → parsers-Ce1grlLx.d.ts} +16 -14
package/index.mjs
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
|
-
import { isPlainObject as
|
|
2
|
+
import { isPlainObject as isPlainObject14, isString as isString12, isUndefined as isUndefined4 } from "@web-ts-toolkit/utils";
|
|
3
3
|
|
|
4
4
|
// src/middleware.ts
|
|
5
5
|
import JsonRouter2 from "@web-ts-toolkit/express-json-router";
|
|
6
|
-
import { isArray as
|
|
6
|
+
import { isArray as isArray10, isFunction as isFunction6, isPlainObject as isPlainObject11, isString as isString7 } from "@web-ts-toolkit/utils";
|
|
7
7
|
|
|
8
8
|
// src/core.ts
|
|
9
9
|
import {
|
|
10
10
|
castArray as castArray5,
|
|
11
11
|
compact as compact3,
|
|
12
|
-
forEach as
|
|
13
|
-
isArray as
|
|
12
|
+
forEach as forEach7,
|
|
13
|
+
isArray as isArray9,
|
|
14
14
|
isBoolean as isBoolean5,
|
|
15
15
|
isFunction as isFunction5,
|
|
16
16
|
isString as isString6,
|
|
@@ -25,11 +25,11 @@ import {
|
|
|
25
25
|
addLeadingSlash,
|
|
26
26
|
forEach as forEach2,
|
|
27
27
|
get as get3,
|
|
28
|
-
isArray as
|
|
28
|
+
isArray as isArray4,
|
|
29
29
|
isBoolean,
|
|
30
30
|
isFunction,
|
|
31
31
|
isNil as isNil2,
|
|
32
|
-
isPlainObject as
|
|
32
|
+
isPlainObject as isPlainObject7,
|
|
33
33
|
isString as isString4,
|
|
34
34
|
keys
|
|
35
35
|
} from "@web-ts-toolkit/utils";
|
|
@@ -51,20 +51,11 @@ var findElementById = (collection, id) => {
|
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
// src/helpers/document.ts
|
|
54
|
-
import {
|
|
55
|
-
|
|
56
|
-
// src/lib.ts
|
|
57
|
-
import { Document, Schema } from "mongoose";
|
|
58
|
-
import { isPlainObject } from "@web-ts-toolkit/utils";
|
|
59
|
-
var isSchema = (val) => val instanceof Schema;
|
|
60
|
-
var isObjectIdType = (val) => val === "ObjectId" || val === Schema.Types.ObjectId;
|
|
61
|
-
var isReference = (val) => isPlainObject(val) && !!val.ref && isObjectIdType(val.type);
|
|
62
|
-
var isDocument = function isDocument2(doc) {
|
|
63
|
-
return doc instanceof Document;
|
|
64
|
-
};
|
|
54
|
+
import { Document } from "mongoose";
|
|
55
|
+
import { get, isPlainObject as isPlainObject2, pick, set } from "@web-ts-toolkit/utils";
|
|
65
56
|
|
|
66
57
|
// src/helpers/query.ts
|
|
67
|
-
import { flattenDeep, isNaN, isNil, isPlainObject
|
|
58
|
+
import { flattenDeep, isNaN, isNil, isPlainObject, isString, reduce } from "@web-ts-toolkit/utils";
|
|
68
59
|
function genPagination({
|
|
69
60
|
skip,
|
|
70
61
|
limit,
|
|
@@ -92,7 +83,7 @@ function parseSortString(sortString) {
|
|
|
92
83
|
}
|
|
93
84
|
function normalizeSelect(select) {
|
|
94
85
|
if (Array.isArray(select)) return flattenDeep(select.map(normalizeSelect));
|
|
95
|
-
if (
|
|
86
|
+
if (isPlainObject(select)) {
|
|
96
87
|
return reduce(
|
|
97
88
|
select,
|
|
98
89
|
(ret, val, key) => {
|
|
@@ -108,17 +99,21 @@ function normalizeSelect(select) {
|
|
|
108
99
|
}
|
|
109
100
|
|
|
110
101
|
// src/helpers/document.ts
|
|
111
|
-
|
|
102
|
+
import { isArray, isPromise, isString as isString2 } from "@web-ts-toolkit/utils";
|
|
103
|
+
function isDocument(doc) {
|
|
104
|
+
return doc instanceof Document;
|
|
105
|
+
}
|
|
106
|
+
function getDocValue(doc, path, defaultValue) {
|
|
112
107
|
if (isDocument(doc)) {
|
|
113
|
-
return get(doc._doc, path,
|
|
114
|
-
} else if (
|
|
115
|
-
return get(doc, path,
|
|
108
|
+
return get(doc._doc, path, defaultValue);
|
|
109
|
+
} else if (isPlainObject2(doc)) {
|
|
110
|
+
return get(doc, path, defaultValue);
|
|
116
111
|
}
|
|
117
112
|
}
|
|
118
113
|
function setDocValue(doc, path, value) {
|
|
119
114
|
if (isDocument(doc)) {
|
|
120
115
|
set(doc._doc, path, value);
|
|
121
|
-
} else if (
|
|
116
|
+
} else if (isPlainObject2(doc)) {
|
|
122
117
|
set(doc, path, value);
|
|
123
118
|
}
|
|
124
119
|
}
|
|
@@ -207,16 +202,19 @@ function handleResultError(result) {
|
|
|
207
202
|
}
|
|
208
203
|
|
|
209
204
|
// src/helpers/index.ts
|
|
210
|
-
import {
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
205
|
+
import { forEach, isArray as isArray2, isEmpty, isObject, isPlainObject as isPlainObject4, isString as isString3, mapValuesAsync } from "@web-ts-toolkit/utils";
|
|
206
|
+
|
|
207
|
+
// src/lib.ts
|
|
208
|
+
import { Document as Document2, Schema } from "mongoose";
|
|
209
|
+
import { isPlainObject as isPlainObject3 } from "@web-ts-toolkit/utils";
|
|
210
|
+
var isSchema = (val) => val instanceof Schema;
|
|
211
|
+
var isObjectIdType = (val) => val === "ObjectId" || val === Schema.Types.ObjectId;
|
|
212
|
+
var isReference = (val) => isPlainObject3(val) && !!val.ref && isObjectIdType(val.type);
|
|
213
|
+
var isDocument2 = function isDocument3(doc) {
|
|
214
|
+
return doc instanceof Document2;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
// src/helpers/index.ts
|
|
220
218
|
function recurseObject(obj) {
|
|
221
219
|
if (isSchema(obj)) {
|
|
222
220
|
return buildRefs(obj.tree);
|
|
@@ -266,7 +264,7 @@ function buildSubPaths(schema) {
|
|
|
266
264
|
}
|
|
267
265
|
async function iterateQuery(query, handler) {
|
|
268
266
|
if (!isPlainObject4(query)) return query;
|
|
269
|
-
if (!handler) return
|
|
267
|
+
if (!handler) return query;
|
|
270
268
|
const queryObject = query;
|
|
271
269
|
return mapValuesAsync(queryObject, async (val, key) => {
|
|
272
270
|
if (isPlainObject4(val)) {
|
|
@@ -295,6 +293,252 @@ var createValidator = (fn) => {
|
|
|
295
293
|
return { stringHandler, arrayHandler };
|
|
296
294
|
};
|
|
297
295
|
|
|
296
|
+
// src/openapi/build-spec.ts
|
|
297
|
+
import { isArray as isArray3, isPlainObject as isPlainObject6 } from "@web-ts-toolkit/utils";
|
|
298
|
+
|
|
299
|
+
// src/openapi/responses.ts
|
|
300
|
+
var json = (schema) => ({
|
|
301
|
+
content: {
|
|
302
|
+
"application/json": {
|
|
303
|
+
schema
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
});
|
|
307
|
+
var problemJson = {
|
|
308
|
+
content: {
|
|
309
|
+
"application/problem+json": {
|
|
310
|
+
schema: {
|
|
311
|
+
type: "object",
|
|
312
|
+
properties: {
|
|
313
|
+
type: { type: "string" },
|
|
314
|
+
title: { type: "string" },
|
|
315
|
+
status: { type: "number" },
|
|
316
|
+
detail: { type: "string" },
|
|
317
|
+
errors: { type: "array", items: {} }
|
|
318
|
+
},
|
|
319
|
+
additionalProperties: true
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
var genericDataSchema = { type: "object", additionalProperties: true };
|
|
325
|
+
var genericListSchema = { type: "array", items: genericDataSchema };
|
|
326
|
+
var openApiResponses = {
|
|
327
|
+
single(description = "Success") {
|
|
328
|
+
return {
|
|
329
|
+
200: { description, ...json(genericDataSchema) },
|
|
330
|
+
400: { description: "Bad Request", ...problemJson },
|
|
331
|
+
401: { description: "Unauthorized", ...problemJson },
|
|
332
|
+
404: { description: "Not Found", ...problemJson }
|
|
333
|
+
};
|
|
334
|
+
},
|
|
335
|
+
list(description = "Success") {
|
|
336
|
+
return {
|
|
337
|
+
200: { description, ...json(genericListSchema) },
|
|
338
|
+
400: { description: "Bad Request", ...problemJson },
|
|
339
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
340
|
+
};
|
|
341
|
+
},
|
|
342
|
+
create(description = "Created") {
|
|
343
|
+
return {
|
|
344
|
+
201: { description, ...json(genericDataSchema) },
|
|
345
|
+
400: { description: "Bad Request", ...problemJson },
|
|
346
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
347
|
+
};
|
|
348
|
+
},
|
|
349
|
+
delete(description = "Deleted") {
|
|
350
|
+
return {
|
|
351
|
+
200: { description, ...json(genericDataSchema) },
|
|
352
|
+
400: { description: "Bad Request", ...problemJson },
|
|
353
|
+
401: { description: "Unauthorized", ...problemJson },
|
|
354
|
+
404: { description: "Not Found", ...problemJson }
|
|
355
|
+
};
|
|
356
|
+
},
|
|
357
|
+
batch(description = "Success") {
|
|
358
|
+
return {
|
|
359
|
+
200: { description, ...json(genericListSchema) },
|
|
360
|
+
400: { description: "Bad Request", ...problemJson },
|
|
361
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
|
|
366
|
+
// src/openapi/schemas.ts
|
|
367
|
+
import { z } from "zod";
|
|
368
|
+
import { isPlainObject as isPlainObject5 } from "@web-ts-toolkit/utils";
|
|
369
|
+
var fallbackObjectSchema = { type: "object", additionalProperties: true };
|
|
370
|
+
function patchOpenApiObjectSchema(source, properties) {
|
|
371
|
+
return {
|
|
372
|
+
kind: "objectProperties",
|
|
373
|
+
source,
|
|
374
|
+
properties
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
function defineOpenApiSchemaResolver(resolve) {
|
|
378
|
+
return {
|
|
379
|
+
kind: "schemaResolver",
|
|
380
|
+
resolve
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
function getNestedOpenApiSchemaDataSource(source) {
|
|
384
|
+
return isPlainObject5(source) && "data" in source ? source.data : void 0;
|
|
385
|
+
}
|
|
386
|
+
function unwrapNestedOpenApiSchemaSource(source, fallback) {
|
|
387
|
+
if (isPlainObject5(source) && ("default" in source || "data" in source)) {
|
|
388
|
+
return source.default ?? fallback;
|
|
389
|
+
}
|
|
390
|
+
return source ?? fallback;
|
|
391
|
+
}
|
|
392
|
+
function isOpenApiSchemaPatch(source) {
|
|
393
|
+
return isPlainObject5(source) && source.kind === "objectProperties";
|
|
394
|
+
}
|
|
395
|
+
function isOpenApiSchemaResolver(source) {
|
|
396
|
+
return isPlainObject5(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
|
|
397
|
+
}
|
|
398
|
+
function isJsonSchemaLike(source) {
|
|
399
|
+
return isPlainObject5(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
|
|
400
|
+
}
|
|
401
|
+
function hasOpenApiSchema(source) {
|
|
402
|
+
return isPlainObject5(source) && isJsonSchemaLike(source.openapi);
|
|
403
|
+
}
|
|
404
|
+
function toOpenApiSchema(source) {
|
|
405
|
+
if (!source) return void 0;
|
|
406
|
+
const resolvedSource = isOpenApiSchemaResolver(source) ? source.resolve() : source;
|
|
407
|
+
if (!resolvedSource) return void 0;
|
|
408
|
+
if (isOpenApiSchemaPatch(resolvedSource)) {
|
|
409
|
+
const schema = toOpenApiSchema(resolvedSource.source) ?? { ...fallbackObjectSchema };
|
|
410
|
+
const properties = isPlainObject5(schema.properties) ? { ...schema.properties } : {};
|
|
411
|
+
for (const [key, value] of Object.entries(resolvedSource.properties)) {
|
|
412
|
+
properties[key] = toOpenApiSchema(value) ?? fallbackObjectSchema;
|
|
413
|
+
}
|
|
414
|
+
return {
|
|
415
|
+
...schema,
|
|
416
|
+
type: schema.type ?? "object",
|
|
417
|
+
properties
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (hasOpenApiSchema(resolvedSource)) {
|
|
421
|
+
return resolvedSource.openapi;
|
|
422
|
+
}
|
|
423
|
+
if (isJsonSchemaLike(resolvedSource)) {
|
|
424
|
+
return resolvedSource;
|
|
425
|
+
}
|
|
426
|
+
try {
|
|
427
|
+
return z.toJSONSchema(resolvedSource);
|
|
428
|
+
} catch {
|
|
429
|
+
return fallbackObjectSchema;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/openapi/build-spec.ts
|
|
434
|
+
var openApiMediaType = "application/json";
|
|
435
|
+
var normalizePath = (path) => {
|
|
436
|
+
if (!path) return "/";
|
|
437
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
438
|
+
};
|
|
439
|
+
var toOpenApiPath = (path) => normalizePath(path).replace(/:([A-Za-z0-9_]+)/g, "{$1}");
|
|
440
|
+
var schemaToQueryParameters = (schema) => {
|
|
441
|
+
const jsonSchema = toOpenApiSchema(schema);
|
|
442
|
+
if (!jsonSchema || jsonSchema.type !== "object") return [];
|
|
443
|
+
const properties = isPlainObject6(jsonSchema.properties) ? jsonSchema.properties : {};
|
|
444
|
+
const required = new Set(
|
|
445
|
+
isArray3(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
|
|
446
|
+
);
|
|
447
|
+
return Object.entries(properties).map(([name, value]) => ({
|
|
448
|
+
name,
|
|
449
|
+
in: "query",
|
|
450
|
+
required: required.has(name),
|
|
451
|
+
schema: value
|
|
452
|
+
}));
|
|
453
|
+
};
|
|
454
|
+
var schemaToPathParameters = (path, pathParams) => {
|
|
455
|
+
const names = [...toOpenApiPath(path).matchAll(/\{([^}]+)\}/g)].map((item) => item[1]);
|
|
456
|
+
return names.map((name) => ({
|
|
457
|
+
name,
|
|
458
|
+
in: "path",
|
|
459
|
+
required: true,
|
|
460
|
+
schema: (pathParams && name in pathParams ? toOpenApiSchema(pathParams[name]) : void 0) ?? { type: "string" }
|
|
461
|
+
}));
|
|
462
|
+
};
|
|
463
|
+
var getDefaultResponses = (route) => {
|
|
464
|
+
if (route.operationId === "root.query") return openApiResponses.batch();
|
|
465
|
+
if (route.method === "delete") return openApiResponses.delete();
|
|
466
|
+
if (route.operationId?.toLowerCase().includes("create")) return openApiResponses.create();
|
|
467
|
+
if (route.operationId?.toLowerCase().includes("list")) return openApiResponses.list();
|
|
468
|
+
if (route.operationId?.toLowerCase().includes("distinct")) return openApiResponses.list();
|
|
469
|
+
return openApiResponses.single();
|
|
470
|
+
};
|
|
471
|
+
var buildOperation = (route) => {
|
|
472
|
+
const queryParameters = schemaToQueryParameters(route.query);
|
|
473
|
+
const pathParameters = schemaToPathParameters(route.path, route.pathParams);
|
|
474
|
+
const bodySchema = toOpenApiSchema(route.body);
|
|
475
|
+
const responses = route.responses ?? getDefaultResponses(route);
|
|
476
|
+
const operation = {
|
|
477
|
+
operationId: route.operationId,
|
|
478
|
+
summary: route.summary,
|
|
479
|
+
description: route.description,
|
|
480
|
+
tags: route.tags,
|
|
481
|
+
deprecated: route.deprecated,
|
|
482
|
+
responses
|
|
483
|
+
};
|
|
484
|
+
const parameters = [...pathParameters, ...queryParameters];
|
|
485
|
+
if (parameters.length) {
|
|
486
|
+
operation.parameters = parameters;
|
|
487
|
+
}
|
|
488
|
+
if (bodySchema) {
|
|
489
|
+
operation.requestBody = {
|
|
490
|
+
required: true,
|
|
491
|
+
content: {
|
|
492
|
+
[openApiMediaType]: {
|
|
493
|
+
schema: bodySchema
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
if (route.acl) {
|
|
499
|
+
operation["x-access-router-acl"] = route.acl;
|
|
500
|
+
}
|
|
501
|
+
return operation;
|
|
502
|
+
};
|
|
503
|
+
function buildOpenApiSpec(routes, options) {
|
|
504
|
+
const paths = {};
|
|
505
|
+
const { servers, ...info } = options;
|
|
506
|
+
for (const route of routes) {
|
|
507
|
+
const path = toOpenApiPath(route.path);
|
|
508
|
+
if (!paths[path]) {
|
|
509
|
+
paths[path] = {};
|
|
510
|
+
}
|
|
511
|
+
paths[path][route.method] = buildOperation(route);
|
|
512
|
+
}
|
|
513
|
+
return {
|
|
514
|
+
openapi: "3.1.0",
|
|
515
|
+
info,
|
|
516
|
+
servers,
|
|
517
|
+
paths
|
|
518
|
+
};
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// src/openapi/registry.ts
|
|
522
|
+
var OpenApiRegistry = class {
|
|
523
|
+
constructor() {
|
|
524
|
+
this.routes = [];
|
|
525
|
+
}
|
|
526
|
+
register(route) {
|
|
527
|
+
const existingIndex = this.routes.findIndex((item) => item.method === route.method && item.path === route.path);
|
|
528
|
+
if (existingIndex === -1) {
|
|
529
|
+
this.routes.push(route);
|
|
530
|
+
return;
|
|
531
|
+
}
|
|
532
|
+
this.routes[existingIndex] = route;
|
|
533
|
+
}
|
|
534
|
+
getRoutes() {
|
|
535
|
+
return [...this.routes];
|
|
536
|
+
}
|
|
537
|
+
getSpec(info) {
|
|
538
|
+
return buildOpenApiSpec(this.routes, info);
|
|
539
|
+
}
|
|
540
|
+
};
|
|
541
|
+
|
|
298
542
|
// src/logger-default.ts
|
|
299
543
|
import util from "util";
|
|
300
544
|
import { createLogger, format, transports } from "winston";
|
|
@@ -401,9 +645,9 @@ var hasModelPermission = (value, modelPermissionPrefix) => {
|
|
|
401
645
|
if (isString4(value)) {
|
|
402
646
|
return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
|
|
403
647
|
}
|
|
404
|
-
if (
|
|
648
|
+
if (isArray4(value)) {
|
|
405
649
|
return value.some((item) => {
|
|
406
|
-
if (isString4(item) ||
|
|
650
|
+
if (isString4(item) || isArray4(item)) {
|
|
407
651
|
return hasModelPermission(item, modelPermissionPrefix);
|
|
408
652
|
}
|
|
409
653
|
return true;
|
|
@@ -417,13 +661,13 @@ var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
|
|
|
417
661
|
const modelPermissionKeys = {};
|
|
418
662
|
forEach2(schemaKeys, (schemaKey) => {
|
|
419
663
|
const schemaRule = permissionSchema[schemaKey];
|
|
420
|
-
const ruleEntries =
|
|
664
|
+
const ruleEntries = isPlainObject7(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
|
|
421
665
|
for (let x = 0; x < ruleEntries.length; x++) {
|
|
422
666
|
const [accessKey, value] = ruleEntries[x];
|
|
423
|
-
if (!
|
|
667
|
+
if (!isArray4(globalPermissionKeys[accessKey])) {
|
|
424
668
|
globalPermissionKeys[accessKey] = [];
|
|
425
669
|
}
|
|
426
|
-
if (!
|
|
670
|
+
if (!isArray4(modelPermissionKeys[accessKey])) {
|
|
427
671
|
modelPermissionKeys[accessKey] = [];
|
|
428
672
|
}
|
|
429
673
|
if (isBoolean(value)) {
|
|
@@ -467,6 +711,16 @@ var AccessRuntime = class {
|
|
|
467
711
|
this.modelRefs = {};
|
|
468
712
|
this.modelSubs = {};
|
|
469
713
|
this.modelAtts = {};
|
|
714
|
+
this.openApiRegistry = new OpenApiRegistry();
|
|
715
|
+
}
|
|
716
|
+
registerOpenApiRoute(route) {
|
|
717
|
+
this.openApiRegistry.register(route);
|
|
718
|
+
}
|
|
719
|
+
getOpenApiRoutes() {
|
|
720
|
+
return this.openApiRegistry.getRoutes();
|
|
721
|
+
}
|
|
722
|
+
getOpenApiSpec(info) {
|
|
723
|
+
return this.openApiRegistry.getSpec(info);
|
|
470
724
|
}
|
|
471
725
|
setGlobalOptions(options) {
|
|
472
726
|
this.globalOptions.assign(options);
|
|
@@ -738,19 +992,19 @@ import {
|
|
|
738
992
|
forEach as forEach3,
|
|
739
993
|
get as get4,
|
|
740
994
|
intersectionBy,
|
|
741
|
-
isArray as
|
|
742
|
-
isPlainObject as
|
|
995
|
+
isArray as isArray5,
|
|
996
|
+
isPlainObject as isPlainObject8,
|
|
743
997
|
uniq
|
|
744
998
|
} from "@web-ts-toolkit/utils";
|
|
745
999
|
function validateClientFilter(filter2) {
|
|
746
1000
|
const errors = [];
|
|
747
1001
|
const blockedOperators = /* @__PURE__ */ new Set(["$where", "$expr", "$function", "$accumulator"]);
|
|
748
1002
|
const visit = (value, path) => {
|
|
749
|
-
if (
|
|
1003
|
+
if (isArray5(value)) {
|
|
750
1004
|
value.forEach((item, index) => visit(item, `${path}[${index}]`));
|
|
751
1005
|
return;
|
|
752
1006
|
}
|
|
753
|
-
if (!
|
|
1007
|
+
if (!isPlainObject8(value)) return;
|
|
754
1008
|
Object.entries(value).forEach(([key, child]) => {
|
|
755
1009
|
const nextPath = path ? `${path}.${key}` : key;
|
|
756
1010
|
if (blockedOperators.has(key)) {
|
|
@@ -866,7 +1120,7 @@ var Base = class {
|
|
|
866
1120
|
if (!include) return docs;
|
|
867
1121
|
const includes = compact(castArray(include));
|
|
868
1122
|
if (includes.length === 0) return docs;
|
|
869
|
-
const isSingle = !
|
|
1123
|
+
const isSingle = !isArray5(docs);
|
|
870
1124
|
if (isSingle) docs = [docs];
|
|
871
1125
|
for (let x = 0; x < includes.length; x++) {
|
|
872
1126
|
const include2 = includes[x];
|
|
@@ -951,14 +1205,16 @@ var Base = class {
|
|
|
951
1205
|
if (!result.success) return null;
|
|
952
1206
|
let ret = result.data;
|
|
953
1207
|
if (sqOptions.path) {
|
|
954
|
-
ret =
|
|
1208
|
+
ret = isArray5(ret) ? flatten(ret.map((v) => get4(v, sqOptions.path))) : get4(ret, sqOptions.path);
|
|
955
1209
|
}
|
|
956
1210
|
if (sqOptions.compact) {
|
|
957
1211
|
ret = compact(castArray(ret));
|
|
958
1212
|
}
|
|
959
1213
|
return ret;
|
|
960
1214
|
}
|
|
961
|
-
|
|
1215
|
+
handleDate(val, key) {
|
|
1216
|
+
if (val instanceof Date) return val;
|
|
1217
|
+
if (typeof val === "string" || typeof val === "number") return new Date(val);
|
|
962
1218
|
return /* @__PURE__ */ new Date();
|
|
963
1219
|
}
|
|
964
1220
|
};
|
|
@@ -966,7 +1222,7 @@ var Base = class {
|
|
|
966
1222
|
// src/services/service.ts
|
|
967
1223
|
import {
|
|
968
1224
|
castArray as castArray2,
|
|
969
|
-
isArray as
|
|
1225
|
+
isArray as isArray6,
|
|
970
1226
|
isBoolean as isBoolean3,
|
|
971
1227
|
isFunction as isFunction3,
|
|
972
1228
|
omit,
|
|
@@ -977,6 +1233,21 @@ import diff from "deep-diff";
|
|
|
977
1233
|
|
|
978
1234
|
// src/model.ts
|
|
979
1235
|
import mongoose3 from "mongoose";
|
|
1236
|
+
|
|
1237
|
+
// src/logger.ts
|
|
1238
|
+
var passthrough = (level) => (...args) => {
|
|
1239
|
+
const globalLogger = getGlobalOption("logger");
|
|
1240
|
+
const target = globalLogger?.[level] ?? defaultLogger[level];
|
|
1241
|
+
return target.apply(globalLogger ?? defaultLogger, args);
|
|
1242
|
+
};
|
|
1243
|
+
var logger = {
|
|
1244
|
+
debug: passthrough("debug"),
|
|
1245
|
+
info: passthrough("info"),
|
|
1246
|
+
warn: passthrough("warn"),
|
|
1247
|
+
error: passthrough("error")
|
|
1248
|
+
};
|
|
1249
|
+
|
|
1250
|
+
// src/model.ts
|
|
980
1251
|
var Model = class {
|
|
981
1252
|
constructor(modelName) {
|
|
982
1253
|
this.modelName = modelName;
|
|
@@ -1006,12 +1277,15 @@ var Model = class {
|
|
|
1006
1277
|
if (lean) builder.lean();
|
|
1007
1278
|
return builder;
|
|
1008
1279
|
}
|
|
1009
|
-
|
|
1010
|
-
validateSort(sort, logError = console.error) {
|
|
1280
|
+
validateSort(sort, logError = logger.error) {
|
|
1011
1281
|
const validSortOrders = [1, -1, "asc", "ascending", "desc", "descending"];
|
|
1282
|
+
const fieldPathPattern = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/;
|
|
1283
|
+
const isValidFieldPath = (field) => fieldPathPattern.test(field);
|
|
1012
1284
|
if (sort === null || sort === void 0) return true;
|
|
1013
1285
|
if (typeof sort === "string") {
|
|
1014
|
-
|
|
1286
|
+
const fields = sort.trim().split(/\s+/).filter(Boolean);
|
|
1287
|
+
const isValid = fields.every((field) => isValidFieldPath(field.startsWith("-") ? field.slice(1) : field));
|
|
1288
|
+
if (!isValid) {
|
|
1015
1289
|
logError("Invalid sort string:", sort);
|
|
1016
1290
|
return false;
|
|
1017
1291
|
}
|
|
@@ -1024,8 +1298,8 @@ var Model = class {
|
|
|
1024
1298
|
return false;
|
|
1025
1299
|
}
|
|
1026
1300
|
const [key, order] = pair;
|
|
1027
|
-
if (typeof key !== "string") {
|
|
1028
|
-
logError("Invalid sort array key: must be string", key);
|
|
1301
|
+
if (typeof key !== "string" || !isValidFieldPath(key)) {
|
|
1302
|
+
logError("Invalid sort array key: must be a field path string", key);
|
|
1029
1303
|
return false;
|
|
1030
1304
|
}
|
|
1031
1305
|
if (!validSortOrders.includes(order)) {
|
|
@@ -1037,7 +1311,11 @@ var Model = class {
|
|
|
1037
1311
|
return isValid;
|
|
1038
1312
|
}
|
|
1039
1313
|
if (typeof sort === "object" && !(sort instanceof Map)) {
|
|
1040
|
-
const isValid = Object.
|
|
1314
|
+
const isValid = Object.entries(sort).every(([key, order]) => {
|
|
1315
|
+
if (!isValidFieldPath(key)) {
|
|
1316
|
+
logError("Invalid sort object key: must be a field path string", key);
|
|
1317
|
+
return false;
|
|
1318
|
+
}
|
|
1041
1319
|
if (!validSortOrders.includes(order)) {
|
|
1042
1320
|
logError('Invalid sort object value: must be 1, -1, "asc", or "desc"', order);
|
|
1043
1321
|
return false;
|
|
@@ -1047,7 +1325,11 @@ var Model = class {
|
|
|
1047
1325
|
return isValid;
|
|
1048
1326
|
}
|
|
1049
1327
|
if (sort instanceof Map) {
|
|
1050
|
-
const isValid = Array.from(sort.
|
|
1328
|
+
const isValid = Array.from(sort.entries()).every(([key, order]) => {
|
|
1329
|
+
if (!isValidFieldPath(key)) {
|
|
1330
|
+
logError("Invalid sort Map key: must be a field path string", key);
|
|
1331
|
+
return false;
|
|
1332
|
+
}
|
|
1051
1333
|
if (!validSortOrders.includes(order)) {
|
|
1052
1334
|
logError('Invalid sort Map value: must be 1, -1, "asc", or "desc"', order);
|
|
1053
1335
|
return false;
|
|
@@ -1070,9 +1352,6 @@ var Model = class {
|
|
|
1070
1352
|
if (lean) builder.lean();
|
|
1071
1353
|
return builder;
|
|
1072
1354
|
}
|
|
1073
|
-
findOneAndDelete(filter2) {
|
|
1074
|
-
return this.model.findOneAndDelete(filter2);
|
|
1075
|
-
}
|
|
1076
1355
|
exists(filter2) {
|
|
1077
1356
|
if (!filter2) return null;
|
|
1078
1357
|
return this.findOne(filter2).select("_id").lean();
|
|
@@ -1081,10 +1360,6 @@ var Model = class {
|
|
|
1081
1360
|
countDocuments(filter2 = {}) {
|
|
1082
1361
|
return this.model.countDocuments(filter2);
|
|
1083
1362
|
}
|
|
1084
|
-
// see https://mongoosejs.com/docs/api.html#model_Model.estimatedDocumentCount
|
|
1085
|
-
estimatedDocumentCount() {
|
|
1086
|
-
return this.model.estimatedDocumentCount();
|
|
1087
|
-
}
|
|
1088
1363
|
// see https://mongoosejs.com/docs/api.html#model_Model.distinct
|
|
1089
1364
|
distinct(field, conditions = {}) {
|
|
1090
1365
|
return this.model.distinct(field, conditions);
|
|
@@ -1092,19 +1367,6 @@ var Model = class {
|
|
|
1092
1367
|
};
|
|
1093
1368
|
var model_default = Model;
|
|
1094
1369
|
|
|
1095
|
-
// src/logger.ts
|
|
1096
|
-
var passthrough = (level) => (...args) => {
|
|
1097
|
-
const globalLogger = getGlobalOption("logger");
|
|
1098
|
-
const target = globalLogger?.[level] ?? defaultLogger[level];
|
|
1099
|
-
return target.apply(globalLogger ?? defaultLogger, args);
|
|
1100
|
-
};
|
|
1101
|
-
var logger = {
|
|
1102
|
-
debug: passthrough("debug"),
|
|
1103
|
-
info: passthrough("info"),
|
|
1104
|
-
warn: passthrough("warn"),
|
|
1105
|
-
error: passthrough("error")
|
|
1106
|
-
};
|
|
1107
|
-
|
|
1108
1370
|
// src/services/model-subdocument-service.ts
|
|
1109
1371
|
import { forEach as forEach4, get as get5, pick as pick3 } from "@web-ts-toolkit/utils";
|
|
1110
1372
|
async function listSub(service, id, sub, options) {
|
|
@@ -1328,7 +1590,7 @@ function resolveExistsOptions(service, options = {}) {
|
|
|
1328
1590
|
|
|
1329
1591
|
// src/services/service.ts
|
|
1330
1592
|
var assertModelDocument = (value, modelName, hookName) => {
|
|
1331
|
-
if (
|
|
1593
|
+
if (isDocument2(value)) {
|
|
1332
1594
|
return value;
|
|
1333
1595
|
}
|
|
1334
1596
|
throw new Error(`${hookName} hook for model=${modelName} must return a Mongoose document instance`);
|
|
@@ -1422,7 +1684,7 @@ var Service = class extends Base {
|
|
|
1422
1684
|
genPagination({ skip, limit, page, pageSize }, this.options.listHardLimit)
|
|
1423
1685
|
]);
|
|
1424
1686
|
const finalSelect = normalizeSelect(_select);
|
|
1425
|
-
const filteredPopulate =
|
|
1687
|
+
const filteredPopulate = isArray6(finalSelect) && isArray6(_populate) ? _populate.filter((p) => finalSelect.includes(p.path.split(".")[0])) : _populate;
|
|
1426
1688
|
const { includes, includeLocalFields, includePaths } = this.processInclude(include);
|
|
1427
1689
|
const query = {
|
|
1428
1690
|
filter: _filter,
|
|
@@ -1505,7 +1767,7 @@ var Service = class extends Base {
|
|
|
1505
1767
|
validationError = { success: false, code: "bad_request" /* BadRequest */ };
|
|
1506
1768
|
return;
|
|
1507
1769
|
}
|
|
1508
|
-
} else if (
|
|
1770
|
+
} else if (isArray6(validated)) {
|
|
1509
1771
|
if (validated.length > 0) {
|
|
1510
1772
|
validationError = { success: false, code: "bad_request" /* BadRequest */, errors: validated };
|
|
1511
1773
|
return;
|
|
@@ -1595,7 +1857,7 @@ var Service = class extends Base {
|
|
|
1595
1857
|
const validated = await this.validate(allowedData, "update", context);
|
|
1596
1858
|
if (isBoolean3(validated)) {
|
|
1597
1859
|
if (!validated) return { success: false, code: "bad_request" /* BadRequest */ };
|
|
1598
|
-
} else if (
|
|
1860
|
+
} else if (isArray6(validated)) {
|
|
1599
1861
|
if (validated.length > 0) return { success: false, code: "bad_request" /* BadRequest */, errors: validated };
|
|
1600
1862
|
}
|
|
1601
1863
|
const prepared = await this.prepare(allowedData, "update", context);
|
|
@@ -2199,29 +2461,29 @@ var DataService = class {
|
|
|
2199
2461
|
};
|
|
2200
2462
|
|
|
2201
2463
|
// src/processors.ts
|
|
2202
|
-
import { castArray as castArray3, cloneDeep, forEach as
|
|
2464
|
+
import { castArray as castArray3, cloneDeep, forEach as forEach6, get as get7, isArray as isArray7, map as map2, set as set5 } from "@web-ts-toolkit/utils";
|
|
2203
2465
|
var copyAndDepopulate = (docObject, operations, options = { mutable: true, idField: "_id" }) => {
|
|
2204
|
-
const obj =
|
|
2205
|
-
const idField =
|
|
2206
|
-
|
|
2466
|
+
const obj = get7(options, "mutable", true) ? docObject : cloneDeep(docObject);
|
|
2467
|
+
const idField = get7(options, "idField", "_id");
|
|
2468
|
+
forEach6(castArray3(operations), (op) => {
|
|
2207
2469
|
if (!op.src || !op.dest) return;
|
|
2208
2470
|
let targets = [obj];
|
|
2209
2471
|
const segs = op.src.split(".");
|
|
2210
|
-
|
|
2472
|
+
forEach6(segs, (seg, ind) => {
|
|
2211
2473
|
if (segs.length === ind + 1) {
|
|
2212
|
-
|
|
2474
|
+
forEach6(targets, (target) => {
|
|
2213
2475
|
const targetObject = target;
|
|
2214
|
-
set5(targetObject, op.dest,
|
|
2476
|
+
set5(targetObject, op.dest, get7(targetObject, seg));
|
|
2215
2477
|
set5(
|
|
2216
2478
|
targetObject,
|
|
2217
2479
|
seg,
|
|
2218
|
-
|
|
2480
|
+
isArray7(targetObject[seg]) ? map2(targetObject[seg], idField) : get7(targetObject, `${seg}.${idField}`)
|
|
2219
2481
|
);
|
|
2220
2482
|
});
|
|
2221
2483
|
} else {
|
|
2222
2484
|
targets = targets.reduce((ret, target) => {
|
|
2223
2485
|
const targetObject = target;
|
|
2224
|
-
if (
|
|
2486
|
+
if (isArray7(targetObject[seg])) ret.push(...targetObject[seg]);
|
|
2225
2487
|
else ret.push(targetObject[seg]);
|
|
2226
2488
|
return ret;
|
|
2227
2489
|
}, []);
|
|
@@ -2272,12 +2534,12 @@ var Cache = class {
|
|
|
2272
2534
|
import {
|
|
2273
2535
|
castArray as castArray4,
|
|
2274
2536
|
arrayToRecord,
|
|
2275
|
-
isArray as
|
|
2537
|
+
isArray as isArray8,
|
|
2276
2538
|
isBoolean as isBoolean4,
|
|
2277
2539
|
isEmpty as isEmpty2,
|
|
2278
2540
|
isEqual,
|
|
2279
2541
|
isFunction as isFunction4,
|
|
2280
|
-
isPlainObject as
|
|
2542
|
+
isPlainObject as isPlainObject10,
|
|
2281
2543
|
isString as isString5
|
|
2282
2544
|
} from "@web-ts-toolkit/utils";
|
|
2283
2545
|
|
|
@@ -2317,10 +2579,10 @@ var permission_default = Permission;
|
|
|
2317
2579
|
|
|
2318
2580
|
// src/core-shared.ts
|
|
2319
2581
|
function isAndFilter(filter2) {
|
|
2320
|
-
return !!filter2 &&
|
|
2582
|
+
return !!filter2 && isPlainObject10(filter2) && Object.keys(filter2).length === 1 && isArray8(filter2.$and);
|
|
2321
2583
|
}
|
|
2322
2584
|
function isMergeableClause(filter2) {
|
|
2323
|
-
return !!filter2 &&
|
|
2585
|
+
return !!filter2 && isPlainObject10(filter2) && Object.keys(filter2).every((key) => !key.startsWith("$"));
|
|
2324
2586
|
}
|
|
2325
2587
|
function optimizeAndFilter(clausesInput) {
|
|
2326
2588
|
const clauses = [];
|
|
@@ -2365,7 +2627,7 @@ function optimizeAndFilter(clausesInput) {
|
|
|
2365
2627
|
}
|
|
2366
2628
|
function normalizeFilter(filter2) {
|
|
2367
2629
|
if (filter2 === false) return false;
|
|
2368
|
-
if (!filter2 || !
|
|
2630
|
+
if (!filter2 || !isPlainObject10(filter2) || isEmpty2(filter2)) return null;
|
|
2369
2631
|
if (!isAndFilter(filter2)) {
|
|
2370
2632
|
return filter2;
|
|
2371
2633
|
}
|
|
@@ -2417,8 +2679,8 @@ async function setRequestPermissions(req) {
|
|
|
2417
2679
|
const globalPermissions = getGlobalOption("globalPermissions");
|
|
2418
2680
|
if (!isFunction4(globalPermissions)) return;
|
|
2419
2681
|
const permissions = await globalPermissions.call(req, req);
|
|
2420
|
-
if (
|
|
2421
|
-
else if (
|
|
2682
|
+
if (isPlainObject10(permissions)) req[requestPermissionField] = permissions;
|
|
2683
|
+
else if (isArray8(permissions)) req[requestPermissionField] = arrayToRecord(permissions);
|
|
2422
2684
|
else if (isString5(permissions)) req[requestPermissionField] = { [permissions]: true };
|
|
2423
2685
|
}
|
|
2424
2686
|
async function evaluateRouteGuard(req, permissions, routeGuard) {
|
|
@@ -2430,7 +2692,7 @@ async function evaluateRouteGuard(req, permissions, routeGuard) {
|
|
|
2430
2692
|
if (isString5(routeGuard)) {
|
|
2431
2693
|
return stringHandler(routeGuard);
|
|
2432
2694
|
}
|
|
2433
|
-
if (
|
|
2695
|
+
if (isArray8(routeGuard)) {
|
|
2434
2696
|
return arrayHandler(routeGuard);
|
|
2435
2697
|
}
|
|
2436
2698
|
if (isFunction4(routeGuard)) {
|
|
@@ -2468,7 +2730,7 @@ async function collectSchemaFields({
|
|
|
2468
2730
|
if (value) fields.push(key);
|
|
2469
2731
|
} else if (isString5(value)) {
|
|
2470
2732
|
if (stringHandler(value)) fields.push(key);
|
|
2471
|
-
} else if (
|
|
2733
|
+
} else if (isArray8(value)) {
|
|
2472
2734
|
if (arrayHandler(value)) fields.push(key);
|
|
2473
2735
|
} else if (isFunction4(value)) {
|
|
2474
2736
|
if (await value.call(req, ...functionArgs)) fields.push(key);
|
|
@@ -2757,7 +3019,7 @@ var Core = class {
|
|
|
2757
3019
|
if (isFunction5(validate)) {
|
|
2758
3020
|
const permissions = this.getGlobalPermissions();
|
|
2759
3021
|
return validate.call(this.req, allowedData, permissions, context);
|
|
2760
|
-
} else if (isBoolean5(validate) ||
|
|
3022
|
+
} else if (isBoolean5(validate) || isArray9(validate)) {
|
|
2761
3023
|
return validate;
|
|
2762
3024
|
} else {
|
|
2763
3025
|
return true;
|
|
@@ -2888,7 +3150,7 @@ var Core = class {
|
|
|
2888
3150
|
runTasks(modelName, docObject, task) {
|
|
2889
3151
|
const tasks = compact3(castArray5(task));
|
|
2890
3152
|
if (tasks.length === 0) return docObject;
|
|
2891
|
-
|
|
3153
|
+
forEach7(tasks, (task2) => {
|
|
2892
3154
|
const { type, args, options } = task2;
|
|
2893
3155
|
switch (type) {
|
|
2894
3156
|
case "COPY_AND_DEPOPULATE":
|
|
@@ -2971,19 +3233,19 @@ function guard(condition) {
|
|
|
2971
3233
|
const permissions = req[PERMISSIONS];
|
|
2972
3234
|
let cond = condition;
|
|
2973
3235
|
let phas = (key) => permissions.has(key);
|
|
2974
|
-
if (
|
|
3236
|
+
if (isPlainObject11(condition)) {
|
|
2975
3237
|
const { modelName, id, condition: _cond } = condition;
|
|
2976
3238
|
const svc = req.macl.getPublicService(modelName);
|
|
2977
3239
|
const select = getModelOption(modelName, `alwaysSelectFields.read`, void 0);
|
|
2978
3240
|
let _id = isString7(id) ? id : null;
|
|
2979
|
-
if (
|
|
3241
|
+
if (isPlainObject11(id)) {
|
|
2980
3242
|
const { type = "param", key } = id;
|
|
2981
3243
|
if (type === "param") {
|
|
2982
3244
|
const paramValue = req.params[key];
|
|
2983
|
-
_id =
|
|
3245
|
+
_id = isArray10(paramValue) ? paramValue[0] ?? null : paramValue ?? null;
|
|
2984
3246
|
} else if (type === "query") {
|
|
2985
3247
|
const _qval = req.query[key];
|
|
2986
|
-
if (
|
|
3248
|
+
if (isArray10(_qval)) _id = _qval.length > 0 ? _qval[0] : null;
|
|
2987
3249
|
else _id = _qval;
|
|
2988
3250
|
} else {
|
|
2989
3251
|
_id = null;
|
|
@@ -3003,7 +3265,7 @@ function guard(condition) {
|
|
|
3003
3265
|
const { stringHandler, arrayHandler } = createValidator(phas);
|
|
3004
3266
|
if (isString7(cond)) {
|
|
3005
3267
|
if (stringHandler(cond)) return next();
|
|
3006
|
-
} else if (
|
|
3268
|
+
} else if (isArray10(cond)) {
|
|
3007
3269
|
if (arrayHandler(cond)) return next();
|
|
3008
3270
|
} else if (isFunction6(cond)) {
|
|
3009
3271
|
const result = await cond.call(req, permissions);
|
|
@@ -3014,11 +3276,11 @@ function guard(condition) {
|
|
|
3014
3276
|
}
|
|
3015
3277
|
|
|
3016
3278
|
// src/routers/index.ts
|
|
3017
|
-
import
|
|
3279
|
+
import express2 from "express";
|
|
3018
3280
|
|
|
3019
3281
|
// src/routers/model-router.ts
|
|
3020
3282
|
import JsonRouter5 from "@web-ts-toolkit/express-json-router";
|
|
3021
|
-
import { forEach as
|
|
3283
|
+
import { forEach as forEach8, isPlainObject as isPlainObject12, isString as isString9, isUndefined as isUndefined2, normalizeUrlPath as normalizeUrlPath2, padEnd } from "@web-ts-toolkit/utils";
|
|
3022
3284
|
|
|
3023
3285
|
// src/routers/router-mutation.ts
|
|
3024
3286
|
var MODEL_BUILD_TIME_OPTION_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -3110,88 +3372,88 @@ function formatModelUpsertResponse(result) {
|
|
|
3110
3372
|
import JsonRouter4 from "@web-ts-toolkit/express-json-router";
|
|
3111
3373
|
|
|
3112
3374
|
// src/validation/common.ts
|
|
3113
|
-
import { z } from "zod";
|
|
3114
|
-
var stringOrStringArray =
|
|
3115
|
-
var queryBooleanString =
|
|
3116
|
-
var positiveIntegerString =
|
|
3117
|
-
var nonNegativeIntegerSchema =
|
|
3118
|
-
var unknownRecord =
|
|
3119
|
-
var projectionObjectSchema =
|
|
3120
|
-
var projectionSchema =
|
|
3121
|
-
var sortOrderSchema =
|
|
3122
|
-
|
|
3123
|
-
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3375
|
+
import { z as z2 } from "zod";
|
|
3376
|
+
var stringOrStringArray = z2.union([z2.string(), z2.array(z2.string())]);
|
|
3377
|
+
var queryBooleanString = z2.enum(["true", "false"]);
|
|
3378
|
+
var positiveIntegerString = z2.string().regex(/^\d+$/, "Expected a non-negative integer");
|
|
3379
|
+
var nonNegativeIntegerSchema = z2.number().int().min(0);
|
|
3380
|
+
var unknownRecord = z2.record(z2.string(), z2.unknown());
|
|
3381
|
+
var projectionObjectSchema = z2.record(z2.string(), z2.union([z2.literal(1), z2.literal(-1)]));
|
|
3382
|
+
var projectionSchema = z2.union([z2.string(), z2.array(z2.string()), projectionObjectSchema]);
|
|
3383
|
+
var sortOrderSchema = z2.union([
|
|
3384
|
+
z2.literal(-1),
|
|
3385
|
+
z2.literal(1),
|
|
3386
|
+
z2.literal("asc"),
|
|
3387
|
+
z2.literal("ascending"),
|
|
3388
|
+
z2.literal("desc"),
|
|
3389
|
+
z2.literal("descending")
|
|
3128
3390
|
]);
|
|
3129
|
-
var sortSchema =
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3391
|
+
var sortSchema = z2.union([
|
|
3392
|
+
z2.string(),
|
|
3393
|
+
z2.record(z2.string(), sortOrderSchema),
|
|
3394
|
+
z2.array(z2.tuple([z2.string(), sortOrderSchema])),
|
|
3395
|
+
z2.null()
|
|
3134
3396
|
]);
|
|
3135
|
-
var populateSchema =
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
path:
|
|
3397
|
+
var populateSchema = z2.union([
|
|
3398
|
+
z2.string(),
|
|
3399
|
+
z2.array(
|
|
3400
|
+
z2.union([
|
|
3401
|
+
z2.string(),
|
|
3402
|
+
z2.object({
|
|
3403
|
+
path: z2.string().min(1),
|
|
3142
3404
|
select: projectionSchema.optional(),
|
|
3143
|
-
match:
|
|
3144
|
-
access:
|
|
3405
|
+
match: z2.unknown().optional(),
|
|
3406
|
+
access: z2.enum(["list", "read"]).optional()
|
|
3145
3407
|
}).passthrough()
|
|
3146
3408
|
])
|
|
3147
3409
|
),
|
|
3148
|
-
|
|
3149
|
-
path:
|
|
3410
|
+
z2.object({
|
|
3411
|
+
path: z2.string().min(1),
|
|
3150
3412
|
select: projectionSchema.optional(),
|
|
3151
|
-
match:
|
|
3152
|
-
access:
|
|
3413
|
+
match: z2.unknown().optional(),
|
|
3414
|
+
access: z2.enum(["list", "read"]).optional()
|
|
3153
3415
|
}).passthrough()
|
|
3154
3416
|
]);
|
|
3155
|
-
var subPopulateSchema =
|
|
3156
|
-
|
|
3157
|
-
|
|
3158
|
-
|
|
3159
|
-
|
|
3160
|
-
|
|
3161
|
-
path:
|
|
3417
|
+
var subPopulateSchema = z2.union([
|
|
3418
|
+
z2.string(),
|
|
3419
|
+
z2.array(
|
|
3420
|
+
z2.union([
|
|
3421
|
+
z2.string(),
|
|
3422
|
+
z2.object({
|
|
3423
|
+
path: z2.string().min(1),
|
|
3162
3424
|
select: projectionSchema.optional()
|
|
3163
3425
|
}).passthrough()
|
|
3164
3426
|
])
|
|
3165
3427
|
),
|
|
3166
|
-
|
|
3167
|
-
path:
|
|
3428
|
+
z2.object({
|
|
3429
|
+
path: z2.string().min(1),
|
|
3168
3430
|
select: projectionSchema.optional()
|
|
3169
3431
|
}).passthrough()
|
|
3170
3432
|
]);
|
|
3171
|
-
var includeItemSchema =
|
|
3172
|
-
model:
|
|
3173
|
-
op:
|
|
3174
|
-
path:
|
|
3175
|
-
filter:
|
|
3176
|
-
localField:
|
|
3177
|
-
foreignField:
|
|
3178
|
-
args:
|
|
3179
|
-
options:
|
|
3433
|
+
var includeItemSchema = z2.object({
|
|
3434
|
+
model: z2.string().min(1),
|
|
3435
|
+
op: z2.enum(["list", "read", "count"]),
|
|
3436
|
+
path: z2.string().min(1),
|
|
3437
|
+
filter: z2.record(z2.string(), z2.unknown()).optional(),
|
|
3438
|
+
localField: z2.string().min(1),
|
|
3439
|
+
foreignField: z2.string().min(1),
|
|
3440
|
+
args: z2.unknown().optional(),
|
|
3441
|
+
options: z2.unknown().optional()
|
|
3180
3442
|
}).passthrough();
|
|
3181
|
-
var includeSchema =
|
|
3182
|
-
var fieldsSchema =
|
|
3183
|
-
var taskSchema =
|
|
3184
|
-
type:
|
|
3185
|
-
args:
|
|
3443
|
+
var includeSchema = z2.union([includeItemSchema, z2.array(includeItemSchema)]);
|
|
3444
|
+
var fieldsSchema = z2.array(z2.string().min(1));
|
|
3445
|
+
var taskSchema = z2.object({
|
|
3446
|
+
type: z2.string().min(1),
|
|
3447
|
+
args: z2.unknown(),
|
|
3186
3448
|
options: unknownRecord.optional()
|
|
3187
3449
|
});
|
|
3188
|
-
var tasksSchema =
|
|
3189
|
-
var objectOrArraySchema =
|
|
3450
|
+
var tasksSchema = z2.union([taskSchema, z2.array(taskSchema)]);
|
|
3451
|
+
var objectOrArraySchema = z2.union([z2.record(z2.string(), z2.unknown()), z2.array(z2.unknown())]);
|
|
3190
3452
|
function rejectKeys(body, ctx, keys2) {
|
|
3191
3453
|
for (const key of keys2) {
|
|
3192
3454
|
if (key in body) {
|
|
3193
3455
|
ctx.addIssue({
|
|
3194
|
-
code:
|
|
3456
|
+
code: z2.ZodIssueCode.custom,
|
|
3195
3457
|
message: `Unsupported field: ${key}`,
|
|
3196
3458
|
path: [key]
|
|
3197
3459
|
});
|
|
@@ -3280,8 +3542,11 @@ function toRequestSchemaValidator(schema) {
|
|
|
3280
3542
|
if (isRequestSchemaValidator(schema)) return schema;
|
|
3281
3543
|
return schema.validate;
|
|
3282
3544
|
}
|
|
3283
|
-
function defineRequestSchema(validator) {
|
|
3284
|
-
return
|
|
3545
|
+
function defineRequestSchema(validator, options = {}) {
|
|
3546
|
+
return {
|
|
3547
|
+
validate: validator,
|
|
3548
|
+
openapi: options.openapi
|
|
3549
|
+
};
|
|
3285
3550
|
}
|
|
3286
3551
|
function fromZod(schema) {
|
|
3287
3552
|
return (value) => {
|
|
@@ -3561,8 +3826,8 @@ function buildPointer(path) {
|
|
|
3561
3826
|
}
|
|
3562
3827
|
|
|
3563
3828
|
// src/validation/model-router.ts
|
|
3564
|
-
import { z as
|
|
3565
|
-
var listQuerySchema =
|
|
3829
|
+
import { z as z3 } from "zod";
|
|
3830
|
+
var listQuerySchema = z3.object({
|
|
3566
3831
|
skip: positiveIntegerString.optional(),
|
|
3567
3832
|
limit: positiveIntegerString.optional(),
|
|
3568
3833
|
page: positiveIntegerString.optional(),
|
|
@@ -3572,122 +3837,122 @@ var listQuerySchema = z2.object({
|
|
|
3572
3837
|
include_count: queryBooleanString.optional(),
|
|
3573
3838
|
include_extra_headers: queryBooleanString.optional()
|
|
3574
3839
|
}).passthrough();
|
|
3575
|
-
var createQuerySchema =
|
|
3840
|
+
var createQuerySchema = z3.object({
|
|
3576
3841
|
include_permissions: queryBooleanString.optional()
|
|
3577
3842
|
}).passthrough();
|
|
3578
|
-
var readQuerySchema =
|
|
3843
|
+
var readQuerySchema = z3.object({
|
|
3579
3844
|
include_permissions: queryBooleanString.optional(),
|
|
3580
3845
|
try_list: queryBooleanString.optional()
|
|
3581
3846
|
}).passthrough();
|
|
3582
|
-
var updateQuerySchema =
|
|
3847
|
+
var updateQuerySchema = z3.object({
|
|
3583
3848
|
returning_all: queryBooleanString.optional(),
|
|
3584
3849
|
include_permissions: queryBooleanString.optional()
|
|
3585
3850
|
}).passthrough();
|
|
3586
|
-
var upsertQuerySchema =
|
|
3851
|
+
var upsertQuerySchema = z3.object({
|
|
3587
3852
|
returning_all: queryBooleanString.optional(),
|
|
3588
3853
|
include_permissions: queryBooleanString.optional()
|
|
3589
3854
|
}).passthrough();
|
|
3590
|
-
var listBodySchema =
|
|
3855
|
+
var listBodySchema = z3.object({
|
|
3591
3856
|
filter: objectOrArraySchema.optional(),
|
|
3592
3857
|
select: projectionSchema.optional(),
|
|
3593
3858
|
sort: sortSchema.optional(),
|
|
3594
3859
|
populate: populateSchema.optional(),
|
|
3595
3860
|
include: includeSchema.optional(),
|
|
3596
3861
|
tasks: tasksSchema.optional(),
|
|
3597
|
-
skip:
|
|
3598
|
-
limit:
|
|
3599
|
-
page:
|
|
3600
|
-
pageSize:
|
|
3601
|
-
options:
|
|
3602
|
-
skim:
|
|
3603
|
-
includePermissions:
|
|
3604
|
-
includeCount:
|
|
3605
|
-
includeExtraHeaders:
|
|
3606
|
-
populateAccess:
|
|
3862
|
+
skip: z3.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3863
|
+
limit: z3.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3864
|
+
page: z3.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3865
|
+
pageSize: z3.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3866
|
+
options: z3.object({
|
|
3867
|
+
skim: z3.boolean().optional(),
|
|
3868
|
+
includePermissions: z3.boolean().optional(),
|
|
3869
|
+
includeCount: z3.boolean().optional(),
|
|
3870
|
+
includeExtraHeaders: z3.boolean().optional(),
|
|
3871
|
+
populateAccess: z3.unknown().optional()
|
|
3607
3872
|
}).passthrough().optional()
|
|
3608
3873
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
|
|
3609
|
-
var countBodySchema =
|
|
3874
|
+
var countBodySchema = z3.object({
|
|
3610
3875
|
filter: objectOrArraySchema.optional(),
|
|
3611
|
-
options:
|
|
3612
|
-
access:
|
|
3876
|
+
options: z3.object({
|
|
3877
|
+
access: z3.unknown().optional()
|
|
3613
3878
|
}).passthrough().optional()
|
|
3614
3879
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access"]));
|
|
3615
|
-
var readFilterBodySchema =
|
|
3880
|
+
var readFilterBodySchema = z3.object({
|
|
3616
3881
|
filter: objectOrArraySchema.optional(),
|
|
3617
3882
|
select: projectionSchema.optional(),
|
|
3618
3883
|
sort: sortSchema.optional(),
|
|
3619
3884
|
populate: populateSchema.optional(),
|
|
3620
3885
|
include: includeSchema.optional(),
|
|
3621
3886
|
tasks: tasksSchema.optional(),
|
|
3622
|
-
options:
|
|
3623
|
-
skim:
|
|
3624
|
-
includePermissions:
|
|
3625
|
-
tryList:
|
|
3626
|
-
populateAccess:
|
|
3887
|
+
options: z3.object({
|
|
3888
|
+
skim: z3.boolean().optional(),
|
|
3889
|
+
includePermissions: z3.boolean().optional(),
|
|
3890
|
+
tryList: z3.boolean().optional(),
|
|
3891
|
+
populateAccess: z3.unknown().optional()
|
|
3627
3892
|
}).passthrough().optional()
|
|
3628
3893
|
}).passthrough();
|
|
3629
|
-
var readByIdBodySchema =
|
|
3894
|
+
var readByIdBodySchema = z3.object({
|
|
3630
3895
|
select: projectionSchema.optional(),
|
|
3631
3896
|
populate: populateSchema.optional(),
|
|
3632
3897
|
include: includeSchema.optional(),
|
|
3633
3898
|
tasks: tasksSchema.optional(),
|
|
3634
|
-
options:
|
|
3635
|
-
skim:
|
|
3636
|
-
includePermissions:
|
|
3637
|
-
tryList:
|
|
3638
|
-
populateAccess:
|
|
3899
|
+
options: z3.object({
|
|
3900
|
+
skim: z3.boolean().optional(),
|
|
3901
|
+
includePermissions: z3.boolean().optional(),
|
|
3902
|
+
tryList: z3.boolean().optional(),
|
|
3903
|
+
populateAccess: z3.unknown().optional()
|
|
3639
3904
|
}).passthrough().optional()
|
|
3640
3905
|
}).passthrough();
|
|
3641
|
-
var advancedCreateBodySchema =
|
|
3642
|
-
data:
|
|
3906
|
+
var advancedCreateBodySchema = z3.object({
|
|
3907
|
+
data: z3.unknown(),
|
|
3643
3908
|
select: projectionSchema.optional(),
|
|
3644
3909
|
populate: populateSchema.optional(),
|
|
3645
3910
|
tasks: tasksSchema.optional(),
|
|
3646
|
-
options:
|
|
3647
|
-
includePermissions:
|
|
3648
|
-
populateAccess:
|
|
3911
|
+
options: z3.object({
|
|
3912
|
+
includePermissions: z3.boolean().optional(),
|
|
3913
|
+
populateAccess: z3.unknown().optional()
|
|
3649
3914
|
}).passthrough().optional()
|
|
3650
3915
|
}).passthrough();
|
|
3651
|
-
var createBodySchema =
|
|
3652
|
-
|
|
3653
|
-
|
|
3916
|
+
var createBodySchema = z3.union([
|
|
3917
|
+
z3.record(z3.string(), z3.unknown()),
|
|
3918
|
+
z3.array(z3.record(z3.string(), z3.unknown()))
|
|
3654
3919
|
]);
|
|
3655
|
-
var updateBodySchema =
|
|
3656
|
-
var advancedUpdateBodySchema =
|
|
3657
|
-
data:
|
|
3920
|
+
var updateBodySchema = z3.record(z3.string(), z3.unknown());
|
|
3921
|
+
var advancedUpdateBodySchema = z3.object({
|
|
3922
|
+
data: z3.unknown(),
|
|
3658
3923
|
select: projectionSchema.optional(),
|
|
3659
3924
|
populate: populateSchema.optional(),
|
|
3660
3925
|
tasks: tasksSchema.optional(),
|
|
3661
|
-
options:
|
|
3662
|
-
returningAll:
|
|
3663
|
-
includePermissions:
|
|
3664
|
-
populateAccess:
|
|
3926
|
+
options: z3.object({
|
|
3927
|
+
returningAll: z3.boolean().optional(),
|
|
3928
|
+
includePermissions: z3.boolean().optional(),
|
|
3929
|
+
populateAccess: z3.unknown().optional()
|
|
3665
3930
|
}).passthrough().optional()
|
|
3666
3931
|
}).passthrough();
|
|
3667
|
-
var upsertBodySchema =
|
|
3668
|
-
var advancedUpsertBodySchema =
|
|
3669
|
-
data:
|
|
3932
|
+
var upsertBodySchema = z3.record(z3.string(), z3.unknown());
|
|
3933
|
+
var advancedUpsertBodySchema = z3.object({
|
|
3934
|
+
data: z3.record(z3.string(), z3.unknown()),
|
|
3670
3935
|
select: projectionSchema.optional(),
|
|
3671
3936
|
populate: populateSchema.optional(),
|
|
3672
3937
|
tasks: tasksSchema.optional(),
|
|
3673
|
-
options:
|
|
3674
|
-
returningAll:
|
|
3675
|
-
includePermissions:
|
|
3676
|
-
populateAccess:
|
|
3938
|
+
options: z3.object({
|
|
3939
|
+
returningAll: z3.boolean().optional(),
|
|
3940
|
+
includePermissions: z3.boolean().optional(),
|
|
3941
|
+
populateAccess: z3.unknown().optional()
|
|
3677
3942
|
}).passthrough().optional()
|
|
3678
3943
|
}).passthrough();
|
|
3679
|
-
var distinctBodySchema =
|
|
3944
|
+
var distinctBodySchema = z3.object({
|
|
3680
3945
|
filter: objectOrArraySchema.optional()
|
|
3681
3946
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
|
|
3682
|
-
var subListBodySchema =
|
|
3683
|
-
filter:
|
|
3947
|
+
var subListBodySchema = z3.object({
|
|
3948
|
+
filter: z3.record(z3.string(), z3.unknown()).optional(),
|
|
3684
3949
|
select: fieldsSchema.optional()
|
|
3685
3950
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
|
|
3686
|
-
var subMutationBodySchema =
|
|
3687
|
-
|
|
3688
|
-
|
|
3951
|
+
var subMutationBodySchema = z3.union([
|
|
3952
|
+
z3.record(z3.string(), z3.unknown()),
|
|
3953
|
+
z3.array(z3.record(z3.string(), z3.unknown()))
|
|
3689
3954
|
]);
|
|
3690
|
-
var subReadBodySchema =
|
|
3955
|
+
var subReadBodySchema = z3.object({
|
|
3691
3956
|
select: fieldsSchema.optional(),
|
|
3692
3957
|
populate: subPopulateSchema.optional()
|
|
3693
3958
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
|
|
@@ -3700,54 +3965,54 @@ var requestSchemas = {
|
|
|
3700
3965
|
};
|
|
3701
3966
|
|
|
3702
3967
|
// src/validation/data-router.ts
|
|
3703
|
-
import { z as
|
|
3704
|
-
var dataListBodySchema =
|
|
3968
|
+
import { z as z4 } from "zod";
|
|
3969
|
+
var dataListBodySchema = z4.object({
|
|
3705
3970
|
filter: objectOrArraySchema.optional(),
|
|
3706
3971
|
select: projectionSchema.optional(),
|
|
3707
|
-
sort:
|
|
3708
|
-
skip:
|
|
3709
|
-
limit:
|
|
3710
|
-
page:
|
|
3711
|
-
pageSize:
|
|
3712
|
-
options:
|
|
3713
|
-
includeCount:
|
|
3714
|
-
includeExtraHeaders:
|
|
3972
|
+
sort: z4.string().optional(),
|
|
3973
|
+
skip: z4.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3974
|
+
limit: z4.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3975
|
+
page: z4.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3976
|
+
pageSize: z4.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3977
|
+
options: z4.object({
|
|
3978
|
+
includeCount: z4.boolean().optional(),
|
|
3979
|
+
includeExtraHeaders: z4.boolean().optional()
|
|
3715
3980
|
}).passthrough().optional()
|
|
3716
3981
|
}).passthrough();
|
|
3717
|
-
var dataReadFilterBodySchema =
|
|
3982
|
+
var dataReadFilterBodySchema = z4.object({
|
|
3718
3983
|
filter: objectOrArraySchema.optional(),
|
|
3719
3984
|
select: projectionSchema.optional()
|
|
3720
3985
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
|
|
3721
|
-
var dataReadByIdBodySchema =
|
|
3986
|
+
var dataReadByIdBodySchema = z4.object({
|
|
3722
3987
|
select: projectionSchema.optional()
|
|
3723
3988
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
|
|
3724
3989
|
|
|
3725
3990
|
// src/validation/root-router.ts
|
|
3726
|
-
import { z as
|
|
3991
|
+
import { z as z5 } from "zod";
|
|
3727
3992
|
var rootEntryBaseSchema = {
|
|
3728
|
-
target:
|
|
3729
|
-
name:
|
|
3730
|
-
order:
|
|
3993
|
+
target: z5.enum(["model", "data"]),
|
|
3994
|
+
name: z5.string().min(1),
|
|
3995
|
+
order: z5.number().int().optional()
|
|
3731
3996
|
};
|
|
3732
|
-
var rootModelListArgsSchema =
|
|
3997
|
+
var rootModelListArgsSchema = z5.object({
|
|
3733
3998
|
select: projectionSchema.optional(),
|
|
3734
3999
|
populate: populateSchema.optional(),
|
|
3735
4000
|
include: includeSchema.optional(),
|
|
3736
4001
|
sort: sortSchema.optional(),
|
|
3737
|
-
skip:
|
|
3738
|
-
limit:
|
|
3739
|
-
page:
|
|
3740
|
-
pageSize:
|
|
4002
|
+
skip: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4003
|
+
limit: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4004
|
+
page: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4005
|
+
pageSize: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
3741
4006
|
tasks: tasksSchema.optional()
|
|
3742
4007
|
}).passthrough();
|
|
3743
|
-
var rootModelListOptionsSchema =
|
|
3744
|
-
skim:
|
|
3745
|
-
includePermissions:
|
|
3746
|
-
includeCount:
|
|
3747
|
-
populateAccess:
|
|
3748
|
-
lean:
|
|
4008
|
+
var rootModelListOptionsSchema = z5.object({
|
|
4009
|
+
skim: z5.boolean().optional(),
|
|
4010
|
+
includePermissions: z5.boolean().optional(),
|
|
4011
|
+
includeCount: z5.boolean().optional(),
|
|
4012
|
+
populateAccess: z5.unknown().optional(),
|
|
4013
|
+
lean: z5.boolean().optional()
|
|
3749
4014
|
}).passthrough();
|
|
3750
|
-
var rootModelReadArgsSchema =
|
|
4015
|
+
var rootModelReadArgsSchema = z5.object({
|
|
3751
4016
|
select: projectionSchema.optional(),
|
|
3752
4017
|
populate: populateSchema.optional(),
|
|
3753
4018
|
include: includeSchema.optional(),
|
|
@@ -3756,210 +4021,219 @@ var rootModelReadArgsSchema = z4.object({
|
|
|
3756
4021
|
var rootModelReadFilterArgsSchema = rootModelReadArgsSchema.extend({
|
|
3757
4022
|
sort: sortSchema.optional()
|
|
3758
4023
|
});
|
|
3759
|
-
var rootModelReadOptionsSchema =
|
|
3760
|
-
skim:
|
|
3761
|
-
includePermissions:
|
|
3762
|
-
tryList:
|
|
3763
|
-
populateAccess:
|
|
3764
|
-
lean:
|
|
4024
|
+
var rootModelReadOptionsSchema = z5.object({
|
|
4025
|
+
skim: z5.boolean().optional(),
|
|
4026
|
+
includePermissions: z5.boolean().optional(),
|
|
4027
|
+
tryList: z5.boolean().optional(),
|
|
4028
|
+
populateAccess: z5.unknown().optional(),
|
|
4029
|
+
lean: z5.boolean().optional()
|
|
3765
4030
|
}).passthrough();
|
|
3766
|
-
var rootModelCreateArgsSchema =
|
|
4031
|
+
var rootModelCreateArgsSchema = z5.object({
|
|
3767
4032
|
select: projectionSchema.optional(),
|
|
3768
4033
|
populate: populateSchema.optional(),
|
|
3769
4034
|
tasks: tasksSchema.optional()
|
|
3770
4035
|
}).passthrough();
|
|
3771
|
-
var rootModelCreateOptionsSchema =
|
|
3772
|
-
skim:
|
|
3773
|
-
includePermissions:
|
|
3774
|
-
populateAccess:
|
|
4036
|
+
var rootModelCreateOptionsSchema = z5.object({
|
|
4037
|
+
skim: z5.boolean().optional(),
|
|
4038
|
+
includePermissions: z5.boolean().optional(),
|
|
4039
|
+
populateAccess: z5.unknown().optional()
|
|
3775
4040
|
}).passthrough();
|
|
3776
|
-
var rootModelUpdateArgsSchema =
|
|
4041
|
+
var rootModelUpdateArgsSchema = z5.object({
|
|
3777
4042
|
select: projectionSchema.optional(),
|
|
3778
4043
|
populate: populateSchema.optional(),
|
|
3779
4044
|
tasks: tasksSchema.optional()
|
|
3780
4045
|
}).passthrough();
|
|
3781
|
-
var rootModelUpdateOptionsSchema =
|
|
3782
|
-
skim:
|
|
3783
|
-
returningAll:
|
|
3784
|
-
includePermissions:
|
|
3785
|
-
populateAccess:
|
|
4046
|
+
var rootModelUpdateOptionsSchema = z5.object({
|
|
4047
|
+
skim: z5.boolean().optional(),
|
|
4048
|
+
returningAll: z5.boolean().optional(),
|
|
4049
|
+
includePermissions: z5.boolean().optional(),
|
|
4050
|
+
populateAccess: z5.unknown().optional()
|
|
3786
4051
|
}).passthrough();
|
|
3787
4052
|
var rootModelUpsertArgsSchema = rootModelUpdateArgsSchema;
|
|
3788
4053
|
var rootModelUpsertOptionsSchema = rootModelUpdateOptionsSchema;
|
|
3789
|
-
var rootModelSubListArgsSchema =
|
|
4054
|
+
var rootModelSubListArgsSchema = z5.object({
|
|
3790
4055
|
select: fieldsSchema.optional()
|
|
3791
4056
|
}).passthrough();
|
|
3792
|
-
var rootModelSubReadArgsSchema =
|
|
4057
|
+
var rootModelSubReadArgsSchema = z5.object({
|
|
3793
4058
|
select: fieldsSchema.optional(),
|
|
3794
4059
|
populate: subPopulateSchema.optional()
|
|
3795
4060
|
}).passthrough();
|
|
3796
|
-
var rootModelCountOptionsSchema =
|
|
3797
|
-
access:
|
|
4061
|
+
var rootModelCountOptionsSchema = z5.object({
|
|
4062
|
+
access: z5.unknown().optional()
|
|
3798
4063
|
}).passthrough();
|
|
3799
|
-
var rootDataListArgsSchema =
|
|
4064
|
+
var rootDataListArgsSchema = z5.object({
|
|
3800
4065
|
select: projectionSchema.optional(),
|
|
3801
|
-
sort:
|
|
3802
|
-
skip:
|
|
3803
|
-
limit:
|
|
3804
|
-
page:
|
|
3805
|
-
pageSize:
|
|
4066
|
+
sort: z5.string().optional(),
|
|
4067
|
+
skip: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4068
|
+
limit: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4069
|
+
page: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional(),
|
|
4070
|
+
pageSize: z5.union([nonNegativeIntegerSchema, positiveIntegerString]).optional()
|
|
3806
4071
|
}).passthrough();
|
|
3807
|
-
var rootDataListOptionsSchema =
|
|
3808
|
-
includeCount:
|
|
4072
|
+
var rootDataListOptionsSchema = z5.object({
|
|
4073
|
+
includeCount: z5.boolean().optional()
|
|
3809
4074
|
}).passthrough();
|
|
3810
|
-
var rootDataReadArgsSchema =
|
|
4075
|
+
var rootDataReadArgsSchema = z5.object({
|
|
3811
4076
|
select: projectionSchema.optional()
|
|
3812
4077
|
}).passthrough();
|
|
3813
|
-
var rootModelQueryEntrySchema =
|
|
3814
|
-
|
|
3815
|
-
|
|
4078
|
+
var rootModelQueryEntrySchema = z5.union([
|
|
4079
|
+
z5.object({ ...rootEntryBaseSchema, target: z5.literal("model"), op: z5.literal("new") }).passthrough(),
|
|
4080
|
+
z5.object({
|
|
3816
4081
|
...rootEntryBaseSchema,
|
|
3817
|
-
target:
|
|
3818
|
-
op:
|
|
4082
|
+
target: z5.literal("model"),
|
|
4083
|
+
op: z5.literal("list"),
|
|
3819
4084
|
filter: objectOrArraySchema.optional(),
|
|
3820
4085
|
args: rootModelListArgsSchema.optional(),
|
|
3821
4086
|
options: rootModelListOptionsSchema.optional()
|
|
3822
4087
|
}).passthrough(),
|
|
3823
|
-
|
|
4088
|
+
z5.object({
|
|
3824
4089
|
...rootEntryBaseSchema,
|
|
3825
|
-
target:
|
|
3826
|
-
op:
|
|
3827
|
-
id:
|
|
4090
|
+
target: z5.literal("model"),
|
|
4091
|
+
op: z5.literal("read"),
|
|
4092
|
+
id: z5.string().min(1),
|
|
3828
4093
|
args: rootModelReadArgsSchema.optional(),
|
|
3829
4094
|
options: rootModelReadOptionsSchema.optional()
|
|
3830
4095
|
}).passthrough(),
|
|
3831
|
-
|
|
4096
|
+
z5.object({
|
|
3832
4097
|
...rootEntryBaseSchema,
|
|
3833
|
-
target:
|
|
3834
|
-
op:
|
|
4098
|
+
target: z5.literal("model"),
|
|
4099
|
+
op: z5.literal("read"),
|
|
3835
4100
|
filter: objectOrArraySchema,
|
|
3836
4101
|
args: rootModelReadFilterArgsSchema.optional(),
|
|
3837
4102
|
options: rootModelReadOptionsSchema.optional()
|
|
3838
4103
|
}).passthrough(),
|
|
3839
|
-
|
|
4104
|
+
z5.object({
|
|
3840
4105
|
...rootEntryBaseSchema,
|
|
3841
|
-
target:
|
|
3842
|
-
op:
|
|
3843
|
-
data:
|
|
4106
|
+
target: z5.literal("model"),
|
|
4107
|
+
op: z5.literal("create"),
|
|
4108
|
+
data: z5.unknown(),
|
|
3844
4109
|
args: rootModelCreateArgsSchema.optional(),
|
|
3845
4110
|
options: rootModelCreateOptionsSchema.optional()
|
|
3846
4111
|
}).passthrough(),
|
|
3847
|
-
|
|
4112
|
+
z5.object({
|
|
3848
4113
|
...rootEntryBaseSchema,
|
|
3849
|
-
target:
|
|
3850
|
-
op:
|
|
3851
|
-
id:
|
|
3852
|
-
data:
|
|
4114
|
+
target: z5.literal("model"),
|
|
4115
|
+
op: z5.literal("update"),
|
|
4116
|
+
id: z5.string().min(1),
|
|
4117
|
+
data: z5.unknown(),
|
|
3853
4118
|
args: rootModelUpdateArgsSchema.optional(),
|
|
3854
4119
|
options: rootModelUpdateOptionsSchema.optional()
|
|
3855
4120
|
}).passthrough(),
|
|
3856
|
-
|
|
4121
|
+
z5.object({
|
|
3857
4122
|
...rootEntryBaseSchema,
|
|
3858
|
-
target:
|
|
3859
|
-
op:
|
|
3860
|
-
data:
|
|
4123
|
+
target: z5.literal("model"),
|
|
4124
|
+
op: z5.literal("upsert"),
|
|
4125
|
+
data: z5.record(z5.string(), z5.unknown()),
|
|
3861
4126
|
args: rootModelUpsertArgsSchema.optional(),
|
|
3862
4127
|
options: rootModelUpsertOptionsSchema.optional()
|
|
3863
4128
|
}).passthrough(),
|
|
3864
|
-
|
|
3865
|
-
|
|
4129
|
+
z5.object({ ...rootEntryBaseSchema, target: z5.literal("model"), op: z5.literal("delete"), id: z5.string().min(1) }).passthrough(),
|
|
4130
|
+
z5.object({
|
|
3866
4131
|
...rootEntryBaseSchema,
|
|
3867
|
-
target:
|
|
3868
|
-
op:
|
|
3869
|
-
id:
|
|
3870
|
-
sub:
|
|
3871
|
-
filter:
|
|
4132
|
+
target: z5.literal("model"),
|
|
4133
|
+
op: z5.literal("subList"),
|
|
4134
|
+
id: z5.string().min(1),
|
|
4135
|
+
sub: z5.string().min(1),
|
|
4136
|
+
filter: z5.record(z5.string(), z5.unknown()).optional(),
|
|
3872
4137
|
args: rootModelSubListArgsSchema.optional()
|
|
3873
4138
|
}).passthrough(),
|
|
3874
|
-
|
|
4139
|
+
z5.object({
|
|
3875
4140
|
...rootEntryBaseSchema,
|
|
3876
|
-
target:
|
|
3877
|
-
op:
|
|
3878
|
-
id:
|
|
3879
|
-
sub:
|
|
3880
|
-
subId:
|
|
4141
|
+
target: z5.literal("model"),
|
|
4142
|
+
op: z5.literal("subRead"),
|
|
4143
|
+
id: z5.string().min(1),
|
|
4144
|
+
sub: z5.string().min(1),
|
|
4145
|
+
subId: z5.string().min(1),
|
|
3881
4146
|
args: rootModelSubReadArgsSchema.optional()
|
|
3882
4147
|
}).passthrough(),
|
|
3883
|
-
|
|
4148
|
+
z5.object({
|
|
3884
4149
|
...rootEntryBaseSchema,
|
|
3885
|
-
target:
|
|
3886
|
-
op:
|
|
3887
|
-
id:
|
|
3888
|
-
sub:
|
|
3889
|
-
data:
|
|
4150
|
+
target: z5.literal("model"),
|
|
4151
|
+
op: z5.literal("subCreate"),
|
|
4152
|
+
id: z5.string().min(1),
|
|
4153
|
+
sub: z5.string().min(1),
|
|
4154
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
3890
4155
|
}).passthrough(),
|
|
3891
|
-
|
|
4156
|
+
z5.object({
|
|
3892
4157
|
...rootEntryBaseSchema,
|
|
3893
|
-
target:
|
|
3894
|
-
op:
|
|
3895
|
-
id:
|
|
3896
|
-
sub:
|
|
3897
|
-
subId:
|
|
3898
|
-
data:
|
|
4158
|
+
target: z5.literal("model"),
|
|
4159
|
+
op: z5.literal("subUpdate"),
|
|
4160
|
+
id: z5.string().min(1),
|
|
4161
|
+
sub: z5.string().min(1),
|
|
4162
|
+
subId: z5.string().min(1),
|
|
4163
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
3899
4164
|
}).passthrough(),
|
|
3900
|
-
|
|
4165
|
+
z5.object({
|
|
3901
4166
|
...rootEntryBaseSchema,
|
|
3902
|
-
target:
|
|
3903
|
-
op:
|
|
3904
|
-
id:
|
|
3905
|
-
sub:
|
|
3906
|
-
data:
|
|
4167
|
+
target: z5.literal("model"),
|
|
4168
|
+
op: z5.literal("subBulkUpdate"),
|
|
4169
|
+
id: z5.string().min(1),
|
|
4170
|
+
sub: z5.string().min(1),
|
|
4171
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
3907
4172
|
}).passthrough(),
|
|
3908
|
-
|
|
4173
|
+
z5.object({
|
|
3909
4174
|
...rootEntryBaseSchema,
|
|
3910
|
-
target:
|
|
3911
|
-
op:
|
|
3912
|
-
id:
|
|
3913
|
-
sub:
|
|
3914
|
-
subId:
|
|
4175
|
+
target: z5.literal("model"),
|
|
4176
|
+
op: z5.literal("subDelete"),
|
|
4177
|
+
id: z5.string().min(1),
|
|
4178
|
+
sub: z5.string().min(1),
|
|
4179
|
+
subId: z5.string().min(1)
|
|
3915
4180
|
}).passthrough(),
|
|
3916
|
-
|
|
4181
|
+
z5.object({
|
|
3917
4182
|
...rootEntryBaseSchema,
|
|
3918
|
-
target:
|
|
3919
|
-
op:
|
|
3920
|
-
field:
|
|
4183
|
+
target: z5.literal("model"),
|
|
4184
|
+
op: z5.literal("distinct"),
|
|
4185
|
+
field: z5.string().min(1),
|
|
3921
4186
|
filter: objectOrArraySchema.optional()
|
|
3922
4187
|
}).passthrough(),
|
|
3923
|
-
|
|
4188
|
+
z5.object({
|
|
3924
4189
|
...rootEntryBaseSchema,
|
|
3925
|
-
target:
|
|
3926
|
-
op:
|
|
4190
|
+
target: z5.literal("model"),
|
|
4191
|
+
op: z5.literal("count"),
|
|
3927
4192
|
filter: objectOrArraySchema.optional(),
|
|
3928
4193
|
options: rootModelCountOptionsSchema.optional()
|
|
3929
4194
|
}).passthrough()
|
|
3930
4195
|
]);
|
|
3931
|
-
var rootDataQueryEntrySchema =
|
|
3932
|
-
|
|
4196
|
+
var rootDataQueryEntrySchema = z5.union([
|
|
4197
|
+
z5.object({
|
|
3933
4198
|
...rootEntryBaseSchema,
|
|
3934
|
-
target:
|
|
3935
|
-
op:
|
|
4199
|
+
target: z5.literal("data"),
|
|
4200
|
+
op: z5.literal("list"),
|
|
3936
4201
|
filter: objectOrArraySchema.optional(),
|
|
3937
4202
|
args: rootDataListArgsSchema.optional(),
|
|
3938
4203
|
options: rootDataListOptionsSchema.optional()
|
|
3939
4204
|
}).passthrough(),
|
|
3940
|
-
|
|
4205
|
+
z5.object({
|
|
3941
4206
|
...rootEntryBaseSchema,
|
|
3942
|
-
target:
|
|
3943
|
-
op:
|
|
3944
|
-
id:
|
|
4207
|
+
target: z5.literal("data"),
|
|
4208
|
+
op: z5.literal("read"),
|
|
4209
|
+
id: z5.string().min(1),
|
|
3945
4210
|
args: rootDataReadArgsSchema.optional()
|
|
3946
4211
|
}).passthrough(),
|
|
3947
|
-
|
|
4212
|
+
z5.object({
|
|
3948
4213
|
...rootEntryBaseSchema,
|
|
3949
|
-
target:
|
|
3950
|
-
op:
|
|
4214
|
+
target: z5.literal("data"),
|
|
4215
|
+
op: z5.literal("read"),
|
|
3951
4216
|
filter: objectOrArraySchema,
|
|
3952
4217
|
args: rootDataReadArgsSchema.optional()
|
|
3953
4218
|
}).passthrough()
|
|
3954
4219
|
]);
|
|
3955
|
-
var rootQuerySchema =
|
|
4220
|
+
var rootQuerySchema = z5.array(z5.union([rootModelQueryEntrySchema, rootDataQueryEntrySchema]));
|
|
3956
4221
|
|
|
3957
4222
|
// src/routers/shared.ts
|
|
3958
|
-
|
|
4223
|
+
import { parseBooleanString } from "@web-ts-toolkit/utils";
|
|
3959
4224
|
|
|
3960
4225
|
// src/routers/model-router-collection-routes.ts
|
|
3961
4226
|
function setModelCollectionRoutes(context) {
|
|
3962
4227
|
const { router, options } = context;
|
|
4228
|
+
const getAdvancedCreateOpenApiBody = () => {
|
|
4229
|
+
const advancedCreateSchema = context.getRequestSchema("requestSchemas.advancedCreate");
|
|
4230
|
+
const dataSchema = context.getRequestSchema("requestSchemas.advancedCreate.data") ?? getNestedOpenApiSchemaDataSource(advancedCreateSchema);
|
|
4231
|
+
const bodySchema = unwrapNestedOpenApiSchemaSource(
|
|
4232
|
+
context.getRequestSchema("requestSchemas.advancedCreate.default") ?? advancedCreateSchema,
|
|
4233
|
+
advancedCreateBodySchema
|
|
4234
|
+
);
|
|
4235
|
+
return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
|
|
4236
|
+
};
|
|
3963
4237
|
router.get("", async (req) => {
|
|
3964
4238
|
await context.assertAllowed(req, "list");
|
|
3965
4239
|
const { skip, limit, page, page_size, skim, include_permissions, include_count, include_extra_headers } = parseQuery(requestSchemas.listQuery, req.query);
|
|
@@ -3978,6 +4252,13 @@ function setModelCollectionRoutes(context) {
|
|
|
3978
4252
|
handleResultError(result);
|
|
3979
4253
|
return formatModelListResponse(req, result, includeCount, includeExtraHeaders);
|
|
3980
4254
|
});
|
|
4255
|
+
context.registerOpenApiRoute({
|
|
4256
|
+
method: "get",
|
|
4257
|
+
path: "",
|
|
4258
|
+
operationId: `${context.modelName}.list`,
|
|
4259
|
+
summary: `List ${context.modelName} documents`,
|
|
4260
|
+
query: requestSchemas.listQuery
|
|
4261
|
+
});
|
|
3981
4262
|
router.post(`/${options.queryRouteSegment}`, async (req) => {
|
|
3982
4263
|
await context.assertAllowed(req, "list");
|
|
3983
4264
|
const body = await parseBodyWithSchema(
|
|
@@ -4003,6 +4284,13 @@ function setModelCollectionRoutes(context) {
|
|
|
4003
4284
|
handleResultError(result);
|
|
4004
4285
|
return formatModelListResponse(req, result, includeCount, includeExtraHeaders);
|
|
4005
4286
|
});
|
|
4287
|
+
context.registerOpenApiRoute({
|
|
4288
|
+
method: "post",
|
|
4289
|
+
path: `/${options.queryRouteSegment}`,
|
|
4290
|
+
operationId: `${context.modelName}.listAdvanced`,
|
|
4291
|
+
summary: `Advanced list ${context.modelName} documents`,
|
|
4292
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.advancedList") ?? listBodySchema)
|
|
4293
|
+
});
|
|
4006
4294
|
router.post("", async (req) => {
|
|
4007
4295
|
await context.assertAllowed(req, "create");
|
|
4008
4296
|
const { include_permissions } = parseQuery(requestSchemas.createQuery, req.query);
|
|
@@ -4016,6 +4304,14 @@ function setModelCollectionRoutes(context) {
|
|
|
4016
4304
|
handleResultError(result);
|
|
4017
4305
|
return formatModelCreatedResponse(result);
|
|
4018
4306
|
});
|
|
4307
|
+
context.registerOpenApiRoute({
|
|
4308
|
+
method: "post",
|
|
4309
|
+
path: "",
|
|
4310
|
+
operationId: `${context.modelName}.create`,
|
|
4311
|
+
summary: `Create a ${context.modelName} document`,
|
|
4312
|
+
query: requestSchemas.createQuery,
|
|
4313
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.create") ?? createBodySchema)
|
|
4314
|
+
});
|
|
4019
4315
|
router.post(`/${options.mutationRouteSegment}`, async (req) => {
|
|
4020
4316
|
await context.assertAllowed(req, "create");
|
|
4021
4317
|
const { include_permissions } = parseQuery(requestSchemas.createQuery, req.query);
|
|
@@ -4045,17 +4341,49 @@ function setModelCollectionRoutes(context) {
|
|
|
4045
4341
|
handleResultError(result);
|
|
4046
4342
|
return formatModelCreatedResponse(result);
|
|
4047
4343
|
});
|
|
4344
|
+
context.registerOpenApiRoute({
|
|
4345
|
+
method: "post",
|
|
4346
|
+
path: `/${options.mutationRouteSegment}`,
|
|
4347
|
+
operationId: `${context.modelName}.createAdvanced`,
|
|
4348
|
+
summary: `Advanced create a ${context.modelName} document`,
|
|
4349
|
+
query: requestSchemas.createQuery,
|
|
4350
|
+
body: defineOpenApiSchemaResolver(getAdvancedCreateOpenApiBody)
|
|
4351
|
+
});
|
|
4048
4352
|
router.get("/new", async (req) => {
|
|
4049
4353
|
const svc = context.getPublicService(req);
|
|
4050
4354
|
const result = await svc._new();
|
|
4051
4355
|
handleResultError(result);
|
|
4052
4356
|
return unwrapServiceData(result);
|
|
4053
4357
|
});
|
|
4358
|
+
context.registerOpenApiRoute({
|
|
4359
|
+
method: "get",
|
|
4360
|
+
path: "/new",
|
|
4361
|
+
operationId: `${context.modelName}.new`,
|
|
4362
|
+
summary: `Get a new ${context.modelName} document template`
|
|
4363
|
+
});
|
|
4054
4364
|
}
|
|
4055
4365
|
|
|
4056
4366
|
// src/routers/model-router-document-routes.ts
|
|
4057
4367
|
function setModelDocumentRoutes(context) {
|
|
4058
4368
|
const { router, options, modelName } = context;
|
|
4369
|
+
const getAdvancedUpdateOpenApiBody = () => {
|
|
4370
|
+
const advancedUpdateSchema = context.getRequestSchema("requestSchemas.advancedUpdate");
|
|
4371
|
+
const dataSchema = context.getRequestSchema("requestSchemas.advancedUpdate.data") ?? getNestedOpenApiSchemaDataSource(advancedUpdateSchema);
|
|
4372
|
+
const bodySchema = unwrapNestedOpenApiSchemaSource(
|
|
4373
|
+
context.getRequestSchema("requestSchemas.advancedUpdate.default") ?? advancedUpdateSchema,
|
|
4374
|
+
advancedUpdateBodySchema
|
|
4375
|
+
);
|
|
4376
|
+
return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
|
|
4377
|
+
};
|
|
4378
|
+
const getAdvancedUpsertOpenApiBody = () => {
|
|
4379
|
+
const advancedUpsertSchema = context.getRequestSchema("requestSchemas.advancedUpsert");
|
|
4380
|
+
const dataSchema = context.getRequestSchema("requestSchemas.advancedUpsert.data") ?? getNestedOpenApiSchemaDataSource(advancedUpsertSchema);
|
|
4381
|
+
const bodySchema = unwrapNestedOpenApiSchemaSource(
|
|
4382
|
+
context.getRequestSchema("requestSchemas.advancedUpsert.default") ?? advancedUpsertSchema,
|
|
4383
|
+
advancedUpsertBodySchema
|
|
4384
|
+
);
|
|
4385
|
+
return dataSchema ? patchOpenApiObjectSchema(bodySchema, { data: dataSchema }) : bodySchema;
|
|
4386
|
+
};
|
|
4059
4387
|
router.get("/count", async (req) => {
|
|
4060
4388
|
await context.assertAllowed(req, "count");
|
|
4061
4389
|
const svc = context.getPublicService(req);
|
|
@@ -4063,6 +4391,12 @@ function setModelDocumentRoutes(context) {
|
|
|
4063
4391
|
handleResultError(result);
|
|
4064
4392
|
return unwrapServiceData(result);
|
|
4065
4393
|
});
|
|
4394
|
+
context.registerOpenApiRoute({
|
|
4395
|
+
method: "get",
|
|
4396
|
+
path: "/count",
|
|
4397
|
+
operationId: `${modelName}.count`,
|
|
4398
|
+
summary: `Count ${modelName} documents`
|
|
4399
|
+
});
|
|
4066
4400
|
router.post("/count", async (req) => {
|
|
4067
4401
|
await context.assertAllowed(req, "count");
|
|
4068
4402
|
const { filter: filter2, options: countOptions = {} } = await parseBodyWithSchema(
|
|
@@ -4078,6 +4412,13 @@ function setModelDocumentRoutes(context) {
|
|
|
4078
4412
|
handleResultError(result);
|
|
4079
4413
|
return unwrapServiceData(result);
|
|
4080
4414
|
});
|
|
4415
|
+
context.registerOpenApiRoute({
|
|
4416
|
+
method: "post",
|
|
4417
|
+
path: "/count",
|
|
4418
|
+
operationId: `${modelName}.countWithFilter`,
|
|
4419
|
+
summary: `Count ${modelName} documents with a filter`,
|
|
4420
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.count") ?? countBodySchema)
|
|
4421
|
+
});
|
|
4081
4422
|
router.get(`/:${options.idParam}`, async (req) => {
|
|
4082
4423
|
await context.assertAllowed(req, "read");
|
|
4083
4424
|
const id = parsePathParam(req.params[options.idParam], options.idParam);
|
|
@@ -4094,6 +4435,13 @@ function setModelDocumentRoutes(context) {
|
|
|
4094
4435
|
handleResultError(result);
|
|
4095
4436
|
return unwrapServiceData(result);
|
|
4096
4437
|
});
|
|
4438
|
+
context.registerOpenApiRoute({
|
|
4439
|
+
method: "get",
|
|
4440
|
+
path: `/:${options.idParam}`,
|
|
4441
|
+
operationId: `${modelName}.read`,
|
|
4442
|
+
summary: `Read a ${modelName} document`,
|
|
4443
|
+
query: requestSchemas.readQuery
|
|
4444
|
+
});
|
|
4097
4445
|
router.post(`/${options.queryRouteSegment}/__filter`, async (req) => {
|
|
4098
4446
|
await context.assertAllowed(req, "read");
|
|
4099
4447
|
const body = await parseBodyWithSchema(
|
|
@@ -4113,6 +4461,15 @@ function setModelDocumentRoutes(context) {
|
|
|
4113
4461
|
handleResultError(result);
|
|
4114
4462
|
return unwrapServiceData(result);
|
|
4115
4463
|
});
|
|
4464
|
+
context.registerOpenApiRoute({
|
|
4465
|
+
method: "post",
|
|
4466
|
+
path: `/${options.queryRouteSegment}/__filter`,
|
|
4467
|
+
operationId: `${modelName}.readByFilterAdvanced`,
|
|
4468
|
+
summary: `Read a ${modelName} document by filter`,
|
|
4469
|
+
body: defineOpenApiSchemaResolver(
|
|
4470
|
+
() => context.getRequestSchema("requestSchemas.advancedReadFilter") ?? readFilterBodySchema
|
|
4471
|
+
)
|
|
4472
|
+
});
|
|
4116
4473
|
router.post(`/${options.queryRouteSegment}/:${options.idParam}`, async (req) => {
|
|
4117
4474
|
await context.assertAllowed(req, "read");
|
|
4118
4475
|
const id = parsePathParam(req.params[options.idParam], options.idParam);
|
|
@@ -4133,6 +4490,15 @@ function setModelDocumentRoutes(context) {
|
|
|
4133
4490
|
handleResultError(result);
|
|
4134
4491
|
return unwrapServiceData(result);
|
|
4135
4492
|
});
|
|
4493
|
+
context.registerOpenApiRoute({
|
|
4494
|
+
method: "post",
|
|
4495
|
+
path: `/${options.queryRouteSegment}/:${options.idParam}`,
|
|
4496
|
+
operationId: `${modelName}.readAdvanced`,
|
|
4497
|
+
summary: `Read a ${modelName} document with advanced options`,
|
|
4498
|
+
body: defineOpenApiSchemaResolver(
|
|
4499
|
+
() => context.getRequestSchema("requestSchemas.advancedRead") ?? readByIdBodySchema
|
|
4500
|
+
)
|
|
4501
|
+
});
|
|
4136
4502
|
router.patch(`/:${options.idParam}`, async (req) => {
|
|
4137
4503
|
await context.assertAllowed(req, "update");
|
|
4138
4504
|
const id = parsePathParam(req.params[options.idParam], options.idParam);
|
|
@@ -4155,6 +4521,14 @@ function setModelDocumentRoutes(context) {
|
|
|
4155
4521
|
handleResultError(result);
|
|
4156
4522
|
return unwrapServiceData(result);
|
|
4157
4523
|
});
|
|
4524
|
+
context.registerOpenApiRoute({
|
|
4525
|
+
method: "patch",
|
|
4526
|
+
path: `/:${options.idParam}`,
|
|
4527
|
+
operationId: `${modelName}.update`,
|
|
4528
|
+
summary: `Update a ${modelName} document`,
|
|
4529
|
+
query: requestSchemas.updateQuery,
|
|
4530
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.update") ?? updateBodySchema)
|
|
4531
|
+
});
|
|
4158
4532
|
router.patch(`/${options.mutationRouteSegment}/:${options.idParam}`, async (req) => {
|
|
4159
4533
|
await context.assertAllowed(req, "update");
|
|
4160
4534
|
const id = parsePathParam(req.params[options.idParam], options.idParam);
|
|
@@ -4187,6 +4561,14 @@ function setModelDocumentRoutes(context) {
|
|
|
4187
4561
|
handleResultError(result);
|
|
4188
4562
|
return unwrapServiceData(result);
|
|
4189
4563
|
});
|
|
4564
|
+
context.registerOpenApiRoute({
|
|
4565
|
+
method: "patch",
|
|
4566
|
+
path: `/${options.mutationRouteSegment}/:${options.idParam}`,
|
|
4567
|
+
operationId: `${modelName}.updateAdvanced`,
|
|
4568
|
+
summary: `Advanced update a ${modelName} document`,
|
|
4569
|
+
query: requestSchemas.updateQuery,
|
|
4570
|
+
body: defineOpenApiSchemaResolver(getAdvancedUpdateOpenApiBody)
|
|
4571
|
+
});
|
|
4190
4572
|
router.put(`/`, async (req) => {
|
|
4191
4573
|
await context.assertAllowed(req, "upsert");
|
|
4192
4574
|
const svc = context.getPublicService(req);
|
|
@@ -4207,6 +4589,14 @@ function setModelDocumentRoutes(context) {
|
|
|
4207
4589
|
handleResultError(result);
|
|
4208
4590
|
return formatModelUpsertResponse(result);
|
|
4209
4591
|
});
|
|
4592
|
+
context.registerOpenApiRoute({
|
|
4593
|
+
method: "put",
|
|
4594
|
+
path: "/",
|
|
4595
|
+
operationId: `${modelName}.upsert`,
|
|
4596
|
+
summary: `Upsert a ${modelName} document`,
|
|
4597
|
+
query: requestSchemas.upsertQuery,
|
|
4598
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.upsert") ?? upsertBodySchema)
|
|
4599
|
+
});
|
|
4210
4600
|
router.put(`/${options.mutationRouteSegment}`, async (req) => {
|
|
4211
4601
|
await context.assertAllowed(req, "upsert");
|
|
4212
4602
|
const svc = context.getPublicService(req);
|
|
@@ -4237,6 +4627,14 @@ function setModelDocumentRoutes(context) {
|
|
|
4237
4627
|
handleResultError(result);
|
|
4238
4628
|
return formatModelUpsertResponse(result);
|
|
4239
4629
|
});
|
|
4630
|
+
context.registerOpenApiRoute({
|
|
4631
|
+
method: "put",
|
|
4632
|
+
path: `/${options.mutationRouteSegment}`,
|
|
4633
|
+
operationId: `${modelName}.upsertAdvanced`,
|
|
4634
|
+
summary: `Advanced upsert a ${modelName} document`,
|
|
4635
|
+
query: requestSchemas.upsertQuery,
|
|
4636
|
+
body: defineOpenApiSchemaResolver(getAdvancedUpsertOpenApiBody)
|
|
4637
|
+
});
|
|
4240
4638
|
router.delete(`/:${options.idParam}`, async (req) => {
|
|
4241
4639
|
await context.assertAllowed(req, "delete");
|
|
4242
4640
|
const id = parsePathParam(req.params[options.idParam], options.idParam);
|
|
@@ -4245,6 +4643,12 @@ function setModelDocumentRoutes(context) {
|
|
|
4245
4643
|
handleResultError(result);
|
|
4246
4644
|
return unwrapServiceData(result);
|
|
4247
4645
|
});
|
|
4646
|
+
context.registerOpenApiRoute({
|
|
4647
|
+
method: "delete",
|
|
4648
|
+
path: `/:${options.idParam}`,
|
|
4649
|
+
operationId: `${modelName}.delete`,
|
|
4650
|
+
summary: `Delete a ${modelName} document`
|
|
4651
|
+
});
|
|
4248
4652
|
router.get("/distinct/:field", async (req) => {
|
|
4249
4653
|
await context.assertAllowed(req, "distinct");
|
|
4250
4654
|
const field = parsePathParam(req.params.field, "field");
|
|
@@ -4253,6 +4657,12 @@ function setModelDocumentRoutes(context) {
|
|
|
4253
4657
|
handleResultError(result);
|
|
4254
4658
|
return unwrapServiceData(result);
|
|
4255
4659
|
});
|
|
4660
|
+
context.registerOpenApiRoute({
|
|
4661
|
+
method: "get",
|
|
4662
|
+
path: "/distinct/:field",
|
|
4663
|
+
operationId: `${modelName}.distinct`,
|
|
4664
|
+
summary: `Get distinct values for a ${modelName} field`
|
|
4665
|
+
});
|
|
4256
4666
|
router.post("/distinct/:field", async (req) => {
|
|
4257
4667
|
await context.assertAllowed(req, "distinct");
|
|
4258
4668
|
const field = parsePathParam(req.params.field, "field");
|
|
@@ -4266,6 +4676,13 @@ function setModelDocumentRoutes(context) {
|
|
|
4266
4676
|
handleResultError(result);
|
|
4267
4677
|
return unwrapServiceData(result);
|
|
4268
4678
|
});
|
|
4679
|
+
context.registerOpenApiRoute({
|
|
4680
|
+
method: "post",
|
|
4681
|
+
path: "/distinct/:field",
|
|
4682
|
+
operationId: `${modelName}.distinctWithFilter`,
|
|
4683
|
+
summary: `Get distinct values for a ${modelName} field with a filter`,
|
|
4684
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.distinct") ?? distinctBodySchema)
|
|
4685
|
+
});
|
|
4269
4686
|
}
|
|
4270
4687
|
|
|
4271
4688
|
// src/routers/model-router-subdocument-routes.ts
|
|
@@ -4282,6 +4699,12 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4282
4699
|
handleResultError(result);
|
|
4283
4700
|
return unwrapServiceData(result);
|
|
4284
4701
|
});
|
|
4702
|
+
context.registerOpenApiRoute({
|
|
4703
|
+
method: "get",
|
|
4704
|
+
path: `/:${context.options.idParam}/${sub}`,
|
|
4705
|
+
operationId: `${context.modelName}.${sub}.list`,
|
|
4706
|
+
summary: `List ${sub} subdocuments`
|
|
4707
|
+
});
|
|
4285
4708
|
context.router.post(
|
|
4286
4709
|
`/:${context.options.idParam}/${sub}/${context.options.queryRouteSegment}`,
|
|
4287
4710
|
async (req) => {
|
|
@@ -4298,6 +4721,13 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4298
4721
|
return unwrapServiceData(result);
|
|
4299
4722
|
}
|
|
4300
4723
|
);
|
|
4724
|
+
context.registerOpenApiRoute({
|
|
4725
|
+
method: "post",
|
|
4726
|
+
path: `/:${context.options.idParam}/${sub}/${context.options.queryRouteSegment}`,
|
|
4727
|
+
operationId: `${context.modelName}.${sub}.listAdvanced`,
|
|
4728
|
+
summary: `Advanced list ${sub} subdocuments`,
|
|
4729
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.subList") ?? subListBodySchema)
|
|
4730
|
+
});
|
|
4301
4731
|
context.router.patch(`/:${context.options.idParam}/${sub}`, async (req) => {
|
|
4302
4732
|
await context.assertAllowed(req, `subs.${sub}.update`);
|
|
4303
4733
|
const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
|
|
@@ -4311,6 +4741,15 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4311
4741
|
handleResultError(result);
|
|
4312
4742
|
return unwrapServiceData(result);
|
|
4313
4743
|
});
|
|
4744
|
+
context.registerOpenApiRoute({
|
|
4745
|
+
method: "patch",
|
|
4746
|
+
path: `/:${context.options.idParam}/${sub}`,
|
|
4747
|
+
operationId: `${context.modelName}.${sub}.bulkUpdate`,
|
|
4748
|
+
summary: `Bulk update ${sub} subdocuments`,
|
|
4749
|
+
body: defineOpenApiSchemaResolver(
|
|
4750
|
+
() => context.getRequestSchema("requestSchemas.subBulkUpdate") ?? subMutationBodySchema
|
|
4751
|
+
)
|
|
4752
|
+
});
|
|
4314
4753
|
context.router.get(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
|
|
4315
4754
|
await context.assertAllowed(req, `subs.${sub}.read`);
|
|
4316
4755
|
const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
|
|
@@ -4320,6 +4759,12 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4320
4759
|
handleResultError(result);
|
|
4321
4760
|
return unwrapServiceData(result);
|
|
4322
4761
|
});
|
|
4762
|
+
context.registerOpenApiRoute({
|
|
4763
|
+
method: "get",
|
|
4764
|
+
path: `/:${context.options.idParam}/${sub}/:subId`,
|
|
4765
|
+
operationId: `${context.modelName}.${sub}.read`,
|
|
4766
|
+
summary: `Read a ${sub} subdocument`
|
|
4767
|
+
});
|
|
4323
4768
|
context.router.post(
|
|
4324
4769
|
`/:${context.options.idParam}/${sub}/:subId/${context.options.queryRouteSegment}`,
|
|
4325
4770
|
async (req) => {
|
|
@@ -4339,6 +4784,13 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4339
4784
|
return unwrapServiceData(result);
|
|
4340
4785
|
}
|
|
4341
4786
|
);
|
|
4787
|
+
context.registerOpenApiRoute({
|
|
4788
|
+
method: "post",
|
|
4789
|
+
path: `/:${context.options.idParam}/${sub}/:subId/${context.options.queryRouteSegment}`,
|
|
4790
|
+
operationId: `${context.modelName}.${sub}.readAdvanced`,
|
|
4791
|
+
summary: `Advanced read a ${sub} subdocument`,
|
|
4792
|
+
body: defineOpenApiSchemaResolver(() => context.getRequestSchema("requestSchemas.subRead") ?? subReadBodySchema)
|
|
4793
|
+
});
|
|
4342
4794
|
context.router.patch(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
|
|
4343
4795
|
await context.assertAllowed(req, `subs.${sub}.update`);
|
|
4344
4796
|
const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
|
|
@@ -4353,6 +4805,15 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4353
4805
|
handleResultError(result);
|
|
4354
4806
|
return unwrapServiceData(result);
|
|
4355
4807
|
});
|
|
4808
|
+
context.registerOpenApiRoute({
|
|
4809
|
+
method: "patch",
|
|
4810
|
+
path: `/:${context.options.idParam}/${sub}/:subId`,
|
|
4811
|
+
operationId: `${context.modelName}.${sub}.update`,
|
|
4812
|
+
summary: `Update a ${sub} subdocument`,
|
|
4813
|
+
body: defineOpenApiSchemaResolver(
|
|
4814
|
+
() => context.getRequestSchema("requestSchemas.subUpdate") ?? subMutationBodySchema
|
|
4815
|
+
)
|
|
4816
|
+
});
|
|
4356
4817
|
context.router.post(`/:${context.options.idParam}/${sub}`, async (req) => {
|
|
4357
4818
|
await context.assertAllowed(req, `subs.${sub}.create`);
|
|
4358
4819
|
const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
|
|
@@ -4366,6 +4827,15 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4366
4827
|
handleResultError(result);
|
|
4367
4828
|
return formatModelCreatedResponse(result);
|
|
4368
4829
|
});
|
|
4830
|
+
context.registerOpenApiRoute({
|
|
4831
|
+
method: "post",
|
|
4832
|
+
path: `/:${context.options.idParam}/${sub}`,
|
|
4833
|
+
operationId: `${context.modelName}.${sub}.create`,
|
|
4834
|
+
summary: `Create a ${sub} subdocument`,
|
|
4835
|
+
body: defineOpenApiSchemaResolver(
|
|
4836
|
+
() => context.getRequestSchema("requestSchemas.subCreate") ?? subMutationBodySchema
|
|
4837
|
+
)
|
|
4838
|
+
});
|
|
4369
4839
|
context.router.delete(`/:${context.options.idParam}/${sub}/:subId`, async (req) => {
|
|
4370
4840
|
await context.assertAllowed(req, `subs.${sub}.delete`);
|
|
4371
4841
|
const id = parsePathParam(req.params[context.options.idParam], context.options.idParam);
|
|
@@ -4375,9 +4845,25 @@ function setModelSubDocumentRoutes(context) {
|
|
|
4375
4845
|
handleResultError(result);
|
|
4376
4846
|
return unwrapServiceData(result);
|
|
4377
4847
|
});
|
|
4848
|
+
context.registerOpenApiRoute({
|
|
4849
|
+
method: "delete",
|
|
4850
|
+
path: `/:${context.options.idParam}/${sub}/:subId`,
|
|
4851
|
+
operationId: `${context.modelName}.${sub}.delete`,
|
|
4852
|
+
summary: `Delete a ${sub} subdocument`
|
|
4853
|
+
});
|
|
4378
4854
|
}
|
|
4379
4855
|
}
|
|
4380
4856
|
|
|
4857
|
+
// src/openapi/route-registration.ts
|
|
4858
|
+
import { normalizeUrlPath } from "@web-ts-toolkit/utils";
|
|
4859
|
+
function registerOpenApiRoute(runtime, basePath, defaultTag, route) {
|
|
4860
|
+
runtime.registerOpenApiRoute({
|
|
4861
|
+
...route,
|
|
4862
|
+
path: normalizeUrlPath(basePath + route.path),
|
|
4863
|
+
tags: route.tags ?? [defaultTag]
|
|
4864
|
+
});
|
|
4865
|
+
}
|
|
4866
|
+
|
|
4381
4867
|
// src/routers/model-router.ts
|
|
4382
4868
|
var clientErrors2 = JsonRouter5.clientErrors;
|
|
4383
4869
|
function setOption(parentKey, optionKey, option) {
|
|
@@ -4543,7 +5029,7 @@ var ModelRouter = class {
|
|
|
4543
5029
|
this.runtime.setModelOptions(modelName, initialOptions);
|
|
4544
5030
|
attachRuntimeToModel(modelName, this.runtime);
|
|
4545
5031
|
this.options = this.runtime.getModelOptions(modelName);
|
|
4546
|
-
this.fullBasePath =
|
|
5032
|
+
this.fullBasePath = normalizeUrlPath2(this.options.parentPath + this.options.basePath);
|
|
4547
5033
|
this.modelName = modelName;
|
|
4548
5034
|
this.router = new JsonRouter5(this.options.basePath, createSetCore(this.runtime), accessRouterResponseHandler);
|
|
4549
5035
|
this.model = new model_default(modelName);
|
|
@@ -4568,6 +5054,9 @@ var ModelRouter = class {
|
|
|
4568
5054
|
const allowed = await req.macl.isAllowed(this.modelName, access);
|
|
4569
5055
|
if (!allowed) throw new clientErrors2.UnauthorizedError();
|
|
4570
5056
|
}
|
|
5057
|
+
registerOpenApiRoute(route) {
|
|
5058
|
+
registerOpenApiRoute(this.runtime, this.fullBasePath, this.modelName, route);
|
|
5059
|
+
}
|
|
4571
5060
|
///////////////////////
|
|
4572
5061
|
// Collection Routes //
|
|
4573
5062
|
///////////////////////
|
|
@@ -4578,7 +5067,8 @@ var ModelRouter = class {
|
|
|
4578
5067
|
options: this.options,
|
|
4579
5068
|
getRequestSchema: this.getRequestSchema.bind(this),
|
|
4580
5069
|
getPublicService: this.getPublicService.bind(this),
|
|
4581
|
-
assertAllowed: this.assertAllowed.bind(this)
|
|
5070
|
+
assertAllowed: this.assertAllowed.bind(this),
|
|
5071
|
+
registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
|
|
4582
5072
|
});
|
|
4583
5073
|
}
|
|
4584
5074
|
/////////////////////
|
|
@@ -4591,7 +5081,8 @@ var ModelRouter = class {
|
|
|
4591
5081
|
options: this.options,
|
|
4592
5082
|
getRequestSchema: this.getRequestSchema.bind(this),
|
|
4593
5083
|
getPublicService: this.getPublicService.bind(this),
|
|
4594
|
-
assertAllowed: this.assertAllowed.bind(this)
|
|
5084
|
+
assertAllowed: this.assertAllowed.bind(this),
|
|
5085
|
+
registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
|
|
4595
5086
|
});
|
|
4596
5087
|
}
|
|
4597
5088
|
/////////////////////////
|
|
@@ -4604,13 +5095,14 @@ var ModelRouter = class {
|
|
|
4604
5095
|
options: this.options,
|
|
4605
5096
|
getRequestSchema: this.getRequestSchema.bind(this),
|
|
4606
5097
|
getPublicService: this.getPublicService.bind(this),
|
|
4607
|
-
assertAllowed: this.assertAllowed.bind(this)
|
|
5098
|
+
assertAllowed: this.assertAllowed.bind(this),
|
|
5099
|
+
registerOpenApiRoute: this.registerOpenApiRoute.bind(this)
|
|
4608
5100
|
});
|
|
4609
5101
|
}
|
|
4610
5102
|
logEndpoints() {
|
|
4611
5103
|
runWithRuntime(this.runtime, () => {
|
|
4612
|
-
|
|
4613
|
-
logger.info(`${padEnd(method, 6)} ${
|
|
5104
|
+
forEach8(this.router.endpoints, ({ method, path }) => {
|
|
5105
|
+
logger.info(`${padEnd(method, 6)} ${normalizeUrlPath2(this.options.parentPath + path)}`);
|
|
4614
5106
|
});
|
|
4615
5107
|
});
|
|
4616
5108
|
}
|
|
@@ -4623,7 +5115,7 @@ var ModelRouter = class {
|
|
|
4623
5115
|
value
|
|
4624
5116
|
);
|
|
4625
5117
|
}
|
|
4626
|
-
if (arguments.length === 1 &&
|
|
5118
|
+
if (arguments.length === 1 && isPlainObject12(keyOrOptions)) {
|
|
4627
5119
|
assertMutableRouterOptions("model", keyOrOptions);
|
|
4628
5120
|
this.runtime.setModelOptions(this.modelName, keyOrOptions);
|
|
4629
5121
|
}
|
|
@@ -4646,7 +5138,7 @@ var ModelRouter = class {
|
|
|
4646
5138
|
|
|
4647
5139
|
// src/routers/root-router.ts
|
|
4648
5140
|
import JsonRouter6 from "@web-ts-toolkit/express-json-router";
|
|
4649
|
-
import { isNumber as _isNumber, isString as isString10, orderBy as _orderBy } from "@web-ts-toolkit/utils";
|
|
5141
|
+
import { isNumber as _isNumber, isString as isString10, normalizeUrlPath as normalizeUrlPath3, orderBy as _orderBy } from "@web-ts-toolkit/utils";
|
|
4650
5142
|
|
|
4651
5143
|
// src/core-data.ts
|
|
4652
5144
|
var DataCore = class {
|
|
@@ -4892,6 +5384,9 @@ var RootRouter = class {
|
|
|
4892
5384
|
);
|
|
4893
5385
|
this.setRoutes();
|
|
4894
5386
|
}
|
|
5387
|
+
registerOpenApiRoute(route) {
|
|
5388
|
+
registerOpenApiRoute(this.runtime, normalizeUrlPath3(this.basename), "root", route);
|
|
5389
|
+
}
|
|
4895
5390
|
wrapResult(index, item, result) {
|
|
4896
5391
|
return {
|
|
4897
5392
|
index,
|
|
@@ -4977,6 +5472,13 @@ var RootRouter = class {
|
|
|
4977
5472
|
}
|
|
4978
5473
|
return _orderBy(results, ["index"], ["asc"]);
|
|
4979
5474
|
});
|
|
5475
|
+
this.registerOpenApiRoute({
|
|
5476
|
+
method: "post",
|
|
5477
|
+
path: "",
|
|
5478
|
+
operationId: "root.query",
|
|
5479
|
+
summary: "Execute batched model and data operations",
|
|
5480
|
+
body: rootQuerySchema
|
|
5481
|
+
});
|
|
4980
5482
|
}
|
|
4981
5483
|
get routes() {
|
|
4982
5484
|
return this.router.original;
|
|
@@ -4985,7 +5487,7 @@ var RootRouter = class {
|
|
|
4985
5487
|
|
|
4986
5488
|
// src/routers/data-router.ts
|
|
4987
5489
|
import JsonRouter7 from "@web-ts-toolkit/express-json-router";
|
|
4988
|
-
import { isPlainObject as
|
|
5490
|
+
import { isPlainObject as isPlainObject13, isString as isString11, isUndefined as isUndefined3, normalizeUrlPath as normalizeUrlPath4 } from "@web-ts-toolkit/utils";
|
|
4989
5491
|
var clientErrors4 = JsonRouter7.clientErrors;
|
|
4990
5492
|
function setOption2(parentKey, optionKey, option) {
|
|
4991
5493
|
const key = isUndefined3(option) ? parentKey : `${parentKey}.${optionKey}`;
|
|
@@ -5025,7 +5527,7 @@ var DataRouter = class {
|
|
|
5025
5527
|
this.runtime = runtime;
|
|
5026
5528
|
this.runtime.setDataOptions(dataName, initialOptions);
|
|
5027
5529
|
this.options = this.runtime.getDataOptions(dataName);
|
|
5028
|
-
this.fullBasePath =
|
|
5530
|
+
this.fullBasePath = normalizeUrlPath4(this.options.parentPath + this.options.basePath);
|
|
5029
5531
|
this.dataName = dataName;
|
|
5030
5532
|
this.router = new JsonRouter7(this.options.basePath, createSetDataCore(this.runtime), accessRouterResponseHandler);
|
|
5031
5533
|
this.setCollectionRoutes();
|
|
@@ -5044,6 +5546,9 @@ var DataRouter = class {
|
|
|
5044
5546
|
const allowed = await req.dacl.isAllowed(this.dataName, access);
|
|
5045
5547
|
if (!allowed) throw new clientErrors4.UnauthorizedError();
|
|
5046
5548
|
}
|
|
5549
|
+
registerOpenApiRoute(route) {
|
|
5550
|
+
registerOpenApiRoute(this.runtime, this.fullBasePath, this.dataName, route);
|
|
5551
|
+
}
|
|
5047
5552
|
///////////////////////
|
|
5048
5553
|
// Collection Routes //
|
|
5049
5554
|
///////////////////////
|
|
@@ -5068,6 +5573,13 @@ var DataRouter = class {
|
|
|
5068
5573
|
const decoratedResult = await decorateDataListResult(svc, result);
|
|
5069
5574
|
return formatListResponse(req, decoratedResult, includeCount, includeExtraHeaders);
|
|
5070
5575
|
});
|
|
5576
|
+
this.registerOpenApiRoute({
|
|
5577
|
+
method: "get",
|
|
5578
|
+
path: "",
|
|
5579
|
+
operationId: `${this.dataName}.list`,
|
|
5580
|
+
summary: `List ${this.dataName} records`,
|
|
5581
|
+
query: requestSchemas.listQuery
|
|
5582
|
+
});
|
|
5071
5583
|
this.router.post(`/${this.options.queryRouteSegment}`, async (req) => {
|
|
5072
5584
|
await this.assertAllowed(req, "list");
|
|
5073
5585
|
let {
|
|
@@ -5091,6 +5603,15 @@ var DataRouter = class {
|
|
|
5091
5603
|
const decoratedResult = await decorateDataListResult(svc, result);
|
|
5092
5604
|
return formatListResponse(req, decoratedResult, includeCount, includeExtraHeaders);
|
|
5093
5605
|
});
|
|
5606
|
+
this.registerOpenApiRoute({
|
|
5607
|
+
method: "post",
|
|
5608
|
+
path: `/${this.options.queryRouteSegment}`,
|
|
5609
|
+
operationId: `${this.dataName}.listAdvanced`,
|
|
5610
|
+
summary: `Advanced list ${this.dataName} records`,
|
|
5611
|
+
body: defineOpenApiSchemaResolver(
|
|
5612
|
+
() => this.getRequestSchema("requestSchemas.advancedList") ?? dataListBodySchema
|
|
5613
|
+
)
|
|
5614
|
+
});
|
|
5094
5615
|
}
|
|
5095
5616
|
/////////////////////
|
|
5096
5617
|
// Document Routes //
|
|
@@ -5105,6 +5626,12 @@ var DataRouter = class {
|
|
|
5105
5626
|
const decoratedResult = await decorateDataSingleResult(svc, result);
|
|
5106
5627
|
return decoratedResult.data;
|
|
5107
5628
|
});
|
|
5629
|
+
this.registerOpenApiRoute({
|
|
5630
|
+
method: "get",
|
|
5631
|
+
path: `/:${this.options.idParam}`,
|
|
5632
|
+
operationId: `${this.dataName}.read`,
|
|
5633
|
+
summary: `Read a ${this.dataName} record`
|
|
5634
|
+
});
|
|
5108
5635
|
this.router.post(`/${this.options.queryRouteSegment}/__filter`, async (req) => {
|
|
5109
5636
|
await this.assertAllowed(req, "read");
|
|
5110
5637
|
let { filter: filter2, select } = await parseBodyWithSchema(
|
|
@@ -5118,6 +5645,15 @@ var DataRouter = class {
|
|
|
5118
5645
|
const decoratedResult = await decorateDataSingleResult(svc, result);
|
|
5119
5646
|
return decoratedResult.data;
|
|
5120
5647
|
});
|
|
5648
|
+
this.registerOpenApiRoute({
|
|
5649
|
+
method: "post",
|
|
5650
|
+
path: `/${this.options.queryRouteSegment}/__filter`,
|
|
5651
|
+
operationId: `${this.dataName}.readByFilter`,
|
|
5652
|
+
summary: `Read a ${this.dataName} record by filter`,
|
|
5653
|
+
body: defineOpenApiSchemaResolver(
|
|
5654
|
+
() => this.getRequestSchema("requestSchemas.advancedReadFilter") ?? dataReadFilterBodySchema
|
|
5655
|
+
)
|
|
5656
|
+
});
|
|
5121
5657
|
this.router.post(`/${this.options.queryRouteSegment}/:${this.options.idParam}`, async (req) => {
|
|
5122
5658
|
await this.assertAllowed(req, "read");
|
|
5123
5659
|
const id = parsePathParam(req.params[this.options.idParam], this.options.idParam);
|
|
@@ -5132,13 +5668,22 @@ var DataRouter = class {
|
|
|
5132
5668
|
const decoratedResult = await decorateDataSingleResult(svc, result);
|
|
5133
5669
|
return decoratedResult.data;
|
|
5134
5670
|
});
|
|
5671
|
+
this.registerOpenApiRoute({
|
|
5672
|
+
method: "post",
|
|
5673
|
+
path: `/${this.options.queryRouteSegment}/:${this.options.idParam}`,
|
|
5674
|
+
operationId: `${this.dataName}.readAdvanced`,
|
|
5675
|
+
summary: `Advanced read a ${this.dataName} record`,
|
|
5676
|
+
body: defineOpenApiSchemaResolver(
|
|
5677
|
+
() => this.getRequestSchema("requestSchemas.advancedRead") ?? dataReadByIdBodySchema
|
|
5678
|
+
)
|
|
5679
|
+
});
|
|
5135
5680
|
}
|
|
5136
5681
|
set(keyOrOptions, value) {
|
|
5137
5682
|
if (arguments.length === 2 && isString11(keyOrOptions)) {
|
|
5138
5683
|
assertMutableRouterOption("data", keyOrOptions);
|
|
5139
5684
|
this.runtime.setDataOption(this.dataName, keyOrOptions, value);
|
|
5140
5685
|
}
|
|
5141
|
-
if (arguments.length === 1 &&
|
|
5686
|
+
if (arguments.length === 1 && isPlainObject13(keyOrOptions)) {
|
|
5142
5687
|
assertMutableRouterOptions("data", keyOrOptions);
|
|
5143
5688
|
this.runtime.setDataOptions(this.dataName, keyOrOptions);
|
|
5144
5689
|
}
|
|
@@ -5161,6 +5706,62 @@ var DataRouter = class {
|
|
|
5161
5706
|
|
|
5162
5707
|
// src/routers/index.ts
|
|
5163
5708
|
import JsonRouter8 from "@web-ts-toolkit/express-json-router";
|
|
5709
|
+
|
|
5710
|
+
// src/openapi/router.ts
|
|
5711
|
+
import express from "express";
|
|
5712
|
+
import { posix } from "path";
|
|
5713
|
+
var escapeHtml = (value) => value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
5714
|
+
var renderDocsHtml = (specPath, title, cssUrl, bundleUrl) => `<!doctype html>
|
|
5715
|
+
<html lang="en">
|
|
5716
|
+
<head>
|
|
5717
|
+
<meta charset="utf-8" />
|
|
5718
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
5719
|
+
<title>${escapeHtml(title)}</title>
|
|
5720
|
+
<link rel="stylesheet" href="${escapeHtml(cssUrl)}" />
|
|
5721
|
+
</head>
|
|
5722
|
+
<body>
|
|
5723
|
+
<div id="swagger-ui"></div>
|
|
5724
|
+
<script src="${escapeHtml(bundleUrl)}"></script>
|
|
5725
|
+
<script>
|
|
5726
|
+
window.ui = SwaggerUIBundle({
|
|
5727
|
+
url: ${JSON.stringify(specPath)},
|
|
5728
|
+
dom_id: '#swagger-ui',
|
|
5729
|
+
deepLinking: true,
|
|
5730
|
+
presets: [SwaggerUIBundle.presets.apis],
|
|
5731
|
+
layout: 'BaseLayout',
|
|
5732
|
+
});
|
|
5733
|
+
</script>
|
|
5734
|
+
</body>
|
|
5735
|
+
</html>`;
|
|
5736
|
+
var getRelativeSpecPath = (docsPath, jsonPath) => {
|
|
5737
|
+
const docsDir = posix.dirname(docsPath.startsWith("/") ? docsPath : `/${docsPath}`);
|
|
5738
|
+
const normalizedJsonPath = jsonPath.startsWith("/") ? jsonPath : `/${jsonPath}`;
|
|
5739
|
+
return posix.relative(docsDir, normalizedJsonPath) || posix.basename(normalizedJsonPath);
|
|
5740
|
+
};
|
|
5741
|
+
function createOpenApiRouter(runtime, options = {}) {
|
|
5742
|
+
const router = express.Router();
|
|
5743
|
+
const jsonPath = options.jsonPath ?? "/openapi.json";
|
|
5744
|
+
const docsPath = options.docsPath ?? "/docs";
|
|
5745
|
+
const swaggerUiCssUrl = options.swaggerUiCssUrl ?? "https://unpkg.com/swagger-ui-dist@5/swagger-ui.css";
|
|
5746
|
+
const swaggerUiBundleUrl = options.swaggerUiBundleUrl ?? "https://unpkg.com/swagger-ui-dist@5/swagger-ui-bundle.js";
|
|
5747
|
+
const info = {
|
|
5748
|
+
title: options.title ?? "Access Router API",
|
|
5749
|
+
version: options.version ?? "0.0.0",
|
|
5750
|
+
description: options.description,
|
|
5751
|
+
servers: options.servers
|
|
5752
|
+
};
|
|
5753
|
+
router.get(jsonPath, (_req, res) => {
|
|
5754
|
+
res.json(runtime.getOpenApiSpec(info));
|
|
5755
|
+
});
|
|
5756
|
+
if (docsPath !== false) {
|
|
5757
|
+
router.get(docsPath, (_req, res) => {
|
|
5758
|
+
res.type("html").send(renderDocsHtml(getRelativeSpecPath(docsPath, jsonPath), info.title, swaggerUiCssUrl, swaggerUiBundleUrl));
|
|
5759
|
+
});
|
|
5760
|
+
}
|
|
5761
|
+
return router;
|
|
5762
|
+
}
|
|
5763
|
+
|
|
5764
|
+
// src/routers/index.ts
|
|
5164
5765
|
var hasRoutes = (input) => {
|
|
5165
5766
|
return typeof input === "object" && input !== null && "routes" in input;
|
|
5166
5767
|
};
|
|
@@ -5168,7 +5769,7 @@ var resolveRoutes = (input) => {
|
|
|
5168
5769
|
return hasRoutes(input) ? input.routes : input;
|
|
5169
5770
|
};
|
|
5170
5771
|
function combineRoutes(...inputs) {
|
|
5171
|
-
const router =
|
|
5772
|
+
const router = express2.Router();
|
|
5172
5773
|
inputs.forEach((input) => {
|
|
5173
5774
|
router.use(resolveRoutes(input));
|
|
5174
5775
|
});
|
|
@@ -5180,7 +5781,7 @@ var accessRouterResponseHandler = JsonRouter8.createHandler({
|
|
|
5180
5781
|
});
|
|
5181
5782
|
accessRouterResponseHandler.errorMessageProvider = function(error) {
|
|
5182
5783
|
const errorLike = error;
|
|
5183
|
-
|
|
5784
|
+
logger.error(error);
|
|
5184
5785
|
return errorLike.message || errorLike._message || String(error);
|
|
5185
5786
|
};
|
|
5186
5787
|
|
|
@@ -5207,12 +5808,15 @@ function createRuntimeApi(runtime) {
|
|
|
5207
5808
|
wtt2.createDataRouter = function(dataName, options) {
|
|
5208
5809
|
return new DataRouter(dataName, options, runtime);
|
|
5209
5810
|
};
|
|
5811
|
+
wtt2.createOpenApiRouter = function(options) {
|
|
5812
|
+
return createOpenApiRouter(runtime, options);
|
|
5813
|
+
};
|
|
5210
5814
|
wtt2.combineRoutes = combineRoutes;
|
|
5211
5815
|
wtt2.set = function(keyOrOptions, value) {
|
|
5212
5816
|
if (arguments.length === 2 && isString12(keyOrOptions)) {
|
|
5213
5817
|
return runtime.setGlobalOption(keyOrOptions, value);
|
|
5214
5818
|
}
|
|
5215
|
-
if (arguments.length === 1 &&
|
|
5819
|
+
if (arguments.length === 1 && isPlainObject14(keyOrOptions)) {
|
|
5216
5820
|
return runtime.setGlobalOptions(keyOrOptions);
|
|
5217
5821
|
}
|
|
5218
5822
|
};
|
|
@@ -5249,6 +5853,7 @@ export {
|
|
|
5249
5853
|
acl,
|
|
5250
5854
|
combineRoutes,
|
|
5251
5855
|
createAccessRuntime,
|
|
5856
|
+
createOpenApiRouter,
|
|
5252
5857
|
index_default as default,
|
|
5253
5858
|
defineRequestSchema,
|
|
5254
5859
|
fromAjv,
|