@znight/openapi 0.0.0-stage → 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.
- 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,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `analyzeClass`: records the `@OpenApiDocument` class and the controllers carrying `@Api*`
|
|
3
|
+
* decorators, and reports misplaced decorators (ZNIGHT030). The operations are built in
|
|
4
|
+
* `validate`, from the route table of the http extension.
|
|
5
|
+
*/
|
|
6
|
+
import type { AnalyzeContext, ClassInfo, DecoratorInfo } from '@znight/compiler'
|
|
7
|
+
import type { OpenApiStored } from './model.ts'
|
|
8
|
+
|
|
9
|
+
import { Codes, EXTENSION_NAME, HttpIds, Ids, ROUTE_DECORATORS } from './model.ts'
|
|
10
|
+
|
|
11
|
+
/** `analyzeClass` of the extension. */
|
|
12
|
+
export function analyzeOpenApiClass(cls: ClassInfo, ctx: AnalyzeContext<OpenApiStored>): void {
|
|
13
|
+
const owned = (decorators: readonly DecoratorInfo[]): DecoratorInfo[] =>
|
|
14
|
+
decorators.filter(decorator => decorator.owner === EXTENSION_NAME)
|
|
15
|
+
const document = cls.decorators.find(decorator => decorator.identity === Ids.OpenApiDocument)
|
|
16
|
+
const controller = cls.decorators.some(decorator => decorator.identity === HttpIds.Controller)
|
|
17
|
+
const members = [
|
|
18
|
+
...cls.methods.map(method => ({ decorators: owned(method.decorators), method })),
|
|
19
|
+
...cls.properties.map(property => ({ decorators: owned(property.decorators), method: undefined })),
|
|
20
|
+
]
|
|
21
|
+
const misplaced = (decorator: DecoratorInfo, message: string, hints: readonly string[]): void => {
|
|
22
|
+
ctx.report({
|
|
23
|
+
code: Codes.InvalidOpenApiDefinition,
|
|
24
|
+
severity: 'error',
|
|
25
|
+
message,
|
|
26
|
+
location: decorator.location,
|
|
27
|
+
hints,
|
|
28
|
+
})
|
|
29
|
+
}
|
|
30
|
+
if (document !== undefined) {
|
|
31
|
+
if (controller) {
|
|
32
|
+
misplaced(document, `@OpenApiDocument goes on a class of its own, not on the controller ${cls.displayName}`, [
|
|
33
|
+
'Declare it on an empty class: @OpenApiDocument({...}) export class Api {}',
|
|
34
|
+
])
|
|
35
|
+
}
|
|
36
|
+
for (const decorator of owned(cls.decorators)) {
|
|
37
|
+
if (decorator !== document && !controller) {
|
|
38
|
+
misplaced(
|
|
39
|
+
decorator,
|
|
40
|
+
`@${decorator.name} applies to controllers and route handlers, not to the @OpenApiDocument class`,
|
|
41
|
+
[],
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
ctx.store({ kind: 'document', identity: cls.identity, displayName: cls.displayName, location: document.location })
|
|
46
|
+
if (!controller) return
|
|
47
|
+
}
|
|
48
|
+
if (!controller) {
|
|
49
|
+
const consumer = cls.decorators.some(decorator => decorator.identity === '@znight/messaging#Consumer')
|
|
50
|
+
const hints = consumer
|
|
51
|
+
? ['Message consumers are not documented by OpenAPI (AsyncAPI is not supported in v0.1)']
|
|
52
|
+
: ['Add @Controller() to the class, or remove the decorator']
|
|
53
|
+
for (const decorator of owned(cls.decorators)) {
|
|
54
|
+
misplaced(decorator, `@${decorator.name} applies to controllers: ${cls.displayName} is not a @Controller`, hints)
|
|
55
|
+
}
|
|
56
|
+
for (const member of members) {
|
|
57
|
+
for (const decorator of member.decorators) {
|
|
58
|
+
misplaced(
|
|
59
|
+
decorator,
|
|
60
|
+
`@${decorator.name} applies to route handlers: ${cls.displayName} is not a @Controller`,
|
|
61
|
+
hints,
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return
|
|
66
|
+
}
|
|
67
|
+
for (const member of members) {
|
|
68
|
+
const handler = member.method?.decorators.some(
|
|
69
|
+
decorator => decorator.identity !== undefined && ROUTE_DECORATORS.has(decorator.identity),
|
|
70
|
+
)
|
|
71
|
+
if (handler === true) continue
|
|
72
|
+
for (const decorator of member.decorators) {
|
|
73
|
+
misplaced(
|
|
74
|
+
decorator,
|
|
75
|
+
`@${decorator.name} applies to route handlers: ${cls.displayName}.${member.method?.name ?? 'this member'} has no route decorator (@Get, @Post...)`,
|
|
76
|
+
['Add a route decorator, or move the decorator to a route handler'],
|
|
77
|
+
)
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
ctx.store({ kind: 'controller', identity: cls.identity, displayName: cls.displayName })
|
|
81
|
+
}
|