@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.
Files changed (110) hide show
  1. package/README.md +0 -3
  2. package/dist/lib/bootstrap-project.d.ts.map +1 -1
  3. package/dist/lib/bootstrap-project.js +32 -9
  4. package/dist/lib/cli.d.ts +29 -0
  5. package/dist/lib/cli.d.ts.map +1 -1
  6. package/dist/lib/cli.js +33 -14
  7. package/dist/lib/commands/completion.d.ts.map +1 -1
  8. package/dist/lib/commands/completion.js +5 -1
  9. package/dist/lib/commands/doctor.js +18 -18
  10. package/dist/lib/commands/help.d.ts.map +1 -1
  11. package/dist/lib/commands/help.js +9 -33
  12. package/dist/lib/commands/routes.js +3 -3
  13. package/dist/lib/commands/test.d.ts +1 -1
  14. package/dist/lib/commands/test.d.ts.map +1 -1
  15. package/dist/lib/commands/test.js +8 -4
  16. package/dist/lib/completion.d.ts.map +1 -1
  17. package/dist/lib/completion.js +4 -106
  18. package/dist/lib/controller-files.d.ts +0 -1
  19. package/dist/lib/controller-files.d.ts.map +1 -1
  20. package/dist/lib/controller-files.js +3 -5
  21. package/dist/lib/controller-ownership.d.ts +9 -9
  22. package/dist/lib/controller-ownership.d.ts.map +1 -1
  23. package/dist/lib/controller-ownership.js +56 -91
  24. package/dist/lib/doctor/controller-findings.d.ts +1 -1
  25. package/dist/lib/doctor/controller-findings.d.ts.map +1 -1
  26. package/dist/lib/doctor/controller-findings.js +15 -87
  27. package/dist/lib/doctor/controller-fix-plans.d.ts.map +1 -1
  28. package/dist/lib/doctor/controller-fix-plans.js +13 -24
  29. package/dist/lib/doctor/controller-placeholders.d.ts +2 -3
  30. package/dist/lib/doctor/controller-placeholders.d.ts.map +1 -1
  31. package/dist/lib/doctor/controller-placeholders.js +18 -149
  32. package/dist/lib/doctor/controllers.js +1 -1
  33. package/dist/lib/doctor/project.js +60 -52
  34. package/dist/lib/doctor/types.d.ts +2 -2
  35. package/dist/lib/doctor/types.d.ts.map +1 -1
  36. package/dist/lib/errors.d.ts +0 -6
  37. package/dist/lib/errors.d.ts.map +1 -1
  38. package/dist/lib/errors.js +0 -11
  39. package/dist/lib/load-route-map-worker.js +17 -9
  40. package/dist/lib/route-map.d.ts +1 -1
  41. package/dist/lib/route-map.d.ts.map +1 -1
  42. package/dist/lib/route-map.js +29 -17
  43. package/package.json +4 -5
  44. package/src/lib/bootstrap-project.ts +39 -13
  45. package/src/lib/cli.ts +46 -15
  46. package/src/lib/commands/completion.ts +6 -1
  47. package/src/lib/commands/doctor.ts +18 -21
  48. package/src/lib/commands/help.ts +9 -43
  49. package/src/lib/commands/routes.ts +3 -3
  50. package/src/lib/commands/test.ts +10 -4
  51. package/src/lib/completion.ts +4 -151
  52. package/src/lib/controller-files.ts +4 -8
  53. package/src/lib/controller-ownership.ts +78 -141
  54. package/src/lib/doctor/controller-findings.ts +20 -97
  55. package/src/lib/doctor/controller-fix-plans.ts +13 -29
  56. package/src/lib/doctor/controller-placeholders.ts +17 -189
  57. package/src/lib/doctor/controllers.ts +1 -1
  58. package/src/lib/doctor/project.ts +60 -52
  59. package/src/lib/doctor/types.ts +1 -5
  60. package/src/lib/errors.ts +0 -12
  61. package/src/lib/load-route-map-worker.ts +19 -10
  62. package/src/lib/route-map.ts +61 -16
  63. package/template/.agents/skills/remix/SKILL.md +588 -0
  64. package/template/.agents/skills/remix/references/animate-elements.md +195 -0
  65. package/template/.agents/skills/remix/references/assets-and-browser-modules.md +130 -0
  66. package/template/.agents/skills/remix/references/auth-and-sessions.md +443 -0
  67. package/template/.agents/skills/remix/references/component-model.md +282 -0
  68. package/template/.agents/skills/remix/references/create-mixins.md +158 -0
  69. package/template/.agents/skills/remix/references/data-and-validation.md +379 -0
  70. package/template/.agents/skills/remix/references/hydration-frames-navigation.md +297 -0
  71. package/template/.agents/skills/remix/references/middleware-and-server.md +233 -0
  72. package/template/.agents/skills/remix/references/mixins-styling-events.md +213 -0
  73. package/template/.agents/skills/remix/references/routing-and-controllers.md +391 -0
  74. package/template/.agents/skills/remix/references/testing-patterns.md +172 -0
  75. package/{bootstrap → template}/AGENTS.md +13 -8
  76. package/template/README.md +29 -0
  77. package/template/app/actions/controller.tsx +18 -0
  78. package/template/app/assets/entry.ts +8 -0
  79. package/template/app/assets/prompt-button.tsx +163 -0
  80. package/template/app/assets.ts +20 -0
  81. package/template/app/middleware/render.tsx +43 -0
  82. package/template/app/router.ts +20 -0
  83. package/template/app/routes.ts +6 -0
  84. package/template/app/ui/document.tsx +33 -0
  85. package/template/app/ui/scaffold-home-page.tsx +527 -0
  86. package/template/gitignore +4 -0
  87. package/{bootstrap → template}/package.json +5 -6
  88. package/template/public/favicon.svg +11 -0
  89. package/{bootstrap → template}/server.ts +4 -5
  90. package/{bootstrap → template}/tsconfig.json +3 -3
  91. package/bootstrap/README.md +0 -27
  92. package/bootstrap/app/controllers/auth.tsx +0 -21
  93. package/bootstrap/app/controllers/home.tsx +0 -26
  94. package/bootstrap/app/router.ts +0 -10
  95. package/bootstrap/app/routes.ts +0 -6
  96. package/bootstrap/app/ui/document.tsx +0 -21
  97. package/bootstrap/app/ui/layout.tsx +0 -22
  98. package/bootstrap/app/utils/render.tsx +0 -7
  99. package/dist/lib/commands/skills.d.ts +0 -6
  100. package/dist/lib/commands/skills.d.ts.map +0 -1
  101. package/dist/lib/commands/skills.js +0 -222
  102. package/dist/lib/skills-cache.d.ts +0 -19
  103. package/dist/lib/skills-cache.d.ts.map +0 -1
  104. package/dist/lib/skills-cache.js +0 -89
  105. package/dist/lib/skills.d.ts +0 -30
  106. package/dist/lib/skills.d.ts.map +0 -1
  107. package/dist/lib/skills.js +0 -441
  108. package/src/lib/commands/skills.ts +0 -306
  109. package/src/lib/skills-cache.ts +0 -140
  110. 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;AAO1E,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"}
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 BOOTSTRAP_DIRECTORY = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '../../bootstrap');
9
- const BOOTSTRAP_EXCLUDED_NAMES = new Set(['.gitkeep', 'node_modules']);
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', () => copyBootstrapDirectory({
25
- sourceDir: BOOTSTRAP_DIRECTORY,
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 copyBootstrapDirectory({ sourceDir, targetDir, templateValues, }) {
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 (BOOTSTRAP_EXCLUDED_NAMES.has(entry.name)) {
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 copyBootstrapDirectory({ sourceDir: sourcePath, targetDir: targetPath, templateValues });
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
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/lib/cli.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAsB,QAAQ,CAC5B,IAAI,GAAE,MAAM,EAA0B,EACtC,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CA4BjB"}
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
- while (argv[0] === '--') {
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,CA6B1E;AAED,wBAAgB,4BAA4B,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAShG"}
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 || argv[0] === '-h' || argv[0] === '--help') {
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
- controllers: {
14
- complete: 'controllers',
15
- running: 'Checking controllers',
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 controller fixes', label: '--fix' },
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 controllersSuite = createSkippedDoctorSuite('controllers', 'Blocked by environment warnings.');
136
- suites.push(projectSuite, controllersSuite);
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(controllersSuite.name, controllersSuite.reason);
141
- writeDoctorSuiteDetails(reporter, controllersSuite);
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 controllersSuite = createSkippedDoctorSuite('controllers', 'Blocked by project warnings.');
185
- suites.push(controllersSuite);
186
- progress?.skip(controllersSuite.name, controllersSuite.reason);
187
- writeDoctorSuiteDetails(reporter, controllersSuite);
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 controllers = await runDoctorSuite(progress, 'controllers', async () => {
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('controllers', remainingFindings);
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(...controllers.suite.findings);
214
- appliedFixes.push(...(controllers.appliedFixes ?? []));
215
- suites.push(controllers.suite);
216
- writeDoctorSuiteDetails(reporter, controllers.suite);
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":"AAgBA,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAepE;AAED,wBAAgB,cAAc,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAoClF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAkB1F"}
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
- return getTestCommandHelpText();
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 CONTROLLERS_PATH_PREFIX = 'app/controllers/';
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(CONTROLLERS_PATH_PREFIX)) {
158
- return ownerPath.slice(CONTROLLERS_PATH_PREFIX.length);
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":"AAGA,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,CAczF;AAED,wBAAgB,sBAAsB,CAAC,MAAM,GAAE,MAAM,CAAC,WAA4B,GAAG,MAAM,CAE1F"}
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
- process.stderr.write(renderCliError(toCliError(error), { helpText: getTestCommandHelpText(process.stderr) }));
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;AAuBlD,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"}
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"}