vela 0.15.5 → 0.15.6

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/dist/bin.js CHANGED
@@ -21,7 +21,7 @@ import pc46 from "picocolors";
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "vela",
24
- version: "0.15.5",
24
+ version: "0.15.6",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -73,7 +73,7 @@ var package_default = {
73
73
  pocketbase: "^0.28.0",
74
74
  "pocketbase-server": "^0.40.5-beta.5",
75
75
  stripe: "^22.6.2",
76
- sv: "~1.0.1",
76
+ sv: "~1.1.1",
77
77
  svelte: "^5.56.10",
78
78
  tar: "^7.5.22",
79
79
  tinyexec: "^1.3.0",
@@ -601,10 +601,10 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
601
601
  // src/commands/bless.ts
602
602
  import fs18 from "node:fs";
603
603
  import path16 from "node:path";
604
- import process8 from "node:process";
604
+ import process9 from "node:process";
605
605
  import * as v4 from "valibot";
606
606
  import { Command } from "commander";
607
- import * as p5 from "@clack/prompts";
607
+ import * as p6 from "@clack/prompts";
608
608
  import pc3 from "picocolors";
609
609
  import { resolveCommand as resolveCommand2 } from "package-manager-detector";
610
610
 
@@ -1533,9 +1533,122 @@ function quoteEnvValue(value) {
1533
1533
  }
1534
1534
 
1535
1535
  // src/lib/superuser.ts
1536
- import process7 from "node:process";
1536
+ import process8 from "node:process";
1537
1537
  import * as v3 from "valibot";
1538
+ import * as p4 from "@clack/prompts";
1539
+
1540
+ // src/lib/providers.ts
1541
+ import process7 from "node:process";
1538
1542
  import * as p3 from "@clack/prompts";
1543
+ import { bySlug } from "@velastack/patterns";
1544
+ function capabilityName(slug2) {
1545
+ return slug2.replace(/^enable-/, "");
1546
+ }
1547
+ function choices(providers) {
1548
+ return `--provider <${providers.map((provider) => provider.id).join("|")}>`;
1549
+ }
1550
+ function unknownProviderMessage(name, raw, providers) {
1551
+ return [
1552
+ `Unknown provider "${raw}" for ${name}.`,
1553
+ "",
1554
+ "Available providers:",
1555
+ ...providers.map((provider) => ` ${provider.id}`)
1556
+ ].join("\n");
1557
+ }
1558
+ function decideProvider(request) {
1559
+ const { patternName, providers, flagValue, interactive } = request;
1560
+ if (flagValue !== void 0) {
1561
+ const provider = providers.find((candidate) => candidate.id === flagValue);
1562
+ if (!provider) {
1563
+ return { kind: "error", message: unknownProviderMessage(patternName, flagValue, providers) };
1564
+ }
1565
+ return { kind: "use", provider };
1566
+ }
1567
+ if (interactive) return { kind: "prompt" };
1568
+ return {
1569
+ kind: "error",
1570
+ message: `Choose ${article(patternName)} ${patternName} provider: pass ${choices(providers)}. There is no terminal to ask on.`
1571
+ };
1572
+ }
1573
+ function article(word) {
1574
+ return /^[aeiou]/i.test(word) ? "an" : "a";
1575
+ }
1576
+ function isInteractive() {
1577
+ return Boolean(process7.stdout.isTTY) && !process7.env.CI;
1578
+ }
1579
+ function providerFlagInArgv(argv) {
1580
+ return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
1581
+ }
1582
+ function checkProviderInput(pattern, argv, input) {
1583
+ const providers = pattern.providers ?? [];
1584
+ if (providers.length > 0) {
1585
+ if (typeof input.provider !== "string" || input.provider.length === 0) {
1586
+ throw new Error(`${pattern.title} needs a provider. Pass ${choices(providers)}.`);
1587
+ }
1588
+ return;
1589
+ }
1590
+ if (providerFlagInArgv(argv)) {
1591
+ throw new Error(`${pattern.title} does not support --provider.`);
1592
+ }
1593
+ }
1594
+ async function resolveProvider(slug2, flagValue) {
1595
+ const pattern = bySlug[slug2];
1596
+ const providers = pattern.providers ?? [];
1597
+ if (providers.length === 0) {
1598
+ throw new Error(`${pattern.title} does not support --provider.`);
1599
+ }
1600
+ const patternName = capabilityName(slug2);
1601
+ const decision = decideProvider({
1602
+ patternName,
1603
+ providers,
1604
+ flagValue,
1605
+ interactive: isInteractive()
1606
+ });
1607
+ if (decision.kind === "error") throw new Error(decision.message);
1608
+ if (decision.kind === "use") return decision.provider;
1609
+ const selected = await p3.select({
1610
+ message: `Select ${patternName} provider`,
1611
+ options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
1612
+ });
1613
+ if (p3.isCancel(selected)) {
1614
+ p3.cancel("Operation cancelled.");
1615
+ process7.exit(0);
1616
+ }
1617
+ return providers.find((provider) => provider.id === selected);
1618
+ }
1619
+ async function collectProviderEnv(provider) {
1620
+ const values = {};
1621
+ const interactive = isInteractive();
1622
+ for (const variable of provider.env ?? []) {
1623
+ const existing = process7.env[variable.key];
1624
+ if (existing) {
1625
+ values[variable.key] = existing;
1626
+ continue;
1627
+ }
1628
+ if (!interactive) {
1629
+ values[variable.key] = variable.default ?? "";
1630
+ continue;
1631
+ }
1632
+ const value = variable.secret ? await p3.password({
1633
+ message: variable.placeholder ? `${variable.label} (${variable.placeholder})` : variable.label
1634
+ }) : await p3.text({
1635
+ message: variable.label,
1636
+ placeholder: variable.placeholder,
1637
+ initialValue: variable.default
1638
+ });
1639
+ if (p3.isCancel(value)) {
1640
+ p3.cancel("Operation cancelled.");
1641
+ process7.exit(0);
1642
+ }
1643
+ values[variable.key] = (value ?? "").trim();
1644
+ }
1645
+ return values;
1646
+ }
1647
+ function missingEnvKeys(provider, values) {
1648
+ return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
1649
+ }
1650
+
1651
+ // src/lib/superuser.ts
1539
1652
  var emailFlag = v3.optional(v3.pipe(v3.string(), v3.email("must be a valid email address")));
1540
1653
  var passwordFlag = v3.optional(
1541
1654
  v3.pipe(v3.string(), v3.minLength(8, "must be at least 8 characters long"))
@@ -1564,17 +1677,23 @@ function decideSuperuser(flags, env2, interactive) {
1564
1677
  message: `Pass ${missing.join(" and ")} for the PocketBase admin user. There is no terminal to ask on.`
1565
1678
  };
1566
1679
  }
1680
+ async function requireSuperuser(flags, env2, onCancel2) {
1681
+ const decision = decideSuperuser(flags, env2, isInteractive());
1682
+ if (decision.kind === "error") throw new Error(decision.message);
1683
+ if (decision.kind === "use") return decision.credentials;
1684
+ return promptSuperuser(decision.known, onCancel2);
1685
+ }
1567
1686
  function superuserFromEnv() {
1568
- const email2 = process7.env.POCKETBASE_SUPERUSER_EMAIL?.trim();
1569
- const password9 = process7.env.POCKETBASE_SUPERUSER_PASSWORD;
1687
+ const email2 = process8.env.POCKETBASE_SUPERUSER_EMAIL?.trim();
1688
+ const password9 = process8.env.POCKETBASE_SUPERUSER_PASSWORD;
1570
1689
  return { ...email2 ? { email: email2 } : {}, ...password9 ? { password: password9 } : {} };
1571
1690
  }
1572
1691
  function promptSuperuser(known, onCancel2) {
1573
- return p3.group(
1692
+ return p4.group(
1574
1693
  {
1575
1694
  email: () => {
1576
1695
  if (known.email) return Promise.resolve(known.email);
1577
- return p3.text({
1696
+ return p4.text({
1578
1697
  message: "Enter an email for the admin user",
1579
1698
  initialValue: "admin@example.com",
1580
1699
  validate: (value) => !value ? "Email is required" : !value.includes("@") ? "Invalid email" : void 0
@@ -1582,7 +1701,7 @@ function promptSuperuser(known, onCancel2) {
1582
1701
  },
1583
1702
  password: () => {
1584
1703
  if (known.password) return Promise.resolve(known.password);
1585
- return p3.password({
1704
+ return p4.password({
1586
1705
  message: "Enter a password for the admin user (at least 8 characters)",
1587
1706
  validate: (value) => !value ? "Password is required" : value.length < 8 ? "Password must be at least 8 characters long" : void 0
1588
1707
  });
@@ -2490,7 +2609,7 @@ async function ensureEnvDeclarations(root, specs) {
2490
2609
  }
2491
2610
 
2492
2611
  // src/lib/result-report.ts
2493
- import * as p4 from "@clack/prompts";
2612
+ import * as p5 from "@clack/prompts";
2494
2613
  function reportResult(report5) {
2495
2614
  const sections = [
2496
2615
  ["Files created", report5.filesCreated],
@@ -2514,20 +2633,20 @@ function reportResult(report5) {
2514
2633
  }
2515
2634
  const failures = report5.failures ?? [];
2516
2635
  if (body.length > 0) {
2517
- p4.log.success(`${report5.summary}
2636
+ p5.log.success(`${report5.summary}
2518
2637
 
2519
2638
  ${body.join("\n")}`);
2520
2639
  } else if (failures.length === 0) {
2521
- p4.log.success(report5.summary);
2640
+ p5.log.success(report5.summary);
2522
2641
  }
2523
2642
  for (const failure of failures) {
2524
2643
  const headline = failure.status === "not-found" ? `Could not find ${failure.path}` : `Could not update ${failure.path}`;
2525
- p4.log.warn(failure.message ? `${headline}
2644
+ p5.log.warn(failure.message ? `${headline}
2526
2645
 
2527
2646
  ${failure.message}` : headline);
2528
2647
  }
2529
2648
  if (report5.nextSteps && report5.nextSteps.length > 0) {
2530
- p4.note(report5.nextSteps.map((s) => `- ${s}`).join("\n"), "Next steps", {
2649
+ p5.note(report5.nextSteps.map((s) => `- ${s}`).join("\n"), "Next steps", {
2531
2650
  format: (line) => line
2532
2651
  });
2533
2652
  }
@@ -2537,7 +2656,11 @@ ${failure.message}` : headline);
2537
2656
  function optionsSchema() {
2538
2657
  const templates = projectTemplateNames({ backend: true });
2539
2658
  return v4.strictObject({
2540
- install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
2659
+ // Unset when neither `--install` nor `--no-install` is passed (commander 15).
2660
+ install: v4.optional(
2661
+ v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
2662
+ true
2663
+ ),
2541
2664
  template: v4.optional(v4.picklist(templates, `must be one of: ${templates.join(", ")}`)),
2542
2665
  email: emailFlag,
2543
2666
  password: passwordFlag,
@@ -2586,9 +2709,9 @@ async function blessProject(cwdArg, options) {
2586
2709
  assertKit3(projectPath, "vela bless");
2587
2710
  assertNotAlreadyBlessed(projectPath);
2588
2711
  const templateDir = findProjectTemplate(options.template ?? DEFAULT_TEMPLATE).dir;
2589
- const { email: email2, password: password9 } = await promptSuperuser(options, () => {
2590
- p5.cancel("Operation cancelled.");
2591
- process8.exit(0);
2712
+ const { email: email2, password: password9 } = await requireSuperuser(options, {}, () => {
2713
+ p6.cancel("Operation cancelled.");
2714
+ process9.exit(0);
2592
2715
  });
2593
2716
  mergeDependencies(projectPath, templateDir);
2594
2717
  copyVelaOnlyFiles(templateDir, projectPath);
@@ -2599,7 +2722,7 @@ async function blessProject(cwdArg, options) {
2599
2722
  mergeConfigFiles(projectPath);
2600
2723
  mergeAppDts(templateDir, projectPath);
2601
2724
  maybeReplaceRoutes(projectPath, templateDir, options);
2602
- p5.log.success("Vela files in place");
2725
+ p6.log.success("Vela files in place");
2603
2726
  let packageManager2;
2604
2727
  if (options.install !== false) {
2605
2728
  const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
@@ -2609,7 +2732,7 @@ async function blessProject(cwdArg, options) {
2609
2732
  packageManager2 = pm;
2610
2733
  }
2611
2734
  }
2612
- p5.log.step("Initializing PocketBase...");
2735
+ p6.log.step("Initializing PocketBase...");
2613
2736
  await createSuperuser(projectPath, email2, password9);
2614
2737
  writeEnvFile(
2615
2738
  projectPath,
@@ -2619,12 +2742,12 @@ async function blessProject(cwdArg, options) {
2619
2742
  },
2620
2743
  ["PocketBase superuser credentials \u2014 used by `vela` commands"]
2621
2744
  );
2622
- p5.log.success("PocketBase initialized");
2745
+ p6.log.success("PocketBase initialized");
2623
2746
  printNextSteps(projectPath, packageManager2);
2624
2747
  }
2625
2748
  function ensureShadcnCss(projectPath) {
2626
2749
  if (ensureShadcnImport(path16.join(projectPath, "src", "app.css"))) {
2627
- p5.log.info(
2750
+ p6.log.info(
2628
2751
  "src/app.css: added the shadcn-svelte/tailwind.css import its registry components rely on."
2629
2752
  );
2630
2753
  }
@@ -2632,7 +2755,7 @@ function ensureShadcnCss(projectPath) {
2632
2755
  function hintComponentsJson(projectPath) {
2633
2756
  const config = readComponentsJson(projectPath);
2634
2757
  if (!config) return;
2635
- for (const hint of componentsJsonHints(config)) p5.log.warn(hint);
2758
+ for (const hint of componentsJsonHints(config)) p6.log.warn(hint);
2636
2759
  }
2637
2760
  function resolveProjectPath(cwdArg) {
2638
2761
  const projectPath = path16.resolve(cwdArg);
@@ -2671,14 +2794,14 @@ function mergeDependencies(projectPath, templateDir) {
2671
2794
  dropTemplateAdapters(userPkg, templatePkg)
2672
2795
  );
2673
2796
  const pinned = applyTemplatePins(merged, templatePkg, conflicts);
2674
- if (ensureLibImports(merged)) p5.log.info("package.json: added the #lib imports.");
2797
+ if (ensureLibImports(merged)) p6.log.info("package.json: added the #lib imports.");
2675
2798
  writePackageJson(userPkgPath, merged);
2676
2799
  if (pinned.length > 0) {
2677
- p5.log.info(`Pinned what SvelteKit 3 needs exactly:
2800
+ p6.log.info(`Pinned what SvelteKit 3 needs exactly:
2678
2801
  ${pinned.map((l) => ` ${l}`).join("\n")}`);
2679
2802
  }
2680
2803
  if (added.length > 0) {
2681
- p5.log.info(
2804
+ p6.log.info(
2682
2805
  `Added ${added.length} entries to package.json (${summarize(added.map((c) => c.name))}).`
2683
2806
  );
2684
2807
  }
@@ -2686,14 +2809,14 @@ ${pinned.map((l) => ` ${l}`).join("\n")}`);
2686
2809
  const lines = replaced.map(
2687
2810
  (c) => ` script ${pc3.bold(c.name)}: ${pc3.gray(c.userValue ?? "")} \u2192 ${pc3.cyan(c.templateValue)}`
2688
2811
  );
2689
- p5.log.info(`Updated ${replaced.length} script(s):
2812
+ p6.log.info(`Updated ${replaced.length} script(s):
2690
2813
  ${lines.join("\n")}`);
2691
2814
  }
2692
2815
  if (conflicts.length > 0) {
2693
2816
  const lines = conflicts.map(
2694
2817
  (c) => ` dep ${pc3.bold(c.name)}: kept ${pc3.cyan(c.userValue ?? "")} (template wants ${pc3.gray(c.templateValue)})`
2695
2818
  );
2696
- p5.log.warn(`Kept ${conflicts.length} dependency version(s) on conflict:
2819
+ p6.log.warn(`Kept ${conflicts.length} dependency version(s) on conflict:
2697
2820
  ${lines.join("\n")}`);
2698
2821
  }
2699
2822
  }
@@ -2734,9 +2857,9 @@ function applyTemplatePins(merged, template, conflicts) {
2734
2857
  async function declareEnvVars(projectPath) {
2735
2858
  const outcome = await ensureEnvDeclarations(projectPath, VELA_ENV_VARS);
2736
2859
  if (outcome.failure) {
2737
- p5.log.warn(`${outcome.file}: ${outcome.failure}`);
2860
+ p6.log.warn(`${outcome.file}: ${outcome.failure}`);
2738
2861
  } else if (outcome.changed) {
2739
- p5.log.info(`${outcome.file}: declared ${outcome.declared.join(", ")}.`);
2862
+ p6.log.info(`${outcome.file}: declared ${outcome.declared.join(", ")}.`);
2740
2863
  }
2741
2864
  }
2742
2865
  function copyVelaOnlyFiles(templateDir, projectPath) {
@@ -2765,7 +2888,7 @@ function writeSiteFile(templateDir, projectPath) {
2765
2888
  const dest = path16.join(projectPath, SITE_FILE);
2766
2889
  if (!fs18.existsSync(source)) return;
2767
2890
  if (fs18.existsSync(dest)) {
2768
- p5.log.info(
2891
+ p6.log.info(
2769
2892
  `Kept your ${pc3.bold(SITE_FILE)}. Vela's layouts read ${pc3.cyan("name")} and ${pc3.cyan("url")} from its ${pc3.cyan("site")} export.`
2770
2893
  );
2771
2894
  return;
@@ -2780,13 +2903,13 @@ function writeSiteFile(templateDir, projectPath) {
2780
2903
  cliVersion: package_default.version
2781
2904
  })
2782
2905
  );
2783
- p5.log.info(`Wrote ${pc3.bold(SITE_FILE)}, naming the app ${pc3.cyan(appName)}. Edit it to rename.`);
2906
+ p6.log.info(`Wrote ${pc3.bold(SITE_FILE)}, naming the app ${pc3.cyan(appName)}. Edit it to rename.`);
2784
2907
  }
2785
2908
  function reportKeptFiles(kept) {
2786
2909
  if (kept.length === 0) return;
2787
2910
  const padding = Math.max(...kept.map((f) => f.path.length));
2788
2911
  const lines = kept.map((f) => ` ${pc3.bold(f.path.padEnd(padding))} ${pc3.gray(f.adds)}`);
2789
- p5.log.info(
2912
+ p6.log.info(
2790
2913
  `Kept ${kept.length} file(s) you already had. Merge by hand to pick up what vela adds:
2791
2914
  ${lines.join("\n")}`
2792
2915
  );
@@ -2814,11 +2937,11 @@ function mergeConfigFiles(projectPath) {
2814
2937
  ];
2815
2938
  for (const [name, outcome] of outcomes) {
2816
2939
  if (outcome.applied) {
2817
- p5.log.info(`${name}: ${outcome.reason}`);
2940
+ p6.log.info(`${name}: ${outcome.reason}`);
2818
2941
  continue;
2819
2942
  }
2820
2943
  if (outcome.snippet) {
2821
- p5.log.warn(
2944
+ p6.log.warn(
2822
2945
  `${name}: ${outcome.reason}
2823
2946
  ${pc3.gray("Add this manually:")}
2824
2947
  ${pc3.cyan(outcome.snippet)}`
@@ -2845,7 +2968,7 @@ function mergeAppDts(templateDir, projectPath) {
2845
2968
  `;
2846
2969
  const match = current.match(/declare global\s*\{\s*\n/);
2847
2970
  if (!match || match.index === void 0) {
2848
- p5.log.warn(
2971
+ p6.log.warn(
2849
2972
  `src/app.d.ts: non-standard shape \u2014 add this namespace manually:
2850
2973
  ${pc3.cyan(block)}`
2851
2974
  );
@@ -2857,11 +2980,11 @@ ${pc3.cyan(block)}`
2857
2980
  }
2858
2981
  function maybeReplaceRoutes(projectPath, templateDir, options) {
2859
2982
  if (options.skipRoutes) {
2860
- p5.log.info("Skipping src/routes (--skip-routes).");
2983
+ p6.log.info("Skipping src/routes (--skip-routes).");
2861
2984
  return;
2862
2985
  }
2863
2986
  if (!options.forceRoutes && !isVanillaRoutes(projectPath)) {
2864
- p5.log.info("Leaving src/routes alone (looks customized).");
2987
+ p6.log.info("Leaving src/routes alone (looks customized).");
2865
2988
  return;
2866
2989
  }
2867
2990
  const target = path16.join(projectPath, "src", "routes");
@@ -2871,14 +2994,14 @@ function maybeReplaceRoutes(projectPath, templateDir, options) {
2871
2994
  recursive: true,
2872
2995
  filter: (s) => path16.basename(s) !== ".DS_Store"
2873
2996
  });
2874
- p5.log.success("Replaced src/routes with the vela template.");
2997
+ p6.log.success("Replaced src/routes with the vela template.");
2875
2998
  }
2876
2999
  function summarize(names) {
2877
3000
  if (names.length <= 4) return names.join(", ");
2878
3001
  return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
2879
3002
  }
2880
3003
  function printNextSteps(projectPath, packageManager2) {
2881
- const relative = path16.relative(process8.cwd(), projectPath);
3004
+ const relative = path16.relative(process9.cwd(), projectPath);
2882
3005
  const pm = packageManager2 ?? getUserAgent() ?? "npm";
2883
3006
  const nextSteps = [];
2884
3007
  if (relative !== "") {
@@ -2910,117 +3033,6 @@ import { Command as Command3 } from "commander";
2910
3033
  import * as p10 from "@clack/prompts";
2911
3034
  import { detect as detect5, resolveCommand as resolveCommand3 } from "package-manager-detector";
2912
3035
 
2913
- // src/lib/providers.ts
2914
- import process9 from "node:process";
2915
- import * as p6 from "@clack/prompts";
2916
- import { bySlug } from "@velastack/patterns";
2917
- function capabilityName(slug2) {
2918
- return slug2.replace(/^enable-/, "");
2919
- }
2920
- function choices(providers) {
2921
- return `--provider <${providers.map((provider) => provider.id).join("|")}>`;
2922
- }
2923
- function unknownProviderMessage(name, raw, providers) {
2924
- return [
2925
- `Unknown provider "${raw}" for ${name}.`,
2926
- "",
2927
- "Available providers:",
2928
- ...providers.map((provider) => ` ${provider.id}`)
2929
- ].join("\n");
2930
- }
2931
- function decideProvider(request) {
2932
- const { patternName, providers, flagValue, interactive } = request;
2933
- if (flagValue !== void 0) {
2934
- const provider = providers.find((candidate) => candidate.id === flagValue);
2935
- if (!provider) {
2936
- return { kind: "error", message: unknownProviderMessage(patternName, flagValue, providers) };
2937
- }
2938
- return { kind: "use", provider };
2939
- }
2940
- if (interactive) return { kind: "prompt" };
2941
- return {
2942
- kind: "error",
2943
- message: `Choose ${article(patternName)} ${patternName} provider: pass ${choices(providers)}. There is no terminal to ask on.`
2944
- };
2945
- }
2946
- function article(word) {
2947
- return /^[aeiou]/i.test(word) ? "an" : "a";
2948
- }
2949
- function isInteractive() {
2950
- return Boolean(process9.stdout.isTTY) && !process9.env.CI;
2951
- }
2952
- function providerFlagInArgv(argv) {
2953
- return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
2954
- }
2955
- function checkProviderInput(pattern, argv, input) {
2956
- const providers = pattern.providers ?? [];
2957
- if (providers.length > 0) {
2958
- if (typeof input.provider !== "string" || input.provider.length === 0) {
2959
- throw new Error(`${pattern.title} needs a provider. Pass ${choices(providers)}.`);
2960
- }
2961
- return;
2962
- }
2963
- if (providerFlagInArgv(argv)) {
2964
- throw new Error(`${pattern.title} does not support --provider.`);
2965
- }
2966
- }
2967
- async function resolveProvider(slug2, flagValue) {
2968
- const pattern = bySlug[slug2];
2969
- const providers = pattern.providers ?? [];
2970
- if (providers.length === 0) {
2971
- throw new Error(`${pattern.title} does not support --provider.`);
2972
- }
2973
- const patternName = capabilityName(slug2);
2974
- const decision = decideProvider({
2975
- patternName,
2976
- providers,
2977
- flagValue,
2978
- interactive: isInteractive()
2979
- });
2980
- if (decision.kind === "error") throw new Error(decision.message);
2981
- if (decision.kind === "use") return decision.provider;
2982
- const selected = await p6.select({
2983
- message: `Select ${patternName} provider`,
2984
- options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
2985
- });
2986
- if (p6.isCancel(selected)) {
2987
- p6.cancel("Operation cancelled.");
2988
- process9.exit(0);
2989
- }
2990
- return providers.find((provider) => provider.id === selected);
2991
- }
2992
- async function collectProviderEnv(provider) {
2993
- const values = {};
2994
- const interactive = isInteractive();
2995
- for (const variable of provider.env ?? []) {
2996
- const existing = process9.env[variable.key];
2997
- if (existing) {
2998
- values[variable.key] = existing;
2999
- continue;
3000
- }
3001
- if (!interactive) {
3002
- values[variable.key] = variable.default ?? "";
3003
- continue;
3004
- }
3005
- const value = variable.secret ? await p6.password({
3006
- message: variable.placeholder ? `${variable.label} (${variable.placeholder})` : variable.label
3007
- }) : await p6.text({
3008
- message: variable.label,
3009
- placeholder: variable.placeholder,
3010
- initialValue: variable.default
3011
- });
3012
- if (p6.isCancel(value)) {
3013
- p6.cancel("Operation cancelled.");
3014
- process9.exit(0);
3015
- }
3016
- values[variable.key] = (value ?? "").trim();
3017
- }
3018
- return values;
3019
- }
3020
- function missingEnvKeys(provider, values) {
3021
- return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
3022
- }
3023
-
3024
3036
  // src/lib/link-on-create.ts
3025
3037
  var FREE_CMS_HINT = "Get a free CMS at https://velastack.dev";
3026
3038
  var PROJECT_ID_RE = /^[a-z0-9]{15}$/;
@@ -5532,7 +5544,13 @@ function optionsSchema2(listing) {
5532
5544
  choices2 += ` (could not reach the template registry: ${listing.registryError})`;
5533
5545
  }
5534
5546
  return v5.strictObject({
5535
- install: v5.union([v5.boolean(), v5.picklist(AGENT_NAMES)], "must be a package manager"),
5547
+ // `--no-install` and `--install <pm>` share a key, and commander 15 leaves it
5548
+ // unset when neither is passed: installing with the detected package
5549
+ // manager is the default.
5550
+ install: v5.optional(
5551
+ v5.union([v5.boolean(), v5.picklist(AGENT_NAMES)], "must be a package manager"),
5552
+ true
5553
+ ),
5536
5554
  template: v5.optional(v5.picklist(names, choices2)),
5537
5555
  name: v5.optional(v5.pipe(v5.string(), v5.trim(), v5.minLength(1, "must not be empty"))),
5538
5556
  email: emailFlag,
@@ -5688,9 +5706,12 @@ async function resolveCreatableTemplate(template) {
5688
5706
  return resolved;
5689
5707
  }
5690
5708
  async function scaffoldProject(cwdArg, options, template, resolved, onCancel2) {
5709
+ const interactive = isInteractive();
5691
5710
  let directory;
5692
5711
  if (cwdArg) {
5693
5712
  directory = path27.resolve(cwdArg);
5713
+ } else if (!interactive) {
5714
+ throw new Error("Pass the directory to create the project in, e.g. `vela create my-app`.");
5694
5715
  } else {
5695
5716
  const answer = await p10.text({
5696
5717
  message: "Where would you like your project to be created?",
@@ -5701,6 +5722,7 @@ async function scaffoldProject(cwdArg, options, template, resolved, onCancel2) {
5701
5722
  directory = path27.resolve(answer);
5702
5723
  }
5703
5724
  if (fs29.existsSync(directory) && fs29.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
5725
+ if (!interactive) throw new Error(`${directory} is not empty.`);
5704
5726
  const force = await p10.confirm({
5705
5727
  message: "Directory not empty. Continue?",
5706
5728
  initialValue: false
@@ -5712,6 +5734,7 @@ async function scaffoldProject(cwdArg, options, template, resolved, onCancel2) {
5712
5734
  {
5713
5735
  name: () => {
5714
5736
  if (options.name) return Promise.resolve(options.name);
5737
+ if (!interactive) return Promise.resolve(dirName || "SvelteKit");
5715
5738
  return p10.text({
5716
5739
  message: "App name (written to src/lib/site.ts)",
5717
5740
  initialValue: dirName || "SvelteKit",
@@ -5721,7 +5744,7 @@ async function scaffoldProject(cwdArg, options, template, resolved, onCancel2) {
5721
5744
  },
5722
5745
  { onCancel: onCancel2 }
5723
5746
  );
5724
- const credentials = template.backend ? await promptSuperuser(options, onCancel2) : void 0;
5747
+ const credentials = template.backend ? await requireSuperuser(options, {}, onCancel2) : void 0;
5725
5748
  const link2 = await linkOnCreate(name, template, options, onCancel2);
5726
5749
  copyTemplate(resolved, directory);
5727
5750
  applyTemplateFiles(directory, {