create-kide-app 0.4.0 → 0.6.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 (3) hide show
  1. package/README.md +7 -5
  2. package/index.js +56 -15
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -17,21 +17,23 @@ The CLI asks for:
17
17
 
18
18
  ## Non-interactive use
19
19
 
20
- Every prompt can be answered with a flag; supplied answers skip their prompts.
20
+ Every prompt can be answered with a flag; supplied answers skip their prompts. Without a terminal (CI, agents) every answer must be supplied — a missing one fails with the flags to pass, before anything is created.
21
21
 
22
22
  ```bash
23
23
  pnpm create kide-app my-app --starter=marketing --seed --mode=embedded --target=local --no-github --no-dev
24
+ pnpm create kide-app my-app --starter=blank --mode=package --target=cloudflare --cloudflare-setup --deploy --no-github
24
25
  ```
25
26
 
26
27
  | Flag | Values |
27
28
  | ---- | ------ |
28
29
  | `--starter=` | `blank` or a starter name from the template release |
29
- | `--seed` / `--no-seed` | Seed example content (local target only) |
30
+ | `--seed` / `--no-seed` | Seed example content (local target with a starter) |
30
31
  | `--mode=` | `package` or `embedded` |
31
32
  | `--target=` | `local` or `cloudflare` |
32
- | `--no-github` | Skip the GitHub repo prompt |
33
- | `--no-dev` | Skip the dev-server prompt |
34
- | `--no-cloudflare-setup` | Skip Cloudflare resource provisioning |
33
+ | `--cloudflare-setup` / `--no-cloudflare-setup` | Create the D1 database and R2 bucket and apply migrations (Cloudflare target) |
34
+ | `--deploy` / `--no-deploy` | Deploy after setup (Cloudflare target) |
35
+ | `--no-github` | Skip the GitHub repo prompt (skipped without a terminal) |
36
+ | `--no-dev` | Skip the dev-server prompt (skipped without a terminal) |
35
37
 
36
38
  The template repo can be overridden with the `KIDE_TEMPLATE_REPO` env var (forks, local testing).
37
39
 
