@1szx1/vite-plugin-swagger2ts 1.0.8 → 1.0.9

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@1szx1/vite-plugin-swagger2ts",
3
3
  "description": "fork for https://github.com/1SZX1/vite-plugin-swagger2ts",
4
- "version": "1.0.8",
4
+ "version": "1.0.9",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
7
7
  "types": "index.d.ts",
@@ -14,20 +14,18 @@
14
14
  "homepage": "https://github.com/1SZX1/vite-plugin-swagger2ts",
15
15
  "bugs": "https://github.com/1SZX1/vite-plugin-swagger2ts/issues",
16
16
  "files": [
17
- "dist",
18
- "src",
19
- "index.d.ts"
17
+ "dist"
20
18
  ],
21
19
  "exports": {
22
20
  ".": {
23
- "types": "./dist/index.d.ts",
24
- "require": "./dist/index.js",
25
- "import": "./dist/index.mjs"
21
+ "types": "./dist/index.d.ts",
22
+ "require": "./dist/index.js",
23
+ "import": "./dist/index.mjs"
26
24
  },
27
25
  "./adapters": {
28
- "types": "./dist/adapters/index.d.ts",
29
- "require": "./dist/adapters/index.js",
30
- "import": "./dist/adapters/index.mjs"
26
+ "types": "./dist/adapters/index.d.ts",
27
+ "require": "./dist/adapters/index.js",
28
+ "import": "./dist/adapters/index.mjs"
31
29
  }
32
30
  },
