@remix-run/cli 0.1.0 → 0.3.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/README.md +0 -3
- package/dist/lib/bootstrap-project.d.ts.map +1 -1
- package/dist/lib/bootstrap-project.js +32 -9
- package/dist/lib/cli.d.ts +29 -0
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +33 -14
- package/dist/lib/commands/completion.d.ts.map +1 -1
- package/dist/lib/commands/completion.js +5 -1
- package/dist/lib/commands/doctor.js +18 -18
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +9 -33
- package/dist/lib/commands/routes.js +3 -3
- package/dist/lib/commands/test.d.ts +1 -1
- package/dist/lib/commands/test.d.ts.map +1 -1
- package/dist/lib/commands/test.js +8 -4
- package/dist/lib/completion.d.ts.map +1 -1
- package/dist/lib/completion.js +4 -106
- package/dist/lib/controller-files.d.ts +0 -1
- package/dist/lib/controller-files.d.ts.map +1 -1
- package/dist/lib/controller-files.js +3 -5
- package/dist/lib/controller-ownership.d.ts +9 -9
- package/dist/lib/controller-ownership.d.ts.map +1 -1
- package/dist/lib/controller-ownership.js +56 -91
- package/dist/lib/doctor/controller-findings.d.ts +1 -1
- package/dist/lib/doctor/controller-findings.d.ts.map +1 -1
- package/dist/lib/doctor/controller-findings.js +15 -87
- package/dist/lib/doctor/controller-fix-plans.d.ts.map +1 -1
- package/dist/lib/doctor/controller-fix-plans.js +13 -24
- package/dist/lib/doctor/controller-placeholders.d.ts +2 -3
- package/dist/lib/doctor/controller-placeholders.d.ts.map +1 -1
- package/dist/lib/doctor/controller-placeholders.js +18 -149
- package/dist/lib/doctor/controllers.js +1 -1
- package/dist/lib/doctor/project.js +60 -52
- package/dist/lib/doctor/types.d.ts +2 -2
- package/dist/lib/doctor/types.d.ts.map +1 -1
- package/dist/lib/errors.d.ts +0 -6
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +0 -11
- package/dist/lib/load-route-map-worker.js +17 -9
- package/dist/lib/route-map.d.ts +1 -1
- package/dist/lib/route-map.d.ts.map +1 -1
- package/dist/lib/route-map.js +29 -17
- package/package.json +4 -5
- package/src/lib/bootstrap-project.ts +39 -13
- package/src/lib/cli.ts +46 -15
- package/src/lib/commands/completion.ts +6 -1
- package/src/lib/commands/doctor.ts +18 -21
- package/src/lib/commands/help.ts +9 -43
- package/src/lib/commands/routes.ts +3 -3
- package/src/lib/commands/test.ts +10 -4
- package/src/lib/completion.ts +4 -151
- package/src/lib/controller-files.ts +4 -8
- package/src/lib/controller-ownership.ts +78 -141
- package/src/lib/doctor/controller-findings.ts +20 -97
- package/src/lib/doctor/controller-fix-plans.ts +13 -29
- package/src/lib/doctor/controller-placeholders.ts +17 -189
- package/src/lib/doctor/controllers.ts +1 -1
- package/src/lib/doctor/project.ts +60 -52
- package/src/lib/doctor/types.ts +1 -5
- package/src/lib/errors.ts +0 -12
- package/src/lib/load-route-map-worker.ts +19 -10
- package/src/lib/route-map.ts +61 -16
- package/template/.agents/skills/remix/SKILL.md +588 -0
- package/template/.agents/skills/remix/references/animate-elements.md +195 -0
- package/template/.agents/skills/remix/references/assets-and-browser-modules.md +130 -0
- package/template/.agents/skills/remix/references/auth-and-sessions.md +443 -0
- package/template/.agents/skills/remix/references/component-model.md +282 -0
- package/template/.agents/skills/remix/references/create-mixins.md +158 -0
- package/template/.agents/skills/remix/references/data-and-validation.md +379 -0
- package/template/.agents/skills/remix/references/hydration-frames-navigation.md +297 -0
- package/template/.agents/skills/remix/references/middleware-and-server.md +233 -0
- package/template/.agents/skills/remix/references/mixins-styling-events.md +213 -0
- package/template/.agents/skills/remix/references/routing-and-controllers.md +391 -0
- package/template/.agents/skills/remix/references/testing-patterns.md +172 -0
- package/{bootstrap → template}/AGENTS.md +13 -8
- package/template/README.md +29 -0
- package/template/app/actions/controller.tsx +18 -0
- package/template/app/assets/entry.ts +8 -0
- package/template/app/assets/prompt-button.tsx +163 -0
- package/template/app/assets.ts +20 -0
- package/template/app/middleware/render.tsx +43 -0
- package/template/app/router.ts +20 -0
- package/template/app/routes.ts +6 -0
- package/template/app/ui/document.tsx +33 -0
- package/template/app/ui/scaffold-home-page.tsx +527 -0
- package/template/gitignore +4 -0
- package/{bootstrap → template}/package.json +5 -6
- package/template/public/favicon.svg +11 -0
- package/{bootstrap → template}/server.ts +4 -5
- package/{bootstrap → template}/tsconfig.json +3 -3
- package/bootstrap/README.md +0 -27
- package/bootstrap/app/controllers/auth.tsx +0 -21
- package/bootstrap/app/controllers/home.tsx +0 -26
- package/bootstrap/app/router.ts +0 -10
- package/bootstrap/app/routes.ts +0 -6
- package/bootstrap/app/ui/document.tsx +0 -21
- package/bootstrap/app/ui/layout.tsx +0 -22
- package/bootstrap/app/utils/render.tsx +0 -7
- package/dist/lib/commands/skills.d.ts +0 -6
- package/dist/lib/commands/skills.d.ts.map +0 -1
- package/dist/lib/commands/skills.js +0 -222
- package/dist/lib/skills-cache.d.ts +0 -19
- package/dist/lib/skills-cache.d.ts.map +0 -1
- package/dist/lib/skills-cache.js +0 -89
- package/dist/lib/skills.d.ts +0 -30
- package/dist/lib/skills.d.ts.map +0 -1
- package/dist/lib/skills.js +0 -441
- package/src/lib/commands/skills.ts +0 -306
- package/src/lib/skills-cache.ts +0 -140
- package/src/lib/skills.ts +0 -706
package/README.md
CHANGED
|
@@ -9,7 +9,6 @@ Command-line interface for creating and managing Remix projects.
|
|
|
9
9
|
- Check project environment and Remix app conventions with `remix doctor`
|
|
10
10
|
- Create low-risk project and controller files with `remix doctor --fix`
|
|
11
11
|
- Inspect the current app route tree with `remix routes`
|
|
12
|
-
- Sync Remix skills into `.agents/skills` with `remix skills`
|
|
13
12
|
- Run project tests with `remix test`
|
|
14
13
|
- Print the current Remix version with `remix version`
|
|
15
14
|
- Use the same CLI through the `remix` package or the `remix/cli` API
|
|
@@ -51,7 +50,6 @@ remix doctor --fix
|
|
|
51
50
|
remix routes
|
|
52
51
|
remix routes --table
|
|
53
52
|
remix routes --table --no-headers
|
|
54
|
-
remix skills install
|
|
55
53
|
remix test
|
|
56
54
|
remix version
|
|
57
55
|
remix --no-color doctor
|
|
@@ -69,7 +67,6 @@ await runRemix(['doctor', '--fix'])
|
|
|
69
67
|
await runRemix(['routes'])
|
|
70
68
|
await runRemix(['routes', '--table'])
|
|
71
69
|
await runRemix(['routes', '--table', '--no-headers'])
|
|
72
|
-
await runRemix(['skills', 'list'])
|
|
73
70
|
await runRemix(['test'])
|
|
74
71
|
await runRemix(['version'])
|
|
75
72
|
```
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bootstrap-project.d.ts","sourceRoot":"","sources":["../../src/lib/bootstrap-project.ts"],"names":[],"mappings":"AAYA,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;
|
|
1
|
+
{"version":3,"file":"bootstrap-project.d.ts","sourceRoot":"","sources":["../../src/lib/bootstrap-project.ts"],"names":[],"mappings":"AAYA,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,eAAe,CAAA;AAM1E,eAAO,MAAM,8BAA8B,WAAW,CAAA;AAEtD,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,OAAO,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,qBAAqB,GAC7B,0BAA0B,GAC1B,yBAAyB,GACzB,uBAAuB,CAAA;AAE3B,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,MAAM,yBAAyB,GAAG,oBAAoB,CAAC,qBAAqB,CAAC,CAAA;AAUnF,wBAAsB,gBAAgB,CACpC,OAAO,EAAE,uBAAuB,EAChC,QAAQ,CAAC,EAAE,yBAAyB,GACnC,OAAO,CAAC,mBAAmB,CAAC,CAgC9B"}
|
|
@@ -5,8 +5,10 @@ import { fileURLToPath } from 'node:url';
|
|
|
5
5
|
import semver from 'semver';
|
|
6
6
|
import { appNameUnavailable, invalidPackageName, targetDirectoryNotEmpty, targetPathNotDirectory, } from "./errors.js";
|
|
7
7
|
import { runProgressStep } from "./reporter.js";
|
|
8
|
-
const
|
|
9
|
-
const
|
|
8
|
+
const MODULE_DIRECTORY = path.dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
const PACKAGE_TEMPLATE_DIRECTORY = path.resolve(MODULE_DIRECTORY, '../../template');
|
|
10
|
+
const REPO_TEMPLATE_DIRECTORY = path.resolve(MODULE_DIRECTORY, '../../../../template');
|
|
11
|
+
const TEMPLATE_EXCLUDED_NAMES = new Set(['.gitkeep', 'node_modules']);
|
|
10
12
|
export const MINIMUM_SUPPORTED_NODE_VERSION = '24.3.0';
|
|
11
13
|
export async function bootstrapProject(options, progress) {
|
|
12
14
|
let cwd = options.cwd ?? process.cwd();
|
|
@@ -21,8 +23,8 @@ export async function bootstrapProject(options, progress) {
|
|
|
21
23
|
remixVersion: readDefaultRemixVersion(options.remixVersion),
|
|
22
24
|
};
|
|
23
25
|
await runProgressStep(progress, 'prepare-target-directory', () => ensureTargetDirectory(targetDir, options.force));
|
|
24
|
-
await runProgressStep(progress, 'generate-scaffold-files', () =>
|
|
25
|
-
sourceDir:
|
|
26
|
+
await runProgressStep(progress, 'generate-scaffold-files', async () => copyTemplateDirectory({
|
|
27
|
+
sourceDir: await resolveTemplateDirectory(),
|
|
26
28
|
targetDir,
|
|
27
29
|
templateValues: createTemplateValues(config),
|
|
28
30
|
}));
|
|
@@ -49,6 +51,28 @@ function createTemplateValues(config) {
|
|
|
49
51
|
'%%RMX_APP_DISPLAY_NAME_URI_COMPONENT%%': encodeURIComponent(config.appDisplayName),
|
|
50
52
|
};
|
|
51
53
|
}
|
|
54
|
+
async function resolveTemplateDirectory() {
|
|
55
|
+
if (await isDirectory(PACKAGE_TEMPLATE_DIRECTORY)) {
|
|
56
|
+
return PACKAGE_TEMPLATE_DIRECTORY;
|
|
57
|
+
}
|
|
58
|
+
if (await isDirectory(REPO_TEMPLATE_DIRECTORY)) {
|
|
59
|
+
return REPO_TEMPLATE_DIRECTORY;
|
|
60
|
+
}
|
|
61
|
+
throw new Error(`Could not find the Remix app template at ${PACKAGE_TEMPLATE_DIRECTORY} or ${REPO_TEMPLATE_DIRECTORY}.`);
|
|
62
|
+
}
|
|
63
|
+
async function isDirectory(directory) {
|
|
64
|
+
try {
|
|
65
|
+
let stats = await fs.stat(directory);
|
|
66
|
+
return stats.isDirectory();
|
|
67
|
+
}
|
|
68
|
+
catch (error) {
|
|
69
|
+
let nodeError = error;
|
|
70
|
+
if (nodeError.code === 'ENOENT') {
|
|
71
|
+
return false;
|
|
72
|
+
}
|
|
73
|
+
throw error;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
52
76
|
async function writeScaffoldPackageJson(targetDir, config) {
|
|
53
77
|
let packageJsonPath = path.join(targetDir, 'package.json');
|
|
54
78
|
let packageJson = JSON.parse(await fs.readFile(packageJsonPath, 'utf8'));
|
|
@@ -56,7 +80,6 @@ async function writeScaffoldPackageJson(targetDir, config) {
|
|
|
56
80
|
packageJson.dependencies = {
|
|
57
81
|
...packageJson.dependencies,
|
|
58
82
|
remix: config.remixVersion,
|
|
59
|
-
tsx: 'latest',
|
|
60
83
|
};
|
|
61
84
|
packageJson.devDependencies = {
|
|
62
85
|
...packageJson.devDependencies,
|
|
@@ -88,17 +111,17 @@ async function ensureTargetDirectory(targetDir, force) {
|
|
|
88
111
|
}
|
|
89
112
|
await fs.mkdir(targetDir, { recursive: true });
|
|
90
113
|
}
|
|
91
|
-
async function
|
|
114
|
+
async function copyTemplateDirectory({ sourceDir, targetDir, templateValues, }) {
|
|
92
115
|
let entries = await fs.readdir(sourceDir, { withFileTypes: true });
|
|
93
116
|
for (let entry of entries) {
|
|
94
117
|
let sourcePath = path.join(sourceDir, entry.name);
|
|
95
|
-
let targetPath = path.join(targetDir, entry.name);
|
|
96
|
-
if (
|
|
118
|
+
let targetPath = path.join(targetDir, entry.name === 'gitignore' ? '.gitignore' : entry.name);
|
|
119
|
+
if (TEMPLATE_EXCLUDED_NAMES.has(entry.name)) {
|
|
97
120
|
continue;
|
|
98
121
|
}
|
|
99
122
|
if (entry.isDirectory()) {
|
|
100
123
|
await fs.mkdir(targetPath, { recursive: true });
|
|
101
|
-
await
|
|
124
|
+
await copyTemplateDirectory({ sourceDir: sourcePath, targetDir: targetPath, templateValues });
|
|
102
125
|
continue;
|
|
103
126
|
}
|
|
104
127
|
let content = await fs.readFile(sourcePath, 'utf8');
|
package/dist/lib/cli.d.ts
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Options accepted by {@link runRemix}.
|
|
3
|
+
*/
|
|
1
4
|
export interface RunRemixOptions {
|
|
5
|
+
/**
|
|
6
|
+
* Directory used as the working root when resolving project files (default
|
|
7
|
+
* `process.cwd()`).
|
|
8
|
+
*/
|
|
2
9
|
cwd?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Override for the Remix version reported by `remix --version`. Defaults to
|
|
12
|
+
* the version of the installed `@remix-run/cli` package.
|
|
13
|
+
*/
|
|
3
14
|
remixVersion?: string;
|
|
4
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Entry point for the `remix` CLI. Parses `argv`, dispatches to the matching
|
|
18
|
+
* subcommand (`new`, `doctor`, `routes`, `test`, `version`, `completion`,
|
|
19
|
+
* `help`), and resolves with the exit code the process should use.
|
|
20
|
+
*
|
|
21
|
+
* @param argv Argument vector to parse, excluding the node and script paths
|
|
22
|
+
* (default `process.argv.slice(2)`).
|
|
23
|
+
* @param options Overrides for CLI context resolution.
|
|
24
|
+
* @returns The numeric exit code (`0` on success, non-zero on failure).
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```ts
|
|
28
|
+
* import { runRemix } from '@remix-run/cli'
|
|
29
|
+
*
|
|
30
|
+
* let exitCode = await runRemix(process.argv.slice(2))
|
|
31
|
+
* process.exit(exitCode)
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
5
34
|
export declare function runRemix(argv?: string[], options?: RunRemixOptions): Promise<number>;
|
|
6
35
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/lib/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAOA;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,QAAQ,CAC5B,IAAI,GAAE,MAAM,EAA0B,EACtC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CA0BjB"}
|
package/dist/lib/cli.js
CHANGED
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
import * as process from 'node:process';
|
|
2
|
-
import { runCompletionCommand } from "./commands/completion.js";
|
|
3
|
-
import { runDoctorCommand } from "./commands/doctor.js";
|
|
4
2
|
import { getCliHelpText, runHelpCommand } from "./commands/help.js";
|
|
5
|
-
import { runNewCommand } from "./commands/new.js";
|
|
6
|
-
import { runRoutesCommand } from "./commands/routes.js";
|
|
7
|
-
import { runSkillsCommand } from "./commands/skills.js";
|
|
8
|
-
import { runTestCommand } from "./commands/test.js";
|
|
9
|
-
import { runVersionCommand } from "./commands/version.js";
|
|
10
3
|
import { resolveCliContext } from "./cli-context.js";
|
|
11
4
|
import { renderCliError, unknownCommand } from "./errors.js";
|
|
12
5
|
import { configureColors, restoreTerminalFormatting } from "./terminal.js";
|
|
6
|
+
/**
|
|
7
|
+
* Entry point for the `remix` CLI. Parses `argv`, dispatches to the matching
|
|
8
|
+
* subcommand (`new`, `doctor`, `routes`, `test`, `version`, `completion`,
|
|
9
|
+
* `help`), and resolves with the exit code the process should use.
|
|
10
|
+
*
|
|
11
|
+
* @param argv Argument vector to parse, excluding the node and script paths
|
|
12
|
+
* (default `process.argv.slice(2)`).
|
|
13
|
+
* @param options Overrides for CLI context resolution.
|
|
14
|
+
* @returns The numeric exit code (`0` on success, non-zero on failure).
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { runRemix } from '@remix-run/cli'
|
|
19
|
+
*
|
|
20
|
+
* let exitCode = await runRemix(process.argv.slice(2))
|
|
21
|
+
* process.exit(exitCode)
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
13
24
|
export async function runRemix(argv = process.argv.slice(2), options = {}) {
|
|
14
25
|
let context = await resolveCliContext(options);
|
|
15
26
|
try {
|
|
16
|
-
|
|
17
|
-
argv = argv.slice(1);
|
|
18
|
-
}
|
|
27
|
+
argv = stripLeadingSeparators(argv);
|
|
19
28
|
let globalOptions = extractGlobalOptions(argv);
|
|
20
|
-
argv = globalOptions.argv;
|
|
29
|
+
argv = stripLeadingSeparators(globalOptions.argv);
|
|
21
30
|
configureColors({ disabled: globalOptions.noColor });
|
|
22
31
|
if (argv.length === 0) {
|
|
23
32
|
process.stdout.write(getCliHelpText());
|
|
@@ -34,32 +43,42 @@ export async function runRemix(argv = process.argv.slice(2), options = {}) {
|
|
|
34
43
|
restoreTerminalFormatting();
|
|
35
44
|
}
|
|
36
45
|
}
|
|
46
|
+
function stripLeadingSeparators(argv) {
|
|
47
|
+
while (argv[0] === '--') {
|
|
48
|
+
argv = argv.slice(1);
|
|
49
|
+
}
|
|
50
|
+
return argv;
|
|
51
|
+
}
|
|
37
52
|
async function runCommand(command, argv, context) {
|
|
38
53
|
if (command === 'help') {
|
|
39
54
|
return runHelpCommand(argv);
|
|
40
55
|
}
|
|
41
56
|
if (command === '-v' || command === '--version') {
|
|
57
|
+
let { runVersionCommand } = await import("./commands/version.js");
|
|
42
58
|
return runVersionCommand([], context);
|
|
43
59
|
}
|
|
44
60
|
if (command === 'new') {
|
|
61
|
+
let { runNewCommand } = await import("./commands/new.js");
|
|
45
62
|
return runNewCommand(argv, context);
|
|
46
63
|
}
|
|
47
64
|
if (command === 'completion') {
|
|
65
|
+
let { runCompletionCommand } = await import("./commands/completion.js");
|
|
48
66
|
return runCompletionCommand(argv);
|
|
49
67
|
}
|
|
50
68
|
if (command === 'doctor') {
|
|
69
|
+
let { runDoctorCommand } = await import("./commands/doctor.js");
|
|
51
70
|
return runDoctorCommand(argv, context);
|
|
52
71
|
}
|
|
53
|
-
if (command === 'skills') {
|
|
54
|
-
return runSkillsCommand(argv, context);
|
|
55
|
-
}
|
|
56
72
|
if (command === 'routes') {
|
|
73
|
+
let { runRoutesCommand } = await import("./commands/routes.js");
|
|
57
74
|
return runRoutesCommand(argv, context);
|
|
58
75
|
}
|
|
59
76
|
if (command === 'test') {
|
|
77
|
+
let { runTestCommand } = await import("./commands/test.js");
|
|
60
78
|
return runTestCommand(argv, context);
|
|
61
79
|
}
|
|
62
80
|
if (command === 'version') {
|
|
81
|
+
let { runVersionCommand } = await import("./commands/version.js");
|
|
63
82
|
return runVersionCommand(argv, context);
|
|
64
83
|
}
|
|
65
84
|
process.stderr.write(renderCliError(unknownCommand(command), { helpText: getCliHelpText(process.stderr) }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/completion.ts"],"names":[],"mappings":"AAiBA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/completion.ts"],"names":[],"mappings":"AAiBA,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC1E;AAED,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAShG"}
|
|
@@ -4,13 +4,17 @@ import { invalidCompletionRequest, renderCliError, toCliError, unknownCompletion
|
|
|
4
4
|
import { formatHelpText } from "../help-text.js";
|
|
5
5
|
import { parseArgs } from "../parse-args.js";
|
|
6
6
|
export async function runCompletionCommand(argv) {
|
|
7
|
-
if (argv.length === 0
|
|
7
|
+
if (argv.length === 0) {
|
|
8
8
|
process.stdout.write(getCompletionCommandHelpText());
|
|
9
9
|
return 0;
|
|
10
10
|
}
|
|
11
11
|
if (argv[0] === '--') {
|
|
12
12
|
return runCompletionPlumbing(argv.slice(1));
|
|
13
13
|
}
|
|
14
|
+
if (argv.includes('-h') || argv.includes('--help')) {
|
|
15
|
+
process.stdout.write(getCompletionCommandHelpText());
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
14
18
|
let [shell, ...rest] = argv;
|
|
15
19
|
try {
|
|
16
20
|
parseArgs(rest, {}, { maxPositionals: 0 });
|
|
@@ -10,9 +10,9 @@ import { formatHelpText } from "../help-text.js";
|
|
|
10
10
|
import { parseArgs } from "../parse-args.js";
|
|
11
11
|
import { createCommandReporter, createStepProgressReporter, } from "../reporter.js";
|
|
12
12
|
const DOCTOR_SUITE_LABELS = {
|
|
13
|
-
|
|
14
|
-
complete: '
|
|
15
|
-
running: 'Checking
|
|
13
|
+
actions: {
|
|
14
|
+
complete: 'actions',
|
|
15
|
+
running: 'Checking actions',
|
|
16
16
|
},
|
|
17
17
|
environment: {
|
|
18
18
|
complete: 'environment',
|
|
@@ -78,7 +78,7 @@ export function getDoctorCommandHelpText(target = process.stdout) {
|
|
|
78
78
|
description: 'Exit with status 1 when warning-level findings are present',
|
|
79
79
|
label: '--strict',
|
|
80
80
|
},
|
|
81
|
-
{ description: 'Apply low-risk project and
|
|
81
|
+
{ description: 'Apply low-risk project and action fixes', label: '--fix' },
|
|
82
82
|
],
|
|
83
83
|
usage: ['remix doctor [--json] [--strict] [--fix] [--no-color]'],
|
|
84
84
|
}, target);
|
|
@@ -132,13 +132,13 @@ async function collectDoctorReport(progress, options, reporter, context) {
|
|
|
132
132
|
progress?.writeSummaryGap();
|
|
133
133
|
if (hasWarningFindings(environment.suite.findings)) {
|
|
134
134
|
let projectSuite = createSkippedDoctorSuite('project', 'Blocked by environment warnings.');
|
|
135
|
-
let
|
|
136
|
-
suites.push(projectSuite,
|
|
135
|
+
let actionsSuite = createSkippedDoctorSuite('actions', 'Blocked by environment warnings.');
|
|
136
|
+
suites.push(projectSuite, actionsSuite);
|
|
137
137
|
progress?.skip(projectSuite.name, projectSuite.reason);
|
|
138
138
|
writeDoctorSuiteDetails(reporter, projectSuite);
|
|
139
139
|
progress?.writeSummaryGap();
|
|
140
|
-
progress?.skip(
|
|
141
|
-
writeDoctorSuiteDetails(reporter,
|
|
140
|
+
progress?.skip(actionsSuite.name, actionsSuite.reason);
|
|
141
|
+
writeDoctorSuiteDetails(reporter, actionsSuite);
|
|
142
142
|
progress?.writeSummaryGap();
|
|
143
143
|
return {
|
|
144
144
|
appRoot: environment.projectRoot,
|
|
@@ -181,10 +181,10 @@ async function collectDoctorReport(progress, options, reporter, context) {
|
|
|
181
181
|
writeDoctorSuiteDetails(reporter, project.suite);
|
|
182
182
|
progress?.writeSummaryGap();
|
|
183
183
|
if (hasWarningFindings(project.suite.findings)) {
|
|
184
|
-
let
|
|
185
|
-
suites.push(
|
|
186
|
-
progress?.skip(
|
|
187
|
-
writeDoctorSuiteDetails(reporter,
|
|
184
|
+
let actionsSuite = createSkippedDoctorSuite('actions', 'Blocked by project warnings.');
|
|
185
|
+
suites.push(actionsSuite);
|
|
186
|
+
progress?.skip(actionsSuite.name, actionsSuite.reason);
|
|
187
|
+
writeDoctorSuiteDetails(reporter, actionsSuite);
|
|
188
188
|
progress?.writeSummaryGap();
|
|
189
189
|
return {
|
|
190
190
|
appRoot: environment.projectRoot,
|
|
@@ -195,7 +195,7 @@ async function collectDoctorReport(progress, options, reporter, context) {
|
|
|
195
195
|
suites,
|
|
196
196
|
};
|
|
197
197
|
}
|
|
198
|
-
let
|
|
198
|
+
let actions = await runDoctorSuite(progress, 'actions', async () => {
|
|
199
199
|
let controllerResult = await checkControllerConventions(project.routeManifest.appRoot, project.routeManifest.tree);
|
|
200
200
|
let remainingFindings = controllerResult.suite.findings;
|
|
201
201
|
let suiteAppliedFixes = [];
|
|
@@ -204,16 +204,16 @@ async function collectDoctorReport(progress, options, reporter, context) {
|
|
|
204
204
|
let finalControllerResult = await checkControllerConventions(project.routeManifest.appRoot, project.routeManifest.tree);
|
|
205
205
|
remainingFindings = finalControllerResult.suite.findings;
|
|
206
206
|
}
|
|
207
|
-
let suite = createDoctorSuite('
|
|
207
|
+
let suite = createDoctorSuite('actions', remainingFindings);
|
|
208
208
|
if (suiteAppliedFixes.length > 0) {
|
|
209
209
|
suite.appliedFixes = suiteAppliedFixes;
|
|
210
210
|
}
|
|
211
211
|
return { appliedFixes: suiteAppliedFixes, suite };
|
|
212
212
|
});
|
|
213
|
-
findings.push(...
|
|
214
|
-
appliedFixes.push(...(
|
|
215
|
-
suites.push(
|
|
216
|
-
writeDoctorSuiteDetails(reporter,
|
|
213
|
+
findings.push(...actions.suite.findings);
|
|
214
|
+
appliedFixes.push(...(actions.appliedFixes ?? []));
|
|
215
|
+
suites.push(actions.suite);
|
|
216
|
+
writeDoctorSuiteDetails(reporter, actions.suite);
|
|
217
217
|
progress?.writeSummaryGap();
|
|
218
218
|
let report = {
|
|
219
219
|
appRoot: environment.projectRoot,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/help.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"help.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/help.ts"],"names":[],"mappings":"AAKA,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAepE;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAiClF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAiB1F"}
|
|
@@ -1,20 +1,13 @@
|
|
|
1
1
|
import * as process from 'node:process';
|
|
2
|
-
import { getCompletionCommandHelpText } from "./completion.js";
|
|
3
2
|
import { renderCliError, toCliError, unknownHelpTopic } from "../errors.js";
|
|
4
3
|
import { formatHelpText } from "../help-text.js";
|
|
5
|
-
import { getDoctorCommandHelpText } from "./doctor.js";
|
|
6
|
-
import { getNewCommandHelpText } from "./new.js";
|
|
7
|
-
import { getRoutesCommandHelpText } from "./routes.js";
|
|
8
|
-
import { getSkillsCommandHelpText, getSkillsInstallCommandHelpText, getSkillsListCommandHelpText, } from "./skills.js";
|
|
9
|
-
import { getTestCommandHelpText } from "./test.js";
|
|
10
|
-
import { getVersionCommandHelpText } from "./version.js";
|
|
11
4
|
export async function runHelpCommand(argv) {
|
|
12
5
|
if (argv.includes('-h') || argv.includes('--help')) {
|
|
13
6
|
process.stdout.write(getHelpCommandHelpText());
|
|
14
7
|
return 0;
|
|
15
8
|
}
|
|
16
9
|
try {
|
|
17
|
-
process.stdout.write(getCommandHelpText(argv));
|
|
10
|
+
process.stdout.write(await getCommandHelpText(argv));
|
|
18
11
|
return 0;
|
|
19
12
|
}
|
|
20
13
|
catch (error) {
|
|
@@ -30,7 +23,6 @@ export function getCliHelpText(target = process.stdout) {
|
|
|
30
23
|
{ description: 'Create a new Remix project', label: 'new <name>' },
|
|
31
24
|
{ description: 'Check project health for the current project', label: 'doctor' },
|
|
32
25
|
{ description: 'Show the route tree for the current project', label: 'routes' },
|
|
33
|
-
{ description: 'Manage Remix skills for the current project', label: 'skills' },
|
|
34
26
|
{ description: 'Run tests for the current project', label: 'test [glob]' },
|
|
35
27
|
{ description: 'Show the current Remix version', label: 'version' },
|
|
36
28
|
],
|
|
@@ -39,12 +31,10 @@ export function getCliHelpText(target = process.stdout) {
|
|
|
39
31
|
'remix help',
|
|
40
32
|
'remix help completion',
|
|
41
33
|
'remix help doctor',
|
|
42
|
-
'remix help skills install',
|
|
43
34
|
'remix doctor',
|
|
44
35
|
'remix new my-remix-app',
|
|
45
36
|
'remix new my-remix-app --app-name "My Remix App"',
|
|
46
37
|
'remix routes',
|
|
47
|
-
'remix skills install',
|
|
48
38
|
'remix test',
|
|
49
39
|
'remix version',
|
|
50
40
|
],
|
|
@@ -65,14 +55,13 @@ export function getHelpCommandHelpText(target = process.stdout) {
|
|
|
65
55
|
'remix help doctor',
|
|
66
56
|
'remix help new',
|
|
67
57
|
'remix help routes',
|
|
68
|
-
'remix help skills install',
|
|
69
58
|
'remix help test',
|
|
70
59
|
'remix help version',
|
|
71
60
|
],
|
|
72
61
|
usage: ['remix help [command]'],
|
|
73
62
|
}, target);
|
|
74
63
|
}
|
|
75
|
-
function getCommandHelpText(argv) {
|
|
64
|
+
async function getCommandHelpText(argv) {
|
|
76
65
|
if (argv.length === 0) {
|
|
77
66
|
return getCliHelpText();
|
|
78
67
|
}
|
|
@@ -81,24 +70,27 @@ function getCommandHelpText(argv) {
|
|
|
81
70
|
return rest.length === 0 ? getHelpCommandHelpText() : getNestedHelpText(command, rest);
|
|
82
71
|
}
|
|
83
72
|
if (command === 'new' && rest.length === 0) {
|
|
73
|
+
let { getNewCommandHelpText } = await import("./new.js");
|
|
84
74
|
return getNewCommandHelpText();
|
|
85
75
|
}
|
|
86
76
|
if (command === 'completion' && rest.length === 0) {
|
|
77
|
+
let { getCompletionCommandHelpText } = await import("./completion.js");
|
|
87
78
|
return getCompletionCommandHelpText();
|
|
88
79
|
}
|
|
89
80
|
if (command === 'doctor' && rest.length === 0) {
|
|
81
|
+
let { getDoctorCommandHelpText } = await import("./doctor.js");
|
|
90
82
|
return getDoctorCommandHelpText();
|
|
91
83
|
}
|
|
92
84
|
if (command === 'routes' && rest.length === 0) {
|
|
85
|
+
let { getRoutesCommandHelpText } = await import("./routes.js");
|
|
93
86
|
return getRoutesCommandHelpText();
|
|
94
87
|
}
|
|
95
|
-
if (command === 'skills') {
|
|
96
|
-
return getSkillsHelpText(rest);
|
|
97
|
-
}
|
|
98
88
|
if (command === 'test' && rest.length === 0) {
|
|
99
|
-
|
|
89
|
+
let { getTestCommandHelpText } = await import("./test.js");
|
|
90
|
+
return await getTestCommandHelpText();
|
|
100
91
|
}
|
|
101
92
|
if (command === 'version' && rest.length === 0) {
|
|
93
|
+
let { getVersionCommandHelpText } = await import("./version.js");
|
|
102
94
|
return getVersionCommandHelpText();
|
|
103
95
|
}
|
|
104
96
|
throw unknownHelpTopic(argv.join(' '));
|
|
@@ -106,19 +98,3 @@ function getCommandHelpText(argv) {
|
|
|
106
98
|
function getNestedHelpText(command, argv) {
|
|
107
99
|
throw unknownHelpTopic(`${command} ${argv.join(' ')}`);
|
|
108
100
|
}
|
|
109
|
-
function getSkillsHelpText(argv) {
|
|
110
|
-
if (argv.length === 0) {
|
|
111
|
-
return getSkillsCommandHelpText();
|
|
112
|
-
}
|
|
113
|
-
let [subcommand, ...rest] = argv;
|
|
114
|
-
if (rest.length > 0) {
|
|
115
|
-
throw unknownHelpTopic(`skills ${argv.join(' ')}`);
|
|
116
|
-
}
|
|
117
|
-
if (subcommand === 'install') {
|
|
118
|
-
return getSkillsInstallCommandHelpText();
|
|
119
|
-
}
|
|
120
|
-
if (subcommand === 'list') {
|
|
121
|
-
return getSkillsListCommandHelpText();
|
|
122
|
-
}
|
|
123
|
-
throw unknownHelpTopic(`skills ${argv.join(' ')}`);
|
|
124
|
-
}
|
|
@@ -5,7 +5,7 @@ import { parseArgs } from "../parse-args.js";
|
|
|
5
5
|
import { createCommandReporter } from "../reporter.js";
|
|
6
6
|
import { loadRouteMap } from "../route-map.js";
|
|
7
7
|
import { lightRed } from "../terminal.js";
|
|
8
|
-
const
|
|
8
|
+
const ACTIONS_PATH_PREFIX = 'app/actions/';
|
|
9
9
|
export async function runRoutesCommand(argv, context) {
|
|
10
10
|
if (argv.includes('-h') || argv.includes('--help')) {
|
|
11
11
|
process.stdout.write(getRoutesCommandHelpText());
|
|
@@ -154,8 +154,8 @@ function colorRouteLine(line, node) {
|
|
|
154
154
|
return node.owner.exists ? line : lightRed(line);
|
|
155
155
|
}
|
|
156
156
|
function getCompactOwnerPath(ownerPath) {
|
|
157
|
-
if (ownerPath.startsWith(
|
|
158
|
-
return ownerPath.slice(
|
|
157
|
+
if (ownerPath.startsWith(ACTIONS_PATH_PREFIX)) {
|
|
158
|
+
return ownerPath.slice(ACTIONS_PATH_PREFIX.length);
|
|
159
159
|
}
|
|
160
160
|
return ownerPath;
|
|
161
161
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { CliContext } from '../cli-context.ts';
|
|
2
2
|
export declare function runTestCommand(argv: string[], context: CliContext): Promise<number>;
|
|
3
|
-
export declare function getTestCommandHelpText(target?: NodeJS.WriteStream): string
|
|
3
|
+
export declare function getTestCommandHelpText(target?: NodeJS.WriteStream): Promise<string>;
|
|
4
4
|
//# sourceMappingURL=test.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/test.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../../src/lib/commands/test.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAGnD,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBzF;AAED,wBAAsB,sBAAsB,CAC1C,MAAM,GAAE,MAAM,CAAC,WAA4B,GAC1C,OAAO,CAAC,MAAM,CAAC,CAGjB"}
|
|
@@ -1,19 +1,23 @@
|
|
|
1
|
-
import { getRemixTestHelpText, runRemixTest } from '@remix-run/test/cli';
|
|
2
1
|
import * as process from 'node:process';
|
|
3
2
|
import { renderCliError, toCliError } from "../errors.js";
|
|
4
3
|
export async function runTestCommand(argv, context) {
|
|
5
4
|
if (argv.includes('-h') || argv.includes('--help')) {
|
|
6
|
-
process.stdout.write(`${getTestCommandHelpText()}\n`);
|
|
5
|
+
process.stdout.write(`${await getTestCommandHelpText()}\n`);
|
|
7
6
|
return 0;
|
|
8
7
|
}
|
|
9
8
|
try {
|
|
9
|
+
let { runRemixTest } = await import('@remix-run/test/cli');
|
|
10
10
|
return await runRemixTest({ argv, cwd: context.cwd });
|
|
11
11
|
}
|
|
12
12
|
catch (error) {
|
|
13
|
-
|
|
13
|
+
let helpText = await getTestCommandHelpText(process.stderr);
|
|
14
|
+
process.stderr.write(renderCliError(toCliError(error), {
|
|
15
|
+
helpText,
|
|
16
|
+
}));
|
|
14
17
|
return 1;
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
|
-
export function getTestCommandHelpText(target = process.stdout) {
|
|
20
|
+
export async function getTestCommandHelpText(target = process.stdout) {
|
|
21
|
+
let { getRemixTestHelpText } = await import('@remix-run/test/cli');
|
|
18
22
|
return getRemixTestHelpText(target);
|
|
19
23
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,QAAA,MAAM,iBAAiB,0BAA2B,CAAA;
|
|
1
|
+
{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/lib/completion.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,QAAQ,CAAA;IACjC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,QAAA,MAAM,iBAAiB,0BAA2B,CAAA;AAIlD,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEhE,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,eAAe,CAEzE;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,YAAY,EAAE,MAAM,GAAG,gBAAgB,CAM3F;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,gBAAgB,GAAG,MAAM,CAQvE;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CA4E5C"}
|