@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,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenAPI 3.1 types (our own, no `openapi-types` dependency). They describe the documents produced
|
|
3
|
+
* by `buildOpenApiDocument`: every object is read-only, optional fields are omitted when absent and
|
|
4
|
+
* `x-*` specification extensions are allowed where OpenAPI allows them.
|
|
5
|
+
*
|
|
6
|
+
* Schemas are JSON Schema 2020-12 ({@link JsonSchema}), the dialect of OpenAPI 3.1.
|
|
7
|
+
*/
|
|
8
|
+
/** A JSON value. */
|
|
9
|
+
type JsonValue = string | number | boolean | null | readonly JsonValue[] | {
|
|
10
|
+
readonly [key: string]: JsonValue;
|
|
11
|
+
};
|
|
12
|
+
/** A JSON Schema 2020-12 object (keywords are not modelled one by one). */
|
|
13
|
+
interface JsonSchema {
|
|
14
|
+
readonly [keyword: string]: JsonValue | undefined;
|
|
15
|
+
}
|
|
16
|
+
/** `x-*` fields. */
|
|
17
|
+
interface SpecificationExtensions {
|
|
18
|
+
readonly [extension: `x-${string}`]: JsonValue | undefined;
|
|
19
|
+
}
|
|
20
|
+
/** `{ $ref }` to a component (`#/components/schemas/Book`). */
|
|
21
|
+
interface ReferenceObject {
|
|
22
|
+
readonly $ref: string;
|
|
23
|
+
readonly summary?: string;
|
|
24
|
+
readonly description?: string;
|
|
25
|
+
}
|
|
26
|
+
interface ContactObject extends SpecificationExtensions {
|
|
27
|
+
readonly name?: string;
|
|
28
|
+
readonly url?: string;
|
|
29
|
+
readonly email?: string;
|
|
30
|
+
}
|
|
31
|
+
interface LicenseObject extends SpecificationExtensions {
|
|
32
|
+
readonly name: string;
|
|
33
|
+
/** SPDX expression (exclusive with `url`). */
|
|
34
|
+
readonly identifier?: string;
|
|
35
|
+
readonly url?: string;
|
|
36
|
+
}
|
|
37
|
+
interface InfoObject extends SpecificationExtensions {
|
|
38
|
+
readonly title: string;
|
|
39
|
+
readonly version: string;
|
|
40
|
+
readonly summary?: string;
|
|
41
|
+
readonly description?: string;
|
|
42
|
+
readonly termsOfService?: string;
|
|
43
|
+
readonly contact?: ContactObject;
|
|
44
|
+
readonly license?: LicenseObject;
|
|
45
|
+
}
|
|
46
|
+
interface ServerVariableObject extends SpecificationExtensions {
|
|
47
|
+
readonly enum?: readonly string[];
|
|
48
|
+
readonly default: string;
|
|
49
|
+
readonly description?: string;
|
|
50
|
+
}
|
|
51
|
+
interface ServerObject extends SpecificationExtensions {
|
|
52
|
+
readonly url: string;
|
|
53
|
+
readonly description?: string;
|
|
54
|
+
readonly variables?: Readonly<Record<string, ServerVariableObject>>;
|
|
55
|
+
}
|
|
56
|
+
interface ExternalDocumentationObject extends SpecificationExtensions {
|
|
57
|
+
readonly url: string;
|
|
58
|
+
readonly description?: string;
|
|
59
|
+
}
|
|
60
|
+
interface TagObject extends SpecificationExtensions {
|
|
61
|
+
readonly name: string;
|
|
62
|
+
readonly description?: string;
|
|
63
|
+
readonly externalDocs?: ExternalDocumentationObject;
|
|
64
|
+
}
|
|
65
|
+
/** Parameter locations. */
|
|
66
|
+
type ParameterLocation = "path" | "query" | "header" | "cookie";
|
|
67
|
+
interface ExampleObject extends SpecificationExtensions {
|
|
68
|
+
readonly summary?: string;
|
|
69
|
+
readonly description?: string;
|
|
70
|
+
readonly value?: JsonValue;
|
|
71
|
+
readonly externalValue?: string;
|
|
72
|
+
}
|
|
73
|
+
interface ParameterObjectOf<S> extends SpecificationExtensions {
|
|
74
|
+
readonly name: string;
|
|
75
|
+
readonly in: ParameterLocation;
|
|
76
|
+
readonly description?: string;
|
|
77
|
+
readonly required?: boolean;
|
|
78
|
+
readonly deprecated?: boolean;
|
|
79
|
+
readonly allowEmptyValue?: boolean;
|
|
80
|
+
readonly style?: string;
|
|
81
|
+
readonly explode?: boolean;
|
|
82
|
+
readonly schema?: S;
|
|
83
|
+
readonly example?: JsonValue;
|
|
84
|
+
readonly examples?: Readonly<Record<string, ExampleObject | ReferenceObject>>;
|
|
85
|
+
}
|
|
86
|
+
interface HeaderObjectOf<S> extends SpecificationExtensions {
|
|
87
|
+
readonly description?: string;
|
|
88
|
+
readonly required?: boolean;
|
|
89
|
+
readonly deprecated?: boolean;
|
|
90
|
+
readonly schema?: S;
|
|
91
|
+
readonly example?: JsonValue;
|
|
92
|
+
}
|
|
93
|
+
interface EncodingObjectOf<S> extends SpecificationExtensions {
|
|
94
|
+
readonly contentType?: string;
|
|
95
|
+
readonly headers?: Readonly<Record<string, HeaderObjectOf<S> | ReferenceObject>>;
|
|
96
|
+
readonly style?: string;
|
|
97
|
+
readonly explode?: boolean;
|
|
98
|
+
}
|
|
99
|
+
interface MediaTypeObjectOf<S> extends SpecificationExtensions {
|
|
100
|
+
readonly schema?: S;
|
|
101
|
+
readonly example?: JsonValue;
|
|
102
|
+
readonly examples?: Readonly<Record<string, ExampleObject | ReferenceObject>>;
|
|
103
|
+
readonly encoding?: Readonly<Record<string, EncodingObjectOf<S>>>;
|
|
104
|
+
}
|
|
105
|
+
interface RequestBodyObjectOf<S> extends SpecificationExtensions {
|
|
106
|
+
readonly description?: string;
|
|
107
|
+
readonly content: Readonly<Record<string, MediaTypeObjectOf<S>>>;
|
|
108
|
+
readonly required?: boolean;
|
|
109
|
+
}
|
|
110
|
+
interface ResponseObjectOf<S> extends SpecificationExtensions {
|
|
111
|
+
readonly description: string;
|
|
112
|
+
readonly headers?: Readonly<Record<string, HeaderObjectOf<S> | ReferenceObject>>;
|
|
113
|
+
readonly content?: Readonly<Record<string, MediaTypeObjectOf<S>>>;
|
|
114
|
+
}
|
|
115
|
+
/** `{ schemeName: scopes }`: every scheme of one requirement applies (AND). */
|
|
116
|
+
interface SecurityRequirementObject {
|
|
117
|
+
readonly [scheme: string]: readonly string[];
|
|
118
|
+
}
|
|
119
|
+
/** An OpenAPI Operation Object whose schemas are `S` and whose parameters may also be `P`. */
|
|
120
|
+
interface OperationObjectOf<S, P = never> extends SpecificationExtensions {
|
|
121
|
+
readonly tags?: readonly string[];
|
|
122
|
+
readonly summary?: string;
|
|
123
|
+
readonly description?: string;
|
|
124
|
+
readonly externalDocs?: ExternalDocumentationObject;
|
|
125
|
+
readonly operationId?: string;
|
|
126
|
+
readonly parameters?: readonly (ParameterObjectOf<S> | ReferenceObject | P)[];
|
|
127
|
+
readonly requestBody?: RequestBodyObjectOf<S> | ReferenceObject;
|
|
128
|
+
readonly responses?: Readonly<Record<string, ResponseObjectOf<S> | ReferenceObject>>;
|
|
129
|
+
readonly deprecated?: boolean;
|
|
130
|
+
readonly security?: readonly SecurityRequirementObject[];
|
|
131
|
+
readonly servers?: readonly ServerObject[];
|
|
132
|
+
}
|
|
133
|
+
type ParameterObject = ParameterObjectOf<JsonSchema>;
|
|
134
|
+
type HeaderObject = HeaderObjectOf<JsonSchema>;
|
|
135
|
+
type MediaTypeObject = MediaTypeObjectOf<JsonSchema>;
|
|
136
|
+
type RequestBodyObject = RequestBodyObjectOf<JsonSchema>;
|
|
137
|
+
type ResponseObject = ResponseObjectOf<JsonSchema>;
|
|
138
|
+
type OperationObject = OperationObjectOf<JsonSchema>;
|
|
139
|
+
/** HTTP methods of a path item, in OpenAPI order. */
|
|
140
|
+
type OpenApiMethod = "get" | "put" | "post" | "delete" | "options" | "head" | "patch";
|
|
141
|
+
interface PathItemObject extends SpecificationExtensions {
|
|
142
|
+
readonly summary?: string;
|
|
143
|
+
readonly description?: string;
|
|
144
|
+
readonly get?: OperationObject;
|
|
145
|
+
readonly put?: OperationObject;
|
|
146
|
+
readonly post?: OperationObject;
|
|
147
|
+
readonly delete?: OperationObject;
|
|
148
|
+
readonly options?: OperationObject;
|
|
149
|
+
readonly head?: OperationObject;
|
|
150
|
+
readonly patch?: OperationObject;
|
|
151
|
+
readonly trace?: OperationObject;
|
|
152
|
+
readonly servers?: readonly ServerObject[];
|
|
153
|
+
readonly parameters?: readonly (ParameterObject | ReferenceObject)[];
|
|
154
|
+
}
|
|
155
|
+
interface OAuthFlowObject extends SpecificationExtensions {
|
|
156
|
+
readonly authorizationUrl?: string;
|
|
157
|
+
readonly tokenUrl?: string;
|
|
158
|
+
readonly refreshUrl?: string;
|
|
159
|
+
readonly scopes: Readonly<Record<string, string>>;
|
|
160
|
+
}
|
|
161
|
+
interface OAuthFlowsObject extends SpecificationExtensions {
|
|
162
|
+
readonly implicit?: OAuthFlowObject;
|
|
163
|
+
readonly password?: OAuthFlowObject;
|
|
164
|
+
readonly clientCredentials?: OAuthFlowObject;
|
|
165
|
+
readonly authorizationCode?: OAuthFlowObject;
|
|
166
|
+
}
|
|
167
|
+
/** An OpenAPI Security Scheme Object. */
|
|
168
|
+
type SecuritySchemeObject = ({
|
|
169
|
+
readonly type: "apiKey";
|
|
170
|
+
readonly name: string;
|
|
171
|
+
readonly in: "query" | "header" | "cookie";
|
|
172
|
+
readonly description?: string;
|
|
173
|
+
} & SpecificationExtensions) | ({
|
|
174
|
+
readonly type: "http";
|
|
175
|
+
/** `bearer`, `basic`... (RFC 7235 scheme name). */
|
|
176
|
+
readonly scheme: string;
|
|
177
|
+
readonly bearerFormat?: string;
|
|
178
|
+
readonly description?: string;
|
|
179
|
+
} & SpecificationExtensions) | ({
|
|
180
|
+
readonly type: "oauth2";
|
|
181
|
+
readonly flows: OAuthFlowsObject;
|
|
182
|
+
readonly description?: string;
|
|
183
|
+
} & SpecificationExtensions) | ({
|
|
184
|
+
readonly type: "openIdConnect";
|
|
185
|
+
readonly openIdConnectUrl: string;
|
|
186
|
+
readonly description?: string;
|
|
187
|
+
} & SpecificationExtensions) | ({
|
|
188
|
+
readonly type: "mutualTLS";
|
|
189
|
+
readonly description?: string;
|
|
190
|
+
} & SpecificationExtensions);
|
|
191
|
+
interface ComponentsObject extends SpecificationExtensions {
|
|
192
|
+
readonly schemas?: Readonly<Record<string, JsonSchema>>;
|
|
193
|
+
readonly responses?: Readonly<Record<string, ResponseObject | ReferenceObject>>;
|
|
194
|
+
readonly parameters?: Readonly<Record<string, ParameterObject | ReferenceObject>>;
|
|
195
|
+
readonly examples?: Readonly<Record<string, ExampleObject | ReferenceObject>>;
|
|
196
|
+
readonly requestBodies?: Readonly<Record<string, RequestBodyObject | ReferenceObject>>;
|
|
197
|
+
readonly headers?: Readonly<Record<string, HeaderObject | ReferenceObject>>;
|
|
198
|
+
readonly securitySchemes?: Readonly<Record<string, SecuritySchemeObject>>;
|
|
199
|
+
}
|
|
200
|
+
/** An OpenAPI 3.1 document. */
|
|
201
|
+
interface OpenApiObject extends SpecificationExtensions {
|
|
202
|
+
readonly openapi: string;
|
|
203
|
+
readonly info: InfoObject;
|
|
204
|
+
readonly jsonSchemaDialect?: string;
|
|
205
|
+
readonly servers?: readonly ServerObject[];
|
|
206
|
+
readonly paths?: Readonly<Record<string, PathItemObject>>;
|
|
207
|
+
readonly components?: ComponentsObject;
|
|
208
|
+
readonly security?: readonly SecurityRequirementObject[];
|
|
209
|
+
readonly tags?: readonly TagObject[];
|
|
210
|
+
readonly externalDocs?: ExternalDocumentationObject;
|
|
211
|
+
}
|
|
212
|
+
export { SecuritySchemeObject as A, PathItemObject as C, ResponseObject as D, RequestBodyObjectOf as E, ServerVariableObject as M, SpecificationExtensions as N, ResponseObjectOf as O, TagObject as P, ParameterObjectOf as S, RequestBodyObject as T, OpenApiObject as _, ExternalDocumentationObject as a, ParameterLocation as b, InfoObject as c, LicenseObject as d, MediaTypeObject as f, OpenApiMethod as g, OAuthFlowsObject as h, ExampleObject as i, ServerObject as j, SecurityRequirementObject as k, JsonSchema as l, OAuthFlowObject as m, ContactObject as n, HeaderObject as o, MediaTypeObjectOf as p, EncodingObjectOf as r, HeaderObjectOf as s, ComponentsObject as t, JsonValue as u, OperationObject as v, ReferenceObject as w, ParameterObject as x, OperationObjectOf as y };
|
|
213
|
+
//# sourceMappingURL=types-VzBexMKj.d.mts.map
|
package/dist/vite.d.mts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { r as EmitRuntime } from "./index-CqQ6IRnN.mjs";
|
|
2
|
+
import { Plugin } from "vite";
|
|
3
|
+
/** Name of the plugin (an application uses one instance: the first one wins). */
|
|
4
|
+
export declare const OPENAPI_PLUGIN_NAME = "znight:openapi";
|
|
5
|
+
/** Options of {@link openapi}. */
|
|
6
|
+
export interface OpenApiVitePluginOptions {
|
|
7
|
+
/** Output files, relative to the Vite root (`.yaml` / `.yml` write YAML). Default: `<build.outDir>/openapi.json`. */
|
|
8
|
+
readonly output?: string | readonly string[];
|
|
9
|
+
/**
|
|
10
|
+
* CI: never write the outputs outside `build.outDir` (the committed files), fail the build when one
|
|
11
|
+
* is missing or stale. The outputs inside `build.outDir` are build artifacts, written by every
|
|
12
|
+
* build. Default `false`.
|
|
13
|
+
*/
|
|
14
|
+
readonly check?: boolean;
|
|
15
|
+
/** HTTP prefix (`servers` default when `@OpenApiDocument` declares none). */
|
|
16
|
+
readonly prefix?: string;
|
|
17
|
+
/** Runtime loading the application modules. Default `'auto'`. */
|
|
18
|
+
readonly runtime?: EmitRuntime;
|
|
19
|
+
/** Module whose default export is a `SchemaConverter[]`, relative to the Vite root. */
|
|
20
|
+
readonly converters?: string;
|
|
21
|
+
}
|
|
22
|
+
/** The `openapi()` Vite plugin (build only). */
|
|
23
|
+
export declare function openapi(options?: OpenApiVitePluginOptions): Plugin;
|
|
24
|
+
//# sourceMappingURL=vite.d.mts.map
|
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { isAbsolute, join, relative, resolve } from "node:path";
|
|
2
|
+
// src/vite.ts
|
|
3
|
+
/** Name of the plugin (an application uses one instance: the first one wins). */
|
|
4
|
+
const OPENAPI_PLUGIN_NAME = "znight:openapi";
|
|
5
|
+
/** The `openapi()` Vite plugin (build only). */
|
|
6
|
+
function openapi(options = {}) {
|
|
7
|
+
let config;
|
|
8
|
+
let active = true;
|
|
9
|
+
let emitted = false;
|
|
10
|
+
const plugin = {
|
|
11
|
+
name: OPENAPI_PLUGIN_NAME,
|
|
12
|
+
apply: "build",
|
|
13
|
+
configResolved(resolved) {
|
|
14
|
+
config = resolved;
|
|
15
|
+
active = resolved.plugins.find((candidate) => candidate.name === OPENAPI_PLUGIN_NAME) === plugin;
|
|
16
|
+
},
|
|
17
|
+
buildStart() {
|
|
18
|
+
emitted = false;
|
|
19
|
+
},
|
|
20
|
+
async writeBundle() {
|
|
21
|
+
if (!active || emitted || config === void 0) return;
|
|
22
|
+
emitted = true;
|
|
23
|
+
const api = config.plugins.find((candidate) => candidate.name === "znight")?.api;
|
|
24
|
+
if (api?.result !== void 0 && api.result.ok === false) return;
|
|
25
|
+
const root = config.root;
|
|
26
|
+
const outputs = options.output === void 0 ? [join(resolve(root, config.build.outDir), "openapi.json")] : (typeof options.output === "string" ? [options.output] : options.output).map((file) => resolve(root, file));
|
|
27
|
+
const outDir = resolve(root, config.build.outDir);
|
|
28
|
+
const checked = options.check === true ? outputs.filter((file) => !isInside(outDir, file)) : [];
|
|
29
|
+
if (options.check === true && checked.length === 0) this.warn("[znight:openapi] check: every output is in build.outDir, written by each build: nothing is checked (add the committed file to output)");
|
|
30
|
+
const compilerRoot = api?.compiler?.options?.root;
|
|
31
|
+
const given = typeof api?.options === "object" && api.options !== null ? api.options : void 0;
|
|
32
|
+
const { emitOpenApi } = await import("./emit.mjs");
|
|
33
|
+
const result = await emitOpenApi({
|
|
34
|
+
root,
|
|
35
|
+
output: outputs,
|
|
36
|
+
...checked.length === 0 ? {} : { check: checked },
|
|
37
|
+
...options.prefix === void 0 ? {} : { prefix: options.prefix },
|
|
38
|
+
...options.runtime === void 0 ? {} : { runtime: options.runtime },
|
|
39
|
+
...options.converters === void 0 ? {} : { converters: options.converters },
|
|
40
|
+
...config.configFile === void 0 ? {} : { config: config.configFile },
|
|
41
|
+
...given === void 0 ? {} : { compilerOptions: {
|
|
42
|
+
...given,
|
|
43
|
+
root: typeof compilerRoot === "string" ? compilerRoot : resolve(root, String(given["root"] ?? "."))
|
|
44
|
+
} }
|
|
45
|
+
});
|
|
46
|
+
const show = (file) => {
|
|
47
|
+
const path = relative(root, file);
|
|
48
|
+
return path === "" || path.startsWith("..") || isAbsolute(path) ? file : path;
|
|
49
|
+
};
|
|
50
|
+
if (!result.ok) this.error(`[znight:openapi] the application does not compile: ${result.diagnostics.filter((d) => d.severity === "error").length} error(s)`);
|
|
51
|
+
for (const warning of result.warnings) this.warn(`${warning.code}: ${warning.message}`);
|
|
52
|
+
if (result.stale) this.error(`[znight:openapi] ${result.staleFiles.map(show).join(", ")} ${result.staleFiles.length > 1 ? "are" : "is"} missing or out of date: run "znight openapi"`);
|
|
53
|
+
for (const file of result.written) config.logger.info(`[znight:openapi] wrote ${show(file)}`);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
return plugin;
|
|
57
|
+
}
|
|
58
|
+
function isInside(directory, file) {
|
|
59
|
+
const path = relative(directory, file);
|
|
60
|
+
return path !== "" && !path.startsWith("..") && !isAbsolute(path);
|
|
61
|
+
}
|
|
62
|
+
export { OPENAPI_PLUGIN_NAME, openapi };
|
|
63
|
+
|
|
64
|
+
//# sourceMappingURL=vite.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vite.mjs","names":[],"sources":["../src/vite.ts"],"sourcesContent":["/**\n * `@znight/openapi/vite`: the `openapi()` Vite plugin. After `vite build` / `znight build` wrote the\n * bundle (and after each good rebuild of `znight dev`), it emits the OpenAPI document with\n * `emitOpenApi()`; with `check`, a missing or stale committed output fails the build.\n *\n * ```ts\n * export default defineConfig({\n * plugins: [znight(options), openapi({ output: ['openapi.json', 'dist/openapi.json'], check: process.env['CI'] === 'true' })],\n * })\n * ```\n */\nimport type { Plugin, ResolvedConfig } from 'vite'\nimport type { EmitRuntime } from './emit/index.ts'\n\nimport { isAbsolute, join, relative, resolve } from 'node:path'\n\n/** Name of the plugin (an application uses one instance: the first one wins). */\nexport const OPENAPI_PLUGIN_NAME = 'znight:openapi'\n\n/** Options of {@link openapi}. */\nexport interface OpenApiVitePluginOptions {\n /** Output files, relative to the Vite root (`.yaml` / `.yml` write YAML). Default: `<build.outDir>/openapi.json`. */\n readonly output?: string | readonly string[]\n /**\n * CI: never write the outputs outside `build.outDir` (the committed files), fail the build when one\n * is missing or stale. The outputs inside `build.outDir` are build artifacts, written by every\n * build. Default `false`.\n */\n readonly check?: boolean\n /** HTTP prefix (`servers` default when `@OpenApiDocument` declares none). */\n readonly prefix?: string\n /** Runtime loading the application modules. Default `'auto'`. */\n readonly runtime?: EmitRuntime\n /** Module whose default export is a `SchemaConverter[]`, relative to the Vite root. */\n readonly converters?: string\n}\n\ninterface ZnightApiLike {\n readonly options?: unknown\n readonly result?: { readonly ok?: unknown }\n readonly compiler?: { readonly options?: { readonly root?: unknown } }\n}\n\n/** The `openapi()` Vite plugin (build only). */\nexport function openapi(options: OpenApiVitePluginOptions = {}): Plugin {\n let config: ResolvedConfig | undefined\n let active = true\n let emitted = false\n const plugin: Plugin = {\n name: OPENAPI_PLUGIN_NAME,\n apply: 'build',\n configResolved(resolved) {\n config = resolved\n // the config file wins over a copy added by the CLI (znight build --openapi)\n active = resolved.plugins.find(candidate => candidate.name === OPENAPI_PLUGIN_NAME) === plugin\n },\n buildStart() {\n emitted = false\n },\n async writeBundle() {\n if (!active || emitted || config === undefined) return\n emitted = true\n const znight = config.plugins.find(candidate => candidate.name === 'znight') as\n | { api?: ZnightApiLike }\n | undefined\n const api = znight?.api\n // watch mode: the bundle of a failed compile throws the diagnostics; keep the last document\n if (api?.result !== undefined && api.result.ok === false) return\n const root = config.root\n const outputs =\n options.output === undefined\n ? [join(resolve(root, config.build.outDir), 'openapi.json')]\n : (typeof options.output === 'string' ? [options.output] : options.output).map(file => resolve(root, file))\n const outDir = resolve(root, config.build.outDir)\n const checked = options.check === true ? outputs.filter(file => !isInside(outDir, file)) : []\n if (options.check === true && checked.length === 0) {\n this.warn(\n '[znight:openapi] check: every output is in build.outDir, written by each build: nothing is checked (add the committed file to output)',\n )\n }\n const compilerRoot = api?.compiler?.options?.root\n const given =\n typeof api?.options === 'object' && api.options !== null ? (api.options as Record<string, unknown>) : undefined\n const { emitOpenApi } = await import('./emit/index.ts')\n const result = await emitOpenApi({\n root,\n output: outputs,\n ...(checked.length === 0 ? {} : { check: checked }),\n ...(options.prefix === undefined ? {} : { prefix: options.prefix }),\n ...(options.runtime === undefined ? {} : { runtime: options.runtime }),\n ...(options.converters === undefined ? {} : { converters: options.converters }),\n ...(config.configFile === undefined ? {} : { config: config.configFile }),\n ...(given === undefined\n ? {}\n : {\n compilerOptions: {\n ...given,\n root: typeof compilerRoot === 'string' ? compilerRoot : resolve(root, String(given['root'] ?? '.')),\n },\n }),\n })\n const show = (file: string): string => {\n const path = relative(root, file)\n return path === '' || path.startsWith('..') || isAbsolute(path) ? file : path\n }\n if (!result.ok) {\n this.error(\n `[znight:openapi] the application does not compile: ${result.diagnostics.filter(d => d.severity === 'error').length} error(s)`,\n )\n }\n for (const warning of result.warnings) this.warn(`${warning.code}: ${warning.message}`)\n if (result.stale) {\n this.error(\n `[znight:openapi] ${result.staleFiles.map(show).join(', ')} ${result.staleFiles.length > 1 ? 'are' : 'is'} missing or out of date: run \"znight openapi\"`,\n )\n }\n for (const file of result.written) config.logger.info(`[znight:openapi] wrote ${show(file)}`)\n },\n }\n return plugin\n}\n\nfunction isInside(directory: string, file: string): boolean {\n const path = relative(directory, file)\n return path !== '' && !path.startsWith('..') && !isAbsolute(path)\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,117 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@znight/openapi",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.1",
|
|
4
|
+
"description": "Znight OpenAPI: OpenAPI 3.1 documents generated at build time from your controllers, served with Scalar or Swagger UI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Ugho STEPHAN",
|
|
7
|
+
"homepage": "https://github.com/znight-org/znight/tree/main/packages/openapi#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/znight-org/znight.git",
|
|
11
|
+
"directory": "packages/openapi"
|
|
12
|
+
},
|
|
13
|
+
"bugs": "https://github.com/znight-org/znight/issues",
|
|
14
|
+
"keywords": ["znight", "openapi", "swagger", "scalar", "api-docs", "json-schema"],
|
|
15
|
+
"type": "module",
|
|
16
|
+
"sideEffects": false,
|
|
17
|
+
"engines": {
|
|
18
|
+
"node": ">=24"
|
|
19
|
+
},
|
|
20
|
+
"exports": {
|
|
21
|
+
".": {
|
|
22
|
+
"@znight/source": "./src/index.ts",
|
|
23
|
+
"types": "./dist/index.d.mts",
|
|
24
|
+
"default": "./dist/index.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./compiler": {
|
|
27
|
+
"@znight/source": "./src/compiler/index.ts",
|
|
28
|
+
"types": "./dist/compiler.d.mts",
|
|
29
|
+
"default": "./dist/compiler.mjs"
|
|
30
|
+
},
|
|
31
|
+
"./emit": {
|
|
32
|
+
"@znight/source": "./src/emit/index.ts",
|
|
33
|
+
"types": "./dist/emit.d.mts",
|
|
34
|
+
"default": "./dist/emit.mjs"
|
|
35
|
+
},
|
|
36
|
+
"./vite": {
|
|
37
|
+
"@znight/source": "./src/vite.ts",
|
|
38
|
+
"types": "./dist/vite.d.mts",
|
|
39
|
+
"default": "./dist/vite.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./testing": {
|
|
42
|
+
"@znight/source": "./src/testing.ts",
|
|
43
|
+
"types": "./dist/testing.d.mts",
|
|
44
|
+
"default": "./dist/testing.mjs"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
47
|
+
},
|
|
48
|
+
"types": "./dist/index.d.mts",
|
|
49
|
+
"files": ["dist", "src"],
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsdown",
|
|
52
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p test"
|
|
53
|
+
},
|
|
54
|
+
"publishConfig": {
|
|
55
|
+
"access": "public"
|
|
56
|
+
},
|
|
57
|
+
"dependencies": {
|
|
58
|
+
"@znight/core": "0.1.1"
|
|
59
|
+
},
|
|
60
|
+
"peerDependencies": {
|
|
61
|
+
"@znight/http": "^0.1.1",
|
|
62
|
+
"@znight/compiler": "^0.1.1",
|
|
63
|
+
"vite": "^8.0.0",
|
|
64
|
+
"@valibot/to-json-schema": "^1.5.0",
|
|
65
|
+
"yaml": "^2.0.0",
|
|
66
|
+
"@scalar/api-reference": "^1.0.0",
|
|
67
|
+
"swagger-ui-dist": "^5.0.0",
|
|
68
|
+
"@cfworker/json-schema": "^4.1.0"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"@znight/compiler": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"vite": {
|
|
75
|
+
"optional": true
|
|
76
|
+
},
|
|
77
|
+
"@valibot/to-json-schema": {
|
|
78
|
+
"optional": true
|
|
79
|
+
},
|
|
80
|
+
"yaml": {
|
|
81
|
+
"optional": true
|
|
82
|
+
},
|
|
83
|
+
"@scalar/api-reference": {
|
|
84
|
+
"optional": true
|
|
85
|
+
},
|
|
86
|
+
"swagger-ui-dist": {
|
|
87
|
+
"optional": true
|
|
88
|
+
},
|
|
89
|
+
"@cfworker/json-schema": {
|
|
90
|
+
"optional": true
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
"devDependencies": {
|
|
94
|
+
"@znight/http": "0.1.1",
|
|
95
|
+
"@znight/compiler": "0.1.1",
|
|
96
|
+
"@znight/testing": "0.1.1",
|
|
97
|
+
"zod": "4.6.7",
|
|
98
|
+
"valibot": "1.5.0",
|
|
99
|
+
"@valibot/to-json-schema": "1.8.0",
|
|
100
|
+
"arktype": "2.2.9",
|
|
101
|
+
"yaml": "2.9.1",
|
|
102
|
+
"@seriousme/openapi-schema-validator": "2.11.0",
|
|
103
|
+
"@cfworker/json-schema": "4.1.1",
|
|
104
|
+
"vite": "8.3.5"
|
|
105
|
+
},
|
|
106
|
+
"znight": {
|
|
107
|
+
"apiVersion": 1,
|
|
108
|
+
"compiler": "@znight/openapi/compiler",
|
|
109
|
+
"provides": [
|
|
110
|
+
{
|
|
111
|
+
"export": "OpenApi",
|
|
112
|
+
"plugin": "OpenApiPlugin",
|
|
113
|
+
"scope": "singleton"
|
|
114
|
+
}
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
}
|