@tyyyho/treg 0.1.2 → 0.1.6

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 (57) hide show
  1. package/README.md +52 -45
  2. package/dist/init-project/cli.js +228 -0
  3. package/dist/init-project/frameworks/index.js +39 -0
  4. package/dist/init-project/frameworks/next/index.js +9 -0
  5. package/dist/init-project/frameworks/node/index.js +8 -0
  6. package/dist/init-project/frameworks/nuxt/index.js +9 -0
  7. package/dist/init-project/frameworks/react/index.js +27 -0
  8. package/dist/init-project/frameworks/react/v18/index.js +6 -0
  9. package/dist/init-project/frameworks/react/v19/index.js +6 -0
  10. package/dist/init-project/frameworks/svelte/index.js +9 -0
  11. package/dist/init-project/frameworks/vue/index.js +9 -0
  12. package/dist/init-project/index.js +65 -0
  13. package/dist/init-project/mrm-core.js +3 -0
  14. package/dist/init-project/mrm-rules/ai-skills.js +200 -0
  15. package/dist/init-project/mrm-rules/format.js +44 -0
  16. package/dist/init-project/mrm-rules/husky.js +61 -0
  17. package/dist/init-project/mrm-rules/index.js +33 -0
  18. package/dist/init-project/mrm-rules/lint.js +16 -0
  19. package/dist/init-project/mrm-rules/shared.js +91 -0
  20. package/dist/init-project/mrm-rules/test-jest.js +48 -0
  21. package/dist/init-project/mrm-rules/test-vitest.js +46 -0
  22. package/dist/init-project/mrm-rules/typescript.js +40 -0
  23. package/dist/init-project/package-manager.js +57 -0
  24. package/dist/init-project/types.js +1 -0
  25. package/dist/init-project/utils.js +9 -0
  26. package/dist/init-project.js +6 -0
  27. package/dist/package.json +3 -0
  28. package/package.json +10 -5
  29. package/scripts/init-project/cli.mjs +0 -173
  30. package/scripts/init-project/cli.test.mjs +0 -116
  31. package/scripts/init-project/frameworks/index.mjs +0 -48
  32. package/scripts/init-project/frameworks/next/index.mjs +0 -10
  33. package/scripts/init-project/frameworks/node/index.mjs +0 -8
  34. package/scripts/init-project/frameworks/nuxt/index.mjs +0 -10
  35. package/scripts/init-project/frameworks/react/index.mjs +0 -35
  36. package/scripts/init-project/frameworks/react/v18/index.mjs +0 -6
  37. package/scripts/init-project/frameworks/react/v19/index.mjs +0 -6
  38. package/scripts/init-project/frameworks/svelte/index.mjs +0 -10
  39. package/scripts/init-project/frameworks/vue/index.mjs +0 -10
  40. package/scripts/init-project/frameworks.test.mjs +0 -63
  41. package/scripts/init-project/index.mjs +0 -89
  42. package/scripts/init-project/mrm-core.mjs +0 -5
  43. package/scripts/init-project/mrm-rules/ai-skills.mjs +0 -220
  44. package/scripts/init-project/mrm-rules/ai-skills.test.mjs +0 -91
  45. package/scripts/init-project/mrm-rules/format.mjs +0 -55
  46. package/scripts/init-project/mrm-rules/husky.mjs +0 -78
  47. package/scripts/init-project/mrm-rules/index.mjs +0 -35
  48. package/scripts/init-project/mrm-rules/lint.mjs +0 -18
  49. package/scripts/init-project/mrm-rules/shared.mjs +0 -61
  50. package/scripts/init-project/mrm-rules/test-jest.mjs +0 -75
  51. package/scripts/init-project/mrm-rules/test-vitest.mjs +0 -64
  52. package/scripts/init-project/mrm-rules/typescript.mjs +0 -44
  53. package/scripts/init-project/package-manager.mjs +0 -68
  54. package/scripts/init-project/package-manager.test.mjs +0 -21
  55. package/scripts/init-project/utils.mjs +0 -12
  56. package/scripts/init-project/utils.test.mjs +0 -22
  57. package/scripts/init-project.mjs +0 -7
package/README.md CHANGED
@@ -1,20 +1,46 @@
1
1
  # @tyyyho/treg
2
2
 
