wormajs 0.0.2-beta.3 → 0.2.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/dist/constant.js +7 -10
- package/dist/core/parser/openApiParser/helper.js +91 -69
- package/dist/helper/config/GeneratorHelper.js +20 -18
- package/dist/helper/config/zType.js +2 -2
- package/dist/helper/progress.js +2 -2
- package/dist/plugins/index.js +6 -2
- package/dist/plugins/presets/payloadModifier/hepler.js +29 -33
- package/dist/plugins/presets/payloadModifier/index.js +8 -8
- package/dist/plugins/presets/platform/fastapi.js +22 -0
- package/dist/plugins/presets/platform/index.js +15 -0
- package/dist/plugins/presets/platform/knife4j.js +24 -0
- package/dist/plugins/presets/platform/shared.js +45 -0
- package/dist/plugins/presets/platform/swagger.js +32 -0
- package/dist/plugins/presets/platform/yapi.js +75 -0
- package/dist/plugins/presets/rename.js +154 -21
- package/dist/plugins/presets/tagModifier.js +6 -2
- package/dist/plugins/presets/utils.js +11 -10
- package/dist/template/index.js +0 -34
- package/dist/template/presets/alova/partials/dts-extra-config.handlebars +3 -3
- package/dist/template/presets/alova/partials/dts-fn-declare.handlebars +1 -1
- package/dist/template/presets/alova/typescript/services/{tag}.ts.handlebars +5 -5
- package/dist/template/presets/axios/partials/dts-types.handlebars +4 -4
- package/dist/template/presets/axios/typescript/services/{tag}.ts.handlebars +4 -4
- package/dist/template/presets/config/common/worma.config.js.handlebars +1 -1
- package/dist/template/presets/config/module/worma.config.js.handlebars +1 -1
- package/dist/template/presets/config/partials/generator-content.handlebars +45 -45
- package/dist/template/presets/config/typescript/worma.config.ts.handlebars +1 -1
- package/dist/template/presets/fetch/partials/dts-types.handlebars +4 -4
- package/dist/template/presets/fetch/typescript/services/{tag}.ts.handlebars +4 -4
- package/dist/template/presets/ky/partials/dts-types.handlebars +4 -4
- package/dist/template/presets/ky/typescript/services/{tag}.ts.handlebars +4 -4
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/template.js +23 -0
- package/package.json +1 -1
- package/typings/index.d.ts +9 -5
- package/typings/plugins.d.ts +134 -48
- package/dist/plugins/presets/platform.js +0 -73
package/dist/constant.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
// 枚举常量定义 — 统一管理项目中所有硬编码的字符串/数字常量
|
|
4
4
|
// ============================================================
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.FRAMEWORK_NAMES = exports.MODULE_TYPE_TO_KIND = exports.MODULE_TYPE_DIRS = exports.ModuleTypeDir = exports.PresetTemplateName = exports.TemplateSkipDir = exports.TemplatePlaceholder = exports.PluginName = exports.
|
|
6
|
+
exports.FRAMEWORK_NAMES = exports.MODULE_TYPE_TO_KIND = exports.MODULE_TYPE_DIRS = exports.ModuleTypeDir = exports.PresetTemplateName = exports.TemplateSkipDir = exports.TemplatePlaceholder = exports.PluginName = exports.FilterScope = exports.RenameScope = exports.ParameterIn = exports.TEMPLATE_EXTENSIONS = exports.FileExtension = exports.FrameworkName = exports.ModuleKind = exports.PlatformTypeEnum = exports.ConfigTypeEnum = exports.TemplateTypeEnum = void 0;
|
|
7
7
|
exports.getTypeFileExtension = getTypeFileExtension;
|
|
8
8
|
/** 模板代码生成类型 */
|
|
9
9
|
var TemplateTypeEnum;
|
|
@@ -26,6 +26,7 @@ var PlatformTypeEnum;
|
|
|
26
26
|
(function (PlatformTypeEnum) {
|
|
27
27
|
PlatformTypeEnum["SWAGGER"] = "swagger";
|
|
28
28
|
PlatformTypeEnum["KNIFE4J"] = "knife4j";
|
|
29
|
+
PlatformTypeEnum["FASTAPI"] = "fastapi";
|
|
29
30
|
PlatformTypeEnum["YAPI"] = "yapi";
|
|
30
31
|
})(PlatformTypeEnum || (exports.PlatformTypeEnum = PlatformTypeEnum = {}));
|
|
31
32
|
/** 模块体系类型 */
|
|
@@ -77,6 +78,7 @@ var RenameScope;
|
|
|
77
78
|
RenameScope["DATA"] = "data";
|
|
78
79
|
RenameScope["RESPONSE"] = "response";
|
|
79
80
|
RenameScope["REF_NAME"] = "refName";
|
|
81
|
+
RenameScope["NAME"] = "name";
|
|
80
82
|
})(RenameScope || (exports.RenameScope = RenameScope = {}));
|
|
81
83
|
/** 过滤 scope 类型 */
|
|
82
84
|
var FilterScope;
|
|
@@ -84,14 +86,6 @@ var FilterScope;
|
|
|
84
86
|
FilterScope["URL"] = "url";
|
|
85
87
|
FilterScope["TAG"] = "tag";
|
|
86
88
|
})(FilterScope || (exports.FilterScope = FilterScope = {}));
|
|
87
|
-
/** 参数修改 scope 类型 */
|
|
88
|
-
var ModifierScope;
|
|
89
|
-
(function (ModifierScope) {
|
|
90
|
-
ModifierScope["PARAMS"] = "params";
|
|
91
|
-
ModifierScope["PATH_PARAMS"] = "pathParams";
|
|
92
|
-
ModifierScope["DATA"] = "data";
|
|
93
|
-
ModifierScope["RESPONSE"] = "response";
|
|
94
|
-
})(ModifierScope || (exports.ModifierScope = ModifierScope = {}));
|
|
95
89
|
/** 内建插件名称 */
|
|
96
90
|
var PluginName;
|
|
97
91
|
(function (PluginName) {
|
|
@@ -102,7 +96,10 @@ var PluginName;
|
|
|
102
96
|
PluginName["IMPORT_TYPE"] = "importType";
|
|
103
97
|
PluginName["AI_DOC"] = "aiDoc";
|
|
104
98
|
PluginName["APIFOX"] = "apifox";
|
|
105
|
-
PluginName["
|
|
99
|
+
PluginName["SWAGGER"] = "swagger";
|
|
100
|
+
PluginName["KNIFE4J"] = "knife4j";
|
|
101
|
+
PluginName["FASTAPI"] = "fastapi";
|
|
102
|
+
PluginName["YAPI"] = "yapi";
|
|
106
103
|
PluginName["TEMPLATE_ALOVA"] = "templateAlova";
|
|
107
104
|
PluginName["TEMPLATE_ALOVA_GLOBALS"] = "templateAlovaGlobals";
|
|
108
105
|
PluginName["TEMPLATE_AXIOS"] = "templateAxios";
|
|
@@ -13,7 +13,6 @@ const swagger2openapi_1 = __importDefault(require("swagger2openapi"));
|
|
|
13
13
|
const poolManager_1 = require("../../../core/workerPool/poolManager");
|
|
14
14
|
const helper_1 = require("../../../helper");
|
|
15
15
|
const utils_1 = require("../../../utils");
|
|
16
|
-
const supportedExtname = ['json', 'yaml'];
|
|
17
16
|
function isSwagger2(data) {
|
|
18
17
|
return !!data?.swagger;
|
|
19
18
|
}
|
|
@@ -61,56 +60,72 @@ function convertSwagger2Async(data) {
|
|
|
61
60
|
});
|
|
62
61
|
});
|
|
63
62
|
}
|
|
64
|
-
//
|
|
65
|
-
async function
|
|
66
|
-
const [, extname] = /\.([^.]+)$/.exec(url) ?? [];
|
|
67
|
-
if (!supportedExtname.includes(extname)) {
|
|
68
|
-
throw helper_1.logger.throwError(`Unsupported file type: ${extname}`, {
|
|
69
|
-
url,
|
|
70
|
-
projectPath,
|
|
71
|
-
});
|
|
72
|
-
}
|
|
63
|
+
// Read local openapi spec file as raw text
|
|
64
|
+
async function fetchRawLocalFile(url, projectPath = process.cwd()) {
|
|
73
65
|
const filePath = node_path_1.default.resolve(projectPath, url);
|
|
74
|
-
if (extname === 'yaml') {
|
|
75
|
-
return js_yaml_1.default.load(await promises_1.default.readFile(filePath, 'utf-8'));
|
|
76
|
-
}
|
|
77
|
-
// M6-C3: prefer async read, fallback to require() for environments where
|
|
78
|
-
// fs is mocked (e.g. memfs in tests) but the real file exists on disk
|
|
79
66
|
try {
|
|
80
|
-
return
|
|
67
|
+
return await promises_1.default.readFile(filePath, 'utf-8');
|
|
81
68
|
}
|
|
82
69
|
catch {
|
|
83
|
-
//
|
|
70
|
+
// M6-C3: fallback to require() for environments where fs is mocked
|
|
71
|
+
// (e.g. memfs in tests) but the real file exists on disk. Limited to JSON.
|
|
84
72
|
// eslint-disable-next-line ts/no-require-imports
|
|
85
|
-
return require(filePath);
|
|
73
|
+
return JSON.stringify(require(filePath), null, 2);
|
|
86
74
|
}
|
|
87
75
|
}
|
|
88
|
-
//
|
|
89
|
-
async function
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
76
|
+
// Fetch remote openapi spec as raw text
|
|
77
|
+
async function fetchRawRemoteFile(url, fetchOptions) {
|
|
78
|
+
return (await (0, utils_1.fetchData)(url, fetchOptions)) ?? '';
|
|
79
|
+
}
|
|
80
|
+
const isRemoteUrl = (u) => /^https?:\/\//.test(u);
|
|
81
|
+
/**
|
|
82
|
+
* Fetch the raw spec text (JSON/YAML) from the first URL that succeeds.
|
|
83
|
+
* Returns the raw text together with the resolved URL; throws if all URLs fail.
|
|
84
|
+
*/
|
|
85
|
+
async function fetchRawText(urls, options) {
|
|
86
|
+
if (urls.length === 0) {
|
|
87
|
+
throw helper_1.logger.throwError('No URLs provided to fetch OpenAPI document');
|
|
95
88
|
}
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
89
|
+
const { projectPath, fetchOptions } = options;
|
|
90
|
+
// All URLs race in parallel: local files are fast, remote ones use network.
|
|
91
|
+
// Each task fetches the raw text AND validates that it is actually an OpenAPI/Swagger
|
|
92
|
+
// document before resolving. Invalid candidates (e.g. an HTML error page returned by
|
|
93
|
+
// a fallback URL) reject, so that Promise.any falls through to the next URL
|
|
94
|
+
// instead of resolving with garbage text.
|
|
95
|
+
const tasks = urls.map((u) => {
|
|
96
|
+
return (async () => {
|
|
97
|
+
const text = isRemoteUrl(u)
|
|
98
|
+
? await fetchRawRemoteFile(u, fetchOptions)
|
|
99
|
+
: await fetchRawLocalFile(u, projectPath);
|
|
100
|
+
// Quick parse + validity check (full parse + Swagger2→OpenAPI3 conversion
|
|
101
|
+
// happens later in parseSpec, after beforeSpecParse may rewrite the text).
|
|
102
|
+
let probe;
|
|
103
|
+
try {
|
|
104
|
+
probe = JSON.parse(text);
|
|
105
|
+
}
|
|
106
|
+
catch (jsonError) {
|
|
107
|
+
try {
|
|
108
|
+
probe = js_yaml_1.default.load(text);
|
|
109
|
+
}
|
|
110
|
+
catch (yamlError) {
|
|
111
|
+
throw new Error(`${u}: ${(jsonError instanceof Error ? jsonError.message : String(jsonError))} (YAML: ${yamlError instanceof Error ? yamlError.message : String(yamlError)})`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (!isValidOpenApiData(probe)) {
|
|
115
|
+
throw new Error(`${u} did not yield a valid OpenAPI/Swagger document`);
|
|
116
|
+
}
|
|
117
|
+
return { text, url: u };
|
|
118
|
+
})();
|
|
119
|
+
});
|
|
120
|
+
try {
|
|
121
|
+
return await Promise.any(tasks);
|
|
108
122
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
123
|
+
catch (err) {
|
|
124
|
+
const errors = (err instanceof AggregateError)
|
|
125
|
+
? err.errors.map((e) => e.message)
|
|
126
|
+
: [err.message];
|
|
127
|
+
throw helper_1.logger.throwError(`Unable to retrieve valid OpenAPI document from any URL:\n${errors.join('\n')}`);
|
|
112
128
|
}
|
|
113
|
-
return data;
|
|
114
129
|
}
|
|
115
130
|
// Validate OpenAPI data
|
|
116
131
|
function isValidOpenApiData(data) {
|
|
@@ -124,49 +139,56 @@ function isValidOpenApiData(data) {
|
|
|
124
139
|
// Check if it contains required OpenAPI/Swagger structure
|
|
125
140
|
return !!(data.openapi || data.swagger || data.info || data.paths);
|
|
126
141
|
}
|
|
127
|
-
const isRemoteUrl = (u) => /^https?:\/\//.test(u);
|
|
128
142
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
143
|
+
* Parse a raw spec string (JSON or YAML) into an OpenAPIDocument.
|
|
144
|
+
* Performs format auto-detection, validity checks, and Swagger2→OpenAPI3 conversion.
|
|
131
145
|
*/
|
|
132
|
-
async function
|
|
133
|
-
|
|
134
|
-
|
|
146
|
+
async function parseSpec(text, url) {
|
|
147
|
+
let data;
|
|
148
|
+
try {
|
|
149
|
+
// Try to parse as JSON first
|
|
150
|
+
data = JSON.parse(text);
|
|
135
151
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
152
|
+
catch (jsonError) {
|
|
153
|
+
try {
|
|
154
|
+
// Fall back to YAML (also covers JSON, since JSON is a subset of YAML)
|
|
155
|
+
data = js_yaml_1.default.load(text);
|
|
156
|
+
}
|
|
157
|
+
catch (yamlError) {
|
|
158
|
+
throw helper_1.logger.throwError(`Only JSON and YAML formats are supported. Parsing failed:
|
|
159
|
+
${jsonError instanceof Error ? jsonError.message : String(jsonError)}
|
|
160
|
+
${yamlError instanceof Error ? yamlError.message : String(yamlError)}`, {
|
|
161
|
+
url,
|
|
142
162
|
});
|
|
143
163
|
}
|
|
144
|
-
return parseLocalFile(u, projectPath).then(data => ({ data, url: u }));
|
|
145
|
-
});
|
|
146
|
-
try {
|
|
147
|
-
return await Promise.any(tasks);
|
|
148
164
|
}
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
165
|
+
// Validate if the data is valid (prevent server from returning error responses)
|
|
166
|
+
if (!isValidOpenApiData(data)) {
|
|
167
|
+
throw new Error(`Data retrieved from URL ${url} is not a valid OpenAPI document`);
|
|
168
|
+
}
|
|
169
|
+
// If it is a swagger2 file — convert via worker to avoid main-thread blocking
|
|
170
|
+
if (isSwagger2(data)) {
|
|
171
|
+
data = await convertSwagger2Async(data);
|
|
154
172
|
}
|
|
173
|
+
return data;
|
|
155
174
|
}
|
|
156
175
|
/**
|
|
157
176
|
* Parse OpenAPI document and return the resolved URL alongside the data.
|
|
158
177
|
* Use this when you need to know which URL actually provided the document.
|
|
178
|
+
*
|
|
179
|
+
* If `beforeSpecParse` is provided, it is invoked with the raw spec text once
|
|
180
|
+
* it has been fetched (but before parsing), and its returned string replaces
|
|
181
|
+
* the text that will be parsed.
|
|
159
182
|
*/
|
|
160
183
|
async function getOpenApiDataWithUrl(url, options) {
|
|
161
|
-
const { projectPath, fetchOptions } = options ?? {};
|
|
184
|
+
const { projectPath, fetchOptions, beforeSpecParse } = options ?? {};
|
|
162
185
|
// Normalize to array — single string or array both handled uniformly
|
|
163
186
|
const urls = Array.isArray(url) ? url : [url];
|
|
164
|
-
const {
|
|
165
|
-
|
|
166
|
-
//
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
187
|
+
const { text, url: resolvedUrl } = await fetchRawText(urls, { projectPath, fetchOptions });
|
|
188
|
+
// Allow the caller (e.g. a `beforeSpecParse` plugin hook) to transform the
|
|
189
|
+
// raw spec text before it is parsed into an OpenAPIDocument.
|
|
190
|
+
const finalText = (beforeSpecParse ? await beforeSpecParse(text) : text) ?? text;
|
|
191
|
+
const result = await parseSpec(finalText, resolvedUrl);
|
|
170
192
|
if (!result) {
|
|
171
193
|
throw helper_1.logger.throwError(`Cannot read file from ${urls.join(', ')}`, {
|
|
172
194
|
projectPath,
|
|
@@ -128,10 +128,11 @@ class GeneratorHelper {
|
|
|
128
128
|
fetchOptions: config.fetchOptions,
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
-
static async openApiDataWithUrl(config, projectPath) {
|
|
131
|
+
static async openApiDataWithUrl(config, projectPath, opts) {
|
|
132
132
|
return (0, helper_1.getOpenApiDataWithUrl)(config.input, {
|
|
133
133
|
projectPath,
|
|
134
134
|
fetchOptions: config.fetchOptions,
|
|
135
|
+
beforeSpecParse: opts?.beforeSpecParse,
|
|
135
136
|
});
|
|
136
137
|
}
|
|
137
138
|
static async generate(config, { projectPath, force, tracker }) {
|
|
@@ -152,16 +153,17 @@ class GeneratorHelper {
|
|
|
152
153
|
});
|
|
153
154
|
reportCore(5, 'starting');
|
|
154
155
|
const frozenConfig = Object.freeze(config);
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
helper_2.logger.debug('Running beforeOpenapiParse hook');
|
|
158
|
-
await pluginDriver.hookParallelEach('beforeOpenapiParse', () => ({
|
|
159
|
-
config: frozenConfig,
|
|
160
|
-
projectPath,
|
|
161
|
-
}));
|
|
156
|
+
reportCore(10, 'beforeSpecParse');
|
|
157
|
+
helper_2.logger.debug('Fetching and parsing OpenAPI document', { input: config.input });
|
|
162
158
|
reportCore(20, 'parsing openapi document');
|
|
163
|
-
|
|
164
|
-
|
|
159
|
+
const openApiResult = await this.openApiDataWithUrl(config, projectPath, {
|
|
160
|
+
// Plugin: beforeSpecParse — receives the raw spec string, may return a modified string
|
|
161
|
+
beforeSpecParse: (spec) => pluginDriver.hookPipe('beforeSpecParse', spec, (_p, current, _ctx) => ({
|
|
162
|
+
config: frozenConfig,
|
|
163
|
+
spec: current,
|
|
164
|
+
projectPath,
|
|
165
|
+
})),
|
|
166
|
+
});
|
|
165
167
|
let document = openApiResult.data;
|
|
166
168
|
const resolvedInput = openApiResult.resolvedUrl;
|
|
167
169
|
if (!document) {
|
|
@@ -174,10 +176,10 @@ class GeneratorHelper {
|
|
|
174
176
|
version: document?.info?.version,
|
|
175
177
|
paths: Object.keys(document?.paths || {}).length,
|
|
176
178
|
});
|
|
177
|
-
reportCore(35, '
|
|
178
|
-
// Plugin: handle after parse openapi (
|
|
179
|
-
helper_2.logger.debug('Running
|
|
180
|
-
const
|
|
179
|
+
reportCore(35, 'specParsed');
|
|
180
|
+
// Plugin: handle after parse openapi (specParsed)
|
|
181
|
+
helper_2.logger.debug('Running specParsed hook', { pluginCount });
|
|
182
|
+
const specParsed = await pluginDriver.hookSeqEach('specParsed', (_p, prevResult, _ctx) => {
|
|
181
183
|
if (prevResult) {
|
|
182
184
|
document = prevResult;
|
|
183
185
|
}
|
|
@@ -187,11 +189,11 @@ class GeneratorHelper {
|
|
|
187
189
|
projectPath,
|
|
188
190
|
};
|
|
189
191
|
});
|
|
190
|
-
if (
|
|
191
|
-
document =
|
|
192
|
-
helper_2.logger.debug('
|
|
192
|
+
if (specParsed) {
|
|
193
|
+
document = specParsed;
|
|
194
|
+
helper_2.logger.debug('specParsed hook modified document');
|
|
193
195
|
}
|
|
194
|
-
reportCore(45, '
|
|
196
|
+
reportCore(45, 'specParsed');
|
|
195
197
|
const output = node_path_1.default.resolve(projectPath, config.output);
|
|
196
198
|
const templateType = await GeneratorHelper.getTemplateType(config, projectPath);
|
|
197
199
|
helper_2.logger.debug('Resolved output and template type', { output, templateType });
|
|
@@ -26,8 +26,8 @@ exports.zFetchOptions = v3_1.z.record(v3_1.z.string(), v3_1.z.any());
|
|
|
26
26
|
exports.zApiPlugin = v3_1.z.object({
|
|
27
27
|
name: v3_1.z.string().optional(),
|
|
28
28
|
config: v3_1.z.function().optional(),
|
|
29
|
-
|
|
30
|
-
|
|
29
|
+
beforeSpecParse: v3_1.z.function().optional(),
|
|
30
|
+
specParsed: v3_1.z.function().optional(),
|
|
31
31
|
beforeCodeGenerate: v3_1.z.function().optional(),
|
|
32
32
|
beforeFileWrite: v3_1.z.function().optional(),
|
|
33
33
|
codeGenerated: v3_1.z.function().optional(),
|
package/dist/helper/progress.js
CHANGED
|
@@ -8,9 +8,9 @@ exports.CORE_PROGRESS_SOURCE = 'core';
|
|
|
8
8
|
*/
|
|
9
9
|
exports.GeneratorStage = {
|
|
10
10
|
INIT: 'init',
|
|
11
|
-
|
|
11
|
+
BEFORE_SPEC_PARSE: 'beforeSpecParse',
|
|
12
12
|
PARSE_OPENAPI: 'parseOpenapi',
|
|
13
|
-
|
|
13
|
+
SPEC_PARSED: 'specParsed',
|
|
14
14
|
TEMPLATE_LOADED: 'templateLoaded',
|
|
15
15
|
TEMPLATE_DATA_PARSED: 'templateDataParsed',
|
|
16
16
|
BEFORE_CODE_GENERATE: 'beforeCodeGenerate',
|
package/dist/plugins/index.js
CHANGED
|
@@ -14,14 +14,18 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
exports.ky = exports.config = exports.axios = exports.alovaGlobals = exports.alova = void 0;
|
|
17
|
+
exports.ky = exports.config = exports.axios = exports.alovaGlobals = exports.alova = exports.yapi = exports.swagger = exports.knife4j = exports.fastapi = void 0;
|
|
18
18
|
__exportStar(require("./createPlugin"), exports);
|
|
19
19
|
__exportStar(require("./presets/aiDoc"), exports);
|
|
20
20
|
__exportStar(require("./presets/apifox"), exports);
|
|
21
21
|
__exportStar(require("./presets/filterApi"), exports);
|
|
22
22
|
__exportStar(require("./presets/importType"), exports);
|
|
23
23
|
__exportStar(require("./presets/payloadModifier"), exports);
|
|
24
|
-
|
|
24
|
+
var platform_1 = require("./presets/platform");
|
|
25
|
+
Object.defineProperty(exports, "fastapi", { enumerable: true, get: function () { return platform_1.fastapi; } });
|
|
26
|
+
Object.defineProperty(exports, "knife4j", { enumerable: true, get: function () { return platform_1.knife4j; } });
|
|
27
|
+
Object.defineProperty(exports, "swagger", { enumerable: true, get: function () { return platform_1.swagger; } });
|
|
28
|
+
Object.defineProperty(exports, "yapi", { enumerable: true, get: function () { return platform_1.yapi; } });
|
|
25
29
|
__exportStar(require("./presets/rename"), exports);
|
|
26
30
|
__exportStar(require("./presets/tagModifier"), exports);
|
|
27
31
|
// Template preset plugins
|
|
@@ -15,11 +15,13 @@ function toSchemaObject(base, s) {
|
|
|
15
15
|
delete schema.required;
|
|
16
16
|
return schema;
|
|
17
17
|
};
|
|
18
|
-
//
|
|
18
|
+
// Native array type (elements are Schema)
|
|
19
19
|
if (Array.isArray(s)) {
|
|
20
|
-
const
|
|
20
|
+
const arr = s;
|
|
21
21
|
cleanType(result);
|
|
22
|
-
result.
|
|
22
|
+
result.type = 'array';
|
|
23
|
+
const items = arr.map(item => toSchemaObject({}, item));
|
|
24
|
+
result.items = (items.length === 1 ? items[0] : items);
|
|
23
25
|
return result;
|
|
24
26
|
}
|
|
25
27
|
// Primitive types and no-op primitives
|
|
@@ -33,18 +35,21 @@ function toSchemaObject(base, s) {
|
|
|
33
35
|
const baseOneOf = base.oneOf || [];
|
|
34
36
|
cleanType(result);
|
|
35
37
|
result.oneOf = spec.oneOf.map((item, idx) => toSchemaObject(baseOneOf[idx] || {}, item));
|
|
38
|
+
return result;
|
|
36
39
|
}
|
|
37
40
|
if (s.anyOf) {
|
|
38
41
|
const spec = s;
|
|
39
42
|
const baseAnyOf = base.anyOf || [];
|
|
40
43
|
cleanType(result);
|
|
41
44
|
result.anyOf = spec.anyOf.map((item, idx) => toSchemaObject(baseAnyOf[idx] || {}, item));
|
|
45
|
+
return result;
|
|
42
46
|
}
|
|
43
47
|
if (s.allOf) {
|
|
44
48
|
const spec = s;
|
|
45
49
|
const baseAllOf = base.allOf || [];
|
|
46
50
|
cleanType(result);
|
|
47
51
|
result.allOf = spec.allOf.map((item, idx) => toSchemaObject(baseAllOf[idx] || {}, item));
|
|
52
|
+
return result;
|
|
48
53
|
}
|
|
49
54
|
// Enum: set enum and optional type
|
|
50
55
|
if (s.enum) {
|
|
@@ -53,30 +58,15 @@ function toSchemaObject(base, s) {
|
|
|
53
58
|
if (spec.type) {
|
|
54
59
|
result.type = spec.type;
|
|
55
60
|
}
|
|
56
|
-
}
|
|
57
|
-
// Array: set/merge items
|
|
58
|
-
if (s.type === 'array') {
|
|
59
|
-
const spec = s;
|
|
60
|
-
result.type = 'array';
|
|
61
|
-
const baseItems = result.items;
|
|
62
|
-
if (Array.isArray(spec.items)) {
|
|
63
|
-
// Tuple items: replace entire items with tuple
|
|
64
|
-
const items = spec.items.map(item => toSchemaObject({}, item));
|
|
65
|
-
result.items = items;
|
|
66
|
-
}
|
|
67
|
-
else {
|
|
68
|
-
// Single items: merge into existing items schema
|
|
69
|
-
const patchItem = toSchemaObject(typeof baseItems === 'object' ? baseItems : {}, spec.items);
|
|
70
|
-
result.items = patchItem;
|
|
71
|
-
}
|
|
72
61
|
return result;
|
|
73
62
|
}
|
|
74
|
-
// Object (reference-like map):
|
|
63
|
+
// Object (reference-like map): replace properties and required with handler's spec
|
|
64
|
+
// (the SchemaReference returned by the handler fully replaces this field, only keeping scalar fields like description from base)
|
|
75
65
|
const ref = s;
|
|
76
66
|
if (ref && typeof ref === 'object') {
|
|
77
67
|
result.type = 'object';
|
|
78
|
-
const properties = {
|
|
79
|
-
const requiredSet = new Set(
|
|
68
|
+
const properties = {};
|
|
69
|
+
const requiredSet = new Set();
|
|
80
70
|
for (const key in ref) {
|
|
81
71
|
const val = ref[key];
|
|
82
72
|
if (!val) {
|
|
@@ -137,16 +127,16 @@ function toSchemaSpec(obj) {
|
|
|
137
127
|
const type = typeof obj.type === 'string' ? obj.type : undefined;
|
|
138
128
|
return { enum: obj.enum, type };
|
|
139
129
|
}
|
|
140
|
-
// Array
|
|
130
|
+
// Array -> native array
|
|
141
131
|
if (obj.type === 'array' || obj.items) {
|
|
142
132
|
const items = obj.items;
|
|
143
133
|
if (Array.isArray(items)) {
|
|
144
|
-
return
|
|
134
|
+
return items.map((it) => toSchemaSpec(it));
|
|
145
135
|
}
|
|
146
136
|
if (items) {
|
|
147
|
-
return
|
|
137
|
+
return [toSchemaSpec(items)];
|
|
148
138
|
}
|
|
149
|
-
return
|
|
139
|
+
return ['unknown'];
|
|
150
140
|
}
|
|
151
141
|
// Object
|
|
152
142
|
if (obj.type === 'object' || obj.properties) {
|
|
@@ -160,7 +150,7 @@ function toSchemaSpec(obj) {
|
|
|
160
150
|
}
|
|
161
151
|
return result;
|
|
162
152
|
}
|
|
163
|
-
// type union as array
|
|
153
|
+
// type union as array -> oneOf
|
|
164
154
|
if (Array.isArray(obj.type)) {
|
|
165
155
|
const typeArr = obj.type;
|
|
166
156
|
const mapped = typeArr.map(schemaTypeToPrimitiveType);
|
|
@@ -175,21 +165,27 @@ function applyModifierSchema(schema, config, { required }) {
|
|
|
175
165
|
}
|
|
176
166
|
const cloned = { ...schema };
|
|
177
167
|
const currentSpec = toSchemaSpec(cloned);
|
|
178
|
-
|
|
168
|
+
// When the field is itself optional and is a primitive, wrap it as { required, type } before passing to handler
|
|
169
|
+
const handlerInput = (required === false && typeof currentSpec === 'string')
|
|
170
|
+
? { required: false, type: currentSpec }
|
|
171
|
+
: currentSpec;
|
|
172
|
+
const ret = config.handler(handlerInput);
|
|
179
173
|
if (!ret) {
|
|
180
174
|
return {
|
|
181
175
|
required,
|
|
182
|
-
|
|
176
|
+
schema: null,
|
|
183
177
|
};
|
|
184
178
|
}
|
|
185
|
-
|
|
179
|
+
// A returned { required, type } means changing requiredness (driven by the `type` field)
|
|
180
|
+
if (typeof ret === 'object' && !Array.isArray(ret) && 'required' in ret && 'type' in ret) {
|
|
181
|
+
const opt = ret;
|
|
186
182
|
return {
|
|
187
|
-
required: !!(
|
|
188
|
-
|
|
183
|
+
required: !!(opt.required ?? required),
|
|
184
|
+
schema: toSchemaObject(cloned, opt.type),
|
|
189
185
|
};
|
|
190
186
|
}
|
|
191
187
|
return {
|
|
192
188
|
required,
|
|
193
|
-
|
|
189
|
+
schema: toSchemaObject(cloned, ret),
|
|
194
190
|
};
|
|
195
191
|
}
|
|
@@ -28,13 +28,13 @@ function modifySchemaProperties(schema, config) {
|
|
|
28
28
|
if (!(0, utils_1.isMatch)(key, config.match)) {
|
|
29
29
|
continue;
|
|
30
30
|
}
|
|
31
|
-
const { required: requiredOverride,
|
|
31
|
+
const { required: requiredOverride, schema: schemaValue } = (0, hepler_1.applyModifierSchema)(props[key], config, { required: required.includes(key) });
|
|
32
32
|
required = required.filter(r => r !== key);
|
|
33
|
-
if (!
|
|
33
|
+
if (!schemaValue) {
|
|
34
34
|
delete props[key];
|
|
35
35
|
continue;
|
|
36
36
|
}
|
|
37
|
-
props[key] =
|
|
37
|
+
props[key] = schemaValue;
|
|
38
38
|
if (requiredOverride) {
|
|
39
39
|
required.push(key);
|
|
40
40
|
}
|
|
@@ -53,7 +53,7 @@ function modifyParameters(parameters, type, config) {
|
|
|
53
53
|
if (!(0, utils_1.isMatch)(param.name, config.match)) {
|
|
54
54
|
return param;
|
|
55
55
|
}
|
|
56
|
-
const {
|
|
56
|
+
const { schema, required } = (0, hepler_1.applyModifierSchema)(param.schema, config, { required: !!param.required });
|
|
57
57
|
if (!schema) {
|
|
58
58
|
return null;
|
|
59
59
|
}
|
|
@@ -73,22 +73,22 @@ function payloadModifierApiDescriptor(apiDescriptor, config) {
|
|
|
73
73
|
const newDescriptor = { ...apiDescriptor };
|
|
74
74
|
const { scope } = config;
|
|
75
75
|
switch (scope) {
|
|
76
|
-
case
|
|
76
|
+
case 'params':
|
|
77
77
|
if (newDescriptor.parameters) {
|
|
78
78
|
newDescriptor.parameters = modifyParameters(newDescriptor.parameters, constant_1.ParameterIn.QUERY, config);
|
|
79
79
|
}
|
|
80
80
|
break;
|
|
81
|
-
case
|
|
81
|
+
case 'pathParams':
|
|
82
82
|
if (newDescriptor.parameters) {
|
|
83
83
|
newDescriptor.parameters = modifyParameters(newDescriptor.parameters, constant_1.ParameterIn.PATH, config);
|
|
84
84
|
}
|
|
85
85
|
break;
|
|
86
|
-
case
|
|
86
|
+
case 'data':
|
|
87
87
|
if (newDescriptor.requestBody) {
|
|
88
88
|
newDescriptor.requestBody = modifySchemaProperties(newDescriptor.requestBody, config);
|
|
89
89
|
}
|
|
90
90
|
break;
|
|
91
|
-
case
|
|
91
|
+
case 'response':
|
|
92
92
|
if (newDescriptor.responses) {
|
|
93
93
|
newDescriptor.responses = modifySchemaProperties(newDescriptor.responses, config);
|
|
94
94
|
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.fastapi = void 0;
|
|
4
|
+
const constant_1 = require("../../../constant");
|
|
5
|
+
const shared_1 = require("./shared");
|
|
6
|
+
/**
|
|
7
|
+
* FastAPI platform plugin.
|
|
8
|
+
*
|
|
9
|
+
* Pass the base URL of your FastAPI app; the plugin will try `/openapi.json`
|
|
10
|
+
* first, then fall back to the bare base URL.
|
|
11
|
+
*
|
|
12
|
+
* @param input - base URL string, or an array of base URLs
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* plugins: [fastapi('http://fastapi-example.dokkuapp.com'), alovaGlobals()]
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
exports.fastapi = (0, shared_1.defineUrlPlatformPlugin)(constant_1.PluginName.FASTAPI, base => [
|
|
20
|
+
`${base}/openapi.json`,
|
|
21
|
+
base,
|
|
22
|
+
]);
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.yapi = exports.swagger = exports.withCookie = exports.normalizeBase = exports.defineUrlPlatformPlugin = exports.knife4j = exports.fastapi = void 0;
|
|
4
|
+
var fastapi_1 = require("./fastapi");
|
|
5
|
+
Object.defineProperty(exports, "fastapi", { enumerable: true, get: function () { return fastapi_1.fastapi; } });
|
|
6
|
+
var knife4j_1 = require("./knife4j");
|
|
7
|
+
Object.defineProperty(exports, "knife4j", { enumerable: true, get: function () { return knife4j_1.knife4j; } });
|
|
8
|
+
var shared_1 = require("./shared");
|
|
9
|
+
Object.defineProperty(exports, "defineUrlPlatformPlugin", { enumerable: true, get: function () { return shared_1.defineUrlPlatformPlugin; } });
|
|
10
|
+
Object.defineProperty(exports, "normalizeBase", { enumerable: true, get: function () { return shared_1.normalizeBase; } });
|
|
11
|
+
Object.defineProperty(exports, "withCookie", { enumerable: true, get: function () { return shared_1.withCookie; } });
|
|
12
|
+
var swagger_1 = require("./swagger");
|
|
13
|
+
Object.defineProperty(exports, "swagger", { enumerable: true, get: function () { return swagger_1.swagger; } });
|
|
14
|
+
var yapi_1 = require("./yapi");
|
|
15
|
+
Object.defineProperty(exports, "yapi", { enumerable: true, get: function () { return yapi_1.yapi; } });
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.knife4j = void 0;
|
|
4
|
+
const constant_1 = require("../../../constant");
|
|
5
|
+
const shared_1 = require("./shared");
|
|
6
|
+
/**
|
|
7
|
+
* Knife4j platform plugin.
|
|
8
|
+
*
|
|
9
|
+
* Pass the base URL of your Knife4j instance; the plugin will try the OAS3
|
|
10
|
+
* endpoint (springdoc) first, then the Swagger2 endpoint (springfox), then the
|
|
11
|
+
* bare base URL.
|
|
12
|
+
*
|
|
13
|
+
* @param input - base URL string, or an array of base URLs
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* plugins: [knife4j('https://openapi3.demo.knife4jnext.com'), alovaGlobals()]
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
exports.knife4j = (0, shared_1.defineUrlPlatformPlugin)(constant_1.PluginName.KNIFE4J, base => [
|
|
21
|
+
`${base}/v3/api-docs`,
|
|
22
|
+
`${base}/v2/api-docs`,
|
|
23
|
+
base,
|
|
24
|
+
]);
|