vela 0.14.3 → 0.14.5

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 CHANGED
@@ -110,12 +110,13 @@ keeps deploying to the same instance, now with a database.
110
110
  Much of `vela` needs neither. In a plain `npx sv create` project, with no setup:
111
111
 
112
112
  - `vela generate schema` and `vela generate form`, the form in plain HTML
113
+ - `vela generate scaffold` once there is a backend: a plain HTML table, detail page and forms
113
114
  - `vela enable i18n`, `ai`, `analytics`, `content-negotiation` and `cms`
114
115
  - `vela legal` and `vela routes`
115
116
  - `vela deploy`, `env`, `status`, `logs` and `rollback`
116
117
 
117
118
  `vela ui`, `vela enable blog`, `vela enable auth` and what builds on it, and
118
- `vela generate scaffold` write shadcn-svelte markup. Without it they refuse before
119
+ `vela generate scaffold --remote` write shadcn-svelte markup. Without it they refuse before
119
120
  changing anything and name the setup: `npx sv add tailwindcss`, then
120
121
  `npx shadcn-svelte@latest init`.
121
122
 
package/dist/bin.js CHANGED
@@ -21,7 +21,7 @@ import pc43 from "picocolors";
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "vela",
24
- version: "0.14.3",
24
+ version: "0.14.5",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -57,9 +57,9 @@ var package_default = {
57
57
  dependencies: {
58
58
  "@clack/prompts": "^1.7.0",
59
59
  "@faker-js/faker": "^10.6.0",
60
- "@velastack/patterns": "^0.3.2",
60
+ "@velastack/patterns": "^0.3.4",
61
61
  "@velastack/pocketbase-codegen": "^0.1.0",
62
- "annotate-json-schema": "^0.1.0",
62
+ "annotate-json-schema": "^0.1.1",
63
63
  commander: "^13.1.0",
64
64
  "cross-spawn": "^7.0.6",
65
65
  dedent: "^1.7.2",
@@ -71,7 +71,7 @@ var package_default = {
71
71
  picocolors: "^1.1.1",
72
72
  pocketbase: "^0.28.0",
73
73
  "pocketbase-server": "^0.40.5-beta.2",
74
- stripe: "^19.3.0",
74
+ stripe: "^22.6.2",
75
75
  svelte: "^5.56.10",
76
76
  tar: "^7.5.22",
77
77
  tinyexec: "^1.3.0",
@@ -903,7 +903,7 @@ function optionalStringArray(value) {
903
903
  import fs8 from "node:fs";
904
904
  import path7 from "node:path";
905
905
  import process5 from "node:process";
906
- import { exec } from "tinyexec";
906
+ import { exec, execSync } from "tinyexec";
907
907
  import { Option } from "commander";
908
908
  import * as p2 from "@clack/prompts";
909
909
  import {
@@ -931,10 +931,10 @@ async function packageManagerPrompt(cwd) {
931
931
  if (!process5.stdout.isTTY) return agent;
932
932
  const options = [
933
933
  { label: "None", value: void 0 },
934
- ...AGENT_NAMES.map((pm2) => ({ value: pm2, label: pm2 }))
934
+ ...AGENT_NAMES.filter(isInstalled).map((pm2) => ({ value: pm2, label: pm2 }))
935
935
  ];
936
936
  const pm = await p2.select({
937
- message: "Which package manager do you want to install dependencies with?",
937
+ message: "Detected package managers. Which one should we use to install dependencies?",
938
938
  options,
939
939
  initialValue: agent
940
940
  });
@@ -944,7 +944,25 @@ async function packageManagerPrompt(cwd) {
944
944
  }
945
945
  return pm;
946
946
  }
947
+ var installedCache = /* @__PURE__ */ new Map();
948
+ function isInstalled(agent) {
949
+ let installed = installedCache.get(agent);
950
+ if (installed === void 0) {
951
+ try {
952
+ execSync(agent, ["--version"], { nodeOptions: { stdio: "ignore" } });
953
+ installed = true;
954
+ } catch {
955
+ installed = false;
956
+ }
957
+ installedCache.set(agent, installed);
958
+ }
959
+ return installed;
960
+ }
947
961
  async function installDependencies(agent, cwd, { exitOnFailure = true } = {}) {
962
+ if (!isInstalled(agent)) {
963
+ p2.log.warn(`${agent} is not installed, skipping dependency installation.`);
964
+ return false;
965
+ }
948
966
  const task = p2.taskLog({
949
967
  title: `Installing dependencies with ${agent}...`,
950
968
  limit: Math.ceil(process5.stdout.rows / 2),
@@ -2572,7 +2590,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
2572
2590
  return runCommand(async () => {
2573
2591
  const listing = await listAllTemplates();
2574
2592
  const options = parseOptions(optionsSchema2(listing), rawOpts);
2575
- const { directory, packageManager: packageManager2, name, template, link: link2 } = await createProject2(
2593
+ const { directory, packageManager: packageManager2, installed, name, template, link: link2 } = await createProject2(
2576
2594
  projectPath,
2577
2595
  options,
2578
2596
  listing
@@ -2584,7 +2602,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
2584
2602
  const hasSpaces = relative.includes(" ");
2585
2603
  nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
2586
2604
  }
2587
- if (!packageManager2) {
2605
+ if (!installed) {
2588
2606
  const resolved = resolveCommand3(pm, "install", []);
2589
2607
  if (resolved) {
2590
2608
  nextSteps.push(
@@ -2681,12 +2699,13 @@ async function createProject2(cwdArg, options, listing) {
2681
2699
  }
2682
2700
  p9.log.success("Project created");
2683
2701
  let packageManager2;
2702
+ let installed = false;
2684
2703
  if (options.install !== false) {
2685
2704
  const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
2686
2705
  if (pm) {
2687
2706
  const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
2688
2707
  addPnpmBuildDependencies(projectPath, pm, builds);
2689
- await installDependencies(pm, projectPath);
2708
+ installed = await installDependencies(pm, projectPath);
2690
2709
  packageManager2 = pm;
2691
2710
  }
2692
2711
  }
@@ -2713,7 +2732,7 @@ async function createProject2(cwdArg, options, listing) {
2713
2732
  );
2714
2733
  p9.log.success("PocketBase initialized");
2715
2734
  }
2716
- return { directory: projectPath, packageManager: packageManager2, name, template, link: link2 };
2735
+ return { directory: projectPath, packageManager: packageManager2, installed, name, template, link: link2 };
2717
2736
  }
2718
2737
  async function linkOnCreate(name, template, options, onCancel2) {
2719
2738
  const templateCms = template.cms === true;
@@ -2839,7 +2858,7 @@ async function runPattern(slug2, argv, input, report4, after) {
2839
2858
  if (pattern.requires.ui === "shadcn" && features.ui !== "shadcn") {
2840
2859
  assertShadcn(`vela ${pattern.command.base.replace(/^vela /, "")}`, workspaceRootDir);
2841
2860
  }
2842
- const log51 = p10.taskLog({ title: report4.task.title });
2861
+ const log53 = p10.taskLog({ title: report4.task.title });
2843
2862
  let result;
2844
2863
  try {
2845
2864
  result = await pattern.generate({
@@ -2860,11 +2879,11 @@ async function runPattern(slug2, argv, input, report4, after) {
2860
2879
  });
2861
2880
  return collections2;
2862
2881
  },
2863
- logger: { info: (message) => log51.message(message) }
2882
+ logger: { info: (message) => log53.message(message) }
2864
2883
  });
2865
- log51.success(report4.task.success);
2884
+ log53.success(report4.task.success);
2866
2885
  } catch (e) {
2867
- log51.error(report4.task.error);
2886
+ log53.error(report4.task.error);
2868
2887
  throw e;
2869
2888
  }
2870
2889
  let afterError;
@@ -3367,12 +3386,20 @@ import * as p17 from "@clack/prompts";
3367
3386
  var scaffold = new Command7("scaffold").description("generate a full CRUD scaffold (model, forms, list, detail)").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--remote", "generate create/update forms with SvelteKit remote functions").option(
3368
3387
  "--route <route>",
3369
3388
  'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under the (app) or (public) group, or src/routes when it has neither.'
3389
+ ).option(
3390
+ "--ui <ui>",
3391
+ 'markup to generate: "shadcn" components or "plain" HTML. Defaults to shadcn when the project has shadcn-svelte, plain otherwise. --remote needs shadcn.'
3370
3392
  ).option(
3371
3393
  "--ai <description>",
3372
3394
  "design the scaffold with AI from a natural-language description (two stages: schema \u2192 layout)"
3373
3395
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3374
3396
  (model, fields, options) => runCommand(async () => {
3375
- assertShadcn("vela generate scaffold");
3397
+ if (options.remote) {
3398
+ if (options.ui === "plain") {
3399
+ throw new Error("--remote has no plain variant; drop --ui plain or --remote.");
3400
+ }
3401
+ assertShadcn("vela generate scaffold --remote");
3402
+ }
3376
3403
  let argv;
3377
3404
  let modelName;
3378
3405
  let sidecarPath = null;
@@ -3400,6 +3427,11 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
3400
3427
  argv = [model, ...fields];
3401
3428
  modelName = model;
3402
3429
  }
3430
+ const { workspaceRootDir, features } = await getWorkspace();
3431
+ const formInput = resolveFormInput(workspaceRootDir, features.ui, options.ui);
3432
+ if (features.ui === "plain" && !options.ui) {
3433
+ p17.log.info("shadcn-svelte not detected: generating plain HTML pages.");
3434
+ }
3403
3435
  const slug2 = options.remote ? "generate-scaffold-remote" : "generate-scaffold";
3404
3436
  const nextSteps = [
3405
3437
  `Run \`vela fixtures generate\` to create 10 ${modelName} records for development.`,
@@ -3414,7 +3446,7 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
3414
3446
  await runPattern(
3415
3447
  slug2,
3416
3448
  argv,
3417
- { route: options.route },
3449
+ { route: options.route, ...formInput },
3418
3450
  {
3419
3451
  summary: `Created ${modelName} scaffold.`,
3420
3452
  nextSteps,
@@ -3672,9 +3704,9 @@ function backendNextSteps(ui2) {
3672
3704
  }
3673
3705
  return [
3674
3706
  dev2,
3675
- "Run `vela generate form <model> <fields...>` to add a collection with a form in plain HTML.",
3707
+ "Run `vela generate scaffold <model> <fields...>` to add a collection with CRUD pages in plain HTML.",
3676
3708
  "Run `vela test:server` to run the server tests that come with it.",
3677
- "`vela enable auth` and `vela generate scaffold` need shadcn-svelte: `npx sv add tailwindcss`, then `npx shadcn-svelte@latest init`."
3709
+ "`vela enable auth` needs shadcn-svelte: `npx sv add tailwindcss`, then `npx shadcn-svelte@latest init`."
3678
3710
  ];
3679
3711
  }
3680
3712
  async function initPocketbase(root, { email: email2, password: password11 }) {
@@ -5574,6 +5606,14 @@ vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}:`
5574
5606
  }
5575
5607
  async function installAdapterDependencies(root) {
5576
5608
  const agent = await packageManager(root);
5609
+ if (!isInstalled(agent)) {
5610
+ throw new AdapterError(
5611
+ `${agent} is not installed, so ${ADAPTER_NODE} couldn't be installed.
5612
+
5613
+ The config and package.json are already updated: install ${agent}, run \`${agent} install\`, then deploy again.`,
5614
+ ""
5615
+ );
5616
+ }
5577
5617
  const ok = await installDependencies(agent, root, { exitOnFailure: false });
5578
5618
  if (!ok) {
5579
5619
  throw new AdapterError(
@@ -6613,18 +6653,18 @@ var add = new Command50("add").description("add ui components (shadcn-svelte ite
6613
6653
  (components, options) => runCommand(async () => {
6614
6654
  const { workspaceRootDir } = await getWorkspace();
6615
6655
  assertShadcn("vela ui add", workspaceRootDir);
6616
- const log51 = p31.taskLog({ title: "Adding UI components..." });
6656
+ const log53 = p31.taskLog({ title: "Adding UI components..." });
6617
6657
  let outcome;
6618
6658
  try {
6619
6659
  outcome = await installComponents({
6620
6660
  root: workspaceRootDir,
6621
6661
  components,
6622
6662
  overwrite: options.overwrite,
6623
- logger: { info: (message) => log51.message(message) }
6663
+ logger: { info: (message) => log53.message(message) }
6624
6664
  });
6625
- log51.success("UI components ready");
6665
+ log53.success("UI components ready");
6626
6666
  } catch (e) {
6627
- log51.error("Could not add UI components");
6667
+ log53.error("Could not add UI components");
6628
6668
  throw e;
6629
6669
  }
6630
6670
  reportResult(uiAddReport(components, outcome));
@@ -6639,13 +6679,13 @@ var base = new Command51("base").description("change the base (gray) palette").a
6639
6679
  (color) => runCommand(async () => {
6640
6680
  const { workspaceRootDir } = await getWorkspace();
6641
6681
  assertShadcn("vela ui base", workspaceRootDir);
6642
- const log51 = p32.taskLog({ title: `Applying the ${color} palette...` });
6682
+ const log53 = p32.taskLog({ title: `Applying the ${color} palette...` });
6643
6683
  let outcome;
6644
6684
  try {
6645
6685
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
6646
- log51.success("Palette applied");
6686
+ log53.success("Palette applied");
6647
6687
  } catch (e) {
6648
- log51.error("Could not change the base color");
6688
+ log53.error("Could not change the base color");
6649
6689
  throw e;
6650
6690
  }
6651
6691
  reportResult({
@@ -6754,14 +6794,14 @@ var style = new Command53("style").description("switch the shadcn-svelte style,
6754
6794
  assertShadcn("vela ui style", workspaceRootDir);
6755
6795
  const spinner8 = p34.spinner();
6756
6796
  spinner8.start(`Reading the ${name} registry...`);
6757
- let log51;
6797
+ let log53;
6758
6798
  let outcome;
6759
6799
  try {
6760
6800
  outcome = await switchStyle({
6761
6801
  root: workspaceRootDir,
6762
6802
  style: name,
6763
6803
  font: options.font,
6764
- logger: { info: (message) => log51?.message(message) },
6804
+ logger: { info: (message) => log53?.message(message) },
6765
6805
  confirm: async (components) => {
6766
6806
  spinner8.stop(`Read the ${name} registry`);
6767
6807
  if (components.length > 0) {
@@ -6778,13 +6818,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
6778
6818
  const ok = await p34.confirm({ message: `Switch to ${name}?`, initialValue: false });
6779
6819
  if (p34.isCancel(ok) || !ok) return false;
6780
6820
  }
6781
- log51 = p34.taskLog({ title: `Switching to the ${name} style...` });
6821
+ log53 = p34.taskLog({ title: `Switching to the ${name} style...` });
6782
6822
  return true;
6783
6823
  }
6784
6824
  });
6785
6825
  } catch (e) {
6786
6826
  spinner8.stop(`Could not switch to ${name}`);
6787
- log51?.error("Could not switch style");
6827
+ log53?.error("Could not switch style");
6788
6828
  throw e;
6789
6829
  }
6790
6830
  spinner8.stop(`Read the ${name} registry`);
@@ -6796,7 +6836,7 @@ ${components.map((c) => `- ${c}`).join("\n")}`
6796
6836
  p34.cancel("Operation cancelled.");
6797
6837
  return;
6798
6838
  }
6799
- log51?.success("Style switched");
6839
+ log53?.success("Style switched");
6800
6840
  reportResult(uiStyleReport(outcome));
6801
6841
  }, "Failed to switch style.")
6802
6842
  );
@@ -6809,13 +6849,13 @@ var theme = new Command54("theme").description("change the accent color, keeping
6809
6849
  (accent) => runCommand(async () => {
6810
6850
  const { workspaceRootDir } = await getWorkspace();
6811
6851
  assertShadcn("vela ui theme", workspaceRootDir);
6812
- const log51 = p35.taskLog({ title: `Applying the ${accent} accent...` });
6852
+ const log53 = p35.taskLog({ title: `Applying the ${accent} accent...` });
6813
6853
  let outcome;
6814
6854
  try {
6815
6855
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
6816
- log51.success("Accent applied");
6856
+ log53.success("Accent applied");
6817
6857
  } catch (e) {
6818
- log51.error("Could not change the accent");
6858
+ log53.error("Could not change the accent");
6819
6859
  throw e;
6820
6860
  }
6821
6861
  reportResult({