package/index.js CHANGED
@@ -142,6 +142,8 @@ const resolveLatestTag = async () => {
142
142
  // --- CLI flags (non-interactive use: CI, agents, testing) ---
143
143
  // Any prompt whose answer is supplied by a flag is skipped. Example:
144
144
  // create-kide-app my-app --starter=marketing --seed --mode=embedded --target=local --no-github --no-dev
145
+ // Without a terminal (CI, agents) a required answer must come from a flag; a missing one
146
+ // fails with the flag to pass instead of stopping at a prompt nobody can answer.
145
147
 
146
148
  const parseArgs = (argv) => {
147
149
  const flags = {};
@@ -151,7 +153,10 @@ const parseArgs = (argv) => {
151
153
  else if (arg === "--no-seed") flags.seed = false;
152
154
  else if (arg === "--no-github") flags.noGithub = true;
153
155
  else if (arg === "--no-dev") flags.noDev = true;
154
- else if (arg === "--no-cloudflare-setup") flags.noCloudflareSetup = true;
156
+ else if (arg === "--cloudflare-setup") flags.cloudflareSetup = true;
157
+ else if (arg === "--no-cloudflare-setup") flags.cloudflareSetup = false;
158
+ else if (arg === "--deploy") flags.deploy = true;
159
+ else if (arg === "--no-deploy") flags.deploy = false;
155
160
  else if (arg.startsWith("--starter=")) flags.starter = arg.slice("--starter=".length);
156
161
  else if (arg.startsWith("--mode=")) flags.mode = arg.slice("--mode=".length);
157
162
  else if (arg.startsWith("--target=")) flags.target = arg.slice("--target=".length);
@@ -161,10 +166,30 @@ const parseArgs = (argv) => {
161
166
  return { flags, positional };
162
167
  };
163
168
 
169
+ const interactive = Boolean(process.stdin.isTTY && process.stdout.isTTY);
170
+
171
+ // Without a terminal, every answer that would otherwise be prompted for must come from a
172
+ // flag. Checked before cloning so a missing flag fails fast and leaves nothing behind.
173
+ const missingAnswers = (flags, positional) => {
174
+ const missing = [];
175
+ if (!positional[0]) missing.push("the project name as the first argument");
176
+ if (flags.starter === undefined) missing.push("--starter=<blank | starter name>");
177
+ if (flags.mode === undefined) missing.push("--mode=package | embedded");
178
+ if (flags.target === undefined) missing.push("--target=local | cloudflare");
179
+ if (flags.target === "local" && flags.starter && flags.starter !== "blank" && flags.seed === undefined) {
180
+ missing.push("--seed or --no-seed");
181
+ }
182
+ if (flags.target === "cloudflare") {
183
+ if (flags.cloudflareSetup === undefined) missing.push("--cloudflare-setup or --no-cloudflare-setup");
184
+ else if (flags.cloudflareSetup && flags.deploy === undefined) missing.push("--deploy or --no-deploy");
185
+ }
186
+ return missing;
187
+ };
188
+
164
189
  // --- Main ---
165
190
 
166
191
  async function main() {
167
- p.intro("🪐 Create Kide CMS Project");
192
+ p.intro("\x1b[34m▣\x1b[39m Create Kide CMS Project");
168
193
 
169
194
  const { flags, positional } = parseArgs(process.argv.slice(2));
170
195
  if (flags.unknown) {
@@ -180,6 +205,14 @@ async function main() {
180
205
  process.exit(1);
181
206
  }
182
207
 
208
+ if (!interactive) {
209
+ const missing = missingAnswers(flags, positional);
210
+ if (missing.length > 0) {
211
+ p.cancel(`No terminal to prompt. Pass:\n ${missing.join("\n ")}`);
212
+ process.exit(1);
213
+ }
214
+ }
215
+
183
216
  // 1. Project name
184
217
  const projectName =
185
218
  positional[0] ||
@@ -648,7 +681,8 @@ async function main() {
648
681
  // gh not installed or not authenticated — skip the prompt
649
682
  }
650
683
 
651
- if (ghAvailable && !flags.noGithub) {
684
+ // Creating a repo needs a name and visibility; without a terminal it is skipped.
685
+ if (ghAvailable && !flags.noGithub && interactive) {
652
686
  const createRepo = await p.confirm({
653
687
  message: "Create a GitHub repository for this project?",
654
688
  initialValue: false,
@@ -783,8 +817,8 @@ async function main() {
783
817
  };
784
818
  if (target === "cloudflare") {
785
819
  const setupNow =
786
- flags.noCloudflareSetup === true
787
- ? false
820
+ flags.cloudflareSetup !== undefined
821
+ ? flags.cloudflareSetup
788
822
  : await p.confirm({
789
823
  message:
790
824
  "Set up Cloudflare resources now? (creates D1 database and R2 bucket)",
@@ -819,13 +853,17 @@ async function main() {
819
853
  authenticated = true;
820
854
  } catch {
821
855
  p.note(
822
- "You need to log in to Cloudflare first.",
856
+ interactive
857
+ ? "You need to log in to Cloudflare first."
858
+ : "Not logged in to Cloudflare. Run `wrangler login` (or set CLOUDFLARE_API_TOKEN), then finish the setup steps listed below.",
823
859
  "Wrangler login required",
824
860
  );
825
- const doLogin = await p.confirm({
826
- message: "Open browser to log in?",
827
- initialValue: true,
828
- });
861
+ const doLogin = interactive
862
+ ? await p.confirm({
863
+ message: "Open browser to log in?",
864
+ initialValue: true,
865
+ })
866
+ : false;
829
867
  if (!p.isCancel(doLogin) && doLogin) {
830
868
  try {
831
869
  execSync(`${pm.exec} wrangler login`, {
@@ -952,10 +990,12 @@ async function main() {
952
990
 
953
991
  // Deploy to Cloudflare
954
992
  if (cf.migrationsApplied) {
955
- const doDeploy = await p.confirm({
956
- message: "Deploy to Cloudflare now?",
957
- initialValue: true,
958
- });
993
+ const doDeploy =
994
+ flags.deploy ??
995
+ (await p.confirm({
996
+ message: "Deploy to Cloudflare now?",
997
+ initialValue: true,
998
+ }));
959
999
  if (!p.isCancel(doDeploy) && doDeploy) {
960
1000
  s.start("Building and deploying to Cloudflare");
961
1001
  try {
@@ -983,7 +1023,8 @@ async function main() {
983
1023
  // --- Done ---
984
1024
 
985
1025
  if (target === "local") {
986
- const startDev = flags.noDev
1026
+ // Without a terminal the dev server would never return control; skip it.
1027
+ const startDev = flags.noDev || !interactive
987
1028
  ? false
988
1029
  : await p.confirm({
989
1030
  message: "Start the dev server now?",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-kide-app",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "Scaffold a new Kide CMS project",
5
5
  "author": "Matti Hernesniemi",
6
6
  "license": "MIT",