3
- Treg is a CLI tool for initializing development conventions in existing projects.
3
+ `treg` is a CLI for quickly setting up project tooling conventions in an existing repository.
4
+ It applies infra setup such as lint, format, TypeScript, test, husky, and AI skill guidance.
4
5
 
5
- It installs and configures tools and records clear usage guidelines as skills.
6
+ ## Quick Start
6
7
 
7
- Treg helps both human developers and AI agents work within the same set of expectations, reducing configuration drift and long-term maintenance overhead.
8
+ ```bash
9
+ pnpm dlx @tyyyho/treg init --framework react
10
+ # or
11
+ npx @tyyyho/treg init --framework react
12
+ ```
8
13
 
9
- ## Usage
14
+ `init` requires `--framework`.
15
+
16
+ ## Commands
10
17
 
11
18
  ```bash
12
- pnpm dlx @tyyyho/treg init <project-dir> --framework react
13
- # or
14
- npx @tyyyho/treg init <project-dir> --framework react
19
+ npx @tyyyho/treg <command> [options]
15
20
  ```
16
21
 
17
- By default, all features are applied:
22
+ - `init`: Initialize infra rules (requires `--framework`)
23
+ - `add`: Add selected infra features to an existing project
24
+ - `list`: List supported frameworks, features, and test runners
25
+
26
+ ## Options
27
+
28
+ - `--framework <node|react|next|vue|svelte|nuxt>`: Target framework
29
+ - `--framework-version <major>`: Optional major version hint (react only)
30
+ - `--features <lint,format,typescript,test,husky>`: Features to install (defaults to all)
31
+ - `--dir <path>`: Target directory (defaults to current directory)
32
+ - `--test-runner <jest|vitest>`: Test runner when test feature is enabled
33
+ - `--pm <pnpm|npm|yarn|auto>`: Package manager (auto-detected by default)
34
+ - `--force`: Overwrite existing config files
35
+ - `--dry-run`: Print full plan without writing files
36
+ - `--skip-husky-install`: Skip husky install command
37
+ - `--skills`: Update existing `AGENTS.md`/`CLAUDE.md` with skill guidance (enabled by default)
38
+ - `--no-skills`: Disable skill guidance updates
39
+ - `--help`: Show help
40
+
41
+ ## Features
42
+
43
+ Default feature set:
18
44
 
19
45
  - `husky`
20
46
  - `typescript`
@@ -22,71 +48,52 @@ By default, all features are applied:
22
48
  - `format`
23
49
  - `test`
24
50
 
25
- ## Options
26
-
27
- ```bash
28
- npx @tyyyho/treg <command> [projectDir] [options]
29
-
30
- init Initialize infra rules (requires --framework)
31
- add Add selected infra features
32
- list List supported targets
33
-
34
- --framework <node|react|next|vue|svelte|nuxt>
35
- Target framework
36
- --framework-version <major> Optional major version hint (currently react only)
37
- --pm <pnpm|npm|yarn|auto> Package manager (auto-detected by default)
38
- --features <lint,format,typescript,test,husky>
39
- Features to install (all selected by default)
40
- --test-runner <jest|vitest> Test runner when test feature is enabled
41
- --force Overwrite existing config files
42
- --dry-run Show planned changes without writing files
43
- --skip-husky-install Do not run husky install
44
- --skills Update AGENTS.md/CLAUDE.md with feature skill guidance
45
- --help Show help
46
- ```
47
-
48
51
  ## Examples
49
52
 
50
53
  Initialize a React project:
51
54
 
52
55
  ```bash
53
- npx @tyyyho/treg init . --framework react
56
+ npx @tyyyho/treg init --framework react
54
57
  ```
55
58
 
56
- Add only lint and format:
59
+ Add only lint + format:
57
60
 
58
61
  ```bash
59
- npx @tyyyho/treg add . --features lint,format
62
+ npx @tyyyho/treg add --features lint,format
60
63
  ```
61
64
 
62
- Use Vitest:
65
+ Use Vitest for test feature:
63
66
 
64
67
  ```bash
65
- npx @tyyyho/treg init . --framework node --features test --test-runner vitest
68
+ npx @tyyyho/treg init --framework node --features test --test-runner vitest
66
69
  ```
67
70
 
68
- Set framework major version explicitly (for variant rules):
71
+ Use react major version variant:
69
72
 
