@contentrail/cli 0.2.2 → 0.2.4
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 +36 -28
- package/dist/cli.d.ts +5 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +238 -140
- package/dist/cli.js.map +1 -1
- package/dist/cloudflare/pages-client.d.ts +4 -0
- package/dist/cloudflare/pages-client.d.ts.map +1 -1
- package/dist/cloudflare/pages-client.js +15 -1
- package/dist/cloudflare/pages-client.js.map +1 -1
- package/dist/commands/configure.d.ts +17 -0
- package/dist/commands/configure.d.ts.map +1 -0
- package/dist/commands/configure.js +109 -0
- package/dist/commands/configure.js.map +1 -0
- package/dist/commands/connect.d.ts +3 -0
- package/dist/commands/connect.d.ts.map +1 -1
- package/dist/commands/connect.js +37 -8
- package/dist/commands/connect.js.map +1 -1
- package/dist/commands/init-next-admin.d.ts.map +1 -1
- package/dist/commands/init-next-admin.js +34 -0
- package/dist/commands/init-next-admin.js.map +1 -1
- package/dist/commands/init.d.ts +6 -0
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +141 -31
- package/dist/commands/init.js.map +1 -1
- package/dist/install/plan.d.ts +8 -0
- package/dist/install/plan.d.ts.map +1 -0
- package/dist/install/plan.js +29 -0
- package/dist/install/plan.js.map +1 -0
- package/dist/install/run.d.ts +5 -0
- package/dist/install/run.d.ts.map +1 -0
- package/dist/install/run.js +80 -0
- package/dist/install/run.js.map +1 -0
- package/dist/interactive/clack-host.d.ts +3 -0
- package/dist/interactive/clack-host.d.ts.map +1 -0
- package/dist/interactive/clack-host.js +47 -0
- package/dist/interactive/clack-host.js.map +1 -0
- package/dist/interactive/connect-wizard.d.ts +17 -0
- package/dist/interactive/connect-wizard.d.ts.map +1 -0
- package/dist/interactive/connect-wizard.js +41 -0
- package/dist/interactive/connect-wizard.js.map +1 -0
- package/dist/interactive/init-wizard.d.ts +12 -0
- package/dist/interactive/init-wizard.d.ts.map +1 -0
- package/dist/interactive/init-wizard.js +73 -0
- package/dist/interactive/init-wizard.js.map +1 -0
- package/dist/interactive/is-interactive.d.ts +9 -0
- package/dist/interactive/is-interactive.d.ts.map +1 -0
- package/dist/interactive/is-interactive.js +19 -0
- package/dist/interactive/is-interactive.js.map +1 -0
- package/dist/interactive/menu.d.ts +4 -0
- package/dist/interactive/menu.d.ts.map +1 -0
- package/dist/interactive/menu.js +55 -0
- package/dist/interactive/menu.js.map +1 -0
- package/dist/interactive/types.d.ts +34 -0
- package/dist/interactive/types.d.ts.map +1 -0
- package/dist/interactive/types.js +2 -0
- package/dist/interactive/types.js.map +1 -0
- package/package.json +5 -4
package/README.md
CHANGED
|
@@ -1,25 +1,31 @@
|
|
|
1
1
|
# `@contentrail/cli`
|
|
2
2
|
|
|
3
|
-
Node.js CLI for ContentRail local development (ADR 020).
|
|
3
|
+
Node.js CLI for ContentRail local development (ADR 020 / ADR 029).
|
|
4
4
|
|
|
5
5
|
Requires **Node.js ≥ 22**. Init works on any static site (`framework: "static"`).
|
|
6
6
|
Astro and Vite have extra helpers (Astro **7.3.8**, Vite **8.3.5**;
|
|
7
7
|
`@contentrail/astro` needs Node ≥ **22.12**).
|
|
8
8
|
|
|
9
|
-
## Install
|
|
10
|
-
|
|
11
|
-
### Monorepo
|
|
9
|
+
## Install (one package)
|
|
12
10
|
|
|
13
11
|
```sh
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
pnpm exec contentrail --help
|
|
12
|
+
npm i -D @contentrail/cli
|
|
13
|
+
npx contentrail
|
|
17
14
|
```
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
On a TTY, `contentrail` opens an interactive menu: Setup, Connect, Doctor,
|
|
17
|
+
Status, Deploy. Setup scaffolds files and can install the other `@contentrail/*`
|
|
18
|
+
packages for your framework. You still configure Git + Cloudflare (tokens stay
|
|
19
|
+
in env / the dashboard — never in `contentrail.config.json`).
|
|
20
|
+
|
|
21
|
+
Non-interactive / CI: pass commands and `-y` / `--yes`. Use `init --install` to
|
|
22
|
+
add packages without prompts.
|
|
23
|
+
|
|
24
|
+
### Monorepo
|
|
20
25
|
|
|
21
26
|
```sh
|
|
22
|
-
pnpm
|
|
27
|
+
pnpm install
|
|
28
|
+
pnpm --filter @contentrail/cli build
|
|
23
29
|
pnpm exec contentrail --help
|
|
24
30
|
```
|
|
25
31
|
|
|
@@ -28,18 +34,21 @@ schemas use Zod **`^4.6.7`** via `@contentrail/core`.
|
|
|
28
34
|
|
|
29
35
|
## Commands
|
|
30
36
|
|
|
31
|
-
| Command | Purpose
|
|
32
|
-
| --------------------------- |
|
|
33
|
-
| `contentrail
|
|
34
|
-
| `contentrail
|
|
35
|
-
| `contentrail
|
|
36
|
-
| `contentrail
|
|
37
|
-
| `contentrail
|
|
38
|
-
| `contentrail
|
|
39
|
-
| `contentrail
|
|
40
|
-
| `contentrail
|
|
41
|
-
| `contentrail
|
|
42
|
-
| `contentrail
|
|
37
|
+
| Command | Purpose |
|
|
38
|
+
| --------------------------- | --------------------------------------------------------------------------- |
|
|
39
|
+
| `contentrail` | Interactive control panel (TTY) |
|
|
40
|
+
| `contentrail init` | Scaffold config + optional `--install` of ContentRail packages |
|
|
41
|
+
| `contentrail validate` | Validate config + local JSON content |
|
|
42
|
+
| `contentrail build` | Validate, then run `package.json` build script |
|
|
43
|
+
| `contentrail doctor` | Diagnose setup (no secret values printed) |
|
|
44
|
+
| `contentrail status` | Summarize local readiness |
|
|
45
|
+
| `contentrail dev` | Run `package.json` `dev` |
|
|
46
|
+
| `contentrail import` | CSV → validated JSON for a registered collection |
|
|
47
|
+
| `contentrail publish` | POST local JSON to `publishApiUrl` (env token) |
|
|
48
|
+
| `contentrail connect` | GitHub origin + Cloudflare Pages project (interactive or `--confirm --yes`) |
|
|
49
|
+
| `contentrail deploy` | Build and deploy to Pages |
|
|
50
|
+
| `contentrail deploy status` | Pages deployment status (`CF_API_TOKEN`) |
|
|
51
|
+
| `contentrail pages setup` | Alias for connect |
|
|
43
52
|
|
|
44
53
|
`rollback` is API-only. `publish` never sends GitHub tokens (ADR 020). See `docs/CONFIGURATION.md`.
|
|
45
54
|
|
|
@@ -71,13 +80,12 @@ schemas use Zod **`^4.6.7`** via `@contentrail/core`.
|
|
|
71
80
|
|
|
72
81
|
## Typical workflow
|
|
73
82
|
|
|
74
|
-
1. Create an Astro, Vite,
|
|
75
|
-
2.
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
6. Framework `dev` / `contentrail build`
|
|
83
|
+
1. Create an Astro, Vite, Next.js, or static site.
|
|
84
|
+
2. `npm i -D @contentrail/cli` then `npx contentrail` → **Setup** (installs the rest).
|
|
85
|
+
3. Export `CF_API_TOKEN` (never commit it) → **Connect** for Pages.
|
|
86
|
+
4. Edit collections / JSON under `content/` (or use `/admin`).
|
|
87
|
+
5. `npx contentrail validate` / `doctor`
|
|
88
|
+
6. Framework `dev` / `contentrail build` / **Deploy**
|
|
81
89
|
7. For `/admin`, add `@contentrail/editor` + `preact@^10.26.0` (`docs/ADMIN.md`)
|
|
82
90
|
8. `contentrail doctor` when something fails
|
|
83
91
|
|
package/dist/cli.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { ExitCode } from "./exit-codes.js";
|
|
2
|
+
import type { InstallDepsFn, PromptHost } from "./interactive/types.js";
|
|
2
3
|
export interface RunCliOptions {
|
|
3
4
|
readonly cwd?: string;
|
|
4
5
|
readonly stdout?: NodeJS.WritableStream;
|
|
@@ -6,6 +7,10 @@ export interface RunCliOptions {
|
|
|
6
7
|
readonly env?: NodeJS.ProcessEnv;
|
|
7
8
|
readonly fetchImpl?: typeof fetch;
|
|
8
9
|
readonly gitRemoteUrl?: string;
|
|
10
|
+
/** Force interactive UI on/off (tests). Default: TTY + non-CI detection. */
|
|
11
|
+
readonly interactive?: boolean;
|
|
12
|
+
readonly prompts?: PromptHost;
|
|
13
|
+
readonly installDeps?: InstallDepsFn;
|
|
9
14
|
}
|
|
10
15
|
export declare function runCli(argv: readonly string[], options?: RunCliOptions): Promise<ExitCode>;
|
|
11
16
|
//# sourceMappingURL=cli.d.ts.map
|
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAcA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAI3C,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AA+IxE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACxC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;IACxC,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACjC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IAClC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC;IAC/B,QAAQ,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,CAAC;CACtC;AAED,wBAAsB,MAAM,CAC1B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,CAAC,EAAE,aAAa,GACtB,OAAO,CAAC,QAAQ,CAAC,CAyFnB"}
|
package/dist/cli.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { runBuild } from "./commands/build.js";
|
|
4
|
+
import { runConfigure } from "./commands/configure.js";
|
|
4
5
|
import { runConnect } from "./commands/connect.js";
|
|
5
6
|
import { runDeploy, runDeployStatus } from "./commands/deploy.js";
|
|
6
7
|
import { runDev } from "./commands/dev.js";
|
|
@@ -12,16 +13,25 @@ import { runStatus } from "./commands/status.js";
|
|
|
12
13
|
import { runValidate } from "./commands/validate.js";
|
|
13
14
|
import { loadProject } from "./config/load.js";
|
|
14
15
|
import { ExitCode } from "./exit-codes.js";
|
|
16
|
+
import { createClackPromptHost } from "./interactive/clack-host.js";
|
|
17
|
+
import { canUseInteractiveUi } from "./interactive/is-interactive.js";
|
|
18
|
+
import { runMainMenu } from "./interactive/menu.js";
|
|
19
|
+
import { createPackageInstallRunner } from "./install/run.js";
|
|
15
20
|
import { createLogger } from "./util/print.js";
|
|
16
21
|
import { findProjectRoot } from "./util/paths.js";
|
|
17
22
|
const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
|
|
18
|
-
const HELP = `ContentRail CLI —
|
|
23
|
+
const HELP = `ContentRail CLI — developer control panel for your static site
|
|
19
24
|
|
|
20
25
|
Usage:
|
|
26
|
+
contentrail Interactive menu (TTY)
|
|
21
27
|
contentrail <command> [options]
|
|
22
28
|
|
|
29
|
+
Install once:
|
|
30
|
+
npm i -D @contentrail/cli
|
|
31
|
+
npx contentrail
|
|
32
|
+
|
|
23
33
|
Commands:
|
|
24
|
-
init Add ContentRail
|
|
34
|
+
init Add ContentRail + optionally install packages for this site
|
|
25
35
|
validate Validate configuration and local JSON content
|
|
26
36
|
build Validate then run the project build script
|
|
27
37
|
doctor Diagnose common setup problems
|
|
@@ -30,6 +40,7 @@ Commands:
|
|
|
30
40
|
import Import a local CSV file into a registered collection
|
|
31
41
|
publish POST local JSON to the configured publish API (needs token)
|
|
32
42
|
connect Record GitHub origin + create/patch their Cloudflare Pages project
|
|
43
|
+
configure Push admin username/password + GitHub token to Pages secrets
|
|
33
44
|
deploy Build and deploy to their Cloudflare Pages project
|
|
34
45
|
deploy status Fetch Cloudflare Pages deployment status
|
|
35
46
|
pages setup Alias for connect
|
|
@@ -43,12 +54,13 @@ Global options:
|
|
|
43
54
|
init options:
|
|
44
55
|
--framework <astro|vite|next|static> Force framework (default: auto-detect)
|
|
45
56
|
--force Overwrite existing generated files
|
|
57
|
+
--install Install ContentRail packages with the project package manager
|
|
46
58
|
--no-editor Skip contentrail.editor.json
|
|
47
59
|
--no-functions Skip Pages Functions templates
|
|
48
|
-
-y, --yes Non-interactive; accept defaults
|
|
60
|
+
-y, --yes Non-interactive; accept defaults (skips prompts)
|
|
49
61
|
|
|
50
62
|
connect / deploy:
|
|
51
|
-
--confirm --yes Required to create or change Pages projects
|
|
63
|
+
--confirm --yes Required to create or change Pages projects (non-interactive)
|
|
52
64
|
--account-id --project Cloudflare account and Pages project name
|
|
53
65
|
--skip-build Deploy without running the site build
|
|
54
66
|
|
|
@@ -66,7 +78,7 @@ deploy status options:
|
|
|
66
78
|
--project <pages-project-name>
|
|
67
79
|
|
|
68
80
|
pages setup options:
|
|
69
|
-
--confirm Required before any Cloudflare mutation
|
|
81
|
+
--confirm Required before any Cloudflare mutation
|
|
70
82
|
-y, --yes Non-interactive confirmation
|
|
71
83
|
|
|
72
84
|
Exit codes:
|
|
@@ -78,13 +90,16 @@ Exit codes:
|
|
|
78
90
|
Notes:
|
|
79
91
|
rollback is not a CLI command. Use the authenticated Worker/Pages API.
|
|
80
92
|
CLI publish never sends GitHub tokens; it uses CONTENTRAIL_PUBLISH_TOKEN.
|
|
93
|
+
Secrets never go in contentrail.config.json.
|
|
81
94
|
`;
|
|
82
95
|
function printCommandHelp(command) {
|
|
83
96
|
switch (command) {
|
|
84
97
|
case "init":
|
|
85
|
-
return `Usage: contentrail init [--framework astro|vite|static] [--force] [--
|
|
98
|
+
return `Usage: contentrail init [--framework astro|vite|next|static] [--force] [--install] [--no-editor] [--no-functions] [--dry-run] [-y]
|
|
86
99
|
|
|
87
100
|
Creates contentrail.config.json, a sample collection module, and sample JSON.
|
|
101
|
+
With --install (or interactive Setup), installs the ContentRail packages this
|
|
102
|
+
site needs so you only add @contentrail/cli yourself.
|
|
88
103
|
Works on Next.js, React, vanilla, Astro, and Vite sites. Does not generate the public site.
|
|
89
104
|
Never overwrites existing files unless --force is set.`;
|
|
90
105
|
case "validate":
|
|
@@ -138,141 +153,205 @@ Prints the Cloudflare automation capability map. Does not mutate production.`;
|
|
|
138
153
|
export async function runCli(argv, options) {
|
|
139
154
|
const log = createLogger(options?.stdout, options?.stderr);
|
|
140
155
|
const baseCwd = options?.cwd ?? process.cwd();
|
|
156
|
+
const env = options?.env ?? process.env;
|
|
157
|
+
const prompts = options?.prompts ?? createClackPromptHost();
|
|
158
|
+
const installDeps = options?.installDeps ?? createPackageInstallRunner({ env });
|
|
141
159
|
try {
|
|
142
160
|
const { command, subcommand, flags, cwd } = parseArgv(argv, baseCwd);
|
|
161
|
+
const interactive = options?.interactive ??
|
|
162
|
+
(canUseInteractiveUi(env) && !flags.yes && !flags.help && !flags.version);
|
|
143
163
|
if (flags.version) {
|
|
144
164
|
log.info(VERSION);
|
|
145
165
|
return ExitCode.Success;
|
|
146
166
|
}
|
|
147
|
-
if (
|
|
148
|
-
log.info(command !== undefined
|
|
149
|
-
? printCommandHelp(command)
|
|
150
|
-
: HELP);
|
|
167
|
+
if (flags.help) {
|
|
168
|
+
log.info(command !== undefined ? printCommandHelp(command) : HELP);
|
|
151
169
|
return ExitCode.Success;
|
|
152
170
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
framework !== "static" &&
|
|
162
|
-
framework !== "next") {
|
|
163
|
-
log.error('--framework must be "astro", "vite", "next", or "static".');
|
|
164
|
-
return ExitCode.Usage;
|
|
165
|
-
}
|
|
166
|
-
return runInit({
|
|
167
|
-
projectRoot,
|
|
168
|
-
...(framework !== undefined ? { framework } : {}),
|
|
169
|
-
force: flags.force,
|
|
170
|
-
withEditor: flags.withEditor,
|
|
171
|
-
withFunctions: flags.withFunctions,
|
|
172
|
-
dryRun: flags.dryRun,
|
|
173
|
-
yes: flags.yes,
|
|
174
|
-
}, log);
|
|
171
|
+
if (command === "help") {
|
|
172
|
+
log.info(HELP);
|
|
173
|
+
return ExitCode.Success;
|
|
174
|
+
}
|
|
175
|
+
if (command === undefined) {
|
|
176
|
+
if (!interactive) {
|
|
177
|
+
log.info(HELP);
|
|
178
|
+
return ExitCode.Success;
|
|
175
179
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
return
|
|
180
|
+
const action = await runMainMenu(prompts, log);
|
|
181
|
+
if (action === "cancelled" || action === "exit") {
|
|
182
|
+
return ExitCode.Success;
|
|
179
183
|
}
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
return
|
|
184
|
+
if (action === "help") {
|
|
185
|
+
log.info(HELP);
|
|
186
|
+
return ExitCode.Success;
|
|
183
187
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
188
|
+
return await dispatchCommand(action, {
|
|
189
|
+
projectRoot: findProjectRoot(cwd),
|
|
190
|
+
flags: {
|
|
191
|
+
...flags,
|
|
192
|
+
yes: false,
|
|
193
|
+
},
|
|
194
|
+
env,
|
|
195
|
+
log,
|
|
196
|
+
interactive: true,
|
|
197
|
+
prompts,
|
|
198
|
+
installDeps,
|
|
199
|
+
...(options !== undefined ? { options } : {}),
|
|
200
|
+
});
|
|
201
|
+
}
|
|
202
|
+
const projectRoot = findProjectRoot(cwd);
|
|
203
|
+
return await dispatchCommand(command, {
|
|
204
|
+
projectRoot,
|
|
205
|
+
...(subcommand !== undefined ? { subcommand } : {}),
|
|
206
|
+
flags,
|
|
207
|
+
env,
|
|
208
|
+
log,
|
|
209
|
+
interactive: interactive && !flags.yes,
|
|
210
|
+
prompts,
|
|
211
|
+
installDeps,
|
|
212
|
+
...(options !== undefined ? { options } : {}),
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
catch (error) {
|
|
216
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
217
|
+
log.error(message);
|
|
218
|
+
if (/Unknown option|Unexpected argument|requires a directory|--framework requires/i.test(message)) {
|
|
219
|
+
return ExitCode.Usage;
|
|
220
|
+
}
|
|
221
|
+
if (/contentrail\.config\.json|Invalid contentrail|collections module|escapes the project/i.test(message)) {
|
|
222
|
+
return ExitCode.Config;
|
|
223
|
+
}
|
|
224
|
+
return ExitCode.Failure;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
async function dispatchCommand(command, ctx) {
|
|
228
|
+
const { projectRoot, subcommand, flags, env, log, interactive, prompts, installDeps, options, } = ctx;
|
|
229
|
+
switch (command) {
|
|
230
|
+
case "setup":
|
|
231
|
+
case "init": {
|
|
232
|
+
const framework = flags.framework;
|
|
233
|
+
if (framework !== undefined &&
|
|
234
|
+
framework !== "astro" &&
|
|
235
|
+
framework !== "vite" &&
|
|
236
|
+
framework !== "static" &&
|
|
237
|
+
framework !== "next") {
|
|
238
|
+
log.error('--framework must be "astro", "vite", "next", or "static".');
|
|
239
|
+
return ExitCode.Usage;
|
|
202
240
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
241
|
+
const useWizard = interactive && (command === "setup" || !flags.yes);
|
|
242
|
+
return runInit({
|
|
243
|
+
projectRoot,
|
|
244
|
+
...(framework !== undefined ? { framework } : {}),
|
|
245
|
+
force: flags.force,
|
|
246
|
+
...(useWizard && !flags.editorFlagSet
|
|
247
|
+
? {}
|
|
248
|
+
: { withEditor: flags.withEditor }),
|
|
249
|
+
...(useWizard && !flags.functionsFlagSet
|
|
250
|
+
? {}
|
|
251
|
+
: { withFunctions: flags.withFunctions }),
|
|
252
|
+
dryRun: flags.dryRun,
|
|
253
|
+
yes: flags.yes,
|
|
254
|
+
install: flags.install,
|
|
255
|
+
interactive: useWizard,
|
|
256
|
+
prompts,
|
|
257
|
+
installDeps,
|
|
258
|
+
}, log);
|
|
259
|
+
}
|
|
260
|
+
case "validate": {
|
|
261
|
+
const project = await loadProject(projectRoot);
|
|
262
|
+
return (await runValidate(project, log)).code;
|
|
263
|
+
}
|
|
264
|
+
case "build": {
|
|
265
|
+
const project = await loadProject(projectRoot);
|
|
266
|
+
return runBuild(project, log);
|
|
267
|
+
}
|
|
268
|
+
case "doctor":
|
|
269
|
+
return runDoctor(projectRoot, log);
|
|
270
|
+
case "status":
|
|
271
|
+
return runStatus(projectRoot, log);
|
|
272
|
+
case "dev":
|
|
273
|
+
return runDev(projectRoot, log);
|
|
274
|
+
case "import": {
|
|
275
|
+
if (flags.collection === undefined || flags.file === undefined) {
|
|
276
|
+
log.error("import requires --collection and --file.");
|
|
277
|
+
return ExitCode.Usage;
|
|
224
278
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
:
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
279
|
+
return runImport({
|
|
280
|
+
projectRoot,
|
|
281
|
+
collection: flags.collection,
|
|
282
|
+
file: flags.file,
|
|
283
|
+
dryRun: flags.dryRun,
|
|
284
|
+
force: flags.force,
|
|
285
|
+
}, log);
|
|
286
|
+
}
|
|
287
|
+
case "publish": {
|
|
288
|
+
if (flags.collection === undefined) {
|
|
289
|
+
log.error("publish requires --collection.");
|
|
290
|
+
return ExitCode.Usage;
|
|
291
|
+
}
|
|
292
|
+
return runPublish({
|
|
293
|
+
projectRoot,
|
|
294
|
+
collection: flags.collection,
|
|
295
|
+
dryRun: flags.dryRun,
|
|
296
|
+
env,
|
|
297
|
+
...(flags.expectedVersion !== undefined
|
|
298
|
+
? {
|
|
299
|
+
expectedVersion: flags.expectedVersion === "null"
|
|
300
|
+
? null
|
|
301
|
+
: flags.expectedVersion,
|
|
302
|
+
}
|
|
303
|
+
: {}),
|
|
304
|
+
...(options?.fetchImpl !== undefined
|
|
305
|
+
? { fetchImpl: options.fetchImpl }
|
|
306
|
+
: {}),
|
|
307
|
+
}, log);
|
|
308
|
+
}
|
|
309
|
+
case "configure": {
|
|
310
|
+
return runConfigure({
|
|
311
|
+
projectRoot,
|
|
312
|
+
dryRun: flags.dryRun,
|
|
313
|
+
yes: flags.yes,
|
|
314
|
+
interactive,
|
|
315
|
+
prompts,
|
|
316
|
+
env,
|
|
317
|
+
...(options?.fetchImpl !== undefined
|
|
318
|
+
? { fetchImpl: options.fetchImpl }
|
|
319
|
+
: {}),
|
|
320
|
+
}, log);
|
|
321
|
+
}
|
|
322
|
+
case "connect":
|
|
323
|
+
case "pages": {
|
|
324
|
+
if (command === "pages" && subcommand !== "setup") {
|
|
325
|
+
log.error("Use `contentrail pages setup` or `contentrail connect`.");
|
|
326
|
+
return ExitCode.Usage;
|
|
250
327
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
328
|
+
return runConnect({
|
|
329
|
+
projectRoot,
|
|
330
|
+
dryRun: flags.dryRun,
|
|
331
|
+
confirm: flags.confirm,
|
|
332
|
+
yes: flags.yes,
|
|
333
|
+
env,
|
|
334
|
+
interactive,
|
|
335
|
+
prompts,
|
|
336
|
+
...(flags.accountId !== undefined
|
|
337
|
+
? { accountId: flags.accountId }
|
|
338
|
+
: {}),
|
|
339
|
+
...(flags.project !== undefined
|
|
340
|
+
? { projectName: flags.project }
|
|
341
|
+
: {}),
|
|
342
|
+
...(options?.fetchImpl !== undefined
|
|
343
|
+
? { fetchImpl: options.fetchImpl }
|
|
344
|
+
: {}),
|
|
345
|
+
...(options?.gitRemoteUrl !== undefined
|
|
346
|
+
? { gitRemoteUrl: options.gitRemoteUrl }
|
|
347
|
+
: {}),
|
|
348
|
+
}, log);
|
|
349
|
+
}
|
|
350
|
+
case "deploy": {
|
|
351
|
+
if (subcommand === "status") {
|
|
352
|
+
return runDeployStatus({
|
|
272
353
|
projectRoot,
|
|
273
354
|
env,
|
|
274
|
-
skipBuild: flags.skipBuild,
|
|
275
|
-
dryRun: flags.dryRun,
|
|
276
355
|
...(flags.accountId !== undefined
|
|
277
356
|
? { accountId: flags.accountId }
|
|
278
357
|
: {}),
|
|
@@ -284,24 +363,32 @@ export async function runCli(argv, options) {
|
|
|
284
363
|
: {}),
|
|
285
364
|
}, log);
|
|
286
365
|
}
|
|
287
|
-
|
|
288
|
-
log.error(
|
|
289
|
-
return ExitCode.Usage;
|
|
290
|
-
default:
|
|
291
|
-
log.error(`Unknown command "${command}". Run contentrail --help.`);
|
|
366
|
+
if (subcommand !== undefined) {
|
|
367
|
+
log.error("Use `contentrail deploy` or `contentrail deploy status`.");
|
|
292
368
|
return ExitCode.Usage;
|
|
369
|
+
}
|
|
370
|
+
return runDeploy({
|
|
371
|
+
projectRoot,
|
|
372
|
+
env,
|
|
373
|
+
skipBuild: flags.skipBuild,
|
|
374
|
+
dryRun: flags.dryRun,
|
|
375
|
+
...(flags.accountId !== undefined
|
|
376
|
+
? { accountId: flags.accountId }
|
|
377
|
+
: {}),
|
|
378
|
+
...(flags.project !== undefined
|
|
379
|
+
? { projectName: flags.project }
|
|
380
|
+
: {}),
|
|
381
|
+
...(options?.fetchImpl !== undefined
|
|
382
|
+
? { fetchImpl: options.fetchImpl }
|
|
383
|
+
: {}),
|
|
384
|
+
}, log);
|
|
293
385
|
}
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
386
|
+
case "rollback":
|
|
387
|
+
log.error('Command "rollback" is not implemented in the CLI. Use the authenticated Worker or Pages API.');
|
|
388
|
+
return ExitCode.Usage;
|
|
389
|
+
default:
|
|
390
|
+
log.error(`Unknown command "${command}". Run contentrail --help.`);
|
|
299
391
|
return ExitCode.Usage;
|
|
300
|
-
}
|
|
301
|
-
if (/contentrail\.config\.json|Invalid contentrail|collections module|escapes the project/i.test(message)) {
|
|
302
|
-
return ExitCode.Config;
|
|
303
|
-
}
|
|
304
|
-
return ExitCode.Failure;
|
|
305
392
|
}
|
|
306
393
|
}
|
|
307
394
|
function parseArgv(argv, baseCwd) {
|
|
@@ -314,10 +401,13 @@ function parseArgv(argv, baseCwd) {
|
|
|
314
401
|
force: false,
|
|
315
402
|
withEditor: true,
|
|
316
403
|
withFunctions: true,
|
|
404
|
+
editorFlagSet: false,
|
|
405
|
+
functionsFlagSet: false,
|
|
317
406
|
yes: false,
|
|
318
407
|
dryRun: false,
|
|
319
408
|
confirm: false,
|
|
320
409
|
skipBuild: false,
|
|
410
|
+
install: false,
|
|
321
411
|
};
|
|
322
412
|
const take = (index, flag) => {
|
|
323
413
|
const value = argv[index];
|
|
@@ -340,20 +430,28 @@ function parseArgv(argv, baseCwd) {
|
|
|
340
430
|
flags.force = true;
|
|
341
431
|
continue;
|
|
342
432
|
}
|
|
433
|
+
if (arg === "--install") {
|
|
434
|
+
flags.install = true;
|
|
435
|
+
continue;
|
|
436
|
+
}
|
|
343
437
|
if (arg === "--with-editor") {
|
|
344
438
|
flags.withEditor = true;
|
|
439
|
+
flags.editorFlagSet = true;
|
|
345
440
|
continue;
|
|
346
441
|
}
|
|
347
442
|
if (arg === "--with-functions") {
|
|
348
443
|
flags.withFunctions = true;
|
|
444
|
+
flags.functionsFlagSet = true;
|
|
349
445
|
continue;
|
|
350
446
|
}
|
|
351
447
|
if (arg === "--no-editor") {
|
|
352
448
|
flags.withEditor = false;
|
|
449
|
+
flags.editorFlagSet = true;
|
|
353
450
|
continue;
|
|
354
451
|
}
|
|
355
452
|
if (arg === "--no-functions") {
|
|
356
453
|
flags.withFunctions = false;
|
|
454
|
+
flags.functionsFlagSet = true;
|
|
357
455
|
continue;
|
|
358
456
|
}
|
|
359
457
|
if (arg === "--skip-build") {
|