@byyuurin/nitro-openapi 0.0.1 → 0.0.2

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 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.d.mts CHANGED
@@ -1,18 +1,50 @@
1
1
  import * as openapi_typescript from 'openapi-typescript';
2
- import { ReferenceObject, PathItemObject, OperationObject, SecurityRequirementObject, OpenAPI3, SchemaObject } from 'openapi-typescript';
2
+ import { SchemaObject, ReferenceObject, PathItemObject, OperationObject, ParameterObject, RequestBodyObject, MediaTypeObject, SecurityRequirementObject, OpenAPI3 } from 'openapi-typescript';
3
3
 
4
- type ReferenceSchema<T> = Omit<ReferenceObject, '$ref'> & {
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 | ReferenceSchema<R>;
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 PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegisterConfig>> = Omit<OperationObject, 'security' | 'tags'> & {
34
+ type PathOperationItem<T extends OpenApiRegisterConfig> = Omit<OperationObject, 'tags' | 'parameters' | 'requestBody' | 'security'> & {
11
35
  tags?: T extends {
12
36
  tags: infer Tags;
13
37
  } ? Tags extends ({
14
38
  name: infer Tag;
15
39
  })[] ? Tag[] | string[] : string[] : string[];
40
+ parameters?: MaybeReference<ParameterObject & {
41
+ schema?: SchemaExtended<ReferenceRef<T>>;
42
+ }, ReferenceRef<T>>[];
43
+ requestBody?: MaybeReference<RequestBodyObject & {
44
+ content: {
45
+ [contentType: string]: MaybeReference<MediaTypeObject, ReferenceRef<T>>;
46
+ };
47
+ }, ReferenceRef<T>>;
16
48
  security?: T extends {
17
49
  components: infer C;
18
50
  } ? C extends {
@@ -23,9 +55,9 @@ type PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegiste
23
55
  };
24
56
  type OpenApiRegisterConfig = Pick<Partial<OpenAPI3>, 'paths' | 'components' | 'security' | 'servers' | 'info' | 'tags'>;
25
57
 
26
- declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults?: T): {
58
+ declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults: T): {
27
59
  configExtends: T;
28
- register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>>, method?: keyof PathOperations) => void;
60
+ register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>, ReferenceRef<T>>, method?: keyof PathOperations) => void;
29
61
  merge: (config: Partial<OpenAPI3>) => {
30
62
  info: openapi_typescript.InfoObject | undefined;
31
63
  };
@@ -35,10 +67,8 @@ type SchemaObjectOptions = SchemaObject & {
35
67
  allowExample?: boolean;
36
68
  };
37
69
  declare function resolveSchemaObject(value: any, options?: SchemaObjectOptions): SchemaObject;
38
- type ExampleDescription<ExampleT> = ExampleT extends number | string | boolean ? string : ExampleT extends (infer ArrayT)[] ? string | ExampleDescription<ArrayT> : ExampleT extends Record<infer PropertyT, unknown> ? {
39
- [key in PropertyT]?: string;
40
- } | string : string;
41
- declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>): {
70
+ type ExampleDescription<ExampleT> = MaybeValueOrObject<ExampleT, string>;
71
+ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>, options?: SchemaObject): {
42
72
  [key: `x-${string}`]: any;
43
73
  discriminator?: openapi_typescript.DiscriminatorObject | undefined;
44
74
  xml?: openapi_typescript.XMLObject | undefined;
@@ -55,10 +85,10 @@ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescr
55
85
  default?: unknown;
56
86
  format?: string | undefined;
57
87
  nullable?: boolean | undefined;
58
- oneOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
59
- allOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
60
- anyOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
88
+ oneOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
89
+ allOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
90
+ anyOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
61
91
  required?: string[] | undefined;
62
92
  };
63
93
 