70
73
  ```bash
71
- npx @tyyyho/treg init . --framework react --framework-version 18
74
+ npx @tyyyho/treg init --framework react --framework-version 18
72
75
  ```
73
76
 
74
77
  Preview changes only:
75
78
 
76
79
  ```bash
77
- npx @tyyyho/treg init . --framework react --dry-run
80
+ npx @tyyyho/treg init --framework react --dry-run
78
81
  ```
79
82
 
80
- Enable AI skill guidance update:
83
+ Update AI skill guidance:
81
84
 
82
85
  ```bash
83
- npx @tyyyho/treg add . --features lint,format,husky --skills
86
+ npx @tyyyho/treg add --features lint,format,husky
84
87
  ```
85
88
 
86
- ## Publish
89
+ Target a different directory explicitly:
87
90
 
88
91
  ```bash
89
- pnpm install
90
- pnpm run prepublishOnly
91
- npm publish --access public
92
+ npx @tyyyho/treg init --framework react --dir ./packages/web
92
93
  ```
94
+
95
+ ## Notes
96
+
97
+ - `init` requires `--framework`.
98
+ - `add` lets you install only the features you specify.
99
+ - `--dry-run` prints the full plan and does not write files.
@@ -0,0 +1,228 @@
1
+ const ALLOWED_COMMANDS = ["init", "add", "list"];
2
+ const ALLOWED_PACKAGE_MANAGERS = [
3
+ "pnpm",
4
+ "npm",
5
+ "yarn",
6
+ "auto",
7
+ ];
8
+ const ALLOWED_FRAMEWORKS = [
9
+ "node",
10
+ "react",
11
+ "next",
12
+ "vue",
13
+ "svelte",
14
+ "nuxt",
15
+ ];
16
+ const ALLOWED_FEATURES = [
17
+ "lint",
18
+ "format",
19
+ "typescript",
20
+ "test",
21
+ "husky",
22
+ ];
23
+ const ALLOWED_TEST_RUNNERS = ["jest", "vitest"];
24
+ export const USAGE = `Usage: treg <command> [options]
25
+
26
+ Commands:
27
+ init Initialize infra rules in a project (requires --framework)
28
+ add Add selected infra features to an existing project
29
+ list List supported frameworks, features, and test runners
30
+
31
+ Options:
32
+ --framework <node|react|next|vue|svelte|nuxt>
33
+ Target framework
34
+ --framework-version <major> Optional framework major version hint
35
+ --features <lint,format,typescript,test,husky>
36
+ Features to install (all selected by default)
37
+ --dir <path> Target directory (defaults to current directory)
38
+ --test-runner <jest|vitest> Test runner when test feature is enabled
39
+ --pm <pnpm|npm|yarn|auto> Package manager (auto-detected if omitted)
40
+ --force Overwrite existing config files
41
+ --dry-run Print planned changes without writing files
42
+ --skip-husky-install Do not run husky install
43
+ --skills Update AGENTS.md/CLAUDE.md with feature skill guidance (default: enabled)
44
+ --no-skills Disable AGENTS.md/CLAUDE.md skill guidance updates
45
+ -h, --help Show help
46
+ `;
47
+ function includes(allowed, value) {
48
+ return allowed.includes(value);
49
+ }
50
+ function isCommandName(value) {
51
+ return includes(ALLOWED_COMMANDS, value);
52
+ }
53
+ function isPackageManagerOption(value) {
54
+ return includes(ALLOWED_PACKAGE_MANAGERS, value);
55
+ }
56
+ function isFrameworkId(value) {
57
+ return includes(ALLOWED_FRAMEWORKS, value);
58
+ }
59
+ function isFeatureName(value) {
60
+ return includes(ALLOWED_FEATURES, value);
61
+ }
62
+ function isTestRunner(value) {
63
+ return includes(ALLOWED_TEST_RUNNERS, value);
64
+ }
65
+ export function parseArgs(argv) {
66
+ const options = {
67
+ command: "init",
68
+ projectDir: null,
69
+ framework: null,
70
+ frameworkVersion: null,
71
+ features: [],
72
+ testRunner: "jest",
73
+ pm: null,
74
+ force: false,
75
+ dryRun: false,
76
+ skipHuskyInstall: false,
77
+ skills: true,
78
+ help: false,
79
+ };
80
+ let cursor = 0;
81
+ const firstArg = argv[0];
82
+ if (firstArg && isCommandName(firstArg)) {
83
+ options.command = firstArg;
84
+ cursor = 1;
85
+ }
86
+ for (let i = cursor; i < argv.length; i += 1) {
87
+ const arg = argv[i];
88
+ if (!arg) {
89
+ continue;
90
+ }
91
+ if (arg === "-h" || arg === "--help") {
92
+ options.help = true;
93
+ }
94
+ else if (arg === "--framework") {
95
+ options.framework = readFlagValue(argv, i, "--framework");
96
+ i += 1;
97
+ }
98
+ else if (arg.startsWith("--framework=")) {
99
+ options.framework = readInlineFlagValue(arg, "--framework");
100
+ }
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
+ else if (arg === "--features") {
109
+ options.features.push(...parseCsvValue(argv[i + 1], "--features"));
110
+ i += 1;
111
+ }
112
+ else if (arg.startsWith("--features=")) {
113
+ options.features.push(...parseCsvValue(readInlineFlagValue(arg, "--features"), "--features"));
114
+ }
115
+ else if (arg === "--dir") {
116
+ options.projectDir = readFlagValue(argv, i, "--dir");
117
+ i += 1;
118
+ }
119
+ else if (arg.startsWith("--dir=")) {
120
+ options.projectDir = readInlineFlagValue(arg, "--dir");
121
+ }
122
+ else if (arg === "--test-runner") {
123
+ options.testRunner = readFlagValue(argv, i, "--test-runner");
124
+ i += 1;
125
+ }
126
+ else if (arg.startsWith("--test-runner=")) {
127
+ options.testRunner = readInlineFlagValue(arg, "--test-runner");
128
+ }
129
+ else if (arg === "--pm") {
130
+ options.pm = readFlagValue(argv, i, "--pm");
131
+ i += 1;
132
+ }
133
+ else if (arg.startsWith("--pm=")) {
134
+ options.pm = readInlineFlagValue(arg, "--pm");
135
+ }
136
+ else if (arg === "--force") {
137
+ options.force = true;
138
+ }
139
+ else if (arg === "--dry-run") {
140
+ options.dryRun = true;
141
+ }
142
+ else if (arg === "--skip-husky-install") {
143
+ options.skipHuskyInstall = true;
144
+ }
145
+ else if (arg === "--skills") {
146
+ options.skills = true;
147
+ }
148
+ else if (arg === "--no-skills") {
149
+ options.skills = false;
150
+ }
151
+ else {
152
+ throw new Error(`Unknown argument: ${arg}`);
153
+ }
154
+ }
155
+ validateParsedOptions(options);
156
+ return options;
157
+ }
158
+ function readFlagValue(argv, index, flagName) {
159
+ const value = argv[index + 1];
160
+ if (!value) {
161
+ throw new Error(`Missing value for ${flagName}`);
162
+ }
163
+ return value;
164
+ }
165
+ function readInlineFlagValue(arg, flagName) {
166
+ const [, rawValue] = arg.split("=", 2);
167
+ if (!rawValue) {
168
+ throw new Error(`Missing value for ${flagName}`);
169
+ }
170
+ return rawValue;
171
+ }
172
+ function parseCsvValue(rawValue, flagName) {
173
+ if (!rawValue) {
174
+ throw new Error(`Missing value for ${flagName}`);
175
+ }
176
+ return rawValue
177
+ .split(",")
178
+ .map(item => item.trim())
179
+ .filter(Boolean);
180
+ }
181
+ function validateParsedOptions(options) {
182
+ if (!isCommandName(options.command)) {
183
+ throw new Error(`Unsupported command: ${options.command}`);
184
+ }
185
+ if (options.projectDir === "") {
186
+ throw new Error("Missing value for --dir");
187
+ }
188
+ if (options.pm && !isPackageManagerOption(options.pm)) {
189
+ throw new Error(`Unsupported package manager: ${options.pm}`);
190
+ }
191
+ if (options.framework && !isFrameworkId(options.framework)) {
192
+ throw new Error(`Unsupported framework: ${options.framework}`);
193
+ }
194
+ if (options.frameworkVersion && !/^\d+$/.test(options.frameworkVersion)) {
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)) {
203
+ throw new Error(`Unsupported test runner: ${options.testRunner}`);
204
+ }
205
+ for (const feature of options.features) {
206
+ if (!isFeatureName(feature)) {
207
+ throw new Error(`Unsupported feature in --features: ${feature}`);
208
+ }
209
+ }
210
+ if (options.command === "init" && !options.help && !options.framework) {
211
+ throw new Error("Missing required option: --framework");
212
+ }
213
+ }
214
+ export function resolveFeatures(options) {
215
+ const selected = new Set(options.features.length > 0 ? options.features : ALLOWED_FEATURES);
216
+ return {
217
+ lint: selected.has("lint"),
218
+ format: selected.has("format"),
219
+ typescript: selected.has("typescript"),
220
+ test: selected.has("test"),
221
+ husky: selected.has("husky"),
222
+ };
223
+ }
224
+ export function printSupportedTargets() {
225
+ console.log("Frameworks: node, react, next, vue, svelte, nuxt");
226
+ console.log("Features: lint, format, typescript, test, husky");
227
+ console.log("Test runners: jest, vitest");
228
+ }
@@ -0,0 +1,39 @@
1
+ import { nextFramework } from "./next/index.js";
2
+ import { nodeFramework } from "./node/index.js";
3
+ import { nuxtFramework } from "./nuxt/index.js";
4
+ import { reactFramework, resolveReactFramework } from "./react/index.js";
5
+ import { svelteFramework } from "./svelte/index.js";
6
+ import { vueFramework } from "./vue/index.js";
7
+ const FRAMEWORK_REGISTRY = {
8
+ next: nextFramework,
9
+ node: nodeFramework,
10
+ nuxt: nuxtFramework,
11
+ react: reactFramework,
12
+ svelte: svelteFramework,
13
+ vue: vueFramework,
14
+ };
15
+ const FRAMEWORK_DETECT_ORDER = [
16
+ nuxtFramework,
17
+ nextFramework,
18
+ reactFramework,
19
+ vueFramework,
20
+ svelteFramework,
21
+ nodeFramework,
22
+ ];
23
+ export function resolveFramework(frameworkArg, frameworkVersion, packageJson) {
24
+ if (frameworkArg === "react") {
25
+ return resolveReactFramework(packageJson, frameworkVersion);
26
+ }
27
+ if (frameworkArg) {
28
+ return FRAMEWORK_REGISTRY[frameworkArg];
29
+ }
30
+ const detected = detectFramework(packageJson);
31
+ if (detected.id === "react") {
32
+ return resolveReactFramework(packageJson, frameworkVersion);
33
+ }
34
+ return detected;
35
+ }
36
+ export function detectFramework(packageJson) {
37
+ const matched = FRAMEWORK_DETECT_ORDER.find(framework => framework.matches(packageJson));
38
+ return matched ?? nodeFramework;
39
+ }
@@ -0,0 +1,9 @@
1
+ import { hasPackage } from "../../utils.js";
2
+ export const nextFramework = {
3
+ id: "next",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: [".next", "dist", "coverage", "jest.config.js", "public"],
6
+ matches(packageJson) {
7
+ return hasPackage(packageJson, "next");
8
+ },
9
+ };
@@ -0,0 +1,8 @@
1
+ export const nodeFramework = {
2
+ id: "node",
3
+ testEnvironment: "node",
4
+ tsRequiredExcludes: ["dist", "coverage"],
5
+ matches() {
6
+ return true;
7
+ },
8
+ };
@@ -0,0 +1,9 @@
1
+ import { hasPackage } from "../../utils.js";
2
+ export const nuxtFramework = {
3
+ id: "nuxt",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: [".nuxt", ".output", "dist", "coverage", "public"],
6
+ matches(packageJson) {
7
+ return hasPackage(packageJson, "nuxt");
8
+ },
9
+ };
@@ -0,0 +1,27 @@
1
+ import { hasPackage } from "../../utils.js";
2
+ import { reactV18Framework } from "./v18/index.js";
3
+ import { reactV19Framework } from "./v19/index.js";
4
+ export const reactFramework = {
5
+ id: "react",
6
+ variant: "v19",
7
+ testEnvironment: "jsdom",
8
+ tsRequiredExcludes: ["dist", "coverage", "jest.config.js", "public"],
9
+ matches(packageJson) {
10
+ return (hasPackage(packageJson, "react") || hasPackage(packageJson, "react-dom"));
11
+ },
12
+ };
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
+ }
@@ -0,0 +1,6 @@
1
+ export const reactV18Framework = {
2
+ id: "react",
3
+ variant: "v18",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: ["dist", "coverage", "jest.config.js", "public"],
6
+ };
@@ -0,0 +1,6 @@
1
+ export const reactV19Framework = {
2
+ id: "react",
3
+ variant: "v19",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: ["dist", "coverage", "jest.config.js", "public"],
6
+ };
@@ -0,0 +1,9 @@
1
+ import { hasPackage } from "../../utils.js";
2
+ export const svelteFramework = {
3
+ id: "svelte",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: ["dist", "coverage", ".svelte-kit"],
6
+ matches(packageJson) {
7
+ return hasPackage(packageJson, "svelte");
8
+ },
9
+ };
@@ -0,0 +1,9 @@
1
+ import { hasPackage } from "../../utils.js";
2
+ export const vueFramework = {
3
+ id: "vue",
4
+ testEnvironment: "jsdom",
5
+ tsRequiredExcludes: ["dist", "coverage"],
6
+ matches(packageJson) {
7
+ return hasPackage(packageJson, "vue");
8
+ },
9
+ };
@@ -0,0 +1,65 @@
1
+ import { existsSync } from "node:fs";
2
+ import { promises as fs } from "node:fs";
3
+ import path from "node:path";
4
+ import { parseArgs, printSupportedTargets, resolveFeatures, USAGE, } from "./cli.js";
5
+ import { resolveFramework } from "./frameworks/index.js";
6
+ import { runFeatureRules } from "./mrm-rules/index.js";
7
+ import { detectPackageManager, runScript } from "./package-manager.js";
8
+ import { formatStep } from "./utils.js";
9
+ const TOTAL_STEPS = 3;
10
+ export async function main(argv = process.argv.slice(2)) {
11
+ let options;
12
+ try {
13
+ options = parseArgs(argv);
14
+ }
15
+ catch (error) {
16
+ console.error(error.message ?? error);
17
+ console.log(USAGE);
18
+ process.exitCode = 1;
19
+ return;
20
+ }
21
+ if (options.help) {
22
+ console.log(USAGE);
23
+ return;
24
+ }
25
+ if (options.command === "list") {
26
+ printSupportedTargets();
27
+ return;
28
+ }
29
+ const projectDir = path.resolve(options.projectDir ?? process.cwd());
30
+ const packageJsonPath = path.join(projectDir, "package.json");
31
+ if (!existsSync(packageJsonPath)) {
32
+ console.error(`package.json not found in ${projectDir}`);
33
+ process.exitCode = 1;
34
+ return;
35
+ }
36
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
37
+ const pm = !options.pm || options.pm === "auto"
38
+ ? detectPackageManager(projectDir)
39
+ : options.pm;
40
+ const framework = resolveFramework(options.framework, options.frameworkVersion, packageJson);
41
+ if (options.frameworkVersion && framework.id !== "react") {
42
+ console.error(`Unsupported --framework-version for framework: ${framework.id}`);
43
+ process.exitCode = 1;
44
+ return;
45
+ }
46
+ const enabledFeatures = resolveFeatures(options);
47
+ const context = {
48
+ ...options,
49
+ projectDir,
50
+ pm,
51
+ framework,
52
+ enabledFeatures,
53
+ };
54
+ console.log(formatStep(1, TOTAL_STEPS, "Resolve plan", options.dryRun));
55
+ console.log(`${options.dryRun ? "[dry-run] " : ""}Framework=${framework.id}${framework.variant ? `/${framework.variant}` : ""}, features=${Object.entries(enabledFeatures)
56
+ .filter(([, enabled]) => enabled)
57
+ .map(([name]) => name)
58
+ .join(", ")}, testRunner=${options.testRunner}`);
59
+ console.log(formatStep(2, TOTAL_STEPS, "Run mrm rules", options.dryRun));
60
+ await runFeatureRules(context);
61
+ console.log(formatStep(3, TOTAL_STEPS, "Finalize", options.dryRun));
62
+ if (enabledFeatures.format) {
63
+ runScript(pm, "format", projectDir, options.dryRun);
64
+ }
65
+ }
@@ -0,0 +1,3 @@
1
+ import { createRequire } from "node:module";
2
+ const require = createRequire(import.meta.url);
3
+ export const { file, json, lines, packageJson, install } = require("mrm-core");