@remix-run/cli 0.3.4 → 0.4.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 +105 -1
- package/dist/index.js +1 -1
- package/dist/lib/app-root.d.ts +11 -0
- package/dist/lib/app-root.d.ts.map +1 -0
- package/dist/lib/app-root.js +38 -0
- package/dist/lib/bootstrap-project.js +2 -2
- package/dist/lib/cli-context.d.ts +6 -0
- package/dist/lib/cli-context.d.ts.map +1 -1
- package/dist/lib/cli-context.js +12 -1
- package/dist/lib/cli.d.ts +3 -2
- package/dist/lib/cli.d.ts.map +1 -1
- package/dist/lib/cli.js +42 -14
- package/dist/lib/commands/completion.js +4 -4
- package/dist/lib/commands/db.d.ts +4 -0
- package/dist/lib/commands/db.d.ts.map +1 -0
- package/dist/lib/commands/db.js +283 -0
- package/dist/lib/commands/doctor.d.ts +5 -0
- package/dist/lib/commands/doctor.d.ts.map +1 -1
- package/dist/lib/commands/doctor.js +26 -251
- package/dist/lib/commands/help.d.ts.map +1 -1
- package/dist/lib/commands/help.js +17 -9
- package/dist/lib/commands/new.js +6 -6
- package/dist/lib/commands/routes.js +6 -6
- package/dist/lib/commands/test.d.ts +20 -1
- package/dist/lib/commands/test.d.ts.map +1 -1
- package/dist/lib/commands/test.js +353 -10
- package/dist/lib/commands/version.js +3 -3
- package/dist/lib/completion.d.ts +1 -1
- package/dist/lib/completion.d.ts.map +1 -1
- package/dist/lib/completion.js +229 -6
- package/dist/lib/controller-files.d.ts +0 -8
- package/dist/lib/controller-files.d.ts.map +1 -1
- package/dist/lib/controller-files.js +0 -23
- package/dist/lib/controller-ownership.d.ts +4 -12
- package/dist/lib/controller-ownership.d.ts.map +1 -1
- package/dist/lib/controller-ownership.js +31 -127
- package/dist/lib/database-command.d.ts +20 -0
- package/dist/lib/database-command.d.ts.map +1 -0
- package/dist/lib/database-command.js +7 -0
- package/dist/lib/doctor/controller-findings.d.ts +2 -2
- package/dist/lib/doctor/controller-findings.d.ts.map +1 -1
- package/dist/lib/doctor/controller-findings.js +23 -39
- package/dist/lib/doctor/controllers.d.ts +1 -2
- package/dist/lib/doctor/controllers.d.ts.map +1 -1
- package/dist/lib/doctor/controllers.js +4 -7
- package/dist/lib/doctor/environment.js +2 -2
- package/dist/lib/doctor/fixes.js +1 -1
- package/dist/lib/doctor/project.d.ts.map +1 -1
- package/dist/lib/doctor/project.js +3 -212
- package/dist/lib/doctor/run.d.ts +9 -0
- package/dist/lib/doctor/run.d.ts.map +1 -0
- package/dist/lib/doctor/run.js +237 -0
- package/dist/lib/doctor/types.d.ts +2 -1
- package/dist/lib/doctor/types.d.ts.map +1 -1
- package/dist/lib/doctor/types.js +4 -1
- package/dist/lib/errors.d.ts +30 -0
- package/dist/lib/errors.d.ts.map +1 -1
- package/dist/lib/errors.js +55 -0
- package/dist/lib/help-text.js +1 -1
- package/dist/lib/parse-args.d.ts.map +1 -1
- package/dist/lib/parse-args.js +17 -4
- package/dist/lib/remix-config.d.ts +75 -0
- package/dist/lib/remix-config.d.ts.map +1 -0
- package/dist/lib/remix-config.js +411 -0
- package/dist/lib/reporter.js +1 -1
- package/dist/lib/route-map.js +13 -33
- package/package.json +13 -7
- package/schema/remix.json +242 -0
- package/src/lib/app-root.ts +46 -0
- package/src/lib/cli-context.ts +17 -0
- package/src/lib/cli.ts +41 -6
- package/src/lib/commands/db.ts +377 -0
- package/src/lib/commands/doctor.ts +27 -329
- package/src/lib/commands/help.ts +10 -1
- package/src/lib/commands/test.ts +453 -12
- package/src/lib/completion.ts +321 -6
- package/src/lib/controller-files.ts +0 -38
- package/src/lib/controller-ownership.ts +50 -203
- package/src/lib/database-command.ts +31 -0
- package/src/lib/doctor/controller-findings.ts +30 -47
- package/src/lib/doctor/controllers.ts +2 -6
- package/src/lib/doctor/project.ts +0 -236
- package/src/lib/doctor/run.ts +311 -0
- package/src/lib/doctor/types.ts +6 -5
- package/src/lib/errors.ts +65 -0
- package/src/lib/parse-args.ts +19 -3
- package/src/lib/remix-config.ts +639 -0
- package/src/lib/route-map.ts +11 -48
- package/template/.agents/skills/remix/SKILL.md +38 -27
- package/template/.agents/skills/remix/references/assets-and-browser-modules.md +53 -10
- package/template/.agents/skills/remix/references/auth-and-sessions.md +5 -5
- package/template/.agents/skills/remix/references/data-and-validation.md +15 -15
- package/template/.agents/skills/remix/references/hydration-frames-navigation.md +54 -8
- package/template/.agents/skills/remix/references/middleware-and-server.md +68 -6
- package/template/.agents/skills/remix/references/mixins-styling-events.md +2 -0
- package/template/.agents/skills/remix/references/routing-and-controllers.md +8 -8
- package/template/.agents/skills/remix/references/testing-patterns.md +19 -18
- package/template/AGENTS.md +6 -3
- package/template/README.md +6 -3
- package/template/app/actions/controller.tsx +1 -1
- package/template/app/{ui → actions}/document.tsx +7 -5
- package/template/app/{ui/scaffold-home-page.tsx → actions/home-page.tsx} +1 -2
- package/template/app/actions/public/entry.ts +48 -0
- package/template/app/{assets → actions/public}/prompt-button.tsx +29 -25
- package/template/app/assets.ts +15 -2
- package/template/hmr.ts +46 -0
- package/template/package.json +1 -0
- package/template/server.ts +8 -1
- package/template/tsconfig.json +1 -1
- package/dist/lib/doctor/controller-fix-plans.d.ts +0 -4
- package/dist/lib/doctor/controller-fix-plans.d.ts.map +0 -1
- package/dist/lib/doctor/controller-fix-plans.js +0 -119
- package/dist/lib/doctor/controller-placeholders.d.ts +0 -3
- package/dist/lib/doctor/controller-placeholders.d.ts.map +0 -1
- package/dist/lib/doctor/controller-placeholders.js +0 -52
- package/src/lib/doctor/controller-fix-plans.ts +0 -168
- package/src/lib/doctor/controller-placeholders.ts +0 -70
- package/template/app/assets/entry.ts +0 -17
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://remix.run/schemas/remix.json",
|
|
4
|
+
"title": "Remix CLI configuration",
|
|
5
|
+
"description": "Configuration for the Remix command-line interface.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"additionalProperties": false,
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "JSON Schema used by editors to validate this file."
|
|
12
|
+
},
|
|
13
|
+
"db": {
|
|
14
|
+
"$ref": "#/$defs/db"
|
|
15
|
+
},
|
|
16
|
+
"doctor": {
|
|
17
|
+
"$ref": "#/$defs/doctor"
|
|
18
|
+
},
|
|
19
|
+
"test": {
|
|
20
|
+
"$ref": "#/$defs/test"
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"$defs": {
|
|
24
|
+
"db": {
|
|
25
|
+
"type": "object",
|
|
26
|
+
"additionalProperties": false,
|
|
27
|
+
"required": ["adapter"],
|
|
28
|
+
"properties": {
|
|
29
|
+
"adapter": {
|
|
30
|
+
"oneOf": [
|
|
31
|
+
{ "$ref": "#/$defs/dbSqliteAdapter" },
|
|
32
|
+
{ "$ref": "#/$defs/dbPostgresAdapter" },
|
|
33
|
+
{ "$ref": "#/$defs/dbMysqlAdapter" }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
"migrations": {
|
|
37
|
+
"$ref": "#/$defs/dbMigrations"
|
|
38
|
+
},
|
|
39
|
+
"seed": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Path to a SQL seed file."
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"dbString": {
|
|
46
|
+
"oneOf": [
|
|
47
|
+
{ "type": "string" },
|
|
48
|
+
{
|
|
49
|
+
"type": "object",
|
|
50
|
+
"additionalProperties": false,
|
|
51
|
+
"required": ["env"],
|
|
52
|
+
"properties": {
|
|
53
|
+
"env": { "type": "string" },
|
|
54
|
+
"default": { "type": "string" }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
"dbSqliteAdapter": {
|
|
60
|
+
"type": "object",
|
|
61
|
+
"additionalProperties": false,
|
|
62
|
+
"required": ["type", "filename"],
|
|
63
|
+
"properties": {
|
|
64
|
+
"type": { "const": "sqlite" },
|
|
65
|
+
"filename": { "$ref": "#/$defs/dbString" },
|
|
66
|
+
"foreignKeys": { "type": "boolean" },
|
|
67
|
+
"busyTimeout": { "type": "number", "minimum": 0 }
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"dbPostgresAdapter": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"additionalProperties": false,
|
|
73
|
+
"required": ["type", "connectionString"],
|
|
74
|
+
"properties": {
|
|
75
|
+
"type": { "const": "postgres" },
|
|
76
|
+
"connectionString": { "$ref": "#/$defs/dbString" },
|
|
77
|
+
"maintenanceDatabase": { "type": "string" },
|
|
78
|
+
"template": { "type": "string" }
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
"dbMysqlAdapter": {
|
|
82
|
+
"type": "object",
|
|
83
|
+
"additionalProperties": false,
|
|
84
|
+
"required": ["type", "uri"],
|
|
85
|
+
"properties": {
|
|
86
|
+
"type": { "const": "mysql" },
|
|
87
|
+
"uri": { "$ref": "#/$defs/dbString" },
|
|
88
|
+
"characterSet": { "type": "string" },
|
|
89
|
+
"collation": { "type": "string" }
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"dbMigrations": {
|
|
93
|
+
"type": "object",
|
|
94
|
+
"additionalProperties": false,
|
|
95
|
+
"required": ["directory"],
|
|
96
|
+
"properties": {
|
|
97
|
+
"directory": { "type": "string" },
|
|
98
|
+
"journalTable": { "type": "string" }
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
"doctor": {
|
|
102
|
+
"type": "object",
|
|
103
|
+
"additionalProperties": false,
|
|
104
|
+
"properties": {
|
|
105
|
+
"strict": {
|
|
106
|
+
"type": "boolean",
|
|
107
|
+
"description": "Whether doctor exits with status 1 when warning-level findings are present."
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
"stringArray": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": {
|
|
114
|
+
"type": "string"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"test": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"additionalProperties": false,
|
|
120
|
+
"properties": {
|
|
121
|
+
"browserFiles": {
|
|
122
|
+
"$ref": "#/$defs/stringArray",
|
|
123
|
+
"description": "Glob patterns for browser test files."
|
|
124
|
+
},
|
|
125
|
+
"concurrency": {
|
|
126
|
+
"type": "integer",
|
|
127
|
+
"minimum": 1,
|
|
128
|
+
"description": "Maximum number of concurrent test workers."
|
|
129
|
+
},
|
|
130
|
+
"coverage": {
|
|
131
|
+
"$ref": "#/$defs/coverage"
|
|
132
|
+
},
|
|
133
|
+
"e2eFiles": {
|
|
134
|
+
"$ref": "#/$defs/stringArray",
|
|
135
|
+
"description": "Glob patterns for end-to-end test files."
|
|
136
|
+
},
|
|
137
|
+
"exclude": {
|
|
138
|
+
"$ref": "#/$defs/stringArray",
|
|
139
|
+
"description": "Glob patterns excluded from test discovery."
|
|
140
|
+
},
|
|
141
|
+
"files": {
|
|
142
|
+
"$ref": "#/$defs/stringArray",
|
|
143
|
+
"description": "Glob patterns for all test files."
|
|
144
|
+
},
|
|
145
|
+
"only": {
|
|
146
|
+
"$ref": "#/$defs/stringArray",
|
|
147
|
+
"description": "Regular expression patterns used to focus tests by full name."
|
|
148
|
+
},
|
|
149
|
+
"playwright": {
|
|
150
|
+
"$ref": "#/$defs/playwright"
|
|
151
|
+
},
|
|
152
|
+
"pool": {
|
|
153
|
+
"enum": ["forks", "threads"],
|
|
154
|
+
"description": "Worker pool used for server and end-to-end tests."
|
|
155
|
+
},
|
|
156
|
+
"quiet": {
|
|
157
|
+
"type": "boolean",
|
|
158
|
+
"description": "Whether skipped tests are omitted from reporter output."
|
|
159
|
+
},
|
|
160
|
+
"reporter": {
|
|
161
|
+
"enum": ["spec", "files", "tap", "dot"],
|
|
162
|
+
"description": "Reporter used for test output."
|
|
163
|
+
},
|
|
164
|
+
"setup": {
|
|
165
|
+
"type": "string",
|
|
166
|
+
"description": "Path to a module exporting globalSetup and/or globalTeardown."
|
|
167
|
+
},
|
|
168
|
+
"type": {
|
|
169
|
+
"type": "array",
|
|
170
|
+
"items": {
|
|
171
|
+
"enum": ["server", "browser", "e2e"]
|
|
172
|
+
},
|
|
173
|
+
"description": "Test types to run."
|
|
174
|
+
},
|
|
175
|
+
"watch": {
|
|
176
|
+
"type": "boolean",
|
|
177
|
+
"description": "Whether tests rerun when files change."
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"coverage": {
|
|
182
|
+
"type": "object",
|
|
183
|
+
"additionalProperties": false,
|
|
184
|
+
"properties": {
|
|
185
|
+
"branches": {
|
|
186
|
+
"type": "number",
|
|
187
|
+
"description": "Minimum branch coverage percentage."
|
|
188
|
+
},
|
|
189
|
+
"dir": {
|
|
190
|
+
"type": "string",
|
|
191
|
+
"description": "Directory where coverage reports are written."
|
|
192
|
+
},
|
|
193
|
+
"enabled": {
|
|
194
|
+
"type": "boolean",
|
|
195
|
+
"description": "Whether coverage is collected."
|
|
196
|
+
},
|
|
197
|
+
"exclude": {
|
|
198
|
+
"$ref": "#/$defs/stringArray",
|
|
199
|
+
"description": "Glob patterns excluded from coverage."
|
|
200
|
+
},
|
|
201
|
+
"functions": {
|
|
202
|
+
"type": "number",
|
|
203
|
+
"description": "Minimum function coverage percentage."
|
|
204
|
+
},
|
|
205
|
+
"include": {
|
|
206
|
+
"$ref": "#/$defs/stringArray",
|
|
207
|
+
"description": "Glob patterns included in coverage."
|
|
208
|
+
},
|
|
209
|
+
"lines": {
|
|
210
|
+
"type": "number",
|
|
211
|
+
"description": "Minimum line coverage percentage."
|
|
212
|
+
},
|
|
213
|
+
"statements": {
|
|
214
|
+
"type": "number",
|
|
215
|
+
"description": "Minimum statement coverage percentage."
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
"playwright": {
|
|
220
|
+
"type": "object",
|
|
221
|
+
"additionalProperties": false,
|
|
222
|
+
"properties": {
|
|
223
|
+
"configFile": {
|
|
224
|
+
"type": "string",
|
|
225
|
+
"description": "Path to a Playwright configuration file."
|
|
226
|
+
},
|
|
227
|
+
"echo": {
|
|
228
|
+
"type": "boolean",
|
|
229
|
+
"description": "Whether browser console output is echoed to stdout."
|
|
230
|
+
},
|
|
231
|
+
"open": {
|
|
232
|
+
"type": "boolean",
|
|
233
|
+
"description": "Whether the browser remains open after tests finish."
|
|
234
|
+
},
|
|
235
|
+
"projects": {
|
|
236
|
+
"$ref": "#/$defs/stringArray",
|
|
237
|
+
"description": "Playwright project names to run."
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises'
|
|
2
|
+
import * as path from 'node:path'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Walks up from `startDir` looking for the closest directory that contains
|
|
6
|
+
* `relativeFilePath`.
|
|
7
|
+
*
|
|
8
|
+
* @param startDir Directory the walk starts from.
|
|
9
|
+
* @param relativeFilePath Slash-separated app file path, for example `app/routes.ts`.
|
|
10
|
+
* @returns The closest ancestor directory that contains the file, or `null`
|
|
11
|
+
* when no ancestor contains it.
|
|
12
|
+
*/
|
|
13
|
+
export async function findAppRoot(
|
|
14
|
+
startDir: string,
|
|
15
|
+
relativeFilePath: string,
|
|
16
|
+
): Promise<string | null> {
|
|
17
|
+
let relativeSegments = relativeFilePath.split('/')
|
|
18
|
+
let currentDir = path.resolve(startDir)
|
|
19
|
+
|
|
20
|
+
while (true) {
|
|
21
|
+
if (await pathExists(path.join(currentDir, ...relativeSegments))) {
|
|
22
|
+
return currentDir
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
let parentDir = path.dirname(currentDir)
|
|
26
|
+
if (parentDir === currentDir) {
|
|
27
|
+
return null
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
currentDir = parentDir
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async function pathExists(filePath: string): Promise<boolean> {
|
|
35
|
+
try {
|
|
36
|
+
await fs.access(filePath)
|
|
37
|
+
return true
|
|
38
|
+
} catch (error) {
|
|
39
|
+
let nodeError = error as NodeJS.ErrnoException
|
|
40
|
+
if (nodeError.code === 'ENOENT') {
|
|
41
|
+
return false
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
throw error
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/lib/cli-context.ts
CHANGED
|
@@ -2,14 +2,20 @@ import * as path from 'node:path'
|
|
|
2
2
|
import * as process from 'node:process'
|
|
3
3
|
|
|
4
4
|
import { resolveDefaultRemixVersion } from './remix-version.ts'
|
|
5
|
+
import { loadRemixConfig, type RemixConfig } from './remix-config.ts'
|
|
5
6
|
|
|
6
7
|
interface ResolveCliContextOptions {
|
|
8
|
+
configPath?: string
|
|
7
9
|
cwd?: string
|
|
8
10
|
remixVersion?: string
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
export interface CliContext {
|
|
14
|
+
/** Explicit Remix configuration path selected by the caller. */
|
|
15
|
+
configPath?: string
|
|
12
16
|
cwd: string
|
|
17
|
+
/** Loads and validates the Remix config file, memoizing the result. */
|
|
18
|
+
loadConfig(): Promise<RemixConfig>
|
|
13
19
|
remixVersion?: string
|
|
14
20
|
}
|
|
15
21
|
|
|
@@ -19,8 +25,19 @@ export async function resolveCliContext(
|
|
|
19
25
|
let cwd = resolveCwd(options.cwd)
|
|
20
26
|
let remixVersion = normalizeRemixVersion(options.remixVersion)
|
|
21
27
|
|
|
28
|
+
let configPromise: Promise<RemixConfig> | undefined
|
|
29
|
+
let loadConfig = () => (configPromise ??= loadRemixConfig(cwd, options.configPath))
|
|
30
|
+
|
|
31
|
+
// Validate an explicitly selected config file up front so every command
|
|
32
|
+
// fails fast on a bad --config path. The default remix.json is loaded
|
|
33
|
+
// lazily by the commands that read it, so an invalid file doesn't break
|
|
34
|
+
// unrelated commands like help, version, or shell completion.
|
|
35
|
+
if (options.configPath !== undefined) await loadConfig()
|
|
36
|
+
|
|
22
37
|
return {
|
|
38
|
+
configPath: options.configPath,
|
|
23
39
|
cwd,
|
|
40
|
+
loadConfig,
|
|
24
41
|
remixVersion: remixVersion ?? (await resolveDefaultRemixVersion(cwd)),
|
|
25
42
|
}
|
|
26
43
|
}
|
package/src/lib/cli.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as process from 'node:process'
|
|
|
2
2
|
|
|
3
3
|
import { getCliHelpText, runHelpCommand } from './commands/help.ts'
|
|
4
4
|
import { resolveCliContext, type CliContext } from './cli-context.ts'
|
|
5
|
-
import { renderCliError, unknownCommand } from './errors.ts'
|
|
5
|
+
import { missingOptionValue, renderCliError, toCliError, unknownCommand } from './errors.ts'
|
|
6
6
|
import { configureColors, restoreTerminalFormatting } from './terminal.ts'
|
|
7
7
|
|
|
8
8
|
/**
|
|
@@ -23,8 +23,9 @@ export interface RunRemixOptions {
|
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
25
|
* Entry point for the `remix` CLI. Parses `argv`, dispatches to the matching
|
|
26
|
-
* subcommand (`new`, `doctor`, `routes`, `test`, `version`,
|
|
27
|
-
* `help`), and resolves with the exit code the process should
|
|
26
|
+
* subcommand (`new`, `db`, `doctor`, `routes`, `test`, `version`,
|
|
27
|
+
* `completion`, `help`), and resolves with the exit code the process should
|
|
28
|
+
* use.
|
|
28
29
|
*
|
|
29
30
|
* @param argv Argument vector to parse, excluding the node and script paths
|
|
30
31
|
* (default `process.argv.slice(2)`).
|
|
@@ -43,14 +44,13 @@ export async function runRemix(
|
|
|
43
44
|
argv: string[] = process.argv.slice(2),
|
|
44
45
|
options: RunRemixOptions = {},
|
|
45
46
|
): Promise<number> {
|
|
46
|
-
let context = await resolveCliContext(options)
|
|
47
|
-
|
|
48
47
|
try {
|
|
49
48
|
argv = stripLeadingSeparators(argv)
|
|
50
49
|
|
|
51
50
|
let globalOptions = extractGlobalOptions(argv)
|
|
52
51
|
argv = stripLeadingSeparators(globalOptions.argv)
|
|
53
52
|
configureColors({ disabled: globalOptions.noColor })
|
|
53
|
+
let context = await resolveCliContext({ ...options, configPath: globalOptions.configPath })
|
|
54
54
|
|
|
55
55
|
if (argv.length === 0) {
|
|
56
56
|
process.stdout.write(getCliHelpText())
|
|
@@ -65,6 +65,11 @@ export async function runRemix(
|
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
return await runCommand(command, rest, context)
|
|
68
|
+
} catch (error) {
|
|
69
|
+
process.stderr.write(
|
|
70
|
+
renderCliError(toCliError(error), { helpText: getCliHelpText(process.stderr) }),
|
|
71
|
+
)
|
|
72
|
+
return 1
|
|
68
73
|
} finally {
|
|
69
74
|
restoreTerminalFormatting()
|
|
70
75
|
}
|
|
@@ -103,6 +108,11 @@ async function runCommand(command: string, argv: string[], context: CliContext):
|
|
|
103
108
|
return runDoctorCommand(argv, context)
|
|
104
109
|
}
|
|
105
110
|
|
|
111
|
+
if (command === 'db') {
|
|
112
|
+
let { runDbCommand } = await import('./commands/db.ts')
|
|
113
|
+
return runDbCommand(argv, context)
|
|
114
|
+
}
|
|
115
|
+
|
|
106
116
|
if (command === 'routes') {
|
|
107
117
|
let { runRoutesCommand } = await import('./commands/routes.ts')
|
|
108
118
|
return runRoutesCommand(argv, context)
|
|
@@ -124,8 +134,13 @@ async function runCommand(command: string, argv: string[], context: CliContext):
|
|
|
124
134
|
return 1
|
|
125
135
|
}
|
|
126
136
|
|
|
127
|
-
function extractGlobalOptions(argv: string[]): {
|
|
137
|
+
function extractGlobalOptions(argv: string[]): {
|
|
138
|
+
argv: string[]
|
|
139
|
+
configPath?: string
|
|
140
|
+
noColor: boolean
|
|
141
|
+
} {
|
|
128
142
|
let filteredArgv: string[] = []
|
|
143
|
+
let configPath: string | undefined
|
|
129
144
|
let noColor = false
|
|
130
145
|
|
|
131
146
|
for (let index = 0; index < argv.length; index++) {
|
|
@@ -141,11 +156,31 @@ function extractGlobalOptions(argv: string[]): { argv: string[]; noColor: boolea
|
|
|
141
156
|
continue
|
|
142
157
|
}
|
|
143
158
|
|
|
159
|
+
if (arg === '--config') {
|
|
160
|
+
let value = argv[index + 1]
|
|
161
|
+
if (value == null || value.length === 0 || value.startsWith('-')) {
|
|
162
|
+
throw missingOptionValue('--config')
|
|
163
|
+
}
|
|
164
|
+
configPath = value
|
|
165
|
+
index++
|
|
166
|
+
continue
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (arg.startsWith('--config=')) {
|
|
170
|
+
let value = arg.slice('--config='.length)
|
|
171
|
+
if (value.length === 0) {
|
|
172
|
+
throw missingOptionValue('--config')
|
|
173
|
+
}
|
|
174
|
+
configPath = value
|
|
175
|
+
continue
|
|
176
|
+
}
|
|
177
|
+
|
|
144
178
|
filteredArgv.push(arg)
|
|
145
179
|
}
|
|
146
180
|
|
|
147
181
|
return {
|
|
148
182
|
argv: filteredArgv,
|
|
183
|
+
configPath,
|
|
149
184
|
noColor,
|
|
150
185
|
}
|
|
151
186
|
}
|