@web-ts-toolkit/access-router 0.3.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/advanced.mjs CHANGED
@@ -1,7 +1,6 @@
1
1
  // src/symbols.ts
2
2
  var MIDDLEWARE = /* @__PURE__ */ Symbol.for("@web-ts-toolkit/access-router/middleware");
3
3
  var DATA_MIDDLEWARE = /* @__PURE__ */ Symbol.for("@web-ts-toolkit/access-router/data-middleware");
4
- var CORE = /* @__PURE__ */ Symbol.for("@web-ts-toolkit/access-router/core");
5
4
  var PERMISSIONS = /* @__PURE__ */ Symbol.for("@web-ts-toolkit/access-router/permissions");
6
5
  var PERMISSION_KEYS = /* @__PURE__ */ Symbol.for("@web-ts-toolkit/access-router/permission-keys");
7
6
 
@@ -139,7 +138,7 @@ var clientErrors = JsonRouter.clientErrors;
139
138
  function parsePathParam(value, parameter) {
140
139
  const result = stringOrStringArray.safeParse(value);
141
140
  if (!result.success) {
142
- throwValidationError(result.error.issues, parameter, "parameter");
141
+ throwValidationError(normalizeIssues(result.error.issues), parameter, "parameter");
143
142
  }
144
143
  const param = Array.isArray(result.data) ? result.data[0] : result.data;
145
144
  if (!param) {
@@ -152,49 +151,336 @@ function parsePathParam(value, parameter) {
152
151
  function parseQuery(schema, value) {
153
152
  const result = schema.safeParse(value);
154
153
  if (!result.success) {
155
- throwValidationError(result.error.issues, void 0, "parameter");
154
+ throwValidationError(normalizeIssues(result.error.issues), void 0, "parameter");
156
155
  }
157
156
  return result.data;
158
157
  }
159
158
  function parseBody(schema, value) {
160
159
  const result = schema.safeParse(value ?? {});
161
160
  if (!result.success) {
162
- throwValidationError(result.error.issues, void 0, "pointer");
161
+ throwValidationError(normalizeIssues(result.error.issues), void 0, "pointer");
163
162
  }
164
163
  return result.data;
165
164
  }
166
165
  function parseBodyWithSchema(schema, value, userSchema) {
167
166
  const body = parseBody(schema, value);
168
- return isZodSchema(userSchema) ? parseUserSchema(userSchema, body) : body;
167
+ return isRequestSchema(userSchema) ? parseUserSchema(userSchema, body) : Promise.resolve(body);
169
168
  }
170
- function parseNestedBodyWithSchema(schema, value, nestedKey, userSchema) {
169
+ async function parseNestedBodyWithSchema(schema, value, nestedKey, userSchema) {
171
170
  const body = parseBody(schema, value);
172
- if (!isZodSchema(userSchema)) return body;
171
+ if (!isRequestSchema(userSchema)) return body;
173
172
  return {
174
173
  ...body,
175
- [nestedKey]: parseUserSchema(userSchema, body?.[nestedKey], [nestedKey])
174
+ [nestedKey]: await parseUserSchema(userSchema, body?.[nestedKey], [nestedKey])
176
175
  };
177
176
  }
178
177
  function throwValidationError(issues, key, location = "pointer") {
179
178
  const errors = issues.map((issue) => formatIssue(issue, key, location));
180
179
  throw new clientErrors.BadRequestError("Bad Request", { errors });
181
180
  }
182
- function parseUserSchema(schema, value, prefix = []) {
183
- const result = schema.safeParse(value);
184
- if (!result.success) {
185
- const issues = result.error.issues.map((issue) => ({
186
- ...issue,
187
- path: prefix.concat(issue.path.map(String))
188
- }));
189
- throwValidationError(issues, void 0, "pointer");
181
+ async function parseUserSchema(schema, value, prefix = []) {
182
+ const validator = toRequestSchemaValidator(schema);
183
+ const result = await validator(value);
184
+ if (!isRequestSchemaFailure(result)) {
185
+ return result.data;
190
186
  }
191
- return result.data;
187
+ const issues = result.issues.map((issue) => ({
188
+ ...issue,
189
+ path: prefix.concat((issue.path ?? []).map(String))
190
+ }));
191
+ throwValidationError(issues, void 0, "pointer");
192
192
  }
193
193
  function isZodSchema(schema) {
194
194
  return typeof schema === "object" && schema !== null && "safeParse" in schema && typeof schema.safeParse === "function";
195
195
  }
196
+ function isRequestSchema(schema) {
197
+ return isZodSchema(schema) || isStandardSchema(schema) || isRequestSchemaValidator(schema) || isRequestSchemaAdapter(schema);
198
+ }
199
+ function isRequestSchemaValidator(schema) {
200
+ return typeof schema === "function";
201
+ }
202
+ function isRequestSchemaAdapter(schema) {
203
+ return typeof schema === "object" && schema !== null && "validate" in schema && typeof schema.validate === "function";
204
+ }
205
+ function isStandardSchema(schema) {
206
+ return typeof schema === "object" && schema !== null && "~standard" in schema && typeof schema["~standard"] === "object" && schema["~standard"] !== null && "validate" in schema["~standard"] && typeof schema["~standard"].validate === "function";
207
+ }
208
+ function isRequestSchemaFailure(result) {
209
+ return result.success === false;
210
+ }
211
+ function toRequestSchemaValidator(schema) {
212
+ if (isZodSchema(schema)) return fromZod(schema);
213
+ if (isStandardSchema(schema)) return fromStandardSchema(schema);
214
+ if (isRequestSchemaValidator(schema)) return schema;
215
+ return schema.validate;
216
+ }
217
+ function defineRequestSchema(validator, options = {}) {
218
+ return {
219
+ validate: validator,
220
+ openapi: options.openapi
221
+ };
222
+ }
223
+ function fromZod(schema) {
224
+ return (value) => {
225
+ const result = schema.safeParse(value);
226
+ if (result.success) {
227
+ return {
228
+ success: true,
229
+ data: result.data
230
+ };
231
+ }
232
+ return {
233
+ success: false,
234
+ issues: normalizeIssues(result.error.issues)
235
+ };
236
+ };
237
+ }
238
+ function fromStandardSchema(schema) {
239
+ return async (value) => {
240
+ const result = await schema["~standard"].validate(value);
241
+ if (!isStandardSchemaFailure(result)) {
242
+ return {
243
+ success: true,
244
+ data: result.value
245
+ };
246
+ }
247
+ return {
248
+ success: false,
249
+ issues: normalizeIssues(result.issues)
250
+ };
251
+ };
252
+ }
253
+ function fromYup(schema) {
254
+ return async (value) => {
255
+ try {
256
+ const data = await schema.validate(value, { abortEarly: false });
257
+ return {
258
+ success: true,
259
+ data
260
+ };
261
+ } catch (error) {
262
+ return {
263
+ success: false,
264
+ issues: normalizeYupIssues(error)
265
+ };
266
+ }
267
+ };
268
+ }
269
+ function fromJoi(schema) {
270
+ return async (value) => {
271
+ const result = await schema.validate(value, { abortEarly: false });
272
+ if (!result.error?.details?.length) {
273
+ return {
274
+ success: true,
275
+ data: result.value
276
+ };
277
+ }
278
+ return {
279
+ success: false,
280
+ issues: normalizeJoiIssues(result.error.details)
281
+ };
282
+ };
283
+ }
284
+ function fromAjv(validator) {
285
+ return async (value) => {
286
+ const valid = await validator(value);
287
+ if (valid) {
288
+ return {
289
+ success: true,
290
+ data: value
291
+ };
292
+ }
293
+ return {
294
+ success: false,
295
+ issues: normalizeAjvIssues(validator.errors ?? [])
296
+ };
297
+ };
298
+ }
299
+ function fromValibot(schema, safeParse) {
300
+ return async (value) => {
301
+ const result = await safeParse(schema, value, { abortEarly: false });
302
+ if (result.success) {
303
+ return {
304
+ success: true,
305
+ data: result.output
306
+ };
307
+ }
308
+ return {
309
+ success: false,
310
+ issues: normalizeValibotIssues(result.issues)
311
+ };
312
+ };
313
+ }
314
+ function fromArkType(type) {
315
+ return async (value) => {
316
+ const result = await type(value);
317
+ if (!isArkTypeErrors(result)) {
318
+ return {
319
+ success: true,
320
+ data: result
321
+ };
322
+ }
323
+ return {
324
+ success: false,
325
+ issues: normalizeArkTypeIssues(result)
326
+ };
327
+ };
328
+ }
329
+ function fromIoTs(decoder) {
330
+ return async (value) => {
331
+ const result = decoder.decode(value);
332
+ if (result._tag === "Right") {
333
+ return {
334
+ success: true,
335
+ data: result.right
336
+ };
337
+ }
338
+ return {
339
+ success: false,
340
+ issues: normalizeIoTsIssues(result.left)
341
+ };
342
+ };
343
+ }
344
+ function fromSuperstruct(struct, validate) {
345
+ return async (value) => {
346
+ const [failure, output] = await validate(value, struct);
347
+ if (!failure) {
348
+ return {
349
+ success: true,
350
+ data: output
351
+ };
352
+ }
353
+ return {
354
+ success: false,
355
+ issues: normalizeSuperstructFailure(failure)
356
+ };
357
+ };
358
+ }
359
+ function fromVine(validator) {
360
+ return async (value) => {
361
+ try {
362
+ const output = await validator.validate(value);
363
+ return {
364
+ success: true,
365
+ data: output
366
+ };
367
+ } catch (error) {
368
+ return {
369
+ success: false,
370
+ issues: normalizeVineError(error)
371
+ };
372
+ }
373
+ };
374
+ }
375
+ function isStandardSchemaFailure(result) {
376
+ return Array.isArray(result.issues);
377
+ }
378
+ function normalizeIssues(issues) {
379
+ return issues.map((issue) => ({
380
+ message: issue.message,
381
+ path: issue.path?.flatMap((segment) => normalizePathSegment(segment))
382
+ }));
383
+ }
384
+ function normalizePathSegment(segment) {
385
+ const key = isStandardSchemaPathSegment(segment) ? segment.key : segment;
386
+ return typeof key === "string" || typeof key === "number" ? [key] : [];
387
+ }
388
+ function isStandardSchemaPathSegment(segment) {
389
+ return typeof segment === "object" && segment !== null && "key" in segment;
390
+ }
391
+ function normalizeYupIssues(error) {
392
+ if (!isYupValidationError(error)) {
393
+ return [{ message: "Validation failed" }];
394
+ }
395
+ const issues = error.inner?.length ? error.inner : [error];
396
+ return issues.map((issue) => ({
397
+ message: issue.message,
398
+ path: parsePathString(issue.path)
399
+ }));
400
+ }
401
+ function normalizeJoiIssues(issues) {
402
+ return issues.map((issue) => ({
403
+ message: issue.message,
404
+ path: issue.path ? [...issue.path] : void 0
405
+ }));
406
+ }
407
+ function normalizeAjvIssues(issues) {
408
+ return issues.map((issue) => ({
409
+ message: issue.message ?? "Validation failed",
410
+ path: parseAjvPath(issue)
411
+ }));
412
+ }
413
+ function normalizeValibotIssues(issues) {
414
+ return issues.map((issue) => ({
415
+ message: issue.message,
416
+ path: issue.path?.flatMap(
417
+ (item) => typeof item.key === "string" || typeof item.key === "number" ? [item.key] : []
418
+ )
419
+ }));
420
+ }
421
+ function normalizeArkTypeIssues(issues) {
422
+ const normalized = issues.map((issue) => ({
423
+ message: issue.message ?? issue.problem ?? issues.summary ?? "Validation failed",
424
+ path: issue.path ? [...issue.path] : void 0
425
+ }));
426
+ return normalized.length ? normalized : [{ message: issues.summary ?? "Validation failed" }];
427
+ }
428
+ function normalizeIoTsIssues(issues) {
429
+ return issues.map((issue) => ({
430
+ message: issue.message ?? "Validation failed",
431
+ path: issue.context.map((entry) => entry.key).filter(Boolean)
432
+ }));
433
+ }
434
+ function normalizeSuperstructFailure(failure) {
435
+ const failures = failure.failures?.() ?? [failure];
436
+ return failures.map((entry) => ({
437
+ message: entry.message ?? "Validation failed",
438
+ path: normalizeSuperstructPath(entry)
439
+ }));
440
+ }
441
+ function normalizeSuperstructPath(failure) {
442
+ if (failure.path?.length) return [...failure.path];
443
+ if (typeof failure.key === "string" || typeof failure.key === "number") return [failure.key];
444
+ return void 0;
445
+ }
446
+ function normalizeVineError(error) {
447
+ if (!isVineValidationError(error)) {
448
+ return [{ message: "Validation failed" }];
449
+ }
450
+ return error.messages.map((message) => ({
451
+ message: message.message,
452
+ path: normalizeVineField(message)
453
+ }));
454
+ }
455
+ function normalizeVineField(message) {
456
+ const path = message.field.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
457
+ if (typeof message.index === "number" && path.length === 0) {
458
+ return [message.index];
459
+ }
460
+ return path.length ? path : void 0;
461
+ }
462
+ function parseAjvPath(issue) {
463
+ const path = issue.instancePath?.split("/").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
464
+ if (issue.params?.missingProperty) {
465
+ return (path ?? []).concat(issue.params.missingProperty);
466
+ }
467
+ return path;
468
+ }
469
+ function parsePathString(path) {
470
+ if (!path) return void 0;
471
+ return path.replace(/\[(\d+)\]/g, ".$1").split(".").filter(Boolean).map((segment) => /^\d+$/.test(segment) ? Number(segment) : segment);
472
+ }
473
+ function isYupValidationError(error) {
474
+ return typeof error === "object" && error !== null && "message" in error;
475
+ }
476
+ function isArkTypeErrors(value) {
477
+ return Array.isArray(value);
478
+ }
479
+ function isVineValidationError(error) {
480
+ return typeof error === "object" && error !== null && "messages" in error && Array.isArray(error.messages);
481
+ }
196
482
  function formatIssue(issue, key, location = "pointer") {
197
- const path = issue.path.map(String);
483
+ const path = (issue.path ?? []).map(String);
198
484
  const joinedPath = path.join(".");
199
485
  if (location === "parameter") {
200
486
  return {
@@ -605,7 +891,6 @@ var rootDataQueryEntrySchema = z4.union([
605
891
  ]);
606
892
  var rootQuerySchema = z4.array(z4.union([rootModelQueryEntrySchema, rootDataQueryEntrySchema]));
607
893
  export {
608
- CORE,
609
894
  Codes,
610
895
  CustomHeaders,
611
896
  DATA_MIDDLEWARE,
@@ -623,7 +908,18 @@ export {
623
908
  dataListBodySchema,
624
909
  dataReadByIdBodySchema,
625
910
  dataReadFilterBodySchema,
911
+ defineRequestSchema,
626
912
  distinctBodySchema,
913
+ fromAjv,
914
+ fromArkType,
915
+ fromIoTs,
916
+ fromJoi,
917
+ fromStandardSchema,
918
+ fromSuperstruct,
919
+ fromValibot,
920
+ fromVine,
921
+ fromYup,
922
+ fromZod,
627
923
  listBodySchema,
628
924
  listQuerySchema,
629
925
  parseBody,
package/index.d.mts CHANGED
@@ -1,11 +1,58 @@
1
1
  import mongoose from 'mongoose';
2
2
  import { Response, NextFunction, Router } from 'express';
3
- import { _ as GlobalOptions, E as DefaultModelRouterOptions, N as ExtendedDefaultModelRouterOptions, ah as ModelRouterOptions, O as ExtendedModelRouterOptions, w as DataRouterOptions, M as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, a0 as GuardHook, ag as ModelRequest, u as DataRequest, bi as DataService, bj as Model, bk as Service, bl as PublicService, bh as Validation, aX as RootRouterOptions } from './service-DLKAswCS.mjs';
4
- export { bm as AccessRouterPermissionMap, bn as AccessRouterPermissions, e as AccessRouterRequest, f as AccessRouterRequestExtensions, bo as Permissions } from './service-DLKAswCS.mjs';
3
+ import { a6 as GlobalOptions, P as DefaultModelRouterOptions, X as ExtendedDefaultModelRouterOptions, aw as ModelRouterOptions, Y as ExtendedModelRouterOptions, L as DataRouterOptions, W as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, a8 as GuardHook, av as ModelRequest, J as DataRequest, cm as DataService, cn as Model, co as Service, cp as PublicService, b$ as Validation, bl as RootRouterOptions } from './parsers-Ce1grlLx.mjs';
4
+ export { cq as AccessRouterPermissionMap, cr as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, m as AjvValidatorLike, n as ArkTypeErrorsLike, o as ArkTypeLike, ab as IoTsContextEntryLike, ac as IoTsDecodeErrorLike, ad as IoTsDecoderLike, ae as JoiSchemaLike, af as JoiValidationErrorDetailLike, cs as Permissions, aR as RequestSchemaAdapter, aS as RequestSchemaFailure, aT as RequestSchemaIssue, aU as RequestSchemaLike, aV as RequestSchemaOptions, aW as RequestSchemaResult, aX as RequestSchemaSuccess, aY as RequestSchemaValidator, bw as StandardSchemaFailure, bx as StandardSchemaInferOutput, by as StandardSchemaIssue, bz as StandardSchemaPathSegment, bA as StandardSchemaResult, bB as StandardSchemaSuccess, bC as StandardSchemaV1, bI as SuperstructFailureLike, bJ as SuperstructValidateLike, bV as ValibotIssueLike, bW as ValibotPathItemLike, bX as ValibotSafeParseLike, bY as ValibotSafeParseResult, c1 as VineValidationErrorLike, c2 as VineValidationMessageLike, c3 as VineValidatorLike, c4 as YupSchemaLike, c5 as YupValidationErrorLike, c6 as defineRequestSchema, c7 as fromAjv, c8 as fromArkType, c9 as fromIoTs, ca as fromJoi, cb as fromStandardSchema, cc as fromSuperstruct, cd as fromValibot, ce as fromVine, cf as fromYup, cg as fromZod } from './parsers-Ce1grlLx.mjs';
5
5
  import JsonRouter from '@web-ts-toolkit/express-json-router';
6
6
  import 'zod';
7
7
  import 'deep-diff';
8
8
 
9
+ type OpenApiMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
10
+ type OpenApiSchema = Record<string, unknown>;
11
+ type OpenApiSchemaSource = unknown;
12
+ type OpenApiParameter = {
13
+ name: string;
14
+ in: 'path' | 'query';
15
+ required?: boolean;
16
+ description?: string;
17
+ schema?: OpenApiSchema;
18
+ };
19
+ type OpenApiResponse = {
20
+ description: string;
21
+ content?: Record<string, {
22
+ schema: OpenApiSchema;
23
+ }>;
24
+ };
25
+ type OpenApiResponses = Record<string, OpenApiResponse>;
26
+ type OpenApiRouteDescriptor = {
27
+ method: OpenApiMethod;
28
+ path: string;
29
+ operationId?: string;
30
+ summary?: string;
31
+ description?: string;
32
+ tags?: string[];
33
+ acl?: string;
34
+ deprecated?: boolean;
35
+ query?: OpenApiSchemaSource;
36
+ body?: OpenApiSchemaSource;
37
+ pathParams?: Record<string, OpenApiSchemaSource>;
38
+ responses?: OpenApiResponses;
39
+ };
40
+ type OpenApiDocumentOptions = {
41
+ title: string;
42
+ version: string;
43
+ description?: string;
44
+ servers?: Array<{
45
+ url: string;
46
+ description?: string;
47
+ }>;
48
+ };
49
+ type OpenApiRouterOptions = Partial<OpenApiDocumentOptions> & {
50
+ jsonPath?: string;
51
+ docsPath?: string | false;
52
+ swaggerUiCssUrl?: string;
53
+ swaggerUiBundleUrl?: string;
54
+ };
55
+
9
56
  declare class AccessRuntime {
10
57
  private readonly globalOptions;
11
58
  private readonly defaultModelOptions;
@@ -15,6 +62,30 @@ declare class AccessRuntime {
15
62
  private readonly modelRefs;
16
63
  private readonly modelSubs;
17
64
  private readonly modelAtts;
65
+ private readonly openApiRegistry;
66
+ registerOpenApiRoute(route: OpenApiRouteDescriptor): void;
67
+ getOpenApiRoutes(): OpenApiRouteDescriptor[];
68
+ getOpenApiSpec(info: OpenApiDocumentOptions): {
69
+ openapi: string;
70
+ info: Omit<OpenApiDocumentOptions, "servers">;
71
+ servers?: OpenApiDocumentOptions["servers"];
72
+ paths: Record<string, Record<string, {
73
+ [key: `x-${string}`]: unknown;
74
+ operationId?: string;
75
+ summary?: string;
76
+ description?: string;
77
+ tags?: string[];
78
+ deprecated?: boolean;
79
+ parameters?: OpenApiParameter[];
80
+ requestBody?: {
81
+ required?: boolean;
82
+ content: Record<string, {
83
+ schema: OpenApiSchema;
84
+ }>;
85
+ };
86
+ responses: OpenApiResponses;
87
+ }>>;
88
+ };
18
89
  setGlobalOptions(options: GlobalOptions): void;
19
90
  setGlobalOption<K extends keyof GlobalOptions>(key: K, value: GlobalOptions[K]): void;
20
91
  getGlobalOptions(): GlobalOptions;
@@ -76,6 +147,7 @@ declare class DataRouter<TData = unknown> {
76
147
  private getRequestSchema;
77
148
  getService(req: DataRequest): DataService<TData>;
78
149
  private assertAllowed;
150
+ private registerOpenApiRoute;
79
151
  private setCollectionRoutes;
80
152
  private setDocumentRoutes;
81
153
  set<K extends keyof DataRouterOptions<TData>>(key: K, value: DataRouterOptions<TData>[K]): this;
@@ -112,6 +184,7 @@ declare class ModelRouter<TModel = unknown> {
112
184
  getService(req: ModelRequest): Service<TModel>;
113
185
  getPublicService(req: ModelRequest): PublicService<TModel>;
114
186
  private assertAllowed;
187
+ private registerOpenApiRoute;
115
188
  private setCollectionRoutes;
116
189
  private setDocumentRoutes;
117
190
  private setSubDocumentRoutes;
@@ -251,6 +324,7 @@ declare class RootRouter {
251
324
  private readonly modelOperations;
252
325
  private readonly dataOperations;
253
326
  constructor(options?: RootRouterOptions, runtime?: AccessRuntime);
327
+ private registerOpenApiRoute;
254
328
  private wrapResult;
255
329
  private hasTarget;
256
330
  private isAllowed;
@@ -261,6 +335,8 @@ declare class RootRouter {
261
335
  get routes(): Router;
262
336
  }
263
337
 
338
+ declare function createOpenApiRouter(runtime: AccessRuntime, options?: OpenApiRouterOptions): Router;
339
+
264
340
  type AccessRouterInstance = ModelRouter<any> | DataRouter<any> | RootRouter;
265
341
  type CombinedRouteInput = Router | AccessRouterInstance;
266
342
  declare function combineRoutes(...inputs: CombinedRouteInput[]): Router;
@@ -296,6 +372,7 @@ type CreateRouter = {
296
372
  type CreateDataRouter = {
297
373
  <TData>(dataName: string, options: DataRouterOptions<TData>): DataRouter<TData>;
298
374
  };
375
+ type CreateRuntimeOpenApiRouter = (options?: OpenApiRouterOptions) => Router;
299
376
  type WttSet = {
300
377
  <K extends keyof GlobalOptions>(key: K, value: GlobalOptions[K]): void;
301
378
  (options: {
@@ -306,6 +383,7 @@ interface Wtt {
306
383
  runtime: AccessRuntime;
307
384
  createRouter: CreateRouter;
308
385
  createDataRouter: CreateDataRouter;
386
+ createOpenApiRouter: CreateRuntimeOpenApiRouter;
309
387
  combineRoutes: typeof combineRoutes;
310
388
  set: WttSet;
311
389
  setGlobalOptions: typeof setGlobalOptions;
@@ -330,4 +408,4 @@ type AccessRuntimeApi = typeof macl & Wtt;
330
408
  declare function createAccessRuntime(): AccessRuntimeApi;
331
409
  declare const acl: AccessRuntimeApi;
332
410
 
333
- export { AccessRuntime, type AccessRuntimeApi, type CombinedRouteInput, DataRouter, DataRouterOptions, GlobalOptions, ModelRouter, ModelRouterOptions, RootRouter, RootRouterOptions, acl, combineRoutes, createAccessRuntime, acl as default, getDefaultModelOption, getDefaultModelOptions, getGlobalOption, getGlobalOptions, getModelJsonSchema, getModelNames, getModelOption, getModelOptions, guard, permissionsPlugin, setDefaultModelOption, setDefaultModelOptions, setGlobalOption, setGlobalOptions, setModelOption, setModelOptions };
411
+ export { AccessRuntime, type AccessRuntimeApi, type CombinedRouteInput, DataRouter, DataRouterOptions, GlobalOptions, ModelRouter, ModelRouterOptions, type OpenApiDocumentOptions, type OpenApiMethod, type OpenApiRouteDescriptor, type OpenApiRouterOptions, RootRouter, RootRouterOptions, acl, combineRoutes, createAccessRuntime, createOpenApiRouter, acl as default, getDefaultModelOption, getDefaultModelOptions, getGlobalOption, getGlobalOptions, getModelJsonSchema, getModelNames, getModelOption, getModelOptions, guard, permissionsPlugin, setDefaultModelOption, setDefaultModelOptions, setGlobalOption, setGlobalOptions, setModelOption, setModelOptions };
package/index.d.ts CHANGED
@@ -1,11 +1,58 @@
1
1
  import mongoose from 'mongoose';
2
2
  import { Response, NextFunction, Router } from 'express';
3
- import { _ as GlobalOptions, E as DefaultModelRouterOptions, N as ExtendedDefaultModelRouterOptions, ah as ModelRouterOptions, O as ExtendedModelRouterOptions, w as DataRouterOptions, M as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, a0 as GuardHook, ag as ModelRequest, u as DataRequest, bi as DataService, bj as Model, bk as Service, bl as PublicService, bh as Validation, aX as RootRouterOptions } from './service-DLKAswCS.js';
4
- export { bm as AccessRouterPermissionMap, bn as AccessRouterPermissions, e as AccessRouterRequest, f as AccessRouterRequestExtensions, bo as Permissions } from './service-DLKAswCS.js';
3
+ import { a6 as GlobalOptions, P as DefaultModelRouterOptions, X as ExtendedDefaultModelRouterOptions, aw as ModelRouterOptions, Y as ExtendedModelRouterOptions, L as DataRouterOptions, W as ExtendedDataRouterOptions, A as AccessRouterBaseRequest, a8 as GuardHook, av as ModelRequest, J as DataRequest, cm as DataService, cn as Model, co as Service, cp as PublicService, b$ as Validation, bl as RootRouterOptions } from './parsers-Ce1grlLx.js';
4
+ export { cq as AccessRouterPermissionMap, cr as AccessRouterPermissions, c as AccessRouterRequest, d as AccessRouterRequestExtensions, l as AjvErrorObjectLike, m as AjvValidatorLike, n as ArkTypeErrorsLike, o as ArkTypeLike, ab as IoTsContextEntryLike, ac as IoTsDecodeErrorLike, ad as IoTsDecoderLike, ae as JoiSchemaLike, af as JoiValidationErrorDetailLike, cs as Permissions, aR as RequestSchemaAdapter, aS as RequestSchemaFailure, aT as RequestSchemaIssue, aU as RequestSchemaLike, aV as RequestSchemaOptions, aW as RequestSchemaResult, aX as RequestSchemaSuccess, aY as RequestSchemaValidator, bw as StandardSchemaFailure, bx as StandardSchemaInferOutput, by as StandardSchemaIssue, bz as StandardSchemaPathSegment, bA as StandardSchemaResult, bB as StandardSchemaSuccess, bC as StandardSchemaV1, bI as SuperstructFailureLike, bJ as SuperstructValidateLike, bV as ValibotIssueLike, bW as ValibotPathItemLike, bX as ValibotSafeParseLike, bY as ValibotSafeParseResult, c1 as VineValidationErrorLike, c2 as VineValidationMessageLike, c3 as VineValidatorLike, c4 as YupSchemaLike, c5 as YupValidationErrorLike, c6 as defineRequestSchema, c7 as fromAjv, c8 as fromArkType, c9 as fromIoTs, ca as fromJoi, cb as fromStandardSchema, cc as fromSuperstruct, cd as fromValibot, ce as fromVine, cf as fromYup, cg as fromZod } from './parsers-Ce1grlLx.js';
5
5
  import JsonRouter from '@web-ts-toolkit/express-json-router';
6
6
  import 'zod';
7
7
  import 'deep-diff';
8
8
 
9
+ type OpenApiMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
10
+ type OpenApiSchema = Record<string, unknown>;
11
+ type OpenApiSchemaSource = unknown;
12
+ type OpenApiParameter = {
13
+ name: string;
14
+ in: 'path' | 'query';
15
+ required?: boolean;
16
+ description?: string;
17
+ schema?: OpenApiSchema;
18
+ };
19
+ type OpenApiResponse = {
20
+ description: string;
21
+ content?: Record<string, {
22
+ schema: OpenApiSchema;
23
+ }>;
24
+ };
25
+ type OpenApiResponses = Record<string, OpenApiResponse>;
26
+ type OpenApiRouteDescriptor = {
27
+ method: OpenApiMethod;
28
+ path: string;
29
+ operationId?: string;
30
+ summary?: string;
31
+ description?: string;
32
+ tags?: string[];
33
+ acl?: string;
34
+ deprecated?: boolean;
35
+ query?: OpenApiSchemaSource;
36
+ body?: OpenApiSchemaSource;
37
+ pathParams?: Record<string, OpenApiSchemaSource>;
38
+ responses?: OpenApiResponses;
39
+ };
40
+ type OpenApiDocumentOptions = {
41
+ title: string;
42
+ version: string;
43
+ description?: string;
44
+ servers?: Array<{
45
+ url: string;
46
+ description?: string;
47
+ }>;
48
+ };
49
+ type OpenApiRouterOptions = Partial<OpenApiDocumentOptions> & {
50
+ jsonPath?: string;
51
+ docsPath?: string | false;
52
+ swaggerUiCssUrl?: string;
53
+ swaggerUiBundleUrl?: string;
54
+ };
55
+
9
56
  declare class AccessRuntime {
10
57
  private readonly globalOptions;
11
58
  private readonly defaultModelOptions;
@@ -15,6 +62,30 @@ declare class AccessRuntime {
15
62
  private readonly modelRefs;
16
63
  private readonly modelSubs;
17
64
  private readonly modelAtts;
65
+ private readonly openApiRegistry;
66
+ registerOpenApiRoute(route: OpenApiRouteDescriptor): void;
67
+ getOpenApiRoutes(): OpenApiRouteDescriptor[];
68
+ getOpenApiSpec(info: OpenApiDocumentOptions): {
69
+ openapi: string;
70
+ info: Omit<OpenApiDocumentOptions, "servers">;
71
+ servers?: OpenApiDocumentOptions["servers"];
72
+ paths: Record<string, Record<string, {
73
+ [key: `x-${string}`]: unknown;
74
+ operationId?: string;
75
+ summary?: string;
76
+ description?: string;
77
+ tags?: string[];
78
+ deprecated?: boolean;
79
+ parameters?: OpenApiParameter[];
80
+ requestBody?: {
81
+ required?: boolean;
82
+ content: Record<string, {
83
+ schema: OpenApiSchema;
84
+ }>;
85
+ };
86
+ responses: OpenApiResponses;
87
+ }>>;
88
+ };
18
89
  setGlobalOptions(options: GlobalOptions): void;
19
90
  setGlobalOption<K extends keyof GlobalOptions>(key: K, value: GlobalOptions[K]): void;
20
91
  getGlobalOptions(): GlobalOptions;
@@ -76,6 +147,7 @@ declare class DataRouter<TData = unknown> {
76
147
  private getRequestSchema;
77
148
  getService(req: DataRequest): DataService<TData>;
78
149
  private assertAllowed;
150
+ private registerOpenApiRoute;
79
151
  private setCollectionRoutes;
80
152
  private setDocumentRoutes;
81
153
  set<K extends keyof DataRouterOptions<TData>>(key: K, value: DataRouterOptions<TData>[K]): this;
@@ -112,6 +184,7 @@ declare class ModelRouter<TModel = unknown> {
112
184
  getService(req: ModelRequest): Service<TModel>;
113
185
  getPublicService(req: ModelRequest): PublicService<TModel>;
114
186
  private assertAllowed;
187
+ private registerOpenApiRoute;
115
188
  private setCollectionRoutes;
116
189
  private setDocumentRoutes;
117
190
  private setSubDocumentRoutes;
@@ -251,6 +324,7 @@ declare class RootRouter {
251
324
  private readonly modelOperations;
252
325
  private readonly dataOperations;
253
326
  constructor(options?: RootRouterOptions, runtime?: AccessRuntime);
327
+ private registerOpenApiRoute;
254
328
  private wrapResult;
255
329
  private hasTarget;
256
330
  private isAllowed;
@@ -261,6 +335,8 @@ declare class RootRouter {
261
335
  get routes(): Router;
262
336
  }
263
337
 
338
+ declare function createOpenApiRouter(runtime: AccessRuntime, options?: OpenApiRouterOptions): Router;
339
+
264
340
  type AccessRouterInstance = ModelRouter<any> | DataRouter<any> | RootRouter;
265
341
  type CombinedRouteInput = Router | AccessRouterInstance;
266
342
  declare function combineRoutes(...inputs: CombinedRouteInput[]): Router;
@@ -296,6 +372,7 @@ type CreateRouter = {
296
372
  type CreateDataRouter = {
297
373
  <TData>(dataName: string, options: DataRouterOptions<TData>): DataRouter<TData>;
298
374
  };
375
+ type CreateRuntimeOpenApiRouter = (options?: OpenApiRouterOptions) => Router;
299
376
  type WttSet = {
300
377
  <K extends keyof GlobalOptions>(key: K, value: GlobalOptions[K]): void;
301
378
  (options: {
@@ -306,6 +383,7 @@ interface Wtt {
306
383
  runtime: AccessRuntime;
307
384
  createRouter: CreateRouter;
308
385
  createDataRouter: CreateDataRouter;
386
+ createOpenApiRouter: CreateRuntimeOpenApiRouter;
309
387
  combineRoutes: typeof combineRoutes;
310
388
  set: WttSet;
311
389
  setGlobalOptions: typeof setGlobalOptions;
@@ -330,4 +408,4 @@ type AccessRuntimeApi = typeof macl & Wtt;
330
408
  declare function createAccessRuntime(): AccessRuntimeApi;
331
409
  declare const acl: AccessRuntimeApi;
332
410
 
333
- export { AccessRuntime, type AccessRuntimeApi, type CombinedRouteInput, DataRouter, DataRouterOptions, GlobalOptions, ModelRouter, ModelRouterOptions, RootRouter, RootRouterOptions, acl, combineRoutes, createAccessRuntime, acl as default, getDefaultModelOption, getDefaultModelOptions, getGlobalOption, getGlobalOptions, getModelJsonSchema, getModelNames, getModelOption, getModelOptions, guard, permissionsPlugin, setDefaultModelOption, setDefaultModelOptions, setGlobalOption, setGlobalOptions, setModelOption, setModelOptions };
411
+ export { AccessRuntime, type AccessRuntimeApi, type CombinedRouteInput, DataRouter, DataRouterOptions, GlobalOptions, ModelRouter, ModelRouterOptions, type OpenApiDocumentOptions, type OpenApiMethod, type OpenApiRouteDescriptor, type OpenApiRouterOptions, RootRouter, RootRouterOptions, acl, combineRoutes, createAccessRuntime, createOpenApiRouter, acl as default, getDefaultModelOption, getDefaultModelOptions, getGlobalOption, getGlobalOptions, getModelJsonSchema, getModelNames, getModelOption, getModelOptions, guard, permissionsPlugin, setDefaultModelOption, setDefaultModelOptions, setGlobalOption, setGlobalOptions, setModelOption, setModelOptions };