@dune2/cli 1.2.6 → 1.2.8
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/cli.d.mts +1 -1
- package/dist/cli.mjs +5 -5
- package/dist/cli.mjs.map +1 -1
- package/dist/{config-CF5PxwnQ.mjs → config-7HzSuDvU.mjs} +4 -3
- package/dist/{config-CF5PxwnQ.mjs.map → config-7HzSuDvU.mjs.map} +1 -1
- package/dist/{generateApi-QJcMk9Aw.mjs → generateApi-DBj2oZpC.mjs} +39 -39
- package/dist/generateApi-DBj2oZpC.mjs.map +1 -0
- package/dist/index.d.mts +1 -2
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/{initConfig-DCOS9II9.mjs → initConfig-BwaePXNS.mjs} +2 -3
- package/dist/initConfig-BwaePXNS.mjs.map +1 -0
- package/dist/{interactive-OXXqccQf.mjs → interactive-zbYM7FbL.mjs} +1 -1
- package/dist/{interactive-OXXqccQf.mjs.map → interactive-zbYM7FbL.mjs.map} +1 -1
- package/dist/normalizeConfig.d.mts +1 -2
- package/dist/normalizeConfig.mjs.map +1 -1
- package/dist/{types-PHOcXvPc.d.mts → types-zWblMo92.d.mts} +2 -3
- package/package.json +4 -4
- package/readme.md +0 -2
- package/dist/generateApi-QJcMk9Aw.mjs.map +0 -1
- package/dist/initConfig-DCOS9II9.mjs.map +0 -1
package/dist/cli.d.mts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export {}
|
package/dist/cli.mjs
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import cac from "cac";
|
|
3
3
|
import debug from "debug";
|
|
4
4
|
//#region package.json
|
|
5
|
-
var version = "1.2.
|
|
5
|
+
var version = "1.2.7";
|
|
6
6
|
//#endregion
|
|
7
7
|
//#region src/shared/index.ts
|
|
8
8
|
const cli = cac("dune");
|
|
@@ -18,19 +18,19 @@ debug.enable(`${cli.name}:*`);
|
|
|
18
18
|
//#endregion
|
|
19
19
|
//#region src/cli.ts
|
|
20
20
|
cli.command("generateApi", "生成 api 文件").example("dune generateApi").action(async () => {
|
|
21
|
-
const { generateApi } = await import("./generateApi-
|
|
21
|
+
const { generateApi } = await import("./generateApi-DBj2oZpC.mjs");
|
|
22
22
|
await generateApi();
|
|
23
23
|
});
|
|
24
24
|
cli.command("init", "初始化配置文件").example("dune init").action(async () => {
|
|
25
|
-
const { initConfig } = await import("./initConfig-
|
|
25
|
+
const { initConfig } = await import("./initConfig-BwaePXNS.mjs");
|
|
26
26
|
await initConfig();
|
|
27
27
|
});
|
|
28
28
|
cli.command("interactive", "交互式操作").example("dune interactive").alias("i").action(async (args) => {
|
|
29
|
-
const { interactive } = await import("./interactive-
|
|
29
|
+
const { interactive } = await import("./interactive-zbYM7FbL.mjs");
|
|
30
30
|
await interactive(args);
|
|
31
31
|
});
|
|
32
32
|
cli.command("").action(async (args) => {
|
|
33
|
-
const { interactive } = await import("./interactive-
|
|
33
|
+
const { interactive } = await import("./interactive-zbYM7FbL.mjs");
|
|
34
34
|
await interactive(args);
|
|
35
35
|
});
|
|
36
36
|
cli.version(version);
|
package/dist/cli.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.mjs","names":[],"sources":["../package.json","../src/shared/index.ts","../src/cli.ts"],"sourcesContent":["","import cac from 'cac';\nimport debug from 'debug';\n\nexport const cli = cac('dune');\n\nexport const createLogger = (name: string) => {\n const info = debug(`${cli.name}:${name}`);\n return {\n ...info,\n info,\n error: info.extend('error'),\n };\n};\n\ndebug.enable(`${cli.name}:*`);\n","#!/usr/bin/env node\nimport { version } from '../package.json';\nimport { cli } from './shared';\n\n//#region api 相关\ncli\n .command('generateApi', '生成 api 文件')\n .example('dune generateApi')\n .action(async () => {\n const { generateApi } = await import('./commands/generateApi');\n await generateApi();\n });\n//#endregion\n\ncli\n .command('init', '初始化配置文件')\n .example('dune init')\n .action(async () => {\n const { initConfig } = await import('./commands/initConfig');\n await initConfig();\n });\n\ncli\n .command('interactive', '交互式操作')\n .example('dune interactive')\n .alias('i')\n .action(async (args) => {\n const { interactive } = await import('./commands/interactive');\n await interactive(args);\n });\n\n// make default command run interactive\ncli.command('').action(async (args) => {\n const { interactive } = await import('./commands/interactive');\n await interactive(args);\n});\n\ncli.version(version);\ncli.help();\n\n(async () => {\n try {\n // Parse CLI args without running the command\n cli.parse(process.argv, { run: false });\n // Run the command yourself\n // You only need `await` when your command action returns a Promise\n await cli.runMatchedCommand();\n } catch (error) {\n // Handle error here..\n // e.g.\n // console.error(error.stack)\n // process.exit(1)\n }\n})();\n"],"mappings":";;;;;;;ACGA,MAAa,MAAM,IAAI,
|
|
1
|
+
{"version":3,"file":"cli.mjs","names":[],"sources":["../package.json","../src/shared/index.ts","../src/cli.ts"],"sourcesContent":["","import cac from 'cac';\nimport debug from 'debug';\n\nexport const cli = cac('dune');\n\nexport const createLogger = (name: string) => {\n const info = debug(`${cli.name}:${name}`);\n return {\n ...info,\n info,\n error: info.extend('error'),\n };\n};\n\ndebug.enable(`${cli.name}:*`);\n","#!/usr/bin/env node\nimport { version } from '../package.json';\nimport { cli } from './shared';\n\n//#region api 相关\ncli\n .command('generateApi', '生成 api 文件')\n .example('dune generateApi')\n .action(async () => {\n const { generateApi } = await import('./commands/generateApi');\n await generateApi();\n });\n//#endregion\n\ncli\n .command('init', '初始化配置文件')\n .example('dune init')\n .action(async () => {\n const { initConfig } = await import('./commands/initConfig');\n await initConfig();\n });\n\ncli\n .command('interactive', '交互式操作')\n .example('dune interactive')\n .alias('i')\n .action(async (args) => {\n const { interactive } = await import('./commands/interactive');\n await interactive(args);\n });\n\n// make default command run interactive\ncli.command('').action(async (args) => {\n const { interactive } = await import('./commands/interactive');\n await interactive(args);\n});\n\ncli.version(version);\ncli.help();\n\n(async () => {\n try {\n // Parse CLI args without running the command\n cli.parse(process.argv, { run: false });\n // Run the command yourself\n // You only need `await` when your command action returns a Promise\n await cli.runMatchedCommand();\n } catch (error) {\n // Handle error here..\n // e.g.\n // console.error(error.stack)\n // process.exit(1)\n }\n})();\n"],"mappings":";;;;;;;ACGA,MAAa,MAAM,IAAI,MAAM;AAE7B,MAAa,gBAAgB,SAAiB;CAC5C,MAAM,OAAO,MAAM,GAAG,IAAI,KAAK,GAAG,MAAM;CACxC,OAAO;EACL,GAAG;EACH;EACA,OAAO,KAAK,OAAO,OAAO;CAC5B;AACF;AAEA,MAAM,OAAO,GAAG,IAAI,KAAK,GAAG;;;ACT5B,IACG,QAAQ,eAAe,WAAW,CAAC,CACnC,QAAQ,kBAAkB,CAAC,CAC3B,OAAO,YAAY;CAClB,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,MAAM,YAAY;AACpB,CAAC;AAGH,IACG,QAAQ,QAAQ,SAAS,CAAC,CAC1B,QAAQ,WAAW,CAAC,CACpB,OAAO,YAAY;CAClB,MAAM,EAAE,eAAe,MAAM,OAAO;CACpC,MAAM,WAAW;AACnB,CAAC;AAEH,IACG,QAAQ,eAAe,OAAO,CAAC,CAC/B,QAAQ,kBAAkB,CAAC,CAC3B,MAAM,GAAG,CAAC,CACV,OAAO,OAAO,SAAS;CACtB,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,MAAM,YAAY,IAAI;AACxB,CAAC;AAGH,IAAI,QAAQ,EAAE,CAAC,CAAC,OAAO,OAAO,SAAS;CACrC,MAAM,EAAE,gBAAgB,MAAM,OAAO;CACrC,MAAM,YAAY,IAAI;AACxB,CAAC;AAED,IAAI,QAAQ,OAAO;AACnB,IAAI,KAAK;CAER,YAAY;CACX,IAAI;EAEF,IAAI,MAAM,QAAQ,MAAM,EAAE,KAAK,MAAM,CAAC;EAGtC,MAAM,IAAI,kBAAkB;CAC9B,SAAS,OAAO,CAKhB;AACF,EAAA,CAAG"}
|
|
@@ -7,13 +7,14 @@ function defineConfig(c) {
|
|
|
7
7
|
const configName = "dune.config.ts";
|
|
8
8
|
async function getConfig() {
|
|
9
9
|
const cwd = process.cwd();
|
|
10
|
-
|
|
10
|
+
const res = await createJiti(cwd).import(`./${configName}`, { default: true }).catch((err) => {
|
|
11
11
|
console.warn(`can not find config file: ${configName} in ${cwd}`);
|
|
12
12
|
console.warn(`please run "dune init" to create config file`);
|
|
13
13
|
return {};
|
|
14
|
-
})
|
|
14
|
+
});
|
|
15
|
+
return normalizeConfig(res);
|
|
15
16
|
}
|
|
16
17
|
//#endregion
|
|
17
18
|
export { defineConfig as n, getConfig as r, configName as t };
|
|
18
19
|
|
|
19
|
-
//# sourceMappingURL=config-
|
|
20
|
+
//# sourceMappingURL=config-7HzSuDvU.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-
|
|
1
|
+
{"version":3,"file":"config-7HzSuDvU.mjs","names":[],"sources":["../src/shared/config/index.ts"],"sourcesContent":["import { createJiti } from 'jiti';\nimport { normalizeConfig } from './normalizeConfig';\nimport { Config } from './types';\n\nexport * from './types';\n\nexport function defineConfig<T extends Config = Config>(c: T) {\n return c;\n}\n\nexport const configName = 'dune.config.ts';\n\nexport async function getConfig(): Promise<Config> {\n const cwd = process.cwd();\n const jiti = createJiti(cwd);\n\n const res = await jiti\n .import<Config>(`./${configName}`, {\n default: true,\n })\n .catch((err) => {\n console.warn(`can not find config file: ${configName} in ${cwd}`);\n console.warn(`please run \"dune init\" to create config file`);\n return {};\n });\n\n return normalizeConfig(res);\n}\n"],"mappings":";;;AAMA,SAAgB,aAAwC,GAAM;CAC5D,OAAO;AACT;AAEA,MAAa,aAAa;AAE1B,eAAsB,YAA6B;CACjD,MAAM,MAAM,QAAQ,IAAI;CAGxB,MAAM,MAAM,MAFC,WAAW,GAEH,CAAC,CACnB,OAAe,KAAK,cAAc,EACjC,SAAS,KACX,CAAC,CAAC,CACD,OAAO,QAAQ;EACd,QAAQ,KAAK,6BAA6B,WAAW,MAAM,KAAK;EAChE,QAAQ,KAAK,8CAA8C;EAC3D,OAAO,CAAC;CACV,CAAC;CAEH,OAAO,gBAAgB,GAAG;AAC5B"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as getConfig } from "./config-
|
|
1
|
+
import { r as getConfig } from "./config-7HzSuDvU.mjs";
|
|
2
2
|
import { n as createLogger } from "./cli.mjs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
@@ -6,8 +6,8 @@ import { spawn } from "node:child_process";
|
|
|
6
6
|
import fs from "node:fs/promises";
|
|
7
7
|
import * as os from "os";
|
|
8
8
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
9
|
+
import { generate } from "@fumari/json-schema-ts";
|
|
9
10
|
import { camelCase, isPlainObject, merge } from "es-toolkit";
|
|
10
|
-
import { compile } from "json-schema-to-typescript";
|
|
11
11
|
import pMap from "p-map";
|
|
12
12
|
import enquirer from "enquirer";
|
|
13
13
|
//#region src/shared/promptConfigEnable.ts
|
|
@@ -15,6 +15,13 @@ const { prompt } = enquirer;
|
|
|
15
15
|
async function promptConfigEnable(opt) {
|
|
16
16
|
const { configArr, getChoiceItem } = opt;
|
|
17
17
|
if (configArr.length <= 1) return configArr;
|
|
18
|
+
const choices = [{
|
|
19
|
+
name: "全部",
|
|
20
|
+
message: "全部",
|
|
21
|
+
choices: configArr.map((item) => {
|
|
22
|
+
return getChoiceItem(item);
|
|
23
|
+
})
|
|
24
|
+
}];
|
|
18
25
|
const res = await prompt({
|
|
19
26
|
type: "multiselect",
|
|
20
27
|
message: "选择要生效的配置项",
|
|
@@ -23,13 +30,7 @@ async function promptConfigEnable(opt) {
|
|
|
23
30
|
validate(value) {
|
|
24
31
|
return value.length === 0 ? `至少选择一项` : true;
|
|
25
32
|
},
|
|
26
|
-
choices
|
|
27
|
-
name: "全部",
|
|
28
|
-
message: "全部",
|
|
29
|
-
choices: configArr.map((item) => {
|
|
30
|
-
return getChoiceItem(item);
|
|
31
|
-
})
|
|
32
|
-
}]
|
|
33
|
+
choices
|
|
33
34
|
});
|
|
34
35
|
configArr.forEach((item) => {
|
|
35
36
|
item.enabled = opt.checkIsEnabled(res.enabled, item);
|
|
@@ -150,7 +151,7 @@ async function fetchRemoteDocument(url, options) {
|
|
|
150
151
|
* 构造一个最小化的定义上下文。
|
|
151
152
|
*
|
|
152
153
|
* 之前是把整个 components/definitions 直接挂到每个待编译的 schema 上,
|
|
153
|
-
*
|
|
154
|
+
* 导致类型生成器每次都要遍历整份 API 的类型图,
|
|
154
155
|
* 261 个接口 × 2(Req/Res)= 522 次全量遍历,非常慢。
|
|
155
156
|
* 这里改为按需收集可达定义,输出结果不变,但速度大幅提升。
|
|
156
157
|
*/
|
|
@@ -202,15 +203,20 @@ function buildRefContext(rootSchema, parsed) {
|
|
|
202
203
|
}
|
|
203
204
|
return context;
|
|
204
205
|
}
|
|
205
|
-
function
|
|
206
|
+
function normalizeSchemaForGenerationDeep(value) {
|
|
206
207
|
if (!value || typeof value !== "object") return;
|
|
207
208
|
if (Array.isArray(value)) {
|
|
208
|
-
value.forEach((item) =>
|
|
209
|
+
value.forEach((item) => normalizeSchemaForGenerationDeep(item));
|
|
209
210
|
return;
|
|
210
211
|
}
|
|
211
212
|
const record = value;
|
|
212
213
|
if ("default" in record) delete record.default;
|
|
213
|
-
|
|
214
|
+
if (record.type === "array" && Array.isArray(record.enum)) {
|
|
215
|
+
const arrayEnum = record.enum.filter(Array.isArray);
|
|
216
|
+
if (arrayEnum.length > 0) record.enum = arrayEnum;
|
|
217
|
+
else delete record.enum;
|
|
218
|
+
}
|
|
219
|
+
Object.values(record).forEach((item) => normalizeSchemaForGenerationDeep(item));
|
|
214
220
|
}
|
|
215
221
|
async function generateApi() {
|
|
216
222
|
const config = await getConfig();
|
|
@@ -269,7 +275,7 @@ async function generateApi() {
|
|
|
269
275
|
try {
|
|
270
276
|
const bundleInput = /^https?:\/\//.test(apiConfig.swaggerJSONPath) ? await fetchRemoteDocument(apiConfig.swaggerJSONPath, dereferenceConfig) : apiConfig.swaggerJSONPath;
|
|
271
277
|
parsed = await parser.bundle(bundleInput, dereferenceConfig);
|
|
272
|
-
|
|
278
|
+
normalizeSchemaForGenerationDeep(parsed);
|
|
273
279
|
log.info("解析 %s 成功,耗时 %dms", apiConfig.swaggerJSONPath, Date.now() - bundleStartedAt);
|
|
274
280
|
} catch (error) {
|
|
275
281
|
totalFailedCount++;
|
|
@@ -403,18 +409,24 @@ async function compileRequestParams(operationObject) {
|
|
|
403
409
|
const parameterSchema = (() => {
|
|
404
410
|
if (!operationObject.parameters) return;
|
|
405
411
|
const extraProperties = {};
|
|
412
|
+
const extraRequired = [];
|
|
406
413
|
const parameters = [];
|
|
407
414
|
operationObject.parameters.forEach((item) => {
|
|
408
415
|
if (!["query", "path"].includes(item.in)) return;
|
|
409
|
-
|
|
410
|
-
|
|
416
|
+
const schema = item.schema && "$ref" in item.schema ? store?.parser.$refs.get(item.schema.$ref) : item.schema;
|
|
417
|
+
if (schema && "type" in schema && schema.type === "object") {
|
|
418
|
+
Object.assign(extraProperties, schema.properties || {});
|
|
419
|
+
extraRequired.push(...schema.required || []);
|
|
420
|
+
} else parameters.push(item);
|
|
411
421
|
});
|
|
422
|
+
const required = parameters.filter((p) => p.required && ![
|
|
423
|
+
"pageNum",
|
|
424
|
+
"pageSize",
|
|
425
|
+
"count"
|
|
426
|
+
].includes(p.name)).map((p) => p.name);
|
|
427
|
+
required.push(...extraRequired);
|
|
412
428
|
return {
|
|
413
|
-
required
|
|
414
|
-
"pageNum",
|
|
415
|
-
"pageSize",
|
|
416
|
-
"count"
|
|
417
|
-
].includes(p.name)).map((p) => p.name),
|
|
429
|
+
required,
|
|
418
430
|
type: "object",
|
|
419
431
|
properties: {
|
|
420
432
|
...Object.fromEntries(parameters.filter((p) => !!p.schema).map((p) => {
|
|
@@ -432,23 +444,17 @@ async function compileRequestParams(operationObject) {
|
|
|
432
444
|
const schemaObject = requestBodySchema && parameterSchema ? {
|
|
433
445
|
...requestBodySchema,
|
|
434
446
|
type: "object",
|
|
435
|
-
required: [
|
|
447
|
+
required: [.../* @__PURE__ */ new Set([...requestBodySchema.required || [], ...parameterSchema.required || []])],
|
|
436
448
|
properties: {
|
|
437
449
|
...requestBodySchema.properties || {},
|
|
438
450
|
...parameterSchema.properties || {}
|
|
439
451
|
}
|
|
440
452
|
} : requestBodySchema || parameterSchema;
|
|
441
|
-
if (schemaObject)
|
|
453
|
+
if (schemaObject) normalizeSchemaForGenerationDeep(schemaObject);
|
|
442
454
|
const finalSchema = schemaObject ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject) : void 0;
|
|
443
455
|
let code = "";
|
|
444
456
|
if (finalSchema) try {
|
|
445
|
-
code =
|
|
446
|
-
bannerComment: "",
|
|
447
|
-
ignoreMinAndMaxItems: true,
|
|
448
|
-
additionalProperties: false,
|
|
449
|
-
unknownAny: false,
|
|
450
|
-
format: false
|
|
451
|
-
});
|
|
457
|
+
code = generate(finalSchema, { name: "Req" });
|
|
452
458
|
} catch (e) {
|
|
453
459
|
const message = e instanceof Error ? e.message : String(e);
|
|
454
460
|
log.error("生成请求参数类型失败,请检查 %o", {
|
|
@@ -470,17 +476,11 @@ async function compileResponseParams(operationObject, apiConfig) {
|
|
|
470
476
|
return schema;
|
|
471
477
|
}
|
|
472
478
|
const schemaObject = resolveSchema(pickSuccessResponse(operationObject.responses));
|
|
473
|
-
if (schemaObject)
|
|
479
|
+
if (schemaObject) normalizeSchemaForGenerationDeep(schemaObject);
|
|
474
480
|
const finalSchema = schemaObject ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject) : void 0;
|
|
475
481
|
let code = "";
|
|
476
482
|
if (finalSchema) try {
|
|
477
|
-
code =
|
|
478
|
-
bannerComment: "",
|
|
479
|
-
ignoreMinAndMaxItems: true,
|
|
480
|
-
additionalProperties: false,
|
|
481
|
-
unknownAny: false,
|
|
482
|
-
format: false
|
|
483
|
-
});
|
|
483
|
+
code = generate(finalSchema, { name: "Res" });
|
|
484
484
|
} catch (e) {
|
|
485
485
|
const message = e instanceof Error ? e.message : String(e);
|
|
486
486
|
log.error("转换响应参数类型失败,请检查 %o", {
|
|
@@ -495,4 +495,4 @@ async function compileResponseParams(operationObject, apiConfig) {
|
|
|
495
495
|
//#endregion
|
|
496
496
|
export { generateApi };
|
|
497
497
|
|
|
498
|
-
//# sourceMappingURL=generateApi-
|
|
498
|
+
//# sourceMappingURL=generateApi-DBj2oZpC.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateApi-DBj2oZpC.mjs","names":[],"sources":["../src/shared/promptConfigEnable.ts","../src/commands/generateApi/index.ts"],"sourcesContent":["import enquirer from 'enquirer';\nimport { ApiConfig } from './config';\nconst { prompt } = enquirer;\n\ninterface Opt<T> {\n configArr: (T & { enabled?: boolean })[];\n getChoiceItem: (item: T) => {\n name: string;\n message?: string;\n value?: string;\n hint?: string;\n };\n checkIsEnabled: (enabledArr: string[], item: T) => boolean;\n}\n\nexport async function promptConfigEnable<T>(opt: Opt<T>) {\n const { configArr, getChoiceItem } = opt;\n // 只有一条配置的时候不用选择\n if (configArr.length <= 1) {\n return configArr;\n }\n\n const choices = [\n {\n name: '全部',\n message: '全部',\n choices: configArr.map((item) => {\n return getChoiceItem(item);\n }),\n },\n ];\n const res = await prompt<{ enabled: string[] }>({\n type: 'multiselect',\n message: '选择要生效的配置项',\n // @ts-ignore\n hint: '(空格选中,回车确认)',\n name: 'enabled',\n validate(value) {\n return value.length === 0 ? `至少选择一项` : true;\n },\n choices,\n });\n\n configArr.forEach((item) => {\n item.enabled = opt.checkIsEnabled(res.enabled, item);\n });\n\n return configArr.filter((c) => c.enabled);\n}\n\nexport function promptApiConfigEnable(configArr: ApiConfig[] | undefined) {\n return promptConfigEnable({\n configArr: configArr ?? [],\n getChoiceItem: (item) => {\n return {\n name: item.output!,\n hint: `swaggerJSONPath: ${item.swaggerJSONPath}`,\n };\n },\n checkIsEnabled: (enabledArr, item) => {\n return enabledArr.includes(item.output!);\n },\n });\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { spawn } from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport * as os from 'os';\nimport path from 'path';\nimport SwaggerParser from '@apidevtools/swagger-parser';\nimport { generate } from '@fumari/json-schema-ts';\nimport { camelCase, isPlainObject, merge } from 'es-toolkit';\nimport type { OpenAPIV2, OpenAPIV3 } from 'openapi-types';\nimport pMap from 'p-map';\nimport { createLogger } from '../../shared';\nimport { ApiConfig, getConfig } from '../../shared/config';\nimport { promptApiConfigEnable } from '../../shared/promptConfigEnable';\n\nconst log = createLogger('generateApi');\n\ntype ParsedDocument = OpenAPIV2.Document | OpenAPIV3.Document;\n\nexport const asyncLocalStorage = new AsyncLocalStorage<{\n parsed: ParsedDocument;\n parser: SwaggerParser;\n}>();\n\nconst HTTP_METHODS = ['get', 'put', 'post', 'delete', 'patch'] as const;\nconst DEFAULT_FETCH_TIMEOUT = 30_000;\nconst FORMATTER_ARGUMENT_PATTERN = /\"([^\"]*)\"|'([^']*)'|(\\S+)/g;\n\nfunction getCodegenConcurrency() {\n const parallelism =\n typeof os.availableParallelism === 'function'\n ? os.availableParallelism()\n : os.cpus().length;\n return Math.max(1, parallelism - 1);\n}\n\nfunction isPathInside(parent: string, child: string) {\n const relative = path.relative(parent, child);\n return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n\nexport function resolveOutputDir(cwd: string, output: string) {\n const resolvedCwd = path.resolve(cwd);\n const resolvedOutput = path.resolve(resolvedCwd, output);\n if (!isPathInside(resolvedCwd, resolvedOutput)) {\n throw new Error(`output must be inside cwd: ${output}`);\n }\n return resolvedOutput;\n}\n\nfunction sanitizeOutputSegment(segment: string) {\n const sanitized = segment.replace(/[<>:\"\\\\|?*\\u0000-\\u001F]/g, '_');\n return sanitized === '.' || sanitized === '..' || sanitized.length === 0\n ? '_'\n : sanitized;\n}\n\nexport function resolveOperationOutputPath(options: {\n outputDir: string;\n url: string;\n method: string;\n enableTs?: boolean;\n}) {\n const outputDir = path.resolve(options.outputDir);\n const urlSegments = options.url\n .split('/')\n .filter(Boolean)\n .map(sanitizeOutputSegment);\n const fileName = `${sanitizeOutputSegment(options.method)}.${\n options.enableTs === false ? 'js' : 'ts'\n }`;\n const outputPath = path.resolve(outputDir, ...urlSegments, fileName);\n if (!isPathInside(outputDir, outputPath)) {\n throw new Error(`operation output escaped output dir: ${options.url}`);\n }\n return outputPath;\n}\n\nfunction parseFormatterCommand(command: string) {\n const args = [...command.matchAll(FORMATTER_ARGUMENT_PATTERN)]\n .map((match) => match[1] ?? match[2] ?? match[3] ?? '')\n .filter(Boolean);\n const [file, ...rest] = args;\n if (!file) {\n throw new Error('codeFormatterCmd is empty');\n }\n return { file, args: rest };\n}\n\nasync function runFormatter(command: string, outputDir: string) {\n const { file, args } = parseFormatterCommand(command);\n await new Promise<void>((resolve, reject) => {\n const child = spawn(file, [...args, outputDir], {\n shell: false,\n stdio: 'inherit',\n });\n child.on('error', reject);\n child.on('exit', (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(\n new Error(\n signal\n ? `formatter exited with signal ${signal}`\n : `formatter exited with code ${code}`,\n ),\n );\n });\n });\n}\n\nfunction getHttpTimeout(options: SwaggerParser.Options) {\n const http = options.resolve?.http;\n if (http && typeof http === 'object' && 'timeout' in http) {\n return typeof http.timeout === 'number'\n ? http.timeout\n : DEFAULT_FETCH_TIMEOUT;\n }\n return DEFAULT_FETCH_TIMEOUT;\n}\n\nfunction isJsonContentType(contentType: string) {\n const mediaType = contentType.split(';', 1)[0].trim().toLowerCase();\n return (\n mediaType === 'application/json' ||\n mediaType === '*/*' ||\n mediaType.endsWith('/json') ||\n mediaType.endsWith('+json')\n );\n}\n\nfunction pickJsonMedia(\n content: Record<string, OpenAPIV3.MediaTypeObject> | undefined,\n) {\n if (!content) return undefined;\n return (\n content['application/json'] ??\n content['*/*'] ??\n Object.entries(content).find(([contentType]) =>\n isJsonContentType(contentType),\n )?.[1]\n );\n}\n\nfunction getRequestBodySchema(\n requestBody:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.RequestBodyObject\n | undefined,\n) {\n if (!requestBody) return undefined;\n if ('$ref' in requestBody) return requestBody;\n return pickJsonMedia(requestBody.content)?.schema;\n}\n\nfunction pickSuccessResponse(responses: OpenAPIV3.ResponsesObject) {\n return responses['200'];\n}\n\nfunction isParsedDocument(value: unknown): value is ParsedDocument {\n return (\n !!value &&\n typeof value === 'object' &&\n ('paths' in value || 'openapi' in value || 'swagger' in value)\n );\n}\n\nasync function fetchRemoteDocument(\n url: string,\n options: SwaggerParser.Options,\n): Promise<ParsedDocument> {\n const res = await fetch(url, {\n signal: AbortSignal.timeout(getHttpTimeout(options)),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} ${res.statusText}`);\n }\n const json = await res.json();\n if (!isParsedDocument(json)) {\n throw new Error(`Remote OpenAPI document is invalid: ${url}`);\n }\n return json;\n}\n\n/**\n * 只收集 rootSchema 里真正引用到的 `$ref`(含传递依赖),\n * 构造一个最小化的定义上下文。\n *\n * 之前是把整个 components/definitions 直接挂到每个待编译的 schema 上,\n * 导致类型生成器每次都要遍历整份 API 的类型图,\n * 261 个接口 × 2(Req/Res)= 522 次全量遍历,非常慢。\n * 这里改为按需收集可达定义,输出结果不变,但速度大幅提升。\n */\nfunction buildRefContext(\n rootSchema: unknown,\n parsed: ParsedDocument | undefined,\n): Record<string, unknown> {\n const context: Record<string, unknown> = {};\n if (!parsed || !rootSchema || typeof rootSchema !== 'object') {\n return context;\n }\n\n const seen = new Set<string>();\n const queue: string[] = [];\n\n const collectRefs = (obj: unknown) => {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n obj.forEach(collectRefs);\n return;\n }\n for (const [key, value] of Object.entries(obj)) {\n if (\n key === '$ref' &&\n typeof value === 'string' &&\n value.startsWith('#/')\n ) {\n queue.push(value);\n } else {\n collectRefs(value);\n }\n }\n };\n\n const decodeSegment = (segment: string) =>\n segment.replace(/~1/g, '/').replace(/~0/g, '~');\n\n const resolvePointer = (ref: string) => {\n const parts = ref.slice(2).split('/').map(decodeSegment);\n let cur: unknown = parsed;\n for (const part of parts) {\n if (!cur || typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[part];\n }\n return cur === undefined ? undefined : { parts, value: cur };\n };\n\n const setPointer = (parts: string[], value: unknown) => {\n let cur = context;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!cur[part] || typeof cur[part] !== 'object') {\n cur[part] = {};\n }\n cur = cur[part] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]] = value;\n };\n\n collectRefs(rootSchema);\n while (queue.length) {\n const ref = queue.shift()!;\n if (seen.has(ref)) continue;\n seen.add(ref);\n const resolved = resolvePointer(ref);\n if (!resolved) continue;\n setPointer(resolved.parts, resolved.value);\n collectRefs(resolved.value);\n }\n\n return context;\n}\n\nfunction normalizeSchemaForGenerationDeep(value: unknown) {\n if (!value || typeof value !== 'object') {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => normalizeSchemaForGenerationDeep(item));\n return;\n }\n\n const record = value as Record<string, unknown>;\n if ('default' in record) {\n delete record.default;\n }\n\n // Some Swagger generators copy an item's string enum onto its array schema.\n // JSON Schema requires enum values there to be arrays; keep only valid values.\n if (record.type === 'array' && Array.isArray(record.enum)) {\n const arrayEnum = record.enum.filter(Array.isArray);\n if (arrayEnum.length > 0) {\n record.enum = arrayEnum;\n } else {\n delete record.enum;\n }\n }\n\n Object.values(record).forEach((item) =>\n normalizeSchemaForGenerationDeep(item),\n );\n}\n\nexport async function generateApi() {\n const config = await getConfig();\n const selectedConfigs = await promptApiConfigEnable(config.api);\n const apiConfigs = selectedConfigs.filter((apiConfig) => {\n if (!apiConfig.output) {\n log.error('配置 %s 缺少 output,已跳过', apiConfig.swaggerJSONPath);\n return false;\n }\n return true;\n });\n const skippedConfigCount = selectedConfigs.length - apiConfigs.length;\n\n if (skippedConfigCount > 0) {\n log.info('由于缺少 output,跳过 %d 个配置', skippedConfigCount);\n }\n\n if (!apiConfigs.length) {\n log.info('没有需要生成的 API 配置,生成流程结束');\n return;\n }\n\n log.info('本次将生成 %d 个 API 配置', apiConfigs.length);\n\n let totalSuccessCount = 0;\n let totalFailedCount = 0;\n const startedAt = Date.now();\n\n const preparedConfigs: ApiConfig[] = [];\n const cwd = config.cwd ?? process.cwd();\n\n for (const apiConfig of apiConfigs) {\n log.info('开始初始化输出目录 %s', apiConfig.output);\n const prepareStartedAt = Date.now();\n try {\n const outputDir = resolveOutputDir(cwd, apiConfig.output!);\n await fs.rm(outputDir, { recursive: true, force: true });\n await fs.mkdir(outputDir, { recursive: true });\n preparedConfigs.push({\n ...apiConfig,\n output: outputDir,\n });\n log.info(\n '输出目录 %s 初始化完成,耗时 %dms',\n apiConfig.output,\n Date.now() - prepareStartedAt,\n );\n } catch (error) {\n totalFailedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error('初始化输出目录 %s 失败:%s', apiConfig.output, message);\n }\n }\n\n if (!preparedConfigs.length) {\n log.error('所有配置都初始化失败,生成流程结束');\n log.info(\n 'generateApi Done,成功 %d 个,失败 %d 个,总耗时 %dms',\n totalSuccessCount,\n totalFailedCount,\n Date.now() - startedAt,\n );\n return;\n }\n\n for (const apiConfig of preparedConfigs) {\n log.info('开始解析 %s', apiConfig.swaggerJSONPath);\n const dereferenceConfig: SwaggerParser.Options = merge(\n {\n resolve: {\n http: {\n timeout: DEFAULT_FETCH_TIMEOUT,\n },\n },\n } satisfies SwaggerParser.Options,\n apiConfig.dereferenceSwaggerConfig || {},\n );\n const parser = new SwaggerParser();\n const bundleStartedAt = Date.now();\n\n let parsed: unknown;\n try {\n // swagger-parser's built-in HTTP resolver fails on remote URLs,\n // so we fetch the JSON ourselves and pass the parsed object instead.\n const isRemoteUrl = /^https?:\\/\\//.test(apiConfig.swaggerJSONPath);\n const bundleInput = isRemoteUrl\n ? await fetchRemoteDocument(\n apiConfig.swaggerJSONPath,\n dereferenceConfig,\n )\n : apiConfig.swaggerJSONPath;\n parsed = await parser.bundle(bundleInput, dereferenceConfig);\n // default 值经常和 type 不一致(例如 integer + \"\"),\n // 生成前统一移除,避免输出错误的类型或文档。\n normalizeSchemaForGenerationDeep(parsed);\n log.info(\n '解析 %s 成功,耗时 %dms',\n apiConfig.swaggerJSONPath,\n Date.now() - bundleStartedAt,\n );\n } catch (error) {\n totalFailedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error('解析 %s 失败:%s', apiConfig.swaggerJSONPath, message);\n continue;\n }\n\n const state = {\n // only support v3\n parsed: parsed as OpenAPIV3.Document,\n parser,\n };\n\n let generatedCount = 0;\n let skippedCount = 0;\n const pathEntries = Object.entries(\n (parsed as OpenAPIV3.Document).paths ?? {},\n );\n if (!pathEntries.length) {\n log.error('%s 中没有可用的 paths,已跳过', apiConfig.swaggerJSONPath);\n totalFailedCount++;\n continue;\n }\n\n const codegenConcurrency = getCodegenConcurrency();\n\n await asyncLocalStorage.run(state, async () => {\n await pMap(\n pathEntries,\n async ([url, pathItemObject]) => {\n if (!pathItemObject) {\n log.error('路径 %s 未定义 pathItemObject,已跳过', url);\n skippedCount++;\n return;\n }\n\n log.info('开始生成 %s', url);\n let generatedForUrl = 0;\n await pMap(\n HTTP_METHODS,\n async (method) => {\n const operationObject = pathItemObject[method];\n if (!operationObject) {\n return;\n }\n\n try {\n const code = await generateApiRequestCode({\n url: url,\n method: method,\n operationObject: operationObject,\n apiConfig,\n });\n const outputPath = resolveOperationOutputPath({\n outputDir: apiConfig.output!,\n url,\n method,\n enableTs: apiConfig.enableTs,\n });\n await fs.mkdir(path.dirname(outputPath), {\n recursive: true,\n });\n await fs.writeFile(outputPath, code);\n generatedCount++;\n generatedForUrl++;\n } catch (error) {\n skippedCount++;\n const message =\n error instanceof Error ? error.message : String(error);\n log.error(\n '%s %s 生成失败:%s',\n method.toUpperCase(),\n url,\n message,\n );\n }\n },\n { concurrency: 1 },\n );\n if (generatedForUrl === 0) {\n log.info('路径 %s 未生成任何方法', url);\n }\n },\n { concurrency: codegenConcurrency },\n );\n });\n\n if (!generatedCount) {\n log.error('%s 未生成任何请求,已标记失败', apiConfig.swaggerJSONPath);\n totalFailedCount++;\n continue;\n }\n\n if (apiConfig.codeFormatterCmd) {\n try {\n await runFormatter(apiConfig.codeFormatterCmd, apiConfig.output!);\n log.info(`Code formatting success`);\n } catch (error) {\n skippedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error(`Code formatting failed: ${message}`);\n }\n }\n\n log.info(\n '%s 生成完成,共生成 %d 个请求,跳过 %d 个',\n apiConfig.swaggerJSONPath,\n generatedCount,\n skippedCount,\n );\n totalSuccessCount++;\n }\n\n log.info(\n 'generateApi Done,成功 %d 个,失败 %d 个,总耗时 %dms',\n totalSuccessCount,\n totalFailedCount,\n Date.now() - startedAt,\n );\n}\n\n/**\n * 根据请求方法,生成请求代码\n */\nexport async function generateApiRequestCode(options: {\n url: string;\n method: string;\n operationObject: OpenAPIV3.OperationObject;\n apiConfig: ApiConfig;\n}): Promise<string> {\n const { method, operationObject, apiConfig } = options;\n\n const url = (() => {\n if (typeof apiConfig.urlTransformer === 'string') {\n return `${apiConfig.urlTransformer}${options.url}`;\n }\n if (typeof apiConfig.urlTransformer === 'function') {\n return apiConfig.urlTransformer(options.url);\n }\n return options.url;\n })();\n\n const seeUrl = apiConfig.swaggerUiUrl\n ? `${apiConfig.swaggerUiUrl}#/${encodeURIComponent(\n `${operationObject.tags?.join('/') ?? ''}/${\n operationObject.operationId\n }`,\n )}`\n : '';\n\n // 生成的请求构造器的名称,需要使用原始 url\n let requestBuilderName = camelCase(`${options.url}_${method}_api`);\n\n // 判断是否有效的 js 变量\n if (!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(requestBuilderName)) {\n // 不是有效的 js 变量,使用 _ + 数字\n requestBuilderName = `_${requestBuilderName}`;\n }\n\n //#region url 上参数 例如 /api/v1/users/{userId}\n const urlPathParams = getUrlPathParams(\n (operationObject.parameters as never) ?? [],\n );\n const urlPathParamsCode = urlPathParams.length\n ? `urlPathParams: ${JSON.stringify(urlPathParams)},`\n : '';\n //#endregion\n\n let code: string[] = [\n '// do not edit this file manually, it will be overwritten by @dune2/cli',\n apiConfig.RequestBuilderImportPath!,\n apiConfig.queryClientImportPath!,\n\n '/**',\n ` * ${operationObject.summary}`,\n ` * @tags ${operationObject.tags?.join(',')}`,\n seeUrl && ` * @see ${seeUrl}`,\n ` */`,\n ].filter(Boolean);\n\n // builder 代码\n let builderCode = `\\\nexport const ${requestBuilderName} = new RequestBuilder({\n url: '${url}',\n method: '${method}',\n ${urlPathParamsCode}\n ${apiConfig.queryClientImportPath ? 'queryClient,' : ''}\n});`\n // 移除空行\n .replace(/,\\n\\s*}/, ',' + os.EOL + '}');\n if (apiConfig.enableTs) {\n builderCode = builderCode.replace(\n 'new RequestBuilder(',\n `new RequestBuilder<${requestBuilderName}.Req, ${requestBuilderName}.Res>(`,\n );\n }\n code.push(builderCode);\n\n if (apiConfig.enableTs) {\n const [requestParamsTypeCode, responseParamsTypeCode] = await Promise.all([\n // 请求参数类型\n compileRequestParams(operationObject),\n // 响应参数类型\n compileResponseParams(operationObject, apiConfig),\n ]);\n\n code.push(`\nexport namespace ${requestBuilderName} {\n ${requestParamsTypeCode.code}\n \n ${responseParamsTypeCode}\n};`);\n }\n\n return code.join(os.EOL);\n}\n\nfunction getUrlPathParams(parameters: OpenAPIV3.ParameterObject[]) {\n return parameters\n .filter((item) => item.in === 'path')\n .map((item) => item.name);\n}\n\n/**\n * 这个方法还不完善,只能处理简单的请求参数\n */\nasync function compileRequestParams(\n operationObject: OpenAPIV3.OperationObject,\n) {\n const store = asyncLocalStorage.getStore();\n const requestBodySchemaOrRef = getRequestBodySchema(\n operationObject.requestBody,\n );\n\n const parameterSchema = (() => {\n if (!operationObject.parameters) {\n return;\n }\n const extraProperties = {};\n const extraRequired: string[] = [];\n const parameters: OpenAPIV3.ParameterObject[] = [];\n (operationObject.parameters as OpenAPIV3.ParameterObject[]).forEach(\n (item) => {\n if (!['query', 'path'].includes(item.in)) {\n return;\n }\n\n const schema =\n item.schema && '$ref' in item.schema\n ? (store?.parser.$refs.get(\n item.schema.$ref,\n ) as OpenAPIV3.SchemaObject)\n : item.schema;\n if (schema && 'type' in schema && schema.type === 'object') {\n // swagger get 请求上有些参数是 object 类型(也可能通过 $ref 引用),应该拍平\n Object.assign(extraProperties, schema.properties || {});\n extraRequired.push(...(schema.required || []));\n } else {\n parameters.push(item);\n }\n },\n );\n // 必填参数中忽略 分页相关的参数\n const required = parameters\n .filter(\n (p) => p.required && !['pageNum', 'pageSize', 'count'].includes(p.name),\n )\n .map((p) => p.name);\n required.push(...extraRequired);\n const properties = Object.fromEntries(\n parameters\n // 后端 swagger 可能出现没有 schema 的情况,这里过滤掉\n .filter((p) => !!p.schema)\n .map((p) => {\n const schema = p.schema;\n return [\n p.name,\n {\n ...schema,\n description: p.description,\n // enum: schema.enum ?? [],\n },\n ];\n }),\n );\n return {\n required,\n type: 'object',\n properties: { ...properties, ...extraProperties },\n } satisfies OpenAPIV3.SchemaObject;\n })();\n\n const requestBodySchema = isPlainObject(requestBodySchemaOrRef)\n ? '$ref' in requestBodySchemaOrRef\n ? (store?.parser.$refs.get(\n requestBodySchemaOrRef.$ref,\n ) as OpenAPIV3.SchemaObject)\n : requestBodySchemaOrRef\n : void 0;\n\n const schemaObject =\n requestBodySchema && parameterSchema\n ? ({\n ...requestBodySchema,\n type: 'object',\n required: [\n ...new Set([\n ...(requestBodySchema.required || []),\n ...(parameterSchema.required || []),\n ]),\n ],\n properties: {\n ...(requestBodySchema.properties || {}),\n ...(parameterSchema.properties || {}),\n },\n } satisfies OpenAPIV3.SchemaObject)\n : requestBodySchema || parameterSchema;\n\n if (schemaObject) {\n normalizeSchemaForGenerationDeep(schemaObject);\n }\n\n const finalSchema = schemaObject\n ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject)\n : void 0;\n\n let code = '';\n if (finalSchema) {\n try {\n code = generate(finalSchema as never, {\n name: 'Req',\n });\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n log.error('生成请求参数类型失败,请检查 %o', {\n summary: operationObject.summary,\n message,\n operationId: operationObject.operationId,\n });\n }\n }\n\n return {\n code: code || 'export type Req = any;',\n };\n}\n\nasync function compileResponseParams(\n operationObject: OpenAPIV3.OperationObject,\n apiConfig: ApiConfig,\n) {\n const store = asyncLocalStorage.getStore();\n\n function resolveSchema(\n arg:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.ResponseObject\n | OpenAPIV3.MediaTypeObject\n | undefined,\n ) {\n if (!arg) return;\n\n if ('content' in arg) {\n return resolveSchema(pickJsonMedia(arg.content)?.schema);\n }\n // 兼容 swagger v2 的 response.schema\n if ('schema' in arg && arg.schema) {\n return resolveSchema(arg.schema as never);\n }\n\n let schema = apiConfig.responseSchemaTransformer!(arg as never) as\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject;\n if ('$ref' in schema) {\n return resolveSchema(store?.parser.$refs.get(schema.$ref) as never);\n }\n return schema;\n }\n const schemaObject = resolveSchema(\n pickSuccessResponse(operationObject.responses),\n );\n if (schemaObject) {\n normalizeSchemaForGenerationDeep(schemaObject);\n }\n\n const finalSchema = schemaObject\n ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject)\n : void 0;\n\n let code = '';\n if (finalSchema) {\n try {\n code = generate(finalSchema as never, {\n name: 'Res',\n });\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n log.error('转换响应参数类型失败,请检查 %o', {\n summary: operationObject.summary,\n error: message,\n operationId: operationObject.operationId,\n });\n }\n } else {\n log.error('responseSchemaTransformer 返回值为空,请检查');\n }\n\n return code ? code : 'export type Res = any;';\n}\n"],"mappings":"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"}
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { n as Config, t as ApiConfig } from "./types-
|
|
2
|
-
|
|
1
|
+
import { n as Config, t as ApiConfig } from "./types-zWblMo92.mjs";
|
|
3
2
|
//#region src/shared/config/index.d.ts
|
|
4
3
|
declare function defineConfig<T extends Config = Config>(c: T): T;
|
|
5
4
|
declare const configName = "dune.config.ts";
|
package/dist/index.mjs
CHANGED
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../src/shared/defaultJsonSorter.ts","../src/shared/letters.ts"],"sourcesContent":["/**\n * 对 JSON 对象的键进行排序\n * @param obj 要排序的 JSON 对象\n * @returns 排序后的 JSON 对象\n */\nexport function defaultJsonSorter<T extends Record<string, any>>(obj: T) {\n const keys = Object.keys(obj);\n const sortedKeys = keys.sort(); // 使用原生 sort 方法对键进行排序\n const sortedObj = sortedKeys.reduce((acc, key) => {\n acc[key as keyof T] = obj[key];\n return acc;\n }, {} as T);\n\n return sortedObj as T;\n}\n","/**\n *\n * - input : A\n * output : 0\n * - input : Z\n * output : 25\n * - input : AA\n * output : 26\n * - input : a\n * output : 0\n */\nexport function letterToNumber(letters: string | number) {\n if (typeof letters === 'number' || !Number.isNaN(+letters)) {\n return +letters;\n }\n\n let n = 0;\n letters = letters.toUpperCase();\n for (let p = 0; p < letters.length; p++) {\n n = letters[p].charCodeAt(0) - 64 + n * 26;\n }\n\n return Math.max(0, n - 1);\n}\n\n/**\n * fork from https://github.com/matthewmueller/number-to-letter\n */\nconst alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst base = alphabet.length;\n/**\n * numberToLetter(0) // A\n * numberToLetter(25) // Z\n * numberToLetter(26) // AA\n * numberToLetter(51) // AZ\n * numberToLetter(52) // BA\n * numberToLetter(676) // ZA\n * numberToLetter(701) // ZZ\n * numberToLetter(702) // AAA\n */\nexport function numberToLetter(n: number) {\n const digits: number[] = [];\n\n do {\n const v = n % base;\n digits.push(v);\n n = Math.floor(n / base);\n } while (n-- > 0);\n\n const chars: string[] = [];\n while (digits.length) {\n chars.push(alphabet[digits.pop()!]);\n }\n\n return chars.join('');\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,kBAAiD,KAAQ;
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../src/shared/defaultJsonSorter.ts","../src/shared/letters.ts"],"sourcesContent":["/**\n * 对 JSON 对象的键进行排序\n * @param obj 要排序的 JSON 对象\n * @returns 排序后的 JSON 对象\n */\nexport function defaultJsonSorter<T extends Record<string, any>>(obj: T) {\n const keys = Object.keys(obj);\n const sortedKeys = keys.sort(); // 使用原生 sort 方法对键进行排序\n const sortedObj = sortedKeys.reduce((acc, key) => {\n acc[key as keyof T] = obj[key];\n return acc;\n }, {} as T);\n\n return sortedObj as T;\n}\n","/**\n *\n * - input : A\n * output : 0\n * - input : Z\n * output : 25\n * - input : AA\n * output : 26\n * - input : a\n * output : 0\n */\nexport function letterToNumber(letters: string | number) {\n if (typeof letters === 'number' || !Number.isNaN(+letters)) {\n return +letters;\n }\n\n let n = 0;\n letters = letters.toUpperCase();\n for (let p = 0; p < letters.length; p++) {\n n = letters[p].charCodeAt(0) - 64 + n * 26;\n }\n\n return Math.max(0, n - 1);\n}\n\n/**\n * fork from https://github.com/matthewmueller/number-to-letter\n */\nconst alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';\nconst base = alphabet.length;\n/**\n * numberToLetter(0) // A\n * numberToLetter(25) // Z\n * numberToLetter(26) // AA\n * numberToLetter(51) // AZ\n * numberToLetter(52) // BA\n * numberToLetter(676) // ZA\n * numberToLetter(701) // ZZ\n * numberToLetter(702) // AAA\n */\nexport function numberToLetter(n: number) {\n const digits: number[] = [];\n\n do {\n const v = n % base;\n digits.push(v);\n n = Math.floor(n / base);\n } while (n-- > 0);\n\n const chars: string[] = [];\n while (digits.length) {\n chars.push(alphabet[digits.pop()!]);\n }\n\n return chars.join('');\n}\n"],"mappings":";;;;;;;AAKA,SAAgB,kBAAiD,KAAQ;CAQvE,OAPa,OAAO,KAAK,GACH,CAAC,CAAC,KACG,CAAC,CAAC,QAAQ,KAAK,QAAQ;EAChD,IAAI,OAAkB,IAAI;EAC1B,OAAO;CACT,GAAG,CAAC,CAEW;AACjB;;;;;;;;;;;;;;ACHA,SAAgB,eAAe,SAA0B;CACvD,IAAI,OAAO,YAAY,YAAY,CAAC,OAAO,MAAM,CAAC,OAAO,GACvD,OAAO,CAAC;CAGV,IAAI,IAAI;CACR,UAAU,QAAQ,YAAY;CAC9B,KAAK,IAAI,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAClC,IAAI,QAAQ,EAAE,CAAC,WAAW,CAAC,IAAI,KAAK,IAAI;CAG1C,OAAO,KAAK,IAAI,GAAG,IAAI,CAAC;AAC1B;;;;AAKA,MAAM,WAAW;AACjB,MAAM,OAAO;;;;;;;;;;;AAWb,SAAgB,eAAe,GAAW;CACxC,MAAM,SAAmB,CAAC;CAE1B,GAAG;EACD,MAAM,IAAI,IAAI;EACd,OAAO,KAAK,CAAC;EACb,IAAI,KAAK,MAAM,IAAI,IAAI;CACzB,SAAS,MAAM;CAEf,MAAM,QAAkB,CAAC;CACzB,OAAO,OAAO,QACZ,MAAM,KAAK,SAAS,OAAO,IAAI,EAAG;CAGpC,OAAO,MAAM,KAAK,EAAE;AACtB"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as configName } from "./config-
|
|
1
|
+
import { t as configName } from "./config-7HzSuDvU.mjs";
|
|
2
2
|
import { n as createLogger } from "./cli.mjs";
|
|
3
3
|
import path from "path";
|
|
4
4
|
import fs from "node:fs/promises";
|
|
@@ -8,7 +8,6 @@ const tpl = `\
|
|
|
8
8
|
import { defineConfig } from "@dune2/cli";
|
|
9
9
|
|
|
10
10
|
export default defineConfig({
|
|
11
|
-
i18n: [],
|
|
12
11
|
api: [],
|
|
13
12
|
});`;
|
|
14
13
|
const initConfig = async () => {
|
|
@@ -24,4 +23,4 @@ const initConfig = async () => {
|
|
|
24
23
|
//#endregion
|
|
25
24
|
export { initConfig };
|
|
26
25
|
|
|
27
|
-
//# sourceMappingURL=initConfig-
|
|
26
|
+
//# sourceMappingURL=initConfig-BwaePXNS.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initConfig-BwaePXNS.mjs","names":[],"sources":["../src/commands/initConfig.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'path';\nimport { createLogger } from '../shared';\nimport { configName } from '../shared/config';\n\nconst log = createLogger('initConfig');\n\nconst tpl = `\\\nimport { defineConfig } from \"@dune2/cli\";\n\nexport default defineConfig({\n api: [],\n});`;\n\nexport const initConfig = async () => {\n const configPath = path.join(process.cwd(), configName);\n log.info(`config file path: ${configPath}`);\n if (\n await fs\n .access(configPath)\n .then(() => true)\n .catch(() => false)\n ) {\n log.info(`config file already exists, skip`);\n return;\n }\n await fs.writeFile(configPath, tpl);\n log.info(`config file created`);\n};\n"],"mappings":";;;;;AAKA,MAAM,MAAM,aAAa,YAAY;AAErC,MAAM,MAAM;;;;;;AAOZ,MAAa,aAAa,YAAY;CACpC,MAAM,aAAa,KAAK,KAAK,QAAQ,IAAI,GAAG,UAAU;CACtD,IAAI,KAAK,qBAAqB,YAAY;CAC1C,IACE,MAAM,GACH,OAAO,UAAU,CAAC,CAClB,WAAW,IAAI,CAAC,CAChB,YAAY,KAAK,GACpB;EACA,IAAI,KAAK,kCAAkC;EAC3C;CACF;CACA,MAAM,GAAG,UAAU,YAAY,GAAG;CAClC,IAAI,KAAK,qBAAqB;AAChC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interactive-
|
|
1
|
+
{"version":3,"file":"interactive-zbYM7FbL.mjs","names":[],"sources":["../src/commands/interactive.ts"],"sourcesContent":["import enquirer from 'enquirer';\nimport { cli, createLogger } from '../shared';\nconst { prompt } = enquirer;\n\nconst log = createLogger('interactive');\n\nexport const interactive = async (args: any) => {\n const commands = cli.commands.filter((command) => {\n if (command.name) {\n return !command.name.startsWith('@@') && command.name !== 'interactive';\n }\n return false;\n });\n\n const commandMap = new Map<string, (typeof commands)[number]>();\n const res = await prompt<{ command: string }>({\n type: 'autocomplete',\n name: 'command',\n message: '选择要执行的命令:',\n choices: commands.map((command) => {\n commandMap.set(command.name, command);\n return {\n name: command.name,\n value: command.name,\n message: command.description,\n hint: `等同命令 ${cli.name} ${command.name}`,\n };\n }),\n });\n const command = commandMap.get(res.command);\n if (!command) {\n log.error('未找到命令 %s', res.command);\n return;\n }\n command.commandAction?.apply(cli, args);\n};\n"],"mappings":";;;AAEA,MAAM,EAAE,WAAW;AAEnB,MAAM,MAAM,aAAa,aAAa;AAEtC,MAAa,cAAc,OAAO,SAAc;CAC9C,MAAM,WAAW,IAAI,SAAS,QAAQ,YAAY;EAChD,IAAI,QAAQ,MACV,OAAO,CAAC,QAAQ,KAAK,WAAW,IAAI,KAAK,QAAQ,SAAS;EAE5D,OAAO;CACT,CAAC;CAED,MAAM,6BAAa,IAAI,IAAuC;CAC9D,MAAM,MAAM,MAAM,OAA4B;EAC5C,MAAM;EACN,MAAM;EACN,SAAS;EACT,SAAS,SAAS,KAAK,YAAY;GACjC,WAAW,IAAI,QAAQ,MAAM,OAAO;GACpC,OAAO;IACL,MAAM,QAAQ;IACd,OAAO,QAAQ;IACf,SAAS,QAAQ;IACjB,MAAM,QAAQ,IAAI,KAAK,GAAG,QAAQ;GACpC;EACF,CAAC;CACH,CAAC;CACD,MAAM,UAAU,WAAW,IAAI,IAAI,OAAO;CAC1C,IAAI,CAAC,SAAS;EACZ,IAAI,MAAM,YAAY,IAAI,OAAO;EACjC;CACF;CACA,QAAQ,eAAe,MAAM,KAAK,IAAI;AACxC"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { n as Config, t as ApiConfig } from "./types-
|
|
2
|
-
|
|
1
|
+
import { n as Config, t as ApiConfig } from "./types-zWblMo92.mjs";
|
|
3
2
|
//#region src/shared/config/normalizeConfig.d.ts
|
|
4
3
|
declare function normalizeConfig(config: Config): Config;
|
|
5
4
|
declare function apiConfigNormalizer(item: ApiConfig): ApiConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalizeConfig.mjs","names":[],"sources":["../src/shared/config/normalizeConfig.ts"],"sourcesContent":["import path from 'path';\nimport { ApiConfig, Config } from './types';\nexport function normalizeConfig(config: Config): Config {\n config.cwd ??= process.cwd();\n config.cacheDir ??= path.join(config.cwd, 'node_modules/.cache/dune-cli');\n\n //#region api 配置标准化\n config.api ??= [];\n config.api = config.api.map(apiConfigNormalizer);\n //#endregion\n return config;\n}\nexport function apiConfigNormalizer(item: ApiConfig) {\n item.output ??= './src/apis';\n item.RequestBuilderImportPath ??= `import { RequestBuilder } from '@dune2/tools/rq';`;\n item.enableTs ??= true;\n item.enabled ??= true;\n item.codeFormatterCmd ??= 'oxfmt';\n item.responseSchemaTransformer ??= (schema) =>\n schema.properties?.data ?? schema;\n return item;\n}\n"],"mappings":";;AAEA,SAAgB,gBAAgB,QAAwB;
|
|
1
|
+
{"version":3,"file":"normalizeConfig.mjs","names":[],"sources":["../src/shared/config/normalizeConfig.ts"],"sourcesContent":["import path from 'path';\nimport { ApiConfig, Config } from './types';\nexport function normalizeConfig(config: Config): Config {\n config.cwd ??= process.cwd();\n config.cacheDir ??= path.join(config.cwd, 'node_modules/.cache/dune-cli');\n\n //#region api 配置标准化\n config.api ??= [];\n config.api = config.api.map(apiConfigNormalizer);\n //#endregion\n return config;\n}\nexport function apiConfigNormalizer(item: ApiConfig) {\n item.output ??= './src/apis';\n item.RequestBuilderImportPath ??= `import { RequestBuilder } from '@dune2/tools/rq';`;\n item.enableTs ??= true;\n item.enabled ??= true;\n item.codeFormatterCmd ??= 'oxfmt';\n item.responseSchemaTransformer ??= (schema) =>\n schema.properties?.data ?? schema;\n return item;\n}\n"],"mappings":";;AAEA,SAAgB,gBAAgB,QAAwB;CACtD,OAAO,QAAQ,QAAQ,IAAI;CAC3B,OAAO,aAAa,KAAK,KAAK,OAAO,KAAK,8BAA8B;CAGxE,OAAO,QAAQ,CAAC;CAChB,OAAO,MAAM,OAAO,IAAI,IAAI,mBAAmB;CAE/C,OAAO;AACT;AACA,SAAgB,oBAAoB,MAAiB;CACnD,KAAK,WAAW;CAChB,KAAK,6BAA6B;CAClC,KAAK,aAAa;CAClB,KAAK,YAAY;CACjB,KAAK,qBAAqB;CAC1B,KAAK,+BAA+B,WAClC,OAAO,YAAY,QAAQ;CAC7B,OAAO;AACT"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import SwaggerParser from "@apidevtools/swagger-parser";
|
|
2
|
-
|
|
3
2
|
//#region ../../node_modules/.pnpm/openapi-types@12.1.3/node_modules/openapi-types/dist/index.d.ts
|
|
4
3
|
declare namespace OpenAPIV3 {
|
|
5
4
|
interface Document<T extends {} = {}> {
|
|
@@ -62,7 +61,7 @@ declare namespace OpenAPIV3 {
|
|
|
62
61
|
description?: string;
|
|
63
62
|
servers?: ServerObject[];
|
|
64
63
|
parameters?: (ReferenceObject | ParameterObject)[];
|
|
65
|
-
} & { [method in HttpMethods]?: OperationObject<T
|
|
64
|
+
} & { [method in HttpMethods]?: OperationObject<T>; };
|
|
66
65
|
type OperationObject<T extends {} = {}> = {
|
|
67
66
|
tags?: string[];
|
|
68
67
|
summary?: string;
|
|
@@ -386,4 +385,4 @@ interface Config {
|
|
|
386
385
|
}
|
|
387
386
|
//#endregion
|
|
388
387
|
export { Config as n, ApiConfig as t };
|
|
389
|
-
//# sourceMappingURL=types-
|
|
388
|
+
//# sourceMappingURL=types-zWblMo92.d.mts.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dune2/cli",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.8",
|
|
4
4
|
"repository": {
|
|
5
5
|
"type": "git",
|
|
6
6
|
"url": "https://github.com/liaoyinglong/next-tools.git",
|
|
@@ -34,19 +34,19 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@apidevtools/swagger-parser": "^12.1.0",
|
|
37
|
+
"@fumari/json-schema-ts": "^1.0.2",
|
|
37
38
|
"cac": "^7.0.0",
|
|
38
39
|
"debug": "^4.4.3",
|
|
39
40
|
"enquirer": "^2.3.6",
|
|
40
|
-
"es-toolkit": "^1.
|
|
41
|
+
"es-toolkit": "^1.50.0",
|
|
41
42
|
"jiti": "^2.6.1",
|
|
42
|
-
"json-schema-to-typescript": "15.0.3",
|
|
43
43
|
"p-map": "^7.0.4"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@types/debug": "^4.1.7",
|
|
47
47
|
"@types/node": "^25",
|
|
48
48
|
"openapi-types": "^12.0.2",
|
|
49
|
-
"tsdown": "^0.
|
|
49
|
+
"tsdown": "^0.22.14"
|
|
50
50
|
},
|
|
51
51
|
"scripts": {
|
|
52
52
|
"build": "tsdown --splitting --clean",
|
package/readme.md
CHANGED
|
@@ -44,7 +44,6 @@ Commands:
|
|
|
44
44
|
import { defineConfig } from '@dune2/cli';
|
|
45
45
|
|
|
46
46
|
export default defineConfig({
|
|
47
|
-
i18n: [],
|
|
48
47
|
api: [],
|
|
49
48
|
});
|
|
50
49
|
```
|
|
@@ -62,4 +61,3 @@ export default defineConfig({
|
|
|
62
61
|
工具会在项目根目录查找 `dune.config.ts` 配置文件,支持:
|
|
63
62
|
|
|
64
63
|
- API 配置:Swagger 文档路径、输出目录等
|
|
65
|
-
- 国际化配置:多语言支持相关配置
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generateApi-QJcMk9Aw.mjs","names":[],"sources":["../src/shared/promptConfigEnable.ts","../src/commands/generateApi/index.ts"],"sourcesContent":["import enquirer from 'enquirer';\nimport { ApiConfig } from './config';\nconst { prompt } = enquirer;\n\ninterface Opt<T> {\n configArr: (T & { enabled?: boolean })[];\n getChoiceItem: (item: T) => {\n name: string;\n message?: string;\n value?: string;\n hint?: string;\n };\n checkIsEnabled: (enabledArr: string[], item: T) => boolean;\n}\n\nexport async function promptConfigEnable<T>(opt: Opt<T>) {\n const { configArr, getChoiceItem } = opt;\n // 只有一条配置的时候不用选择\n if (configArr.length <= 1) {\n return configArr;\n }\n\n const choices = [\n {\n name: '全部',\n message: '全部',\n choices: configArr.map((item) => {\n return getChoiceItem(item);\n }),\n },\n ];\n const res = await prompt<{ enabled: string[] }>({\n type: 'multiselect',\n message: '选择要生效的配置项',\n // @ts-ignore\n hint: '(空格选中,回车确认)',\n name: 'enabled',\n validate(value) {\n return value.length === 0 ? `至少选择一项` : true;\n },\n choices,\n });\n\n configArr.forEach((item) => {\n item.enabled = opt.checkIsEnabled(res.enabled, item);\n });\n\n return configArr.filter((c) => c.enabled);\n}\n\nexport function promptApiConfigEnable(configArr: ApiConfig[] | undefined) {\n return promptConfigEnable({\n configArr: configArr ?? [],\n getChoiceItem: (item) => {\n return {\n name: item.output!,\n hint: `swaggerJSONPath: ${item.swaggerJSONPath}`,\n };\n },\n checkIsEnabled: (enabledArr, item) => {\n return enabledArr.includes(item.output!);\n },\n });\n}\n","import { AsyncLocalStorage } from 'node:async_hooks';\nimport { spawn } from 'node:child_process';\nimport fs from 'node:fs/promises';\nimport * as os from 'os';\nimport path from 'path';\nimport SwaggerParser from '@apidevtools/swagger-parser';\nimport { camelCase, isPlainObject, merge } from 'es-toolkit';\nimport { compile } from 'json-schema-to-typescript';\nimport type { OpenAPIV2, OpenAPIV3 } from 'openapi-types';\nimport pMap from 'p-map';\nimport { createLogger } from '../../shared';\nimport { ApiConfig, getConfig } from '../../shared/config';\nimport { promptApiConfigEnable } from '../../shared/promptConfigEnable';\n\nconst log = createLogger('generateApi');\n\ntype ParsedDocument = OpenAPIV2.Document | OpenAPIV3.Document;\n\nexport const asyncLocalStorage = new AsyncLocalStorage<{\n parsed: ParsedDocument;\n parser: SwaggerParser;\n}>();\n\nconst HTTP_METHODS = ['get', 'put', 'post', 'delete', 'patch'] as const;\nconst DEFAULT_FETCH_TIMEOUT = 30_000;\nconst FORMATTER_ARGUMENT_PATTERN = /\"([^\"]*)\"|'([^']*)'|(\\S+)/g;\n\nfunction getCodegenConcurrency() {\n const parallelism =\n typeof os.availableParallelism === 'function'\n ? os.availableParallelism()\n : os.cpus().length;\n return Math.max(1, parallelism - 1);\n}\n\nfunction isPathInside(parent: string, child: string) {\n const relative = path.relative(parent, child);\n return !!relative && !relative.startsWith('..') && !path.isAbsolute(relative);\n}\n\nexport function resolveOutputDir(cwd: string, output: string) {\n const resolvedCwd = path.resolve(cwd);\n const resolvedOutput = path.resolve(resolvedCwd, output);\n if (!isPathInside(resolvedCwd, resolvedOutput)) {\n throw new Error(`output must be inside cwd: ${output}`);\n }\n return resolvedOutput;\n}\n\nfunction sanitizeOutputSegment(segment: string) {\n const sanitized = segment.replace(/[<>:\"\\\\|?*\\u0000-\\u001F]/g, '_');\n return sanitized === '.' || sanitized === '..' || sanitized.length === 0\n ? '_'\n : sanitized;\n}\n\nexport function resolveOperationOutputPath(options: {\n outputDir: string;\n url: string;\n method: string;\n enableTs?: boolean;\n}) {\n const outputDir = path.resolve(options.outputDir);\n const urlSegments = options.url\n .split('/')\n .filter(Boolean)\n .map(sanitizeOutputSegment);\n const fileName = `${sanitizeOutputSegment(options.method)}.${\n options.enableTs === false ? 'js' : 'ts'\n }`;\n const outputPath = path.resolve(outputDir, ...urlSegments, fileName);\n if (!isPathInside(outputDir, outputPath)) {\n throw new Error(`operation output escaped output dir: ${options.url}`);\n }\n return outputPath;\n}\n\nfunction parseFormatterCommand(command: string) {\n const args = [...command.matchAll(FORMATTER_ARGUMENT_PATTERN)]\n .map((match) => match[1] ?? match[2] ?? match[3] ?? '')\n .filter(Boolean);\n const [file, ...rest] = args;\n if (!file) {\n throw new Error('codeFormatterCmd is empty');\n }\n return { file, args: rest };\n}\n\nasync function runFormatter(command: string, outputDir: string) {\n const { file, args } = parseFormatterCommand(command);\n await new Promise<void>((resolve, reject) => {\n const child = spawn(file, [...args, outputDir], {\n shell: false,\n stdio: 'inherit',\n });\n child.on('error', reject);\n child.on('exit', (code, signal) => {\n if (code === 0) {\n resolve();\n return;\n }\n reject(\n new Error(\n signal\n ? `formatter exited with signal ${signal}`\n : `formatter exited with code ${code}`,\n ),\n );\n });\n });\n}\n\nfunction getHttpTimeout(options: SwaggerParser.Options) {\n const http = options.resolve?.http;\n if (http && typeof http === 'object' && 'timeout' in http) {\n return typeof http.timeout === 'number'\n ? http.timeout\n : DEFAULT_FETCH_TIMEOUT;\n }\n return DEFAULT_FETCH_TIMEOUT;\n}\n\nfunction isJsonContentType(contentType: string) {\n const mediaType = contentType.split(';', 1)[0].trim().toLowerCase();\n return (\n mediaType === 'application/json' ||\n mediaType === '*/*' ||\n mediaType.endsWith('/json') ||\n mediaType.endsWith('+json')\n );\n}\n\nfunction pickJsonMedia(\n content: Record<string, OpenAPIV3.MediaTypeObject> | undefined,\n) {\n if (!content) return undefined;\n return (\n content['application/json'] ??\n content['*/*'] ??\n Object.entries(content).find(([contentType]) =>\n isJsonContentType(contentType),\n )?.[1]\n );\n}\n\nfunction getRequestBodySchema(\n requestBody:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.RequestBodyObject\n | undefined,\n) {\n if (!requestBody) return undefined;\n if ('$ref' in requestBody) return requestBody;\n return pickJsonMedia(requestBody.content)?.schema;\n}\n\nfunction pickSuccessResponse(responses: OpenAPIV3.ResponsesObject) {\n return responses['200'];\n}\n\nfunction isParsedDocument(value: unknown): value is ParsedDocument {\n return (\n !!value &&\n typeof value === 'object' &&\n ('paths' in value || 'openapi' in value || 'swagger' in value)\n );\n}\n\nasync function fetchRemoteDocument(\n url: string,\n options: SwaggerParser.Options,\n): Promise<ParsedDocument> {\n const res = await fetch(url, {\n signal: AbortSignal.timeout(getHttpTimeout(options)),\n });\n if (!res.ok) {\n throw new Error(`HTTP ${res.status} ${res.statusText}`);\n }\n const json = await res.json();\n if (!isParsedDocument(json)) {\n throw new Error(`Remote OpenAPI document is invalid: ${url}`);\n }\n return json;\n}\n\n/**\n * 只收集 rootSchema 里真正引用到的 `$ref`(含传递依赖),\n * 构造一个最小化的定义上下文。\n *\n * 之前是把整个 components/definitions 直接挂到每个待编译的 schema 上,\n * 导致 json-schema-to-typescript 每次 compile 都要遍历整份 API 的类型图,\n * 261 个接口 × 2(Req/Res)= 522 次全量遍历,非常慢。\n * 这里改为按需收集可达定义,输出结果不变,但速度大幅提升。\n */\nfunction buildRefContext(\n rootSchema: unknown,\n parsed: ParsedDocument | undefined,\n): Record<string, unknown> {\n const context: Record<string, unknown> = {};\n if (!parsed || !rootSchema || typeof rootSchema !== 'object') {\n return context;\n }\n\n const seen = new Set<string>();\n const queue: string[] = [];\n\n const collectRefs = (obj: unknown) => {\n if (!obj || typeof obj !== 'object') return;\n if (Array.isArray(obj)) {\n obj.forEach(collectRefs);\n return;\n }\n for (const [key, value] of Object.entries(obj)) {\n if (\n key === '$ref' &&\n typeof value === 'string' &&\n value.startsWith('#/')\n ) {\n queue.push(value);\n } else {\n collectRefs(value);\n }\n }\n };\n\n const decodeSegment = (segment: string) =>\n segment.replace(/~1/g, '/').replace(/~0/g, '~');\n\n const resolvePointer = (ref: string) => {\n const parts = ref.slice(2).split('/').map(decodeSegment);\n let cur: unknown = parsed;\n for (const part of parts) {\n if (!cur || typeof cur !== 'object') return undefined;\n cur = (cur as Record<string, unknown>)[part];\n }\n return cur === undefined ? undefined : { parts, value: cur };\n };\n\n const setPointer = (parts: string[], value: unknown) => {\n let cur = context;\n for (let i = 0; i < parts.length - 1; i++) {\n const part = parts[i];\n if (!cur[part] || typeof cur[part] !== 'object') {\n cur[part] = {};\n }\n cur = cur[part] as Record<string, unknown>;\n }\n cur[parts[parts.length - 1]] = value;\n };\n\n collectRefs(rootSchema);\n while (queue.length) {\n const ref = queue.shift()!;\n if (seen.has(ref)) continue;\n seen.add(ref);\n const resolved = resolvePointer(ref);\n if (!resolved) continue;\n setPointer(resolved.parts, resolved.value);\n collectRefs(resolved.value);\n }\n\n return context;\n}\n\nfunction stripDefaultKeywordDeep(value: unknown) {\n if (!value || typeof value !== 'object') {\n return;\n }\n\n if (Array.isArray(value)) {\n value.forEach((item) => stripDefaultKeywordDeep(item));\n return;\n }\n\n const record = value as Record<string, unknown>;\n if ('default' in record) {\n delete record.default;\n }\n\n Object.values(record).forEach((item) => stripDefaultKeywordDeep(item));\n}\n\nexport async function generateApi() {\n const config = await getConfig();\n const selectedConfigs = await promptApiConfigEnable(config.api);\n const apiConfigs = selectedConfigs.filter((apiConfig) => {\n if (!apiConfig.output) {\n log.error('配置 %s 缺少 output,已跳过', apiConfig.swaggerJSONPath);\n return false;\n }\n return true;\n });\n const skippedConfigCount = selectedConfigs.length - apiConfigs.length;\n\n if (skippedConfigCount > 0) {\n log.info('由于缺少 output,跳过 %d 个配置', skippedConfigCount);\n }\n\n if (!apiConfigs.length) {\n log.info('没有需要生成的 API 配置,生成流程结束');\n return;\n }\n\n log.info('本次将生成 %d 个 API 配置', apiConfigs.length);\n\n let totalSuccessCount = 0;\n let totalFailedCount = 0;\n const startedAt = Date.now();\n\n const preparedConfigs: ApiConfig[] = [];\n const cwd = config.cwd ?? process.cwd();\n\n for (const apiConfig of apiConfigs) {\n log.info('开始初始化输出目录 %s', apiConfig.output);\n const prepareStartedAt = Date.now();\n try {\n const outputDir = resolveOutputDir(cwd, apiConfig.output!);\n await fs.rm(outputDir, { recursive: true, force: true });\n await fs.mkdir(outputDir, { recursive: true });\n preparedConfigs.push({\n ...apiConfig,\n output: outputDir,\n });\n log.info(\n '输出目录 %s 初始化完成,耗时 %dms',\n apiConfig.output,\n Date.now() - prepareStartedAt,\n );\n } catch (error) {\n totalFailedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error('初始化输出目录 %s 失败:%s', apiConfig.output, message);\n }\n }\n\n if (!preparedConfigs.length) {\n log.error('所有配置都初始化失败,生成流程结束');\n log.info(\n 'generateApi Done,成功 %d 个,失败 %d 个,总耗时 %dms',\n totalSuccessCount,\n totalFailedCount,\n Date.now() - startedAt,\n );\n return;\n }\n\n for (const apiConfig of preparedConfigs) {\n log.info('开始解析 %s', apiConfig.swaggerJSONPath);\n const dereferenceConfig: SwaggerParser.Options = merge(\n {\n resolve: {\n http: {\n timeout: DEFAULT_FETCH_TIMEOUT,\n },\n },\n } satisfies SwaggerParser.Options,\n apiConfig.dereferenceSwaggerConfig || {},\n );\n const parser = new SwaggerParser();\n const bundleStartedAt = Date.now();\n\n let parsed: unknown;\n try {\n // swagger-parser's built-in HTTP resolver fails on remote URLs,\n // so we fetch the JSON ourselves and pass the parsed object instead.\n const isRemoteUrl = /^https?:\\/\\//.test(apiConfig.swaggerJSONPath);\n const bundleInput = isRemoteUrl\n ? await fetchRemoteDocument(\n apiConfig.swaggerJSONPath,\n dereferenceConfig,\n )\n : apiConfig.swaggerJSONPath;\n parsed = await parser.bundle(bundleInput, dereferenceConfig);\n // default 值经常和 type 不一致(例如 integer + \"\"),\n // 会被 json-schema-to-typescript 推断成交叉类型(number & string)。\n // 生成前统一移除 default,避免污染类型。\n stripDefaultKeywordDeep(parsed);\n log.info(\n '解析 %s 成功,耗时 %dms',\n apiConfig.swaggerJSONPath,\n Date.now() - bundleStartedAt,\n );\n } catch (error) {\n totalFailedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error('解析 %s 失败:%s', apiConfig.swaggerJSONPath, message);\n continue;\n }\n\n const state = {\n // only support v3\n parsed: parsed as OpenAPIV3.Document,\n parser,\n };\n\n let generatedCount = 0;\n let skippedCount = 0;\n const pathEntries = Object.entries(\n (parsed as OpenAPIV3.Document).paths ?? {},\n );\n if (!pathEntries.length) {\n log.error('%s 中没有可用的 paths,已跳过', apiConfig.swaggerJSONPath);\n totalFailedCount++;\n continue;\n }\n\n const codegenConcurrency = getCodegenConcurrency();\n\n await asyncLocalStorage.run(state, async () => {\n await pMap(\n pathEntries,\n async ([url, pathItemObject]) => {\n if (!pathItemObject) {\n log.error('路径 %s 未定义 pathItemObject,已跳过', url);\n skippedCount++;\n return;\n }\n\n log.info('开始生成 %s', url);\n let generatedForUrl = 0;\n await pMap(\n HTTP_METHODS,\n async (method) => {\n const operationObject = pathItemObject[method];\n if (!operationObject) {\n return;\n }\n\n try {\n const code = await generateApiRequestCode({\n url: url,\n method: method,\n operationObject: operationObject,\n apiConfig,\n });\n const outputPath = resolveOperationOutputPath({\n outputDir: apiConfig.output!,\n url,\n method,\n enableTs: apiConfig.enableTs,\n });\n await fs.mkdir(path.dirname(outputPath), {\n recursive: true,\n });\n await fs.writeFile(outputPath, code);\n generatedCount++;\n generatedForUrl++;\n } catch (error) {\n skippedCount++;\n const message =\n error instanceof Error ? error.message : String(error);\n log.error(\n '%s %s 生成失败:%s',\n method.toUpperCase(),\n url,\n message,\n );\n }\n },\n { concurrency: 1 },\n );\n if (generatedForUrl === 0) {\n log.info('路径 %s 未生成任何方法', url);\n }\n },\n { concurrency: codegenConcurrency },\n );\n });\n\n if (!generatedCount) {\n log.error('%s 未生成任何请求,已标记失败', apiConfig.swaggerJSONPath);\n totalFailedCount++;\n continue;\n }\n\n if (apiConfig.codeFormatterCmd) {\n try {\n await runFormatter(apiConfig.codeFormatterCmd, apiConfig.output!);\n log.info(`Code formatting success`);\n } catch (error) {\n skippedCount++;\n const message = error instanceof Error ? error.message : String(error);\n log.error(`Code formatting failed: ${message}`);\n }\n }\n\n log.info(\n '%s 生成完成,共生成 %d 个请求,跳过 %d 个',\n apiConfig.swaggerJSONPath,\n generatedCount,\n skippedCount,\n );\n totalSuccessCount++;\n }\n\n log.info(\n 'generateApi Done,成功 %d 个,失败 %d 个,总耗时 %dms',\n totalSuccessCount,\n totalFailedCount,\n Date.now() - startedAt,\n );\n}\n\n/**\n * 根据请求方法,生成请求代码\n */\nexport async function generateApiRequestCode(options: {\n url: string;\n method: string;\n operationObject: OpenAPIV3.OperationObject;\n apiConfig: ApiConfig;\n}): Promise<string> {\n const { method, operationObject, apiConfig } = options;\n\n const url = (() => {\n if (typeof apiConfig.urlTransformer === 'string') {\n return `${apiConfig.urlTransformer}${options.url}`;\n }\n if (typeof apiConfig.urlTransformer === 'function') {\n return apiConfig.urlTransformer(options.url);\n }\n return options.url;\n })();\n\n const seeUrl = apiConfig.swaggerUiUrl\n ? `${apiConfig.swaggerUiUrl}#/${encodeURIComponent(\n `${operationObject.tags?.join('/') ?? ''}/${\n operationObject.operationId\n }`,\n )}`\n : '';\n\n // 生成的请求构造器的名称,需要使用原始 url\n let requestBuilderName = camelCase(`${options.url}_${method}_api`);\n\n // 判断是否有效的 js 变量\n if (!/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(requestBuilderName)) {\n // 不是有效的 js 变量,使用 _ + 数字\n requestBuilderName = `_${requestBuilderName}`;\n }\n\n //#region url 上参数 例如 /api/v1/users/{userId}\n const urlPathParams = getUrlPathParams(\n (operationObject.parameters as never) ?? [],\n );\n const urlPathParamsCode = urlPathParams.length\n ? `urlPathParams: ${JSON.stringify(urlPathParams)},`\n : '';\n //#endregion\n\n let code: string[] = [\n '// do not edit this file manually, it will be overwritten by @dune2/cli',\n apiConfig.RequestBuilderImportPath!,\n apiConfig.queryClientImportPath!,\n\n '/**',\n ` * ${operationObject.summary}`,\n ` * @tags ${operationObject.tags?.join(',')}`,\n seeUrl && ` * @see ${seeUrl}`,\n ` */`,\n ].filter(Boolean);\n\n // builder 代码\n let builderCode = `\\\nexport const ${requestBuilderName} = new RequestBuilder({\n url: '${url}',\n method: '${method}',\n ${urlPathParamsCode}\n ${apiConfig.queryClientImportPath ? 'queryClient,' : ''}\n});`\n // 移除空行\n .replace(/,\\n\\s*}/, ',' + os.EOL + '}');\n if (apiConfig.enableTs) {\n builderCode = builderCode.replace(\n 'new RequestBuilder(',\n `new RequestBuilder<${requestBuilderName}.Req, ${requestBuilderName}.Res>(`,\n );\n }\n code.push(builderCode);\n\n if (apiConfig.enableTs) {\n const [requestParamsTypeCode, responseParamsTypeCode] = await Promise.all([\n // 请求参数类型\n compileRequestParams(operationObject),\n // 响应参数类型\n compileResponseParams(operationObject, apiConfig),\n ]);\n\n code.push(`\nexport namespace ${requestBuilderName} {\n ${requestParamsTypeCode.code}\n \n ${responseParamsTypeCode}\n};`);\n }\n\n return code.join(os.EOL);\n}\n\nfunction getUrlPathParams(parameters: OpenAPIV3.ParameterObject[]) {\n return parameters\n .filter((item) => item.in === 'path')\n .map((item) => item.name);\n}\n\n/**\n * 这个方法还不完善,只能处理简单的请求参数\n */\nasync function compileRequestParams(\n operationObject: OpenAPIV3.OperationObject,\n) {\n const store = asyncLocalStorage.getStore();\n const requestBodySchemaOrRef = getRequestBodySchema(\n operationObject.requestBody,\n );\n\n const parameterSchema = (() => {\n if (!operationObject.parameters) {\n return;\n }\n const extraProperties = {};\n const parameters: OpenAPIV3.ParameterObject[] = [];\n (operationObject.parameters as OpenAPIV3.ParameterObject[]).forEach(\n (item) => {\n if (!['query', 'path'].includes(item.in)) {\n return;\n }\n if (\n item.schema &&\n 'type' in item.schema &&\n item.schema.type === 'object'\n ) {\n // swagger get 请求上 有些参数是 object 类型 应该拍平\n Object.assign(\n extraProperties,\n (item.schema as OpenAPIV3.SchemaObject).properties || {},\n );\n } else {\n parameters.push(item);\n }\n },\n );\n // 必填参数中忽略 分页相关的参数\n const required = parameters\n .filter(\n (p) => p.required && !['pageNum', 'pageSize', 'count'].includes(p.name),\n )\n .map((p) => p.name);\n const properties = Object.fromEntries(\n parameters\n // 后端 swagger 可能出现没有 schema 的情况,这里过滤掉\n .filter((p) => !!p.schema)\n .map((p) => {\n const schema = p.schema;\n return [\n p.name,\n {\n ...schema,\n description: p.description,\n // enum: schema.enum ?? [],\n },\n ];\n }),\n );\n return {\n required,\n type: 'object',\n properties: { ...properties, ...extraProperties },\n } satisfies OpenAPIV3.SchemaObject;\n })();\n\n const requestBodySchema = isPlainObject(requestBodySchemaOrRef)\n ? '$ref' in requestBodySchemaOrRef\n ? (store?.parser.$refs.get(\n requestBodySchemaOrRef.$ref,\n ) as OpenAPIV3.SchemaObject)\n : requestBodySchemaOrRef\n : void 0;\n\n const schemaObject =\n requestBodySchema && parameterSchema\n ? ({\n ...requestBodySchema,\n type: 'object',\n required: [\n ...new Set([\n ...(requestBodySchema.required || []),\n ...(parameterSchema.required || []),\n ]),\n ],\n properties: {\n ...(requestBodySchema.properties || {}),\n ...(parameterSchema.properties || {}),\n },\n } satisfies OpenAPIV3.SchemaObject)\n : requestBodySchema || parameterSchema;\n\n if (schemaObject) {\n stripDefaultKeywordDeep(schemaObject);\n }\n\n const finalSchema = schemaObject\n ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject)\n : void 0;\n\n let code = '';\n if (finalSchema) {\n try {\n code = await compile(finalSchema as never, 'Req', {\n bannerComment: '',\n ignoreMinAndMaxItems: !!1,\n additionalProperties: false,\n unknownAny: false,\n // 生成完成后会统一用 codeFormatterCmd 格式化,\n // 这里关闭内置 prettier,避免每个类型都跑一次格式化拖慢速度。\n format: false,\n });\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n log.error('生成请求参数类型失败,请检查 %o', {\n summary: operationObject.summary,\n message,\n operationId: operationObject.operationId,\n });\n }\n }\n\n return {\n code: code || 'export type Req = any;',\n };\n}\n\nasync function compileResponseParams(\n operationObject: OpenAPIV3.OperationObject,\n apiConfig: ApiConfig,\n) {\n const store = asyncLocalStorage.getStore();\n\n function resolveSchema(\n arg:\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.ResponseObject\n | OpenAPIV3.MediaTypeObject\n | undefined,\n ) {\n if (!arg) return;\n\n if ('content' in arg) {\n return resolveSchema(pickJsonMedia(arg.content)?.schema);\n }\n // 兼容 swagger v2 的 response.schema\n if ('schema' in arg && arg.schema) {\n return resolveSchema(arg.schema as never);\n }\n\n let schema = apiConfig.responseSchemaTransformer!(arg as never) as\n | OpenAPIV3.ReferenceObject\n | OpenAPIV3.SchemaObject;\n if ('$ref' in schema) {\n return resolveSchema(store?.parser.$refs.get(schema.$ref) as never);\n }\n return schema;\n }\n const schemaObject = resolveSchema(\n pickSuccessResponse(operationObject.responses),\n );\n if (schemaObject) {\n stripDefaultKeywordDeep(schemaObject);\n }\n\n const finalSchema = schemaObject\n ? Object.assign(buildRefContext(schemaObject, store?.parsed), schemaObject)\n : void 0;\n\n let code = '';\n if (finalSchema) {\n try {\n code = await compile(finalSchema, 'Res', {\n bannerComment: '',\n ignoreMinAndMaxItems: !!1,\n additionalProperties: false,\n unknownAny: false,\n // 生成完成后会统一用 codeFormatterCmd 格式化,\n // 这里关闭内置 prettier,避免每个类型都跑一次格式化拖慢速度。\n format: false,\n });\n } catch (e) {\n const message = e instanceof Error ? e.message : String(e);\n log.error('转换响应参数类型失败,请检查 %o', {\n summary: operationObject.summary,\n error: message,\n operationId: operationObject.operationId,\n });\n }\n } else {\n log.error('responseSchemaTransformer 返回值为空,请检查');\n }\n\n return code ? code : 'export type Res = any;';\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"initConfig-DCOS9II9.mjs","names":[],"sources":["../src/commands/initConfig.ts"],"sourcesContent":["import fs from 'node:fs/promises';\nimport path from 'path';\nimport { createLogger } from '../shared';\nimport { configName } from '../shared/config';\n\nconst log = createLogger('initConfig');\n\nconst tpl = `\\\nimport { defineConfig } from \"@dune2/cli\";\n\nexport default defineConfig({\n i18n: [],\n api: [],\n});`;\n\nexport const initConfig = async () => {\n const configPath = path.join(process.cwd(), configName);\n log.info(`config file path: ${configPath}`);\n if (\n await fs\n .access(configPath)\n .then(() => true)\n .catch(() => false)\n ) {\n log.info(`config file already exists, skip`);\n return;\n }\n await fs.writeFile(configPath, tpl);\n log.info(`config file created`);\n};\n"],"mappings":";;;;;AAKA,MAAM,MAAM,aAAa,aAAa;AAEtC,MAAM,MAAM;;;;;;;AAQZ,MAAa,aAAa,YAAY;CACpC,MAAM,aAAa,KAAK,KAAK,QAAQ,KAAK,EAAE,WAAW;AACvD,KAAI,KAAK,qBAAqB,aAAa;AAC3C,KACE,MAAM,GACH,OAAO,WAAW,CAClB,WAAW,KAAK,CAChB,YAAY,MAAM,EACrB;AACA,MAAI,KAAK,mCAAmC;AAC5C;;AAEF,OAAM,GAAG,UAAU,YAAY,IAAI;AACnC,KAAI,KAAK,sBAAsB"}
|