@cnbcool/cnb-api-generate 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +399 -0
  2. package/bin/cag.js +3 -0
  3. package/bin/csg.js +3 -0
  4. package/built/codegen/action/generate-redux-action-ast-node.js +85 -0
  5. package/built/codegen/action/generate-redux-action-call-api-function-param-ast-node.js +40 -0
  6. package/built/codegen/action/generate-redux-action-normal-params-ast-node.js +52 -0
  7. package/built/codegen/action/generate-redux-action-params-binding-element-ast-node.js +40 -0
  8. package/built/codegen/action/generate-redux-action-params-type-literal-ast-node.js +58 -0
  9. package/built/codegen/api/generate-api-error-response-ast-node.js +83 -0
  10. package/built/codegen/api/generate-api-function-ast-node.js +133 -0
  11. package/built/codegen/api/generate-api-function-request-params-type-ast-node.js +59 -0
  12. package/built/codegen/api/generate-api-response-return-type-content.js +80 -0
  13. package/built/codegen/api/generate-api-success-response-ast-node.js +84 -0
  14. package/built/codegen/api/generate-function-content-ast-node.js +104 -0
  15. package/built/codegen/api/generate-function-normal-params-ast-node.js +49 -0
  16. package/built/codegen/api/generate-function-params-ast-node.js +249 -0
  17. package/built/codegen/api/generate-function-refs-type-params-ast-node.js +102 -0
  18. package/built/codegen/api/generate-import-ast-node.js +58 -0
  19. package/built/codegen/api/generate-request-function.js +81 -0
  20. package/built/codegen/api/generate-request-url-ast-node.js +98 -0
  21. package/built/codegen/enum/generate-enum-ast-node.js +95 -0
  22. package/built/codegen/enum/generate-enum-content-ast-node.js +74 -0
  23. package/built/codegen/interface/generate-import-interface-ast-node.js +47 -0
  24. package/built/codegen/interface/generate-interface-anchor-ast-node.js +25 -0
  25. package/built/codegen/interface/generate-interface-ast-node.js +322 -0
  26. package/built/codegen/interface/generate-interface-desc-ast-node.js +51 -0
  27. package/built/codegen/interface/generate-interface-entrance.js +110 -0
  28. package/built/codegen/printer/printer-skill-client-modules.js +58 -0
  29. package/built/codegen/printer/printer-skills-client-core.js +69 -0
  30. package/built/codegen/printer/printer-swagger-api-to-file.js +128 -0
  31. package/built/codegen/printer/printer-swagger-definitions-to-file.js +81 -0
  32. package/built/codegen/printer/printer-ts-ast-to-js-file.js +72 -0
  33. package/built/codegen/record/generate-record-anchor-ast-node.js +25 -0
  34. package/built/codegen/record/generate-record-ast-node.js +134 -0
  35. package/built/codegen/swagger-definitions-to-ast-node.js +36 -0
  36. package/built/codegen/types/md-array-type-content-ast-node.js +46 -0
  37. package/built/constants/actions.js +8 -0
  38. package/built/constants/definitions.js +20 -0
  39. package/built/constants/file.js +12 -0
  40. package/built/constants/index.js +20 -0
  41. package/built/constants/prettier.js +4 -0
  42. package/built/constants/request.js +35 -0
  43. package/built/constants/skills.js +5 -0
  44. package/built/generate-api.js +36 -0
  45. package/built/generate-defintions.js +32 -0
  46. package/built/generate-entrypoint.js +130 -0
  47. package/built/index.js +19 -0
  48. package/built/interface/index.js +16 -0
  49. package/built/skills-tools/generate-config.js +28 -0
  50. package/built/skills-tools/generate-skill-cli-help.js +156 -0
  51. package/built/skills-tools/generate-skill-cli-scripts.js +20 -0
  52. package/built/skills-tools/generate-skill-md.js +25 -0
  53. package/built/skills.js +36 -0
  54. package/built/test.js +1 -0
  55. package/built/utils/camel-to-kebab.js +13 -0
  56. package/built/utils/comment-line-break.js +6 -0
  57. package/built/utils/filter-api-param.js +64 -0
  58. package/built/utils/format-interface-name.js +12 -0
  59. package/built/utils/format-type-name.js +12 -0
  60. package/built/utils/gen-operation-id.js +24 -0
  61. package/built/utils/generate-map-item.js +16 -0
  62. package/built/utils/get-codegen-target.js +8 -0
  63. package/built/utils/get-config.js +68 -0
  64. package/built/utils/get-defintion-name.js +8 -0
  65. package/built/utils/get-defintion-type.js +13 -0
  66. package/built/utils/get-generate-license.js +39 -0
  67. package/built/utils/get-keyword-type-node.js +60 -0
  68. package/built/utils/get-printer-file-prefix.js +21 -0
  69. package/built/utils/get-skills-codegen-target.js +15 -0
  70. package/built/utils/get-swagger-file.js +60 -0
  71. package/built/utils/inject-param-to-path.js +12 -0
  72. package/built/utils/is-english-only.js +8 -0
  73. package/built/utils/is-skills.js +6 -0
  74. package/built/utils/lower-first-char.js +8 -0
  75. package/built/utils/path-to-camel-case.js +31 -0
  76. package/built/utils/progress.js +76 -0
  77. package/built/utils/to-camel-case.js +8 -0
  78. package/built/utils/translations-keyworad-to-string.js +55 -0
  79. package/client/core.ts +114 -0
  80. package/client/fetch-response-handler.ts +36 -0
  81. package/client/index.ts +377 -0
  82. package/client/modules.help.ts +36 -0
  83. package/client/schemaToJson.ts +26 -0
  84. package/client/shortcuts.ts +208 -0
  85. package/client/tools.help.ts +104 -0
  86. package/client/utils/convert-link.ts +139 -0
  87. package/client/utils/generate-unique-id.ts +3 -0
  88. package/package.json +75 -0
  89. package/skills-template/SKILL.md +100 -0
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getSwaggerFile = getSwaggerFile;
7
+ const path_1 = __importDefault(require("path"));
8
+ const fs_1 = __importDefault(require("fs"));
9
+ const http_1 = __importDefault(require("http"));
10
+ const https_1 = __importDefault(require("https"));
11
+ const get_config_1 = require("./get-config");
12
+ function isHttpUrl(url) {
13
+ return url.startsWith('http://') || url.startsWith('https://');
14
+ }
15
+ function fetchRemoteFile(url) {
16
+ return new Promise((resolve, reject) => {
17
+ const client = url.startsWith('https://') ? https_1.default : http_1.default;
18
+ const req = client.get(url, (res) => {
19
+ if (res.statusCode !== 200) {
20
+ reject(new Error(`HTTP请求失败,状态码: ${res.statusCode}`));
21
+ return;
22
+ }
23
+ let data = '';
24
+ res.on('data', (chunk) => {
25
+ data += chunk;
26
+ });
27
+ res.on('end', () => {
28
+ resolve(data);
29
+ });
30
+ });
31
+ req.on('error', (err) => {
32
+ reject(new Error(`网络请求失败: ${err.message}`));
33
+ });
34
+ req.setTimeout(10000, () => {
35
+ req.destroy();
36
+ reject(new Error('请求超时'));
37
+ });
38
+ });
39
+ }
40
+ async function getSwaggerFile() {
41
+ const config = (0, get_config_1.getConfig)();
42
+ if (!config.target) {
43
+ throw new Error('缺失config.target');
44
+ }
45
+ if (isHttpUrl(config.target)) {
46
+ try {
47
+ const content = await fetchRemoteFile(config.target);
48
+ return JSON.parse(content);
49
+ }
50
+ catch (error) {
51
+ throw new Error(`远程文件加载失败: ${error.message}`);
52
+ }
53
+ }
54
+ const fsPath = path_1.default.resolve(process.cwd(), config.target);
55
+ if (!fs_1.default.existsSync(fsPath)) {
56
+ throw new Error(`swagger.json文件不存在 ${fsPath}`);
57
+ }
58
+ const content = JSON.parse(fs_1.default.readFileSync(fsPath, 'utf8'));
59
+ return content;
60
+ }
@@ -0,0 +1,12 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.injectParamToPath = injectParamToPath;
4
+ function injectParamToPath(path, params) {
5
+ let newPath = path;
6
+ // eslint-disable-next-line @typescript-eslint/prefer-for-of
7
+ for (let i = 0; i < params.length; i++) {
8
+ const param = params[i];
9
+ newPath = newPath.replace(`{${param.name}}`, param.name);
10
+ }
11
+ return newPath;
12
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isEnglishOnly = isEnglishOnly;
4
+ function isEnglishOnly(str) {
5
+ // ^ 和 $ 表示字符串的开始和结束,确保整个字符串都匹配
6
+ // [A-Za-z]+ 表示一个或多个英文大小写字母
7
+ return /^[A-Za-z_]+$/.test(str);
8
+ }
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.isSkills = isSkills;
4
+ function isSkills() {
5
+ return process.env.CNB_GENERATE_MODE === 'skills';
6
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.lowerFirstChar = lowerFirstChar;
4
+ function lowerFirstChar(str) {
5
+ if (!str)
6
+ return str; // 处理空字符串或非字符串
7
+ return str.charAt(0).toLowerCase() + str.slice(1);
8
+ }
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.pathToCamelCase = pathToCamelCase;
4
+ function pathToCamelCase(path) {
5
+ return path
6
+ .split('/') // 按斜杠分割
7
+ .filter((part) => part && part !== '-') // 过滤空字符串和单独的 '-'
8
+ .map((part) => {
9
+ // 去掉花括号
10
+ part = part.replace(/[{}]/g, '');
11
+ // 按 '-' 分割,转驼峰
12
+ return part
13
+ .split('-')
14
+ .map((word, index) => {
15
+ word = word.toLowerCase();
16
+ if (index === 0) {
17
+ return word;
18
+ }
19
+ return word.charAt(0).toUpperCase() + word.slice(1);
20
+ })
21
+ .join('');
22
+ })
23
+ .map((word, index) => {
24
+ // 整体首字母小写,后续单词首字母大写
25
+ if (index === 0) {
26
+ return word.charAt(0).toLowerCase() + word.slice(1);
27
+ }
28
+ return word.charAt(0).toUpperCase() + word.slice(1);
29
+ })
30
+ .join('');
31
+ }
@@ -0,0 +1,76 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.startProgress = startProgress;
7
+ exports.successProgress = successProgress;
8
+ exports.infoProgress = infoProgress;
9
+ exports.createProgressBar = createProgressBar;
10
+ exports.startProgressBar = startProgressBar;
11
+ exports.updateProgressBar = updateProgressBar;
12
+ exports.stopProgressBar = stopProgressBar;
13
+ const ora_1 = __importDefault(require("ora"));
14
+ const cli_progress_1 = __importDefault(require("cli-progress"));
15
+ const tty = process.stdout.isTTY;
16
+ function isOpenCagDebugLogger() {
17
+ if (process.env.DEBUG) {
18
+ return process.env.DEBUG.includes('cag:');
19
+ }
20
+ return false;
21
+ }
22
+ function startProgress(message = '') {
23
+ if (isOpenCagDebugLogger())
24
+ return;
25
+ if (!tty) {
26
+ process.stdout.write(`${message}\n`);
27
+ }
28
+ else {
29
+ const spinner = (0, ora_1.default)(message).start();
30
+ return spinner;
31
+ }
32
+ }
33
+ function successProgress(message, spinner) {
34
+ if (isOpenCagDebugLogger())
35
+ return;
36
+ if (!tty || !spinner) {
37
+ process.stdout.write(`${message}\n`);
38
+ }
39
+ else {
40
+ spinner.succeed(message);
41
+ }
42
+ }
43
+ function infoProgress(message, spinner) {
44
+ if (isOpenCagDebugLogger())
45
+ return;
46
+ if (!tty || !spinner) {
47
+ process.stdout.write(`${message}\n`);
48
+ }
49
+ else {
50
+ spinner.info(message);
51
+ }
52
+ }
53
+ function createProgressBar(title) {
54
+ if (isOpenCagDebugLogger())
55
+ return;
56
+ return new cli_progress_1.default.SingleBar({
57
+ format: `${title} |{bar}| {value}/{total} | {percentage}% | {duration_formatted}`,
58
+ fps: 30,
59
+ clearOnComplete: true,
60
+ }, cli_progress_1.default.Presets.shades_classic);
61
+ }
62
+ function startProgressBar(total, startValue, progressBar) {
63
+ if (!progressBar)
64
+ return;
65
+ progressBar.start(total, startValue);
66
+ }
67
+ function updateProgressBar(value, progressBar) {
68
+ if (!progressBar)
69
+ return;
70
+ progressBar.update(value);
71
+ }
72
+ function stopProgressBar(progressBar) {
73
+ if (!progressBar)
74
+ return;
75
+ progressBar.stop();
76
+ }
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toCamelCase = toCamelCase;
4
+ function toCamelCase(str) {
5
+ return str
6
+ .toLowerCase()
7
+ .replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));
8
+ }
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.translationsKeyworadToString = translationsKeyworadToString;
37
+ const ts = __importStar(require("typescript"));
38
+ const constants_1 = require("../constants");
39
+ function translationsKeyworadToString(keyword) {
40
+ switch (keyword) {
41
+ case ts.SyntaxKind.StringKeyword:
42
+ return constants_1.DefinitionsKeywordTypeNodeKey.string;
43
+ case ts.SyntaxKind.NumberKeyword:
44
+ return constants_1.DefinitionsKeywordTypeNodeKey.number;
45
+ case ts.SyntaxKind.BooleanKeyword:
46
+ return constants_1.DefinitionsKeywordTypeNodeKey.boolean;
47
+ case ts.SyntaxKind.ObjectKeyword:
48
+ return constants_1.DefinitionsKeywordTypeNodeKey.object;
49
+ case ts.SyntaxKind.ArrayType:
50
+ return constants_1.DefinitionsKeywordTypeNodeKey.array;
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ ;
package/client/core.ts ADDED
@@ -0,0 +1,114 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ import { fetchResponseHandler } from "./fetch-response-handler";
5
+ import { generateUniqueId } from './utils/generate-unique-id';
6
+
7
+
8
+ async function formatResponse(data: any, response: any) {
9
+ const responseData: {
10
+ status: number;
11
+ trace: string;
12
+ header: Record<string, string>;
13
+ data: Record<string, any> | string | null;
14
+ } = {
15
+ status: response.status,
16
+ trace: response.headers.get('traceparent'),
17
+ header: {
18
+ 'x-cnb-page': response.headers.get('x-cnb-page'),
19
+ 'x-cnb-page-size': response.headers.get('x-cnb-page-size'),
20
+ 'x-cnb-total': response.headers.get('x-cnb-total'),
21
+ },
22
+ data: null,
23
+ };
24
+
25
+ const contentType = response.headers.get('content-type') || '';
26
+ const isJson = [
27
+ 'application/vnd.cnb.api+json',
28
+ 'application/json',
29
+ 'text/json',
30
+ ].some((t) => contentType.includes(t));
31
+ const isText = contentType.startsWith('text/') || contentType.includes('xml');
32
+ const isImage = contentType.startsWith('image/');
33
+ try {
34
+ if (isJson) {
35
+ responseData.data = await response.json();
36
+ } else if (isText) {
37
+ responseData.data = await response.text();
38
+ } else if (isImage) {
39
+ const arrayBuffer = await response.arrayBuffer();
40
+ const buffer = Buffer.from(arrayBuffer);
41
+
42
+ // 确定文件扩展名
43
+ let extension = '.bin';
44
+ if (contentType.includes('png')) extension = '.png';
45
+ else if (contentType.includes('jpeg') || contentType.includes('jpg')) extension = '.jpg';
46
+ else if (contentType.includes('gif')) extension = '.gif';
47
+ else if (contentType.includes('webp')) extension = '.webp';
48
+ else if (contentType.includes('svg')) extension = '.svg';
49
+ // 可以根据需要添加更多类型
50
+
51
+ // 构建本地保存路径
52
+ // 注意:请确保 './downloads' 目录存在,或者使用 fs.mkdirSync 创建它
53
+ const tempDir = os.tmpdir();
54
+ const uploadDir = path.join(tempDir, 'cnb-skill');
55
+ if (!fs.existsSync(uploadDir)) {
56
+ fs.mkdirSync(uploadDir, { recursive: true });
57
+ }
58
+
59
+ const fileName = `${generateUniqueId()}${extension}`;
60
+ const filePath = path.join(uploadDir, fileName);
61
+
62
+ fs.writeFileSync(filePath, buffer);
63
+ responseData.data = filePath;
64
+ } else {
65
+ // 其他二进制数据保持原有的 Base64 逻辑,或者也可以按需保存
66
+ const arrayBuffer = await response.arrayBuffer();
67
+ const buffer = Buffer.from(arrayBuffer);
68
+ const base64String = buffer.toString('base64');
69
+
70
+ responseData.data = {
71
+ type: 'base64',
72
+ data: base64String,
73
+ mimeType: contentType || 'application/octet-stream',
74
+ };
75
+ }
76
+ } catch (err: any) {
77
+ responseData.data = err?.message || 'Unknown Error';
78
+ }
79
+
80
+
81
+ if (responseData.status >= 200 && responseData.status < 300) {
82
+ return await fetchResponseHandler(data._originParams, responseData);
83
+ }
84
+
85
+ return responseData;
86
+ }
87
+
88
+ async function clientFetch(data: any): Promise<any> {
89
+ const domain = process.env.CNB_API_ENDPOINT || 'https://api.cnb.cool'
90
+ const url = `${domain}${data.url}`
91
+ const urlParse = new URL(url);
92
+ if (data.params) {
93
+ // eslint-disable-next-line no-restricted-syntax
94
+ for (const key in data.params) {
95
+ urlParse.searchParams.append(key, data.params[key]);
96
+ }
97
+ }
98
+
99
+ const response = await fetch(urlParse.href, {
100
+ method: data.method.toUpperCase(),
101
+ body: data.data ? JSON.stringify(data.data) : undefined,
102
+ headers: {
103
+ Authorization: `Bearer ${process.env.CNB_TOKEN}`,
104
+ Accept: 'application/vnd.cnb.api+json',
105
+ ...(data?.header || {}),
106
+ },
107
+ });
108
+
109
+ return await formatResponse(data, response);
110
+ }
111
+
112
+ export default {
113
+ request: clientFetch,
114
+ };
@@ -0,0 +1,36 @@
1
+ export async function fetchResponseHandler(fetchOriginParams: Record<string, any>, response: {
2
+ status: number,
3
+ trace: string,
4
+ header: Record<string, string>
5
+ data: Record<string, any> | string | { // 二进制数据标识
6
+ type: 'base64';
7
+ data: string; // base64 字符串
8
+ mimeType: string; // 原始 MIME type,方便模型知道是什么文件
9
+ }
10
+ | null
11
+ }) {
12
+
13
+ const config = require('./config/cag.config.js');
14
+ const responseConverter = config?.skillConfig?.fetchConfig?.responseConverter;
15
+
16
+ if (!responseConverter) {
17
+ return response;
18
+ }
19
+
20
+ const { method, _apiTag } = fetchOriginParams;
21
+ const requestTag = `${method}@${_apiTag}`;
22
+ const convertConfig = responseConverter[requestTag];
23
+ if (convertConfig) {
24
+ const {converter, handler} = convertConfig;
25
+ try {
26
+ const converterExample = require(`./utils/${converter}`).default;
27
+ if (converterExample && typeof converterExample === 'function') {
28
+ return handler(converterExample, fetchOriginParams, response.data);
29
+ }
30
+ } catch (e) {
31
+ console.error(`converter ${converter} not found`);
32
+ }
33
+ }
34
+
35
+ return response;
36
+ }