@tyyyho/treg 0.1.8 → 0.1.11
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/README.md +19 -15
- package/README.zh-hant.md +103 -0
- package/dist/init-project/cli.js +14 -25
- package/dist/init-project/frameworks/index.js +3 -10
- package/dist/init-project/frameworks/react/index.js +0 -18
- package/dist/init-project/index.js +6 -9
- package/package.json +1 -1
- package/dist/init-project/frameworks/react/v18/index.js +0 -6
- package/dist/init-project/frameworks/react/v19/index.js +0 -6
package/README.md
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
# @tyyyho/treg
|
|
2
2
|
|
|
3
|
+
[繁體中文 README](./README.zh-hant.md)
|
|
4
|
+
|
|
3
5
|
`treg` is a CLI for quickly setting up project tooling conventions in an existing repository.
|
|
4
6
|
It applies infra setup such as lint, format, TypeScript, test, husky, and AI skill guidance.
|
|
5
7
|
|
|
6
8
|
## Quick Start
|
|
7
9
|
|
|
8
10
|
```bash
|
|
9
|
-
pnpm dlx @tyyyho/treg init
|
|
11
|
+
pnpm dlx @tyyyho/treg init
|
|
10
12
|
# or
|
|
11
|
-
npx @tyyyho/treg init
|
|
13
|
+
npx @tyyyho/treg init
|
|
12
14
|
```
|
|
13
15
|
|
|
14
|
-
`init`
|
|
16
|
+
`init` auto-detects framework from dependencies.
|
|
15
17
|
|
|
16
18
|
## Commands
|
|
17
19
|
|
|
@@ -19,17 +21,16 @@ npx @tyyyho/treg init --framework react
|
|
|
19
21
|
npx @tyyyho/treg <command> [options]
|
|
20
22
|
```
|
|
21
23
|
|
|
22
|
-
- `init`: Initialize infra rules (
|
|
24
|
+
- `init`: Initialize infra rules (framework auto-detected from dependencies)
|
|
23
25
|
- `add`: Add selected infra features to an existing project
|
|
24
26
|
- `list`: List supported frameworks, features, and test runners
|
|
25
27
|
|
|
26
28
|
## Options
|
|
27
29
|
|
|
28
|
-
- `--framework <node|react|next|vue|svelte|nuxt>`:
|
|
29
|
-
- `--framework-version <major>`: Optional major version hint (react only)
|
|
30
|
+
- `--framework <node|react|next|vue|svelte|nuxt>`: Optional framework override
|
|
30
31
|
- `--features <lint,format,typescript,test,husky>`: Features to install (defaults to all)
|
|
31
32
|
- `--dir <path>`: Target directory (defaults to current directory)
|
|
32
|
-
- `--test-runner <jest|vitest>`:
|
|
33
|
+
- `--test-runner <jest|vitest>`: Optional test runner override when test feature is enabled
|
|
33
34
|
- `--pm <pnpm|npm|yarn|auto>`: Package manager (auto-detected by default)
|
|
34
35
|
- `--force`: Overwrite existing config files
|
|
35
36
|
- `--dry-run`: Print full plan without writing files
|
|
@@ -50,7 +51,13 @@ Default feature set:
|
|
|
50
51
|
|
|
51
52
|
## Examples
|
|
52
53
|
|
|
53
|
-
Initialize
|
|
54
|
+
Initialize with auto-detected framework:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx @tyyyho/treg init
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
Initialize with explicit framework override:
|
|
54
61
|
|
|
55
62
|
```bash
|
|
56
63
|
npx @tyyyho/treg init --framework react
|
|
@@ -68,12 +75,6 @@ Use Vitest for test feature:
|
|
|
68
75
|
npx @tyyyho/treg init --framework node --features test --test-runner vitest
|
|
69
76
|
```
|
|
70
77
|
|
|
71
|
-
Use react major version variant:
|
|
72
|
-
|
|
73
|
-
```bash
|
|
74
|
-
npx @tyyyho/treg init --framework react --framework-version 18
|
|
75
|
-
```
|
|
76
|
-
|
|
77
78
|
Preview changes only:
|
|
78
79
|
|
|
79
80
|
```bash
|
|
@@ -94,6 +95,9 @@ npx @tyyyho/treg init --framework react --dir ./packages/web
|
|
|
94
95
|
|
|
95
96
|
## Notes
|
|
96
97
|
|
|
97
|
-
- `init`
|
|
98
|
+
- `init` auto-detects framework from repo dependencies.
|
|
99
|
+
- Detection order is `nuxt -> next -> react -> vue -> svelte -> node`.
|
|
100
|
+
- Default test runner is `vitest` for `vue`/`nuxt`, and `jest` for other frameworks.
|
|
98
101
|
- `add` lets you install only the features you specify.
|
|
102
|
+
- Framework setup uses one stable config per framework (no `--framework-version` variants).
|
|
99
103
|
- `--dry-run` prints the full plan and does not write files.
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# @tyyyho/treg(繁體中文)
|
|
2
|
+
|
|
3
|
+
[English README](./README.md)
|
|
4
|
+
|
|
5
|
+
`treg` 是一個用於既有專案的 CLI 工具,可快速建立與套用工具鏈規範。
|
|
6
|
+
預設搭建基礎設定,包含 lint、format、TypeScript、test、husky、skills。
|
|
7
|
+
|
|
8
|
+
## 快速開始
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm dlx @tyyyho/treg init
|
|
12
|
+
# 或
|
|
13
|
+
npx @tyyyho/treg init
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
`init` 會依照依賴自動偵測 framework。
|
|
17
|
+
|
|
18
|
+
## 指令
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npx @tyyyho/treg <command> [options]
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- `init`:初始化基礎規範(依賴自動偵測 framework)
|
|
25
|
+
- `add`:在既有專案中新增指定 feature
|
|
26
|
+
- `list`:列出支援的 framework、feature 與 test runner
|
|
27
|
+
|
|
28
|
+
## 參數
|
|
29
|
+
|
|
30
|
+
- `--framework <node|react|next|vue|svelte|nuxt>`:可選,手動覆寫 framework
|
|
31
|
+
- `--features <lint,format,typescript,test,husky>`:指定要安裝的 feature(預設全部)
|
|
32
|
+
- `--dir <path>`:指定目標目錄(預設為目前目錄)
|
|
33
|
+
- `--test-runner <jest|vitest>`:可選,啟用 test feature 時覆寫測試框架
|
|
34
|
+
- `--pm <pnpm|npm|yarn|auto>`:套件管理器(預設自動偵測)
|
|
35
|
+
- `--force`:覆寫既有設定檔
|
|
36
|
+
- `--dry-run`:輸出完整執行計畫,但不寫入檔案
|
|
37
|
+
- `--skip-husky-install`:略過 `husky install`
|
|
38
|
+
- `--skills`:更新既有 `AGENTS.md`/`CLAUDE.md` 的 skill 指引(預設啟用)
|
|
39
|
+
- `--no-skills`:停用 skill 指引更新
|
|
40
|
+
- `--help`:顯示說明
|
|
41
|
+
|
|
42
|
+
## Features
|
|
43
|
+
|
|
44
|
+
預設 feature 組合:
|
|
45
|
+
|
|
46
|
+
- `husky`
|
|
47
|
+
- `typescript`
|
|
48
|
+
- `lint`
|
|
49
|
+
- `format`
|
|
50
|
+
- `test`
|
|
51
|
+
|
|
52
|
+
## 使用範例
|
|
53
|
+
|
|
54
|
+
依賴自動偵測 framework 初始化:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
npx @tyyyho/treg init
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
手動指定 framework 初始化:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npx @tyyyho/treg init --framework react
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
只安裝 lint + format:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
npx @tyyyho/treg add --features lint,format
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
test feature 使用 Vitest:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
npx @tyyyho/treg init --framework node --features test --test-runner vitest
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
僅預覽變更(不寫檔):
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
npx @tyyyho/treg init --framework react --dry-run
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
更新 AI skills 指引:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
npx @tyyyho/treg add --features lint,format,husky
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
明確指定其他目錄:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
npx @tyyyho/treg init --framework react --dir ./packages/web
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
## 注意事項
|
|
97
|
+
|
|
98
|
+
- `init` 會依 repo 依賴自動偵測 framework。
|
|
99
|
+
- 偵測順序:`nuxt -> next -> react -> vue -> svelte -> node`。
|
|
100
|
+
- 預設測試工具為:`vue`/`nuxt` 使用 `vitest`,其他 framework 使用 `jest`。
|
|
101
|
+
- `add` 可只安裝你指定的 features。
|
|
102
|
+
- 每個 framework 僅提供單一穩定設定,不支援 `--framework-version` 版本變體。
|
|
103
|
+
- `--dry-run` 會輸出完整計畫且不寫入任何檔案。
|
package/dist/init-project/cli.js
CHANGED
|
@@ -24,18 +24,17 @@ const ALLOWED_TEST_RUNNERS = ["jest", "vitest"];
|
|
|
24
24
|
export const USAGE = `Usage: treg <command> [options]
|
|
25
25
|
|
|
26
26
|
Commands:
|
|
27
|
-
init Initialize infra rules in a project (
|
|
27
|
+
init Initialize infra rules in a project (framework auto-detected from dependencies)
|
|
28
28
|
add Add selected infra features to an existing project
|
|
29
29
|
list List supported frameworks, features, and test runners
|
|
30
30
|
|
|
31
31
|
Options:
|
|
32
32
|
--framework <node|react|next|vue|svelte|nuxt>
|
|
33
|
-
|
|
34
|
-
--framework-version <major> Optional framework major version hint
|
|
33
|
+
Optional framework override (default: auto-detected)
|
|
35
34
|
--features <lint,format,typescript,test,husky>
|
|
36
35
|
Features to install (all selected by default)
|
|
37
36
|
--dir <path> Target directory (defaults to current directory)
|
|
38
|
-
--test-runner <jest|vitest>
|
|
37
|
+
--test-runner <jest|vitest> Optional test runner override (default: vue/nuxt=vitest, others=jest)
|
|
39
38
|
--pm <pnpm|npm|yarn|auto> Package manager (auto-detected if omitted)
|
|
40
39
|
--force Overwrite existing config files
|
|
41
40
|
--dry-run Print planned changes without writing files
|
|
@@ -67,9 +66,8 @@ export function parseArgs(argv) {
|
|
|
67
66
|
command: "init",
|
|
68
67
|
projectDir: null,
|
|
69
68
|
framework: null,
|
|
70
|
-
frameworkVersion: null,
|
|
71
69
|
features: [],
|
|
72
|
-
testRunner:
|
|
70
|
+
testRunner: null,
|
|
73
71
|
pm: null,
|
|
74
72
|
force: false,
|
|
75
73
|
dryRun: false,
|
|
@@ -98,13 +96,6 @@ export function parseArgs(argv) {
|
|
|
98
96
|
else if (arg.startsWith("--framework=")) {
|
|
99
97
|
options.framework = readInlineFlagValue(arg, "--framework");
|
|
100
98
|
}
|
|
101
|
-
else if (arg === "--framework-version") {
|
|
102
|
-
options.frameworkVersion = readFlagValue(argv, i, "--framework-version");
|
|
103
|
-
i += 1;
|
|
104
|
-
}
|
|
105
|
-
else if (arg.startsWith("--framework-version=")) {
|
|
106
|
-
options.frameworkVersion = readInlineFlagValue(arg, "--framework-version");
|
|
107
|
-
}
|
|
108
99
|
else if (arg === "--features") {
|
|
109
100
|
options.features.push(...parseCsvValue(argv[i + 1], "--features"));
|
|
110
101
|
i += 1;
|
|
@@ -191,15 +182,7 @@ function validateParsedOptions(options) {
|
|
|
191
182
|
if (options.framework && !isFrameworkId(options.framework)) {
|
|
192
183
|
throw new Error(`Unsupported framework: ${options.framework}`);
|
|
193
184
|
}
|
|
194
|
-
if (options.
|
|
195
|
-
throw new Error("Invalid --framework-version: major version must be numeric");
|
|
196
|
-
}
|
|
197
|
-
if (options.frameworkVersion &&
|
|
198
|
-
options.framework &&
|
|
199
|
-
options.framework !== "react") {
|
|
200
|
-
throw new Error(`Unsupported --framework-version for framework: ${options.framework}`);
|
|
201
|
-
}
|
|
202
|
-
if (!isTestRunner(options.testRunner)) {
|
|
185
|
+
if (options.testRunner && !isTestRunner(options.testRunner)) {
|
|
203
186
|
throw new Error(`Unsupported test runner: ${options.testRunner}`);
|
|
204
187
|
}
|
|
205
188
|
for (const feature of options.features) {
|
|
@@ -207,9 +190,6 @@ function validateParsedOptions(options) {
|
|
|
207
190
|
throw new Error(`Unsupported feature in --features: ${feature}`);
|
|
208
191
|
}
|
|
209
192
|
}
|
|
210
|
-
if (options.command === "init" && !options.help && !options.framework) {
|
|
211
|
-
throw new Error("Missing required option: --framework");
|
|
212
|
-
}
|
|
213
193
|
}
|
|
214
194
|
export function resolveFeatures(options) {
|
|
215
195
|
const selected = new Set(options.features.length > 0 ? options.features : ALLOWED_FEATURES);
|
|
@@ -226,3 +206,12 @@ export function printSupportedTargets() {
|
|
|
226
206
|
console.log("Features: lint, format, typescript, test, husky");
|
|
227
207
|
console.log("Test runners: jest, vitest");
|
|
228
208
|
}
|
|
209
|
+
export function resolveTestRunner(frameworkId, testRunner) {
|
|
210
|
+
if (testRunner) {
|
|
211
|
+
return testRunner;
|
|
212
|
+
}
|
|
213
|
+
if (frameworkId === "vue" || frameworkId === "nuxt") {
|
|
214
|
+
return "vitest";
|
|
215
|
+
}
|
|
216
|
+
return "jest";
|
|
217
|
+
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { nextFramework } from "./next/index.js";
|
|
2
2
|
import { nodeFramework } from "./node/index.js";
|
|
3
3
|
import { nuxtFramework } from "./nuxt/index.js";
|
|
4
|
-
import { reactFramework
|
|
4
|
+
import { reactFramework } from "./react/index.js";
|
|
5
5
|
import { svelteFramework } from "./svelte/index.js";
|
|
6
6
|
import { vueFramework } from "./vue/index.js";
|
|
7
7
|
const FRAMEWORK_REGISTRY = {
|
|
@@ -20,18 +20,11 @@ const FRAMEWORK_DETECT_ORDER = [
|
|
|
20
20
|
svelteFramework,
|
|
21
21
|
nodeFramework,
|
|
22
22
|
];
|
|
23
|
-
export function resolveFramework(frameworkArg,
|
|
24
|
-
if (frameworkArg === "react") {
|
|
25
|
-
return resolveReactFramework(packageJson, frameworkVersion);
|
|
26
|
-
}
|
|
23
|
+
export function resolveFramework(frameworkArg, packageJson) {
|
|
27
24
|
if (frameworkArg) {
|
|
28
25
|
return FRAMEWORK_REGISTRY[frameworkArg];
|
|
29
26
|
}
|
|
30
|
-
|
|
31
|
-
if (detected.id === "react") {
|
|
32
|
-
return resolveReactFramework(packageJson, frameworkVersion);
|
|
33
|
-
}
|
|
34
|
-
return detected;
|
|
27
|
+
return detectFramework(packageJson);
|
|
35
28
|
}
|
|
36
29
|
export function detectFramework(packageJson) {
|
|
37
30
|
const matched = FRAMEWORK_DETECT_ORDER.find(framework => framework.matches(packageJson));
|
|
@@ -1,27 +1,9 @@
|
|
|
1
1
|
import { hasPackage } from "../../utils.js";
|
|
2
|
-
import { reactV18Framework } from "./v18/index.js";
|
|
3
|
-
import { reactV19Framework } from "./v19/index.js";
|
|
4
2
|
export const reactFramework = {
|
|
5
3
|
id: "react",
|
|
6
|
-
variant: "v19",
|
|
7
4
|
testEnvironment: "jsdom",
|
|
8
5
|
tsRequiredExcludes: ["dist", "coverage", "jest.config.js", "public"],
|
|
9
6
|
matches(packageJson) {
|
|
10
7
|
return (hasPackage(packageJson, "react") || hasPackage(packageJson, "react-dom"));
|
|
11
8
|
},
|
|
12
9
|
};
|
|
13
|
-
const REACT_VARIANTS = {
|
|
14
|
-
"18": reactV18Framework,
|
|
15
|
-
"19": reactV19Framework,
|
|
16
|
-
};
|
|
17
|
-
export function resolveReactFramework(packageJson, frameworkVersion) {
|
|
18
|
-
if (frameworkVersion && REACT_VARIANTS[frameworkVersion]) {
|
|
19
|
-
return REACT_VARIANTS[frameworkVersion];
|
|
20
|
-
}
|
|
21
|
-
const detected = packageJson?.dependencies?.react ?? packageJson?.devDependencies?.react;
|
|
22
|
-
const major = typeof detected === "string" ? detected.match(/\d+/)?.[0] : null;
|
|
23
|
-
if (major && REACT_VARIANTS[major]) {
|
|
24
|
-
return REACT_VARIANTS[major];
|
|
25
|
-
}
|
|
26
|
-
return reactFramework;
|
|
27
|
-
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { promises as fs } from "node:fs";
|
|
3
3
|
import path from "node:path";
|
|
4
|
-
import { parseArgs, printSupportedTargets, resolveFeatures, USAGE, } from "./cli.js";
|
|
4
|
+
import { parseArgs, printSupportedTargets, resolveFeatures, resolveTestRunner, USAGE, } from "./cli.js";
|
|
5
5
|
import { resolveFramework } from "./frameworks/index.js";
|
|
6
6
|
import { runFeatureRules } from "./mrm-rules/index.js";
|
|
7
7
|
import { detectPackageManager, runScript } from "./package-manager.js";
|
|
@@ -37,25 +37,22 @@ export async function main(argv = process.argv.slice(2)) {
|
|
|
37
37
|
const pm = !options.pm || options.pm === "auto"
|
|
38
38
|
? detectPackageManager(projectDir)
|
|
39
39
|
: options.pm;
|
|
40
|
-
const framework = resolveFramework(options.framework,
|
|
41
|
-
|
|
42
|
-
console.error(`Unsupported --framework-version for framework: ${framework.id}`);
|
|
43
|
-
process.exitCode = 1;
|
|
44
|
-
return;
|
|
45
|
-
}
|
|
40
|
+
const framework = resolveFramework(options.framework, packageJson);
|
|
41
|
+
const testRunner = resolveTestRunner(framework.id, options.testRunner);
|
|
46
42
|
const enabledFeatures = resolveFeatures(options);
|
|
47
43
|
const context = {
|
|
48
44
|
...options,
|
|
45
|
+
testRunner,
|
|
49
46
|
projectDir,
|
|
50
47
|
pm,
|
|
51
48
|
framework,
|
|
52
49
|
enabledFeatures,
|
|
53
50
|
};
|
|
54
51
|
console.log(formatStep(1, TOTAL_STEPS, "Resolve plan", options.dryRun));
|
|
55
|
-
console.log(`${options.dryRun ? "[dry-run] " : ""}Framework=${framework.id}
|
|
52
|
+
console.log(`${options.dryRun ? "[dry-run] " : ""}Framework=${framework.id}, features=${Object.entries(enabledFeatures)
|
|
56
53
|
.filter(([, enabled]) => enabled)
|
|
57
54
|
.map(([name]) => name)
|
|
58
|
-
.join(", ")}, testRunner=${
|
|
55
|
+
.join(", ")}, testRunner=${testRunner}`);
|
|
59
56
|
console.log(formatStep(2, TOTAL_STEPS, "Run mrm rules", options.dryRun));
|
|
60
57
|
await runFeatureRules(context);
|
|
61
58
|
console.log(formatStep(3, TOTAL_STEPS, "Finalize", options.dryRun));
|
package/package.json
CHANGED