@znight/openapi 0.0.0-stage → 0.1.1
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/LICENSE +21 -0
- package/README.md +572 -2
- package/dist/build-BTUC96mY.d.mts +174 -0
- package/dist/build-DXunOzlI.mjs +733 -0
- package/dist/build-DXunOzlI.mjs.map +1 -0
- package/dist/compiler.d.mts +16 -0
- package/dist/compiler.mjs +2639 -0
- package/dist/compiler.mjs.map +1 -0
- package/dist/emit-child.d.mts +1 -0
- package/dist/emit-child.mjs +124 -0
- package/dist/emit-child.mjs.map +1 -0
- package/dist/emit.d.mts +2 -0
- package/dist/emit.mjs +252 -0
- package/dist/emit.mjs.map +1 -0
- package/dist/index-CqQ6IRnN.d.mts +60 -0
- package/dist/index.d.mts +260 -0
- package/dist/index.mjs +777 -0
- package/dist/index.mjs.map +1 -0
- package/dist/openapi-CQk5dHqc.mjs +39 -0
- package/dist/openapi-CQk5dHqc.mjs.map +1 -0
- package/dist/shared-BZxtyaB0.mjs +147 -0
- package/dist/shared-BZxtyaB0.mjs.map +1 -0
- package/dist/testing.d.mts +39 -0
- package/dist/testing.mjs +155 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/types-VzBexMKj.d.mts +213 -0
- package/dist/vite.d.mts +24 -0
- package/dist/vite.mjs +64 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +115 -4
- package/src/build.ts +898 -0
- package/src/compiler/analyze.ts +81 -0
- package/src/compiler/document.ts +612 -0
- package/src/compiler/generate.ts +79 -0
- package/src/compiler/index.ts +47 -0
- package/src/compiler/model.ts +141 -0
- package/src/compiler/operations.ts +1475 -0
- package/src/compiler/schemas.ts +706 -0
- package/src/compiler/validate.ts +102 -0
- package/src/compiler/values.ts +81 -0
- package/src/converters.ts +137 -0
- package/src/decorators.ts +187 -0
- package/src/emit/child.ts +144 -0
- package/src/emit/index.ts +377 -0
- package/src/emit/protocol.ts +35 -0
- package/src/index.ts +94 -0
- package/src/metadata.ts +112 -0
- package/src/openapi.ts +55 -0
- package/src/plugin.ts +810 -0
- package/src/shared.ts +154 -0
- package/src/testing.ts +224 -0
- package/src/types.ts +240 -0
- package/src/ui.ts +215 -0
- package/src/vite.ts +126 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@znight/openapi/compiler`: the compiler extension of `@znight/openapi` (architecture §6.5),
|
|
3
|
+
* loaded by `@znight/compiler` through `package.json#znight.compiler`.
|
|
4
|
+
*
|
|
5
|
+
* - `analyzeClass`: records the `@OpenApiDocument` class, checks where `@Api*` decorators are
|
|
6
|
+
* (ZNIGHT030);
|
|
7
|
+
* - `validate`: builds the operation model from the route table of `@znight/http/compiler`, the
|
|
8
|
+
* handler signatures, their JSDoc and the type shapes, and reports ZNIGHT030–036;
|
|
9
|
+
* - `generate`: `metadata.extensions.openapi` (README, "Compiler contract").
|
|
10
|
+
*
|
|
11
|
+
* This entry only `import type`s from `@znight/compiler` and `@znight/http/compiler` and never
|
|
12
|
+
* loads the runtime of `@znight/openapi`.
|
|
13
|
+
*/
|
|
14
|
+
import type { CompilerExtension, DecoratorSpec } from '@znight/compiler'
|
|
15
|
+
import type { OpenApiStored } from './model.ts'
|
|
16
|
+
|
|
17
|
+
import { analyzeOpenApiClass } from './analyze.ts'
|
|
18
|
+
import { generateOpenApi } from './generate.ts'
|
|
19
|
+
import { EXTENSION_NAME, Ids } from './model.ts'
|
|
20
|
+
import { validateOpenApi } from './validate.ts'
|
|
21
|
+
|
|
22
|
+
export type { OpenApiStored } from './model.ts'
|
|
23
|
+
|
|
24
|
+
/** Decorators owned by the extension, by canonical identity (static / value arguments, §4.6). */
|
|
25
|
+
const decorators: Readonly<Record<string, DecoratorSpec>> = Object.freeze({
|
|
26
|
+
[Ids.OpenApiDocument]: { targets: ['class'], params: ['value'] },
|
|
27
|
+
[Ids.ApiOperation]: { targets: ['method'], params: ['static'] },
|
|
28
|
+
[Ids.ApiTags]: { targets: ['class', 'method'], params: [], rest: 'static' },
|
|
29
|
+
[Ids.ApiResponse]: { targets: ['method'], params: ['static', 'value'] },
|
|
30
|
+
[Ids.ApiBody]: { targets: ['method'], params: ['value'] },
|
|
31
|
+
[Ids.ApiQuery]: { targets: ['method'], params: ['static', 'static'] },
|
|
32
|
+
[Ids.ApiHeader]: { targets: ['class', 'method'], params: ['static', 'static'] },
|
|
33
|
+
[Ids.ApiSecurity]: { targets: ['class', 'method'], params: [], rest: 'value' },
|
|
34
|
+
[Ids.ApiExclude]: { targets: ['class', 'method'], params: [] },
|
|
35
|
+
})
|
|
36
|
+
|
|
37
|
+
/** The `@znight/openapi` compiler extension. */
|
|
38
|
+
const openapi: CompilerExtension<OpenApiStored> = Object.freeze({
|
|
39
|
+
apiVersion: 1,
|
|
40
|
+
name: EXTENSION_NAME,
|
|
41
|
+
decorators,
|
|
42
|
+
analyzeClass: analyzeOpenApiClass,
|
|
43
|
+
validate: validateOpenApi,
|
|
44
|
+
generate: generateOpenApi,
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
export default openapi
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Identities, codes and the data model of the `@znight/openapi` compiler extension. Pure: types and
|
|
3
|
+
* constants only.
|
|
4
|
+
*/
|
|
5
|
+
import type { Location, ValueRef } from '@znight/compiler'
|
|
6
|
+
|
|
7
|
+
/** Name of the extension (key of `metadata.extensions`). */
|
|
8
|
+
export const EXTENSION_NAME = 'openapi'
|
|
9
|
+
|
|
10
|
+
/** Canonical identities of the decorators and functions of `@znight/openapi`. */
|
|
11
|
+
export const Ids: {
|
|
12
|
+
readonly OpenApiDocument: string
|
|
13
|
+
readonly ApiOperation: string
|
|
14
|
+
readonly ApiTags: string
|
|
15
|
+
readonly ApiResponse: string
|
|
16
|
+
readonly ApiBody: string
|
|
17
|
+
readonly ApiQuery: string
|
|
18
|
+
readonly ApiHeader: string
|
|
19
|
+
readonly ApiSecurity: string
|
|
20
|
+
readonly ApiExclude: string
|
|
21
|
+
readonly securityScheme: string
|
|
22
|
+
} = Object.freeze({
|
|
23
|
+
OpenApiDocument: '@znight/openapi#OpenApiDocument',
|
|
24
|
+
ApiOperation: '@znight/openapi#ApiOperation',
|
|
25
|
+
ApiTags: '@znight/openapi#ApiTags',
|
|
26
|
+
ApiResponse: '@znight/openapi#ApiResponse',
|
|
27
|
+
ApiBody: '@znight/openapi#ApiBody',
|
|
28
|
+
ApiQuery: '@znight/openapi#ApiQuery',
|
|
29
|
+
ApiHeader: '@znight/openapi#ApiHeader',
|
|
30
|
+
ApiSecurity: '@znight/openapi#ApiSecurity',
|
|
31
|
+
ApiExclude: '@znight/openapi#ApiExclude',
|
|
32
|
+
securityScheme: '@znight/openapi#securityScheme',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
/** Identities of `@znight/http` read by the extension. */
|
|
36
|
+
export const HttpIds: {
|
|
37
|
+
readonly Controller: string
|
|
38
|
+
readonly createRouteDecorator: string
|
|
39
|
+
readonly HttpResponse: string
|
|
40
|
+
readonly FileBody: string
|
|
41
|
+
readonly SseEvent: string
|
|
42
|
+
readonly SseBody: string
|
|
43
|
+
} = Object.freeze({
|
|
44
|
+
Controller: '@znight/http#Controller',
|
|
45
|
+
createRouteDecorator: '@znight/http#createRouteDecorator',
|
|
46
|
+
HttpResponse: '@znight/http#HttpResponse',
|
|
47
|
+
FileBody: '@znight/http#FileBody',
|
|
48
|
+
SseEvent: '@znight/http#SseEvent',
|
|
49
|
+
SseBody: '@znight/http#SseBody',
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
/** Route method decorators of `@znight/http` (a method carrying one is a route handler). */
|
|
53
|
+
export const ROUTE_DECORATORS: ReadonlySet<string> = new Set([
|
|
54
|
+
'@znight/http#Get',
|
|
55
|
+
'@znight/http#Post',
|
|
56
|
+
'@znight/http#Put',
|
|
57
|
+
'@znight/http#Patch',
|
|
58
|
+
'@znight/http#Delete',
|
|
59
|
+
'@znight/http#Head',
|
|
60
|
+
'@znight/http#Options',
|
|
61
|
+
'@znight/http#All',
|
|
62
|
+
'@znight/http#Sse',
|
|
63
|
+
])
|
|
64
|
+
|
|
65
|
+
/** Error codes used by the extension (see `ErrorCode` in `@znight/core`). */
|
|
66
|
+
export const Codes: {
|
|
67
|
+
readonly InvalidDecorator: 'ZNIGHT005'
|
|
68
|
+
readonly InvalidOpenApiDefinition: 'ZNIGHT030'
|
|
69
|
+
readonly UndocumentedResponse: 'ZNIGHT031'
|
|
70
|
+
readonly UnrepresentableType: 'ZNIGHT032'
|
|
71
|
+
readonly DuplicateOperationId: 'ZNIGHT033'
|
|
72
|
+
readonly SchemaNameConflict: 'ZNIGHT034'
|
|
73
|
+
readonly InconsistentOperation: 'ZNIGHT035'
|
|
74
|
+
readonly InvalidSecurityRequirement: 'ZNIGHT036'
|
|
75
|
+
} = Object.freeze({
|
|
76
|
+
InvalidDecorator: 'ZNIGHT005',
|
|
77
|
+
InvalidOpenApiDefinition: 'ZNIGHT030',
|
|
78
|
+
UndocumentedResponse: 'ZNIGHT031',
|
|
79
|
+
UnrepresentableType: 'ZNIGHT032',
|
|
80
|
+
DuplicateOperationId: 'ZNIGHT033',
|
|
81
|
+
SchemaNameConflict: 'ZNIGHT034',
|
|
82
|
+
InconsistentOperation: 'ZNIGHT035',
|
|
83
|
+
InvalidSecurityRequirement: 'ZNIGHT036',
|
|
84
|
+
})
|
|
85
|
+
|
|
86
|
+
/** Generic aliases meaning "the Standard Schema S" (`z.output<typeof S>`), checked against the installed libraries. */
|
|
87
|
+
export const SCHEMA_ALIASES: Readonly<Record<string, 'input' | 'output'>> = Object.freeze({
|
|
88
|
+
'zod#output': 'output',
|
|
89
|
+
'zod#infer': 'output',
|
|
90
|
+
'zod#input': 'input',
|
|
91
|
+
'zod/v4#output': 'output',
|
|
92
|
+
'zod/v4#infer': 'output',
|
|
93
|
+
'zod/v4#input': 'input',
|
|
94
|
+
'valibot#InferOutput': 'output',
|
|
95
|
+
'valibot#InferInput': 'input',
|
|
96
|
+
'@znight/http#InferSchemaOutput': 'output',
|
|
97
|
+
'@znight/http#InferSchemaInput': 'input',
|
|
98
|
+
'@standard-schema/spec#StandardSchemaV1.InferOutput': 'output',
|
|
99
|
+
'@standard-schema/spec#StandardSchemaV1.InferInput': 'input',
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
/** ArkType: `typeof S.infer` / `typeof S.inferIn`. */
|
|
103
|
+
export const SCHEMA_MEMBERS: Readonly<Record<string, 'input' | 'output'>> = Object.freeze({
|
|
104
|
+
infer: 'output',
|
|
105
|
+
inferIn: 'input',
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
/** Types kept as references by the shape resolver (bodies of special responses). */
|
|
109
|
+
export const KEEP: readonly string[] = Object.freeze([
|
|
110
|
+
HttpIds.HttpResponse,
|
|
111
|
+
HttpIds.FileBody,
|
|
112
|
+
HttpIds.SseEvent,
|
|
113
|
+
HttpIds.SseBody,
|
|
114
|
+
'globalThis#AsyncIterable',
|
|
115
|
+
'globalThis#AsyncIterableIterator',
|
|
116
|
+
'globalThis#AsyncGenerator',
|
|
117
|
+
'globalThis#Response',
|
|
118
|
+
])
|
|
119
|
+
|
|
120
|
+
/** Data stored by `analyzeClass`. */
|
|
121
|
+
export type OpenApiStored =
|
|
122
|
+
| {
|
|
123
|
+
readonly kind: 'document'
|
|
124
|
+
readonly identity: string
|
|
125
|
+
readonly displayName: string
|
|
126
|
+
readonly location: Location
|
|
127
|
+
}
|
|
128
|
+
| {
|
|
129
|
+
readonly kind: 'controller'
|
|
130
|
+
readonly identity: string
|
|
131
|
+
readonly displayName: string
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/** A Standard Schema to convert at assembly. */
|
|
135
|
+
export interface SlotData {
|
|
136
|
+
readonly name: string
|
|
137
|
+
readonly ref: ValueRef
|
|
138
|
+
readonly io: Set<'input' | 'output'>
|
|
139
|
+
/** The declaration of the schema (the reference when it cannot be found). */
|
|
140
|
+
readonly location: Location
|
|
141
|
+
}
|