64
- export { type MaybeReference, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type ReferenceSchema, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
94
+ export { type MaybeReference, type MaybeValueOrObject, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type ReferenceExtended, type ReferenceRef, type SchemaExtended, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
package/dist/index.d.ts CHANGED
@@ -1,18 +1,50 @@
1
1
  import * as openapi_typescript from 'openapi-typescript';
2
- import { ReferenceObject, PathItemObject, OperationObject, SecurityRequirementObject, OpenAPI3, SchemaObject } from 'openapi-typescript';
2
+ import { SchemaObject, ReferenceObject, PathItemObject, OperationObject, ParameterObject, RequestBodyObject, MediaTypeObject, SecurityRequirementObject, OpenAPI3 } from 'openapi-typescript';
3
3
 
4
- type ReferenceSchema<T> = Omit<ReferenceObject, '$ref'> & {
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 | ReferenceSchema<R>;
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 PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegisterConfig>> = Omit<OperationObject, 'security' | 'tags'> & {
34
+ type PathOperationItem<T extends OpenApiRegisterConfig> = Omit<OperationObject, 'tags' | 'parameters' | 'requestBody' | 'security'> & {
11
35
  tags?: T extends {
12
36
  tags: infer Tags;
13
37
  } ? Tags extends ({
14
38
  name: infer Tag;
15
39
  })[] ? Tag[] | string[] : string[] : string[];
40
+ parameters?: MaybeReference<ParameterObject & {
41
+ schema?: SchemaExtended<ReferenceRef<T>>;
42
+ }, ReferenceRef<T>>[];
43
+ requestBody?: MaybeReference<RequestBodyObject & {
44
+ content: {
45
+ [contentType: string]: MaybeReference<MediaTypeObject, ReferenceRef<T>>;
46
+ };
47
+ }, ReferenceRef<T>>;
16
48
  security?: T extends {
17
49
  components: infer C;
18
50
  } ? C extends {
@@ -23,9 +55,9 @@ type PathOperationItem<T extends OpenApiRegisterConfig = Required<OpenApiRegiste
23
55
  };
24
56
  type OpenApiRegisterConfig = Pick<Partial<OpenAPI3>, 'paths' | 'components' | 'security' | 'servers' | 'info' | 'tags'>;
25
57
 
26
- declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults?: T): {
58
+ declare function createOpenApiRegister<T extends OpenApiRegisterConfig = OpenApiRegisterConfig>(defaults: T): {
27
59
  configExtends: T;
28
- register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>>, method?: keyof PathOperations) => void;
60
+ register: (route: string, routeOperation: MaybeReference<PathOperationItem<T>, ReferenceRef<T>>, method?: keyof PathOperations) => void;
29
61
  merge: (config: Partial<OpenAPI3>) => {
30
62
  info: openapi_typescript.InfoObject | undefined;
31
63
  };
@@ -35,10 +67,8 @@ type SchemaObjectOptions = SchemaObject & {
35
67
  allowExample?: boolean;
36
68
  };
37
69
  declare function resolveSchemaObject(value: any, options?: SchemaObjectOptions): SchemaObject;
38
- type ExampleDescription<ExampleT> = ExampleT extends number | string | boolean ? string : ExampleT extends (infer ArrayT)[] ? string | ExampleDescription<ArrayT> : ExampleT extends Record<infer PropertyT, unknown> ? {
39
- [key in PropertyT]?: string;
40
- } | string : string;
41
- declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>): {
70
+ type ExampleDescription<ExampleT> = MaybeValueOrObject<ExampleT, string>;
71
+ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescription<T>, options?: SchemaObject): {
42
72
  [key: `x-${string}`]: any;
43
73
  discriminator?: openapi_typescript.DiscriminatorObject | undefined;
44
74
  xml?: openapi_typescript.XMLObject | undefined;
@@ -55,10 +85,10 @@ declare function toExampleSchema<T = any>(example: T, description?: ExampleDescr
55
85
  default?: unknown;
56
86
  format?: string | undefined;
57
87
  nullable?: boolean | undefined;
58
- oneOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
59
- allOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
60
- anyOf?: (openapi_typescript.ReferenceObject | SchemaObject)[] | undefined;
88
+ oneOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
89
+ allOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
90
+ anyOf?: (SchemaObject | openapi_typescript.ReferenceObject)[] | undefined;
61
91
  required?: string[] | undefined;
62
92
  };
63
93
 
64
- export { type MaybeReference, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type ReferenceSchema, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
94
+ export { type MaybeReference, type MaybeValueOrObject, type OpenApiRegisterConfig, type PathOperationItem, type PathOperationMethod, type PathOperations, type ReferenceExtended, type ReferenceRef, type SchemaExtended, createOpenApiRegister, resolveSchemaObject, toExampleSchema };
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
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
5
  function register(route, routeOperation, method = "get") {
6
6
  const _route = normalizeRoute(route);
@@ -71,8 +71,7 @@ function normalizeSchema(obj) {
71
71
  }
72
72
 
73
73
  function resolveSchemaObject(value, options = {}) {
74
- const { allowExample = true, ...defaults } = options;
75
- const { description: _, ...inheritOptions } = options;
74
+ const { allowExample = true, ...defaults } = options || {};
76
75
  const resolveResult = (obj, example) => {
77
76
  if (allowExample && example != null)
78
77
  obj.example = example;
@@ -82,7 +81,7 @@ function resolveSchemaObject(value, options = {}) {
82
81
  return resolveResult(
83
82
  {
84
83
  type: "array",
85
- items: resolveSchemaObject(value[0], { ...inheritOptions, allowExample: false })
84
+ items: resolveSchemaObject(value[0], { allowExample: false })
86
85
  },
87
86
  value
88
87
  );
@@ -100,7 +99,6 @@ function resolveSchemaObject(value, options = {}) {
100
99
  properties: Object.fromEntries(Object.entries(value).map(([k, v]) => [
101
100
  k,
102
101
  resolveSchemaObject(v, {
103
- ...inheritOptions,
104
102
  allowExample: false
105
103
  })
106
104
  ]))
@@ -124,23 +122,23 @@ function resolveSchemaObject(value, options = {}) {
124
122
  );
125
123
  }
126
124
  }
127
- function toExampleSchema(example, description) {
125
+ function toExampleSchema(example, description, options) {
128
126
  if (typeof example !== "object") {
129
127
  return resolveSchemaObject(
130
128
  example,
131
- typeof description === "string" ? { description } : {}
129
+ typeof description === "string" ? { ...options, description } : {}
132
130
  );
133
131
  }
134
132
  if (Array.isArray(example)) {
135
133
  if (typeof description === "string")
136
- return resolveSchemaObject(example, { description });
134
+ return resolveSchemaObject(example, { ...options, description });
137
135
  const schema2 = resolveSchemaObject(example, { allowExample: false });
138
- schema2.items = toExampleSchema(example[0], description);
136
+ schema2.items = toExampleSchema(example[0], description, options);
139
137
  return schema2;
140
138
  }
141
139
  if (typeof description === "string")
142
- return resolveSchemaObject(example, { description });
143
- const schema = resolveSchemaObject(example);
140
+ return resolveSchemaObject(example, { ...options, description });
141
+ const schema = resolveSchemaObject(example, options);
144
142
  schema.properties = Object.fromEntries(Object.entries(schema.properties).map(([p, item]) => [p, {
145
143
  ...item,
146
144
  ...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.1",
4
+ "version": "0.0.2",
5
5
  "private": false,
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/byyuurin/nitro-openapi",
@@ -21,17 +21,6 @@
21
21
  "*.d.ts",
22
22
  "dist"
23
23
  ],
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
24
  "dependencies": {
36
25
  "defu": "^6.1.4",
37
26
  "openapi-typescript": "^6.7.4"
@@ -45,5 +34,16 @@
45
34
  },
46
35
  "resolutions": {
47
36
  "@byyuurin/nitro-openapi": "link:."
37
+ },
38
+ "scripts": {
39
+ "build": "unbuild",
40
+ "dev": "nitropack dev playground",
41
+ "dev:prepare": "nitropack prepare playground",
42
+ "dev:build": "nitropack build playground",
43
+ "dev:preview": "node playground/.output/server/index.mjs",
44
+ "lint": "eslint .",
45
+ "test": "vitest",
46
+ "release": "bumpp && pnpm publish",
47
+ "stub": "unbuild --stub"
48
48
  }
49
- }
49
+ }