@farris/cli 2.1.2 → 2.1.3
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/lib/commands/build-components.js +39 -39
- package/lib/commands/build-components.js.map +1 -1
- package/lib/commands/build-css.js +38 -38
- package/lib/commands/build-css.js.map +1 -1
- package/lib/commands/build-lib.js +25 -25
- package/lib/commands/build.js +14 -14
- package/lib/commands/build.js.map +1 -1
- package/lib/commands/create-app.js +54 -54
- package/lib/commands/dev-serve.js +18 -18
- package/lib/commands/extract-i18n.js +74 -74
- package/lib/commands/extract-i18n.js.map +1 -1
- package/lib/commands/generate/api.js +124 -124
- package/lib/commands/generate/api.js.map +1 -1
- package/lib/commands/generate/common.js +100 -100
- package/lib/commands/generate/common.js.map +1 -1
- package/lib/commands/generate/component.js +156 -156
- package/lib/commands/generate/component.js.map +1 -1
- package/lib/commands/generate/view.js +165 -165
- package/lib/commands/generate/view.js.map +1 -1
- package/lib/commands/preview-serve.js +16 -16
- package/lib/commands/workspace/add-app.js +180 -180
- package/lib/commands/workspace/add-app.js.map +1 -1
- package/lib/commands/workspace/create.js +379 -379
- package/lib/commands/workspace/create.js.map +1 -1
- package/lib/commands/workspace/inspect.js +30 -30
- package/lib/commands/workspace/inspect.js.map +1 -1
- package/lib/commands/workspace/verify.js +38 -38
- package/lib/commands/workspace/verify.js.map +1 -1
- package/lib/common/constant.js +64 -63
- package/lib/common/constant.js.map +1 -1
- package/lib/common/generate-app.js +44 -44
- package/lib/common/get-dependencies.js +9 -9
- package/lib/common/get-farris-config.js +11 -11
- package/lib/common/get-farris-config.js.map +1 -1
- package/lib/common/get-version.js +6 -6
- package/lib/common/get-vite-config.js +105 -105
- package/lib/common/get-vite-config.js.map +1 -1
- package/lib/common/output.js +94 -94
- package/lib/common/output.js.map +1 -1
- package/lib/common/safety.js +171 -171
- package/lib/common/safety.js.map +1 -1
- package/lib/common/template-renderer.js +114 -114
- package/lib/common/template-renderer.js.map +1 -1
- package/lib/common/transaction.js +83 -83
- package/lib/common/transaction.js.map +1 -1
- package/lib/common/verifier.js +146 -146
- package/lib/common/verifier.js.map +1 -1
- package/lib/config/vite-app.js +13 -13
- package/lib/config/vite-common.js +20 -20
- package/lib/config/vite-common.js.map +1 -1
- package/lib/config/vite-component.js +30 -30
- package/lib/config/vite-component.js.map +1 -1
- package/lib/config/vite-lib.js +26 -26
- package/lib/index.js +175 -175
- package/lib/plugins/create-component-style.js +44 -44
- package/lib/plugins/create-package-json.js +33 -33
- package/lib/plugins/create-package-json.js.map +1 -1
- package/lib/plugins/dts.js +8 -8
- package/lib/plugins/html-system.js +9 -9
- package/lib/plugins/replace.js +17 -17
- package/lib/plugins/systemjs-bundle.js +15 -15
- package/lib/plugins/systemjs-bundle.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,73 +1,73 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { join } from 'node:path';
|
|
3
|
-
import { findAppContext, normalizeGeneratorName, toPascalCase, toCamelCase } from './common.js';
|
|
4
|
-
import { Transaction } from '../../common/transaction.js';
|
|
5
|
-
import { sendJson, logInfo, fail, setJsonMode, createSpinner } from '../../common/output.js';
|
|
6
|
-
import { ExitCode } from '../../common/constant.js';
|
|
7
|
-
export async function generateApi(rawName, options = {}) {
|
|
8
|
-
const isJson = !!options.json;
|
|
9
|
-
setJsonMode(isJson);
|
|
10
|
-
if (!rawName) {
|
|
11
|
-
fail({
|
|
12
|
-
command: 'generate.api',
|
|
13
|
-
error: '必须指定 API 模块名称: farris-cli generate api <name>',
|
|
14
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
15
|
-
});
|
|
16
|
-
}
|
|
17
|
-
const { endpoint } = options;
|
|
18
|
-
if (!endpoint || typeof endpoint !== 'string' || !endpoint.trim()) {
|
|
19
|
-
fail({
|
|
20
|
-
command: 'generate.api',
|
|
21
|
-
error: '必须指定真实 API endpoint (--endpoint <path>),如: --endpoint /api/v1/orders',
|
|
22
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
23
|
-
});
|
|
24
|
-
}
|
|
25
|
-
const normalizedName = normalizeGeneratorName(rawName);
|
|
26
|
-
if (!normalizedName.valid) {
|
|
27
|
-
fail({
|
|
28
|
-
command: 'generate.api',
|
|
29
|
-
error: `非法的 API 名称: ${normalizedName.error}`,
|
|
30
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
const name = normalizedName.name;
|
|
34
|
-
const pascalName = toPascalCase(name);
|
|
35
|
-
const camelName = toCamelCase(name);
|
|
36
|
-
const method = (options.method || 'get').toLowerCase();
|
|
37
|
-
const appContext = findAppContext(options.cwd || process.cwd());
|
|
38
|
-
const apiDir = join(appContext.srcDir, 'api');
|
|
39
|
-
const targetApiFile = join(apiDir, `${name}.api.ts`);
|
|
40
|
-
const indexPath = join(apiDir, 'index.ts');
|
|
41
|
-
const httpClientPath = join(apiDir, 'http-client.ts');
|
|
42
|
-
if (existsSync(targetApiFile)) {
|
|
43
|
-
fail({
|
|
44
|
-
command: 'generate.api',
|
|
45
|
-
error: `API 文件已存在: ${targetApiFile}`,
|
|
46
|
-
exitCode: ExitCode.TARGET_CONFLICT
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
const hasHttpClient = existsSync(httpClientPath);
|
|
50
|
-
const clientPath = options.client || './http-client';
|
|
51
|
-
if (!hasHttpClient && !options.client && !options.initClient) {
|
|
52
|
-
fail({
|
|
53
|
-
command: 'generate.api',
|
|
54
|
-
error: '未发现现有 HTTP client (src/api/http-client.ts)。请使用 --init-client 初始化标准客户端,或通过 --client <path> 指定已有客户端路径。',
|
|
55
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
const transaction = new Transaction();
|
|
59
|
-
const spinner = createSpinner(`正在生成 API: ${name}...`);
|
|
60
|
-
spinner.start();
|
|
61
|
-
try {
|
|
62
|
-
if (!existsSync(apiDir)) {
|
|
63
|
-
mkdirSync(apiDir, { recursive: true });
|
|
64
|
-
transaction.recordCreatedDir(apiDir);
|
|
65
|
-
}
|
|
66
|
-
const filesCreated = [];
|
|
67
|
-
const filesModified = [];
|
|
68
|
-
// 1. 若需要且不存在,初始化标准 http-client.ts
|
|
69
|
-
if (!hasHttpClient && options.initClient) {
|
|
70
|
-
transaction.prepareWrite(httpClientPath);
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { findAppContext, normalizeGeneratorName, toPascalCase, toCamelCase } from './common.js';
|
|
4
|
+
import { Transaction } from '../../common/transaction.js';
|
|
5
|
+
import { sendJson, logInfo, fail, setJsonMode, createSpinner } from '../../common/output.js';
|
|
6
|
+
import { ExitCode } from '../../common/constant.js';
|
|
7
|
+
export async function generateApi(rawName, options = {}) {
|
|
8
|
+
const isJson = !!options.json;
|
|
9
|
+
setJsonMode(isJson);
|
|
10
|
+
if (!rawName) {
|
|
11
|
+
fail({
|
|
12
|
+
command: 'generate.api',
|
|
13
|
+
error: '必须指定 API 模块名称: farris-cli generate api <name>',
|
|
14
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
const { endpoint } = options;
|
|
18
|
+
if (!endpoint || typeof endpoint !== 'string' || !endpoint.trim()) {
|
|
19
|
+
fail({
|
|
20
|
+
command: 'generate.api',
|
|
21
|
+
error: '必须指定真实 API endpoint (--endpoint <path>),如: --endpoint /api/v1/orders',
|
|
22
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
const normalizedName = normalizeGeneratorName(rawName);
|
|
26
|
+
if (!normalizedName.valid) {
|
|
27
|
+
fail({
|
|
28
|
+
command: 'generate.api',
|
|
29
|
+
error: `非法的 API 名称: ${normalizedName.error}`,
|
|
30
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const name = normalizedName.name;
|
|
34
|
+
const pascalName = toPascalCase(name);
|
|
35
|
+
const camelName = toCamelCase(name);
|
|
36
|
+
const method = (options.method || 'get').toLowerCase();
|
|
37
|
+
const appContext = findAppContext(options.cwd || process.cwd());
|
|
38
|
+
const apiDir = join(appContext.srcDir, 'api');
|
|
39
|
+
const targetApiFile = join(apiDir, `${name}.api.ts`);
|
|
40
|
+
const indexPath = join(apiDir, 'index.ts');
|
|
41
|
+
const httpClientPath = join(apiDir, 'http-client.ts');
|
|
42
|
+
if (existsSync(targetApiFile)) {
|
|
43
|
+
fail({
|
|
44
|
+
command: 'generate.api',
|
|
45
|
+
error: `API 文件已存在: ${targetApiFile}`,
|
|
46
|
+
exitCode: ExitCode.TARGET_CONFLICT
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
const hasHttpClient = existsSync(httpClientPath);
|
|
50
|
+
const clientPath = options.client || './http-client';
|
|
51
|
+
if (!hasHttpClient && !options.client && !options.initClient) {
|
|
52
|
+
fail({
|
|
53
|
+
command: 'generate.api',
|
|
54
|
+
error: '未发现现有 HTTP client (src/api/http-client.ts)。请使用 --init-client 初始化标准客户端,或通过 --client <path> 指定已有客户端路径。',
|
|
55
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
const transaction = new Transaction();
|
|
59
|
+
const spinner = createSpinner(`正在生成 API: ${name}...`);
|
|
60
|
+
spinner.start();
|
|
61
|
+
try {
|
|
62
|
+
if (!existsSync(apiDir)) {
|
|
63
|
+
mkdirSync(apiDir, { recursive: true });
|
|
64
|
+
transaction.recordCreatedDir(apiDir);
|
|
65
|
+
}
|
|
66
|
+
const filesCreated = [];
|
|
67
|
+
const filesModified = [];
|
|
68
|
+
// 1. 若需要且不存在,初始化标准 http-client.ts
|
|
69
|
+
if (!hasHttpClient && options.initClient) {
|
|
70
|
+
transaction.prepareWrite(httpClientPath);
|
|
71
71
|
const clientContent = `/**
|
|
72
72
|
* Farris 标准 HTTP 请求客户端封装
|
|
73
73
|
*/
|
|
@@ -106,12 +106,12 @@ export async function request<T = any>(url: string, options: RequestOptions = {}
|
|
|
106
106
|
|
|
107
107
|
return response.json();
|
|
108
108
|
}
|
|
109
|
-
`;
|
|
110
|
-
writeFileSync(httpClientPath, clientContent, 'utf-8');
|
|
111
|
-
filesCreated.push(httpClientPath);
|
|
112
|
-
}
|
|
113
|
-
// 2. 生成 API 文件: src/api/<name>.api.ts
|
|
114
|
-
transaction.prepareWrite(targetApiFile);
|
|
109
|
+
`;
|
|
110
|
+
writeFileSync(httpClientPath, clientContent, 'utf-8');
|
|
111
|
+
filesCreated.push(httpClientPath);
|
|
112
|
+
}
|
|
113
|
+
// 2. 生成 API 文件: src/api/<name>.api.ts
|
|
114
|
+
transaction.prepareWrite(targetApiFile);
|
|
115
115
|
const apiFunctionContent = `import { request } from ${JSON.stringify(clientPath)};
|
|
116
116
|
|
|
117
117
|
export interface ${pascalName}Item {
|
|
@@ -137,52 +137,52 @@ export async function get${pascalName}List(params?: ${pascalName}Params): Promis
|
|
|
137
137
|
params
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
|
-
`;
|
|
141
|
-
writeFileSync(targetApiFile, apiFunctionContent, 'utf-8');
|
|
142
|
-
filesCreated.push(targetApiFile);
|
|
143
|
-
// 3. 维护 src/api/index.ts
|
|
144
|
-
transaction.prepareWrite(indexPath);
|
|
145
|
-
let indexContent = existsSync(indexPath) ? readFileSync(indexPath, 'utf-8') : '';
|
|
146
|
-
const exportStatement = `export * from './${name}.api';\n`;
|
|
147
|
-
if (!indexContent.includes(`./${name}.api`)) {
|
|
148
|
-
indexContent += exportStatement;
|
|
149
|
-
writeFileSync(indexPath, indexContent, 'utf-8');
|
|
150
|
-
if (existsSync(indexPath)) {
|
|
151
|
-
filesModified.push(indexPath);
|
|
152
|
-
}
|
|
153
|
-
else {
|
|
154
|
-
filesCreated.push(indexPath);
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
transaction.commit();
|
|
158
|
-
spinner.succeed(`API ${name} 生成成功!`);
|
|
159
|
-
if (isJson) {
|
|
160
|
-
sendJson({
|
|
161
|
-
command: 'generate.api',
|
|
162
|
-
ok: true,
|
|
163
|
-
apiName: name,
|
|
164
|
-
endpoint,
|
|
165
|
-
method,
|
|
166
|
-
targetApiFile,
|
|
167
|
-
filesCreated,
|
|
168
|
-
filesModified
|
|
169
|
-
});
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
logInfo(`\n✨ 已成功生成 API: src/api/${name}.api.ts`);
|
|
173
|
-
filesCreated.forEach((f) => logInfo(` + ${f}`));
|
|
174
|
-
if (filesModified.length > 0) {
|
|
175
|
-
filesModified.forEach((f) => logInfo(` ~ ${f} (更新导出)`));
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
catch (err) {
|
|
179
|
-
spinner.fail('生成 API 失败,正在回滚...');
|
|
180
|
-
transaction.rollback();
|
|
181
|
-
fail({
|
|
182
|
-
command: 'generate.api',
|
|
183
|
-
error: `生成 API 失败: ${err.message}`,
|
|
184
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
185
|
-
});
|
|
186
|
-
}
|
|
187
|
-
}
|
|
140
|
+
`;
|
|
141
|
+
writeFileSync(targetApiFile, apiFunctionContent, 'utf-8');
|
|
142
|
+
filesCreated.push(targetApiFile);
|
|
143
|
+
// 3. 维护 src/api/index.ts
|
|
144
|
+
transaction.prepareWrite(indexPath);
|
|
145
|
+
let indexContent = existsSync(indexPath) ? readFileSync(indexPath, 'utf-8') : '';
|
|
146
|
+
const exportStatement = `export * from './${name}.api';\n`;
|
|
147
|
+
if (!indexContent.includes(`./${name}.api`)) {
|
|
148
|
+
indexContent += exportStatement;
|
|
149
|
+
writeFileSync(indexPath, indexContent, 'utf-8');
|
|
150
|
+
if (existsSync(indexPath)) {
|
|
151
|
+
filesModified.push(indexPath);
|
|
152
|
+
}
|
|
153
|
+
else {
|
|
154
|
+
filesCreated.push(indexPath);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
transaction.commit();
|
|
158
|
+
spinner.succeed(`API ${name} 生成成功!`);
|
|
159
|
+
if (isJson) {
|
|
160
|
+
sendJson({
|
|
161
|
+
command: 'generate.api',
|
|
162
|
+
ok: true,
|
|
163
|
+
apiName: name,
|
|
164
|
+
endpoint,
|
|
165
|
+
method,
|
|
166
|
+
targetApiFile,
|
|
167
|
+
filesCreated,
|
|
168
|
+
filesModified
|
|
169
|
+
});
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
logInfo(`\n✨ 已成功生成 API: src/api/${name}.api.ts`);
|
|
173
|
+
filesCreated.forEach((f) => logInfo(` + ${f}`));
|
|
174
|
+
if (filesModified.length > 0) {
|
|
175
|
+
filesModified.forEach((f) => logInfo(` ~ ${f} (更新导出)`));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch (err) {
|
|
179
|
+
spinner.fail('生成 API 失败,正在回滚...');
|
|
180
|
+
transaction.rollback();
|
|
181
|
+
fail({
|
|
182
|
+
command: 'generate.api',
|
|
183
|
+
error: `生成 API 失败: ${err.message}`,
|
|
184
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
188
|
//# sourceMappingURL=api.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/commands/generate/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAW,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EACL,cAAc,EACd,sBAAsB,EACtB,YAAY,EACZ,WAAW,EACZ,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAC1D,OAAO,EACL,QAAQ,EACR,OAAO,EAEP,IAAI,EACJ,WAAW,EACX,aAAa,EACd,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAWpD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAe,EAAE,UAA8B,EAAE;IACjF,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC;IAC9B,WAAW,CAAC,MAAM,CAAC,CAAC;IAEpB,IAAI,CAAC,OAAO,EAAE;
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/commands/generate/api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,101 +1,101 @@
|
|
|
1
|
-
import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
|
|
2
|
-
import { resolve, join, dirname } from 'node:path';
|
|
3
|
-
import { fail } from '../../common/output.js';
|
|
4
|
-
import { ExitCode } from '../../common/constant.js';
|
|
5
|
-
export function toKebabCase(str) {
|
|
6
|
-
return str
|
|
7
|
-
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
8
|
-
.replace(/[\s_]+/g, '-')
|
|
9
|
-
.toLowerCase()
|
|
10
|
-
.replace(/^-+|-+$/g, '');
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* 生成器名称必须可安全地映射为文件名和 TypeScript 标识符。
|
|
14
|
-
* 先校验原始输入,避免 toKebabCase 保留路径分隔符后造成目录穿越。
|
|
15
|
-
*/
|
|
16
|
-
export function normalizeGeneratorName(value) {
|
|
17
|
-
const raw = typeof value === 'string' ? value.trim() : '';
|
|
18
|
-
if (!raw) {
|
|
19
|
-
return { valid: false, error: '名称不能为空' };
|
|
20
|
-
}
|
|
21
|
-
if (!/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/.test(raw)) {
|
|
22
|
-
return {
|
|
23
|
-
valid: false,
|
|
24
|
-
error: '名称仅支持字母、数字和短横线,且不能以短横线开头或结尾'
|
|
25
|
-
};
|
|
26
|
-
}
|
|
27
|
-
return { valid: true, name: toKebabCase(raw) };
|
|
28
|
-
}
|
|
29
|
-
export function toPascalCase(str) {
|
|
30
|
-
const kebab = toKebabCase(str);
|
|
31
|
-
return kebab
|
|
32
|
-
.split('-')
|
|
33
|
-
.filter(Boolean)
|
|
34
|
-
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
35
|
-
.join('');
|
|
36
|
-
}
|
|
37
|
-
export function toCamelCase(str) {
|
|
38
|
-
const pascal = toPascalCase(str);
|
|
39
|
-
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
40
|
-
}
|
|
41
|
-
export function toReadableTitle(str) {
|
|
42
|
-
const kebab = toKebabCase(str);
|
|
43
|
-
return kebab
|
|
44
|
-
.split('-')
|
|
45
|
-
.filter(Boolean)
|
|
46
|
-
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
47
|
-
.join(' ');
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* 向上查找当前所在应用目录
|
|
51
|
-
*/
|
|
52
|
-
export function findAppContext(startDir = process.cwd()) {
|
|
53
|
-
let current = resolve(startDir);
|
|
54
|
-
while (true) {
|
|
55
|
-
const pkgPath = join(current, 'package.json');
|
|
56
|
-
const srcPath = join(current, 'src');
|
|
57
|
-
if (existsSync(pkgPath) && existsSync(srcPath) && statSync(srcPath).isDirectory()) {
|
|
58
|
-
try {
|
|
59
|
-
const pkgContent = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
60
|
-
// 排除根 workspace 的 package.json (根一般有 pnpm-workspace.yaml 且无 src)
|
|
61
|
-
return {
|
|
62
|
-
appRoot: current,
|
|
63
|
-
srcDir: srcPath,
|
|
64
|
-
pkgJsonPath: pkgPath,
|
|
65
|
-
pkgJson: pkgContent
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
// 继续查找
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
const parent = dirname(current);
|
|
73
|
-
if (parent === current) {
|
|
74
|
-
break;
|
|
75
|
-
}
|
|
76
|
-
current = parent;
|
|
77
|
-
}
|
|
78
|
-
// 检查是否在 workspace 根目录执行
|
|
79
|
-
const wsYaml = join(startDir, 'pnpm-workspace.yaml');
|
|
80
|
-
if (existsSync(wsYaml)) {
|
|
81
|
-
const packagesDir = join(startDir, 'packages');
|
|
82
|
-
if (existsSync(packagesDir)) {
|
|
83
|
-
const apps = readdirSync(packagesDir).filter((d) => statSync(join(packagesDir, d)).isDirectory());
|
|
84
|
-
if (apps.length === 1) {
|
|
85
|
-
const singleAppDir = join(packagesDir, apps[0]);
|
|
86
|
-
return findAppContext(singleAppDir);
|
|
87
|
-
}
|
|
88
|
-
fail({
|
|
89
|
-
command: 'generate',
|
|
90
|
-
error: `当前处于 Workspace 根目录,存在多个应用 (${apps.join(', ')})。请先进入具体应用目录 (如 cd packages/${apps[0]}) 后再执行 generate 命令。`,
|
|
91
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
fail({
|
|
96
|
-
command: 'generate',
|
|
97
|
-
error: '未找到合法的前端应用工程目录 (必须包含 package.json 与 src/ 目录)',
|
|
98
|
-
exitCode: ExitCode.GENERAL_ERROR
|
|
99
|
-
});
|
|
100
|
-
}
|
|
1
|
+
import { existsSync, readdirSync, statSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { resolve, join, dirname } from 'node:path';
|
|
3
|
+
import { fail } from '../../common/output.js';
|
|
4
|
+
import { ExitCode } from '../../common/constant.js';
|
|
5
|
+
export function toKebabCase(str) {
|
|
6
|
+
return str
|
|
7
|
+
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
|
8
|
+
.replace(/[\s_]+/g, '-')
|
|
9
|
+
.toLowerCase()
|
|
10
|
+
.replace(/^-+|-+$/g, '');
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* 生成器名称必须可安全地映射为文件名和 TypeScript 标识符。
|
|
14
|
+
* 先校验原始输入,避免 toKebabCase 保留路径分隔符后造成目录穿越。
|
|
15
|
+
*/
|
|
16
|
+
export function normalizeGeneratorName(value) {
|
|
17
|
+
const raw = typeof value === 'string' ? value.trim() : '';
|
|
18
|
+
if (!raw) {
|
|
19
|
+
return { valid: false, error: '名称不能为空' };
|
|
20
|
+
}
|
|
21
|
+
if (!/^[A-Za-z0-9]+(?:-[A-Za-z0-9]+)*$/.test(raw)) {
|
|
22
|
+
return {
|
|
23
|
+
valid: false,
|
|
24
|
+
error: '名称仅支持字母、数字和短横线,且不能以短横线开头或结尾'
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
return { valid: true, name: toKebabCase(raw) };
|
|
28
|
+
}
|
|
29
|
+
export function toPascalCase(str) {
|
|
30
|
+
const kebab = toKebabCase(str);
|
|
31
|
+
return kebab
|
|
32
|
+
.split('-')
|
|
33
|
+
.filter(Boolean)
|
|
34
|
+
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
|
|
35
|
+
.join('');
|
|
36
|
+
}
|
|
37
|
+
export function toCamelCase(str) {
|
|
38
|
+
const pascal = toPascalCase(str);
|
|
39
|
+
return pascal.charAt(0).toLowerCase() + pascal.slice(1);
|
|
40
|
+
}
|
|
41
|
+
export function toReadableTitle(str) {
|
|
42
|
+
const kebab = toKebabCase(str);
|
|
43
|
+
return kebab
|
|
44
|
+
.split('-')
|
|
45
|
+
.filter(Boolean)
|
|
46
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
47
|
+
.join(' ');
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 向上查找当前所在应用目录
|
|
51
|
+
*/
|
|
52
|
+
export function findAppContext(startDir = process.cwd()) {
|
|
53
|
+
let current = resolve(startDir);
|
|
54
|
+
while (true) {
|
|
55
|
+
const pkgPath = join(current, 'package.json');
|
|
56
|
+
const srcPath = join(current, 'src');
|
|
57
|
+
if (existsSync(pkgPath) && existsSync(srcPath) && statSync(srcPath).isDirectory()) {
|
|
58
|
+
try {
|
|
59
|
+
const pkgContent = JSON.parse(readFileSync(pkgPath, 'utf-8'));
|
|
60
|
+
// 排除根 workspace 的 package.json (根一般有 pnpm-workspace.yaml 且无 src)
|
|
61
|
+
return {
|
|
62
|
+
appRoot: current,
|
|
63
|
+
srcDir: srcPath,
|
|
64
|
+
pkgJsonPath: pkgPath,
|
|
65
|
+
pkgJson: pkgContent
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
// 继续查找
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
const parent = dirname(current);
|
|
73
|
+
if (parent === current) {
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
current = parent;
|
|
77
|
+
}
|
|
78
|
+
// 检查是否在 workspace 根目录执行
|
|
79
|
+
const wsYaml = join(startDir, 'pnpm-workspace.yaml');
|
|
80
|
+
if (existsSync(wsYaml)) {
|
|
81
|
+
const packagesDir = join(startDir, 'packages');
|
|
82
|
+
if (existsSync(packagesDir)) {
|
|
83
|
+
const apps = readdirSync(packagesDir).filter((d) => statSync(join(packagesDir, d)).isDirectory());
|
|
84
|
+
if (apps.length === 1) {
|
|
85
|
+
const singleAppDir = join(packagesDir, apps[0]);
|
|
86
|
+
return findAppContext(singleAppDir);
|
|
87
|
+
}
|
|
88
|
+
fail({
|
|
89
|
+
command: 'generate',
|
|
90
|
+
error: `当前处于 Workspace 根目录,存在多个应用 (${apps.join(', ')})。请先进入具体应用目录 (如 cd packages/${apps[0]}) 后再执行 generate 命令。`,
|
|
91
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
fail({
|
|
96
|
+
command: 'generate',
|
|
97
|
+
error: '未找到合法的前端应用工程目录 (必须包含 package.json 与 src/ 目录)',
|
|
98
|
+
exitCode: ExitCode.GENERAL_ERROR
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
101
|
//# sourceMappingURL=common.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/commands/generate/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,wBAAwB,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEpD,MAAM,UAAU,WAAW,CAAC,GAAW;IACrC,OAAO,GAAG;SACP,OAAO,CAAC,iBAAiB,EAAE,OAAO,CAAC;SACnC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC;SACvB,WAAW,EAAE;SACb,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa;IAClD,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,IAAI,CAAC,GAAG,EAAE;
|
|
1
|
+
{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/commands/generate/common.ts"],"names":[],"mappings":"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"}
|