@kontract/adonis 0.1.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.
Files changed (46) hide show
  1. package/README.md +507 -0
  2. package/dist/adapters/controller-registrar.d.ts +313 -0
  3. package/dist/adapters/controller-registrar.d.ts.map +1 -0
  4. package/dist/adapters/controller-registrar.js +324 -0
  5. package/dist/adapters/controller-registrar.js.map +1 -0
  6. package/dist/adapters/index.d.ts +2 -0
  7. package/dist/adapters/index.d.ts.map +1 -0
  8. package/dist/adapters/index.js +2 -0
  9. package/dist/adapters/index.js.map +1 -0
  10. package/dist/adapters/route-registrar.d.ts +53 -0
  11. package/dist/adapters/route-registrar.d.ts.map +1 -0
  12. package/dist/adapters/route-registrar.js +139 -0
  13. package/dist/adapters/route-registrar.js.map +1 -0
  14. package/dist/adapters/router.d.ts +37 -0
  15. package/dist/adapters/router.d.ts.map +1 -0
  16. package/dist/adapters/router.js +129 -0
  17. package/dist/adapters/router.js.map +1 -0
  18. package/dist/builder/index.d.ts +2 -0
  19. package/dist/builder/index.d.ts.map +1 -0
  20. package/dist/builder/index.js +3 -0
  21. package/dist/builder/index.js.map +1 -0
  22. package/dist/builder/openapi-builder.d.ts +100 -0
  23. package/dist/builder/openapi-builder.d.ts.map +1 -0
  24. package/dist/builder/openapi-builder.js +388 -0
  25. package/dist/builder/openapi-builder.js.map +1 -0
  26. package/dist/index.d.ts +34 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +45 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/serializers/index.d.ts +2 -0
  31. package/dist/serializers/index.d.ts.map +1 -0
  32. package/dist/serializers/index.js +2 -0
  33. package/dist/serializers/index.js.map +1 -0
  34. package/dist/serializers/lucid.d.ts +100 -0
  35. package/dist/serializers/lucid.d.ts.map +1 -0
  36. package/dist/serializers/lucid.js +114 -0
  37. package/dist/serializers/lucid.js.map +1 -0
  38. package/dist/validation/ajv.d.ts +42 -0
  39. package/dist/validation/ajv.d.ts.map +1 -0
  40. package/dist/validation/ajv.js +170 -0
  41. package/dist/validation/ajv.js.map +1 -0
  42. package/dist/validation/index.d.ts +2 -0
  43. package/dist/validation/index.d.ts.map +1 -0
  44. package/dist/validation/index.js +3 -0
  45. package/dist/validation/index.js.map +1 -0
  46. package/package.json +96 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/adapters/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,iBAAiB,EACjB,SAAS,GAMV,MAAM,2BAA2B,CAAA"}