33
31
  "scripts": {
package/index.d.ts DELETED
@@ -1,4 +0,0 @@
1
- import plugin from "./dist";
2
-
3
- export * from "./dist";
4
- export default plugin;
@@ -1,41 +0,0 @@
1
- import type { AxiosInstance, AxiosRequestConfig } from 'axios'
2
- import {Get, mergeUrlParam} from './utils'
3
-
4
- function axiosAdapter<T>(httpInstance: AxiosInstance) {
5
- type UrlKey = string & keyof T
6
- type MethodKey<U extends UrlKey> = string & keyof T[U]
7
-
8
- type SwaggerInterfaceSingle<U extends UrlKey, M extends MethodKey<U>> = T[U][M]
9
- type SwaggerField<U extends UrlKey, M extends MethodKey<U>> = keyof SwaggerInterfaceSingle<U, M>
10
- type SwaggerFieldType<U extends UrlKey, M extends MethodKey<U>, F extends SwaggerField<U, M>> = SwaggerInterfaceSingle<U, M>[F]
11
-
12
- type Param<U extends UrlKey, M extends MethodKey<U>> = SwaggerFieldType<U, M, 'param' & SwaggerField<U, M>>
13
- type Response<U extends UrlKey, M extends MethodKey<U>> = SwaggerFieldType<U, M, 'response' & SwaggerField<U, M>>
14
-
15
- async function request<U extends UrlKey, M extends MethodKey<U>>(
16
- url: U, method: M,
17
- param?: Get<Param<U, M>, M extends 'get' ? 'query' : 'body'>,
18
- config?: AxiosRequestConfig & {
19
- data?: Get<Param<U, M>, 'body'>
20
- params?: Get<Param<U, M>, 'query'>
21
- path?: Get<Param<U, M>, 'path'>
22
- },
23
- ) {
24
- if (config?.path)
25
- (url as string) = mergeUrlParam(url, config.path)
26
-
27
- const response = await httpInstance.request<Response<U, M>>({
28
- url,
29
- method,
30
- params: method === 'get' ? param : config?.params,
31
- data: method !== 'get' ? param : config?.data,
32
- ...config,
33
- })
34
- return response.data
35
- }
36
-
37
- return { request }
38
- }
39
-
40
-
41
- export { axiosAdapter }
@@ -1 +0,0 @@
1
- export * from './axios'
@@ -1,5 +0,0 @@
1
- export type Get<T, K> = T[K & keyof T]
2
-
3
- export function mergeUrlParam(url: string, paths: Record<string, any>) {
4
- return url.replace(/{(.*?)}/g, (_, key) => paths[key])
5
- }
package/src/generator.ts DELETED
@@ -1,176 +0,0 @@
1
- import { OpenAPIObject, RequestBodyObject, ResponseObject, ReferenceObject, OperationObject, ParameterObject, SchemaObject } from "openapi3-ts";
2
- import { getRefName, isTypeAny } from "./utils";
3
- import { GenerateDocOption } from "./types";
4
-
5
- export function generateDocs(input: OpenAPIObject, { docsName, baseUrl, formatSchema }: GenerateDocOption) {
6
- function getRefObject(ref: string) {
7
- return ref
8
- .split("/")
9
- .slice(1)
10
- .reduce((obj, item) => {
11
- return obj[item] || {};
12
- }, input);
13
- }
14
-
15
- const pathsTypeString = Object.entries(input.paths)
16
- .map(([endPoint, value]) => {
17
- const pathValue = value as OperationObject;
18
- const parametersExtended = pathValue.parameters;
19
- // 处理请求方法里面的类型
20
- const result = Object.entries(pathValue)
21
- .map(([method, options]: [string, OperationObject]) => {
22
- // 不是请求方法的属性都跳过
23
- if (!["get", "put", "post", "delete", "options", "head", "patch", "trace"].includes(method)) {
24
- return;
25
- }
26
- let allParameters = [...(parametersExtended || []), ...(options.parameters || [])].map((item) => {
27
- // 将 $ref 转换为正常的 ParameterObject 的对象
28
- if ("$ref" in item) {
29
- return getRefObject(item.$ref) as any as ParameterObject;
30
- } else {
31
- return item;
32
- }
33
- });
34
- const queryParameters = allParameters.filter((item) => item.in === "query");
35
- const pathParameters = allParameters.filter((item) => item.in === "path");
36
- const bodyParameters = allParameters.filter((item) => !item.in);
37
-
38
- // 将 $ref 转换为 requestBody 对象
39
- const requestBody = options.requestBody ? ("$ref" in options.requestBody ? (getRefObject(options.requestBody.$ref) as any as RequestBodyObject) : options.requestBody) : undefined;
40
-
41
- // 找到状态码为 200 或者 default 的 responses 体,并将 ReferenceObject 格式的转换为 ResponseObject;
42
- let responses = Object.entries(options.responses)
43
- .filter((items) => items[0] == "200" || items[0] == "default")
44
- .sort()?.[0]?.[1] as ResponseObject | ReferenceObject;
45
-
46
- if ("$ref" in responses) {
47
- responses = getRefObject(responses.$ref) as any as ResponseObject;
48
- }
49
-
50
- const queryString = queryParameters.length > 0 ? jsDoc({}, { key: "query", result: `{${queryParameters.map((item) => generatorParameterType(item, docsName)).join("")}\n}` }) : "";
51
- const pathString = pathParameters.length > 0 ? jsDoc({}, { key: "path", result: `{${pathParameters.map((item) => generatorParameterType(item, docsName)).join("")}\n}` }) : "";
52
- const bodyExtraString = bodyParameters.length > 0 ? jsDoc({}, { key: "body", result: `{${bodyParameters.map((item) => generatorParameterType(item, docsName)).join("")}\n}` }) : "";
53
- const bodyString = requestBody ? generatorRequestBodyType(requestBody, docsName) : "";
54
- const responseString = generatorResponseBodyType(responses, docsName);
55
-
56
- const paramString = `${queryString}${pathString}${bodyString || bodyExtraString}`;
57
- return jsDoc({}, { key: method, result: `{${paramString ? `\nparam:{${paramString}}` : ""}${responseString}}` });
58
- })
59
- .join("");
60
-
61
- return jsDoc({}, { key: `'${baseUrl}${endPoint}'`, result: `{${result}}` });
62
- })
63
- .join("");
64
- const typeString = input.components?.schemas
65
- ? Object.entries(input.components.schemas)
66
- .map(([name, schema]) => {
67
- if (typeof formatSchema == "function") {
68
- schema = formatSchema(schema);
69
- }
70
- if ("$ref" in schema) {
71
- schema = getRefObject(schema.$ref) as any as SchemaObject;
72
- }
73
- return generatorSchemaType(getRefName(`#/components/schemas/${name}`, docsName), schema, { isRoot: true, isExport: true, docsName });
74
- })
75
- .join("")
76
- : "";
77
- const apiString = `${typeString}\nexport interface Paths${getRefName(docsName)}{${pathsTypeString}}\n`;
78
- return apiString.replaceAll(/\n\n/g, "\n").replaceAll(/\n\n/g, "\n");
79
- }
80
-
81
- const TYPES = {
82
- integer: "number",
83
- number: "number",
84
- boolean: "boolean",
85
- object: "object",
86
- string: "string",
87
- array: "array"
88
- };
89
-
90
- interface GeneratorSchemaTypeOption {
91
- isRoot?: boolean;
92
- isRequired?: boolean;
93
- isExport?: boolean;
94
- docsName?: string;
95
- }
96
- export function generatorSchemaType(
97
- key: string,
98
- schema: SchemaObject | boolean | {} | undefined,
99
- { isRoot = false, isRequired, isExport = false, docsName = "" }: GeneratorSchemaTypeOption = {}
100
- ): string {
101
- if (isTypeAny(schema)) {
102
- return `\n${key}${isRequired === false ? "?" : ""}: any;\n`;
103
- }
104
-
105
- const { type, $ref, enum: Enum, items, properties, oneOf, additionalProperties, required, allOf } = schema as SchemaObject;
106
- let result = "";
107
- if ($ref) {
108
- // 引用
109
- result = getRefName($ref, docsName);
110
- } else if (Enum) {
111
- // 枚举
112
- result = `${Enum.map((t) => `"${t}"`).join(" | ")}`;
113
- } else if (items) {
114
- // 数组
115
- result = `${generatorSchemaType("", items, { docsName })}[]`;
116
- } else if (properties) {
117
- // 对象
118
- result += `{${Object.entries(properties)
119
- .map(([pName, _schema]) => generatorSchemaType(pName, _schema, { isRequired: !required || required.includes(pName) ? true : false, docsName }))
120
- .join("")}\n}`;
121
- } else if (oneOf) {
122
- // 联合类型
123
- result = `${oneOf.map((_schema) => `${generatorSchemaType("", _schema, { docsName })}`).join(" | ")}`;
124
- } else if (allOf) {
125
- // 交叉类型
126
- result = `${allOf.map((_schema) => generatorSchemaType("", _schema, { docsName })).join(" & ")}`;
127
- } else if (type === "object" && !result) {
128
- // additionalProperties
129
- if (additionalProperties) {
130
- result = `{${generatorSchemaType("[x: string | number]", additionalProperties, { docsName })}\n}`;
131
- } else {
132
- result = "{[x: string | number]: any}";
133
- }
134
- } else {
135
- // 基本类型,如果没有在基础类型里面默认为 string
136
- result = TYPES[type as keyof typeof TYPES] || "string";
137
- }
138
- if (!key) {
139
- return result;
140
- }
141
- return jsDoc(schema, { key, result, isExport, isRequired, isRoot });
142
- }
143
-
144
- export function generatorParameterType(schemas: ParameterObject, docsName?: string): string {
145
- const { name, required, schema, description } = schemas;
146
- const result = generatorSchemaType("", schema, { docsName });
147
- return jsDoc({ description, ...schema }, { key: name, result, isRequired: required });
148
- }
149
- export function generatorRequestBodyType(schemas: RequestBodyObject, docsName?: string): string {
150
- const { description, content, required } = schemas;
151
- const schema = content && Object.values(content)[0]?.["schema"];
152
- if (!schema) return "";
153
- const result = generatorSchemaType("", schema, { docsName });
154
- return jsDoc({ description }, { key: "body", result, isRequired: required });
155
- }
156
- export function generatorResponseBodyType(schemas: ResponseObject, docsName?: string): string {
157
- const { description, content } = schemas;
158
- const schema = content && Object.values(content)[0]?.["schema"];
159
- let result: string;
160
- if (!schema) {
161
- result = "any";
162
- } else {
163
- result = generatorSchemaType("", schema, { docsName });
164
- }
165
- return jsDoc({ description }, { key: "response", result });
166
- }
167
-
168
- export function jsDoc(
169
- { description, title, format, example, default: default1 }: any,
170
- { key, result, isRoot, isExport, isRequired }: { key: string; result: string; isRoot?: boolean; isExport?: boolean; isRequired?: boolean }
171
- ): string {
172
- const jsDoc = `\n/**\n${title ? ` * @title ${title}\n` : ""}${description ? ` * @description ${description}\n` : ""}${format ? ` * @format ${format}\n` : ""}${
173
- default1 ? ` * @default ${default1}\n` : ""
174
- }${example ? ` * @example ${example}\n` : ""} **/\n`;
175
- return `${jsDoc == "\n/**\n **/\n" ? "" : jsDoc}${isRoot ? `${isExport ? "export " : ""}type ${key} = ${result};\n` : `${key}${isRequired === false ? "?" : ""}: ${result};\n`}`;
176
- }
package/src/global.d.ts DELETED
@@ -1,7 +0,0 @@
1
- declare module "swagger2openapi" {
2
- import { OpenAPIObject } from "openapi3-ts";
3
- interface ConverObjCallbackData {
4
- openapi: OpenAPIObject;
5
- }
6
- function convertObj(schema: unknown, options: {}, callback: (err: Error, data: ConverObjCallbackData) => void): void;
7
- }
package/src/index.ts DELETED
@@ -1,57 +0,0 @@
1
- import { writeFileSync } from "fs";
2
- import { resolve } from "path";
3
- import { convertObj } from "swagger2openapi";
4
- import { OpenAPIObject } from "openapi3-ts";
5
- import { doc, format } from "prettier";
6
- import { UserOptions, ExportPlugin, SwaggerSource, SwaggerDoc } from "./types";
7
- import { resolveOptions, fetchUrl, getPrettierOptions } from "./utils";
8
- import { generateDocs } from "./generator";
9
-
10
- function convertObjPromise(docs: any): Promise<OpenAPIObject> {
11
- return new Promise((resolve, reject) => {
12
- convertObj(docs, { patch: true }, function (err, option) {
13
- // err && console.log("err", err);
14
- if (err || !option.openapi) return reject(err);
15
- resolve(option.openapi);
16
- });
17
- });
18
- }
19
-
20
- function swagger2TsPlugin(userOptions: UserOptions): ExportPlugin {
21
- const { swaggerUrl, output, prettierPath, formatDocs, formatSchema } = resolveOptions(userOptions);
22
- const prettierOptions = getPrettierOptions(prettierPath);
23
-
24
- async function loadSwaggerSource() {
25
- const sources = (await fetchUrl(`${swaggerUrl}/swagger-resources`)) as SwaggerSource[];
26
- let code = "";
27
- for (let i = 0; i < sources.length; i++) {
28
- const { url, name: docsName } = sources[i];
29
- try {
30
- const docs = (await fetchUrl(`${swaggerUrl}${url}`)) as SwaggerDoc | OpenAPIObject;
31
- let openapiDocs = formatDocs ? formatDocs(docs) : docs;
32
- if (!("openapi" in openapiDocs)) {
33
- if (docs.swagger) openapiDocs = await convertObjPromise(openapiDocs);
34
- else continue;
35
- }
36
- const apistrings = generateDocs(openapiDocs, { docsName, baseUrl: docs.basePath ?? "", formatSchema });
37
- code += apistrings;
38
- // console.log("apistrings", apistrings);
39
- } catch (error) {
40
- // console.log("vite-plugin-swagger2ts convert error", error);
41
- }
42
- }
43
- const outputFile = resolve(process.cwd(), output);
44
- writeFileSync(outputFile, format(code, prettierOptions));
45
- }
46
-
47
- loadSwaggerSource();
48
-
49
- return {
50
- name: "vite-plugin-swagger2ts",
51
- enforce: "pre",
52
- apply: "serve"
53
- };
54
- }
55
-
56
- export * from "./types";
57
- export default swagger2TsPlugin;
package/src/tmpl.ts DELETED
@@ -1,52 +0,0 @@
1
- interface SwaggerInterface1 {
2
- // SwaggerInterface start
3
- adsf: {
4
- get: {
5
- param: {
6
- path: { id: string };
7
- };
8
- response: any;
9
- };
10
- };
11
- adsf2: {
12
- get: {
13
- param: {
14
- path: { id: string };
15
- };
16
- response: any;
17
- };
18
- };
19
- }
20
- interface SwaggerInterface2 {
21
- // SwaggerInterface start
22
- ccccc1: {
23
- get: {
24
- param: {
25
- path: { id: string };
26
- };
27
- response: any;
28
- };
29
- };
30
- ccccc2: {
31
- get: {
32
- param: {
33
- path: { id: string };
34
- };
35
- response: any;
36
- };
37
- };
38
- }
39
-
40
- type SwaggerInterface = SwaggerInterface1 & SwaggerInterface2;
41
- type ReturnDataType = { code: number; data: any; message: string };
42
- type ReturnData<T extends ReturnDataType | any> = T extends ReturnDataType ? T["data"] : T;
43
-
44
- export type UrlKey = keyof SwaggerInterface;
45
- export type MethodKey<U extends UrlKey> = string & keyof SwaggerInterface[U];
46
-
47
- type SwaggerInterfaceSingle<U extends UrlKey, M extends MethodKey<U>> = SwaggerInterface[U][M];
48
- type SwaggerField<U extends UrlKey, M extends MethodKey<U>> = keyof SwaggerInterfaceSingle<U, M>;
49
- type SwaggerFieldType<U extends UrlKey, M extends MethodKey<U>, F extends SwaggerField<U, M>> = SwaggerInterfaceSingle<U, M>[F];
50
-
51
- export type Param<U extends UrlKey, M extends MethodKey<U>> = SwaggerFieldType<U, M, "param" & SwaggerField<U, M>>;
52
- export type Response<U extends UrlKey, M extends MethodKey<U>> = ReturnData<SwaggerFieldType<U, M, "response" & SwaggerField<U, M>>>;
package/src/types.ts DELETED
@@ -1,43 +0,0 @@
1
- import type { OpenAPIObject, SchemaObject } from "openapi3-ts";
2
- import type { Plugin } from "vite";
3
-
4
- type FormatSchema = (schema: SchemaObject) => SchemaObject;
5
-
6
- interface Options {
7
- swaggerUrl: string;
8
- output?: string;
9
- prettierPath?: string;
10
- formatDocs?: (docs: SwaggerDoc | OpenAPIObject) => typeof docs;
11
- formatSchema?: FormatSchema;
12
- }
13
-
14
- export type UserOptions = Options;
15
- export interface ResolvedOptions extends Options {
16
- output: string;
17
- }
18
-
19
- export type ExportPlugin = Required<Pick<Plugin, "name" | "enforce" | "apply">>;
20
-
21
- export interface SwaggerSource {
22
- name: string;
23
- url: string;
24
- swaggerVersion: string;
25
- location: string;
26
- }
27
-
28
- export interface SwaggerDoc {
29
- basePath: string;
30
- swagger: string;
31
- paths: { [key: string]: any };
32
- definitions: { [key: string]: any };
33
- host: string;
34
- info: any;
35
- tags: any[];
36
- securityDefinitions: any;
37
- }
38
-
39
- export interface GenerateDocOption {
40
- docsName: string;
41
- baseUrl: string;
42
- formatSchema?: FormatSchema;
43
- }
package/src/utils.ts DELETED
@@ -1,83 +0,0 @@
1
- import { existsSync, readFileSync } from "fs";
2
- import { resolve } from "path";
3
- import { UserOptions, ResolvedOptions } from "./types";
4
- import { OpenAPIObject, SchemaObject } from "openapi3-ts";
5
- import fetch from "cross-fetch";
6
-
7
- export function resolveOptions(userOptions: UserOptions): ResolvedOptions {
8
- const { output } = userOptions;
9
-
10
- const root = process.cwd();
11
- const outputFile = output ? (output?.endsWith(".ts") ? output : output + ".ts") : "./src/swagger.ts";
12
-
13
- return Object.assign({ output: resolve(root, outputFile) }, userOptions);
14
- }
15
-
16
- export async function fetchUrl(url: string) {
17
- return await fetch(url).then((res) => res.json());
18
- }
19
-
20
- export function getRef(ref: string, apiDocs: OpenAPIObject) {
21
- const paths = ref.split("/").slice(1);
22
- return paths.reduce((obj: any, key) => {
23
- return obj[key];
24
- }, apiDocs) as SchemaObject;
25
- }
26
-
27
- export function isTypeAny(type: true | undefined | {} | SchemaObject) {
28
- if (type === true) {
29
- return true;
30
- }
31
-
32
- if (typeof type === "object" && Object.keys(type).length <= 0) {
33
- return true;
34
- }
35
-
36
- if (!type) {
37
- return true;
38
- }
39
-
40
- return false;
41
- }
42
-
43
- export function toPascalCase(str: string): string {
44
- return `${str.substring(0, 1).toUpperCase()}${str.substring(1)}`;
45
- }
46
- function replaceWithUpper(str: string, sp: string) {
47
- let pointArray = str.split(sp);
48
- pointArray = pointArray.map((point) => toPascalCase(point));
49
-
50
- return pointArray.join("");
51
- }
52
- function getSchemaName(name: string): string {
53
- const removePound = replaceWithUpper(name, "#");
54
- const removeDot = replaceWithUpper(removePound, ".");
55
- const removeBackTick = replaceWithUpper(removeDot, "`");
56
- const removeFirstBracket = replaceWithUpper(removeBackTick, "[");
57
- const removeLastBracket = replaceWithUpper(removeFirstBracket, "]");
58
- const removeDash = replaceWithUpper(removeLastBracket, "-");
59
- const removeSlash = replaceWithUpper(removeDash, "/");
60
- return removeSlash;
61
- }
62
- export function getRefName($ref: string, prefix: string = ""): string {
63
- return getSchemaName(prefix) + getSchemaName($ref || "");
64
- }
65
-
66
- export function getPrettierOptions(prettierPath?: string) {
67
- let prettierOptions: any = {};
68
- if (prettierPath && existsSync(prettierPath)) {
69
- prettierOptions = JSON.parse(readFileSync(prettierPath).toString());
70
- } else {
71
- if (existsSync(".prettierrc")) {
72
- prettierOptions = JSON.parse(readFileSync(".prettierrc").toString());
73
- } else if (existsSync("prettier.json")) {
74
- prettierOptions = JSON.parse(readFileSync("prettier.json").toString());
75
- }
76
- }
77
-
78
- if (!prettierOptions.parser) {
79
- prettierOptions.parser = "typescript";
80
- }
81
-
82
- return prettierOptions;
83
- }