@dune2/cli 0.6.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/{chunk-UGSBKD2I.js → chunk-DORNSRHQ.js} +2 -3
  2. package/dist/{chunk-555YTWSW.js → chunk-VS4LDXR3.js} +1 -4
  3. package/dist/chunk-VS4LDXR3.js.map +1 -0
  4. package/dist/{chunk-PRJ3NOXB.js → chunk-YZLVO3MA.js} +2 -2
  5. package/dist/cli.js +6 -46
  6. package/dist/cli.js.map +1 -1
  7. package/dist/{generateApi-6O2YBWTL.js → generateApi-S77LKSZT.js} +93 -33
  8. package/dist/generateApi-S77LKSZT.js.map +1 -0
  9. package/dist/index.d.ts +3 -35
  10. package/dist/index.js +30 -10
  11. package/dist/index.js.map +1 -1
  12. package/dist/{initConfig-5VN3U4OF.js → initConfig-NHHN2HCE.js} +4 -4
  13. package/dist/{interactive-HNOHT33A.js → interactive-BVOA3VKY.js} +2 -2
  14. package/dist/normalizeConfig.d.ts +1 -1
  15. package/dist/normalizeConfig.js +1 -1
  16. package/dist/prettier.cjs.map +1 -1
  17. package/dist/{types-D01zR42f.d.ts → types-CqBxoc6L.d.ts} +0 -12
  18. package/package.json +2 -9
  19. package/readme.md +49 -17
  20. package/dist/auth-777GVVSS.js +0 -8
  21. package/dist/auth-777GVVSS.js.map +0 -1
  22. package/dist/chunk-2SEEW5WZ.js +0 -67
  23. package/dist/chunk-2SEEW5WZ.js.map +0 -1
  24. package/dist/chunk-555YTWSW.js.map +0 -1
  25. package/dist/chunk-6UFZ6KLX.js +0 -124
  26. package/dist/chunk-6UFZ6KLX.js.map +0 -1
  27. package/dist/chunk-ADQ6JLT6.js +0 -196
  28. package/dist/chunk-ADQ6JLT6.js.map +0 -1
  29. package/dist/chunk-IKJLPHF7.js +0 -117
  30. package/dist/chunk-IKJLPHF7.js.map +0 -1
  31. package/dist/chunk-KNC7XY4Z.js +0 -130
  32. package/dist/chunk-KNC7XY4Z.js.map +0 -1
  33. package/dist/chunk-Q7UJ456X.js +0 -24
  34. package/dist/chunk-Q7UJ456X.js.map +0 -1
  35. package/dist/download-KXSMWNXH.js +0 -49
  36. package/dist/download-KXSMWNXH.js.map +0 -1
  37. package/dist/extract-ARNNWYYN.js +0 -113
  38. package/dist/extract-ARNNWYYN.js.map +0 -1
  39. package/dist/generateApi-6O2YBWTL.js.map +0 -1
  40. package/dist/namespace-SAPL3UY6.js +0 -137
  41. package/dist/namespace-SAPL3UY6.js.map +0 -1
  42. package/dist/upload-S43DON7A.js +0 -92
  43. package/dist/upload-S43DON7A.js.map +0 -1
  44. /package/dist/{chunk-UGSBKD2I.js.map → chunk-DORNSRHQ.js.map} +0 -0
  45. /package/dist/{chunk-PRJ3NOXB.js.map → chunk-YZLVO3MA.js.map} +0 -0
  46. /package/dist/{initConfig-5VN3U4OF.js.map → initConfig-NHHN2HCE.js.map} +0 -0
  47. /package/dist/{interactive-HNOHT33A.js.map → interactive-BVOA3VKY.js.map} +0 -0