@@ -0,0 +1,53 @@
1
+ import type { Router, HttpContext } from '@adonisjs/core/http';
2
+ import type { TSchema } from '@sinclair/typebox';
3
+ /**
4
+ * Validation schemas for request data.
5
+ */
6
+ export interface ValidationSchemas {
7
+ body?: TSchema;
8
+ query?: TSchema;
9
+ params?: TSchema;
10
+ }
11
+ /**
12
+ * Extended HttpContext with validated data and auth.
13
+ */
14
+ export interface ValidatedContext extends HttpContext {
15
+ validatedBody?: unknown;
16
+ validatedQuery?: unknown;
17
+ validatedParams?: unknown;
18
+ auth: {
19
+ authenticate(): Promise<unknown>;
20
+ };
21
+ }
22
+ /**
23
+ * Validator function type.
24
+ */
25
+ export type ValidateFn = <T>(schema: TSchema, data: unknown) => T;
26
+ /**
27
+ * Options for registering decorator routes.
28
+ */
29
+ export interface RegisterRoutesOptions {
30
+ /** Validation function (e.g., AJV validate) */
31
+ validate: ValidateFn;
32
+ }
33
+ /**
34
+ * Registers all routes defined via @Endpoint decorators.
35
+ * Call this in your routes.ts file after importing decorated controllers.
36
+ *
37
+ * @example
38
+ * ```typescript
39
+ * // start/routes.ts
40
+ * import router from '@adonisjs/core/services/router'
41
+ * import { registerDecoratorRoutes } from '@kontract/adonis'
42
+ * import { validate } from '#validators/ajv'
43
+ *
44
+ * // Import controllers to trigger decorator registration
45
+ * import '#controllers/games_controller'
46
+ * import '#controllers/books_controller'
47
+ *
48
+ * // Register all decorated routes
49
+ * registerDecoratorRoutes(router, { validate })
50
+ * ```
51
+ */
52
+ export declare function registerDecoratorRoutes(router: Router, options: RegisterRoutesOptions): void;
53
+ //# sourceMappingURL=route-registrar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-registrar.d.ts","sourceRoot":"","sources":["../../src/adapters/route-registrar.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAE9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAShD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;IACzB,IAAI,EAAE;QACJ,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAAA;KACjC,CAAA;CACF;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,CAAA;AAEjE;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,+CAA+C;IAC/C,QAAQ,EAAE,UAAU,CAAA;CACrB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,GAC7B,IAAI,CAaN"}
@@ -0,0 +1,139 @@
1
+ import { getApiMetadata, getEndpointMetadata, getRegisteredControllers, isBinaryResponse, } from 'kontract';
2
+ /**
3
+ * Registers all routes defined via @Endpoint decorators.
4
+ * Call this in your routes.ts file after importing decorated controllers.
5
+ *
6
+ * @example
7
+ * ```typescript
8
+ * // start/routes.ts
9
+ * import router from '@adonisjs/core/services/router'
10
+ * import { registerDecoratorRoutes } from '@kontract/adonis'
11
+ * import { validate } from '#validators/ajv'
12
+ *
13
+ * // Import controllers to trigger decorator registration
14
+ * import '#controllers/games_controller'
15
+ * import '#controllers/books_controller'
16
+ *
17
+ * // Register all decorated routes
18
+ * registerDecoratorRoutes(router, { validate })
19
+ * ```
20
+ */
21
+ export function registerDecoratorRoutes(router, options) {
22
+ const controllers = getRegisteredControllers();
23
+ for (const controller of controllers) {
24
+ const apiMeta = getApiMetadata(controller);
25
+ const endpoints = getEndpointMetadata(controller);
26
+ if (!apiMeta || endpoints.length === 0)
27
+ continue;
28
+ for (const endpoint of endpoints) {
29
+ registerEndpoint(router, controller, endpoint, options.validate);
30
+ }
31
+ }
32
+ }
33
+ /**
34
+ * Register a single endpoint.
35
+ */
36
+ function registerEndpoint(router, Controller, endpoint, validate) {
37
+ const { method, path, methodName, auth, body, query, params, middleware } = endpoint;
38
+ // Build validation schemas
39
+ const validationSchemas = {};
40
+ if (body)
41
+ validationSchemas.body = body;
42
+ if (query)
43
+ validationSchemas.query = query;
44
+ if (params)
45
+ validationSchemas.params = params;
46
+ // Create handler
47
+ const handler = createHandler(Controller, methodName, auth, validationSchemas, validate);
48
+ // Register the route
49
+ let route;
50
+ switch (method) {
51
+ case 'get':
52
+ route = router.get(path, handler);
53
+ break;
54
+ case 'post':
55
+ route = router.post(path, handler);
56
+ break;
57
+ case 'put':
58
+ route = router.put(path, handler);
59
+ break;
60
+ case 'patch':
61
+ route = router.patch(path, handler);
62
+ break;
63
+ case 'delete':
64
+ route = router.delete(path, handler);
65
+ break;
66
+ }
67
+ // Apply additional middleware (cast to expected type)
68
+ if (middleware && Array.isArray(middleware) && middleware.length > 0) {
69
+ route.use(middleware);
70
+ }
71
+ }
72
+ /**
73
+ * Create a request handler for an endpoint.
74
+ */
75
+ function createHandler(Controller, methodName, auth, validationSchemas, validate) {
76
+ return async (ctx) => {
77
+ const validatedCtx = ctx;
78
+ // Handle authentication
79
+ if (auth === 'required') {
80
+ await validatedCtx.auth.authenticate();
81
+ }
82
+ else if (auth === 'optional') {
83
+ try {
84
+ await validatedCtx.auth.authenticate();
85
+ }
86
+ catch {
87
+ // Ignore auth failure for optional auth
88
+ }
89
+ }
90
+ // Validate request data
91
+ if (validationSchemas.body) {
92
+ validatedCtx.validatedBody = validate(validationSchemas.body, ctx.request.body());
93
+ }
94
+ if (validationSchemas.query) {
95
+ validatedCtx.validatedQuery = validate(validationSchemas.query, ctx.request.qs());
96
+ }
97
+ if (validationSchemas.params) {
98
+ validatedCtx.validatedParams = validate(validationSchemas.params, ctx.params);
99
+ }
100
+ const controller = await ctx.containerResolver.make(Controller);
101
+ const result = await controller[methodName](ctx, validatedCtx.validatedBody, validatedCtx.validatedQuery, validatedCtx.validatedParams);
102
+ // Handle the response
103
+ return handleResponse(ctx, result);
104
+ };
105
+ }
106
+ /**
107
+ * Handle the response from a controller method.
108
+ */
109
+ function handleResponse(ctx, result) {
110
+ // Handle binary response (file downloads)
111
+ if (isBinaryResponse(result)) {
112
+ ctx.response.header('Content-Type', result.contentType);
113
+ if (result.filename) {
114
+ ctx.response.header('Content-Disposition', `attachment; filename="${result.filename}"`);
115
+ }
116
+ return ctx.response.status(result.status).send(result.data);
117
+ }
118
+ // Handle structured API response
119
+ if (isApiResponse(result)) {
120
+ if (result.status === 204) {
121
+ return ctx.response.noContent();
122
+ }
123
+ return ctx.response.status(result.status).json(result.data);
124
+ }
125
+ // Return raw result for backwards compatibility
126
+ return result;
127
+ }
128
+ /**
129
+ * Type guard for API responses.
130
+ */
131
+ function isApiResponse(value) {
132
+ return (value !== null
133
+ && typeof value === 'object'
134
+ && 'status' in value
135
+ && 'data' in value
136
+ && !('binary' in value)
137
+ && typeof value.status === 'number');
138
+ }
139
+ //# sourceMappingURL=route-registrar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route-registrar.js","sourceRoot":"","sources":["../../src/adapters/route-registrar.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ import type { Router, HttpContext } from '@adonisjs/core/http';
2
+ import type { TSchema } from '@sinclair/typebox';
3
+ import { type RouterAdapter } from 'kontract';
4
+ /**
5
+ * Validation schemas for request data.
6
+ */
7
+ export interface ValidationSchemas {
8
+ body?: TSchema;
9
+ query?: TSchema;
10
+ params?: TSchema;
11
+ }
12
+ /**
13
+ * Extended HttpContext with validated data.
14
+ */
15
+ export interface ValidatedContext extends HttpContext {
16
+ validatedBody?: unknown;
17
+ validatedQuery?: unknown;
18
+ validatedParams?: unknown;
19
+ }
20
+ /**
21
+ * Validator function type.
22
+ */
23
+ export type ValidateFn = <T>(schema: TSchema, data: unknown) => T;
24
+ /**
25
+ * Options for creating the AdonisJS router adapter.
26
+ */
27
+ export interface AdonisRouterAdapterOptions {
28
+ /** The AdonisJS router instance */
29
+ router: Router;
30
+ /** Validation function (e.g., AJV validate) */
31
+ validate: ValidateFn;
32
+ }
33
+ /**
34
+ * Create an AdonisJS router adapter.
35
+ */
36
+ export declare function createAdonisRouterAdapter(options: AdonisRouterAdapterOptions): RouterAdapter;
37
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../src/adapters/router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EACL,KAAK,aAAa,EAKnB,MAAM,0BAA0B,CAAA;AAEjC;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAiB,SAAQ,WAAW;IACnD,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B;AAED;;GAEG;AACH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,KAAK,CAAC,CAAA;AAEjE;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,mCAAmC;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,+CAA+C;IAC/C,QAAQ,EAAE,UAAU,CAAA;CACrB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,aAAa,CA4Df"}
@@ -0,0 +1,129 @@
1
+ import { isBinaryResponse, } from '@blog/openapi-decorators';
2
+ /**
3
+ * Create an AdonisJS router adapter.
4
+ */
5
+ export function createAdonisRouterAdapter(options) {
6
+ const { router, validate } = options;
7
+ const registeredRoutes = [];
8
+ return {
9
+ register(method, path, _handler, metadata) {
10
+ const { methodName, auth, body, query, params, middleware } = metadata;
11
+ // Build validation schemas
12
+ const validationSchemas = {};
13
+ if (body)
14
+ validationSchemas.body = body;
15
+ if (query)
16
+ validationSchemas.query = query;
17
+ if (params)
18
+ validationSchemas.params = params;
19
+ // Create the handler
20
+ const handler = createHandler(metadata, methodName, auth, validationSchemas, validate);
21
+ // Register the route
22
+ let route;
23
+ switch (method) {
24
+ case 'get':
25
+ route = router.get(path, handler);
26
+ break;
27
+ case 'post':
28
+ route = router.post(path, handler);
29
+ break;
30
+ case 'put':
31
+ route = router.put(path, handler);
32
+ break;
33
+ case 'patch':
34
+ route = router.patch(path, handler);
35
+ break;
36
+ case 'delete':
37
+ route = router.delete(path, handler);
38
+ break;
39
+ }
40
+ // Apply additional middleware
41
+ if (middleware && Array.isArray(middleware) && middleware.length > 0) {
42
+ route.use(middleware);
43
+ }
44
+ registeredRoutes.push({ method, path });
45
+ },
46
+ getRoutes() {
47
+ return registeredRoutes;
48
+ },
49
+ };
50
+ }
51
+ /**
52
+ * Create a request handler for an endpoint.
53
+ */
54
+ function createHandler(metadata, methodName, auth, validationSchemas, validate) {
55
+ // Get the controller class from metadata
56
+ // This will be set by the route registrar
57
+ let Controller = null;
58
+ return async (ctx) => {
59
+ const validatedCtx = ctx;
60
+ // Handle authentication
61
+ if (auth === 'required') {
62
+ await ctx.auth.authenticate();
63
+ }
64
+ else if (auth === 'optional') {
65
+ try {
66
+ await ctx.auth.authenticate();
67
+ }
68
+ catch {
69
+ // Ignore auth failure for optional auth
70
+ }
71
+ }
72
+ // Validate request data
73
+ if (validationSchemas.body) {
74
+ validatedCtx.validatedBody = validate(validationSchemas.body, ctx.request.body());
75
+ }
76
+ if (validationSchemas.query) {
77
+ validatedCtx.validatedQuery = validate(validationSchemas.query, ctx.request.qs());
78
+ }
79
+ if (validationSchemas.params) {
80
+ validatedCtx.validatedParams = validate(validationSchemas.params, ctx.params);
81
+ }
82
+ // Resolve controller from container
83
+ // The Controller will be passed via the metadata
84
+ if (!Controller) {
85
+ // For now, we'll need to get it from the route's controller reference
86
+ // This will be handled by the registration function
87
+ throw new Error(`Controller not found for endpoint ${methodName}. ` +
88
+ 'Use registerDecoratorRoutes() to register routes.');
89
+ }
90
+ const controller = await ctx.containerResolver.make(Controller);
91
+ const result = await controller[methodName](ctx, validatedCtx.validatedBody, validatedCtx.validatedQuery, validatedCtx.validatedParams);
92
+ // Handle the response
93
+ return handleResponse(ctx, result);
94
+ };
95
+ }
96
+ /**
97
+ * Handle the response from a controller method.
98
+ */
99
+ function handleResponse(ctx, result) {
100
+ // Handle binary response (file downloads)
101
+ if (isBinaryResponse(result)) {
102
+ ctx.response.header('Content-Type', result.contentType);
103
+ if (result.filename) {
104
+ ctx.response.header('Content-Disposition', `attachment; filename="${result.filename}"`);
105
+ }
106
+ return ctx.response.status(result.status).send(result.data);
107
+ }
108
+ // Handle structured API response
109
+ if (isApiResponse(result)) {
110
+ if (result.status === 204) {
111
+ return ctx.response.noContent();
112
+ }
113
+ return ctx.response.status(result.status).json(result.data);
114
+ }
115
+ // Return raw result for backwards compatibility
116
+ return result;
117
+ }
118
+ /**
119
+ * Type guard for API responses.
120
+ */
121
+ function isApiResponse(value) {
122
+ return (value !== null &&
123
+ typeof value === 'object' &&
124
+ 'status' in value &&
125
+ 'data' in value &&
126
+ !('binary' in value) &&
127
+ typeof value.status === 'number');
128
+ }
129
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../src/adapters/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export { OpenApiBuilder, type OpenApiBuilderOptions } from 'kontract';
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,KAAK,qBAAqB,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,3 @@
1
+ // Re-export from core package
2
+ export { OpenApiBuilder } from 'kontract';
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/builder/index.ts"],"names":[],"mappings":"AAAA,8BAA8B;AAC9B,OAAO,EAAE,cAAc,EAA8B,MAAM,UAAU,CAAA"}
@@ -0,0 +1,100 @@
1
+ import { type OpenApiDocument, type OpenApiVersion } from 'kontract';
2
+ /**
3
+ * Options for building the OpenAPI document.
4
+ */
5
+ export interface OpenApiBuilderOptions {
6
+ title: string;
7
+ description: string;
8
+ version: string;
9
+ servers: Array<{
10
+ url: string;
11
+ description: string;
12
+ }>;
13
+ /**
14
+ * OpenAPI specification version.
15
+ * @default '3.1.0'
16
+ */
17
+ openapiVersion?: OpenApiVersion;
18
+ /**
19
+ * Security scheme configuration.
20
+ * @default Bearer JWT authentication
21
+ */
22
+ securityScheme?: {
23
+ name: string;
24
+ type: 'http' | 'apiKey' | 'oauth2';
25
+ scheme?: string;
26
+ bearerFormat?: string;
27
+ description?: string;
28
+ };
29
+ }
30
+ /**
31
+ * Builds an OpenAPI specification from registered @Api and @Endpoint decorators.
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const builder = new OpenApiBuilder({
36
+ * title: 'My API',
37
+ * description: 'API description',
38
+ * version: '1.0.0',
39
+ * servers: [{ url: 'http://localhost:3333', description: 'Development' }],
40
+ * })
41
+ *
42
+ * const spec = builder.build()
43
+ * ```
44
+ */
45
+ export declare class OpenApiBuilder {
46
+ private document;
47
+ private schemas;
48
+ private tags;
49
+ private securitySchemeName;
50
+ constructor(options: OpenApiBuilderOptions);
51
+ /**
52
+ * Build the OpenAPI document from registered decorators.
53
+ */
54
+ build(): OpenApiDocument;
55
+ /**
56
+ * Process a single endpoint and add it to the document.
57
+ */
58
+ private processEndpoint;
59
+ /**
60
+ * Build file upload request body.
61
+ */
62
+ private buildFileRequestBody;
63
+ /**
64
+ * Build parameters from endpoint metadata.
65
+ */
66
+ private buildParameters;
67
+ /**
68
+ * Convert a TypeBox schema to OpenAPI parameters.
69
+ */
70
+ private schemaToParameters;
71
+ /**
72
+ * Build responses from endpoint metadata.
73
+ */
74
+ private buildResponses;
75
+ /**
76
+ * Register a schema and return its name.
77
+ */
78
+ private registerSchema;
79
+ /**
80
+ * Extract and register nested schemas with $id.
81
+ */
82
+ private extractNestedSchemas;
83
+ /**
84
+ * Convert TypeBox schema to JSON Schema (for OpenAPI).
85
+ */
86
+ private toJsonSchema;
87
+ /**
88
+ * Remove TypeBox-specific properties from schema.
89
+ */
90
+ private removeTypeBoxProps;
91
+ /**
92
+ * Generate an operation ID from endpoint metadata.
93
+ */
94
+ private generateOperationId;
95
+ /**
96
+ * Get default description for a status code.
97
+ */
98
+ private defaultDescription;
99
+ }
100
+ //# sourceMappingURL=openapi-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"openapi-builder.d.ts","sourceRoot":"","sources":["../../src/builder/openapi-builder.ts"],"names":[],"mappings":"AACA,OAAO,EAML,KAAK,eAAe,EACpB,KAAK,cAAc,EAMpB,MAAM,0BAA0B,CAAA;AAEjC;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACpD;;;OAGG;IACH,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B;;;OAGG;IACH,cAAc,CAAC,EAAE;QACf,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAA;QAClC,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,YAAY,CAAC,EAAE,MAAM,CAAA;QACrB,WAAW,CAAC,EAAE,MAAM,CAAA;KACrB,CAAA;CACF;AAED;;;;;;;;;;;;;;GAcG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,IAAI,CAAwC;IACpD,OAAO,CAAC,kBAAkB,CAAQ;gBAEtB,OAAO,EAAE,qBAAqB;IAgC1C;;OAEG;IACH,KAAK,IAAI,eAAe;IA+BxB;;OAEG;IACH,OAAO,CAAC,eAAe;IA4DvB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAgD5B;;OAEG;IACH,OAAO,CAAC,eAAe;IAwCvB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0B1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA0CtB;;OAEG;IACH,OAAO,CAAC,cAAc;IAWtB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAqB5B;;OAEG;IACH,OAAO,CAAC,YAAY;IAKpB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA8B1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAgC3B;;OAEG;IACH,OAAO,CAAC,kBAAkB;CAc3B"}