@byyuurin/nitro-openapi 0.0.1 → 0.0.3
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 +87 -0
- package/dist/index.cjs +159 -0
- package/dist/index.d.cts +105 -0
- package/dist/index.d.mts +58 -17
- package/dist/index.d.ts +58 -17
- package/dist/index.mjs +11 -11
- package/package.json +18 -17
package/README.md
CHANGED
|
@@ -1 +1,88 @@
|
|
|
1
1
|
# @byyuurin/nitro-openapi
|
|
2
|
+
|
|
3
|
+
> WIP
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i -D @byyuurin/nitro-openapi
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
Enable openApi
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// nitor.config.ts
|
|
17
|
+
export default defineNitroConfig({
|
|
18
|
+
experimental: {
|
|
19
|
+
openAPI: true,
|
|
20
|
+
},
|
|
21
|
+
})
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Create nitor plugin:
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
// plugins/swagger.ts
|
|
28
|
+
import { createOpenApiRegister } from '@byyuurin/nitro-openapi'
|
|
29
|
+
import type { OpenAPI3 } from 'openapi-typescript'
|
|
30
|
+
|
|
31
|
+
export const { register, merge, configExtends } = createOpenApiRegister({
|
|
32
|
+
// ...
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
export default defineNitroPlugin((nitro) => {
|
|
36
|
+
nitro.hooks.hook('beforeResponse', (event, context) => {
|
|
37
|
+
if (!/openapi.json/.test(event.path))
|
|
38
|
+
return
|
|
39
|
+
|
|
40
|
+
// merge config
|
|
41
|
+
const config = context.body as OpenAPI3
|
|
42
|
+
context.body = merge(config)
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Auto import
|
|
48
|
+
|
|
49
|
+
```ts
|
|
50
|
+
// utils/swagger.ts
|
|
51
|
+
export { register } from '../plugins/swagger'
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Or custom register
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
// utils/swagger.ts
|
|
58
|
+
import type { PathOperationItem, PathOperationMethod } from '@byyuurin/nitro-openapi'
|
|
59
|
+
import type { InternalApi } from 'nitropack'
|
|
60
|
+
import type { configExtends } from '../plugins/swagger'
|
|
61
|
+
import { register } from '../plugins/swagger'
|
|
62
|
+
|
|
63
|
+
type RouteMeta = PathOperationItem<typeof configExtends> & {
|
|
64
|
+
method?: PathOperationMethod
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function defineRouteMeta(
|
|
68
|
+
route: keyof InternalApi,
|
|
69
|
+
meta: RouteMeta,
|
|
70
|
+
) {
|
|
71
|
+
const { method, ...operation } = meta
|
|
72
|
+
register(route, operation, method)
|
|
73
|
+
}
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Then use the register
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
// route/**/*.ts
|
|
80
|
+
|
|
81
|
+
defineRouteMeta('/api/...', {
|
|
82
|
+
/* ... */
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
export default defineEventHandler(() => {
|
|
86
|
+
/* ... */
|
|
87
|
+
})
|
|
88
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const defu = require('defu');
|
|
4
|
+
|
|
5
|
+
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
|
|
6
|
+
|
|
7
|
+
const defu__default = /*#__PURE__*/_interopDefaultCompat(defu);
|
|
8
|
+
|
|
9
|
+
function createOpenApiRegister(defaults) {
|
|
10
|
+
const { paths = {}, components = {}, security = [], servers = [], info, tags = [] } = defaults;
|
|
11
|
+
const defineOperation = (operation) => operation;
|
|
12
|
+
function register(route, routeOperation, method = "get") {
|
|
13
|
+
const _route = normalizeRoute(route);
|
|
14
|
+
paths[_route] = defu__default(
|
|
15
|
+
{ [method]: routeOperation },
|
|
16
|
+
paths[_route]
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
function merge(config) {
|
|
20
|
+
return mergeConfig(
|
|
21
|
+
config,
|
|
22
|
+
{
|
|
23
|
+
paths,
|
|
24
|
+
components,
|
|
25
|
+
security,
|
|
26
|
+
servers,
|
|
27
|
+
info,
|
|
28
|
+
tags
|
|
29
|
+
}
|
|
30
|
+
);
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
configExtends: {
|
|
34
|
+
paths,
|
|
35
|
+
components,
|
|
36
|
+
security,
|
|
37
|
+
servers,
|
|
38
|
+
info,
|
|
39
|
+
tags
|
|
40
|
+
},
|
|
41
|
+
defineOperation,
|
|
42
|
+
register,
|
|
43
|
+
merge
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function normalizeRoute(_route) {
|
|
47
|
+
let anonymousCtr = 0;
|
|
48
|
+
const route = _route.replace(/:(\w+)/g, (_, name) => `{${name}}`).replace(/\/(\*)\//g, () => `/{param${++anonymousCtr}}/`).replace(/\*\*{/, "{").replace(/\/(\*\*)$/g, () => `/{*param${++anonymousCtr}}`);
|
|
49
|
+
return route;
|
|
50
|
+
}
|
|
51
|
+
function mergeConfig(defaults, appends) {
|
|
52
|
+
const methods = /* @__PURE__ */ new Set(["delete", "get", "head", "options", "patch", "post", "put", "trace"]);
|
|
53
|
+
const { info } = appends;
|
|
54
|
+
const { paths = {} } = defaults;
|
|
55
|
+
for (const path in paths) {
|
|
56
|
+
const operations = paths[path];
|
|
57
|
+
if ("$ref" in operations)
|
|
58
|
+
continue;
|
|
59
|
+
paths[path] = Object.fromEntries(Object.entries(operations).map(([key, obj]) => {
|
|
60
|
+
if (methods.has(key))
|
|
61
|
+
return [key, normalizeSchema(obj)];
|
|
62
|
+
return [key, obj];
|
|
63
|
+
}));
|
|
64
|
+
}
|
|
65
|
+
return defu__default({ info }, defaults, appends);
|
|
66
|
+
}
|
|
67
|
+
function normalizeSchema(obj) {
|
|
68
|
+
if ("$ref" in obj)
|
|
69
|
+
return obj;
|
|
70
|
+
const { parameters = [] } = obj;
|
|
71
|
+
obj.parameters = parameters.map((p) => {
|
|
72
|
+
if ("$ref" in p)
|
|
73
|
+
return p;
|
|
74
|
+
return defu__default(p, {
|
|
75
|
+
schema: { type: "string" }
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
return obj;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function resolveSchemaObject(value, options = {}) {
|
|
82
|
+
const { allowExample = true, ...defaults } = options || {};
|
|
83
|
+
const resolveResult = (obj, example) => {
|
|
84
|
+
if (allowExample && example != null)
|
|
85
|
+
obj.example = example;
|
|
86
|
+
return { ...defaults, ...obj };
|
|
87
|
+
};
|
|
88
|
+
if (Array.isArray(value)) {
|
|
89
|
+
return resolveResult(
|
|
90
|
+
{
|
|
91
|
+
type: "array",
|
|
92
|
+
items: resolveSchemaObject(value[0], { allowExample: false })
|
|
93
|
+
},
|
|
94
|
+
value
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
const _type = typeof value;
|
|
98
|
+
switch (_type) {
|
|
99
|
+
case "function":
|
|
100
|
+
case "symbol":
|
|
101
|
+
case "undefined":
|
|
102
|
+
return { type: "null" };
|
|
103
|
+
case "object":
|
|
104
|
+
return resolveResult(
|
|
105
|
+
{
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: Object.fromEntries(Object.entries(value).map(([k, v]) => [
|
|
108
|
+
k,
|
|
109
|
+
resolveSchemaObject(v, {
|
|
110
|
+
allowExample: false
|
|
111
|
+
})
|
|
112
|
+
]))
|
|
113
|
+
},
|
|
114
|
+
value
|
|
115
|
+
);
|
|
116
|
+
case "bigint":
|
|
117
|
+
return resolveResult(
|
|
118
|
+
{ type: "integer" },
|
|
119
|
+
value
|
|
120
|
+
);
|
|
121
|
+
case "string":
|
|
122
|
+
return resolveResult(
|
|
123
|
+
{ type: "string" },
|
|
124
|
+
value || null
|
|
125
|
+
);
|
|
126
|
+
default:
|
|
127
|
+
return resolveResult(
|
|
128
|
+
{ type: _type },
|
|
129
|
+
value
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
function toExampleSchema(example, description, options) {
|
|
134
|
+
if (typeof example !== "object") {
|
|
135
|
+
return resolveSchemaObject(
|
|
136
|
+
example,
|
|
137
|
+
typeof description === "string" ? { ...options, description } : {}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
if (Array.isArray(example)) {
|
|
141
|
+
if (typeof description === "string")
|
|
142
|
+
return resolveSchemaObject(example, { ...options, description });
|
|
143
|
+
const schema2 = resolveSchemaObject(example, { allowExample: false });
|
|
144
|
+
schema2.items = toExampleSchema(example[0], description, options);
|
|
145
|
+
return schema2;
|
|
146
|
+
}
|
|
147
|
+
if (typeof description === "string")
|
|
148
|
+
return resolveSchemaObject(example, { ...options, description });
|
|
149
|
+
const schema = resolveSchemaObject(example, options);
|
|
150
|
+
schema.properties = Object.fromEntries(Object.entries(schema.properties).map(([p, item]) => [p, {
|
|
151
|
+
...item,
|
|
152
|
+
...typeof description === "object" ? { description: description?.[p] } : {}
|
|
153
|
+
}]));
|
|
154
|
+
return schema;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
exports.createOpenApiRegister = createOpenApiRegister;
|
|
158
|
+
exports.resolveSchemaObject = resolveSchemaObject;
|
|
159
|
+
exports.toExampleSchema = toExampleSchema;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import * as openapi_typescript from 'openapi-typescript';
|
|
2
|
+
import { SchemaObject, ReferenceObject, PathItemObject, ResponseObject, MediaTypeObject, OperationObject, ParameterObject, RequestBodyObject, SecurityRequirementObject, OpenAPI3 } from 'openapi-typescript';
|
|
3
|
+
|
|
4
|
+
type ReferenceRef<T extends OpenApiRegisterConfig> = T extends {
|
|
5
|
+
components: infer C;
|
|
6
|
+
} ? {
|
|
7
|
+
[K in keyof C]: C[K] extends object ? `#/components/${K & string}/${keyof C[K] & string}` : never;
|
|
8
|
+
}[keyof C] : string;
|
|
9
|
+
type SchemaExtended<T extends string> = SchemaObject | ({
|
|
10
|
+
type: 'array';
|
|
11
|
+
prefixItems?: MaybeReference<SchemaExtended<T>, T>[];
|
|
12
|
+
items?: MaybeReference<SchemaExtended<T>, T> | MaybeReference<SchemaExtended<T>, T>[];
|
|
13
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
14
|
+
description?: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'object' | ['object', 'null'];
|
|
17
|
+
properties?: {
|
|
18
|
+
[name: string]: MaybeReference<SchemaExtended<T>, T>;
|
|
19
|
+
};
|
|
20
|
+
allOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
21
|
+
anyOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
22
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
23
|
+
description?: string;
|
|
24
|
+
});
|
|
25
|
+
type ReferenceExtended<T extends string> = Omit<ReferenceObject, '$ref'> & {
|
|
26
|
+
$ref: T;
|
|
27
|
+
};
|
|
28
|
+
type MaybeReference<T, R extends string = string> = T | ReferenceExtended<R>;
|
|
29
|
+
type MaybeValueOrObject<ExampleT, ContentT> = ExampleT extends number | string | boolean ? ContentT : ExampleT extends (infer ArrayT)[] ? ContentT | MaybeValueOrObject<ArrayT, ContentT> : ExampleT extends Record<infer PropertyT, unknown> ? {
|
|
30
|
+
[key in PropertyT]?: ContentT;
|
|
31
|
+
} | ContentT : ContentT;
|
|
32
|
+
type PathOperations = Omit<PathItemObject, 'servers' | 'parameters' | `x-${string}`>;
|
|
33
|
+
type PathOperationMethod = keyof PathOperations;
|
|
34
|
+
type PathResponse<RefT extends string> = Omit<ResponseObject, 'content'> & {
|
|
35
|
+
content?: {
|
|
36
|
+
[contentType: string]: Omit<MediaTypeObject, 'schema'> & {
|
|
37
|
+
schema?: MaybeReference<SchemaExtended<RefT>, RefT>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type PathOperationItem<T extends OpenApiRegisterConfig> = Omit<OperationObject, 'tags' | 'parameters' | 'requestBody' | 'responses' | 'security'> & {
|
|
42
|
+
tags?: T extends {
|
|
43
|
+
tags: infer Tags;
|
|
44
|
+
} ? Tags extends ({
|
|
45
|
+
name: infer Tag;
|
|
46
|
+
})[] ? Tag[] | string[] : string[] : string[];
|
|
47
|
+
parameters?: MaybeReference<ParameterObject & {
|
|
48
|
+
schema?: SchemaExtended<ReferenceRef<T>>;
|
|
49
|
+
}, ReferenceRef<T>>[];
|
|
50
|
+
requestBody?: MaybeReference<RequestBodyObject & {
|
|
51
|
+
content: {
|
|
52
|
+
[contentType: string]: MaybeReference<MediaTypeObject, ReferenceRef<T>>;
|
|
53
|
+
};
|
|
54
|
+
}, ReferenceRef<T>>;
|
|
55
|
+
responses?: {
|
|
56
|
+
[responseCode: string]: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
57
|
+
} & {
|
|
58
|
+
default?: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
59
|
+
};
|
|
60
|
+
security?: T extends {
|
|
61
|
+
components: infer C;
|
|
62
|
+
} ? C extends {
|
|
63
|
+
securitySchemes: infer S;
|
|
64
|
+
} ? {
|
|
65
|
+
[SecurityName in keyof S]?: string[];
|
|
66
|
+
}[] : SecurityRequirementObject[] : SecurityRequirementObject[];
|
|
67
|
+
};
|
|
68
|
+
type OpenApiRegisterConfig = Pick<Partial<OpenAPI3>, 'paths' | 'components' | 'security' | 'servers' | 'info' | 'tags'>;
|
|
69
|
+
|
|
70
|
+
declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults: T): {
|
|
71
|
+
configExtends: T;
|
|
72
|
+
defineOperation: (operation: PathOperationItem<T>) => PathOperationItem<T>;
|
|
73
|
+
register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>, ReferenceRef<T>>, method?: keyof PathOperations) => void;
|
|
74
|
+
merge: (config: Partial<OpenAPI3>) => Partial<OpenAPI3>;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
type SchemaObjectOptions = SchemaObject & {
|
|
78
|
+
allowExample?: boolean;
|
|
79
|
+
};
|
|
80
|
+
declare function resolveSchemaObject(value: any, options?: SchemaObjectOptions): SchemaObject;
|
|
81
|
+
type ExampleDescription<ExampleT> = MaybeValueOrObject<ExampleT, string>;
|
|
82
|
+
declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>, options?: SchemaObject): {
|
|
83
|
+
[key: `x-${string}`]: any;
|
|
84
|
+
discriminator?: openapi_typescript.DiscriminatorObject | undefined;
|
|
85
|
+
xml?: openapi_typescript.XMLObject | undefined;
|
|
86
|
+
externalDocs?: openapi_typescript.ExternalDocumentationObject | undefined;
|
|
87
|
+
example?: any;
|
|
88
|
+
title?: string | undefined;
|
|
89
|
+
description?: string | undefined;
|
|
90
|
+
$comment?: string | undefined;
|
|
91
|
+
deprecated?: boolean | undefined;
|
|
92
|
+
readOnly?: boolean | undefined;
|
|
93
|
+
writeOnly?: boolean | undefined;
|
|
94
|
+
enum?: unknown[] | undefined;
|
|
95
|
+
const?: unknown;
|
|
96
|
+
default?: unknown;
|
|
97
|
+
format?: string | undefined;
|
|
98
|
+
nullable?: boolean | undefined;
|
|
99
|
+
oneOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
100
|
+
allOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
101
|
+
anyOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
102
|
+
required?: string[] | undefined;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export { type MaybeReference, type MaybeValueOrObject, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type PathResponse, type ReferenceExtended, type ReferenceRef, type SchemaExtended, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,18 +1,62 @@
|
|
|
1
1
|
import * as openapi_typescript from 'openapi-typescript';
|
|
2
|
-
import { ReferenceObject, PathItemObject, OperationObject, SecurityRequirementObject, OpenAPI3
|
|
2
|
+
import { SchemaObject, ReferenceObject, PathItemObject, ResponseObject, MediaTypeObject, OperationObject, ParameterObject, RequestBodyObject, SecurityRequirementObject, OpenAPI3 } from 'openapi-typescript';
|
|
3
3
|
|
|
4
|
-
type
|
|
4
|
+
type ReferenceRef<T extends OpenApiRegisterConfig> = T extends {
|
|
5
|
+
components: infer C;
|
|
6
|
+
} ? {
|
|
7
|
+
[K in keyof C]: C[K] extends object ? `#/components/${K & string}/${keyof C[K] & string}` : never;
|
|
8
|
+
}[keyof C] : string;
|
|
9
|
+
type SchemaExtended<T extends string> = SchemaObject | ({
|
|
10
|
+
type: 'array';
|
|
11
|
+
prefixItems?: MaybeReference<SchemaExtended<T>, T>[];
|
|
12
|
+
items?: MaybeReference<SchemaExtended<T>, T> | MaybeReference<SchemaExtended<T>, T>[];
|
|
13
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
14
|
+
description?: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'object' | ['object', 'null'];
|
|
17
|
+
properties?: {
|
|
18
|
+
[name: string]: MaybeReference<SchemaExtended<T>, T>;
|
|
19
|
+
};
|
|
20
|
+
allOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
21
|
+
anyOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
22
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
23
|
+
description?: string;
|
|
24
|
+
});
|
|
25
|
+
type ReferenceExtended<T extends string> = Omit<ReferenceObject, '$ref'> & {
|
|
5
26
|
$ref: T;
|
|
6
27
|
};
|
|
7
|
-
type MaybeReference<T, R = string> = T |
|
|
28
|
+
type MaybeReference<T, R extends string = string> = T | ReferenceExtended<R>;
|
|
29
|
+
type MaybeValueOrObject<ExampleT, ContentT> = ExampleT extends number | string | boolean ? ContentT : ExampleT extends (infer ArrayT)[] ? ContentT | MaybeValueOrObject<ArrayT, ContentT> : ExampleT extends Record<infer PropertyT, unknown> ? {
|
|
30
|
+
[key in PropertyT]?: ContentT;
|
|
31
|
+
} | ContentT : ContentT;
|
|
8
32
|
type PathOperations = Omit<PathItemObject, 'servers' | 'parameters' | `x-${string}`>;
|
|
9
33
|
type PathOperationMethod = keyof PathOperations;
|
|
10
|
-
type
|
|
34
|
+
type PathResponse<RefT extends string> = Omit<ResponseObject, 'content'> & {
|
|
35
|
+
content?: {
|
|
36
|
+
[contentType: string]: Omit<MediaTypeObject, 'schema'> & {
|
|
37
|
+
schema?: MaybeReference<SchemaExtended<RefT>, RefT>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type PathOperationItem<T extends OpenApiRegisterConfig> = Omit<OperationObject, 'tags' | 'parameters' | 'requestBody' | 'responses' | 'security'> & {
|
|
11
42
|
tags?: T extends {
|
|
12
43
|
tags: infer Tags;
|
|
13
44
|
} ? Tags extends ({
|
|
14
45
|
name: infer Tag;
|
|
15
46
|
})[] ? Tag[] | string[] : string[] : string[];
|
|
47
|
+
parameters?: MaybeReference<ParameterObject & {
|
|
48
|
+
schema?: SchemaExtended<ReferenceRef<T>>;
|
|
49
|
+
}, ReferenceRef<T>>[];
|
|
50
|
+
requestBody?: MaybeReference<RequestBodyObject & {
|
|
51
|
+
content: {
|
|
52
|
+
[contentType: string]: MaybeReference<MediaTypeObject, ReferenceRef<T>>;
|
|
53
|
+
};
|
|
54
|
+
}, ReferenceRef<T>>;
|
|
55
|
+
responses?: {
|
|
56
|
+
[responseCode: string]: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
57
|
+
} & {
|
|
58
|
+
default?: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
59
|
+
};
|
|
16
60
|
security?: T extends {
|
|
17
61
|
components: infer C;
|
|
18
62
|
} ? C extends {
|
|
@@ -23,22 +67,19 @@ type PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegiste
|
|
|
23
67
|
};
|
|
24
68
|
type OpenApiRegisterConfig = Pick<Partial<OpenAPI3>, 'paths' | 'components' | 'security' | 'servers' | 'info' | 'tags'>;
|
|
25
69
|
|
|
26
|
-
declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults
|
|
70
|
+
declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults: T): {
|
|
27
71
|
configExtends: T;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
72
|
+
defineOperation: (operation: PathOperationItem<T>) => PathOperationItem<T>;
|
|
73
|
+
register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>, ReferenceRef<T>>, method?: keyof PathOperations) => void;
|
|
74
|
+
merge: (config: Partial<OpenAPI3>) => Partial<OpenAPI3>;
|
|
32
75
|
};
|
|
33
76
|
|
|
34
77
|
type SchemaObjectOptions = SchemaObject & {
|
|
35
78
|
allowExample?: boolean;
|
|
36
79
|
};
|
|
37
80
|
declare function resolveSchemaObject(value: any, options?: SchemaObjectOptions): SchemaObject;
|
|
38
|
-
type ExampleDescription<ExampleT> =
|
|
39
|
-
|
|
40
|
-
} | string : string;
|
|
41
|
-
declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>): {
|
|
81
|
+
type ExampleDescription<ExampleT> = MaybeValueOrObject<ExampleT, string>;
|
|
82
|
+
declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>, options?: SchemaObject): {
|
|
42
83
|
[key: `x-${string}`]: any;
|
|
43
84
|
discriminator?: openapi_typescript.DiscriminatorObject | undefined;
|
|
44
85
|
xml?: openapi_typescript.XMLObject | undefined;
|
|
@@ -55,10 +96,10 @@ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescr
|
|
|
55
96
|
default?: unknown;
|
|
56
97
|
format?: string | undefined;
|
|
57
98
|
nullable?: boolean | undefined;
|
|
58
|
-
oneOf?: (openapi_typescript.ReferenceObject
|
|
59
|
-
allOf?: (openapi_typescript.ReferenceObject
|
|
60
|
-
anyOf?: (openapi_typescript.ReferenceObject
|
|
99
|
+
oneOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
100
|
+
allOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
101
|
+
anyOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
61
102
|
required?: string[] | undefined;
|
|
62
103
|
};
|
|
63
104
|
|
|
64
|
-
export { type MaybeReference, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type
|
|
105
|
+
export { type MaybeReference, type MaybeValueOrObject, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type PathResponse, type ReferenceExtended, type ReferenceRef, type SchemaExtended, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,62 @@
|
|
|
1
1
|
import * as openapi_typescript from 'openapi-typescript';
|
|
2
|
-
import { ReferenceObject, PathItemObject, OperationObject, SecurityRequirementObject, OpenAPI3
|
|
2
|
+
import { SchemaObject, ReferenceObject, PathItemObject, ResponseObject, MediaTypeObject, OperationObject, ParameterObject, RequestBodyObject, SecurityRequirementObject, OpenAPI3 } from 'openapi-typescript';
|
|
3
3
|
|
|
4
|
-
type
|
|
4
|
+
type ReferenceRef<T extends OpenApiRegisterConfig> = T extends {
|
|
5
|
+
components: infer C;
|
|
6
|
+
} ? {
|
|
7
|
+
[K in keyof C]: C[K] extends object ? `#/components/${K & string}/${keyof C[K] & string}` : never;
|
|
8
|
+
}[keyof C] : string;
|
|
9
|
+
type SchemaExtended<T extends string> = SchemaObject | ({
|
|
10
|
+
type: 'array';
|
|
11
|
+
prefixItems?: MaybeReference<SchemaExtended<T>, T>[];
|
|
12
|
+
items?: MaybeReference<SchemaExtended<T>, T> | MaybeReference<SchemaExtended<T>, T>[];
|
|
13
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
14
|
+
description?: string;
|
|
15
|
+
} | {
|
|
16
|
+
type: 'object' | ['object', 'null'];
|
|
17
|
+
properties?: {
|
|
18
|
+
[name: string]: MaybeReference<SchemaExtended<T>, T>;
|
|
19
|
+
};
|
|
20
|
+
allOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
21
|
+
anyOf?: MaybeReference<SchemaExtended<T>, T>[];
|
|
22
|
+
enum?: MaybeReference<SchemaExtended<T>, T>[];
|
|
23
|
+
description?: string;
|
|
24
|
+
});
|
|
25
|
+
type ReferenceExtended<T extends string> = Omit<ReferenceObject, '$ref'> & {
|
|
5
26
|
$ref: T;
|
|
6
27
|
};
|
|
7
|
-
type MaybeReference<T, R = string> = T |
|
|
28
|
+
type MaybeReference<T, R extends string = string> = T | ReferenceExtended<R>;
|
|
29
|
+
type MaybeValueOrObject<ExampleT, ContentT> = ExampleT extends number | string | boolean ? ContentT : ExampleT extends (infer ArrayT)[] ? ContentT | MaybeValueOrObject<ArrayT, ContentT> : ExampleT extends Record<infer PropertyT, unknown> ? {
|
|
30
|
+
[key in PropertyT]?: ContentT;
|
|
31
|
+
} | ContentT : ContentT;
|
|
8
32
|
type PathOperations = Omit<PathItemObject, 'servers' | 'parameters' | `x-${string}`>;
|
|
9
33
|
type PathOperationMethod = keyof PathOperations;
|
|
10
|
-
type
|
|
34
|
+
type PathResponse<RefT extends string> = Omit<ResponseObject, 'content'> & {
|
|
35
|
+
content?: {
|
|
36
|
+
[contentType: string]: Omit<MediaTypeObject, 'schema'> & {
|
|
37
|
+
schema?: MaybeReference<SchemaExtended<RefT>, RefT>;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
type PathOperationItem<T extends OpenApiRegisterConfig> = Omit<OperationObject, 'tags' | 'parameters' | 'requestBody' | 'responses' | 'security'> & {
|
|
11
42
|
tags?: T extends {
|
|
12
43
|
tags: infer Tags;
|
|
13
44
|
} ? Tags extends ({
|
|
14
45
|
name: infer Tag;
|
|
15
46
|
})[] ? Tag[] | string[] : string[] : string[];
|
|
47
|
+
parameters?: MaybeReference<ParameterObject & {
|
|
48
|
+
schema?: SchemaExtended<ReferenceRef<T>>;
|
|
49
|
+
}, ReferenceRef<T>>[];
|
|
50
|
+
requestBody?: MaybeReference<RequestBodyObject & {
|
|
51
|
+
content: {
|
|
52
|
+
[contentType: string]: MaybeReference<MediaTypeObject, ReferenceRef<T>>;
|
|
53
|
+
};
|
|
54
|
+
}, ReferenceRef<T>>;
|
|
55
|
+
responses?: {
|
|
56
|
+
[responseCode: string]: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
57
|
+
} & {
|
|
58
|
+
default?: MaybeReference<PathResponse<ReferenceRef<T>>, ReferenceRef<T>>;
|
|
59
|
+
};
|
|
16
60
|
security?: T extends {
|
|
17
61
|
components: infer C;
|
|
18
62
|
} ? C extends {
|
|
@@ -23,22 +67,19 @@ type PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegiste
|
|
|
23
67
|
};
|
|
24
68
|
type OpenApiRegisterConfig = Pick<Partial<OpenAPI3>, 'paths' | 'components' | 'security' | 'servers' | 'info' | 'tags'>;
|
|
25
69
|
|
|
26
|
-
declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults
|
|
70
|
+
declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults: T): {
|
|
27
71
|
configExtends: T;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
};
|
|
72
|
+
defineOperation: (operation: PathOperationItem<T>) => PathOperationItem<T>;
|
|
73
|
+
register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>, ReferenceRef<T>>, method?: keyof PathOperations) => void;
|
|
74
|
+
merge: (config: Partial<OpenAPI3>) => Partial<OpenAPI3>;
|
|
32
75
|
};
|
|
33
76
|
|
|
34
77
|
type SchemaObjectOptions = SchemaObject & {
|
|
35
78
|
allowExample?: boolean;
|
|
36
79
|
};
|
|
37
80
|
declare function resolveSchemaObject(value: any, options?: SchemaObjectOptions): SchemaObject;
|
|
38
|
-
type ExampleDescription<ExampleT> =
|
|
39
|
-
|
|
40
|
-
} | string : string;
|
|
41
|
-
declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>): {
|
|
81
|
+
type ExampleDescription<ExampleT> = MaybeValueOrObject<ExampleT, string>;
|
|
82
|
+
declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>, options?: SchemaObject): {
|
|
42
83
|
[key: `x-${string}`]: any;
|
|
43
84
|
discriminator?: openapi_typescript.DiscriminatorObject | undefined;
|
|
44
85
|
xml?: openapi_typescript.XMLObject | undefined;
|
|
@@ -55,10 +96,10 @@ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescr
|
|
|
55
96
|
default?: unknown;
|
|
56
97
|
format?: string | undefined;
|
|
57
98
|
nullable?: boolean | undefined;
|
|
58
|
-
oneOf?: (openapi_typescript.ReferenceObject
|
|
59
|
-
allOf?: (openapi_typescript.ReferenceObject
|
|
60
|
-
anyOf?: (openapi_typescript.ReferenceObject
|
|
99
|
+
oneOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
100
|
+
allOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
101
|
+
anyOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
|
|
61
102
|
required?: string[] | undefined;
|
|
62
103
|
};
|
|
63
104
|
|
|
64
|
-
export { type MaybeReference, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type
|
|
105
|
+
export { type MaybeReference, type MaybeValueOrObject, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type PathResponse, type ReferenceExtended, type ReferenceRef, type SchemaExtended, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import defu from 'defu';
|
|
2
2
|
|
|
3
|
-
function createOpenApiRegister(defaults
|
|
3
|
+
function createOpenApiRegister(defaults) {
|
|
4
4
|
const { paths = {}, components = {}, security = [], servers = [], info, tags = [] } = defaults;
|
|
5
|
+
const defineOperation = (operation) => operation;
|
|
5
6
|
function register(route, routeOperation, method = "get") {
|
|
6
7
|
const _route = normalizeRoute(route);
|
|
7
8
|
paths[_route] = defu(
|
|
@@ -31,6 +32,7 @@ function createOpenApiRegister(defaults = {}) {
|
|
|
31
32
|
info,
|
|
32
33
|
tags
|
|
33
34
|
},
|
|
35
|
+
defineOperation,
|
|
34
36
|
register,
|
|
35
37
|
merge
|
|
36
38
|
};
|
|
@@ -71,8 +73,7 @@ function normalizeSchema(obj) {
|
|
|
71
73
|
}
|
|
72
74
|
|
|
73
75
|
function resolveSchemaObject(value, options = {}) {
|
|
74
|
-
const { allowExample = true, ...defaults } = options;
|
|
75
|
-
const { description: _, ...inheritOptions } = options;
|
|
76
|
+
const { allowExample = true, ...defaults } = options || {};
|
|
76
77
|
const resolveResult = (obj, example) => {
|
|
77
78
|
if (allowExample && example != null)
|
|
78
79
|
obj.example = example;
|
|
@@ -82,7 +83,7 @@ function resolveSchemaObject(value, options = {}) {
|
|
|
82
83
|
return resolveResult(
|
|
83
84
|
{
|
|
84
85
|
type: "array",
|
|
85
|
-
items: resolveSchemaObject(value[0], {
|
|
86
|
+
items: resolveSchemaObject(value[0], { allowExample: false })
|
|
86
87
|
},
|
|
87
88
|
value
|
|
88
89
|
);
|
|
@@ -100,7 +101,6 @@ function resolveSchemaObject(value, options = {}) {
|
|
|
100
101
|
properties: Object.fromEntries(Object.entries(value).map(([k, v]) => [
|
|
101
102
|
k,
|
|
102
103
|
resolveSchemaObject(v, {
|
|
103
|
-
...inheritOptions,
|
|
104
104
|
allowExample: false
|
|
105
105
|
})
|
|
106
106
|
]))
|
|
@@ -124,23 +124,23 @@ function resolveSchemaObject(value, options = {}) {
|
|
|
124
124
|
);
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
|
-
function toExampleSchema(example, description) {
|
|
127
|
+
function toExampleSchema(example, description, options) {
|
|
128
128
|
if (typeof example !== "object") {
|
|
129
129
|
return resolveSchemaObject(
|
|
130
130
|
example,
|
|
131
|
-
typeof description === "string" ? { description } : {}
|
|
131
|
+
typeof description === "string" ? { ...options, description } : {}
|
|
132
132
|
);
|
|
133
133
|
}
|
|
134
134
|
if (Array.isArray(example)) {
|
|
135
135
|
if (typeof description === "string")
|
|
136
|
-
return resolveSchemaObject(example, { description });
|
|
136
|
+
return resolveSchemaObject(example, { ...options, description });
|
|
137
137
|
const schema2 = resolveSchemaObject(example, { allowExample: false });
|
|
138
|
-
schema2.items = toExampleSchema(example[0], description);
|
|
138
|
+
schema2.items = toExampleSchema(example[0], description, options);
|
|
139
139
|
return schema2;
|
|
140
140
|
}
|
|
141
141
|
if (typeof description === "string")
|
|
142
|
-
return resolveSchemaObject(example, { description });
|
|
143
|
-
const schema = resolveSchemaObject(example);
|
|
142
|
+
return resolveSchemaObject(example, { ...options, description });
|
|
143
|
+
const schema = resolveSchemaObject(example, options);
|
|
144
144
|
schema.properties = Object.fromEntries(Object.entries(schema.properties).map(([p, item]) => [p, {
|
|
145
145
|
...item,
|
|
146
146
|
...typeof description === "object" ? { description: description?.[p] } : {}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@byyuurin/nitro-openapi",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/byyuurin/nitro-openapi",
|
|
@@ -12,7 +12,8 @@
|
|
|
12
12
|
"exports": {
|
|
13
13
|
".": {
|
|
14
14
|
"types": "./dist/index.d.ts",
|
|
15
|
-
"import": "./dist/index.mjs"
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
16
17
|
}
|
|
17
18
|
},
|
|
18
19
|
"main": "./dist/index.mjs",
|
|
@@ -21,29 +22,29 @@
|
|
|
21
22
|
"*.d.ts",
|
|
22
23
|
"dist"
|
|
23
24
|
],
|
|
24
|
-
"scripts": {
|
|
25
|
-
"build": "unbuild",
|
|
26
|
-
"prepare": "nitropack prepare",
|
|
27
|
-
"dev": "nitropack dev playground",
|
|
28
|
-
"dev:build": "nitropack build playground",
|
|
29
|
-
"dev:preview": "node playground/.output/server/index.mjs",
|
|
30
|
-
"lint": "eslint .",
|
|
31
|
-
"test": "vitest",
|
|
32
|
-
"release": "bumpp && pnpm publish",
|
|
33
|
-
"stub": "unbuild --stub"
|
|
34
|
-
},
|
|
35
25
|
"dependencies": {
|
|
36
26
|
"defu": "^6.1.4",
|
|
37
27
|
"openapi-typescript": "^6.7.4"
|
|
38
28
|
},
|
|
39
29
|
"devDependencies": {
|
|
40
|
-
"@byyuurin/eslint-config": "^1.0.
|
|
41
|
-
"bumpp": "^9.3.
|
|
30
|
+
"@byyuurin/eslint-config": "^1.0.2",
|
|
31
|
+
"bumpp": "^9.3.1",
|
|
42
32
|
"nitropack": "latest",
|
|
43
33
|
"unbuild": "^2.0.0",
|
|
44
|
-
"vitest": "^1.3.
|
|
34
|
+
"vitest": "^1.3.1"
|
|
45
35
|
},
|
|
46
36
|
"resolutions": {
|
|
47
37
|
"@byyuurin/nitro-openapi": "link:."
|
|
38
|
+
},
|
|
39
|
+
"scripts": {
|
|
40
|
+
"build": "unbuild",
|
|
41
|
+
"dev": "nitropack dev playground",
|
|
42
|
+
"dev:prepare": "nitropack prepare playground",
|
|
43
|
+
"dev:build": "nitropack build playground",
|
|
44
|
+
"dev:preview": "node playground/.output/server/index.mjs",
|
|
45
|
+
"lint": "eslint .",
|
|
46
|
+
"test": "vitest",
|
|
47
|
+
"release": "bumpp && pnpm publish",
|
|
48
|
+
"stub": "unbuild --stub"
|
|
48
49
|
}
|
|
49
|
-
}
|
|
50
|
+
}
|