@web-ts-toolkit/access-router 0.32.0 → 0.33.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 +101 -37
- package/advanced.d.mts +12 -1444
- package/advanced.d.ts +12 -1444
- package/advanced.js +1167 -269
- package/advanced.mjs +1178 -269
- package/index.d.mts +93 -1264
- package/index.d.ts +93 -1264
- package/index.js +1465 -489
- package/index.mjs +1354 -388
- package/llms.txt +34 -11
- package/package.json +10 -5
- package/parsers-D9B9dS0p.d.mts +1702 -0
- package/parsers-D9B9dS0p.d.ts +1702 -0
- package/processors.d.mts +72 -1
- package/processors.d.ts +72 -1
- package/processors.js +61 -13
- package/processors.mjs +62 -14
package/advanced.mjs
CHANGED
|
@@ -43,89 +43,982 @@ var FilterOperator = /* @__PURE__ */ ((FilterOperator2) => {
|
|
|
43
43
|
// src/validation/parsers.ts
|
|
44
44
|
import JsonRouter from "@web-ts-toolkit/express-json-router";
|
|
45
45
|
|
|
46
|
-
// src/
|
|
46
|
+
// src/runtime.ts
|
|
47
|
+
import mongoose from "mongoose";
|
|
48
|
+
import mschema2Jsonschema from "mongoose-schema-jsonschema";
|
|
49
|
+
import {
|
|
50
|
+
addLeadingSlash,
|
|
51
|
+
forEach as forEach2,
|
|
52
|
+
get as get2,
|
|
53
|
+
isArray as isArray4,
|
|
54
|
+
isBoolean,
|
|
55
|
+
isFunction,
|
|
56
|
+
isNil,
|
|
57
|
+
isPlainObject as isPlainObject7,
|
|
58
|
+
isString as isString2,
|
|
59
|
+
keys
|
|
60
|
+
} from "@web-ts-toolkit/utils";
|
|
61
|
+
|
|
62
|
+
// src/helpers/index.ts
|
|
63
|
+
import { forEach, isArray, isEmpty, isObject, isPlainObject as isPlainObject2, isString, mapValuesAsync } from "@web-ts-toolkit/utils";
|
|
64
|
+
|
|
65
|
+
// src/lib.ts
|
|
66
|
+
import { Document, Schema } from "mongoose";
|
|
67
|
+
import { isPlainObject } from "@web-ts-toolkit/utils";
|
|
68
|
+
var isSchema = (val) => val instanceof Schema;
|
|
69
|
+
var isObjectIdType = (val) => val === "ObjectId" || val === Schema.Types.ObjectId;
|
|
70
|
+
var isReference = (val) => isPlainObject(val) && !!val.ref && isObjectIdType(val.type);
|
|
71
|
+
|
|
72
|
+
// src/helpers/index.ts
|
|
73
|
+
function recurseObject(obj) {
|
|
74
|
+
if (isSchema(obj)) {
|
|
75
|
+
return buildRefs(obj.tree);
|
|
76
|
+
}
|
|
77
|
+
if (!isObject(obj)) return null;
|
|
78
|
+
if (isReference(obj)) {
|
|
79
|
+
return obj.ref;
|
|
80
|
+
}
|
|
81
|
+
let ret = null;
|
|
82
|
+
forEach(obj, (val) => {
|
|
83
|
+
ret = recurseObject(val);
|
|
84
|
+
if (!isEmpty(ret)) {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return ret;
|
|
89
|
+
}
|
|
90
|
+
function buildRefs(schema) {
|
|
91
|
+
if (!isObject(schema)) return {};
|
|
92
|
+
const references = {};
|
|
93
|
+
forEach(schema, (val, key) => {
|
|
94
|
+
const paths = recurseObject(val);
|
|
95
|
+
if (!isEmpty(paths)) {
|
|
96
|
+
references[key] = paths;
|
|
97
|
+
}
|
|
98
|
+
const target = isObject(val) && "type" in val ? val.type ?? val : val;
|
|
99
|
+
if (isArray(target) && target.length > 0) {
|
|
100
|
+
if (isSchema(target[0]) || isPlainObject2(target[0])) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
return references;
|
|
106
|
+
}
|
|
107
|
+
function buildSubPaths(schema) {
|
|
108
|
+
if (!isObject(schema)) return [];
|
|
109
|
+
const subPaths = [];
|
|
110
|
+
forEach(schema, (val, key) => {
|
|
111
|
+
const target = isObject(val) && "type" in val ? val.type ?? val : val;
|
|
112
|
+
if (isArray(target) && target.length > 0) {
|
|
113
|
+
if (isSchema(target[0]) || isPlainObject2(target[0]) && !isReference(target[0])) {
|
|
114
|
+
subPaths.push(key);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
return subPaths;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// src/openapi/build-spec.ts
|
|
122
|
+
import { isArray as isArray2, isPlainObject as isPlainObject4 } from "@web-ts-toolkit/utils";
|
|
123
|
+
|
|
124
|
+
// src/openapi/responses.ts
|
|
125
|
+
var json = (schema) => ({
|
|
126
|
+
content: {
|
|
127
|
+
"application/json": {
|
|
128
|
+
schema
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
var problemJson = {
|
|
133
|
+
content: {
|
|
134
|
+
"application/problem+json": {
|
|
135
|
+
schema: {
|
|
136
|
+
type: "object",
|
|
137
|
+
properties: {
|
|
138
|
+
type: { type: "string" },
|
|
139
|
+
title: { type: "string" },
|
|
140
|
+
status: { type: "number" },
|
|
141
|
+
detail: { type: "string" },
|
|
142
|
+
errors: { type: "array", items: {} }
|
|
143
|
+
},
|
|
144
|
+
additionalProperties: true
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
};
|
|
149
|
+
var genericDataSchema = { type: "object", additionalProperties: true };
|
|
150
|
+
var genericListSchema = { type: "array", items: genericDataSchema };
|
|
151
|
+
var openApiResponses = {
|
|
152
|
+
single(description = "Success") {
|
|
153
|
+
return {
|
|
154
|
+
200: { description, ...json(genericDataSchema) },
|
|
155
|
+
400: { description: "Bad Request", ...problemJson },
|
|
156
|
+
401: { description: "Unauthorized", ...problemJson },
|
|
157
|
+
404: { description: "Not Found", ...problemJson }
|
|
158
|
+
};
|
|
159
|
+
},
|
|
160
|
+
list(description = "Success") {
|
|
161
|
+
return {
|
|
162
|
+
200: { description, ...json(genericListSchema) },
|
|
163
|
+
400: { description: "Bad Request", ...problemJson },
|
|
164
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
165
|
+
};
|
|
166
|
+
},
|
|
167
|
+
create(description = "Created") {
|
|
168
|
+
return {
|
|
169
|
+
201: { description, ...json(genericDataSchema) },
|
|
170
|
+
400: { description: "Bad Request", ...problemJson },
|
|
171
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
172
|
+
};
|
|
173
|
+
},
|
|
174
|
+
delete(description = "Deleted") {
|
|
175
|
+
return {
|
|
176
|
+
200: { description, ...json(genericDataSchema) },
|
|
177
|
+
400: { description: "Bad Request", ...problemJson },
|
|
178
|
+
401: { description: "Unauthorized", ...problemJson },
|
|
179
|
+
404: { description: "Not Found", ...problemJson }
|
|
180
|
+
};
|
|
181
|
+
},
|
|
182
|
+
batch(description = "Success") {
|
|
183
|
+
return {
|
|
184
|
+
200: { description, ...json(genericListSchema) },
|
|
185
|
+
400: { description: "Bad Request", ...problemJson },
|
|
186
|
+
401: { description: "Unauthorized", ...problemJson }
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
// src/openapi/schemas.ts
|
|
47
192
|
import { z } from "zod";
|
|
48
|
-
|
|
49
|
-
var
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
193
|
+
import { isPlainObject as isPlainObject3 } from "@web-ts-toolkit/utils";
|
|
194
|
+
var fallbackObjectSchema = { type: "object", additionalProperties: true };
|
|
195
|
+
function isOpenApiSchemaPatch(source) {
|
|
196
|
+
return isPlainObject3(source) && source.kind === "objectProperties";
|
|
197
|
+
}
|
|
198
|
+
function isOpenApiSchemaResolver(source) {
|
|
199
|
+
return isPlainObject3(source) && source.kind === "schemaResolver" && typeof source.resolve === "function";
|
|
200
|
+
}
|
|
201
|
+
function isJsonSchemaLike(source) {
|
|
202
|
+
return isPlainObject3(source) && ("type" in source || "properties" in source || "$ref" in source || "anyOf" in source);
|
|
203
|
+
}
|
|
204
|
+
function hasOpenApiSchema(source) {
|
|
205
|
+
return isPlainObject3(source) && isJsonSchemaLike(source.openapi);
|
|
206
|
+
}
|
|
207
|
+
function toOpenApiSchema(source) {
|
|
208
|
+
if (!source) return void 0;
|
|
209
|
+
const resolvedSource = isOpenApiSchemaResolver(source) ? source.resolve() : source;
|
|
210
|
+
if (!resolvedSource) return void 0;
|
|
211
|
+
if (isOpenApiSchemaPatch(resolvedSource)) {
|
|
212
|
+
const schema = toOpenApiSchema(resolvedSource.source) ?? { ...fallbackObjectSchema };
|
|
213
|
+
const properties = isPlainObject3(schema.properties) ? { ...schema.properties } : {};
|
|
214
|
+
for (const [key, value] of Object.entries(resolvedSource.properties)) {
|
|
215
|
+
properties[key] = toOpenApiSchema(value) ?? fallbackObjectSchema;
|
|
216
|
+
}
|
|
217
|
+
return {
|
|
218
|
+
...schema,
|
|
219
|
+
type: schema.type ?? "object",
|
|
220
|
+
properties
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
if (hasOpenApiSchema(resolvedSource)) {
|
|
224
|
+
return resolvedSource.openapi;
|
|
225
|
+
}
|
|
226
|
+
if (isJsonSchemaLike(resolvedSource)) {
|
|
227
|
+
return resolvedSource;
|
|
228
|
+
}
|
|
229
|
+
try {
|
|
230
|
+
return z.toJSONSchema(resolvedSource);
|
|
231
|
+
} catch {
|
|
232
|
+
return fallbackObjectSchema;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// src/openapi/build-spec.ts
|
|
237
|
+
var openApiMediaType = "application/json";
|
|
238
|
+
var normalizePath = (path) => {
|
|
239
|
+
if (!path) return "/";
|
|
240
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
241
|
+
};
|
|
242
|
+
var toOpenApiPath = (path) => normalizePath(path).replace(/:([A-Za-z0-9_]+)/g, "{$1}");
|
|
243
|
+
var schemaToQueryParameters = (schema) => {
|
|
244
|
+
const jsonSchema = toOpenApiSchema(schema);
|
|
245
|
+
if (!jsonSchema || jsonSchema.type !== "object") return [];
|
|
246
|
+
const properties = isPlainObject4(jsonSchema.properties) ? jsonSchema.properties : {};
|
|
247
|
+
const required = new Set(
|
|
248
|
+
isArray2(jsonSchema.required) ? jsonSchema.required.filter((item) => typeof item === "string") : []
|
|
249
|
+
);
|
|
250
|
+
return Object.entries(properties).map(([name, value]) => ({
|
|
251
|
+
name,
|
|
252
|
+
in: "query",
|
|
253
|
+
required: required.has(name),
|
|
254
|
+
schema: value
|
|
255
|
+
}));
|
|
256
|
+
};
|
|
257
|
+
var schemaToPathParameters = (path, pathParams) => {
|
|
258
|
+
const names = [...toOpenApiPath(path).matchAll(/\{([^}]+)\}/g)].map((item) => item[1]);
|
|
259
|
+
return names.map((name) => ({
|
|
260
|
+
name,
|
|
261
|
+
in: "path",
|
|
262
|
+
required: true,
|
|
263
|
+
schema: (pathParams && name in pathParams ? toOpenApiSchema(pathParams[name]) : void 0) ?? { type: "string" }
|
|
264
|
+
}));
|
|
265
|
+
};
|
|
266
|
+
var getDefaultResponses = (route) => {
|
|
267
|
+
if (route.operationId === "root.query") return openApiResponses.batch();
|
|
268
|
+
if (route.method === "delete") return openApiResponses.delete();
|
|
269
|
+
if (route.operationId?.toLowerCase().includes("create")) return openApiResponses.create();
|
|
270
|
+
if (route.operationId?.toLowerCase().includes("list")) return openApiResponses.list();
|
|
271
|
+
if (route.operationId?.toLowerCase().includes("distinct")) return openApiResponses.list();
|
|
272
|
+
return openApiResponses.single();
|
|
273
|
+
};
|
|
274
|
+
var buildOperation = (route) => {
|
|
275
|
+
const queryParameters = schemaToQueryParameters(route.query);
|
|
276
|
+
const pathParameters = schemaToPathParameters(route.path, route.pathParams);
|
|
277
|
+
const bodySchema = toOpenApiSchema(route.body);
|
|
278
|
+
const responses = route.responses ?? getDefaultResponses(route);
|
|
279
|
+
const operation = {
|
|
280
|
+
operationId: route.operationId,
|
|
281
|
+
summary: route.summary,
|
|
282
|
+
description: route.description,
|
|
283
|
+
tags: route.tags,
|
|
284
|
+
deprecated: route.deprecated,
|
|
285
|
+
responses
|
|
286
|
+
};
|
|
287
|
+
const parameters = [...pathParameters, ...queryParameters];
|
|
288
|
+
if (parameters.length) {
|
|
289
|
+
operation.parameters = parameters;
|
|
290
|
+
}
|
|
291
|
+
if (bodySchema) {
|
|
292
|
+
operation.requestBody = {
|
|
293
|
+
required: true,
|
|
294
|
+
content: {
|
|
295
|
+
[openApiMediaType]: {
|
|
296
|
+
schema: bodySchema
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
}
|
|
301
|
+
if (route.acl) {
|
|
302
|
+
operation["x-access-router-acl"] = route.acl;
|
|
303
|
+
}
|
|
304
|
+
return operation;
|
|
305
|
+
};
|
|
306
|
+
function buildOpenApiSpec(routes, options) {
|
|
307
|
+
const paths = {};
|
|
308
|
+
const { servers, ...info } = options;
|
|
309
|
+
for (const route of routes) {
|
|
310
|
+
const path = toOpenApiPath(route.path);
|
|
311
|
+
if (!paths[path]) {
|
|
312
|
+
paths[path] = {};
|
|
313
|
+
}
|
|
314
|
+
paths[path][route.method] = buildOperation(route);
|
|
315
|
+
}
|
|
316
|
+
return {
|
|
317
|
+
openapi: "3.1.0",
|
|
318
|
+
info,
|
|
319
|
+
servers,
|
|
320
|
+
paths
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/openapi/errors.ts
|
|
325
|
+
var OpenApiCollisionError = class extends Error {
|
|
326
|
+
constructor(message, details) {
|
|
327
|
+
super(message);
|
|
328
|
+
this.name = "OpenApiCollisionError";
|
|
329
|
+
this.collisionKind = details.collisionKind;
|
|
330
|
+
this.method = details.method;
|
|
331
|
+
this.path = details.path;
|
|
332
|
+
this.operationId = details.operationId;
|
|
333
|
+
this.existing = details.existing;
|
|
334
|
+
this.incoming = details.incoming;
|
|
335
|
+
}
|
|
336
|
+
};
|
|
337
|
+
|
|
338
|
+
// src/openapi/registry.ts
|
|
339
|
+
var isPlainObject5 = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
340
|
+
var stableKey = (value) => {
|
|
341
|
+
if (value === null || typeof value === "undefined") return "null";
|
|
342
|
+
if (typeof value === "function") return "[Function]";
|
|
343
|
+
if (typeof value !== "object") return JSON.stringify(value);
|
|
344
|
+
if (Array.isArray(value)) {
|
|
345
|
+
return `[${value.map(stableKey).join(",")}]`;
|
|
346
|
+
}
|
|
347
|
+
const obj = value;
|
|
348
|
+
return `{${Object.keys(obj).sort().map((k) => `${JSON.stringify(k)}:${stableKey(obj[k])}`).join(",")}}`;
|
|
349
|
+
};
|
|
350
|
+
var descriptorsEqual = (a, b) => {
|
|
351
|
+
return a.method === b.method && a.path === b.path && (a.operationId ?? "") === (b.operationId ?? "") && (a.acl ?? "") === (b.acl ?? "") && stableKey(a.query) === stableKey(b.query) && stableKey(a.body) === stableKey(b.body) && stableKey(a.pathParams) === stableKey(b.pathParams) && stableKey(a.responses) === stableKey(b.responses) && stableKey(a.tags) === stableKey(b.tags) && (a.summary ?? "") === (b.summary ?? "") && (a.description ?? "") === (b.description ?? "") && Boolean(a.deprecated) === Boolean(b.deprecated);
|
|
352
|
+
};
|
|
353
|
+
var OpenApiRegistry = class {
|
|
354
|
+
constructor(options = {}) {
|
|
355
|
+
this.routes = [];
|
|
356
|
+
this.options = {
|
|
357
|
+
rejectConflicts: options.rejectConflicts ?? true,
|
|
358
|
+
rejectDuplicateOperationIds: options.rejectDuplicateOperationIds ?? true
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
register(route) {
|
|
362
|
+
const existingIndex = this.routes.findIndex((item) => item.method === route.method && item.path === route.path);
|
|
363
|
+
if (existingIndex === -1) {
|
|
364
|
+
this.assertOperationIdAvailable(route);
|
|
365
|
+
this.routes.push(route);
|
|
366
|
+
return;
|
|
367
|
+
}
|
|
368
|
+
const existing = this.routes[existingIndex];
|
|
369
|
+
if (route.allowReplace) {
|
|
370
|
+
this.assertOperationIdAvailable(route, existing);
|
|
371
|
+
this.routes[existingIndex] = route;
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
if (descriptorsEqual(existing, route) && (route.idempotent || isPlainObject5(existing) && existing.idempotent)) {
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (this.options.rejectConflicts) {
|
|
378
|
+
throw new OpenApiCollisionError(
|
|
379
|
+
`OpenAPI route collision: ${route.method.toUpperCase()} ${route.path} is already registered` + (existing.operationId ? ` as operationId="${existing.operationId}"` : "") + (route.operationId ? `; new registration uses operationId="${route.operationId}"` : "") + ". Set allowReplace:true on the new descriptor to override, or fix the duplicate registration.",
|
|
380
|
+
{
|
|
381
|
+
collisionKind: "path",
|
|
382
|
+
method: route.method,
|
|
383
|
+
path: route.path,
|
|
384
|
+
existing,
|
|
385
|
+
incoming: route
|
|
386
|
+
}
|
|
387
|
+
);
|
|
388
|
+
}
|
|
389
|
+
this.routes[existingIndex] = route;
|
|
390
|
+
}
|
|
391
|
+
assertOperationIdAvailable(route, replacing) {
|
|
392
|
+
if (!this.options.rejectDuplicateOperationIds) return;
|
|
393
|
+
if (!route.operationId) return;
|
|
394
|
+
const clash = this.routes.find(
|
|
395
|
+
(item) => item.operationId && item.operationId === route.operationId && item !== replacing
|
|
396
|
+
);
|
|
397
|
+
if (clash) {
|
|
398
|
+
if (route.idempotent && clash.idempotent) return;
|
|
399
|
+
throw new OpenApiCollisionError(
|
|
400
|
+
`OpenAPI operationId collision: "${route.operationId}" is already bound to ${clash.method.toUpperCase()} ${clash.path}. Each operationId must be unique across the spec.`,
|
|
401
|
+
{
|
|
402
|
+
collisionKind: "operationId",
|
|
403
|
+
operationId: route.operationId,
|
|
404
|
+
existing: clash,
|
|
405
|
+
incoming: route
|
|
406
|
+
}
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
getRoutes() {
|
|
411
|
+
return [...this.routes];
|
|
412
|
+
}
|
|
413
|
+
clear() {
|
|
414
|
+
this.routes.length = 0;
|
|
415
|
+
}
|
|
416
|
+
setStrictMode(enabled) {
|
|
417
|
+
this.options.rejectConflicts = enabled;
|
|
418
|
+
this.options.rejectDuplicateOperationIds = enabled;
|
|
419
|
+
}
|
|
420
|
+
getSpec(info) {
|
|
421
|
+
return buildOpenApiSpec(this.routes, info);
|
|
422
|
+
}
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
// src/logger-default.ts
|
|
426
|
+
import util from "util";
|
|
427
|
+
import { createLogger, format, transports } from "winston";
|
|
428
|
+
var colorizer = format.colorize();
|
|
429
|
+
var defaultLogLevel = process.env.WTT_LOG_LEVEL || "silent";
|
|
430
|
+
var inspectValue = (value) => {
|
|
431
|
+
return typeof value === "string" ? value : util.inspect(value, { depth: 5, colors: false });
|
|
432
|
+
};
|
|
433
|
+
var defaultLogger = createLogger({
|
|
434
|
+
level: defaultLogLevel,
|
|
435
|
+
format: format.combine(
|
|
436
|
+
format.errors({ stack: true }),
|
|
437
|
+
format.splat(),
|
|
438
|
+
format.label({ label: "[WTT]" }),
|
|
439
|
+
format.timestamp(),
|
|
440
|
+
format.printf(({ level, label, message, timestamp, stack, ...meta }) => {
|
|
441
|
+
const formattedLabel = colorizer.colorize(level, String(label));
|
|
442
|
+
const formattedLevel = colorizer.colorize(level, `[${String(level).toUpperCase()}]`);
|
|
443
|
+
const formattedMessage = colorizer.colorize(level, inspectValue(stack ?? message));
|
|
444
|
+
const formattedMeta = Object.keys(meta).length > 0 ? ` ${inspectValue(meta)}` : "";
|
|
445
|
+
return `${formattedLabel} ${timestamp} ${formattedLevel} ${formattedMessage}${formattedMeta}`;
|
|
446
|
+
})
|
|
447
|
+
),
|
|
448
|
+
transports: [new transports.Console()]
|
|
449
|
+
});
|
|
450
|
+
|
|
451
|
+
// src/options/manager.ts
|
|
452
|
+
import { assign, get, set } from "@web-ts-toolkit/utils";
|
|
453
|
+
var getNestedOption = (manager, key, defaultValue) => {
|
|
454
|
+
const keys2 = String(key).split(".");
|
|
455
|
+
if (keys2.length === 1) {
|
|
456
|
+
return manager.get(key, defaultValue);
|
|
457
|
+
}
|
|
458
|
+
let option = manager.get(key, void 0);
|
|
459
|
+
if (option !== void 0) {
|
|
460
|
+
return option;
|
|
461
|
+
}
|
|
462
|
+
const parentKey = keys2.slice(0, -1).join(".");
|
|
463
|
+
option = manager.get(`${parentKey}.default`, void 0);
|
|
464
|
+
if (option === void 0) {
|
|
465
|
+
option = manager.get(parentKey, defaultValue);
|
|
466
|
+
}
|
|
467
|
+
return option;
|
|
468
|
+
};
|
|
469
|
+
var OptionsManager = class {
|
|
470
|
+
constructor(defaultOptions) {
|
|
471
|
+
this.defaultOptions = defaultOptions;
|
|
472
|
+
this.listeners = {};
|
|
473
|
+
const _this = this;
|
|
474
|
+
this.currentOptions = new Proxy({}, {
|
|
475
|
+
set(target, key, value) {
|
|
476
|
+
const keystr = String(key);
|
|
477
|
+
const oldvalue = target[keystr];
|
|
478
|
+
target[keystr] = value;
|
|
479
|
+
_this.listeners[keystr] && _this.listeners[keystr].call(_this, value, keystr, target, oldvalue);
|
|
480
|
+
return true;
|
|
481
|
+
}
|
|
482
|
+
});
|
|
483
|
+
}
|
|
484
|
+
build() {
|
|
485
|
+
this.assign(this.defaultOptions);
|
|
486
|
+
return this;
|
|
487
|
+
}
|
|
488
|
+
get(key, defaultValue) {
|
|
489
|
+
return get(this.currentOptions, key, defaultValue);
|
|
490
|
+
}
|
|
491
|
+
set(key, value) {
|
|
492
|
+
set(this.currentOptions, key, value);
|
|
493
|
+
}
|
|
494
|
+
fetch() {
|
|
495
|
+
return { ...this.currentOptions };
|
|
496
|
+
}
|
|
497
|
+
assign(options) {
|
|
498
|
+
assign(this.currentOptions, options);
|
|
499
|
+
}
|
|
500
|
+
onchange(key, func) {
|
|
501
|
+
set(this.listeners, key, func);
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
};
|
|
505
|
+
|
|
506
|
+
// src/request-complexity.ts
|
|
507
|
+
import { isArray as isArray3, isPlainObject as isPlainObject6 } from "@web-ts-toolkit/utils";
|
|
508
|
+
var defaultRequestComplexity = {
|
|
509
|
+
maxDepth: 8,
|
|
510
|
+
maxNodes: 500,
|
|
511
|
+
maxLogicalClauses: 50,
|
|
512
|
+
maxInValues: 100,
|
|
513
|
+
maxBulkItems: 100,
|
|
514
|
+
maxIncludeCount: 10,
|
|
515
|
+
maxSubQueryCount: 10,
|
|
516
|
+
maxBulkConcurrency: 10
|
|
517
|
+
};
|
|
518
|
+
var normalizePositiveInteger = (value, fallback) => {
|
|
519
|
+
return Number.isSafeInteger(value) && Number(value) > 0 ? Number(value) : fallback;
|
|
520
|
+
};
|
|
521
|
+
var resolveRequestComplexity = (options) => ({
|
|
522
|
+
maxDepth: normalizePositiveInteger(options?.maxDepth, defaultRequestComplexity.maxDepth),
|
|
523
|
+
maxNodes: normalizePositiveInteger(options?.maxNodes, defaultRequestComplexity.maxNodes),
|
|
524
|
+
maxLogicalClauses: normalizePositiveInteger(options?.maxLogicalClauses, defaultRequestComplexity.maxLogicalClauses),
|
|
525
|
+
maxInValues: normalizePositiveInteger(options?.maxInValues, defaultRequestComplexity.maxInValues),
|
|
526
|
+
maxBulkItems: normalizePositiveInteger(options?.maxBulkItems, defaultRequestComplexity.maxBulkItems),
|
|
527
|
+
maxIncludeCount: normalizePositiveInteger(options?.maxIncludeCount, defaultRequestComplexity.maxIncludeCount),
|
|
528
|
+
maxSubQueryCount: normalizePositiveInteger(options?.maxSubQueryCount, defaultRequestComplexity.maxSubQueryCount),
|
|
529
|
+
maxBulkConcurrency: normalizePositiveInteger(
|
|
530
|
+
options?.maxBulkConcurrency,
|
|
531
|
+
defaultRequestComplexity.maxBulkConcurrency
|
|
532
|
+
)
|
|
533
|
+
});
|
|
534
|
+
function validateRequestComplexity(value, options, scope = "request") {
|
|
535
|
+
const limits = resolveRequestComplexity(options);
|
|
536
|
+
const errors = [];
|
|
537
|
+
let nodes = 0;
|
|
538
|
+
let logicalClauses = 0;
|
|
539
|
+
let includeCount = 0;
|
|
540
|
+
let subQueryCount = 0;
|
|
541
|
+
const pointer = (path) => path.length === 0 ? "#" : `#/${path.join("/")}`;
|
|
542
|
+
const pushError = (detail, path) => {
|
|
543
|
+
if (errors.length === 0) {
|
|
544
|
+
errors.push({ detail, pointer: pointer(path) });
|
|
545
|
+
}
|
|
546
|
+
};
|
|
547
|
+
const visit = (current, path, depth, parentKey) => {
|
|
548
|
+
if (errors.length > 0) return;
|
|
549
|
+
nodes += 1;
|
|
550
|
+
if (nodes > limits.maxNodes) {
|
|
551
|
+
pushError(`Request exceeds maximum node budget of ${limits.maxNodes}`, path);
|
|
552
|
+
return;
|
|
553
|
+
}
|
|
554
|
+
if (depth > limits.maxDepth) {
|
|
555
|
+
pushError(`Request exceeds maximum depth of ${limits.maxDepth}`, path);
|
|
556
|
+
return;
|
|
557
|
+
}
|
|
558
|
+
if (isArray3(current)) {
|
|
559
|
+
if (parentKey === "$and" || parentKey === "$or" || parentKey === "$nor") {
|
|
560
|
+
logicalClauses += current.length;
|
|
561
|
+
if (logicalClauses > limits.maxLogicalClauses) {
|
|
562
|
+
pushError(`Filter exceeds maximum logical clause budget of ${limits.maxLogicalClauses}`, path);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
if (parentKey === "$in") {
|
|
567
|
+
if (current.length > limits.maxInValues) {
|
|
568
|
+
pushError(`Filter exceeds maximum $in values of ${limits.maxInValues}`, path);
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
for (let index = 0; index < current.length; index++) {
|
|
573
|
+
visit(current[index], path.concat(index), depth + 1, parentKey);
|
|
574
|
+
if (errors.length > 0) return;
|
|
575
|
+
}
|
|
576
|
+
return;
|
|
577
|
+
}
|
|
578
|
+
if (!isPlainObject6(current)) return;
|
|
579
|
+
for (const [key, child] of Object.entries(current)) {
|
|
580
|
+
if (key === "__proto__" || key === "prototype" || key === "constructor") {
|
|
581
|
+
pushError(`Unsupported key: ${key}`, path.concat(key));
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
if (scope === "request" && key === "include") {
|
|
585
|
+
includeCount += isArray3(child) ? child.length : 1;
|
|
586
|
+
if (includeCount > limits.maxIncludeCount) {
|
|
587
|
+
pushError(`Request exceeds maximum include count of ${limits.maxIncludeCount}`, path.concat(key));
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
if (key === "$$sq") {
|
|
592
|
+
subQueryCount += 1;
|
|
593
|
+
if (subQueryCount > limits.maxSubQueryCount) {
|
|
594
|
+
pushError(`Request exceeds maximum subquery count of ${limits.maxSubQueryCount}`, path.concat(key));
|
|
595
|
+
return;
|
|
596
|
+
}
|
|
597
|
+
visit(child, path.concat(key), depth + 1, key);
|
|
598
|
+
if (errors.length > 0) return;
|
|
599
|
+
continue;
|
|
600
|
+
}
|
|
601
|
+
visit(child, path.concat(key), depth + 1, key);
|
|
602
|
+
if (errors.length > 0) return;
|
|
603
|
+
}
|
|
604
|
+
};
|
|
605
|
+
visit(value, [], 0);
|
|
606
|
+
return errors;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
// src/runtime.ts
|
|
610
|
+
var mongooseJsonSchemaInitialized = false;
|
|
611
|
+
var ensureMongooseJsonSchemaInitialized = () => {
|
|
612
|
+
if (mongooseJsonSchemaInitialized) return;
|
|
613
|
+
mschema2Jsonschema(mongoose);
|
|
614
|
+
mongooseJsonSchemaInitialized = true;
|
|
615
|
+
};
|
|
616
|
+
var pluralize = mongoose.pluralize();
|
|
617
|
+
var FIELD_ACCESS_KEYS = ["list", "create", "read", "update"];
|
|
618
|
+
var defaultModelOptions = {
|
|
619
|
+
basePath: null,
|
|
620
|
+
alwaysSelectFields: []
|
|
621
|
+
};
|
|
622
|
+
var defaultDataOptions = {
|
|
623
|
+
basePath: null,
|
|
624
|
+
parentPath: "/",
|
|
625
|
+
queryRouteSegment: "__query"
|
|
626
|
+
};
|
|
627
|
+
var normalizeBasePath = (name, value) => {
|
|
628
|
+
if (isNil(value)) {
|
|
629
|
+
return `/${pluralize(name)}`;
|
|
630
|
+
}
|
|
631
|
+
return isString2(value) ? addLeadingSlash(value) : "";
|
|
632
|
+
};
|
|
633
|
+
var hasModelPermission = (value, modelPermissionPrefix) => {
|
|
634
|
+
if (!modelPermissionPrefix) {
|
|
635
|
+
return true;
|
|
636
|
+
}
|
|
637
|
+
if (isString2(value)) {
|
|
638
|
+
return value.trim().split(" ").some((item) => item.startsWith(modelPermissionPrefix));
|
|
639
|
+
}
|
|
640
|
+
if (isArray4(value)) {
|
|
641
|
+
return value.some((item) => {
|
|
642
|
+
if (isString2(item) || isArray4(item)) {
|
|
643
|
+
return hasModelPermission(item, modelPermissionPrefix);
|
|
644
|
+
}
|
|
645
|
+
return true;
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
return isFunction(value);
|
|
649
|
+
};
|
|
650
|
+
var classifyPermissionSchema = (permissionSchema, modelPermissionPrefix) => {
|
|
651
|
+
const schemaKeys = Object.keys(permissionSchema);
|
|
652
|
+
const globalPermissionKeys = {};
|
|
653
|
+
const modelPermissionKeys = {};
|
|
654
|
+
forEach2(schemaKeys, (schemaKey) => {
|
|
655
|
+
const schemaRule = permissionSchema[schemaKey];
|
|
656
|
+
const ruleEntries = isPlainObject7(schemaRule) ? Object.entries(schemaRule) : FIELD_ACCESS_KEYS.map((accessKey) => [accessKey, schemaRule]);
|
|
657
|
+
for (let x = 0; x < ruleEntries.length; x++) {
|
|
658
|
+
const [accessKey, value] = ruleEntries[x];
|
|
659
|
+
if (!isArray4(globalPermissionKeys[accessKey])) {
|
|
660
|
+
globalPermissionKeys[accessKey] = [];
|
|
661
|
+
}
|
|
662
|
+
if (!isArray4(modelPermissionKeys[accessKey])) {
|
|
663
|
+
modelPermissionKeys[accessKey] = [];
|
|
664
|
+
}
|
|
665
|
+
if (isBoolean(value)) {
|
|
666
|
+
globalPermissionKeys[accessKey].push(schemaKey);
|
|
667
|
+
return;
|
|
668
|
+
}
|
|
669
|
+
if (hasModelPermission(value, modelPermissionPrefix)) {
|
|
670
|
+
modelPermissionKeys[accessKey].push(schemaKey);
|
|
671
|
+
return;
|
|
672
|
+
}
|
|
673
|
+
globalPermissionKeys[accessKey].push(schemaKey);
|
|
674
|
+
}
|
|
675
|
+
});
|
|
676
|
+
return {
|
|
677
|
+
schemaKeys,
|
|
678
|
+
globalPermissionKeys,
|
|
679
|
+
modelPermissionKeys
|
|
680
|
+
};
|
|
681
|
+
};
|
|
682
|
+
var AccessRuntime = class {
|
|
683
|
+
constructor() {
|
|
684
|
+
this.globalOptions = new OptionsManager({
|
|
685
|
+
requestPermissionField: "_permissions",
|
|
686
|
+
globalPermissions: () => ({}),
|
|
687
|
+
logger: defaultLogger,
|
|
688
|
+
requestComplexity: defaultRequestComplexity
|
|
689
|
+
}).build();
|
|
690
|
+
this.defaultModelOptions = new OptionsManager({
|
|
691
|
+
listHardLimit: 1e3,
|
|
692
|
+
documentPermissionField: "_permissions",
|
|
693
|
+
idParam: "id",
|
|
694
|
+
idField: "_id",
|
|
695
|
+
parentPath: "/",
|
|
696
|
+
queryRouteSegment: "__query",
|
|
697
|
+
mutationRouteSegment: "__mutation",
|
|
698
|
+
operationAccess: false,
|
|
699
|
+
modelPermissionPrefix: ""
|
|
700
|
+
}).build();
|
|
701
|
+
this.modelOptions = {};
|
|
702
|
+
this.modelJsonSchemas = {};
|
|
703
|
+
this.dataOptions = {};
|
|
704
|
+
this.modelRefs = {};
|
|
705
|
+
this.modelSubs = {};
|
|
706
|
+
this.modelAtts = {};
|
|
707
|
+
this.modelInstances = {};
|
|
708
|
+
this.openApiRegistry = new OpenApiRegistry();
|
|
709
|
+
ensureMongooseJsonSchemaInitialized();
|
|
710
|
+
}
|
|
711
|
+
registerModelInstance(modelName, model) {
|
|
712
|
+
if (!modelName || typeof modelName !== "string") {
|
|
713
|
+
throw new TypeError(`registerModelInstance: modelName must be a non-empty string, received ${typeof modelName}`);
|
|
714
|
+
}
|
|
715
|
+
const existing = this.modelInstances[modelName];
|
|
716
|
+
if (existing && existing !== model) {
|
|
717
|
+
throw new Error(
|
|
718
|
+
`Runtime model registry conflict: model "${modelName}" is already registered to a different mongoose.Model instance on this runtime. Use a distinct model name or a separate runtime.`
|
|
719
|
+
);
|
|
720
|
+
}
|
|
721
|
+
this.modelInstances[modelName] = model;
|
|
722
|
+
}
|
|
723
|
+
hasModelInstance(modelName) {
|
|
724
|
+
return modelName in this.modelInstances;
|
|
725
|
+
}
|
|
726
|
+
getModelInstance(modelName) {
|
|
727
|
+
const registered = this.modelInstances[modelName];
|
|
728
|
+
if (registered) return registered;
|
|
729
|
+
const global = mongoose.models[modelName];
|
|
730
|
+
return global ?? null;
|
|
731
|
+
}
|
|
732
|
+
registerOpenApiRoute(route) {
|
|
733
|
+
this.openApiRegistry.register(route);
|
|
734
|
+
}
|
|
735
|
+
/**
|
|
736
|
+
* Enable strict OpenAPI collision detection for the remainder of this
|
|
737
|
+
* runtime's lifetime. After this call, conflicting method/path
|
|
738
|
+
* registrations and duplicate operationIds throw {@link OpenApiCollisionError}
|
|
739
|
+
* instead of silently replacing. Existing already-registered routes are
|
|
740
|
+
* not retroactively re-validated.
|
|
741
|
+
*/
|
|
742
|
+
enableOpenApiCollisionDetection() {
|
|
743
|
+
this.openApiRegistry.setStrictMode(true);
|
|
744
|
+
}
|
|
745
|
+
getOpenApiRoutes() {
|
|
746
|
+
return this.openApiRegistry.getRoutes();
|
|
747
|
+
}
|
|
748
|
+
clearOpenApiRoutes() {
|
|
749
|
+
this.openApiRegistry.clear();
|
|
750
|
+
}
|
|
751
|
+
getOpenApiSpec(info) {
|
|
752
|
+
return this.openApiRegistry.getSpec(info);
|
|
753
|
+
}
|
|
754
|
+
setGlobalOptions(options) {
|
|
755
|
+
this.globalOptions.assign(options);
|
|
756
|
+
}
|
|
757
|
+
setGlobalOption(key, value) {
|
|
758
|
+
this.globalOptions.set(key, value);
|
|
759
|
+
}
|
|
760
|
+
getGlobalOptions() {
|
|
761
|
+
return this.globalOptions.fetch();
|
|
762
|
+
}
|
|
763
|
+
getGlobalOption(key, defaultValue) {
|
|
764
|
+
return this.globalOptions.get(key, defaultValue);
|
|
765
|
+
}
|
|
766
|
+
setDefaultModelOptions(options) {
|
|
767
|
+
this.defaultModelOptions.assign(options);
|
|
768
|
+
}
|
|
769
|
+
setDefaultModelOption(key, value) {
|
|
770
|
+
this.defaultModelOptions.set(key, value);
|
|
771
|
+
}
|
|
772
|
+
getDefaultModelOptions() {
|
|
773
|
+
return this.defaultModelOptions.fetch();
|
|
774
|
+
}
|
|
775
|
+
getDefaultModelOption(key, defaultValue) {
|
|
776
|
+
return this.defaultModelOptions.get(key, defaultValue);
|
|
777
|
+
}
|
|
778
|
+
createModelOptions(modelName) {
|
|
779
|
+
const model = this.getModelInstance(modelName) ?? mongoose.model(modelName);
|
|
780
|
+
const manager = new OptionsManager({
|
|
781
|
+
...defaultModelOptions,
|
|
782
|
+
modelName
|
|
783
|
+
});
|
|
784
|
+
manager.onchange("permissionSchema", function(newval, key, target) {
|
|
785
|
+
const permissionSchema = newval ?? {};
|
|
786
|
+
const { schemaKeys, globalPermissionKeys, modelPermissionKeys } = classifyPermissionSchema(
|
|
787
|
+
permissionSchema,
|
|
788
|
+
target.modelPermissionPrefix ?? ""
|
|
789
|
+
);
|
|
790
|
+
target._permissionSchemaKeys = schemaKeys;
|
|
791
|
+
target._globalPermissionKeys = globalPermissionKeys;
|
|
792
|
+
target._modelPermissionKeys = modelPermissionKeys;
|
|
793
|
+
}).onchange("basePath", function(newval, key, target) {
|
|
794
|
+
target[key] = normalizeBasePath(
|
|
795
|
+
modelName,
|
|
796
|
+
isString2(newval) || isNil(newval) ? newval : void 0
|
|
797
|
+
);
|
|
798
|
+
}).build();
|
|
799
|
+
this.modelJsonSchemas[modelName] = model.jsonSchema();
|
|
800
|
+
return manager;
|
|
801
|
+
}
|
|
802
|
+
getOrCreateModelOptions(modelName) {
|
|
803
|
+
let manager = this.modelOptions[modelName];
|
|
804
|
+
if (!manager) {
|
|
805
|
+
manager = this.createModelOptions(modelName);
|
|
806
|
+
this.modelOptions[modelName] = manager;
|
|
807
|
+
}
|
|
808
|
+
return manager;
|
|
809
|
+
}
|
|
810
|
+
setModelOptions(modelName, options) {
|
|
811
|
+
const manager = this.getOrCreateModelOptions(modelName);
|
|
812
|
+
const defaultOptions = this.getDefaultModelOptions();
|
|
813
|
+
const currentModelOptions = manager.fetch();
|
|
814
|
+
manager.assign({ ...defaultOptions, ...currentModelOptions, ...options });
|
|
815
|
+
}
|
|
816
|
+
setModelOption(modelName, key, value) {
|
|
817
|
+
const manager = this.getOrCreateModelOptions(modelName);
|
|
818
|
+
manager.set(key, value);
|
|
819
|
+
}
|
|
820
|
+
getModelOptions(modelName) {
|
|
821
|
+
const manager = this.getOrCreateModelOptions(modelName);
|
|
822
|
+
return manager.fetch();
|
|
823
|
+
}
|
|
824
|
+
getModelOption(modelName, key, defaultValue) {
|
|
825
|
+
const manager = this.getOrCreateModelOptions(modelName);
|
|
826
|
+
const defaultModelValue = this.getDefaultModelOption(
|
|
827
|
+
key,
|
|
828
|
+
defaultValue
|
|
829
|
+
);
|
|
830
|
+
return getNestedOption(manager, key, defaultModelValue);
|
|
831
|
+
}
|
|
832
|
+
getExactModelOption(modelName, key) {
|
|
833
|
+
const manager = this.getOrCreateModelOptions(modelName);
|
|
834
|
+
const defaultModelValue = this.getDefaultModelOption(key);
|
|
835
|
+
return manager.get(key, defaultModelValue);
|
|
836
|
+
}
|
|
837
|
+
getModelNames() {
|
|
838
|
+
return Object.keys(this.modelOptions);
|
|
839
|
+
}
|
|
840
|
+
hasModel(modelName) {
|
|
841
|
+
return modelName in this.modelOptions;
|
|
842
|
+
}
|
|
843
|
+
getModelJsonSchema(modelName) {
|
|
844
|
+
return this.modelJsonSchemas[modelName];
|
|
845
|
+
}
|
|
846
|
+
createDataOptions(dataName) {
|
|
847
|
+
const manager = new OptionsManager({
|
|
848
|
+
...defaultDataOptions,
|
|
849
|
+
dataName
|
|
850
|
+
});
|
|
851
|
+
manager.onchange("basePath", function(newval, key, target) {
|
|
852
|
+
target[key] = normalizeBasePath(
|
|
853
|
+
dataName,
|
|
854
|
+
isString2(newval) || isNil(newval) ? newval : void 0
|
|
855
|
+
);
|
|
856
|
+
}).build();
|
|
857
|
+
return manager;
|
|
858
|
+
}
|
|
859
|
+
getOrCreateDataOptions(dataName) {
|
|
860
|
+
let manager = this.dataOptions[dataName];
|
|
861
|
+
if (!manager) {
|
|
862
|
+
manager = this.createDataOptions(dataName);
|
|
863
|
+
this.dataOptions[dataName] = manager;
|
|
864
|
+
}
|
|
865
|
+
return manager;
|
|
866
|
+
}
|
|
867
|
+
setDataOptions(dataName, options) {
|
|
868
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
869
|
+
const currentDataOptions = manager.fetch();
|
|
870
|
+
manager.assign({ ...currentDataOptions, ...options });
|
|
871
|
+
}
|
|
872
|
+
setDataOption(dataName, key, value) {
|
|
873
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
874
|
+
manager.set(key, value);
|
|
875
|
+
}
|
|
876
|
+
getDataOptions(dataName) {
|
|
877
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
878
|
+
return manager.fetch();
|
|
879
|
+
}
|
|
880
|
+
getDataOption(dataName, key, defaultValue) {
|
|
881
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
882
|
+
return getNestedOption(manager, key, defaultValue);
|
|
883
|
+
}
|
|
884
|
+
getExactDataOption(dataName, key) {
|
|
885
|
+
const manager = this.getOrCreateDataOptions(dataName);
|
|
886
|
+
return manager.get(key);
|
|
887
|
+
}
|
|
888
|
+
getDataNames() {
|
|
889
|
+
return Object.keys(this.dataOptions);
|
|
890
|
+
}
|
|
891
|
+
ensureModelMeta(modelName) {
|
|
892
|
+
if (modelName in this.modelRefs && modelName in this.modelSubs && modelName in this.modelAtts) {
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
const model = this.getModelInstance(modelName);
|
|
896
|
+
if (!model) {
|
|
897
|
+
this.modelRefs[modelName] = this.modelRefs[modelName] ?? {};
|
|
898
|
+
this.modelSubs[modelName] = this.modelSubs[modelName] ?? [];
|
|
899
|
+
this.modelAtts[modelName] = this.modelAtts[modelName] ?? [];
|
|
900
|
+
return;
|
|
901
|
+
}
|
|
902
|
+
const schema = model.schema;
|
|
903
|
+
this.modelRefs[modelName] = buildRefs(schema.tree);
|
|
904
|
+
this.modelSubs[modelName] = buildSubPaths(schema.tree);
|
|
905
|
+
this.modelAtts[modelName] = keys(schema.obj);
|
|
906
|
+
}
|
|
907
|
+
getModelRef(modelName, refPath) {
|
|
908
|
+
this.ensureModelMeta(modelName);
|
|
909
|
+
const value = get2(this.modelRefs, `${modelName}.${refPath}`, null);
|
|
910
|
+
return isString2(value) ? value : null;
|
|
911
|
+
}
|
|
912
|
+
getModelSub(modelName) {
|
|
913
|
+
this.ensureModelMeta(modelName);
|
|
914
|
+
return get2(this.modelSubs, modelName, []);
|
|
915
|
+
}
|
|
916
|
+
getModelAtt(modelName) {
|
|
917
|
+
this.ensureModelMeta(modelName);
|
|
918
|
+
return get2(this.modelAtts, modelName, []);
|
|
919
|
+
}
|
|
920
|
+
};
|
|
921
|
+
var defaultRuntime = new AccessRuntime();
|
|
922
|
+
|
|
923
|
+
// src/runtime-context.ts
|
|
924
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
925
|
+
var runtimeStorage = new AsyncLocalStorage();
|
|
926
|
+
function getActiveRuntime() {
|
|
927
|
+
return runtimeStorage.getStore() ?? null;
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
// src/options/global-options.ts
|
|
931
|
+
var getRuntime = () => getActiveRuntime() ?? defaultRuntime;
|
|
932
|
+
var getGlobalOption = (key, defaultValue) => {
|
|
933
|
+
return getRuntime().getGlobalOption(key, defaultValue);
|
|
934
|
+
};
|
|
935
|
+
|
|
936
|
+
// src/validation/common.ts
|
|
937
|
+
import { z as z2 } from "zod";
|
|
938
|
+
var stringOrStringArray = z2.union([z2.string(), z2.array(z2.string())]);
|
|
939
|
+
var safeIntegerString = (min, message) => z2.string().regex(/^\d+$/, message).refine((value) => Number.isSafeInteger(Number(value)), "Expected a safe integer").refine((value) => Number(value) >= min, message);
|
|
940
|
+
var queryBooleanString = z2.enum(["true", "false"]);
|
|
941
|
+
var nonNegativeIntegerString = safeIntegerString(0, "Expected a non-negative integer");
|
|
942
|
+
var positiveIntegerString = safeIntegerString(1, "Expected a positive integer");
|
|
943
|
+
var nonNegativeIntegerSchema = z2.number().int().min(0).max(Number.MAX_SAFE_INTEGER);
|
|
944
|
+
var positiveIntegerSchema = z2.number().int().min(1).max(Number.MAX_SAFE_INTEGER);
|
|
945
|
+
var unknownRecord = z2.record(z2.string(), z2.unknown());
|
|
946
|
+
var projectionObjectSchema = z2.record(z2.string(), z2.union([z2.literal(1), z2.literal(-1)]));
|
|
947
|
+
var projectionSchema = z2.union([z2.string(), z2.array(z2.string()), projectionObjectSchema]);
|
|
948
|
+
var sortOrderSchema = z2.union([
|
|
949
|
+
z2.literal(-1),
|
|
950
|
+
z2.literal(1),
|
|
951
|
+
z2.literal("asc"),
|
|
952
|
+
z2.literal("ascending"),
|
|
953
|
+
z2.literal("desc"),
|
|
954
|
+
z2.literal("descending")
|
|
62
955
|
]);
|
|
63
|
-
var sortSchema =
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
956
|
+
var sortSchema = z2.union([
|
|
957
|
+
z2.string(),
|
|
958
|
+
z2.record(z2.string(), sortOrderSchema),
|
|
959
|
+
z2.array(z2.tuple([z2.string(), sortOrderSchema])),
|
|
960
|
+
z2.null()
|
|
68
961
|
]);
|
|
69
|
-
var populateSchema =
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
path:
|
|
962
|
+
var populateSchema = z2.union([
|
|
963
|
+
z2.string(),
|
|
964
|
+
z2.array(
|
|
965
|
+
z2.union([
|
|
966
|
+
z2.string(),
|
|
967
|
+
z2.object({
|
|
968
|
+
path: z2.string().min(1),
|
|
76
969
|
select: projectionSchema.optional(),
|
|
77
|
-
match:
|
|
78
|
-
access:
|
|
970
|
+
match: z2.unknown().optional(),
|
|
971
|
+
access: z2.enum(["list", "read"]).optional()
|
|
79
972
|
}).passthrough()
|
|
80
973
|
])
|
|
81
974
|
),
|
|
82
|
-
|
|
83
|
-
path:
|
|
975
|
+
z2.object({
|
|
976
|
+
path: z2.string().min(1),
|
|
84
977
|
select: projectionSchema.optional(),
|
|
85
|
-
match:
|
|
86
|
-
access:
|
|
978
|
+
match: z2.unknown().optional(),
|
|
979
|
+
access: z2.enum(["list", "read"]).optional()
|
|
87
980
|
}).passthrough()
|
|
88
981
|
]);
|
|
89
|
-
var subPopulateSchema =
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
path:
|
|
982
|
+
var subPopulateSchema = z2.union([
|
|
983
|
+
z2.string(),
|
|
984
|
+
z2.array(
|
|
985
|
+
z2.union([
|
|
986
|
+
z2.string(),
|
|
987
|
+
z2.object({
|
|
988
|
+
path: z2.string().min(1),
|
|
96
989
|
select: projectionSchema.optional()
|
|
97
990
|
}).passthrough()
|
|
98
991
|
])
|
|
99
992
|
),
|
|
100
|
-
|
|
101
|
-
path:
|
|
993
|
+
z2.object({
|
|
994
|
+
path: z2.string().min(1),
|
|
102
995
|
select: projectionSchema.optional()
|
|
103
996
|
}).passthrough()
|
|
104
997
|
]);
|
|
105
|
-
var includeItemSchema =
|
|
106
|
-
model:
|
|
107
|
-
op:
|
|
108
|
-
path:
|
|
109
|
-
filter:
|
|
110
|
-
localField:
|
|
111
|
-
foreignField:
|
|
112
|
-
args:
|
|
113
|
-
options:
|
|
998
|
+
var includeItemSchema = z2.object({
|
|
999
|
+
model: z2.string().min(1),
|
|
1000
|
+
op: z2.enum(["list", "read", "count"]),
|
|
1001
|
+
path: z2.string().min(1),
|
|
1002
|
+
filter: z2.record(z2.string(), z2.unknown()).optional(),
|
|
1003
|
+
localField: z2.string().min(1),
|
|
1004
|
+
foreignField: z2.string().min(1),
|
|
1005
|
+
args: z2.unknown().optional(),
|
|
1006
|
+
options: z2.unknown().optional()
|
|
114
1007
|
}).passthrough();
|
|
115
|
-
var includeSchema =
|
|
116
|
-
var fieldsSchema =
|
|
117
|
-
var taskSchema =
|
|
118
|
-
type:
|
|
119
|
-
args:
|
|
1008
|
+
var includeSchema = z2.union([includeItemSchema, z2.array(includeItemSchema)]);
|
|
1009
|
+
var fieldsSchema = z2.array(z2.string().min(1));
|
|
1010
|
+
var taskSchema = z2.object({
|
|
1011
|
+
type: z2.string().min(1),
|
|
1012
|
+
args: z2.unknown(),
|
|
120
1013
|
options: unknownRecord.optional()
|
|
121
1014
|
});
|
|
122
|
-
var tasksSchema =
|
|
123
|
-
var objectOrArraySchema =
|
|
124
|
-
function rejectKeys(body, ctx,
|
|
125
|
-
for (const key of
|
|
1015
|
+
var tasksSchema = z2.union([taskSchema, z2.array(taskSchema)]);
|
|
1016
|
+
var objectOrArraySchema = z2.union([z2.record(z2.string(), z2.unknown()), z2.array(z2.unknown())]);
|
|
1017
|
+
function rejectKeys(body, ctx, keys2) {
|
|
1018
|
+
for (const key of keys2) {
|
|
126
1019
|
if (key in body) {
|
|
127
1020
|
ctx.addIssue({
|
|
128
|
-
code:
|
|
1021
|
+
code: z2.ZodIssueCode.custom,
|
|
129
1022
|
message: `Unsupported field: ${key}`,
|
|
130
1023
|
path: [key]
|
|
131
1024
|
});
|
|
@@ -149,6 +1042,10 @@ function parsePathParam(value, parameter) {
|
|
|
149
1042
|
return param;
|
|
150
1043
|
}
|
|
151
1044
|
function parseQuery(schema, value) {
|
|
1045
|
+
const complexityErrors = validateRequestComplexity(value, getGlobalOption("requestComplexity"), "request");
|
|
1046
|
+
if (complexityErrors.length > 0) {
|
|
1047
|
+
throw new clientErrors.BadRequestError("Bad Request", { errors: complexityErrors });
|
|
1048
|
+
}
|
|
152
1049
|
const result = schema.safeParse(value);
|
|
153
1050
|
if (!result.success) {
|
|
154
1051
|
throwValidationError(normalizeIssues(result.error.issues), void 0, "parameter");
|
|
@@ -156,6 +1053,10 @@ function parseQuery(schema, value) {
|
|
|
156
1053
|
return result.data;
|
|
157
1054
|
}
|
|
158
1055
|
function parseBody(schema, value) {
|
|
1056
|
+
const complexityErrors = validateRequestComplexity(value ?? {}, getGlobalOption("requestComplexity"), "request");
|
|
1057
|
+
if (complexityErrors.length > 0) {
|
|
1058
|
+
throw new clientErrors.BadRequestError("Bad Request", { errors: complexityErrors });
|
|
1059
|
+
}
|
|
159
1060
|
const result = schema.safeParse(value ?? {});
|
|
160
1061
|
if (!result.success) {
|
|
161
1062
|
throwValidationError(normalizeIssues(result.error.issues), void 0, "pointer");
|
|
@@ -498,133 +1399,130 @@ function buildPointer(path) {
|
|
|
498
1399
|
}
|
|
499
1400
|
|
|
500
1401
|
// src/validation/model-router.ts
|
|
501
|
-
import { z as
|
|
502
|
-
var listQuerySchema =
|
|
503
|
-
skip:
|
|
1402
|
+
import { z as z3 } from "zod";
|
|
1403
|
+
var listQuerySchema = z3.object({
|
|
1404
|
+
skip: nonNegativeIntegerString.optional(),
|
|
504
1405
|
limit: positiveIntegerString.optional(),
|
|
505
|
-
page:
|
|
1406
|
+
page: nonNegativeIntegerString.optional(),
|
|
506
1407
|
page_size: positiveIntegerString.optional(),
|
|
507
1408
|
skim: queryBooleanString.optional(),
|
|
508
1409
|
include_permissions: queryBooleanString.optional(),
|
|
509
1410
|
include_count: queryBooleanString.optional(),
|
|
510
1411
|
include_extra_headers: queryBooleanString.optional()
|
|
511
1412
|
}).passthrough();
|
|
512
|
-
var createQuerySchema =
|
|
1413
|
+
var createQuerySchema = z3.object({
|
|
513
1414
|
include_permissions: queryBooleanString.optional()
|
|
514
1415
|
}).passthrough();
|
|
515
|
-
var readQuerySchema =
|
|
1416
|
+
var readQuerySchema = z3.object({
|
|
516
1417
|
include_permissions: queryBooleanString.optional(),
|
|
517
1418
|
try_list: queryBooleanString.optional()
|
|
518
1419
|
}).passthrough();
|
|
519
|
-
var updateQuerySchema =
|
|
1420
|
+
var updateQuerySchema = z3.object({
|
|
520
1421
|
returning_all: queryBooleanString.optional(),
|
|
521
1422
|
include_permissions: queryBooleanString.optional()
|
|
522
1423
|
}).passthrough();
|
|
523
|
-
var upsertQuerySchema =
|
|
1424
|
+
var upsertQuerySchema = z3.object({
|
|
524
1425
|
returning_all: queryBooleanString.optional(),
|
|
525
1426
|
include_permissions: queryBooleanString.optional()
|
|
526
1427
|
}).passthrough();
|
|
527
|
-
var listBodySchema =
|
|
1428
|
+
var listBodySchema = z3.object({
|
|
528
1429
|
filter: objectOrArraySchema.optional(),
|
|
529
1430
|
select: projectionSchema.optional(),
|
|
530
1431
|
sort: sortSchema.optional(),
|
|
531
1432
|
populate: populateSchema.optional(),
|
|
532
1433
|
include: includeSchema.optional(),
|
|
533
1434
|
tasks: tasksSchema.optional(),
|
|
534
|
-
skip:
|
|
535
|
-
limit:
|
|
536
|
-
page:
|
|
537
|
-
pageSize:
|
|
538
|
-
options:
|
|
539
|
-
skim:
|
|
540
|
-
includePermissions:
|
|
541
|
-
includeCount:
|
|
542
|
-
includeExtraHeaders:
|
|
543
|
-
populateAccess:
|
|
1435
|
+
skip: z3.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1436
|
+
limit: z3.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1437
|
+
page: z3.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1438
|
+
pageSize: z3.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1439
|
+
options: z3.object({
|
|
1440
|
+
skim: z3.boolean().optional(),
|
|
1441
|
+
includePermissions: z3.boolean().optional(),
|
|
1442
|
+
includeCount: z3.boolean().optional(),
|
|
1443
|
+
includeExtraHeaders: z3.boolean().optional(),
|
|
1444
|
+
populateAccess: z3.unknown().optional()
|
|
544
1445
|
}).passthrough().optional()
|
|
545
1446
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
|
|
546
|
-
var countBodySchema =
|
|
547
|
-
filter: objectOrArraySchema.optional()
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
}).passthrough().optional()
|
|
551
|
-
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access"]));
|
|
552
|
-
var readFilterBodySchema = z2.object({
|
|
1447
|
+
var countBodySchema = z3.object({
|
|
1448
|
+
filter: objectOrArraySchema.optional()
|
|
1449
|
+
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query", "access", "options"]));
|
|
1450
|
+
var readFilterBodySchema = z3.object({
|
|
553
1451
|
filter: objectOrArraySchema.optional(),
|
|
554
1452
|
select: projectionSchema.optional(),
|
|
555
1453
|
sort: sortSchema.optional(),
|
|
556
1454
|
populate: populateSchema.optional(),
|
|
557
1455
|
include: includeSchema.optional(),
|
|
558
1456
|
tasks: tasksSchema.optional(),
|
|
559
|
-
options:
|
|
560
|
-
skim:
|
|
561
|
-
includePermissions:
|
|
562
|
-
tryList:
|
|
563
|
-
populateAccess:
|
|
1457
|
+
options: z3.object({
|
|
1458
|
+
skim: z3.boolean().optional(),
|
|
1459
|
+
includePermissions: z3.boolean().optional(),
|
|
1460
|
+
tryList: z3.boolean().optional(),
|
|
1461
|
+
populateAccess: z3.unknown().optional()
|
|
564
1462
|
}).passthrough().optional()
|
|
565
1463
|
}).passthrough();
|
|
566
|
-
var readByIdBodySchema =
|
|
1464
|
+
var readByIdBodySchema = z3.object({
|
|
567
1465
|
select: projectionSchema.optional(),
|
|
568
1466
|
populate: populateSchema.optional(),
|
|
569
1467
|
include: includeSchema.optional(),
|
|
570
1468
|
tasks: tasksSchema.optional(),
|
|
571
|
-
options:
|
|
572
|
-
skim:
|
|
573
|
-
includePermissions:
|
|
574
|
-
tryList:
|
|
575
|
-
populateAccess:
|
|
1469
|
+
options: z3.object({
|
|
1470
|
+
skim: z3.boolean().optional(),
|
|
1471
|
+
includePermissions: z3.boolean().optional(),
|
|
1472
|
+
tryList: z3.boolean().optional(),
|
|
1473
|
+
populateAccess: z3.unknown().optional()
|
|
576
1474
|
}).passthrough().optional()
|
|
577
1475
|
}).passthrough();
|
|
578
|
-
var advancedCreateBodySchema =
|
|
579
|
-
data:
|
|
1476
|
+
var advancedCreateBodySchema = z3.object({
|
|
1477
|
+
data: z3.unknown(),
|
|
580
1478
|
select: projectionSchema.optional(),
|
|
581
1479
|
populate: populateSchema.optional(),
|
|
582
1480
|
tasks: tasksSchema.optional(),
|
|
583
|
-
options:
|
|
584
|
-
includePermissions:
|
|
585
|
-
populateAccess:
|
|
1481
|
+
options: z3.object({
|
|
1482
|
+
includePermissions: z3.boolean().optional(),
|
|
1483
|
+
populateAccess: z3.unknown().optional()
|
|
586
1484
|
}).passthrough().optional()
|
|
587
1485
|
}).passthrough();
|
|
588
|
-
var createBodySchema =
|
|
589
|
-
|
|
590
|
-
|
|
1486
|
+
var createBodySchema = z3.union([
|
|
1487
|
+
z3.record(z3.string(), z3.unknown()),
|
|
1488
|
+
z3.array(z3.record(z3.string(), z3.unknown()))
|
|
591
1489
|
]);
|
|
592
|
-
var updateBodySchema =
|
|
593
|
-
var advancedUpdateBodySchema =
|
|
594
|
-
data:
|
|
1490
|
+
var updateBodySchema = z3.record(z3.string(), z3.unknown());
|
|
1491
|
+
var advancedUpdateBodySchema = z3.object({
|
|
1492
|
+
data: z3.unknown(),
|
|
595
1493
|
select: projectionSchema.optional(),
|
|
596
1494
|
populate: populateSchema.optional(),
|
|
597
1495
|
tasks: tasksSchema.optional(),
|
|
598
|
-
options:
|
|
599
|
-
returningAll:
|
|
600
|
-
includePermissions:
|
|
601
|
-
populateAccess:
|
|
1496
|
+
options: z3.object({
|
|
1497
|
+
returningAll: z3.boolean().optional(),
|
|
1498
|
+
includePermissions: z3.boolean().optional(),
|
|
1499
|
+
populateAccess: z3.unknown().optional()
|
|
602
1500
|
}).passthrough().optional()
|
|
603
1501
|
}).passthrough();
|
|
604
|
-
var upsertBodySchema =
|
|
605
|
-
var advancedUpsertBodySchema =
|
|
606
|
-
data:
|
|
1502
|
+
var upsertBodySchema = z3.record(z3.string(), z3.unknown());
|
|
1503
|
+
var advancedUpsertBodySchema = z3.object({
|
|
1504
|
+
data: z3.record(z3.string(), z3.unknown()),
|
|
607
1505
|
select: projectionSchema.optional(),
|
|
608
1506
|
populate: populateSchema.optional(),
|
|
609
1507
|
tasks: tasksSchema.optional(),
|
|
610
|
-
options:
|
|
611
|
-
returningAll:
|
|
612
|
-
includePermissions:
|
|
613
|
-
populateAccess:
|
|
1508
|
+
options: z3.object({
|
|
1509
|
+
returningAll: z3.boolean().optional(),
|
|
1510
|
+
includePermissions: z3.boolean().optional(),
|
|
1511
|
+
populateAccess: z3.unknown().optional()
|
|
614
1512
|
}).passthrough().optional()
|
|
615
1513
|
}).passthrough();
|
|
616
|
-
var distinctBodySchema =
|
|
1514
|
+
var distinctBodySchema = z3.object({
|
|
617
1515
|
filter: objectOrArraySchema.optional()
|
|
618
1516
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["query"]));
|
|
619
|
-
var subListBodySchema =
|
|
620
|
-
filter:
|
|
1517
|
+
var subListBodySchema = z3.object({
|
|
1518
|
+
filter: z3.record(z3.string(), z3.unknown()).optional(),
|
|
621
1519
|
select: fieldsSchema.optional()
|
|
622
1520
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
|
|
623
|
-
var subMutationBodySchema =
|
|
624
|
-
|
|
625
|
-
|
|
1521
|
+
var subMutationBodySchema = z3.union([
|
|
1522
|
+
z3.record(z3.string(), z3.unknown()),
|
|
1523
|
+
z3.array(z3.record(z3.string(), z3.unknown()))
|
|
626
1524
|
]);
|
|
627
|
-
var subReadBodySchema =
|
|
1525
|
+
var subReadBodySchema = z3.object({
|
|
628
1526
|
select: fieldsSchema.optional(),
|
|
629
1527
|
populate: subPopulateSchema.optional()
|
|
630
1528
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["fields"]));
|
|
@@ -637,54 +1535,54 @@ var requestSchemas = {
|
|
|
637
1535
|
};
|
|
638
1536
|
|
|
639
1537
|
// src/validation/data-router.ts
|
|
640
|
-
import { z as
|
|
641
|
-
var dataListBodySchema =
|
|
1538
|
+
import { z as z4 } from "zod";
|
|
1539
|
+
var dataListBodySchema = z4.object({
|
|
642
1540
|
filter: objectOrArraySchema.optional(),
|
|
643
1541
|
select: projectionSchema.optional(),
|
|
644
|
-
sort:
|
|
645
|
-
skip:
|
|
646
|
-
limit:
|
|
647
|
-
page:
|
|
648
|
-
pageSize:
|
|
649
|
-
options:
|
|
650
|
-
includeCount:
|
|
651
|
-
includeExtraHeaders:
|
|
1542
|
+
sort: z4.string().optional(),
|
|
1543
|
+
skip: z4.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1544
|
+
limit: z4.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1545
|
+
page: z4.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1546
|
+
pageSize: z4.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1547
|
+
options: z4.object({
|
|
1548
|
+
includeCount: z4.boolean().optional(),
|
|
1549
|
+
includeExtraHeaders: z4.boolean().optional()
|
|
652
1550
|
}).passthrough().optional()
|
|
653
1551
|
}).passthrough();
|
|
654
|
-
var dataReadFilterBodySchema =
|
|
1552
|
+
var dataReadFilterBodySchema = z4.object({
|
|
655
1553
|
filter: objectOrArraySchema.optional(),
|
|
656
1554
|
select: projectionSchema.optional()
|
|
657
1555
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
|
|
658
|
-
var dataReadByIdBodySchema =
|
|
1556
|
+
var dataReadByIdBodySchema = z4.object({
|
|
659
1557
|
select: projectionSchema.optional()
|
|
660
1558
|
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["options"]));
|
|
661
1559
|
|
|
662
1560
|
// src/validation/root-router.ts
|
|
663
|
-
import { z as
|
|
1561
|
+
import { z as z5 } from "zod";
|
|
664
1562
|
var rootEntryBaseSchema = {
|
|
665
|
-
target:
|
|
666
|
-
name:
|
|
667
|
-
order:
|
|
1563
|
+
target: z5.enum(["model", "data"]),
|
|
1564
|
+
name: z5.string().min(1),
|
|
1565
|
+
order: nonNegativeIntegerSchema.optional()
|
|
668
1566
|
};
|
|
669
|
-
var rootModelListArgsSchema =
|
|
1567
|
+
var rootModelListArgsSchema = z5.object({
|
|
670
1568
|
select: projectionSchema.optional(),
|
|
671
1569
|
populate: populateSchema.optional(),
|
|
672
1570
|
include: includeSchema.optional(),
|
|
673
1571
|
sort: sortSchema.optional(),
|
|
674
|
-
skip:
|
|
675
|
-
limit:
|
|
676
|
-
page:
|
|
677
|
-
pageSize:
|
|
1572
|
+
skip: z5.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1573
|
+
limit: z5.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1574
|
+
page: z5.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1575
|
+
pageSize: z5.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
678
1576
|
tasks: tasksSchema.optional()
|
|
679
1577
|
}).passthrough();
|
|
680
|
-
var rootModelListOptionsSchema =
|
|
681
|
-
skim:
|
|
682
|
-
includePermissions:
|
|
683
|
-
includeCount:
|
|
684
|
-
populateAccess:
|
|
685
|
-
lean:
|
|
1578
|
+
var rootModelListOptionsSchema = z5.object({
|
|
1579
|
+
skim: z5.boolean().optional(),
|
|
1580
|
+
includePermissions: z5.boolean().optional(),
|
|
1581
|
+
includeCount: z5.boolean().optional(),
|
|
1582
|
+
populateAccess: z5.unknown().optional(),
|
|
1583
|
+
lean: z5.boolean().optional()
|
|
686
1584
|
}).passthrough();
|
|
687
|
-
var rootModelReadArgsSchema =
|
|
1585
|
+
var rootModelReadArgsSchema = z5.object({
|
|
688
1586
|
select: projectionSchema.optional(),
|
|
689
1587
|
populate: populateSchema.optional(),
|
|
690
1588
|
include: includeSchema.optional(),
|
|
@@ -693,203 +1591,214 @@ var rootModelReadArgsSchema = z4.object({
|
|
|
693
1591
|
var rootModelReadFilterArgsSchema = rootModelReadArgsSchema.extend({
|
|
694
1592
|
sort: sortSchema.optional()
|
|
695
1593
|
});
|
|
696
|
-
var rootModelReadOptionsSchema =
|
|
697
|
-
skim:
|
|
698
|
-
includePermissions:
|
|
699
|
-
tryList:
|
|
700
|
-
populateAccess:
|
|
701
|
-
lean:
|
|
1594
|
+
var rootModelReadOptionsSchema = z5.object({
|
|
1595
|
+
skim: z5.boolean().optional(),
|
|
1596
|
+
includePermissions: z5.boolean().optional(),
|
|
1597
|
+
tryList: z5.boolean().optional(),
|
|
1598
|
+
populateAccess: z5.unknown().optional(),
|
|
1599
|
+
lean: z5.boolean().optional()
|
|
702
1600
|
}).passthrough();
|
|
703
|
-
var rootModelCreateArgsSchema =
|
|
1601
|
+
var rootModelCreateArgsSchema = z5.object({
|
|
704
1602
|
select: projectionSchema.optional(),
|
|
705
1603
|
populate: populateSchema.optional(),
|
|
706
1604
|
tasks: tasksSchema.optional()
|
|
707
1605
|
}).passthrough();
|
|
708
|
-
var rootModelCreateOptionsSchema =
|
|
709
|
-
skim:
|
|
710
|
-
includePermissions:
|
|
711
|
-
populateAccess:
|
|
1606
|
+
var rootModelCreateOptionsSchema = z5.object({
|
|
1607
|
+
skim: z5.boolean().optional(),
|
|
1608
|
+
includePermissions: z5.boolean().optional(),
|
|
1609
|
+
populateAccess: z5.unknown().optional()
|
|
712
1610
|
}).passthrough();
|
|
713
|
-
var rootModelUpdateArgsSchema =
|
|
1611
|
+
var rootModelUpdateArgsSchema = z5.object({
|
|
714
1612
|
select: projectionSchema.optional(),
|
|
715
1613
|
populate: populateSchema.optional(),
|
|
716
1614
|
tasks: tasksSchema.optional()
|
|
717
1615
|
}).passthrough();
|
|
718
|
-
var rootModelUpdateOptionsSchema =
|
|
719
|
-
skim:
|
|
720
|
-
returningAll:
|
|
721
|
-
includePermissions:
|
|
722
|
-
populateAccess:
|
|
1616
|
+
var rootModelUpdateOptionsSchema = z5.object({
|
|
1617
|
+
skim: z5.boolean().optional(),
|
|
1618
|
+
returningAll: z5.boolean().optional(),
|
|
1619
|
+
includePermissions: z5.boolean().optional(),
|
|
1620
|
+
populateAccess: z5.unknown().optional()
|
|
723
1621
|
}).passthrough();
|
|
724
1622
|
var rootModelUpsertArgsSchema = rootModelUpdateArgsSchema;
|
|
725
1623
|
var rootModelUpsertOptionsSchema = rootModelUpdateOptionsSchema;
|
|
726
|
-
var rootModelSubListArgsSchema =
|
|
1624
|
+
var rootModelSubListArgsSchema = z5.object({
|
|
727
1625
|
select: fieldsSchema.optional()
|
|
728
1626
|
}).passthrough();
|
|
729
|
-
var rootModelSubReadArgsSchema =
|
|
1627
|
+
var rootModelSubReadArgsSchema = z5.object({
|
|
730
1628
|
select: fieldsSchema.optional(),
|
|
731
1629
|
populate: subPopulateSchema.optional()
|
|
732
1630
|
}).passthrough();
|
|
733
|
-
var rootModelCountOptionsSchema =
|
|
734
|
-
|
|
735
|
-
}).passthrough();
|
|
736
|
-
var rootDataListArgsSchema = z4.object({
|
|
1631
|
+
var rootModelCountOptionsSchema = z5.object({}).strict().optional();
|
|
1632
|
+
var rootDataListArgsSchema = z5.object({
|
|
737
1633
|
select: projectionSchema.optional(),
|
|
738
|
-
sort:
|
|
739
|
-
skip:
|
|
740
|
-
limit:
|
|
741
|
-
page:
|
|
742
|
-
pageSize:
|
|
1634
|
+
sort: z5.string().optional(),
|
|
1635
|
+
skip: z5.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1636
|
+
limit: z5.union([positiveIntegerSchema, positiveIntegerString]).optional(),
|
|
1637
|
+
page: z5.union([nonNegativeIntegerSchema, nonNegativeIntegerString]).optional(),
|
|
1638
|
+
pageSize: z5.union([positiveIntegerSchema, positiveIntegerString]).optional()
|
|
743
1639
|
}).passthrough();
|
|
744
|
-
var rootDataListOptionsSchema =
|
|
745
|
-
includeCount:
|
|
1640
|
+
var rootDataListOptionsSchema = z5.object({
|
|
1641
|
+
includeCount: z5.boolean().optional()
|
|
746
1642
|
}).passthrough();
|
|
747
|
-
var rootDataReadArgsSchema =
|
|
1643
|
+
var rootDataReadArgsSchema = z5.object({
|
|
748
1644
|
select: projectionSchema.optional()
|
|
749
1645
|
}).passthrough();
|
|
750
|
-
var
|
|
751
|
-
|
|
752
|
-
|
|
1646
|
+
var rootModelNewArgsSchema = z5.object({
|
|
1647
|
+
select: projectionSchema.optional()
|
|
1648
|
+
}).passthrough();
|
|
1649
|
+
var rootModelNewOptionsSchema = z5.object({
|
|
1650
|
+
skim: z5.boolean().optional(),
|
|
1651
|
+
includePermissions: z5.boolean().optional()
|
|
1652
|
+
}).passthrough();
|
|
1653
|
+
var rootModelQueryEntrySchema = z5.union([
|
|
1654
|
+
z5.object({
|
|
753
1655
|
...rootEntryBaseSchema,
|
|
754
|
-
target:
|
|
755
|
-
op:
|
|
1656
|
+
target: z5.literal("model"),
|
|
1657
|
+
op: z5.literal("new"),
|
|
1658
|
+
args: rootModelNewArgsSchema.optional(),
|
|
1659
|
+
options: rootModelNewOptionsSchema.optional()
|
|
1660
|
+
}).passthrough(),
|
|
1661
|
+
z5.object({
|
|
1662
|
+
...rootEntryBaseSchema,
|
|
1663
|
+
target: z5.literal("model"),
|
|
1664
|
+
op: z5.literal("list"),
|
|
756
1665
|
filter: objectOrArraySchema.optional(),
|
|
757
1666
|
args: rootModelListArgsSchema.optional(),
|
|
758
1667
|
options: rootModelListOptionsSchema.optional()
|
|
759
1668
|
}).passthrough(),
|
|
760
|
-
|
|
1669
|
+
z5.object({
|
|
761
1670
|
...rootEntryBaseSchema,
|
|
762
|
-
target:
|
|
763
|
-
op:
|
|
764
|
-
id:
|
|
1671
|
+
target: z5.literal("model"),
|
|
1672
|
+
op: z5.literal("read"),
|
|
1673
|
+
id: z5.string().min(1),
|
|
765
1674
|
args: rootModelReadArgsSchema.optional(),
|
|
766
1675
|
options: rootModelReadOptionsSchema.optional()
|
|
767
1676
|
}).passthrough(),
|
|
768
|
-
|
|
1677
|
+
z5.object({
|
|
769
1678
|
...rootEntryBaseSchema,
|
|
770
|
-
target:
|
|
771
|
-
op:
|
|
1679
|
+
target: z5.literal("model"),
|
|
1680
|
+
op: z5.literal("read"),
|
|
772
1681
|
filter: objectOrArraySchema,
|
|
773
1682
|
args: rootModelReadFilterArgsSchema.optional(),
|
|
774
1683
|
options: rootModelReadOptionsSchema.optional()
|
|
775
1684
|
}).passthrough(),
|
|
776
|
-
|
|
1685
|
+
z5.object({
|
|
777
1686
|
...rootEntryBaseSchema,
|
|
778
|
-
target:
|
|
779
|
-
op:
|
|
780
|
-
data:
|
|
1687
|
+
target: z5.literal("model"),
|
|
1688
|
+
op: z5.literal("create"),
|
|
1689
|
+
data: z5.unknown(),
|
|
781
1690
|
args: rootModelCreateArgsSchema.optional(),
|
|
782
1691
|
options: rootModelCreateOptionsSchema.optional()
|
|
783
1692
|
}).passthrough(),
|
|
784
|
-
|
|
1693
|
+
z5.object({
|
|
785
1694
|
...rootEntryBaseSchema,
|
|
786
|
-
target:
|
|
787
|
-
op:
|
|
788
|
-
id:
|
|
789
|
-
data:
|
|
1695
|
+
target: z5.literal("model"),
|
|
1696
|
+
op: z5.literal("update"),
|
|
1697
|
+
id: z5.string().min(1),
|
|
1698
|
+
data: z5.unknown(),
|
|
790
1699
|
args: rootModelUpdateArgsSchema.optional(),
|
|
791
1700
|
options: rootModelUpdateOptionsSchema.optional()
|
|
792
1701
|
}).passthrough(),
|
|
793
|
-
|
|
1702
|
+
z5.object({
|
|
794
1703
|
...rootEntryBaseSchema,
|
|
795
|
-
target:
|
|
796
|
-
op:
|
|
797
|
-
data:
|
|
1704
|
+
target: z5.literal("model"),
|
|
1705
|
+
op: z5.literal("upsert"),
|
|
1706
|
+
data: z5.record(z5.string(), z5.unknown()),
|
|
798
1707
|
args: rootModelUpsertArgsSchema.optional(),
|
|
799
1708
|
options: rootModelUpsertOptionsSchema.optional()
|
|
800
1709
|
}).passthrough(),
|
|
801
|
-
|
|
802
|
-
|
|
1710
|
+
z5.object({ ...rootEntryBaseSchema, target: z5.literal("model"), op: z5.literal("delete"), id: z5.string().min(1) }).passthrough(),
|
|
1711
|
+
z5.object({
|
|
803
1712
|
...rootEntryBaseSchema,
|
|
804
|
-
target:
|
|
805
|
-
op:
|
|
806
|
-
id:
|
|
807
|
-
sub:
|
|
808
|
-
filter:
|
|
1713
|
+
target: z5.literal("model"),
|
|
1714
|
+
op: z5.literal("subList"),
|
|
1715
|
+
id: z5.string().min(1),
|
|
1716
|
+
sub: z5.string().min(1),
|
|
1717
|
+
filter: z5.record(z5.string(), z5.unknown()).optional(),
|
|
809
1718
|
args: rootModelSubListArgsSchema.optional()
|
|
810
1719
|
}).passthrough(),
|
|
811
|
-
|
|
1720
|
+
z5.object({
|
|
812
1721
|
...rootEntryBaseSchema,
|
|
813
|
-
target:
|
|
814
|
-
op:
|
|
815
|
-
id:
|
|
816
|
-
sub:
|
|
817
|
-
subId:
|
|
1722
|
+
target: z5.literal("model"),
|
|
1723
|
+
op: z5.literal("subRead"),
|
|
1724
|
+
id: z5.string().min(1),
|
|
1725
|
+
sub: z5.string().min(1),
|
|
1726
|
+
subId: z5.string().min(1),
|
|
818
1727
|
args: rootModelSubReadArgsSchema.optional()
|
|
819
1728
|
}).passthrough(),
|
|
820
|
-
|
|
1729
|
+
z5.object({
|
|
821
1730
|
...rootEntryBaseSchema,
|
|
822
|
-
target:
|
|
823
|
-
op:
|
|
824
|
-
id:
|
|
825
|
-
sub:
|
|
826
|
-
data:
|
|
1731
|
+
target: z5.literal("model"),
|
|
1732
|
+
op: z5.literal("subCreate"),
|
|
1733
|
+
id: z5.string().min(1),
|
|
1734
|
+
sub: z5.string().min(1),
|
|
1735
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
827
1736
|
}).passthrough(),
|
|
828
|
-
|
|
1737
|
+
z5.object({
|
|
829
1738
|
...rootEntryBaseSchema,
|
|
830
|
-
target:
|
|
831
|
-
op:
|
|
832
|
-
id:
|
|
833
|
-
sub:
|
|
834
|
-
subId:
|
|
835
|
-
data:
|
|
1739
|
+
target: z5.literal("model"),
|
|
1740
|
+
op: z5.literal("subUpdate"),
|
|
1741
|
+
id: z5.string().min(1),
|
|
1742
|
+
sub: z5.string().min(1),
|
|
1743
|
+
subId: z5.string().min(1),
|
|
1744
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
836
1745
|
}).passthrough(),
|
|
837
|
-
|
|
1746
|
+
z5.object({
|
|
838
1747
|
...rootEntryBaseSchema,
|
|
839
|
-
target:
|
|
840
|
-
op:
|
|
841
|
-
id:
|
|
842
|
-
sub:
|
|
843
|
-
data:
|
|
1748
|
+
target: z5.literal("model"),
|
|
1749
|
+
op: z5.literal("subBulkUpdate"),
|
|
1750
|
+
id: z5.string().min(1),
|
|
1751
|
+
sub: z5.string().min(1),
|
|
1752
|
+
data: z5.union([z5.record(z5.string(), z5.unknown()), z5.array(z5.record(z5.string(), z5.unknown()))])
|
|
844
1753
|
}).passthrough(),
|
|
845
|
-
|
|
1754
|
+
z5.object({
|
|
846
1755
|
...rootEntryBaseSchema,
|
|
847
|
-
target:
|
|
848
|
-
op:
|
|
849
|
-
id:
|
|
850
|
-
sub:
|
|
851
|
-
subId:
|
|
1756
|
+
target: z5.literal("model"),
|
|
1757
|
+
op: z5.literal("subDelete"),
|
|
1758
|
+
id: z5.string().min(1),
|
|
1759
|
+
sub: z5.string().min(1),
|
|
1760
|
+
subId: z5.string().min(1)
|
|
852
1761
|
}).passthrough(),
|
|
853
|
-
|
|
1762
|
+
z5.object({
|
|
854
1763
|
...rootEntryBaseSchema,
|
|
855
|
-
target:
|
|
856
|
-
op:
|
|
857
|
-
field:
|
|
1764
|
+
target: z5.literal("model"),
|
|
1765
|
+
op: z5.literal("distinct"),
|
|
1766
|
+
field: z5.string().min(1),
|
|
858
1767
|
filter: objectOrArraySchema.optional()
|
|
859
1768
|
}).passthrough(),
|
|
860
|
-
|
|
1769
|
+
z5.object({
|
|
861
1770
|
...rootEntryBaseSchema,
|
|
862
|
-
target:
|
|
863
|
-
op:
|
|
1771
|
+
target: z5.literal("model"),
|
|
1772
|
+
op: z5.literal("count"),
|
|
864
1773
|
filter: objectOrArraySchema.optional(),
|
|
865
1774
|
options: rootModelCountOptionsSchema.optional()
|
|
866
|
-
}).passthrough()
|
|
1775
|
+
}).passthrough().superRefine((body, ctx) => rejectKeys(body, ctx, ["access"]))
|
|
867
1776
|
]);
|
|
868
|
-
var rootDataQueryEntrySchema =
|
|
869
|
-
|
|
1777
|
+
var rootDataQueryEntrySchema = z5.union([
|
|
1778
|
+
z5.object({
|
|
870
1779
|
...rootEntryBaseSchema,
|
|
871
|
-
target:
|
|
872
|
-
op:
|
|
1780
|
+
target: z5.literal("data"),
|
|
1781
|
+
op: z5.literal("list"),
|
|
873
1782
|
filter: objectOrArraySchema.optional(),
|
|
874
1783
|
args: rootDataListArgsSchema.optional(),
|
|
875
1784
|
options: rootDataListOptionsSchema.optional()
|
|
876
1785
|
}).passthrough(),
|
|
877
|
-
|
|
1786
|
+
z5.object({
|
|
878
1787
|
...rootEntryBaseSchema,
|
|
879
|
-
target:
|
|
880
|
-
op:
|
|
881
|
-
id:
|
|
1788
|
+
target: z5.literal("data"),
|
|
1789
|
+
op: z5.literal("read"),
|
|
1790
|
+
id: z5.string().min(1),
|
|
882
1791
|
args: rootDataReadArgsSchema.optional()
|
|
883
1792
|
}).passthrough(),
|
|
884
|
-
|
|
1793
|
+
z5.object({
|
|
885
1794
|
...rootEntryBaseSchema,
|
|
886
|
-
target:
|
|
887
|
-
op:
|
|
1795
|
+
target: z5.literal("data"),
|
|
1796
|
+
op: z5.literal("read"),
|
|
888
1797
|
filter: objectOrArraySchema,
|
|
889
1798
|
args: rootDataReadArgsSchema.optional()
|
|
890
1799
|
}).passthrough()
|
|
891
1800
|
]);
|
|
892
|
-
var rootQuerySchema =
|
|
1801
|
+
var rootQuerySchema = z5.array(z5.union([rootModelQueryEntrySchema, rootDataQueryEntrySchema]));
|
|
893
1802
|
export {
|
|
894
1803
|
Codes,
|
|
895
1804
|
CustomHeaders,
|