@robot-admin/git-standards 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.
package/dist/index.js ADDED
@@ -0,0 +1,1228 @@
1
+ // src/configs/lint-staged.ts
2
+ function createLintStagedConfig(options = {}) {
3
+ const codePattern = options.filePatterns?.code || "src/**/*.{js,jsx,ts,tsx,vue}";
4
+ const markupPattern = options.filePatterns?.markup || "*.{json,md,yml,yaml}";
5
+ const codeCommands = [];
6
+ if (options.oxlint !== false) {
7
+ codeCommands.push("oxlint --max-warnings 0 --deny-warnings");
8
+ }
9
+ if (options.eslint !== false) {
10
+ codeCommands.push("eslint --fix --no-cache");
11
+ }
12
+ if (options.prettier !== false) {
13
+ codeCommands.push("prettier --write");
14
+ }
15
+ const config = {};
16
+ if (codeCommands.length > 0) {
17
+ config[codePattern] = codeCommands;
18
+ }
19
+ if (options.prettier !== false) {
20
+ config[markupPattern] = ["prettier --write"];
21
+ }
22
+ return config;
23
+ }
24
+ function generateLintStagedConfig(options = {}) {
25
+ return createLintStagedConfig(options);
26
+ }
27
+
28
+ // src/cli/init.ts
29
+ import { resolve as resolve4 } from "path";
30
+ import { unlinkSync, existsSync as existsSync4, rmSync } from "fs";
31
+ import chalk from "chalk";
32
+ import ora from "ora";
33
+ import { execa as execa2 } from "execa";
34
+
35
+ // src/utils/package-manager.ts
36
+ import { existsSync } from "fs";
37
+ import { resolve } from "path";
38
+ async function detectPackageManager(cwd = process.cwd()) {
39
+ if (existsSync(resolve(cwd, "bun.lockb")) || existsSync(resolve(cwd, "bun.lock"))) {
40
+ return "bun";
41
+ }
42
+ if (existsSync(resolve(cwd, "pnpm-lock.yaml"))) {
43
+ return "pnpm";
44
+ }
45
+ if (existsSync(resolve(cwd, "yarn.lock"))) {
46
+ return "yarn";
47
+ }
48
+ if (existsSync(resolve(cwd, "package-lock.json"))) {
49
+ return "npm";
50
+ }
51
+ return "npm";
52
+ }
53
+ function getInstallCommand(pm) {
54
+ const commands = {
55
+ npm: "npm install --save-dev",
56
+ yarn: "yarn add --dev",
57
+ pnpm: "pnpm add -D",
58
+ bun: "bun add --dev"
59
+ };
60
+ return commands[pm];
61
+ }
62
+ function getExecCommand(pm) {
63
+ const commands = {
64
+ npm: "npx --no",
65
+ yarn: "yarn",
66
+ pnpm: "pnpm dlx",
67
+ bun: "bunx"
68
+ };
69
+ return commands[pm];
70
+ }
71
+ function getPackageManagerName(pm) {
72
+ const names = {
73
+ npm: "npm",
74
+ yarn: "Yarn",
75
+ pnpm: "pnpm",
76
+ bun: "Bun"
77
+ };
78
+ return names[pm];
79
+ }
80
+
81
+ // src/utils/git.ts
82
+ import { existsSync as existsSync2 } from "fs";
83
+ import { resolve as resolve2 } from "path";
84
+ import { execa } from "execa";
85
+ function isGitRepository(cwd = process.cwd()) {
86
+ return existsSync2(resolve2(cwd, ".git"));
87
+ }
88
+ async function initGitRepository(cwd = process.cwd()) {
89
+ if (!isGitRepository(cwd)) {
90
+ await execa("git", ["init"], { cwd });
91
+ }
92
+ }
93
+
94
+ // src/utils/file.ts
95
+ import { existsSync as existsSync3 } from "fs";
96
+ import { readFile, writeFile, mkdir } from "fs/promises";
97
+ import { resolve as resolve3, dirname } from "path";
98
+ function fileExists(filePath) {
99
+ return existsSync3(filePath);
100
+ }
101
+ async function readFileContent(filePath) {
102
+ return await readFile(filePath, "utf-8");
103
+ }
104
+ async function writeFileContent(filePath, content) {
105
+ const dir = dirname(filePath);
106
+ if (!existsSync3(dir)) {
107
+ await mkdir(dir, { recursive: true });
108
+ }
109
+ await writeFile(filePath, content, "utf-8");
110
+ }
111
+ async function readJsonFile(filePath) {
112
+ const content = await readFileContent(filePath);
113
+ return JSON.parse(content);
114
+ }
115
+ async function writeJsonFile(filePath, data, pretty = true) {
116
+ const content = pretty ? JSON.stringify(data, null, 2) + "\n" : JSON.stringify(data);
117
+ await writeFileContent(filePath, content);
118
+ }
119
+ async function updatePackageJson(updates, cwd = process.cwd()) {
120
+ const packageJsonPath = resolve3(cwd, "package.json");
121
+ const packageJson = await readJsonFile(packageJsonPath);
122
+ const updated = { ...packageJson, ...updates };
123
+ await writeJsonFile(packageJsonPath, updated);
124
+ }
125
+
126
+ // src/cli/init.ts
127
+ var BRAND = "#7C3AED";
128
+ var S = {
129
+ LOGO: chalk.hex(BRAND).bold("[RS]"),
130
+ OK: chalk.green("\u2714"),
131
+ FAIL: chalk.red("\u2716"),
132
+ WARN: chalk.yellow("\u25B2"),
133
+ STEP: chalk.hex(BRAND)("\u25C6"),
134
+ ARROW: chalk.cyan("\u25B8"),
135
+ DOT: chalk.gray("\u25CF"),
136
+ INFO: chalk.blue("\u2139"),
137
+ LINE: chalk.gray("\u2500".repeat(48))
138
+ };
139
+ var PRESETS = {
140
+ minimal: {
141
+ name: "\u6781\u7B80\u6A21\u5F0F",
142
+ desc: "\u4EC5 Git \u63D0\u4EA4\u89C4\u8303 (Commitizen + Commitlint)",
143
+ features: {
144
+ eslint: false,
145
+ lintStaged: false,
146
+ prettier: false,
147
+ oxlint: false,
148
+ editorconfig: false
149
+ }
150
+ },
151
+ standard: {
152
+ name: "\u6807\u51C6\u6A21\u5F0F",
153
+ desc: "\u63D0\u4EA4\u89C4\u8303 + \u4EE3\u7801\u8D28\u91CF\u68C0\u67E5 (+ ESLint + lint-staged)",
154
+ features: {
155
+ eslint: true,
156
+ lintStaged: true,
157
+ prettier: false,
158
+ oxlint: false,
159
+ editorconfig: true
160
+ }
161
+ },
162
+ full: {
163
+ name: "\u5B8C\u6574\u6A21\u5F0F",
164
+ desc: "\u5168\u90E8\u5DE5\u5177\u94FE (+ Prettier + Oxlint + EditorConfig)",
165
+ features: {
166
+ eslint: true,
167
+ lintStaged: true,
168
+ prettier: true,
169
+ oxlint: true,
170
+ editorconfig: true
171
+ }
172
+ }
173
+ };
174
+ async function init(options = {}) {
175
+ const cwd = options.cwd || process.cwd();
176
+ printBanner();
177
+ console.log(` ${S.STEP} ${chalk.bold("\u73AF\u5883\u68C0\u6D4B")}`);
178
+ console.log();
179
+ if (!isGitRepository(cwd)) {
180
+ const spinner = ora({
181
+ text: chalk.gray("\u521D\u59CB\u5316 Git \u4ED3\u5E93..."),
182
+ prefixText: " ",
183
+ spinner: "dots"
184
+ }).start();
185
+ await initGitRepository(cwd);
186
+ spinner.succeed(chalk.white("Git \u4ED3\u5E93\u521D\u59CB\u5316\u5B8C\u6210"));
187
+ } else {
188
+ console.log(` ${S.OK} Git \u4ED3\u5E93\u5DF2\u5C31\u7EEA`);
189
+ }
190
+ const pm = await detectPackageManager(cwd);
191
+ const pmName = getPackageManagerName(pm);
192
+ console.log(` ${S.OK} \u5305\u7BA1\u7406\u5668: ${chalk.cyan.bold(pmName)}`);
193
+ console.log();
194
+ let features;
195
+ let eslintOpts = {
196
+ framework: "vue",
197
+ typescript: true,
198
+ jsdoc: false
199
+ };
200
+ if (options.ci) {
201
+ const presetId = options.preset || "standard";
202
+ if (presetId === "custom") {
203
+ features = {
204
+ eslint: true,
205
+ lintStaged: true,
206
+ prettier: options.prettier ?? true,
207
+ oxlint: options.oxlint ?? true,
208
+ editorconfig: true
209
+ };
210
+ } else {
211
+ features = { ...PRESETS[presetId].features };
212
+ }
213
+ if (options.prettier !== void 0) features.prettier = options.prettier;
214
+ if (options.oxlint !== void 0) features.oxlint = options.oxlint;
215
+ const jsdocDefault = presetId === "full" ? true : false;
216
+ eslintOpts = {
217
+ framework: options.framework || "vue",
218
+ typescript: options.typescript ?? true,
219
+ jsdoc: options.jsdoc ?? jsdocDefault
220
+ };
221
+ console.log(
222
+ ` ${S.INFO} ${chalk.gray("CI \u6A21\u5F0F")} ${chalk.white(
223
+ "\u9884\u8BBE:"
224
+ )} ${chalk.cyan(presetId)}`
225
+ );
226
+ console.log();
227
+ } else {
228
+ const result = await interactiveSetup(options);
229
+ features = result.features;
230
+ eslintOpts = result.eslintOpts;
231
+ }
232
+ printSummary(features, eslintOpts, pmName);
233
+ if (!options.ci) {
234
+ const { confirm } = await import("@inquirer/prompts");
235
+ const proceed = await confirm({
236
+ message: chalk.white("\u786E\u8BA4\u4EE5\u4E0A\u914D\u7F6E\u5E76\u5F00\u59CB\u5B89\u88C5?"),
237
+ default: true,
238
+ theme: { prefix: ` ${S.ARROW}` }
239
+ });
240
+ if (!proceed) {
241
+ console.log();
242
+ console.log(` ${S.INFO} ${chalk.gray("\u91CD\u65B0\u9009\u62E9\u914D\u7F6E...")}`);
243
+ console.log();
244
+ const result = await interactiveSetup(options);
245
+ features = result.features;
246
+ eslintOpts = result.eslintOpts;
247
+ printSummary(features, eslintOpts, pmName);
248
+ }
249
+ }
250
+ console.log();
251
+ await installDependencies(cwd, pm, features, eslintOpts);
252
+ await generateConfigFiles(cwd, features, eslintOpts);
253
+ await setupHusky(cwd, pm, features);
254
+ await addPackageScripts(cwd, pm, features);
255
+ printCompletion(pm, features);
256
+ }
257
+ function printBanner() {
258
+ console.log();
259
+ console.log(S.LINE);
260
+ console.log(
261
+ ` ${S.LOGO} ${chalk.bold("Robot Standards")} ${chalk.gray("v1.0.0")}`
262
+ );
263
+ console.log(` ${chalk.gray("\u96F6\u914D\u7F6E \xB7 \u6A21\u5757\u5316 \xB7 Git \u5DE5\u7A0B\u5316\u6807\u51C6\u5DE5\u5177\u5305")}`);
264
+ console.log(S.LINE);
265
+ console.log();
266
+ }
267
+ async function interactiveSetup(options) {
268
+ const { select, checkbox, confirm } = await import("@inquirer/prompts");
269
+ while (true) {
270
+ console.log(` ${S.STEP} ${chalk.bold("\u9009\u62E9\u6A21\u5F0F")}`);
271
+ console.log();
272
+ const presetId = await select({
273
+ message: chalk.white("\u9009\u62E9\u9884\u8BBE\u65B9\u6848"),
274
+ choices: [
275
+ {
276
+ name: `\u6781\u7B80\u6A21\u5F0F ${chalk.gray(
277
+ "\u2500\u2500 \u4EC5\u63D0\u4EA4\u89C4\u8303 (Commitizen + Commitlint)"
278
+ )}`,
279
+ value: "minimal",
280
+ description: chalk.gray("\u9002\u5408\u53EA\u9700\u89C4\u8303\u63D0\u4EA4\u4FE1\u606F\u7684\u9879\u76EE")
281
+ },
282
+ {
283
+ name: `\u6807\u51C6\u6A21\u5F0F ${chalk.gray("\u2500\u2500 \u63D0\u4EA4\u89C4\u8303 + \u4EE3\u7801\u68C0\u67E5 (+ ESLint)")}`,
284
+ value: "standard",
285
+ description: chalk.gray("\u9002\u5408\u5927\u591A\u6570\u9879\u76EE")
286
+ },
287
+ {
288
+ name: `\u5B8C\u6574\u6A21\u5F0F ${chalk.gray(
289
+ "\u2500\u2500 \u5168\u90E8\u5DE5\u5177\u94FE (+ Prettier + Oxlint)"
290
+ )} ${chalk.hex(BRAND)("\u4E3B\u9879\u76EE(Robot_Admin)")}`,
291
+ value: "full",
292
+ description: chalk.gray("\u5168\u9762\u4EE3\u7801\u8D28\u91CF\u7BA1\u63A7")
293
+ },
294
+ {
295
+ name: `\u81EA\u5B9A\u4E49 ${chalk.gray("\u2500\u2500 \u81EA\u7531\u7EC4\u5408\u9700\u8981\u7684\u5DE5\u5177\u94FE")}`,
296
+ value: "custom",
297
+ description: chalk.gray("\u7CBE\u786E\u63A7\u5236\u6BCF\u4E2A\u529F\u80FD\u6A21\u5757")
298
+ }
299
+ ],
300
+ default: "standard",
301
+ theme: { prefix: ` ${S.ARROW}` }
302
+ });
303
+ let features;
304
+ if (presetId === "custom") {
305
+ console.log();
306
+ console.log(
307
+ ` ${S.STEP} ${chalk.bold("\u9009\u62E9\u529F\u80FD")} ${chalk.gray(
308
+ "(Git \u63D0\u4EA4\u89C4\u8303\u9ED8\u8BA4\u5305\u542B)"
309
+ )}`
310
+ );
311
+ console.log();
312
+ const selected = await checkbox({
313
+ message: chalk.white("\u9009\u62E9\u9644\u52A0\u529F\u80FD (\u7A7A\u683C\u5207\u6362, \u56DE\u8F66\u786E\u8BA4)"),
314
+ choices: [
315
+ {
316
+ name: `ESLint ${chalk.gray("\u4EE3\u7801\u8D28\u91CF\u68C0\u67E5")}`,
317
+ value: "eslint"
318
+ },
319
+ {
320
+ name: `lint-staged ${chalk.gray("\u6682\u5B58\u533A\u589E\u91CF\u68C0\u67E5")}`,
321
+ value: "lintStaged"
322
+ },
323
+ {
324
+ name: `Prettier ${chalk.gray("\u4EE3\u7801\u81EA\u52A8\u683C\u5F0F\u5316")}`,
325
+ value: "prettier"
326
+ },
327
+ {
328
+ name: `Oxlint ${chalk.gray(
329
+ "\u9AD8\u6027\u80FD Lint \u5F15\u64CE (50x faster)"
330
+ )}`,
331
+ value: "oxlint"
332
+ },
333
+ {
334
+ name: `EditorConfig ${chalk.gray("\u7F16\u8F91\u5668\u7EDF\u4E00\u914D\u7F6E")}`,
335
+ value: "editorconfig"
336
+ },
337
+ {
338
+ name: chalk.yellow("\u21A9 \u8FD4\u56DE\u4E0A\u4E00\u6B65"),
339
+ value: "__back__"
340
+ }
341
+ ],
342
+ theme: { prefix: ` ${S.ARROW}` }
343
+ });
344
+ if (selected.includes("__back__")) continue;
345
+ features = {
346
+ eslint: selected.includes("eslint"),
347
+ lintStaged: selected.includes("lintStaged"),
348
+ prettier: selected.includes("prettier"),
349
+ oxlint: selected.includes("oxlint"),
350
+ editorconfig: selected.includes("editorconfig")
351
+ };
352
+ if (features.oxlint && !features.eslint) {
353
+ console.log(
354
+ `
355
+ ${S.INFO} ${chalk.gray(
356
+ "Oxlint \u9700\u8981 ESLint \u914D\u5408\uFF0C\u5DF2\u81EA\u52A8\u542F\u7528 ESLint"
357
+ )}`
358
+ );
359
+ features.eslint = true;
360
+ }
361
+ if (features.lintStaged && !features.eslint && !features.prettier) {
362
+ console.log(
363
+ `
364
+ ${S.INFO} ${chalk.gray(
365
+ "lint-staged \u9700\u8981 ESLint \u6216 Prettier\uFF0C\u5DF2\u81EA\u52A8\u542F\u7528 ESLint"
366
+ )}`
367
+ );
368
+ features.eslint = true;
369
+ }
370
+ } else {
371
+ features = { ...PRESETS[presetId].features };
372
+ }
373
+ let eslintOpts = {
374
+ framework: "vue",
375
+ typescript: true,
376
+ jsdoc: false
377
+ };
378
+ if (features.eslint) {
379
+ console.log();
380
+ console.log(` ${S.STEP} ${chalk.bold("ESLint \u914D\u7F6E")}`);
381
+ console.log();
382
+ const framework = await select({
383
+ message: chalk.white("\u9879\u76EE\u6846\u67B6"),
384
+ choices: [
385
+ {
386
+ name: "Vue 3",
387
+ value: "vue"
388
+ },
389
+ { name: "React", value: "react" },
390
+ { name: "Vanilla JS / TS", value: "vanilla" },
391
+ {
392
+ name: chalk.yellow("\u21A9 \u8FD4\u56DE\u4E0A\u4E00\u6B65"),
393
+ value: "__back__"
394
+ }
395
+ ],
396
+ default: options.framework || "vue",
397
+ theme: { prefix: ` ${S.ARROW}` }
398
+ });
399
+ if (framework === "__back__") continue;
400
+ const typescript = await confirm({
401
+ message: chalk.white("\u4F7F\u7528 TypeScript"),
402
+ default: options.typescript ?? true,
403
+ theme: { prefix: ` ${S.ARROW}` }
404
+ });
405
+ const jsdoc = await confirm({
406
+ message: chalk.white("\u5F3A\u5236 JSDoc \u6CE8\u91CA"),
407
+ default: options.jsdoc ?? true,
408
+ theme: { prefix: ` ${S.ARROW}` }
409
+ });
410
+ eslintOpts = { framework, typescript, jsdoc };
411
+ }
412
+ return { features, eslintOpts };
413
+ }
414
+ }
415
+ function printSummary(features, eslintOpts, pmName) {
416
+ console.log();
417
+ console.log(` ${S.STEP} ${chalk.bold("\u914D\u7F6E\u6458\u8981")}`);
418
+ console.log();
419
+ console.log(
420
+ ` ${S.OK} ${chalk.white("\u6838\u5FC3")} Commitizen + Commitlint + Husky`
421
+ );
422
+ if (features.eslint) {
423
+ const fw = eslintOpts.framework === "vue" ? "Vue 3" : eslintOpts.framework === "react" ? "React" : "Vanilla";
424
+ const ts = eslintOpts.typescript ? " + TS" : "";
425
+ const jsdoc = eslintOpts.jsdoc ? " + JSDoc" : "";
426
+ console.log(
427
+ ` ${S.OK} ${chalk.white("\u68C0\u67E5")} ESLint (${fw}${ts}${jsdoc})`
428
+ );
429
+ }
430
+ if (features.lintStaged) {
431
+ console.log(` ${S.OK} ${chalk.white("\u6682\u5B58")} lint-staged`);
432
+ }
433
+ if (features.oxlint) {
434
+ console.log(
435
+ ` ${S.OK} ${chalk.white("\u52A0\u901F")} Oxlint ${chalk.gray("(50x faster)")}`
436
+ );
437
+ }
438
+ if (features.prettier) {
439
+ console.log(` ${S.OK} ${chalk.white("\u683C\u5F0F")} Prettier`);
440
+ }
441
+ if (features.editorconfig) {
442
+ console.log(` ${S.OK} ${chalk.white("\u7F16\u8F91")} EditorConfig`);
443
+ }
444
+ console.log(` ${S.DOT} ${chalk.gray("\u7BA1\u7406")} ${pmName}`);
445
+ console.log();
446
+ }
447
+ async function installDependencies(cwd, pm, features, eslintOpts) {
448
+ const spinner = ora({
449
+ text: chalk.gray("\u5206\u6790\u4F9D\u8D56..."),
450
+ prefixText: " ",
451
+ spinner: "dots"
452
+ }).start();
453
+ const deps = [
454
+ "@commitlint/cli",
455
+ "@commitlint/config-conventional",
456
+ "commitizen",
457
+ "cz-customizable",
458
+ "husky"
459
+ ];
460
+ if (features.eslint) {
461
+ deps.push("eslint");
462
+ if (eslintOpts.framework === "vue") {
463
+ deps.push("eslint-plugin-vue", "@vue/eslint-config-typescript");
464
+ }
465
+ if (eslintOpts.typescript) {
466
+ deps.push(
467
+ "@typescript-eslint/eslint-plugin",
468
+ "@typescript-eslint/parser"
469
+ );
470
+ }
471
+ if (eslintOpts.jsdoc) {
472
+ deps.push("eslint-plugin-jsdoc");
473
+ }
474
+ }
475
+ if (features.lintStaged) {
476
+ deps.push("lint-staged");
477
+ }
478
+ if (features.oxlint) {
479
+ deps.push("oxlint", "eslint-plugin-oxlint");
480
+ }
481
+ if (features.prettier) {
482
+ deps.push("prettier");
483
+ if (features.eslint && eslintOpts.framework === "vue") {
484
+ deps.push("@vue/eslint-config-prettier");
485
+ }
486
+ }
487
+ spinner.text = chalk.gray(`\u5B89\u88C5 ${deps.length} \u4E2A\u4F9D\u8D56...`);
488
+ try {
489
+ const installCmd = getInstallCommand(pm);
490
+ await execa2(
491
+ installCmd.split(" ")[0],
492
+ [...installCmd.split(" ").slice(1), ...deps],
493
+ { cwd, stdio: "pipe" }
494
+ );
495
+ spinner.succeed(
496
+ chalk.white("\u4F9D\u8D56\u5B89\u88C5\u5B8C\u6210 ") + chalk.gray(`(${deps.length} packages)`)
497
+ );
498
+ } catch (error) {
499
+ spinner.fail(chalk.red("\u4F9D\u8D56\u5B89\u88C5\u5931\u8D25"));
500
+ throw error;
501
+ }
502
+ }
503
+ async function generateConfigFiles(cwd, features, eslintOpts) {
504
+ const spinner = ora({
505
+ text: chalk.gray("\u751F\u6210\u914D\u7F6E\u6587\u4EF6..."),
506
+ prefixText: " ",
507
+ spinner: "dots"
508
+ }).start();
509
+ const generated = [];
510
+ try {
511
+ const czConfig = `/*
512
+ * Commitizen \u81EA\u5B9A\u4E49\u914D\u7F6E (cz-customizable)
513
+ * @generated by @robot-admin/git-standards
514
+ *
515
+ * \u76F4\u63A5\u4FEE\u6539\u6B64\u6587\u4EF6\u5373\u53EF\u81EA\u5B9A\u4E49\u63D0\u4EA4\u89C4\u8303
516
+ */
517
+ module.exports = {
518
+ scopes: [],
519
+ allowEmptyScopes: false,
520
+ allowCustomScopes: true,
521
+
522
+ types: [
523
+ { value: 'wip', name: 'wip: \u{1F6A7} \u5F00\u53D1\u4E2D' },
524
+ { value: 'feat', name: 'feat: \u{1F3AF} \u65B0\u529F\u80FD' },
525
+ { value: 'fix', name: 'fix: \u{1F41B} Bug \u4FEE\u590D' },
526
+ { value: 'perf', name: 'perf: \u26A1\uFE0F \u6027\u80FD\u4F18\u5316' },
527
+ { value: 'deps', name: 'deps: \u{1F4E6} \u4F9D\u8D56\u66F4\u65B0' },
528
+ { value: 'refactor', name: 'refactor: \u267B\uFE0F \u91CD\u6784' },
529
+ { value: 'docs', name: 'docs: \u{1F4DA} \u6587\u6863\u53D8\u66F4' },
530
+ { value: 'test', name: 'test: \u{1F50E} \u6D4B\u8BD5\u76F8\u5173' },
531
+ { value: 'style', name: 'style: \u{1F484} \u4EE3\u7801\u6837\u5F0F' },
532
+ { value: 'build', name: 'build: \u{1F9F3} \u6784\u5EFA/\u6253\u5305' },
533
+ { value: 'chore', name: 'chore: \u{1F527} \u5176\u4ED6\u6742\u9879' },
534
+ { value: 'revert', name: 'revert: \u{1F519} \u56DE\u9000' },
535
+ ],
536
+
537
+ messages: {
538
+ type: '\u8BF7\u9009\u62E9\u63D0\u4EA4\u7C7B\u578B:',
539
+ customScope: '\u8BF7\u8F93\u5165\u4FEE\u6539\u8303\u56F4(\u5FC5\u586B\uFF0C\u683C\u5F0F\u5982\uFF1A\u6A21\u5757/\u5B50\u6A21\u5757):',
540
+ subject: '\u8BF7\u7B80\u8981\u63CF\u8FF0\u63D0\u4EA4(\u5FC5\u586B\uFF0C\u4E0D\u52A0\u53E5\u53F7):',
541
+ body: '\u8BF7\u8F93\u5165\u66F4\u8BE6\u7EC6\u7684\u8BF4\u660E(\u53EF\u9009):\\n',
542
+ footer: 'Footer(\u53EF\u9009): \u4F8B\u5982 "Closes #123" \u6216 "Release-As: 1.3.1"\\n',
543
+ confirmCommit: '\u786E\u8BA4\u63D0\u4EA4\u4EE5\u4E0A\u5185\u5BB9\uFF1F(y/n/e/h)',
544
+ },
545
+
546
+ skipQuestions: ['body'],
547
+
548
+ allowBreakingChanges: ['feat', 'fix', 'refactor'],
549
+ breakingPrefix: 'BREAKING CHANGE:',
550
+
551
+ subjectLimit: 88,
552
+ }
553
+ `;
554
+ await writeFileContent(resolve4(cwd, ".cz-config.js"), czConfig);
555
+ generated.push(".cz-config.js");
556
+ const commitlintConfig = `/*
557
+ * Commitlint \u914D\u7F6E
558
+ * @generated by @robot-admin/git-standards
559
+ *
560
+ * \u76F4\u63A5\u4FEE\u6539\u6B64\u6587\u4EF6\u5373\u53EF\u81EA\u5B9A\u4E49\u63D0\u4EA4\u6821\u9A8C\u89C4\u5219
561
+ */
562
+ module.exports = {
563
+ extends: ['@commitlint/config-conventional'],
564
+ rules: {
565
+ 'type-enum': [
566
+ 2,
567
+ 'always',
568
+ [
569
+ 'wip', 'feat', 'fix', 'docs', 'style', 'refactor',
570
+ 'perf', 'test', 'chore', 'revert', 'build', 'deps',
571
+ ],
572
+ ],
573
+ 'subject-case': [0],
574
+ },
575
+ }
576
+ `;
577
+ await writeFileContent(
578
+ resolve4(cwd, "commitlint.config.js"),
579
+ commitlintConfig
580
+ );
581
+ generated.push("commitlint.config.js");
582
+ if (features.prettier) {
583
+ const prettierConfig = `/*
584
+ * Prettier \u914D\u7F6E
585
+ * @generated by @robot-admin/git-standards
586
+ *
587
+ * \u76F4\u63A5\u4FEE\u6539\u6B64\u6587\u4EF6\u5373\u53EF\u81EA\u5B9A\u4E49\u683C\u5F0F\u5316\u89C4\u5219
588
+ */
589
+ module.exports = {
590
+ $schema: 'https://json.schemastore.org/prettierrc',
591
+ semi: false,
592
+ singleQuote: true,
593
+ printWidth: 80,
594
+ tabWidth: 2,
595
+ quoteProps: 'as-needed',
596
+ trailingComma: 'es5',
597
+ bracketSpacing: true,
598
+ jsxSingleQuote: true,
599
+ arrowParens: 'avoid',
600
+ endOfLine: 'auto',
601
+ htmlWhitespaceSensitivity: 'strict',
602
+ vueIndentScriptAndStyle: true,
603
+ singleAttributePerLine: true,
604
+ }
605
+ `;
606
+ await writeFileContent(resolve4(cwd, ".prettierrc.js"), prettierConfig);
607
+ generated.push(".prettierrc.js");
608
+ }
609
+ if (features.eslint) {
610
+ const hasOxlint = features.oxlint;
611
+ const hasPrettier = features.prettier;
612
+ const hasJsdoc = eslintOpts.jsdoc;
613
+ const isVue = eslintOpts.framework === "vue";
614
+ const isTs = eslintOpts.typescript;
615
+ const importLines = [];
616
+ if (isVue) importLines.push("import pluginVue from 'eslint-plugin-vue'");
617
+ if (isVue && isTs) {
618
+ importLines.push(
619
+ "import {\n defineConfigWithVueTs,\n vueTsConfigs,\n} from '@vue/eslint-config-typescript'"
620
+ );
621
+ }
622
+ if (hasOxlint)
623
+ importLines.push("import oxlint from 'eslint-plugin-oxlint'");
624
+ if (hasPrettier && isVue) {
625
+ importLines.push(
626
+ "import skipFormatting from '@vue/eslint-config-prettier/skip-formatting'"
627
+ );
628
+ }
629
+ if (hasJsdoc)
630
+ importLines.push("import jsdocPlugin from 'eslint-plugin-jsdoc'");
631
+ const fileExts = isTs ? "js,ts,mts,tsx,vue" : "js,jsx,vue";
632
+ const vue2DeprecationRules = isVue ? `
633
+ //! \u4E3B\u52A8\u7981\u6B62 Vue 2 \u5199\u6CD5
634
+ 'vue/no-deprecated-props-default-this': 'error',
635
+ 'vue/no-deprecated-events-api': 'error',
636
+ 'vue/no-deprecated-filter': 'error',
637
+ 'vue/no-deprecated-functional-template': 'error',
638
+ ` : "";
639
+ const vueComponentRules = isVue ? `
640
+ // Vue \u89C4\u8303
641
+ //! PascalCase \u547D\u540D\u89C4\u8303
642
+ 'vue/component-name-in-template-casing': [
643
+ 'error',
644
+ 'PascalCase',
645
+ {
646
+ registeredComponentsOnly: false,
647
+ ignores: [
648
+ 'router-view',
649
+ 'router-link',
650
+ 'transition',
651
+ 'draggable',
652
+ '/^icon-/i',
653
+ '/^C_/',
654
+ '/^c_/',
655
+ 'v-md-editor',
656
+ ],
657
+ },
658
+ ],
659
+ 'vue/multi-word-component-names': [
660
+ 'error',
661
+ {
662
+ ignores: ['index'],
663
+ },
664
+ ],
665
+ //! \u7981\u6B62\u5728\u6A21\u677F\u4E2D\u6CE8\u518C\u4F46\u672A\u4F7F\u7528\u7684\u7EC4\u4EF6
666
+ 'vue/no-unused-components': 'error',
667
+ ${vue2DeprecationRules}` : "";
668
+ const jsdocBlock = hasJsdoc ? `
669
+ //MARK: \u81EA\u5B9A\u4E49\u89C4\u5219\u7EC4\uFF08\u4F18\u5148\u7EA7\u6700\u9AD8\uFF09
670
+ {
671
+ plugins: {
672
+ jsdoc: jsdocPlugin,
673
+ },
674
+ rules: {
675
+ //! JSDoc \u6CE8\u91CA\u89C4\u5219
676
+ 'jsdoc/require-jsdoc': [
677
+ 'error',
678
+ {
679
+ require: {
680
+ FunctionDeclaration: true,
681
+ MethodDefinition: true,
682
+ ClassDeclaration: true,
683
+ ArrowFunctionExpression: false,
684
+ FunctionExpression: true,
685
+ },
686
+ contexts: [
687
+ 'FunctionDeclaration',
688
+ 'ClassDeclaration',
689
+ 'ClassProperty',
690
+ 'MethodDefinition',
691
+ 'FunctionExpression',
692
+ ],
693
+ checkConstructors: true,
694
+ checkGetters: true,
695
+ checkSetters: true,
696
+ },
697
+ ],
698
+ ` : `
699
+ // \u81EA\u5B9A\u4E49\u89C4\u5219\u7EC4
700
+ {
701
+ rules: {
702
+ `;
703
+ const fileTypeOverrides = isTs ? `
704
+ //MARK: \u6587\u4EF6\u7C7B\u578B\u8986\u76D6\u89C4\u5219
705
+
706
+ //! \u53D8\u91CF\u4F7F\u7528\u89C4\u5219
707
+ {
708
+ files: ['**/*.js'],
709
+ rules: {
710
+ 'no-unused-vars': 'error',
711
+ '@typescript-eslint/no-unused-vars': 'off',
712
+ },
713
+ },
714
+ {
715
+ files: ['**/*.{ts,mts,tsx,vue}'],
716
+ rules: {
717
+ 'no-unused-vars': 'off',
718
+ '@typescript-eslint/no-unused-vars': 'error',
719
+ },
720
+ },
721
+ ` : "";
722
+ const jsdocWhitelist = hasJsdoc ? `
723
+ //MARK: JSDoc \u767D\u540D\u5355\u8986\u76D6\u89C4\u5219
724
+ {
725
+ files: [
726
+ 'src/router/**/*.ts',
727
+ 'src/stores/**/*.ts',
728
+ 'src/views/**/components/*.vue',
729
+ ],
730
+ rules: {
731
+ 'jsdoc/require-jsdoc': 'off',
732
+ '@typescript-eslint/require-jsdoc': 'off',
733
+ },
734
+ },
735
+ ` : "";
736
+ const ignoreAssets = `
737
+ //MARK: ESLINT \u767D\u540D\u5355\u914D\u7F6E\u7EC4
738
+ {
739
+ name: 'app/ignore-assets',
740
+ ignores: [
741
+ 'src/assets/images/**/*',
742
+ '**/*.d.ts',
743
+ '**/auto-imports.d.ts',
744
+ 'src/views/**/components/*.vue',
745
+ 'scripts/**/*',
746
+ ],
747
+ },
748
+ `;
749
+ const tsRules = isTs ? `
750
+ //! \u5173\u95ED\u4E0E oxlint \u91CD\u590D\u7684 ESLint \u89C4\u5219
751
+ 'no-undef': 'off',
752
+
753
+ //! \u5F15\u53F7\u89C4\u8303
754
+ '@typescript-eslint/quotes': ['error', 'single'],${isVue ? "\n 'vue/html-quotes': ['error', 'double']," : ""}
755
+
756
+ //! TypeScript \u5B89\u5168
757
+ '@typescript-eslint/no-explicit-any': 'off',
758
+ '@typescript-eslint/ban-ts-comment': [
759
+ 'error',
760
+ {
761
+ 'ts-ignore': 'allow-with-description',
762
+ },
763
+ ],
764
+
765
+ //! \u8868\u8FBE\u5F0F\u89C4\u8303
766
+ '@typescript-eslint/no-unused-expressions': [
767
+ 'error',
768
+ {
769
+ allowShortCircuit: true,
770
+ allowTernary: false,
771
+ allowTaggedTemplates: false,
772
+ enforceForJSX: true,
773
+ },
774
+ ],
775
+ ` : "";
776
+ const useWrapper = isVue && isTs;
777
+ const wrapperStart = useWrapper ? "export default defineConfigWithVueTs(" : "export default [";
778
+ const wrapperEnd = useWrapper ? ")" : "]";
779
+ const oxlintLine = hasOxlint ? "\n ...oxlint.configs['flat/recommended'], // \u9AD8\u6027\u80FD\u57FA\u7840\u6821\u9A8C\n" : "";
780
+ const vueLine = isVue ? `
781
+ //! \u5FFD\u7565\u8F6C\u4E49\u5B57\u7B26
782
+ {
783
+ rules: {
784
+ 'no-useless-escape': 'off',
785
+ },
786
+ },
787
+
788
+ pluginVue.configs['flat/essential'], // Vue \u4E13\u7528\u89C4\u5219` : "";
789
+ const tsLine = isVue && isTs ? "\n vueTsConfigs.recommended, // TS \u4E13\u7528\u89C4\u5219" : "";
790
+ const skipLine = hasPrettier && isVue ? "\n skipFormatting" : "";
791
+ const eslintConfig = `/*
792
+ * ESLint Flat Config
793
+ * @generated by @robot-admin/git-standards
794
+ *
795
+ * \u76F4\u63A5\u4FEE\u6539\u6B64\u6587\u4EF6\u5373\u53EF\u81EA\u5B9A\u4E49 ESLint \u89C4\u5219
796
+ */
797
+ ${importLines.join("\n")}
798
+
799
+ ${wrapperStart}
800
+ //MARK: \u57FA\u7840\u914D\u7F6E\u7EC4
801
+ {
802
+ name: 'app/files-to-lint',
803
+ files: ['**/*.{${fileExts}}'],
804
+ },
805
+
806
+ {
807
+ name: 'app/files-to-ignore',
808
+ ignores: [
809
+ '**/dist/**',
810
+ '**/dist-ssr/**',
811
+ '**/coverage/**',
812
+ ],
813
+ },
814
+
815
+ //MARK: \u6838\u5FC3\u89C4\u5219\u7EC4\uFF08\u6309\u4F18\u5148\u7EA7\u6392\u5E8F\uFF09
816
+ ${oxlintLine}${vueLine}${tsLine}
817
+ ${fileTypeOverrides}
818
+ ${jsdocBlock}${tsRules}
819
+ //! \u4EE3\u7801\u590D\u6742\u5EA6
820
+ 'max-depth': ['error', 4],
821
+ complexity: ['warn', 10],
822
+
823
+ //! \u5F02\u6B65\u4EE3\u7801\u89C4\u8303
824
+ 'no-await-in-loop': 'error',
825
+ ${vueComponentRules}
826
+ //MARK: \u683C\u5F0F\u89C4\u8303
827
+ 'no-irregular-whitespace': 'error',
828
+ 'no-multi-spaces': 'error',
829
+ 'space-infix-ops': 'error',
830
+ 'array-bracket-spacing': ['error', 'never'],
831
+ 'arrow-spacing': ['error', { before: true, after: true }],
832
+ 'max-params': ['warn', 6],
833
+ 'no-eval': 'error',
834
+ 'prefer-const': 'warn',
835
+ 'no-var': 'warn',
836
+ 'prefer-destructuring': [
837
+ 1,
838
+ { object: true, array: false },
839
+ ],
840
+ 'no-duplicate-imports': 'error',
841
+ },
842
+ },
843
+ ${ignoreAssets}${jsdocWhitelist}${skipLine}
844
+ ${wrapperEnd}
845
+ `;
846
+ await writeFileContent(resolve4(cwd, "eslint.config.ts"), eslintConfig);
847
+ generated.push("eslint.config.ts");
848
+ }
849
+ if (features.editorconfig) {
850
+ const editorConfig = `# EditorConfig - \u7F16\u8F91\u5668\u7EDF\u4E00\u914D\u7F6E
851
+ # @generated by @robot-admin/git-standards
852
+ # \u53C2\u8003: https://editorconfig.org
853
+
854
+ root = true
855
+
856
+ [*]
857
+ charset = utf-8
858
+ indent_style = space
859
+ indent_size = 2
860
+ end_of_line = lf
861
+ insert_final_newline = true
862
+ trim_trailing_whitespace = true
863
+
864
+ [*.md]
865
+ trim_trailing_whitespace = false
866
+
867
+ [*.{yml,yaml}]
868
+ indent_size = 2
869
+
870
+ [Makefile]
871
+ indent_style = tab
872
+ `;
873
+ await writeFileContent(resolve4(cwd, ".editorconfig"), editorConfig);
874
+ generated.push(".editorconfig");
875
+ }
876
+ spinner.succeed(
877
+ chalk.white("\u914D\u7F6E\u6587\u4EF6\u751F\u6210\u5B8C\u6210 ") + chalk.gray(`(${generated.join(", ")})`)
878
+ );
879
+ } catch (error) {
880
+ spinner.fail(chalk.red("\u914D\u7F6E\u6587\u4EF6\u751F\u6210\u5931\u8D25"));
881
+ throw error;
882
+ }
883
+ }
884
+ async function setupHusky(cwd, pm, features) {
885
+ const spinner = ora({
886
+ text: chalk.gray("\u521D\u59CB\u5316 Husky..."),
887
+ prefixText: " ",
888
+ spinner: "dots"
889
+ }).start();
890
+ try {
891
+ const execCmd = getExecCommand(pm);
892
+ await execa2(execCmd, ["husky", "init"], { cwd, stdio: "pipe" });
893
+ const legacyDir = resolve4(cwd, ".husky/_");
894
+ if (existsSync4(legacyDir)) {
895
+ rmSync(legacyDir, { recursive: true, force: true });
896
+ }
897
+ const commitMsg = `${execCmd} --no-install commitlint --edit "$1"
898
+ `;
899
+ await writeFileContent(resolve4(cwd, ".husky/commit-msg"), commitMsg);
900
+ const hooks = ["commit-msg"];
901
+ const needsPreCommit = features.eslint || features.lintStaged || features.oxlint;
902
+ if (needsPreCommit) {
903
+ const cmds = [];
904
+ if (features.oxlint) {
905
+ cmds.push(`${execCmd} oxlint --max-warnings 0`);
906
+ }
907
+ if (features.lintStaged) {
908
+ cmds.push(`${execCmd} lint-staged`);
909
+ } else if (features.eslint) {
910
+ cmds.push(`${execCmd} eslint . --fix`);
911
+ }
912
+ await writeFileContent(
913
+ resolve4(cwd, ".husky/pre-commit"),
914
+ cmds.join("\n") + "\n"
915
+ );
916
+ hooks.push("pre-commit");
917
+ } else {
918
+ const defaultPreCommit = resolve4(cwd, ".husky/pre-commit");
919
+ if (existsSync4(defaultPreCommit)) {
920
+ unlinkSync(defaultPreCommit);
921
+ }
922
+ }
923
+ spinner.succeed(
924
+ chalk.white("Husky \u521D\u59CB\u5316\u5B8C\u6210 ") + chalk.gray(`(${hooks.join(", ")})`)
925
+ );
926
+ } catch (error) {
927
+ spinner.fail(chalk.red("Husky \u521D\u59CB\u5316\u5931\u8D25"));
928
+ throw error;
929
+ }
930
+ }
931
+ async function addPackageScripts(cwd, pm, features) {
932
+ const spinner = ora({
933
+ text: chalk.gray("\u66F4\u65B0 package.json..."),
934
+ prefixText: " ",
935
+ spinner: "dots"
936
+ }).start();
937
+ try {
938
+ const packageJsonPath = resolve4(cwd, "package.json");
939
+ const packageJson = await readJsonFile(packageJsonPath);
940
+ const scripts = packageJson.scripts || {};
941
+ scripts.cz = "git-cz";
942
+ scripts.prepare = "husky";
943
+ if (features.eslint) {
944
+ scripts.lint = features.oxlint ? "oxlint . --fix -D correctness --ignore-path .gitignore && eslint . --fix" : "eslint . --fix";
945
+ }
946
+ if (features.prettier) {
947
+ scripts.format = "prettier --write src/";
948
+ }
949
+ const czConfig = {
950
+ commitizen: { path: "node_modules/cz-customizable" }
951
+ };
952
+ const updates = { scripts, config: czConfig };
953
+ if (features.lintStaged) {
954
+ updates["lint-staged"] = generateLintStagedConfig({
955
+ eslint: features.eslint,
956
+ oxlint: features.oxlint,
957
+ prettier: features.prettier
958
+ });
959
+ }
960
+ await updatePackageJson(updates, cwd);
961
+ const parts = ["scripts"];
962
+ if (features.lintStaged) parts.push("lint-staged");
963
+ spinner.succeed(
964
+ chalk.white("package.json \u66F4\u65B0\u5B8C\u6210 ") + chalk.gray(`(${parts.join(" + ")})`)
965
+ );
966
+ } catch (error) {
967
+ spinner.fail(chalk.red("package.json \u66F4\u65B0\u5931\u8D25"));
968
+ throw error;
969
+ }
970
+ }
971
+ function printCompletion(pm, features) {
972
+ console.log();
973
+ console.log(S.LINE);
974
+ console.log(` ${S.OK} ${chalk.green.bold("\u521D\u59CB\u5316\u5B8C\u6210!")}`);
975
+ console.log(S.LINE);
976
+ console.log();
977
+ console.log(` ${chalk.bold("\u5FEB\u901F\u5F00\u59CB:")}`);
978
+ console.log();
979
+ console.log(` ${S.DOT} \u63D0\u4EA4\u4EE3\u7801 ${chalk.cyan(`${pm} run cz`)}`);
980
+ if (features.eslint) {
981
+ console.log(` ${S.DOT} \u68C0\u67E5\u4EE3\u7801 ${chalk.cyan(`${pm} run lint`)}`);
982
+ }
983
+ if (features.prettier) {
984
+ console.log(` ${S.DOT} \u683C\u5F0F\u5316 ${chalk.cyan(`${pm} run format`)}`);
985
+ }
986
+ console.log();
987
+ console.log(
988
+ ` ${S.INFO} ${chalk.gray("\u5168\u5C40\u5B89\u88C5 commitizen \u540E\u53EF\u76F4\u63A5\u4F7F\u7528 git cz \u63D0\u4EA4")}`
989
+ );
990
+ console.log(` ${S.DOT} ${chalk.gray(`npm install -g commitizen`)}`);
991
+ console.log();
992
+ console.log(
993
+ ` ${S.INFO} ${chalk.gray("\u6240\u6709\u914D\u7F6E\u6587\u4EF6\u5747\u652F\u6301\u8986\u76D6\u6269\u5C55\uFF0C\u8BE6\u89C1 README.md")}`
994
+ );
995
+ console.log();
996
+ }
997
+
998
+ // src/cli/doctor.ts
999
+ import { resolve as resolve5 } from "path";
1000
+ import chalk2 from "chalk";
1001
+ var BRAND2 = "#7C3AED";
1002
+ var S2 = {
1003
+ LOGO: chalk2.hex(BRAND2).bold("[RS]"),
1004
+ OK: chalk2.green("\u2714"),
1005
+ FAIL: chalk2.red("\u2716"),
1006
+ WARN: chalk2.yellow("\u25B2"),
1007
+ SKIP: chalk2.gray("\u25CB"),
1008
+ LINE: chalk2.gray("\u2500".repeat(48))
1009
+ };
1010
+ async function doctor(options = {}) {
1011
+ const cwd = options.cwd || process.cwd();
1012
+ console.log();
1013
+ console.log(S2.LINE);
1014
+ console.log(
1015
+ ` ${S2.LOGO} ${chalk2.bold("Robot Standards")} ${chalk2.gray("Doctor")}`
1016
+ );
1017
+ console.log(S2.LINE);
1018
+ console.log();
1019
+ const checks = [];
1020
+ const isGit = isGitRepository(cwd);
1021
+ checks.push({
1022
+ name: "Git \u4ED3\u5E93",
1023
+ status: isGit ? "pass" : "fail",
1024
+ message: isGit ? void 0 : "\u672A\u521D\u59CB\u5316 Git \u4ED3\u5E93\uFF0C\u8FD0\u884C git init"
1025
+ });
1026
+ let packageJson = {};
1027
+ const packageJsonPath = resolve5(cwd, "package.json");
1028
+ const hasPackageJson = fileExists(packageJsonPath);
1029
+ if (hasPackageJson) {
1030
+ try {
1031
+ packageJson = await readJsonFile(packageJsonPath);
1032
+ } catch {
1033
+ }
1034
+ } else {
1035
+ checks.push({
1036
+ name: "package.json",
1037
+ status: "fail",
1038
+ message: "\u7F3A\u5C11 package.json"
1039
+ });
1040
+ }
1041
+ const allDeps = {
1042
+ ...packageJson.dependencies,
1043
+ ...packageJson.devDependencies
1044
+ };
1045
+ const hasCommitizen = !!allDeps["commitizen"];
1046
+ const hasCommitlint = !!allDeps["@commitlint/cli"];
1047
+ const hasHusky = !!allDeps["husky"];
1048
+ const hasEslint = !!allDeps["eslint"];
1049
+ const hasLintStaged = !!allDeps["lint-staged"];
1050
+ const hasPrettier = !!allDeps["prettier"];
1051
+ console.log(` ${chalk2.bold("\u6838\u5FC3\u529F\u80FD")}`);
1052
+ console.log();
1053
+ if (hasHusky) {
1054
+ const huskyDir = fileExists(resolve5(cwd, ".husky"));
1055
+ checks.push({
1056
+ name: "Husky \u76EE\u5F55",
1057
+ status: huskyDir ? "pass" : "fail",
1058
+ message: huskyDir ? void 0 : "\u7F3A\u5C11 .husky \u76EE\u5F55"
1059
+ });
1060
+ const commitMsg = fileExists(resolve5(cwd, ".husky/commit-msg"));
1061
+ checks.push({
1062
+ name: "commit-msg hook",
1063
+ status: commitMsg ? "pass" : "fail",
1064
+ message: commitMsg ? void 0 : "\u7F3A\u5C11 commit-msg hook"
1065
+ });
1066
+ } else {
1067
+ checks.push({
1068
+ name: "Husky",
1069
+ status: "fail",
1070
+ message: "\u672A\u5B89\u88C5 husky"
1071
+ });
1072
+ }
1073
+ if (hasCommitlint) {
1074
+ const hasConfig = fileExists(resolve5(cwd, "commitlint.config.cjs")) || fileExists(resolve5(cwd, "commitlint.config.js")) || fileExists(resolve5(cwd, "commitlint.config.ts"));
1075
+ checks.push({
1076
+ name: "Commitlint \u914D\u7F6E",
1077
+ status: hasConfig ? "pass" : "fail",
1078
+ message: hasConfig ? void 0 : "\u7F3A\u5C11 commitlint.config.*"
1079
+ });
1080
+ } else {
1081
+ checks.push({
1082
+ name: "Commitlint",
1083
+ status: "fail",
1084
+ message: "\u672A\u5B89\u88C5 @commitlint/cli"
1085
+ });
1086
+ }
1087
+ if (hasCommitizen) {
1088
+ const hasCzConfig = fileExists(resolve5(cwd, ".cz-config.cjs")) || fileExists(resolve5(cwd, ".cz-config.js"));
1089
+ checks.push({
1090
+ name: "Commitizen \u914D\u7F6E",
1091
+ status: hasCzConfig ? "pass" : "fail",
1092
+ message: hasCzConfig ? void 0 : "\u7F3A\u5C11 .cz-config.*"
1093
+ });
1094
+ const hasCommitizenPath = !!packageJson.config?.commitizen;
1095
+ checks.push({
1096
+ name: "commitizen path \u914D\u7F6E",
1097
+ status: hasCommitizenPath ? "pass" : "fail",
1098
+ message: hasCommitizenPath ? void 0 : "package.json \u4E2D\u7F3A\u5C11 config.commitizen"
1099
+ });
1100
+ } else {
1101
+ checks.push({
1102
+ name: "Commitizen",
1103
+ status: "fail",
1104
+ message: "\u672A\u5B89\u88C5 commitizen"
1105
+ });
1106
+ }
1107
+ const hasCzScript = !!packageJson.scripts?.cz;
1108
+ checks.push({
1109
+ name: "cz \u811A\u672C",
1110
+ status: hasCzScript ? "pass" : "fail",
1111
+ message: hasCzScript ? void 0 : "\u7F3A\u5C11 cz \u811A\u672C (bun run cz)"
1112
+ });
1113
+ const coreChecks = checks.slice();
1114
+ for (const check of coreChecks) {
1115
+ printCheck(check);
1116
+ }
1117
+ const extraChecks = [];
1118
+ if (hasEslint) {
1119
+ console.log();
1120
+ console.log(` ${chalk2.bold("\u4EE3\u7801\u68C0\u67E5")}`);
1121
+ console.log();
1122
+ const hasEslintConfig = fileExists(resolve5(cwd, "eslint.config.ts")) || fileExists(resolve5(cwd, "eslint.config.js")) || fileExists(resolve5(cwd, "eslint.config.mjs"));
1123
+ const eslintCheck = {
1124
+ name: "ESLint \u914D\u7F6E",
1125
+ status: hasEslintConfig ? "pass" : "fail",
1126
+ message: hasEslintConfig ? void 0 : "\u7F3A\u5C11 eslint.config.*"
1127
+ };
1128
+ extraChecks.push(eslintCheck);
1129
+ printCheck(eslintCheck);
1130
+ if (hasHusky) {
1131
+ const preCommit = fileExists(resolve5(cwd, ".husky/pre-commit"));
1132
+ const preCommitCheck = {
1133
+ name: "pre-commit hook",
1134
+ status: preCommit ? "pass" : "fail",
1135
+ message: preCommit ? void 0 : "\u7F3A\u5C11 pre-commit hook"
1136
+ };
1137
+ extraChecks.push(preCommitCheck);
1138
+ printCheck(preCommitCheck);
1139
+ }
1140
+ }
1141
+ if (hasLintStaged) {
1142
+ const lintStagedConfig = !!packageJson["lint-staged"];
1143
+ const lintStagedCheck = {
1144
+ name: "lint-staged \u914D\u7F6E",
1145
+ status: lintStagedConfig ? "pass" : "fail",
1146
+ message: lintStagedConfig ? void 0 : "package.json \u4E2D\u7F3A\u5C11 lint-staged \u914D\u7F6E"
1147
+ };
1148
+ extraChecks.push(lintStagedCheck);
1149
+ printCheck(lintStagedCheck);
1150
+ }
1151
+ if (hasPrettier) {
1152
+ console.log();
1153
+ console.log(` ${chalk2.bold("\u4EE3\u7801\u683C\u5F0F\u5316")}`);
1154
+ console.log();
1155
+ const hasPrettierConfig = fileExists(resolve5(cwd, ".prettierrc.cjs")) || fileExists(resolve5(cwd, ".prettierrc.js")) || fileExists(resolve5(cwd, ".prettierrc.json")) || fileExists(resolve5(cwd, ".prettierrc"));
1156
+ const prettierCheck = {
1157
+ name: "Prettier \u914D\u7F6E",
1158
+ status: hasPrettierConfig ? "pass" : "fail",
1159
+ message: hasPrettierConfig ? void 0 : "\u7F3A\u5C11 .prettierrc.*"
1160
+ };
1161
+ extraChecks.push(prettierCheck);
1162
+ printCheck(prettierCheck);
1163
+ }
1164
+ const hasEditorConfig = fileExists(resolve5(cwd, ".editorconfig"));
1165
+ if (hasEditorConfig) {
1166
+ }
1167
+ const notInstalled = [];
1168
+ if (!hasEslint) notInstalled.push("ESLint");
1169
+ if (!hasLintStaged) notInstalled.push("lint-staged");
1170
+ if (!hasPrettier) notInstalled.push("Prettier");
1171
+ if (!hasEditorConfig) notInstalled.push("EditorConfig");
1172
+ if (notInstalled.length > 0) {
1173
+ console.log();
1174
+ console.log(` ${chalk2.bold("\u672A\u542F\u7528\u7684\u529F\u80FD")}`);
1175
+ console.log();
1176
+ for (const name of notInstalled) {
1177
+ console.log(` ${S2.SKIP} ${chalk2.gray(name)}`);
1178
+ }
1179
+ }
1180
+ const allChecks = [...coreChecks, ...extraChecks];
1181
+ const passedCount = allChecks.filter((c) => c.status === "pass").length;
1182
+ const failedCount = allChecks.filter((c) => c.status === "fail").length;
1183
+ console.log();
1184
+ console.log(S2.LINE);
1185
+ console.log(
1186
+ ` ${chalk2.bold("\u603B\u8BA1:")} ${chalk2.green(`${passedCount} \u901A\u8FC7`)} ${failedCount > 0 ? chalk2.red(`${failedCount} \u5931\u8D25`) : chalk2.gray("0 \u5931\u8D25")}`
1187
+ );
1188
+ if (failedCount > 0) {
1189
+ console.log();
1190
+ console.log(
1191
+ ` ${S2.WARN} ${chalk2.yellow("\u8FD0\u884C")} ${chalk2.cyan(
1192
+ "robot-standards init"
1193
+ )} ${chalk2.yellow("\u4FEE\u590D\u95EE\u9898")}`
1194
+ );
1195
+ } else {
1196
+ console.log();
1197
+ console.log(` ${S2.OK} ${chalk2.green("\u6240\u6709\u68C0\u67E5\u901A\u8FC7!")}`);
1198
+ }
1199
+ console.log(S2.LINE);
1200
+ console.log();
1201
+ return failedCount === 0;
1202
+ }
1203
+ function printCheck(check) {
1204
+ const icon = check.status === "pass" ? S2.OK : check.status === "fail" ? S2.FAIL : S2.SKIP;
1205
+ console.log(` ${icon} ${check.name}`);
1206
+ if (check.message && check.status === "fail") {
1207
+ console.log(` ${chalk2.gray(check.message)}`);
1208
+ }
1209
+ }
1210
+ export {
1211
+ createLintStagedConfig,
1212
+ detectPackageManager,
1213
+ doctor,
1214
+ fileExists,
1215
+ generateLintStagedConfig,
1216
+ getExecCommand,
1217
+ getInstallCommand,
1218
+ getPackageManagerName,
1219
+ init,
1220
+ initGitRepository,
1221
+ isGitRepository,
1222
+ readFileContent,
1223
+ readJsonFile,
1224
+ updatePackageJson,
1225
+ writeFileContent,
1226
+ writeJsonFile
1227
+ };
1228
+ //# sourceMappingURL=index.js.map