@@ -1,117 +0,0 @@
1
- import {
2
- googleSheet,
3
- letterToNumber
4
- } from "./chunk-6UFZ6KLX.js";
5
- import {
6
- createLogger
7
- } from "./chunk-UGSBKD2I.js";
8
-
9
- // src/shared/resolveSheetData.ts
10
- var log = createLogger("shared:resolveSheetData");
11
- var SheetI18nItem = class {
12
- constructor(spreadsheetId, range, key, colIndex, row, rowIndex) {
13
- this.spreadsheetId = spreadsheetId;
14
- this.range = range;
15
- this.key = key;
16
- this.row = row;
17
- this.rowIndex = rowIndex;
18
- this.colIndex = letterToNumber(colIndex);
19
- this.value = this.row[this.colIndex] || "";
20
- }
21
- /**
22
- * 尝试更新 单元格的值
23
- * 如果一样则不更新
24
- */
25
- async tryUpdate(newValue) {
26
- if (newValue === this.value) {
27
- return;
28
- }
29
- await googleSheet.updateCell(
30
- this.spreadsheetId,
31
- this.range,
32
- this.colIndex,
33
- this.rowIndex,
34
- newValue
35
- );
36
- }
37
- };
38
- async function resolveSheetData(config) {
39
- const { position } = config;
40
- const parseStartIndex = config.parseStartIndex ?? 2;
41
- log.info(`\u8BFB\u53D6 ${config.sheetRange} sheet\u6570\u636E`);
42
- const res = await googleSheet.get({
43
- spreadsheetId: config.sheetId,
44
- range: config.sheetRange
45
- });
46
- if (!res.data.values) {
47
- log.error(
48
- `${config.sheetRange} sheet\u6570\u636E\u4E3A\u7A7A\uFF0C\u8BF7\u68C0\u67E5\uFF0C\u5E94\u8BE5\u6700\u5C11\u6709\u4E00\u884C\u5934\u90E8\u6570\u636E`
49
- );
50
- return new SheetData(config, 2);
51
- }
52
- const sheetData = new SheetData(config, res.data.values.length + 1);
53
- res.data.values.forEach((row, rowIndex) => {
54
- var _a;
55
- const trulyRowIndex = rowIndex + 1;
56
- if (parseStartIndex > trulyRowIndex) {
57
- return;
58
- }
59
- const i18nKey = row[letterToNumber(position.key)];
60
- if (i18nKey) {
61
- if (sheetData.keySet.has(i18nKey)) {
62
- log.error(
63
- `\u8868\u683C ${config.sheetRange} \u53D1\u73B0\u91CD\u590D\u7684i18nKey: ${i18nKey}, \u5C06\u8986\u76D6\u524D\u9762\u7684\u503C`
64
- );
65
- } else {
66
- sheetData.keySet.add(i18nKey);
67
- }
68
- (_a = config.locales) == null ? void 0 : _a.forEach((lang) => {
69
- sheetData.setI18nItem(
70
- lang,
71
- new SheetI18nItem(
72
- config.sheetId,
73
- config.sheetRange,
74
- i18nKey,
75
- position[lang],
76
- row,
77
- trulyRowIndex
78
- )
79
- );
80
- });
81
- }
82
- });
83
- return sheetData;
84
- }
85
- var SheetData = class {
86
- constructor(config, nextAppendRowIndex) {
87
- this.config = config;
88
- this.nextAppendRowIndex = nextAppendRowIndex;
89
- this.keySet = /* @__PURE__ */ new Set();
90
- this.value = new Map(
91
- this.config.locales.map((lang) => {
92
- return [lang, /* @__PURE__ */ new Map()];
93
- })
94
- );
95
- }
96
- getI18nItem(lang, i18nKey) {
97
- return this.value.get(lang).get(i18nKey);
98
- }
99
- setI18nItem(lang, i18nItem) {
100
- this.value.get(lang).set(i18nItem.key, i18nItem);
101
- }
102
- hasI18nItem(lang, i18nKey) {
103
- return this.value.get(lang).has(i18nKey);
104
- }
105
- getLangDataJSON(lang) {
106
- const res = {};
107
- this.value.get(lang).forEach((i18nItem) => {
108
- res[i18nItem.key] = i18nItem.value;
109
- });
110
- return res;
111
- }
112
- };
113
-
114
- export {
115
- resolveSheetData
116
- };
117
- //# sourceMappingURL=chunk-IKJLPHF7.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/resolveSheetData.ts"],"sourcesContent":["import { I18nConfig } from \"./config\";\nimport { googleSheet } from \"./google/sheet\";\nimport { createLogger } from \"./index\";\nimport { letterToNumber } from \"./letters\";\n\nconst log = createLogger(\"shared:resolveSheetData\");\n\nclass SheetI18nItem {\n value: string;\n\n colIndex: number;\n\n constructor(\n private spreadsheetId: string,\n private range: string,\n public key: string,\n colIndex: number | string,\n public row: string[],\n private rowIndex: number\n ) {\n this.colIndex = letterToNumber(colIndex);\n // TODO: 待确定 无值的key是否要生成\n // value = undefined 即不会生成\n this.value = this.row[this.colIndex] || \"\";\n }\n\n /**\n * 尝试更新 单元格的值\n * 如果一样则不更新\n */\n async tryUpdate(newValue: string) {\n if (newValue === this.value) {\n // 云端的值跟本地一样 不需要同步\n return;\n }\n\n await googleSheet.updateCell(\n this.spreadsheetId,\n this.range,\n this.colIndex,\n this.rowIndex,\n newValue\n );\n }\n}\n\nexport async function resolveSheetData(config: I18nConfig): Promise<SheetData> {\n const { position } = config;\n const parseStartIndex = config.parseStartIndex ?? 2;\n\n log.info(`读取 ${config.sheetRange} sheet数据`);\n\n const res = await googleSheet.get({\n spreadsheetId: config.sheetId,\n range: config.sheetRange,\n });\n if (!res.data.values) {\n log.error(\n `${config.sheetRange} sheet数据为空,请检查,应该最少有一行头部数据`\n );\n return new SheetData(config, 2);\n }\n\n const sheetData = new SheetData(config, res.data.values.length + 1);\n\n res.data.values.forEach((row: string[], rowIndex) => {\n // excel 的开始索引是1,所以要 +1\n const trulyRowIndex = rowIndex + 1;\n if (parseStartIndex > trulyRowIndex) {\n // 还未到可以开始解析的行数\n return;\n }\n\n const i18nKey = row[letterToNumber(position!.key)];\n\n if (i18nKey) {\n if (sheetData.keySet.has(i18nKey)) {\n log.error(\n `表格 ${config.sheetRange} 发现重复的i18nKey: ${i18nKey}, 将覆盖前面的值`\n );\n } else {\n sheetData.keySet.add(i18nKey);\n }\n\n config.locales?.forEach((lang) => {\n sheetData.setI18nItem(\n lang,\n new SheetI18nItem(\n config.sheetId!,\n config.sheetRange!,\n i18nKey,\n position![lang],\n row,\n trulyRowIndex\n )\n );\n });\n }\n });\n\n return sheetData;\n}\n\nexport class SheetData {\n keySet = new Set<string>();\n\n constructor(\n private config: I18nConfig,\n // 当前有多少行 新增的时候往后面添加\n public nextAppendRowIndex: number\n ) {}\n\n private value = new Map(\n this.config.locales!.map((lang) => {\n return [lang, new Map<string, SheetI18nItem>()];\n })\n );\n\n getI18nItem(lang: string, i18nKey: string) {\n return this.value.get(lang)!.get(i18nKey);\n }\n\n setI18nItem(lang: string, i18nItem: SheetI18nItem) {\n this.value.get(lang)!.set(i18nItem.key, i18nItem);\n }\n\n hasI18nItem(lang: string, i18nKey: string) {\n return this.value.get(lang)!.has(i18nKey);\n }\n\n getLangDataJSON(lang: string) {\n const res = {} as Record<string, string>;\n this.value.get(lang)!.forEach((i18nItem) => {\n res[i18nItem.key] = i18nItem.value;\n });\n return res;\n }\n}\n"],"mappings":";;;;;;;;;AAKA,IAAM,MAAM,aAAa,yBAAyB;AAElD,IAAM,gBAAN,MAAoB;AAAA,EAKlB,YACU,eACA,OACD,KACP,UACO,KACC,UACR;AANQ;AACA;AACD;AAEA;AACC;AAER,SAAK,WAAW,eAAe,QAAQ;AAGvC,SAAK,QAAQ,KAAK,IAAI,KAAK,QAAQ,KAAK;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAU,UAAkB;AAChC,QAAI,aAAa,KAAK,OAAO;AAE3B;AAAA,IACF;AAEA,UAAM,YAAY;AAAA,MAChB,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL,KAAK;AAAA,MACL;AAAA,IACF;AAAA,EACF;AACF;AAEA,eAAsB,iBAAiB,QAAwC;AAC7E,QAAM,EAAE,SAAS,IAAI;AACrB,QAAM,kBAAkB,OAAO,mBAAmB;AAElD,MAAI,KAAK,gBAAM,OAAO,UAAU,oBAAU;AAE1C,QAAM,MAAM,MAAM,YAAY,IAAI;AAAA,IAChC,eAAe,OAAO;AAAA,IACtB,OAAO,OAAO;AAAA,EAChB,CAAC;AACD,MAAI,CAAC,IAAI,KAAK,QAAQ;AACpB,QAAI;AAAA,MACF,GAAG,OAAO,UAAU;AAAA,IACtB;AACA,WAAO,IAAI,UAAU,QAAQ,CAAC;AAAA,EAChC;AAEA,QAAM,YAAY,IAAI,UAAU,QAAQ,IAAI,KAAK,OAAO,SAAS,CAAC;AAElE,MAAI,KAAK,OAAO,QAAQ,CAAC,KAAe,aAAa;AAjEvD;AAmEI,UAAM,gBAAgB,WAAW;AACjC,QAAI,kBAAkB,eAAe;AAEnC;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,eAAe,SAAU,GAAG,CAAC;AAEjD,QAAI,SAAS;AACX,UAAI,UAAU,OAAO,IAAI,OAAO,GAAG;AACjC,YAAI;AAAA,UACF,gBAAM,OAAO,UAAU,2CAAkB,OAAO;AAAA,QAClD;AAAA,MACF,OAAO;AACL,kBAAU,OAAO,IAAI,OAAO;AAAA,MAC9B;AAEA,mBAAO,YAAP,mBAAgB,QAAQ,CAAC,SAAS;AAChC,kBAAU;AAAA,UACR;AAAA,UACA,IAAI;AAAA,YACF,OAAO;AAAA,YACP,OAAO;AAAA,YACP;AAAA,YACA,SAAU,IAAI;AAAA,YACd;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF,CAAC;AAED,SAAO;AACT;AAEO,IAAM,YAAN,MAAgB;AAAA,EAGrB,YACU,QAED,oBACP;AAHQ;AAED;AALT,kBAAS,oBAAI,IAAY;AAQzB,SAAQ,QAAQ,IAAI;AAAA,MAClB,KAAK,OAAO,QAAS,IAAI,CAAC,SAAS;AACjC,eAAO,CAAC,MAAM,oBAAI,IAA2B,CAAC;AAAA,MAChD,CAAC;AAAA,IACH;AAAA,EANG;AAAA,EAQH,YAAY,MAAc,SAAiB;AACzC,WAAO,KAAK,MAAM,IAAI,IAAI,EAAG,IAAI,OAAO;AAAA,EAC1C;AAAA,EAEA,YAAY,MAAc,UAAyB;AACjD,SAAK,MAAM,IAAI,IAAI,EAAG,IAAI,SAAS,KAAK,QAAQ;AAAA,EAClD;AAAA,EAEA,YAAY,MAAc,SAAiB;AACzC,WAAO,KAAK,MAAM,IAAI,IAAI,EAAG,IAAI,OAAO;AAAA,EAC1C;AAAA,EAEA,gBAAgB,MAAc;AAC5B,UAAM,MAAM,CAAC;AACb,SAAK,MAAM,IAAI,IAAI,EAAG,QAAQ,CAAC,aAAa;AAC1C,UAAI,SAAS,GAAG,IAAI,SAAS;AAAA,IAC/B,CAAC;AACD,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -1,130 +0,0 @@
1
- import {
2
- createLogger,
3
- homeConfigDir
4
- } from "./chunk-UGSBKD2I.js";
5
-
6
- // src/shared/google/auth.ts
7
- import fs from "fs-extra";
8
- import { google } from "googleapis";
9
-
10
- // src/shared/google/shared.ts
11
- import connect from "connect";
12
- import open, { apps } from "open";
13
- import { URL } from "url";
14
- var log = createLogger("google:shared");
15
- function openBrowser(url) {
16
- log.info(`\u5982\u672A\u81EA\u52A8\u6253\u5F00\u6D4F\u89C8\u5668\uFF0C\u53EF\u8BBF\u95EE\u4EE5\u4E0B\u5730\u5740\uFF1A${url}`);
17
- open(url, { app: { name: apps.chrome } });
18
- }
19
- function openAndWaitReturnQuery(toOpenUrl, port, queryKey) {
20
- return new Promise((resolve) => {
21
- openBrowser(toOpenUrl);
22
- const app = connect();
23
- app.use((req, res, next) => {
24
- const parsedUrl = new URL(req.url, `http://localhost:${port}`);
25
- const target = parsedUrl.searchParams.get(queryKey);
26
- if (target) {
27
- res.writeHead(200, {
28
- "content-type": "text/html;charset=utf8"
29
- });
30
- res.end(
31
- `<div>\u5F53\u524D\u7A97\u53E3\u53EF\u76F4\u63A5\u5173\u95ED</div>
32
- <script>
33
- window.open("", "_self", "");
34
- window.close();
35
- </script>`
36
- );
37
- server.close();
38
- server.unref();
39
- resolve(target);
40
- }
41
- next();
42
- });
43
- const server = app.listen(port);
44
- });
45
- }
46
-
47
- // src/shared/google/auth.ts
48
- var log2 = createLogger("google:auth");
49
- var GoogleAuth = class {
50
- constructor(options) {
51
- this.options = options;
52
- this.tokens = null;
53
- this.tokensCachePath = homeConfigDir("chromeAuthToken.json");
54
- this.oauth2Client = new google.auth.OAuth2(
55
- this.options.client_id,
56
- this.options.client_secret,
57
- "http://localhost:12345"
58
- );
59
- this.initCredentialsPromise = null;
60
- this.options.scope = this.options.scope ?? ["spreadsheets"];
61
- const scopePrefix = `https://www.googleapis.com/auth/`;
62
- this.scope = this.options.scope.map((item) => {
63
- if (item.startsWith(scopePrefix)) {
64
- return item;
65
- }
66
- return `${scopePrefix}${item}`;
67
- });
68
- try {
69
- this.tokens = fs.readJsonSync(this.tokensCachePath);
70
- } catch (e) {
71
- log2.info("\u672A\u83B7\u53D6\u5230\u7F13\u5B58\u7684 token");
72
- this.tokens = null;
73
- }
74
- }
75
- async saveTokens(tokens) {
76
- this.tokens = tokens;
77
- await fs.writeJSON(this.tokensCachePath, tokens);
78
- log2.info("\u4FDD\u5B58 token \u6210\u529F");
79
- }
80
- async getCode() {
81
- log2.info("\u5C06\u6253\u5F00 chrome \u6D4F\u89C8\u5668\u8FDB\u884C\u6388\u6743");
82
- const authUrl = this.oauth2Client.generateAuthUrl({
83
- access_type: "offline",
84
- scope: this.scope
85
- });
86
- return await openAndWaitReturnQuery(authUrl, 12345, "code");
87
- }
88
- async initCredentialsImpl() {
89
- if (!this.tokens) {
90
- const code = await this.getCode();
91
- const { tokens } = await this.oauth2Client.getToken(code);
92
- if (tokens.access_token) {
93
- const res = await this.oauth2Client.getTokenInfo(tokens.access_token);
94
- Object.assign(tokens, res);
95
- }
96
- await this.saveTokens(tokens);
97
- }
98
- this.oauth2Client.setCredentials(this.tokens);
99
- }
100
- async initCredentials() {
101
- if (!this.initCredentialsPromise) {
102
- this.initCredentialsPromise = this.initCredentialsImpl();
103
- }
104
- return await this.initCredentialsPromise;
105
- }
106
- /**
107
- * 清除 token
108
- */
109
- async removeCredentials() {
110
- if (this.tokens) {
111
- await fs.remove(this.tokensCachePath);
112
- }
113
- this.tokens = null;
114
- }
115
- };
116
- var clientSecret = {
117
- client_id: "691639467478-gugsam9ukfg3m3ga70imecktvqgkqljc.apps.googleusercontent.com",
118
- project_id: "dune-cli-423514",
119
- auth_uri: "https://accounts.google.com/o/oauth2/auth",
120
- token_uri: "https://oauth2.googleapis.com/token",
121
- auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
122
- client_secret: "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",
123
- redirect_uris: ["http://localhost"]
124
- };
125
- var googleAuth = new GoogleAuth(clientSecret);
126
-
127
- export {
128
- googleAuth
129
- };
130
- //# sourceMappingURL=chunk-KNC7XY4Z.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/google/auth.ts","../src/shared/google/shared.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport { OAuth2Client } from \"google-auth-library\";\nimport type {\n GetTokenResponse,\n TokenInfo,\n} from \"google-auth-library/build/src/auth/oauth2client\";\nimport { google } from \"googleapis\";\nimport { createLogger, homeConfigDir } from \"../index\";\nimport { openAndWaitReturnQuery } from \"./shared\";\n\ninterface AuthOptions {\n client_id: string;\n client_secret: string;\n /**\n * @default ['spreadsheets']\n */\n scope?: string[];\n}\n\nconst log = createLogger(\"google:auth\");\n\nclass GoogleAuth {\n tokens: (GetTokenResponse & TokenInfo) | null = null;\n\n private tokensCachePath = homeConfigDir(\"chromeAuthToken.json\");\n\n private readonly scope: string[];\n\n oauth2Client: OAuth2Client = new google.auth.OAuth2(\n this.options.client_id,\n this.options.client_secret,\n \"http://localhost:12345\",\n );\n\n constructor(private options: AuthOptions) {\n this.options.scope = this.options.scope ?? [\"spreadsheets\"];\n const scopePrefix = `https://www.googleapis.com/auth/`;\n this.scope = this.options.scope.map((item) => {\n if (item.startsWith(scopePrefix)) {\n return item;\n }\n return `${scopePrefix}${item}`;\n });\n\n try {\n this.tokens = fs.readJsonSync(this.tokensCachePath);\n } catch (e) {\n log.info(\"未获取到缓存的 token\");\n this.tokens = null;\n }\n }\n\n private async saveTokens(tokens: any): Promise<void> {\n this.tokens = tokens;\n await fs.writeJSON(this.tokensCachePath, tokens);\n log.info(\"保存 token 成功\");\n }\n\n async getCode(): Promise<string> {\n log.info(\"将打开 chrome 浏览器进行授权\");\n const authUrl = this.oauth2Client.generateAuthUrl({\n access_type: \"offline\",\n scope: this.scope,\n });\n return await openAndWaitReturnQuery(authUrl, 12345, \"code\");\n }\n\n private async initCredentialsImpl(): Promise<void> {\n if (!this.tokens) {\n const code = await this.getCode();\n const { tokens } = await this.oauth2Client.getToken(code);\n if (tokens.access_token) {\n const res = await this.oauth2Client.getTokenInfo(tokens.access_token);\n Object.assign(tokens, res);\n }\n await this.saveTokens(tokens);\n }\n this.oauth2Client.setCredentials(this.tokens!);\n }\n private initCredentialsPromise: Promise<void> | null = null;\n async initCredentials() {\n if (!this.initCredentialsPromise) {\n this.initCredentialsPromise = this.initCredentialsImpl();\n }\n return await this.initCredentialsPromise;\n }\n\n /**\n * 清除 token\n */\n async removeCredentials() {\n if (this.tokens) {\n await fs.remove(this.tokensCachePath);\n }\n this.tokens = null;\n }\n}\n\n// see in https://console.cloud.google.com/apis/credentials?organizationId=286245507762&orgonly=true&project=dune-cli&supportedpurview=organizationId\nconst clientSecret = {\n client_id:\n \"691639467478-gugsam9ukfg3m3ga70imecktvqgkqljc.apps.googleusercontent.com\",\n project_id: \"dune-cli-423514\",\n auth_uri: \"https://accounts.google.com/o/oauth2/auth\",\n token_uri: \"https://oauth2.googleapis.com/token\",\n auth_provider_x509_cert_url: \"https://www.googleapis.com/oauth2/v1/certs\",\n client_secret: \"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\",\n redirect_uris: [\"http://localhost\"],\n};\n\nexport const googleAuth = new GoogleAuth(clientSecret);\n","import connect from \"connect\";\nimport open, { apps } from \"open\";\nimport { URL } from \"url\";\nimport { createLogger } from \"../index\";\n\nconst log = createLogger(\"google:shared\");\n\nfunction openBrowser(url: string) {\n log.info(`如未自动打开浏览器,可访问以下地址:${url}`);\n open(url, { app: { name: apps.chrome } });\n}\n\nexport function openAndWaitReturnQuery(\n toOpenUrl: string,\n port: number,\n queryKey: string,\n) {\n return new Promise<string>((resolve) => {\n openBrowser(toOpenUrl);\n\n const app = connect();\n app.use((req, res, next) => {\n const parsedUrl = new URL(req.url, `http://localhost:${port}`);\n const target = parsedUrl.searchParams.get(queryKey);\n if (target) {\n res.writeHead(200, {\n \"content-type\": \"text/html;charset=utf8\",\n });\n res.end(\n `<div>当前窗口可直接关闭</div>\n <script>\n window.open(\"\", \"_self\", \"\");\n window.close();\n </script>`,\n );\n server.close();\n server.unref();\n resolve(target);\n }\n next();\n });\n\n const server = app.listen(port);\n });\n}\n"],"mappings":"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","names":["log"]}
@@ -1,24 +0,0 @@
1
- import {
2
- createLogger
3
- } from "./chunk-UGSBKD2I.js";
4
-
5
- // src/shared/formatFile.ts
6
- import * as child_process from "child_process";
7
- var log = createLogger("formatFile");
8
- function formatFile(filename) {
9
- log.info(`\u5C1D\u8BD5\u683C\u5F0F\u5316\u4EE3\u7801: %s`, filename);
10
- child_process.exec(`prettier --write '${filename}'`, (error) => {
11
- if (error) {
12
- log.error(`\u683C\u5F0F\u5316\u4EE3\u7801\u5931\u8D25: ${error}`);
13
- log.error(`\u8BF7\u624B\u52A8\u6267\u884C: prettier --write ${filename}`);
14
- log.error(`\u6216\u8005\u5728\u914D\u7F6E\u6587\u4EF6\u4E2D\u5173\u95ED\u683C\u5F0F\u5316\u529F\u80FD`);
15
- } else {
16
- log.info(`\u683C\u5F0F\u5316\u4EE3\u7801\u6210\u529F: %s`, filename);
17
- }
18
- });
19
- }
20
-
21
- export {
22
- formatFile
23
- };
24
- //# sourceMappingURL=chunk-Q7UJ456X.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/shared/formatFile.ts"],"sourcesContent":["import { createLogger } from \".\";\nimport * as child_process from \"child_process\";\n\nconst log = createLogger(\"formatFile\");\n\nexport function formatFile(filename: string) {\n // 格式化代码\n log.info(`尝试格式化代码: %s`, filename);\n child_process.exec(`prettier --write '${filename}'`, (error) => {\n if (error) {\n log.error(`格式化代码失败: ${error}`);\n log.error(`请手动执行: prettier --write ${filename}`);\n log.error(`或者在配置文件中关闭格式化功能`);\n } else {\n log.info(`格式化代码成功: %s`, filename);\n }\n });\n}\n"],"mappings":";;;;;AACA,YAAY,mBAAmB;AAE/B,IAAM,MAAM,aAAa,YAAY;AAE9B,SAAS,WAAW,UAAkB;AAE3C,MAAI,KAAK,kDAAe,QAAQ;AAChC,EAAc,mBAAK,qBAAqB,QAAQ,KAAK,CAAC,UAAU;AAC9D,QAAI,OAAO;AACT,UAAI,MAAM,+CAAY,KAAK,EAAE;AAC7B,UAAI,MAAM,oDAA2B,QAAQ,EAAE;AAC/C,UAAI,MAAM,4FAAiB;AAAA,IAC7B,OAAO;AACL,UAAI,KAAK,kDAAe,QAAQ;AAAA,IAClC;AAAA,EACF,CAAC;AACH;","names":[]}
@@ -1,49 +0,0 @@
1
- import {
2
- resolveSheetData
3
- } from "./chunk-IKJLPHF7.js";
4
- import "./chunk-6UFZ6KLX.js";
5
- import "./chunk-KNC7XY4Z.js";
6
- import {
7
- I18nData
8
- } from "./chunk-ADQ6JLT6.js";
9
- import {
10
- promptI18nConfigEnable
11
- } from "./chunk-2SEEW5WZ.js";
12
- import {
13
- getConfig
14
- } from "./chunk-PRJ3NOXB.js";
15
- import "./chunk-555YTWSW.js";
16
- import {
17
- createLogger
18
- } from "./chunk-UGSBKD2I.js";
19
-
20
- // src/commands/download.ts
21
- import pMap from "p-map";
22
- var log = createLogger("generate");
23
- async function download() {
24
- const config = await getConfig();
25
- let i18nConfigs = await promptI18nConfigEnable(config.i18n);
26
- let i = 0;
27
- for (const configItem of i18nConfigs) {
28
- i++;
29
- if (!configItem.sheetId || !configItem.sheetRange) {
30
- log.error(`config.${i} sheetId \u6216 sheetRange \u4E3A\u7A7A\uFF0C\u8BF7\u68C0\u67E5`);
31
- continue;
32
- }
33
- const sheetData = await resolveSheetData(configItem);
34
- const statistics = await pMap(
35
- configItem.locales ?? [],
36
- async (locale, index) => {
37
- const i18nData = new I18nData(locale, configItem);
38
- await i18nData.updateFromSheetData(sheetData.getLangDataJSON(locale));
39
- await i18nData.saveToDisk();
40
- return i18nData;
41
- }
42
- );
43
- I18nData.printStatistic(`${configItem.sheetRange} \u751F\u6210\u7ED3\u679C: `, statistics);
44
- }
45
- }
46
- export {
47
- download
48
- };
49
- //# sourceMappingURL=download-KXSMWNXH.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/download.ts"],"sourcesContent":["import pMap from \"p-map\";\nimport { createLogger } from \"../shared\";\nimport { getConfig } from \"../shared/config\";\nimport { I18nData } from \"../shared/i18nData\";\nimport { resolveSheetData } from \"../shared/resolveSheetData\";\nimport { promptI18nConfigEnable } from \"../shared/promptConfigEnable\";\n\nconst log = createLogger(\"generate\");\n\nexport async function download() {\n const config = await getConfig();\n\n let i18nConfigs = await promptI18nConfigEnable(config.i18n);\n\n let i = 0;\n for (const configItem of i18nConfigs) {\n i++;\n if (!configItem.sheetId || !configItem.sheetRange) {\n log.error(`config.${i} sheetId 或 sheetRange 为空,请检查`);\n continue;\n }\n const sheetData = await resolveSheetData(configItem);\n\n const statistics = await pMap(\n configItem.locales ?? [],\n async (locale, index) => {\n const i18nData = new I18nData(locale, configItem);\n await i18nData.updateFromSheetData(sheetData.getLangDataJSON(locale));\n await i18nData.saveToDisk();\n return i18nData;\n }\n );\n I18nData.printStatistic(`${configItem.sheetRange} 生成结果: `, statistics);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA,OAAO,UAAU;AAOjB,IAAM,MAAM,aAAa,UAAU;AAEnC,eAAsB,WAAW;AAC/B,QAAM,SAAS,MAAM,UAAU;AAE/B,MAAI,cAAc,MAAM,uBAAuB,OAAO,IAAI;AAE1D,MAAI,IAAI;AACR,aAAW,cAAc,aAAa;AACpC;AACA,QAAI,CAAC,WAAW,WAAW,CAAC,WAAW,YAAY;AACjD,UAAI,MAAM,UAAU,CAAC,iEAA8B;AACnD;AAAA,IACF;AACA,UAAM,YAAY,MAAM,iBAAiB,UAAU;AAEnD,UAAM,aAAa,MAAM;AAAA,MACvB,WAAW,WAAW,CAAC;AAAA,MACvB,OAAO,QAAQ,UAAU;AACvB,cAAM,WAAW,IAAI,SAAS,QAAQ,UAAU;AAChD,cAAM,SAAS,oBAAoB,UAAU,gBAAgB,MAAM,CAAC;AACpE,cAAM,SAAS,WAAW;AAC1B,eAAO;AAAA,MACT;AAAA,IACF;AACA,aAAS,eAAe,GAAG,WAAW,UAAU,+BAAW,UAAU;AAAA,EACvE;AACF;","names":[]}
@@ -1,113 +0,0 @@
1
- import {
2
- I18nData
3
- } from "./chunk-ADQ6JLT6.js";
4
- import {
5
- promptI18nConfigEnable
6
- } from "./chunk-2SEEW5WZ.js";
7
- import {
8
- getConfig
9
- } from "./chunk-PRJ3NOXB.js";
10
- import "./chunk-555YTWSW.js";
11
- import {
12
- createLogger
13
- } from "./chunk-UGSBKD2I.js";
14
-
15
- // src/commands/extract/index.ts
16
- import fs from "fs-extra";
17
- import { globby } from "globby";
18
- import os from "os";
19
- import pMap from "p-map";
20
- import path from "path";
21
- import pc from "picocolors";
22
- var log = createLogger("extract");
23
- async function extract(opts) {
24
- var _a;
25
- const config = await getConfig();
26
- const { extract: extract2 } = await import("@dune2/wasm");
27
- let i18nConfigs = await promptI18nConfigEnable(
28
- (_a = config.i18n) == null ? void 0 : _a.filter((item) => !item.disableExtract)
29
- );
30
- for (const configItem of i18nConfigs) {
31
- const files = await globby(
32
- [
33
- `./src/**/**.{js,jsx,ts,tsx}`,
34
- "!**/node_modules/**",
35
- "!**.d.ts",
36
- "!**/.next/**",
37
- "!**/out/**"
38
- ].concat(configItem.include ?? []),
39
- { cwd: configItem.cwd }
40
- );
41
- log.info("\u9884\u8BA1\u5171\u89E3\u6790 %s \u4E2A\u6587\u4EF6", pc.green(files.length));
42
- let errMsgs = [];
43
- const extractedI18nDataMap = /* @__PURE__ */ new Map();
44
- await pMap(
45
- files,
46
- async (file) => {
47
- const content = await fs.readFile(file, "utf-8");
48
- const res = await extract2(content, file);
49
- if (res.data.size) {
50
- log.info(
51
- "\u4ECE %s \u4E2D\u63D0\u53D6\u5230 %s \u6761\u6587\u6848",
52
- pc.dim(file),
53
- pc.green(res.data.size)
54
- );
55
- res.data.forEach((value, key) => {
56
- let cur = extractedI18nDataMap.get(key);
57
- const hasCache = !!cur;
58
- if (!hasCache) {
59
- cur = { ...value, files: [] };
60
- }
61
- cur.files.push(
62
- path.resolve(file) + ":" + value.line + ":" + value.column
63
- );
64
- cur.messages = value.messages || cur.messages;
65
- if (!hasCache) {
66
- extractedI18nDataMap.set(key, cur);
67
- }
68
- });
69
- }
70
- if (res.errMsg) {
71
- errMsgs.push(res.errMsg);
72
- }
73
- },
74
- { concurrency: 20 }
75
- );
76
- await saveExtractedMetaData(configItem, extractedI18nDataMap);
77
- const i18nDataArr = await pMap(configItem.locales ?? [], async (locale) => {
78
- const i18nData = new I18nData(locale, configItem, opts == null ? void 0 : opts.deleteUnused);
79
- await i18nData.updateByExtractedData(extractedI18nDataMap);
80
- await i18nData.saveToDisk();
81
- return i18nData;
82
- });
83
- if (errMsgs.length) {
84
- console.log(pc.bold("\u4EE5\u4E0B\u672A\u80FD\u6210\u529F\u63D0\u53D6\u7684\u6587\u6848\uFF0C\u8BF7\u624B\u52A8\u5904\u7406\uFF1A"));
85
- console.log(errMsgs.join(os.EOL));
86
- }
87
- I18nData.printStatistic("\u63D0\u53D6\u7ED3\u679C\uFF1A", i18nDataArr);
88
- }
89
- }
90
- async function saveExtractedMetaData(config, extractedI18nDataMap) {
91
- const { i18nDir } = config;
92
- const prefix = i18nDir.replace("./", "").replace(/\//g, "_");
93
- const filename = `${prefix}.extractedLog.json`;
94
- const metaDataJsonPath = path.join(i18nDir, filename);
95
- await fs.ensureFile(metaDataJsonPath);
96
- let data = Array.from(extractedI18nDataMap.entries()).map(
97
- ([key, value]) => value
98
- );
99
- data = data.sort((a, b) => {
100
- return a.id.localeCompare(b.id);
101
- });
102
- await fs.writeJSON(
103
- metaDataJsonPath,
104
- data,
105
- {
106
- spaces: 2
107
- }
108
- );
109
- }
110
- export {
111
- extract
112
- };
113
- //# sourceMappingURL=extract-ARNNWYYN.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/extract/index.ts"],"sourcesContent":["import fs from \"fs-extra\";\nimport { globby } from \"globby\";\nimport os from \"os\";\nimport pMap from \"p-map\";\nimport path from \"path\";\nimport pc from \"picocolors\";\nimport { createLogger } from \"../../shared\";\nimport { getConfig, I18nConfig } from \"../../shared/config\";\nimport { ExtractedMap, I18nData } from \"../../shared/i18nData\";\nimport { promptI18nConfigEnable } from \"../../shared/promptConfigEnable\";\n\nconst log = createLogger(\"extract\");\n\n/**\n * 提取文案\n */\nexport async function extract(opts?: { deleteUnused: boolean }) {\n const config = await getConfig();\n const { extract } = await import(\"@dune2/wasm\");\n\n let i18nConfigs = await promptI18nConfigEnable(\n config.i18n?.filter((item) => !item.disableExtract),\n );\n\n // 这是使得任务串行,方便看日志\n for (const configItem of i18nConfigs) {\n const files = await globby(\n [\n `./src/**/**.{js,jsx,ts,tsx}`,\n \"!**/node_modules/**\",\n \"!**.d.ts\",\n \"!**/.next/**\",\n \"!**/out/**\",\n ].concat(configItem.include ?? []),\n { cwd: configItem.cwd },\n );\n log.info(\"预计共解析 %s 个文件\", pc.green(files.length));\n let errMsgs: string[] = [];\n const extractedI18nDataMap: ExtractedMap = new Map();\n\n await pMap(\n files,\n async (file) => {\n const content = await fs.readFile(file, \"utf-8\");\n const res = await extract(content, file);\n if (res.data.size) {\n log.info(\n \"从 %s 中提取到 %s 条文案\",\n pc.dim(file),\n pc.green(res.data.size),\n );\n res.data.forEach((value, key) => {\n let cur = extractedI18nDataMap.get(key)!;\n const hasCache = !!cur;\n if (!hasCache) {\n cur = { ...value, files: [] };\n }\n cur.files.push(\n path.resolve(file) + \":\" + value.line + \":\" + value.column,\n );\n // 优先使用 提取出来的文案\n cur.messages = value.messages || cur.messages;\n\n if (!hasCache) {\n extractedI18nDataMap.set(key, cur);\n }\n });\n }\n if (res.errMsg) {\n errMsgs.push(res.errMsg);\n }\n },\n { concurrency: 20 },\n );\n\n await saveExtractedMetaData(configItem, extractedI18nDataMap);\n\n const i18nDataArr = await pMap(configItem.locales ?? [], async (locale) => {\n const i18nData = new I18nData(locale, configItem, opts?.deleteUnused);\n await i18nData.updateByExtractedData(extractedI18nDataMap);\n await i18nData.saveToDisk();\n return i18nData;\n });\n if (errMsgs.length) {\n console.log(pc.bold(\"以下未能成功提取的文案,请手动处理:\"));\n console.log(errMsgs.join(os.EOL));\n }\n I18nData.printStatistic(\"提取结果:\", i18nDataArr);\n }\n}\n\n/**\n * 保存相关的提取信息\n */\nasync function saveExtractedMetaData(\n config: I18nConfig,\n extractedI18nDataMap: ExtractedMap,\n) {\n const { i18nDir } = config;\n // case:\n // input: \"./src/i18n\"\n // output: \"src_i18n.extractedLog.json\"\n const prefix = i18nDir!.replace(\"./\", \"\").replace(/\\//g, \"_\");\n const filename = `${prefix}.extractedLog.json`;\n\n const metaDataJsonPath = path.join(i18nDir!, filename);\n\n await fs.ensureFile(metaDataJsonPath);\n\n // extractedI18nDataMap 是个 Map 需要转成换 json\n let data = Array.from(extractedI18nDataMap.entries()).map(\n ([key, value]) => value,\n );\n // 按照 id 排序\n data = data.sort((a, b) => {\n return a.id.localeCompare(b.id);\n });\n\n await fs.writeJSON(\n metaDataJsonPath,\n\n data,\n {\n spaces: 2,\n },\n );\n}\n"],"mappings":"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","names":["extract"]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/commands/generateApi/index.ts"],"sourcesContent":["import SwaggerParser from \"@apidevtools/swagger-parser\";\nimport fs from \"fs-extra\";\nimport { compile } from \"json-schema-to-typescript\";\nimport _ from \"lodash\";\nimport { OpenAPIV3 } from \"openapi-types\";\nimport * as os from \"os\";\nimport pMap from \"p-map\";\nimport path from \"path\";\nimport { createLogger } from \"../../shared\";\nimport { ApiConfig, getConfig } from \"../../shared/config\";\nimport { formatFile } from \"../../shared/formatFile\";\nimport { promptApiConfigEnable } from \"../../shared/promptConfigEnable\";\n\nconst log = createLogger(\"generateApi\");\n\nexport async function generateApi() {\n const config = await getConfig();\n const apiConfigs = await promptApiConfigEnable(config.api);\n\n for (const apiConfig of apiConfigs) {\n log.info(`清除旧的 api 文件:${apiConfig.output}`);\n await fs.emptydir(apiConfig.output!);\n }\n\n for (const apiConfig of apiConfigs) {\n log.info(\"开始解析 %s\", apiConfig.swaggerJSONPath);\n const dereferenceConfig = _.merge(\n {\n resolve: {\n http: {\n timeout: 30 * 1000,\n },\n },\n },\n apiConfig.dereferenceSwaggerConfig,\n );\n const parsed = (await SwaggerParser.dereference(\n apiConfig.swaggerJSONPath,\n dereferenceConfig,\n )) as OpenAPIV3.Document;\n\n await pMap(Object.entries(parsed.paths), async ([url, pathItemObject]) => {\n log.info(\"开始生成 %s\", url);\n if (pathItemObject) {\n await pMap(\n [\"get\", \"put\", \"post\", \"delete\", \"patch\"],\n async (method) => {\n const operationObject = pathItemObject[method];\n if (operationObject) {\n const code = await generateApiRequestCode({\n url: url,\n method: method,\n operationObject: operationObject,\n apiConfig,\n });\n const outputPath = path\n .join(\n apiConfig.output!,\n url,\n apiConfig.enableTs ? `${method}.ts` : `${method}.js`,\n )\n .replace(/:/g, \"_\");\n await fs.ensureFile(outputPath);\n await fs.writeFile(outputPath, code);\n }\n },\n );\n }\n });\n\n if (apiConfig.format) {\n await formatFile(apiConfig.output!);\n }\n }\n\n log.info(\"generateApi Done\");\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}#/${operationObject.tags?.join(\"/\") ?? \"\"}/${\n operationObject.operationId\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 \"// 这个文件由 @dune2/cli 自动生成,不要手动修改,否则会被覆盖\",\n apiConfig.RequestBuilderImportPath!,\n apiConfig.requestFnImportPath!,\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 ${apiConfig.requestFnImportPath ? \"requestFn,\" : \"\"}\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 // post 和 put 请求需要生成表单 fieldsMap\n const isGenerateFieldsMap = [\"post\", \"put\"].includes(method);\n // 请求参数类型\n // 响应参数类型\n const [requestParamsTypeCode, responseParamsTypeCode] = await Promise.all([\n compileRequestParams(operationObject, isGenerateFieldsMap),\n compileResponseParams(operationObject, apiConfig),\n ]);\n\n code.push(`\nexport namespace ${requestBuilderName} {\n ${requestParamsTypeCode.code}\n \n ${responseParamsTypeCode}\n};`);\n\n if (isGenerateFieldsMap && !_.isEmpty(requestParamsTypeCode.fieldsMap)) {\n // 生成表单 fieldsMap\n code.push(`\nexport const ${requestBuilderName}FieldsMap = ${JSON.stringify(\n requestParamsTypeCode.fieldsMap,\n )} as const\n`);\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 generateFieldsMap = false,\n) {\n let schema;\n if (operationObject.requestBody) {\n //TODO: 这里也需要处理其他类型\n schema = (operationObject.requestBody as OpenAPIV3.RequestBodyObject)\n .content[\"application/json\"].schema;\n } else if (operationObject.parameters) {\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 (_.get(item.schema, \"type\") === \"object\") {\n // swagger get 请求上 有些参数是 object 类型 应该拍平\n _.assign(extraProperties, _.get(item.schema, \"properties\", {}));\n } else {\n parameters.push(item);\n }\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 //TODO: 这里也要处理 ref 类型\n const schema = p.schema as OpenAPIV3.SchemaObject;\n return [\n p.name,\n {\n ...schema,\n description: p.description,\n // enum: schema.enum ?? [],\n },\n ];\n }),\n );\n schema = {\n required,\n type: \"object\",\n properties: { ...properties, ...extraProperties },\n };\n }\n\n let code = \"\";\n const fieldsMap: Record<string, string> = {};\n if (schema) {\n try {\n code = await compile(schema, \"Req\", {\n bannerComment: \"\",\n ignoreMinAndMaxItems: !!1,\n additionalProperties: false,\n // format: false,\n });\n\n // 判断接口是否是分页请求\n const isPageSearchRequest = (data: any) => {\n // 入参有这些字段就认为是分页查询接口\n const keys = [\"pageNum\", \"pageSize\", \"count\"];\n return (\n _.get(data, \"type\") === \"object\" &&\n _.get(data, \"required\", []).filter((item) => keys.includes(item))\n .length === keys.length\n );\n };\n\n if (generateFieldsMap) {\n // 分页查询接口取 params 字段\n const params = isPageSearchRequest(schema)\n ? _.get(schema, \"properties.params.properties\", {})\n : schema.properties;\n _.forEach(params, (_, field) => {\n fieldsMap[field] = field;\n });\n }\n } catch (e) {\n log.error(\"生成请求参数类型失败,请检查 %o\", {\n summary: operationObject.summary,\n message: e.message,\n });\n }\n }\n\n return {\n code: code || \"export type Req = any;\",\n fieldsMap,\n };\n}\n\nasync function compileResponseParams(\n operationObject: OpenAPIV3.OperationObject,\n apiConfig: ApiConfig,\n) {\n const temp = operationObject.responses[\"200\"] as OpenAPIV3.ResponseObject;\n let code = \"\";\n if (temp?.content) {\n // FIXME: 可能需要处理其他的 content 类型\n const temp2 = temp.content[\"application/json\"] || temp.content[\"*/*\"];\n const schema = temp2.schema as OpenAPIV3.SchemaObject;\n let data = apiConfig.responseSchemaTransformer!(schema);\n if (data) {\n // 这里需要深度 clone 的原因是:\n // 解析出来的 scheme 会尽可能的被复用,导致影响到下次解析\n data = _.cloneDeep(data);\n markCircularToRef(data);\n try {\n code = await compile(data, \"Res\", {\n bannerComment: \"\",\n ignoreMinAndMaxItems: !!1,\n additionalProperties: false,\n // format: false,\n });\n\n // 通过响应数据判断是否是分页查询接口\n const isPageSearchResponse = (data: any) => {\n // 有 result 字段且为数组,就认为是分页查询接口\n return (\n _.get(data, \"type\") === \"object\" &&\n _.get(data, \"properties.result.type\") === \"array\"\n );\n };\n\n // 新增后端分页查询返回的数据类型\n if (isPageSearchResponse(data)) {\n code += `${os.EOL}export type ResultItem = Res['result'][0]`;\n }\n } catch (e) {\n log.error(\"转换响应参数类型失败,请检查 %o\", {\n summary: operationObject.summary,\n error: e.message,\n });\n }\n } else {\n log.error(\"responseSchemaTransformer 返回值为空,请检查\");\n }\n }\n\n return code ? code : \"export type Res = any;\";\n}\n\nexport function markCircularToRef(\n obj,\n parentMark = \"#\",\n map = new Map([[obj, parentMark]]),\n set = new Set([obj]),\n) {\n Object.keys(obj).forEach((key) => {\n const value = obj[key];\n if (typeof value === \"object\" && !Array.isArray(value)) {\n if (set.has(value)) {\n obj[key] = { $ref: map.get(value) };\n return;\n }\n const tempMark = parentMark + \"/\" + key;\n set.add(value);\n map.set(value, tempMark);\n markCircularToRef(value, tempMark, map, set);\n }\n });\n return map;\n}\n"],"mappings":"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","names":["schema","_","data"]}