vela 0.10.14 → 0.11.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/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/bin.ts
4
- import process36 from "node:process";
4
+ import process38 from "node:process";
5
5
 
6
6
  // src/lib/argv.ts
7
7
  function normalizeArgv(argv) {
@@ -11,17 +11,17 @@ function normalizeArgv(argv) {
11
11
  }
12
12
 
13
13
  // src/program.ts
14
- import process35 from "node:process";
15
- import * as p59 from "@clack/prompts";
16
- import { Command as Command103 } from "commander";
14
+ import process37 from "node:process";
15
+ import * as p61 from "@clack/prompts";
16
+ import { Command as Command104 } from "commander";
17
17
  import nodePath from "node:path";
18
18
  import dotenv2 from "dotenv";
19
- import pc36 from "picocolors";
19
+ import pc38 from "picocolors";
20
20
 
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "vela",
24
- version: "0.10.14",
24
+ version: "0.11.0",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -222,15 +222,19 @@ function stubCommand(name, description, fullName) {
222
222
  // src/lib/workspace.ts
223
223
  import fs2 from "node:fs";
224
224
  import path from "node:path";
225
- import process2 from "node:process";
225
+ import process3 from "node:process";
226
226
 
227
227
  // src/lib/constants.ts
228
+ import process2 from "node:process";
228
229
  var DATA_DIR = "data";
229
230
  var MIGRATIONS_DIR = "migrations";
230
231
  var PUBLIC_DIR = "(public)";
231
232
  var APP_DIR = "(app)";
232
233
  var LEGAL_DIR = "(legal)";
233
- var API_URL = "https://velastack.dev";
234
+ var API_URL = (process2.env.VELA_API_URL?.trim() || "https://velastack.dev").replace(
235
+ /\/$/,
236
+ ""
237
+ );
234
238
  var FIXTURE_PREFIX = "vela";
235
239
 
236
240
  // src/lib/package-json.ts
@@ -313,7 +317,7 @@ function sortKeys(obj) {
313
317
  }
314
318
 
315
319
  // src/lib/workspace.ts
316
- function findWorkspaceRoot(from = process2.cwd()) {
320
+ function findWorkspaceRoot(from = process3.cwd()) {
317
321
  let currentDir = from;
318
322
  while (currentDir !== path.parse(currentDir).root) {
319
323
  if (fs2.existsSync(path.join(currentDir, "package.json"))) return currentDir;
@@ -321,11 +325,11 @@ function findWorkspaceRoot(from = process2.cwd()) {
321
325
  }
322
326
  return null;
323
327
  }
324
- function hasBackend(from = process2.cwd()) {
328
+ function hasBackend(from = process3.cwd()) {
325
329
  const root = findWorkspaceRoot(from);
326
330
  return root !== null && fs2.existsSync(path.join(root, DATA_DIR));
327
331
  }
328
- function localDataDir(from = process2.cwd()) {
332
+ function localDataDir(from = process3.cwd()) {
329
333
  return path.join(findWorkspaceRoot(from) ?? from, DATA_DIR);
330
334
  }
331
335
  async function getWorkspace() {
@@ -381,7 +385,7 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
381
385
  // src/commands/bless.ts
382
386
  import fs13 from "node:fs";
383
387
  import path11 from "node:path";
384
- import process5 from "node:process";
388
+ import process6 from "node:process";
385
389
  import * as v2 from "valibot";
386
390
  import { Command as Command2 } from "commander";
387
391
  import * as p4 from "@clack/prompts";
@@ -482,7 +486,7 @@ function readManifest(root, name) {
482
486
  // src/lib/package-manager.ts
483
487
  import fs4 from "node:fs";
484
488
  import path3 from "node:path";
485
- import process3 from "node:process";
489
+ import process4 from "node:process";
486
490
  import { exec } from "tinyexec";
487
491
  import { Option } from "commander";
488
492
  import * as p2 from "@clack/prompts";
@@ -498,7 +502,7 @@ var installOption = new Option(
498
502
  "installs dependencies with a specified package manager"
499
503
  ).choices(AGENT_NAMES);
500
504
  function getUserAgent() {
501
- const userAgent = process3.env.npm_config_user_agent;
505
+ const userAgent = process4.env.npm_config_user_agent;
502
506
  if (!userAgent) return void 0;
503
507
  const pmSpec = userAgent.split(" ")[0];
504
508
  const separatorPos = pmSpec.lastIndexOf("/");
@@ -508,7 +512,7 @@ function getUserAgent() {
508
512
  async function packageManagerPrompt(cwd) {
509
513
  const detected = await detect({ cwd });
510
514
  const agent = detected?.name ?? getUserAgent();
511
- if (!process3.stdout.isTTY) return agent;
515
+ if (!process4.stdout.isTTY) return agent;
512
516
  const options = [
513
517
  { label: "None", value: void 0 },
514
518
  ...AGENT_NAMES.map((pm2) => ({ value: pm2, label: pm2 }))
@@ -520,14 +524,14 @@ async function packageManagerPrompt(cwd) {
520
524
  });
521
525
  if (p2.isCancel(pm)) {
522
526
  p2.cancel("Operation cancelled.");
523
- process3.exit(1);
527
+ process4.exit(1);
524
528
  }
525
529
  return pm;
526
530
  }
527
531
  async function installDependencies(agent, cwd) {
528
532
  const task = p2.taskLog({
529
533
  title: `Installing dependencies with ${agent}...`,
530
- limit: Math.ceil(process3.stdout.rows / 2),
534
+ limit: Math.ceil(process4.stdout.rows / 2),
531
535
  spacing: 0,
532
536
  retainLog: true
533
537
  });
@@ -544,7 +548,7 @@ async function installDependencies(agent, cwd) {
544
548
  } catch {
545
549
  task.error("Failed to install dependencies");
546
550
  p2.cancel("Operation failed.");
547
- process3.exit(2);
551
+ process4.exit(2);
548
552
  }
549
553
  }
550
554
  function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
@@ -566,7 +570,7 @@ function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
566
570
  import fs5 from "node:fs";
567
571
  import net from "node:net";
568
572
  import path4 from "node:path";
569
- import process4 from "node:process";
573
+ import process5 from "node:process";
570
574
  import { createRequire } from "node:module";
571
575
  import { spawn } from "node:child_process";
572
576
  import PocketBase from "pocketbase";
@@ -696,8 +700,8 @@ async function withPocketbase(cwd, fn, creds) {
696
700
  const dir = path4.join(cwd, DATA_DIR);
697
701
  const migrationsDir = path4.join(cwd, MIGRATIONS_DIR);
698
702
  const host = "localhost";
699
- const email3 = creds?.email ?? process4.env.POCKETBASE_SUPERUSER_EMAIL;
700
- const password11 = creds?.password ?? process4.env.POCKETBASE_SUPERUSER_PASSWORD;
703
+ const email3 = creds?.email ?? process5.env.POCKETBASE_SUPERUSER_EMAIL;
704
+ const password11 = creds?.password ?? process5.env.POCKETBASE_SUPERUSER_PASSWORD;
701
705
  if (!fs5.existsSync(dir)) {
702
706
  throw new Error("PocketBase data directory does not exist");
703
707
  }
@@ -791,8 +795,8 @@ function pocketbaseVersion() {
791
795
  return pkg.version;
792
796
  }
793
797
  async function ensureSuperuser(cwd) {
794
- const email3 = process4.env.POCKETBASE_SUPERUSER_EMAIL;
795
- const password11 = process4.env.POCKETBASE_SUPERUSER_PASSWORD;
798
+ const email3 = process5.env.POCKETBASE_SUPERUSER_EMAIL;
799
+ const password11 = process5.env.POCKETBASE_SUPERUSER_PASSWORD;
796
800
  if (!email3 || !password11) return;
797
801
  const dir = path4.join(cwd, DATA_DIR);
798
802
  if (!fs5.existsSync(dir)) return;
@@ -1339,7 +1343,7 @@ async function blessProject(cwdArg, options) {
1339
1343
  {
1340
1344
  onCancel: () => {
1341
1345
  p4.cancel("Operation cancelled.");
1342
- process5.exit(0);
1346
+ process6.exit(0);
1343
1347
  }
1344
1348
  }
1345
1349
  );
@@ -1556,7 +1560,7 @@ function summarize(names) {
1556
1560
  return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
1557
1561
  }
1558
1562
  function printNextSteps(projectPath, packageManager) {
1559
- const relative = path11.relative(process5.cwd(), projectPath);
1563
+ const relative = path11.relative(process6.cwd(), projectPath);
1560
1564
  const pm = packageManager ?? getUserAgent() ?? "npm";
1561
1565
  const nextSteps = [];
1562
1566
  if (relative !== "") {
@@ -1582,7 +1586,7 @@ function printNextSteps(projectPath, packageManager) {
1582
1586
  // src/commands/create.ts
1583
1587
  import fs14 from "node:fs";
1584
1588
  import path12 from "node:path";
1585
- import process6 from "node:process";
1589
+ import process7 from "node:process";
1586
1590
  import * as v3 from "valibot";
1587
1591
  import { Command as Command3 } from "commander";
1588
1592
  import * as p5 from "@clack/prompts";
@@ -1604,7 +1608,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
1604
1608
  projectPath,
1605
1609
  options
1606
1610
  );
1607
- const relative = path12.relative(process6.cwd(), directory);
1611
+ const relative = path12.relative(process7.cwd(), directory);
1608
1612
  const pm = packageManager ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
1609
1613
  const nextSteps = [];
1610
1614
  if (relative !== "") {
@@ -1643,7 +1647,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
1643
1647
  async function createProject(cwdArg, options) {
1644
1648
  const onCancel2 = () => {
1645
1649
  p5.cancel("Operation cancelled.");
1646
- process6.exit(0);
1650
+ process7.exit(0);
1647
1651
  };
1648
1652
  const template = findProjectTemplate(options.template ?? DEFAULT_TEMPLATE);
1649
1653
  if (!template.backend && (options.email || options.password)) {
@@ -1780,7 +1784,7 @@ async function runPattern(slug2, argv, input, report4) {
1780
1784
  throw new Error(`Unknown pattern: ${slug2}`);
1781
1785
  }
1782
1786
  const { workspaceRootDir, features } = await getWorkspace();
1783
- const log43 = p6.taskLog({ title: report4.task.title });
1787
+ const log45 = p6.taskLog({ title: report4.task.title });
1784
1788
  let result;
1785
1789
  try {
1786
1790
  result = await pattern.generate({
@@ -1800,11 +1804,11 @@ async function runPattern(slug2, argv, input, report4) {
1800
1804
  });
1801
1805
  return collections2;
1802
1806
  },
1803
- logger: { info: (message) => log43.message(message) }
1807
+ logger: { info: (message) => log45.message(message) }
1804
1808
  });
1805
- log43.success(report4.task.success);
1809
+ log45.success(report4.task.success);
1806
1810
  } catch (e) {
1807
- log43.error(report4.task.error);
1811
+ log45.error(report4.task.error);
1808
1812
  throw e;
1809
1813
  }
1810
1814
  const rel = (f) => toRelative(workspaceRootDir, f);
@@ -1847,6 +1851,7 @@ import pc4 from "picocolors";
1847
1851
  import fs15 from "node:fs";
1848
1852
  import os from "node:os";
1849
1853
  import path14 from "node:path";
1854
+ import process8 from "node:process";
1850
1855
  var CONFIG_DIR = path14.join(os.homedir(), ".vela");
1851
1856
  var CONFIG_PATH = path14.join(CONFIG_DIR, "config.json");
1852
1857
  function readConfig() {
@@ -1864,12 +1869,17 @@ function writeConfig(config) {
1864
1869
  function clearConfig() {
1865
1870
  if (fs15.existsSync(CONFIG_PATH)) fs15.unlinkSync(CONFIG_PATH);
1866
1871
  }
1872
+ function readApiKey() {
1873
+ const fromEnv = process8.env.VELA_API_KEY?.trim();
1874
+ if (fromEnv) return fromEnv;
1875
+ return readConfig()?.apiKey ?? null;
1876
+ }
1867
1877
  function requireApiKey() {
1868
- const config = readConfig();
1869
- if (!config?.apiKey) {
1870
- throw new Error("Not logged in. Run `vela login` to login.");
1878
+ const apiKey = readApiKey();
1879
+ if (!apiKey) {
1880
+ throw new Error("Not logged in. Run `vela login` to login, or set VELA_API_KEY.");
1871
1881
  }
1872
- return config.apiKey;
1882
+ return apiKey;
1873
1883
  }
1874
1884
 
1875
1885
  // src/lib/project-config.ts
@@ -2415,7 +2425,7 @@ var migration = new Command8("migration").description("generate a migration for
2415
2425
  var generate = new Command9("generate").description("generate scaffolding for database models and forms").configureHelp(helpConfig).addCommand(form).addCommand(schema).addCommand(resource).addCommand(scaffold).addCommand(migration);
2416
2426
 
2417
2427
  // src/commands/enable.ts
2418
- import { Command as Command23 } from "commander";
2428
+ import { Command as Command24 } from "commander";
2419
2429
 
2420
2430
  // src/commands/enable/auth.ts
2421
2431
  import { Command as Command10 } from "commander";
@@ -2574,7 +2584,7 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
2574
2584
  );
2575
2585
 
2576
2586
  // src/commands/enable/payments.ts
2577
- import process7 from "node:process";
2587
+ import process9 from "node:process";
2578
2588
  import { Command as Command16 } from "commander";
2579
2589
  import * as p14 from "@clack/prompts";
2580
2590
  var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
@@ -2620,12 +2630,12 @@ async function resolveProvider(value, source) {
2620
2630
  });
2621
2631
  if (p14.isCancel(selected)) {
2622
2632
  p14.cancel("Operation cancelled.");
2623
- process7.exit(0);
2633
+ process9.exit(0);
2624
2634
  }
2625
2635
  return selected;
2626
2636
  }
2627
2637
  async function ensureWebhookSecret() {
2628
- const existing = process7.env.STRIPE_WEBHOOK_SECRET;
2638
+ const existing = process9.env.STRIPE_WEBHOOK_SECRET;
2629
2639
  if (existing) return existing;
2630
2640
  p14.note(
2631
2641
  [
@@ -2653,12 +2663,12 @@ async function ensurePriceId() {
2653
2663
  });
2654
2664
  if (p14.isCancel(value)) {
2655
2665
  p14.cancel("Operation cancelled.");
2656
- process7.exit(0);
2666
+ process9.exit(0);
2657
2667
  }
2658
2668
  return (value ?? "").trim();
2659
2669
  }
2660
2670
  async function ensureKey(envVar, message) {
2661
- const existing = process7.env[envVar];
2671
+ const existing = process9.env[envVar];
2662
2672
  if (existing) return existing;
2663
2673
  return promptPassword(message);
2664
2674
  }
@@ -2669,7 +2679,7 @@ async function promptPassword(message) {
2669
2679
  });
2670
2680
  if (p14.isCancel(value)) {
2671
2681
  p14.cancel("Operation cancelled.");
2672
- process7.exit(0);
2682
+ process9.exit(0);
2673
2683
  }
2674
2684
  return value;
2675
2685
  }
@@ -2700,14 +2710,40 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
2700
2710
  )
2701
2711
  );
2702
2712
 
2703
- // src/commands/enable/s3.ts
2704
- import process10 from "node:process";
2713
+ // src/commands/enable/notifications.ts
2705
2714
  import { Command as Command18 } from "commander";
2715
+ var notifications = new Command18("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).configureHelp(helpConfig).action(
2716
+ (_opts, cmd) => runCommand(
2717
+ () => runPattern(
2718
+ "enable-notifications",
2719
+ cmd.args,
2720
+ {},
2721
+ {
2722
+ summary: "Enabled notifications.",
2723
+ nextSteps: [
2724
+ "Run `vela dev` and open any (app) page to see the bell in the header; /notifications lists them all.",
2725
+ "Send one from server code with `notify(locals.admin, userId, { title, body })` from $lib/server/notifications.",
2726
+ "Customize the bell in src/lib/components/notifications-bell.svelte and the page in src/routes/(app)/notifications/."
2727
+ ],
2728
+ task: {
2729
+ title: "Enabling notifications",
2730
+ success: "Enabled notifications",
2731
+ error: "Failed to enable notifications"
2732
+ }
2733
+ }
2734
+ ),
2735
+ "Failed to enable notifications."
2736
+ )
2737
+ );
2738
+
2739
+ // src/commands/enable/s3.ts
2740
+ import process12 from "node:process";
2741
+ import { Command as Command19 } from "commander";
2706
2742
  import * as p17 from "@clack/prompts";
2707
2743
  import pc8 from "picocolors";
2708
2744
 
2709
2745
  // src/lib/server-command.ts
2710
- import process9 from "node:process";
2746
+ import process11 from "node:process";
2711
2747
  import * as v5 from "valibot";
2712
2748
  import * as p15 from "@clack/prompts";
2713
2749
  import pc5 from "picocolors";
@@ -2865,30 +2901,18 @@ function releaseId(date = /* @__PURE__ */ new Date()) {
2865
2901
  return date.toISOString().replace(/[-:]/g, "").replace(/\.\d+Z$/, "Z");
2866
2902
  }
2867
2903
 
2868
- // src/lib/ssh-options.ts
2869
- import * as v4 from "valibot";
2870
- var SSH_OPTION_SCHEMA = {
2871
- identity: v4.optional(v4.string()),
2872
- sshPort: v4.optional(v4.string()),
2873
- acceptHostKeys: v4.optional(v4.boolean())
2874
- };
2875
- function addSshOptions(command) {
2876
- return command.option("-i, --identity <file>", "SSH private key to authenticate with").option("--ssh-port <port>", "SSH port").option("--accept-host-keys", "trust an unknown host key on first connect (CI)");
2877
- }
2878
- function sshOptionsFrom(options) {
2879
- return {
2880
- identityFile: options.identity,
2881
- port: options.sshPort ? Number(options.sshPort) : void 0,
2882
- acceptNewHostKeys: options.acceptHostKeys
2883
- };
2884
- }
2904
+ // src/lib/artifact.ts
2905
+ import fs20 from "node:fs";
2906
+ import path19 from "node:path";
2907
+ import { detect as detect4 } from "package-manager-detector";
2908
+ import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
2885
2909
 
2886
2910
  // src/lib/ssh.ts
2887
2911
  import fs19 from "node:fs";
2888
2912
  import os2 from "node:os";
2889
2913
  import path18 from "node:path";
2890
2914
  import crypto2 from "node:crypto";
2891
- import process8 from "node:process";
2915
+ import process10 from "node:process";
2892
2916
  import { spawn as spawn2 } from "node:child_process";
2893
2917
  var RemoteCommandError = class extends Error {
2894
2918
  exitCode;
@@ -3166,17 +3190,17 @@ function spawnCapture(command, args, opts = {}) {
3166
3190
  const child = spawn2(command, args, {
3167
3191
  stdio,
3168
3192
  cwd: opts.cwd,
3169
- env: opts.env ? { ...process8.env, ...opts.env } : void 0
3193
+ env: opts.env ? { ...process10.env, ...opts.env } : void 0
3170
3194
  });
3171
3195
  let stdout = "";
3172
3196
  let stderr = "";
3173
3197
  child.stdout?.on("data", (chunk) => {
3174
3198
  stdout += chunk;
3175
- if (opts.streamStdout) process8.stdout.write(chunk);
3199
+ if (opts.streamStdout) process10.stdout.write(chunk);
3176
3200
  });
3177
3201
  child.stderr?.on("data", (chunk) => {
3178
3202
  stderr += chunk;
3179
- if (opts.stream) process8.stderr.write(chunk);
3203
+ if (opts.stream) process10.stderr.write(chunk);
3180
3204
  });
3181
3205
  child.on("error", reject);
3182
3206
  child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
@@ -3186,15 +3210,108 @@ function spawnCapture(command, args, opts = {}) {
3186
3210
  });
3187
3211
  }
3188
3212
 
3213
+ // src/lib/artifact.ts
3214
+ var DEFAULT_OUTPUT_DIR = "build";
3215
+ var BuildError = class extends Error {
3216
+ };
3217
+ async function runBuild(cwd, buildCommand, env2) {
3218
+ if (buildCommand) {
3219
+ const result2 = await spawnCapture("bash", ["-lc", buildCommand], {
3220
+ cwd,
3221
+ stream: true,
3222
+ streamStdout: true,
3223
+ env: env2
3224
+ });
3225
+ if (result2.exitCode !== 0)
3226
+ throw new BuildError(`\`${buildCommand}\` exited ${result2.exitCode}.`);
3227
+ return;
3228
+ }
3229
+ const pm = (await detect4({ cwd }))?.name ?? "npm";
3230
+ const resolved = resolveCommand4(pm, "run", ["build"]);
3231
+ if (!resolved) throw new BuildError(`Could not work out how to run a build with ${pm}.`);
3232
+ const result = await spawnCapture(resolved.command, resolved.args, {
3233
+ cwd,
3234
+ stream: true,
3235
+ streamStdout: true,
3236
+ env: env2
3237
+ });
3238
+ if (result.exitCode !== 0) {
3239
+ throw new BuildError(
3240
+ `\`${resolved.command} ${resolved.args.join(" ")}\` exited ${result.exitCode}.`
3241
+ );
3242
+ }
3243
+ }
3244
+ function collectArtifact(cwd, config = {}) {
3245
+ const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
3246
+ const entries = [];
3247
+ const add2 = (rel, remoteDir = "") => {
3248
+ const localPath = path19.join(cwd, rel);
3249
+ if (fs20.existsSync(localPath)) entries.push({ localPath, remoteDir });
3250
+ };
3251
+ const buildPath = path19.join(cwd, outputDir);
3252
+ if (!fs20.existsSync(path19.join(buildPath, "index.js"))) {
3253
+ throw new BuildError(
3254
+ `No ${outputDir}/index.js after the build.
3255
+
3256
+ Deploying to a server needs @sveltejs/adapter-node. Install it and set it as
3257
+ the adapter in your Vite or Svelte config, then build again.`
3258
+ );
3259
+ }
3260
+ entries.push({ localPath: buildPath, remoteDir: "" });
3261
+ add2("package.json");
3262
+ add2("package-lock.json");
3263
+ add2(".npmrc");
3264
+ add2(MIGRATIONS_DIR);
3265
+ const hooks = path19.join(cwd, DATA_DIR, "hooks");
3266
+ if (fs20.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
3267
+ for (const extra of config.include ?? []) add2(extra);
3268
+ return entries;
3269
+ }
3270
+ async function gitSha(cwd) {
3271
+ const result = await spawnCapture("git", ["rev-parse", "HEAD"], { cwd });
3272
+ return result.exitCode === 0 ? result.stdout.trim() : "";
3273
+ }
3274
+ async function currentBranch(cwd) {
3275
+ const result = await spawnCapture("git", ["rev-parse", "--abbrev-ref", "HEAD"], { cwd });
3276
+ const branch = result.exitCode === 0 ? result.stdout.trim() : "";
3277
+ if (!branch || branch === "HEAD") {
3278
+ throw new Error(
3279
+ `No branch is checked out here${branch === "HEAD" ? " (detached HEAD)" : ""}, so \`-t preview\` has nothing to name.
3280
+
3281
+ Name it: \`-t preview:<branch>\`.`
3282
+ );
3283
+ }
3284
+ return branch;
3285
+ }
3286
+
3287
+ // src/lib/ssh-options.ts
3288
+ import * as v4 from "valibot";
3289
+ var SSH_OPTION_SCHEMA = {
3290
+ identity: v4.optional(v4.string()),
3291
+ sshPort: v4.optional(v4.string()),
3292
+ acceptHostKeys: v4.optional(v4.boolean())
3293
+ };
3294
+ function addSshOptions(command) {
3295
+ return command.option("-i, --identity <file>", "SSH private key to authenticate with").option("--ssh-port <port>", "SSH port").option("--accept-host-keys", "trust an unknown host key on first connect (CI)");
3296
+ }
3297
+ function sshOptionsFrom(options) {
3298
+ return {
3299
+ identityFile: options.identity,
3300
+ port: options.sshPort ? Number(options.sshPort) : void 0,
3301
+ acceptNewHostKeys: options.acceptHostKeys
3302
+ };
3303
+ }
3304
+
3189
3305
  // src/lib/remote.ts
3190
- import path19 from "node:path";
3306
+ import path20 from "node:path";
3191
3307
  var VELA_ROOT = "/var/lib/vela";
3192
3308
  var VELA_ETC = "/etc/vela";
3193
3309
  var VELA_USER = "vela";
3194
3310
  var SCRIPTS_DIR = `${VELA_ROOT}/scripts`;
3195
3311
  var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
3312
+ var ORIGIN_FILE = `${VELA_ETC}/origin.json`;
3196
3313
  function serverTemplatesDir() {
3197
- return path19.join(templatesDir(), "server");
3314
+ return path20.join(templatesDir(), "server");
3198
3315
  }
3199
3316
  async function syncServerScripts(session) {
3200
3317
  await session.script(`mkdir -p "$1" && chmod 0755 "$1"`, { args: [SCRIPTS_DIR] });
@@ -3226,6 +3343,20 @@ async function readServerInfo(session) {
3226
3343
  return null;
3227
3344
  }
3228
3345
  }
3346
+ async function readServerIdentity(session) {
3347
+ const raw = await session.readFile(ORIGIN_FILE);
3348
+ if (!raw) return null;
3349
+ try {
3350
+ const parsed = JSON.parse(raw);
3351
+ if (!parsed.serverId || !parsed.originHost || !parsed.token) return null;
3352
+ return { serverId: parsed.serverId, originHost: parsed.originHost, token: parsed.token };
3353
+ } catch {
3354
+ return null;
3355
+ }
3356
+ }
3357
+ async function writeServerIdentity(session, identity) {
3358
+ await session.writeFile(ORIGIN_FILE, JSON.stringify(identity, null, 2) + "\n", "0600");
3359
+ }
3229
3360
  async function requireProvisioned(session) {
3230
3361
  const info = await readServerInfo(session);
3231
3362
  if (!info) {
@@ -3257,12 +3388,13 @@ var remotePaths = {
3257
3388
  env: (instance) => `${VELA_ETC}/apps/${instance}/env`,
3258
3389
  runtimeEnv: (instance) => `${VELA_ETC}/apps/${instance}/runtime.env`,
3259
3390
  caddy: (instance) => `${VELA_ETC}/caddy/${instance}.caddy`,
3391
+ route: (instance) => `${VELA_ETC}/caddy/routes/${instance}.route`,
3260
3392
  webUnit: (instance) => `vela-web@${instance}.service`,
3261
3393
  pbUnit: (instance) => `vela-pb@${instance}.service`
3262
3394
  };
3263
3395
 
3264
3396
  // src/lib/remote-env.ts
3265
- import fs20 from "node:fs";
3397
+ import fs21 from "node:fs";
3266
3398
  import dotenv from "dotenv";
3267
3399
  var KEY_PATTERN = /^[A-Za-z_][A-Za-z0-9_]*$/;
3268
3400
  function isValidKey(key) {
@@ -3310,7 +3442,7 @@ function quote(value) {
3310
3442
  return `"${escaped}"`;
3311
3443
  }
3312
3444
  function readLocalEnvFile(file) {
3313
- const parsed = dotenv.parse(fs20.readFileSync(file));
3445
+ const parsed = dotenv.parse(fs21.readFileSync(file));
3314
3446
  const result = {};
3315
3447
  for (const [key, value] of Object.entries(parsed)) {
3316
3448
  if (isValidKey(key)) result[key] = value;
@@ -3367,6 +3499,15 @@ function parseTarget(raw, fallback) {
3367
3499
  if (!value) {
3368
3500
  return fallback === "local" ? { kind: "local" } : production();
3369
3501
  }
3502
+ const lower = value.toLowerCase();
3503
+ if (lower === PREVIEW || lower.startsWith(`${PREVIEW}:`)) {
3504
+ const branch = value.slice(PREVIEW.length + 1) || void 0;
3505
+ return {
3506
+ kind: "preview",
3507
+ branch,
3508
+ envTag: branch ? branchToEnvTag(branch) : PREVIEW
3509
+ };
3510
+ }
3370
3511
  if (SERVER_SHAPED.test(value)) {
3371
3512
  throw new TargetError(
3372
3513
  `${value} looks like a server, and ${bold("-t")} now selects a target rather than a machine.
@@ -3375,18 +3516,7 @@ Targets are ${bold("local")}, ${bold("production")}, or a name you choose such a
3375
3516
  To point a target at a server, pass ${bold("--server")} on \`vela deploy\`.`
3376
3517
  );
3377
3518
  }
3378
- const lower = value.toLowerCase();
3379
3519
  if (lower === LOCAL_TARGET) return { kind: "local" };
3380
- if (lower === PREVIEW || lower.startsWith(`${PREVIEW}:`)) {
3381
- const branch = lower.slice(PREVIEW.length + 1) || void 0;
3382
- return {
3383
- kind: "preview",
3384
- branch,
3385
- // Held for when previews are built, so the grammar and the instance
3386
- // naming cannot drift apart in the meantime.
3387
- envTag: branch ? branchToEnvTag(branch) : PREVIEW
3388
- };
3389
- }
3390
3520
  if (value.includes(":")) {
3391
3521
  throw new TargetError(
3392
3522
  `${value} is not a target. Only ${bold("preview")} takes a \`:branch\` suffix.`
@@ -3401,6 +3531,9 @@ Use lowercase letters, digits and single dashes, such as ${bold("staging")}.`
3401
3531
  }
3402
3532
  return { kind: "remote", name: lower, envTag: normalizeEnvTag(lower) };
3403
3533
  }
3534
+ function bindingKey(target) {
3535
+ return target.kind === "preview" ? PREVIEW : target.envTag;
3536
+ }
3404
3537
  function production() {
3405
3538
  return { kind: "remote", name: PRODUCTION_TARGET, envTag: PROD_ENV };
3406
3539
  }
@@ -3430,17 +3563,13 @@ function addTargetOptions(command, fallback) {
3430
3563
  }
3431
3564
  async function withTarget(raw, handlers, run = {}) {
3432
3565
  const options = parseOptions(OptionsSchema, raw);
3433
- const target = parseTarget(options.target, "production");
3566
+ let target = parseTarget(options.target, "production");
3434
3567
  const label4 = run.label ? `vela ${run.label}` : "this command";
3435
- if (target.kind === "preview") {
3436
- throw new Error(
3437
- `Preview targets are not supported yet.
3438
-
3439
- \`${describeTarget(target)}\` parses, but nothing deploys it: previews need wildcard
3440
- DNS and certificates that \`vela provision\` does not set up yet.`
3441
- );
3442
- }
3443
3568
  const { workspaceRootDir } = await getWorkspace();
3569
+ if (target.kind === "preview" && !target.branch) {
3570
+ const branch = await currentBranch(workspaceRootDir);
3571
+ target = { kind: "preview", branch, envTag: branchToEnvTag(branch) };
3572
+ }
3444
3573
  const config = await loadDeployConfig(workspaceRootDir);
3445
3574
  const app = resolveAppIdentity(workspaceRootDir, {
3446
3575
  ...config,
@@ -3484,30 +3613,32 @@ ${run.localHint}` : "")
3484
3613
  session,
3485
3614
  instance: instanceId(app.appId, target.envTag),
3486
3615
  envTag: target.envTag,
3487
- targetName: target.name,
3616
+ targetName: describeTarget(target),
3617
+ target,
3488
3618
  server: binding.server,
3489
3619
  binding
3490
3620
  });
3491
3621
  });
3492
3622
  }
3493
3623
  async function ensureBinding(workspaceRootDir, target, request = {}) {
3494
- const existing = readBinding(workspaceRootDir, target.envTag);
3624
+ const key = bindingKey(target);
3625
+ const existing = readBinding(workspaceRootDir, key);
3495
3626
  const moving = Boolean(request.server && existing && existing.server !== request.server);
3496
3627
  let server = request.server ?? existing?.server;
3497
3628
  if (!server) {
3498
3629
  server = await promptServer(target);
3499
3630
  }
3500
- let domain = request.domain ?? existing?.domain;
3501
- if (!domain && request.askDomain && !request.server) {
3631
+ let domain = target.kind === "preview" ? void 0 : request.domain ?? existing?.domain;
3632
+ if (!domain && request.askDomain && !request.server && target.kind !== "preview") {
3502
3633
  domain = await promptDomain(target);
3503
3634
  }
3504
3635
  const binding = domain ? { server, domain } : { server };
3505
3636
  if (!existing || existing.server !== server || existing.domain !== domain) {
3506
- writeBinding(workspaceRootDir, target.envTag, binding);
3637
+ writeBinding(workspaceRootDir, key, binding);
3507
3638
  }
3508
3639
  if (moving) {
3509
3640
  p15.log.warn(
3510
- `${pc5.cyan(target.name)} now points at ${pc5.cyan(server)}.
3641
+ `${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
3511
3642
 
3512
3643
  Whatever is running on ${existing.server} is left there, and this project can no
3513
3644
  longer reach it. Remove it there first if that was not intended.`
@@ -3515,36 +3646,42 @@ longer reach it. Remove it there first if that was not intended.`
3515
3646
  }
3516
3647
  return binding;
3517
3648
  }
3649
+ function bindingName(target) {
3650
+ return target.kind === "preview" ? "previews" : target.name;
3651
+ }
3518
3652
  async function promptServer(target) {
3519
- if (!process9.stdout.isTTY || process9.env.CI) {
3653
+ const name = bindingName(target);
3654
+ if (!process11.stdout.isTTY || process11.env.CI) {
3520
3655
  throw new Error(
3521
- `${target.name} is not bound to a server yet, and there is no terminal to ask on.
3656
+ `${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
3522
3657
 
3523
3658
  Pass ${pc5.cyan("--server user@host")}, or run the command once from your own machine
3524
3659
  and commit ${pc5.cyan(".vela/project.json")}.`
3525
3660
  );
3526
3661
  }
3527
- p15.log.info(`${pc5.cyan(target.name)} is not bound to a server yet.`);
3662
+ p15.log.info(
3663
+ `${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
3664
+ );
3528
3665
  const value = await p15.text({
3529
- message: `Which server should ${target.name} run on?`,
3666
+ message: `Which server should ${name} run on?`,
3530
3667
  placeholder: "root@203.0.113.10",
3531
3668
  validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
3532
3669
  });
3533
3670
  if (p15.isCancel(value)) {
3534
3671
  p15.cancel("Operation cancelled.");
3535
- process9.exit(0);
3672
+ process11.exit(0);
3536
3673
  }
3537
3674
  return value.trim();
3538
3675
  }
3539
3676
  async function promptDomain(target) {
3540
- if (!process9.stdout.isTTY || process9.env.CI) return void 0;
3677
+ if (!process11.stdout.isTTY || process11.env.CI) return void 0;
3541
3678
  const value = await p15.text({
3542
3679
  message: `Which hostname should ${target.name} be served on?`,
3543
3680
  placeholder: "example.com \u2014 leave blank to decide later"
3544
3681
  });
3545
3682
  if (p15.isCancel(value)) {
3546
3683
  p15.cancel("Operation cancelled.");
3547
- process9.exit(0);
3684
+ process11.exit(0);
3548
3685
  }
3549
3686
  return value.trim() || void 0;
3550
3687
  }
@@ -3580,7 +3717,7 @@ async function withServerSession(raw, fn) {
3580
3717
  if (!server) {
3581
3718
  const { workspaceRootDir } = await getWorkspace();
3582
3719
  const target = parseTarget(options.target, "production");
3583
- if (target.kind !== "remote") {
3720
+ if (target.kind === "local") {
3584
3721
  throw new Error(`${describeTarget(target)} does not run on a server.`);
3585
3722
  }
3586
3723
  server = (await ensureBinding(workspaceRootDir, target, { server: options.server })).server;
@@ -3600,17 +3737,17 @@ function envFilePath(workspaceRootDir) {
3600
3737
  import pc7 from "picocolors";
3601
3738
 
3602
3739
  // src/lib/local-env.ts
3603
- import fs21 from "node:fs";
3740
+ import fs22 from "node:fs";
3604
3741
  import * as p16 from "@clack/prompts";
3605
3742
  import pc6 from "picocolors";
3606
3743
  function readLocalEnv(envFile) {
3607
- if (!fs21.existsSync(envFile)) return {};
3744
+ if (!fs22.existsSync(envFile)) return {};
3608
3745
  return readLocalEnvFile(envFile);
3609
3746
  }
3610
3747
  function editLocalEnv(envFile, edit) {
3611
- const before = fs21.existsSync(envFile) ? fs21.readFileSync(envFile, "utf8") : "";
3748
+ const before = fs22.existsSync(envFile) ? fs22.readFileSync(envFile, "utf8") : "";
3612
3749
  const after = edit(before);
3613
- if (after !== before) fs21.writeFileSync(envFile, after);
3750
+ if (after !== before) fs22.writeFileSync(envFile, after);
3614
3751
  }
3615
3752
  function setLocalEnv(envFile, key, value) {
3616
3753
  editLocalEnv(envFile, (content) => upsertEnvVar(content, key, value));
@@ -3742,8 +3879,8 @@ Set ${pc7.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc7.cyan("POCKETBASE_SUPERUS
3742
3879
  }
3743
3880
 
3744
3881
  // src/lib/s3-settings.ts
3745
- import fs22 from "node:fs";
3746
- import path20 from "node:path";
3882
+ import fs23 from "node:fs";
3883
+ import path21 from "node:path";
3747
3884
  var VIRTUAL_HOSTED = [/\.amazonaws\.com$/i, /\.r2\.cloudflarestorage\.com$/i];
3748
3885
  function defaultForcePathStyle(endpoint) {
3749
3886
  let host;
@@ -3781,25 +3918,25 @@ async function hasLocalUploads(session, instance, workspaceRootDir) {
3781
3918
  });
3782
3919
  return result.stdout.trim().length > 0;
3783
3920
  }
3784
- return hasFile(path20.join(workspaceRootDir, DATA_DIR, "storage"));
3921
+ return hasFile(path21.join(workspaceRootDir, DATA_DIR, "storage"));
3785
3922
  }
3786
3923
  function hasFile(dir) {
3787
3924
  let entries;
3788
3925
  try {
3789
- entries = fs22.readdirSync(dir, { withFileTypes: true });
3926
+ entries = fs23.readdirSync(dir, { withFileTypes: true });
3790
3927
  } catch {
3791
3928
  return false;
3792
3929
  }
3793
3930
  for (const entry of entries) {
3794
3931
  if (entry.isFile()) return true;
3795
- if (entry.isDirectory() && hasFile(path20.join(dir, entry.name))) return true;
3932
+ if (entry.isDirectory() && hasFile(path21.join(dir, entry.name))) return true;
3796
3933
  }
3797
3934
  return false;
3798
3935
  }
3799
3936
 
3800
3937
  // src/commands/enable/s3.ts
3801
3938
  var s3 = addTargetOptions(
3802
- new Command18("s3").description("enable S3 file storage").option("--backups", "configure where backups are kept, not where uploads go").option("--endpoint <url>", "S3 endpoint URL").option("--bucket <name>", "S3 bucket name").option("--region <region>", "S3 region").option("--access-key <key>", "S3 access key").option("--secret <secret>", "S3 secret key \u2014 prefer VELA_S3_SECRET").option("--force-path-style", "address the bucket in the path (MinIO, Ceph)").option("--no-force-path-style", "address the bucket as a subdomain (AWS, R2)").option("--force", "enable it even though uploads already exist on disk").configureHelp(helpConfig),
3939
+ new Command19("s3").description("enable S3 file storage").option("--backups", "configure where backups are kept, not where uploads go").option("--endpoint <url>", "S3 endpoint URL").option("--bucket <name>", "S3 bucket name").option("--region <region>", "S3 region").option("--access-key <key>", "S3 access key").option("--secret <secret>", "S3 secret key \u2014 prefer VELA_S3_SECRET").option("--force-path-style", "address the bucket in the path (MinIO, Ceph)").option("--no-force-path-style", "address the bucket as a subdomain (AWS, R2)").option("--force", "enable it even though uploads already exist on disk").configureHelp(helpConfig),
3803
3940
  "local"
3804
3941
  ).action(
3805
3942
  (raw) => runCommand(() => {
@@ -3865,7 +4002,7 @@ async function promptConfig(options, existing) {
3865
4002
  const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
3866
4003
  const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
3867
4004
  const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
3868
- const secret = options.secret ?? process10.env.VELA_S3_SECRET ?? await password5("S3 secret key");
4005
+ const secret = options.secret ?? process12.env.VELA_S3_SECRET ?? await password5("S3 secret key");
3869
4006
  const forcePathStyle = options.forcePathStyle ?? await confirm3(
3870
4007
  "Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
3871
4008
  defaultForcePathStyle(endpoint)
@@ -3880,7 +4017,7 @@ async function text7(message, initialValue = "") {
3880
4017
  });
3881
4018
  if (p17.isCancel(value)) {
3882
4019
  p17.cancel("Operation cancelled.");
3883
- process10.exit(0);
4020
+ process12.exit(0);
3884
4021
  }
3885
4022
  return value.trim();
3886
4023
  }
@@ -3891,7 +4028,7 @@ async function password5(message) {
3891
4028
  });
3892
4029
  if (p17.isCancel(value)) {
3893
4030
  p17.cancel("Operation cancelled.");
3894
- process10.exit(0);
4031
+ process12.exit(0);
3895
4032
  }
3896
4033
  return value;
3897
4034
  }
@@ -3899,16 +4036,16 @@ async function confirm3(message, initialValue) {
3899
4036
  const value = await p17.confirm({ message, initialValue });
3900
4037
  if (p17.isCancel(value)) {
3901
4038
  p17.cancel("Operation cancelled.");
3902
- process10.exit(0);
4039
+ process12.exit(0);
3903
4040
  }
3904
4041
  return value;
3905
4042
  }
3906
4043
 
3907
4044
  // src/commands/enable/smtp.ts
3908
- import process11 from "node:process";
3909
- import { Command as Command19 } from "commander";
4045
+ import process13 from "node:process";
4046
+ import { Command as Command20 } from "commander";
3910
4047
  import * as p18 from "@clack/prompts";
3911
- var smtp = new Command19("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4048
+ var smtp = new Command20("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
3912
4049
  () => runCommand(async () => {
3913
4050
  const { workspaceRootDir } = await getWorkspace();
3914
4051
  const config = await p18.group(
@@ -3934,7 +4071,7 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
3934
4071
  {
3935
4072
  onCancel: () => {
3936
4073
  p18.cancel("Operation cancelled.");
3937
- process11.exit(0);
4074
+ process13.exit(0);
3938
4075
  }
3939
4076
  }
3940
4077
  );
@@ -3961,11 +4098,11 @@ var smtp = new Command19("smtp").description("configure SMTP for transactional e
3961
4098
  );
3962
4099
 
3963
4100
  // src/commands/enable/cms.ts
3964
- import process12 from "node:process";
3965
- import { Command as Command20 } from "commander";
4101
+ import process14 from "node:process";
4102
+ import { Command as Command21 } from "commander";
3966
4103
  import * as p19 from "@clack/prompts";
3967
4104
  import pc9 from "picocolors";
3968
- var cms = new Command20("cms").description("enable an inline-editing CMS with an admin bar").allowUnknownOption(true).configureHelp(helpConfig).action(
4105
+ var cms = new Command21("cms").description("enable an inline-editing CMS with an admin bar").allowUnknownOption(true).configureHelp(helpConfig).action(
3969
4106
  (_opts, cmd) => runCommand(async () => {
3970
4107
  if (!hasBackend()) {
3971
4108
  p19.log.error(
@@ -3975,7 +4112,7 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
3975
4112
  );
3976
4113
  p19.log.message();
3977
4114
  p19.cancel("Operation failed.");
3978
- process12.exitCode = 1;
4115
+ process14.exitCode = 1;
3979
4116
  return;
3980
4117
  }
3981
4118
  await runPattern(
@@ -4000,8 +4137,8 @@ Run ${pc9.cyan("vela bless")} to add a backend first.`
4000
4137
  );
4001
4138
 
4002
4139
  // src/commands/enable/blog.ts
4003
- import { Command as Command21 } from "commander";
4004
- var blog = new Command21("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).configureHelp(helpConfig).action(
4140
+ import { Command as Command22 } from "commander";
4141
+ var blog = new Command22("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).configureHelp(helpConfig).action(
4005
4142
  (_opts, cmd) => runCommand(
4006
4143
  () => runPattern(
4007
4144
  "enable-blog",
@@ -4026,8 +4163,8 @@ var blog = new Command21("blog").description("enable an mdsvex blog with posts,
4026
4163
  );
4027
4164
 
4028
4165
  // src/commands/enable/content-negotiation.ts
4029
- import { Command as Command22 } from "commander";
4030
- var contentNegotiation = new Command22("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).configureHelp(helpConfig).action(
4166
+ import { Command as Command23 } from "commander";
4167
+ var contentNegotiation = new Command23("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).configureHelp(helpConfig).action(
4031
4168
  (_opts, cmd) => runCommand(
4032
4169
  () => runPattern(
4033
4170
  "enable-content-negotiation",
@@ -4051,16 +4188,16 @@ var contentNegotiation = new Command22("content-negotiation").description("enabl
4051
4188
  );
4052
4189
 
4053
4190
  // src/commands/enable.ts
4054
- var enable = new Command23("enable").description("enable features").configureHelp(helpConfig).addCommand(auth).addCommand(api).addCommand(apiKeys).addCommand(backend).addCommand(contentNegotiation).addCommand(i18n).addCommand(teams).addCommand(payments).addCommand(subscriptions).addCommand(s3).addCommand(smtp).addCommand(cms).addCommand(blog);
4191
+ var enable = new Command24("enable").description("enable features").configureHelp(helpConfig).addCommand(auth).addCommand(api).addCommand(apiKeys).addCommand(backend).addCommand(contentNegotiation).addCommand(i18n).addCommand(teams).addCommand(payments).addCommand(subscriptions).addCommand(notifications).addCommand(s3).addCommand(smtp).addCommand(cms).addCommand(blog);
4055
4192
 
4056
4193
  // src/commands/disable.ts
4057
- import { Command as Command34 } from "commander";
4194
+ import { Command as Command35 } from "commander";
4058
4195
 
4059
4196
  // src/commands/disable/auth.ts
4060
- import { Command as Command24 } from "commander";
4197
+ import { Command as Command25 } from "commander";
4061
4198
 
4062
4199
  // src/commands/disable/_shared.ts
4063
- import process13 from "node:process";
4200
+ import process15 from "node:process";
4064
4201
  import * as p20 from "@clack/prompts";
4065
4202
  async function runDisable(opts, flags, cmdArgs) {
4066
4203
  if (!flags.yes) {
@@ -4070,14 +4207,14 @@ async function runDisable(opts, flags, cmdArgs) {
4070
4207
  });
4071
4208
  if (p20.isCancel(ok) || !ok) {
4072
4209
  p20.cancel("Operation cancelled.");
4073
- process13.exit(0);
4210
+ process15.exit(0);
4074
4211
  }
4075
4212
  }
4076
4213
  await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
4077
4214
  }
4078
4215
 
4079
4216
  // src/commands/disable/auth.ts
4080
- var auth2 = new Command24("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4217
+ var auth2 = new Command25("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4081
4218
  (opts, cmd) => runCommand(
4082
4219
  () => runDisable(
4083
4220
  {
@@ -4103,8 +4240,8 @@ var auth2 = new Command24("auth").description("disable authentication").option("
4103
4240
  );
4104
4241
 
4105
4242
  // src/commands/disable/api.ts
4106
- import { Command as Command25 } from "commander";
4107
- var api2 = new Command25("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4243
+ import { Command as Command26 } from "commander";
4244
+ var api2 = new Command26("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4108
4245
  (opts, cmd) => runCommand(
4109
4246
  () => runDisable(
4110
4247
  {
@@ -4127,8 +4264,8 @@ var api2 = new Command25("api").description("disable the REST API").option("-y,
4127
4264
  );
4128
4265
 
4129
4266
  // src/commands/disable/api-keys.ts
4130
- import { Command as Command26 } from "commander";
4131
- var apiKeys2 = new Command26("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4267
+ import { Command as Command27 } from "commander";
4268
+ var apiKeys2 = new Command27("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4132
4269
  (opts, cmd) => runCommand(
4133
4270
  () => runDisable(
4134
4271
  {
@@ -4151,8 +4288,8 @@ var apiKeys2 = new Command26("api-keys").description("disable API key management
4151
4288
  );
4152
4289
 
4153
4290
  // src/commands/disable/backend.ts
4154
- import { Command as Command27 } from "commander";
4155
- var backend2 = new Command27("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4291
+ import { Command as Command28 } from "commander";
4292
+ var backend2 = new Command28("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4156
4293
  (opts, cmd) => runCommand(
4157
4294
  () => runDisable(
4158
4295
  {
@@ -4175,8 +4312,8 @@ var backend2 = new Command27("backend").description("disable the PocketBase back
4175
4312
  );
4176
4313
 
4177
4314
  // src/commands/disable/content-negotiation.ts
4178
- import { Command as Command28 } from "commander";
4179
- var contentNegotiation2 = new Command28("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4315
+ import { Command as Command29 } from "commander";
4316
+ var contentNegotiation2 = new Command29("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4180
4317
  (opts, cmd) => runCommand(
4181
4318
  () => runDisable(
4182
4319
  {
@@ -4199,8 +4336,8 @@ var contentNegotiation2 = new Command28("content-negotiation").description("disa
4199
4336
  );
4200
4337
 
4201
4338
  // src/commands/disable/i18n.ts
4202
- import { Command as Command29 } from "commander";
4203
- var i18n2 = new Command29("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4339
+ import { Command as Command30 } from "commander";
4340
+ var i18n2 = new Command30("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4204
4341
  (opts, cmd) => runCommand(
4205
4342
  () => runDisable(
4206
4343
  {
@@ -4226,8 +4363,8 @@ var i18n2 = new Command29("i18n").description("disable internationalization").op
4226
4363
  );
4227
4364
 
4228
4365
  // src/commands/disable/teams.ts
4229
- import { Command as Command30 } from "commander";
4230
- var teams2 = new Command30("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4366
+ import { Command as Command31 } from "commander";
4367
+ var teams2 = new Command31("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4231
4368
  (opts, cmd) => runCommand(
4232
4369
  () => runDisable(
4233
4370
  {
@@ -4253,8 +4390,8 @@ var teams2 = new Command30("teams").description("disable teams").option("-y, --y
4253
4390
  );
4254
4391
 
4255
4392
  // src/commands/disable/payments.ts
4256
- import { Command as Command31 } from "commander";
4257
- var payments2 = new Command31("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4393
+ import { Command as Command32 } from "commander";
4394
+ var payments2 = new Command32("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4258
4395
  (opts, cmd) => runCommand(
4259
4396
  () => runDisable(
4260
4397
  {
@@ -4281,11 +4418,11 @@ var payments2 = new Command31("payments").description("disable payments").option
4281
4418
  );
4282
4419
 
4283
4420
  // src/commands/disable/s3.ts
4284
- import { Command as Command32 } from "commander";
4421
+ import { Command as Command33 } from "commander";
4285
4422
  import * as p21 from "@clack/prompts";
4286
4423
  import pc10 from "picocolors";
4287
4424
  var s32 = addTargetOptions(
4288
- new Command32("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4425
+ new Command33("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4289
4426
  "local"
4290
4427
  ).action(
4291
4428
  (raw) => runCommand(() => {
@@ -4314,8 +4451,8 @@ function label2(filesystem) {
4314
4451
  }
4315
4452
 
4316
4453
  // src/commands/disable/smtp.ts
4317
- import { Command as Command33 } from "commander";
4318
- var smtp2 = new Command33("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4454
+ import { Command as Command34 } from "commander";
4455
+ var smtp2 = new Command34("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4319
4456
  () => runCommand(async () => {
4320
4457
  const { workspaceRootDir } = await getWorkspace();
4321
4458
  await withPocketbase(workspaceRootDir, async (pb) => {
@@ -4332,30 +4469,30 @@ var smtp2 = new Command33("smtp").description("disable SMTP configuration").conf
4332
4469
  );
4333
4470
 
4334
4471
  // src/commands/disable.ts
4335
- var disable = new Command34("disable").description("disable features").configureHelp(helpConfig).addCommand(auth2).addCommand(api2).addCommand(apiKeys2).addCommand(backend2).addCommand(contentNegotiation2).addCommand(i18n2).addCommand(teams2).addCommand(payments2).addCommand(s32).addCommand(smtp2);
4472
+ var disable = new Command35("disable").description("disable features").configureHelp(helpConfig).addCommand(auth2).addCommand(api2).addCommand(apiKeys2).addCommand(backend2).addCommand(contentNegotiation2).addCommand(i18n2).addCommand(teams2).addCommand(payments2).addCommand(s32).addCommand(smtp2);
4336
4473
 
4337
4474
  // src/commands/destroy.ts
4338
- import { Command as Command40 } from "commander";
4475
+ import { Command as Command41 } from "commander";
4339
4476
 
4340
4477
  // src/commands/destroy/form.ts
4341
- import { Command as Command35 } from "commander";
4478
+ import { Command as Command36 } from "commander";
4342
4479
 
4343
4480
  // src/commands/destroy/_shared.ts
4344
- import process14 from "node:process";
4481
+ import process16 from "node:process";
4345
4482
  import * as p22 from "@clack/prompts";
4346
4483
  async function runDestroy(slug2, model, confirmMessage, report4, flags) {
4347
4484
  if (!flags.yes) {
4348
4485
  const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
4349
4486
  if (p22.isCancel(ok) || !ok) {
4350
4487
  p22.cancel("Operation cancelled.");
4351
- process14.exit(0);
4488
+ process16.exit(0);
4352
4489
  }
4353
4490
  }
4354
4491
  await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
4355
4492
  }
4356
4493
 
4357
4494
  // src/commands/destroy/form.ts
4358
- var form2 = new Command35("form").description("destroy a form generated by `vela generate form`").argument("<model>", "model name used when the form was generated (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").option(
4495
+ var form2 = new Command36("form").description("destroy a form generated by `vela generate form`").argument("<model>", "model name used when the form was generated (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").option(
4359
4496
  "--route <route>",
4360
4497
  "custom route the form was generated at (must match the --route used at generation)"
4361
4498
  ).allowUnknownOption(true).configureHelp(helpConfig).action(
@@ -4379,8 +4516,8 @@ var form2 = new Command35("form").description("destroy a form generated by `vela
4379
4516
  );
4380
4517
 
4381
4518
  // src/commands/destroy/schema.ts
4382
- import { Command as Command36 } from "commander";
4383
- var schema2 = new Command36("schema").description("destroy a zod schema generated by `vela generate schema`").argument("<model>", "schema model name (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4519
+ import { Command as Command37 } from "commander";
4520
+ var schema2 = new Command37("schema").description("destroy a zod schema generated by `vela generate schema`").argument("<model>", "schema model name (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4384
4521
  (model, opts) => runCommand(
4385
4522
  () => runDestroy(
4386
4523
  "destroy-schema",
@@ -4401,8 +4538,8 @@ var schema2 = new Command36("schema").description("destroy a zod schema generate
4401
4538
  );
4402
4539
 
4403
4540
  // src/commands/destroy/resource.ts
4404
- import { Command as Command37 } from "commander";
4405
- var resource2 = new Command37("resource").description("destroy a resource generated by `vela generate resource`").argument("<model>", "model path used when the resource was generated (e.g., contacts, articles)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4541
+ import { Command as Command38 } from "commander";
4542
+ var resource2 = new Command38("resource").description("destroy a resource generated by `vela generate resource`").argument("<model>", "model path used when the resource was generated (e.g., contacts, articles)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).configureHelp(helpConfig).action(
4406
4543
  (model, opts) => runCommand(
4407
4544
  () => runDestroy(
4408
4545
  "destroy-resource",
@@ -4423,8 +4560,8 @@ var resource2 = new Command37("resource").description("destroy a resource genera
4423
4560
  );
4424
4561
 
4425
4562
  // src/commands/destroy/scaffold.ts
4426
- import { Command as Command38 } from "commander";
4427
- var scaffold2 = new Command38("scaffold").description("destroy a scaffold generated by `vela generate scaffold`").argument("<model>", "model name used when the scaffold was generated (e.g., contact, todo)").option("-y, --yes", "skip confirmation prompt").option(
4563
+ import { Command as Command39 } from "commander";
4564
+ var scaffold2 = new Command39("scaffold").description("destroy a scaffold generated by `vela generate scaffold`").argument("<model>", "model name used when the scaffold was generated (e.g., contact, todo)").option("-y, --yes", "skip confirmation prompt").option(
4428
4565
  "--route <route>",
4429
4566
  "custom route the scaffold was generated at (must match the --route used at generation)"
4430
4567
  ).allowUnknownOption(true).configureHelp(helpConfig).action(
@@ -4451,12 +4588,205 @@ var scaffold2 = new Command38("scaffold").description("destroy a scaffold genera
4451
4588
  );
4452
4589
 
4453
4590
  // src/commands/destroy/deployment.ts
4454
- import process15 from "node:process";
4455
- import { Command as Command39 } from "commander";
4591
+ import process17 from "node:process";
4592
+ import { Command as Command40 } from "commander";
4593
+ import * as p25 from "@clack/prompts";
4594
+ import pc13 from "picocolors";
4595
+
4596
+ // src/lib/deploy-report.ts
4597
+ import * as p24 from "@clack/prompts";
4598
+ import pc12 from "picocolors";
4599
+
4600
+ // src/lib/server-identity.ts
4456
4601
  import * as p23 from "@clack/prompts";
4457
4602
  import pc11 from "picocolors";
4603
+
4604
+ // src/lib/velastack-api.ts
4605
+ async function apiFetch(apiKey, pathAndQuery, init) {
4606
+ const headers = new Headers(init?.headers);
4607
+ headers.set("Authorization", `Bearer ${apiKey}`);
4608
+ if (init?.body && !headers.has("Content-Type")) {
4609
+ headers.set("Content-Type", "application/json");
4610
+ }
4611
+ const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
4612
+ if (res.status === 401) {
4613
+ throw new Error("API key invalid \u2014 run `vela login`");
4614
+ }
4615
+ if (res.status === 403) {
4616
+ const body = await res.text().catch(() => "");
4617
+ throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
4618
+ }
4619
+ if (!res.ok) {
4620
+ const body = await res.text().catch(() => "");
4621
+ throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
4622
+ }
4623
+ return await res.json();
4624
+ }
4625
+ async function getCurrentUser(apiKey) {
4626
+ const data = await apiFetch(
4627
+ apiKey,
4628
+ "/api/collections/users/records?perPage=1"
4629
+ );
4630
+ const user = data.items[0];
4631
+ if (!user) throw new Error("No user found. Run `vela login` to login.");
4632
+ return user;
4633
+ }
4634
+ async function listTeams(apiKey) {
4635
+ const data = await apiFetch(
4636
+ apiKey,
4637
+ "/api/collections/teams/records?perPage=200"
4638
+ );
4639
+ return data.items;
4640
+ }
4641
+ async function listProjects(apiKey) {
4642
+ const data = await apiFetch(
4643
+ apiKey,
4644
+ "/api/collections/projects/records?perPage=200&expand=team"
4645
+ );
4646
+ return data.items;
4647
+ }
4648
+ async function createProject2(apiKey, args) {
4649
+ return apiFetch(apiKey, "/api/collections/projects/records", {
4650
+ method: "POST",
4651
+ body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
4652
+ });
4653
+ }
4654
+ async function registerServer(apiKey, input) {
4655
+ return apiFetch(apiKey, "/v1/servers", {
4656
+ method: "POST",
4657
+ body: JSON.stringify(input)
4658
+ });
4659
+ }
4660
+ async function startDeployment(apiKey, projectId, input) {
4661
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
4662
+ method: "POST",
4663
+ body: JSON.stringify(input)
4664
+ });
4665
+ }
4666
+ async function finishDeployment(apiKey, projectId, deploymentId, input) {
4667
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
4668
+ method: "PATCH",
4669
+ body: JSON.stringify(input)
4670
+ });
4671
+ }
4672
+ async function destroyEnvironment(apiKey, projectId, envTag) {
4673
+ return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
4674
+ method: "DELETE"
4675
+ });
4676
+ }
4677
+
4678
+ // src/lib/server-identity.ts
4679
+ var IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
4680
+ async function ensureServerIdentity(session, apiKey) {
4681
+ const existing = await readServerIdentity(session);
4682
+ const ip = await publicIp(session);
4683
+ const registered = await registerServer(apiKey, {
4684
+ ip,
4685
+ serverId: existing?.serverId,
4686
+ token: existing?.token
4687
+ });
4688
+ if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
4689
+ await writeServerIdentity(session, registered);
4690
+ if (existing) {
4691
+ p23.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
4692
+ }
4693
+ }
4694
+ await runServerScript(session, "origin.sh");
4695
+ return registered;
4696
+ }
4697
+ async function publicIp(session) {
4698
+ const result = await session.script(
4699
+ `api="$1"
4700
+ if ip=$(curl -4fsS --max-time 10 "$api/v1/ip" 2>/dev/null); then
4701
+ printf '%s' "$ip"
4702
+ else
4703
+ ip -4 route get 1.1.1.1 2>/dev/null | awk '{for (i = 1; i <= NF; i++) if ($i == "src") print $(i + 1)}'
4704
+ fi`,
4705
+ { args: [API_URL], check: false }
4706
+ );
4707
+ const raw = result.stdout.trim();
4708
+ let ip = raw;
4709
+ try {
4710
+ const parsed = JSON.parse(raw);
4711
+ if (typeof parsed.ip === "string") ip = parsed.ip;
4712
+ } catch {
4713
+ }
4714
+ ip = ip.trim().replace(/^::ffff:/, "");
4715
+ if (!IPV4.test(ip)) {
4716
+ throw new Error(
4717
+ `Could not work out the public IPv4 address of ${session.target}.
4718
+
4719
+ The server needs to reach ${API_URL} (or have a default IPv4 route) for velastack.dev
4720
+ to point its origin record at it.`
4721
+ );
4722
+ }
4723
+ return ip;
4724
+ }
4725
+
4726
+ // src/lib/deploy-report.ts
4727
+ function createDeployReporter(workspaceRootDir) {
4728
+ const link2 = readProjectConfig(workspaceRootDir);
4729
+ const apiKey = link2 ? readApiKey() : null;
4730
+ if (link2 && !apiKey) {
4731
+ p24.log.warn(
4732
+ `This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
4733
+ API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
4734
+ ${pc12.cyan("VELA_API_KEY")}.`
4735
+ );
4736
+ }
4737
+ let deploymentId = null;
4738
+ return {
4739
+ enabled: Boolean(link2 && apiKey),
4740
+ async identifyServer(session) {
4741
+ if (!link2 || !apiKey) return null;
4742
+ try {
4743
+ return await ensureServerIdentity(session, apiKey);
4744
+ } catch (err) {
4745
+ warn("register this server", err);
4746
+ return null;
4747
+ }
4748
+ },
4749
+ async start(input) {
4750
+ if (!link2 || !apiKey) return null;
4751
+ try {
4752
+ const result = await startDeployment(apiKey, link2.projectId, input);
4753
+ deploymentId = result.deploymentId;
4754
+ return result;
4755
+ } catch (err) {
4756
+ warn("record this deploy", err);
4757
+ return null;
4758
+ }
4759
+ },
4760
+ async finish(input) {
4761
+ if (!link2 || !apiKey || !deploymentId) return;
4762
+ try {
4763
+ await finishDeployment(apiKey, link2.projectId, deploymentId, input);
4764
+ } catch (err) {
4765
+ warn("update this deploy", err);
4766
+ }
4767
+ }
4768
+ };
4769
+ }
4770
+ async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
4771
+ const link2 = readProjectConfig(workspaceRootDir);
4772
+ const apiKey = link2 ? readApiKey() : null;
4773
+ if (!link2 || !apiKey) return;
4774
+ try {
4775
+ await destroyEnvironment(apiKey, link2.projectId, envTag);
4776
+ } catch (err) {
4777
+ warn("retire the environment", err);
4778
+ }
4779
+ }
4780
+ function warn(what, err) {
4781
+ p24.log.warn(
4782
+ `velastack.dev could not ${what}.
4783
+ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
4784
+ );
4785
+ }
4786
+
4787
+ // src/commands/destroy/deployment.ts
4458
4788
  var deployment = addTargetOptions(
4459
- new Command39("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
4789
+ new Command40("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
4460
4790
  "production"
4461
4791
  ).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").action(
4462
4792
  (raw) => runCommand(async () => {
@@ -4472,10 +4802,11 @@ var deployment = addTargetOptions(
4472
4802
  args: [ctx.instance, ...options.purge ? ["--purge"] : []],
4473
4803
  stream: true
4474
4804
  });
4475
- p23.log.success(
4476
- `Removed ${pc11.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? "" : `
4805
+ await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
4806
+ p25.log.success(
4807
+ `Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? "" : `
4477
4808
 
4478
- The database and uploads are still in the instance's shared directory. Pass ${pc11.cyan("--purge")} to delete them.`)
4809
+ The database and uploads are still in the instance's shared directory. Pass ${pc13.cyan("--purge")} to delete them.`)
4479
4810
  );
4480
4811
  }
4481
4812
  },
@@ -4488,35 +4819,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
4488
4819
  );
4489
4820
  async function confirm7(appName, targetName, envTag, purge) {
4490
4821
  if (isProd(envTag) || purge) {
4491
- const answer = await p23.text({
4492
- message: `This removes ${pc11.cyan(`${appName} (${targetName})`)}${purge ? " and its database" : ""}. Type the app name to confirm`,
4822
+ const answer = await p25.text({
4823
+ message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}${purge ? " and its database" : ""}. Type the app name to confirm`,
4493
4824
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
4494
4825
  });
4495
- if (p23.isCancel(answer)) {
4496
- p23.cancel("Operation cancelled.");
4497
- process15.exit(0);
4826
+ if (p25.isCancel(answer)) {
4827
+ p25.cancel("Operation cancelled.");
4828
+ process17.exit(0);
4498
4829
  }
4499
4830
  return;
4500
4831
  }
4501
- const ok = await p23.confirm({
4832
+ const ok = await p25.confirm({
4502
4833
  message: `Remove ${appName} (${targetName})?`,
4503
4834
  initialValue: false
4504
4835
  });
4505
- if (p23.isCancel(ok) || !ok) {
4506
- p23.cancel("Operation cancelled.");
4507
- process15.exit(0);
4836
+ if (p25.isCancel(ok) || !ok) {
4837
+ p25.cancel("Operation cancelled.");
4838
+ process17.exit(0);
4508
4839
  }
4509
4840
  }
4510
4841
 
4511
4842
  // src/commands/destroy.ts
4512
- var destroy = new Command40("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
4843
+ var destroy = new Command41("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
4513
4844
 
4514
4845
  // src/commands/ui.ts
4515
- import { Command as Command46 } from "commander";
4846
+ import { Command as Command47 } from "commander";
4516
4847
 
4517
4848
  // src/commands/ui/add.ts
4518
- import { Command as Command41 } from "commander";
4519
- import * as p24 from "@clack/prompts";
4849
+ import { Command as Command42 } from "commander";
4850
+ import * as p26 from "@clack/prompts";
4520
4851
  import { installComponents } from "@velastack/patterns";
4521
4852
 
4522
4853
  // src/lib/ui-add.ts
@@ -4565,21 +4896,21 @@ function uiAddReport(requested, outcome) {
4565
4896
  }
4566
4897
 
4567
4898
  // src/commands/ui/add.ts
4568
- var add = new Command41("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
4899
+ var add = new Command42("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
4569
4900
  (components, options) => runCommand(async () => {
4570
4901
  const { workspaceRootDir } = await getWorkspace();
4571
- const log43 = p24.taskLog({ title: "Adding UI components..." });
4902
+ const log45 = p26.taskLog({ title: "Adding UI components..." });
4572
4903
  let outcome;
4573
4904
  try {
4574
4905
  outcome = await installComponents({
4575
4906
  root: workspaceRootDir,
4576
4907
  components,
4577
4908
  overwrite: options.overwrite,
4578
- logger: { info: (message) => log43.message(message) }
4909
+ logger: { info: (message) => log45.message(message) }
4579
4910
  });
4580
- log43.success("UI components ready");
4911
+ log45.success("UI components ready");
4581
4912
  } catch (e) {
4582
- log43.error("Could not add UI components");
4913
+ log45.error("Could not add UI components");
4583
4914
  throw e;
4584
4915
  }
4585
4916
  reportResult(uiAddReport(components, outcome));
@@ -4587,19 +4918,19 @@ var add = new Command41("add").description("add ui components (shadcn-svelte ite
4587
4918
  );
4588
4919
 
4589
4920
  // src/commands/ui/base.ts
4590
- import { Command as Command42 } from "commander";
4591
- import * as p25 from "@clack/prompts";
4921
+ import { Command as Command43 } from "commander";
4922
+ import * as p27 from "@clack/prompts";
4592
4923
  import { applyBaseColor } from "@velastack/patterns";
4593
- var base = new Command42("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
4924
+ var base = new Command43("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
4594
4925
  (color) => runCommand(async () => {
4595
4926
  const { workspaceRootDir } = await getWorkspace();
4596
- const log43 = p25.taskLog({ title: `Applying the ${color} palette...` });
4927
+ const log45 = p27.taskLog({ title: `Applying the ${color} palette...` });
4597
4928
  let outcome;
4598
4929
  try {
4599
4930
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
4600
- log43.success("Palette applied");
4931
+ log45.success("Palette applied");
4601
4932
  } catch (e) {
4602
- log43.error("Could not change the base color");
4933
+ log45.error("Could not change the base color");
4603
4934
  throw e;
4604
4935
  }
4605
4936
  reportResult({
@@ -4615,8 +4946,8 @@ var base = new Command42("base").description("change the base (gray) palette").a
4615
4946
  );
4616
4947
 
4617
4948
  // src/commands/ui/list.ts
4618
- import { Command as Command43 } from "commander";
4619
- import * as p26 from "@clack/prompts";
4949
+ import { Command as Command44 } from "commander";
4950
+ import * as p28 from "@clack/prompts";
4620
4951
  import { listComponents } from "@velastack/patterns";
4621
4952
 
4622
4953
  // src/lib/ui-list.ts
@@ -4647,7 +4978,7 @@ function uiListReport(result) {
4647
4978
  }
4648
4979
 
4649
4980
  // src/commands/ui/list.ts
4650
- var list = new Command43("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
4981
+ var list = new Command44("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
4651
4982
  (options) => runCommand(async () => {
4652
4983
  const { workspaceRootDir } = await getWorkspace();
4653
4984
  if (options.json) {
@@ -4655,7 +4986,7 @@ var list = new Command43("list").description("list installed ui components, vela
4655
4986
  console.log(JSON.stringify(result2, null, 2));
4656
4987
  return;
4657
4988
  }
4658
- const spinner7 = p26.spinner();
4989
+ const spinner7 = p28.spinner();
4659
4990
  spinner7.start("Reading the registry...");
4660
4991
  let result;
4661
4992
  try {
@@ -4667,15 +4998,15 @@ var list = new Command43("list").description("list installed ui components, vela
4667
4998
  spinner7.stop(`Read the ${result.style} registry`);
4668
4999
  reportResult(uiListReport(result));
4669
5000
  if (result.registryUnavailable) {
4670
- p26.log.warn(`${result.registryUnavailable}
5001
+ p28.log.warn(`${result.registryUnavailable}
4671
5002
  Registry components are not listed.`);
4672
5003
  }
4673
5004
  }, "Failed to list UI components.")
4674
5005
  );
4675
5006
 
4676
5007
  // src/commands/ui/style.ts
4677
- import { Command as Command44 } from "commander";
4678
- import * as p27 from "@clack/prompts";
5008
+ import { Command as Command45 } from "commander";
5009
+ import * as p29 from "@clack/prompts";
4679
5010
  import { switchStyle } from "@velastack/patterns";
4680
5011
 
4681
5012
  // src/lib/ui-style.ts
@@ -4701,72 +5032,72 @@ function uiStyleReport(result) {
4701
5032
  }
4702
5033
 
4703
5034
  // src/commands/ui/style.ts
4704
- var style = new Command44("style").description("switch the shadcn-svelte style, re-adding its components").argument("<style>", `style to switch to (${STYLES.join(", ")})`).option("-y, --yes", "skip the confirmation prompt").option("--no-font", "keep the current font instead of applying the style's").configureHelp(helpConfig).action(
5035
+ var style = new Command45("style").description("switch the shadcn-svelte style, re-adding its components").argument("<style>", `style to switch to (${STYLES.join(", ")})`).option("-y, --yes", "skip the confirmation prompt").option("--no-font", "keep the current font instead of applying the style's").configureHelp(helpConfig).action(
4705
5036
  (name, options) => runCommand(async () => {
4706
5037
  const { workspaceRootDir } = await getWorkspace();
4707
- const spinner7 = p27.spinner();
5038
+ const spinner7 = p29.spinner();
4708
5039
  spinner7.start(`Reading the ${name} registry...`);
4709
- let log43;
5040
+ let log45;
4710
5041
  let outcome;
4711
5042
  try {
4712
5043
  outcome = await switchStyle({
4713
5044
  root: workspaceRootDir,
4714
5045
  style: name,
4715
5046
  font: options.font,
4716
- logger: { info: (message) => log43?.message(message) },
5047
+ logger: { info: (message) => log45?.message(message) },
4717
5048
  confirm: async (components) => {
4718
5049
  spinner7.stop(`Read the ${name} registry`);
4719
5050
  if (components.length > 0) {
4720
- p27.log.info(
5051
+ p29.log.info(
4721
5052
  `Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
4722
5053
  ${components.map((c) => `- ${c}`).join("\n")}`
4723
5054
  );
4724
5055
  } else {
4725
- p27.log.info(
5056
+ p29.log.info(
4726
5057
  `No installed component comes from the registry; only the config changes.`
4727
5058
  );
4728
5059
  }
4729
5060
  if (!options.yes) {
4730
- const ok = await p27.confirm({ message: `Switch to ${name}?`, initialValue: false });
4731
- if (p27.isCancel(ok) || !ok) return false;
5061
+ const ok = await p29.confirm({ message: `Switch to ${name}?`, initialValue: false });
5062
+ if (p29.isCancel(ok) || !ok) return false;
4732
5063
  }
4733
- log43 = p27.taskLog({ title: `Switching to the ${name} style...` });
5064
+ log45 = p29.taskLog({ title: `Switching to the ${name} style...` });
4734
5065
  return true;
4735
5066
  }
4736
5067
  });
4737
5068
  } catch (e) {
4738
5069
  spinner7.stop(`Could not switch to ${name}`);
4739
- log43?.error("Could not switch style");
5070
+ log45?.error("Could not switch style");
4740
5071
  throw e;
4741
5072
  }
4742
5073
  spinner7.stop(`Read the ${name} registry`);
4743
5074
  if (outcome.status === "unchanged") {
4744
- p27.log.info(`Already using the ${name} style.`);
5075
+ p29.log.info(`Already using the ${name} style.`);
4745
5076
  return;
4746
5077
  }
4747
5078
  if (outcome.status === "cancelled") {
4748
- p27.cancel("Operation cancelled.");
5079
+ p29.cancel("Operation cancelled.");
4749
5080
  return;
4750
5081
  }
4751
- log43?.success("Style switched");
5082
+ log45?.success("Style switched");
4752
5083
  reportResult(uiStyleReport(outcome));
4753
5084
  }, "Failed to switch style.")
4754
5085
  );
4755
5086
 
4756
5087
  // src/commands/ui/theme.ts
4757
- import { Command as Command45 } from "commander";
4758
- import * as p28 from "@clack/prompts";
5088
+ import { Command as Command46 } from "commander";
5089
+ import * as p30 from "@clack/prompts";
4759
5090
  import { applyTheme } from "@velastack/patterns";
4760
- var theme = new Command45("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
5091
+ var theme = new Command46("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
4761
5092
  (accent) => runCommand(async () => {
4762
5093
  const { workspaceRootDir } = await getWorkspace();
4763
- const log43 = p28.taskLog({ title: `Applying the ${accent} accent...` });
5094
+ const log45 = p30.taskLog({ title: `Applying the ${accent} accent...` });
4764
5095
  let outcome;
4765
5096
  try {
4766
5097
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
4767
- log43.success("Accent applied");
5098
+ log45.success("Accent applied");
4768
5099
  } catch (e) {
4769
- log43.error("Could not change the accent");
5100
+ log45.error("Could not change the accent");
4770
5101
  throw e;
4771
5102
  }
4772
5103
  reportResult({
@@ -4782,22 +5113,22 @@ var theme = new Command45("theme").description("change the accent color, keeping
4782
5113
  );
4783
5114
 
4784
5115
  // src/commands/ui.ts
4785
- var ui = new Command46("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5116
+ var ui = new Command47("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
4786
5117
 
4787
5118
  // src/commands/legal.ts
4788
- import { Command as Command49 } from "commander";
5119
+ import { Command as Command50 } from "commander";
4789
5120
 
4790
5121
  // src/commands/legal/terms.ts
4791
- import fs23 from "node:fs";
4792
- import path21 from "node:path";
4793
- import { Command as Command47 } from "commander";
4794
- import * as p30 from "@clack/prompts";
5122
+ import fs24 from "node:fs";
5123
+ import path22 from "node:path";
5124
+ import { Command as Command48 } from "commander";
5125
+ import * as p32 from "@clack/prompts";
4795
5126
 
4796
5127
  // src/commands/legal/shared.ts
4797
- import process16 from "node:process";
4798
- import * as p29 from "@clack/prompts";
5128
+ import process18 from "node:process";
5129
+ import * as p31 from "@clack/prompts";
4799
5130
  var sharedFields = {
4800
- websiteUrl: () => p29.text({
5131
+ websiteUrl: () => p31.text({
4801
5132
  message: "What is your website URL?",
4802
5133
  placeholder: "http://www.mysite.com",
4803
5134
  validate: (value) => {
@@ -4806,7 +5137,7 @@ var sharedFields = {
4806
5137
  }
4807
5138
  }
4808
5139
  }),
4809
- websiteName: () => p29.text({
5140
+ websiteName: () => p31.text({
4810
5141
  message: "What is your website name?",
4811
5142
  placeholder: "My Site",
4812
5143
  validate: (value) => {
@@ -4815,7 +5146,7 @@ var sharedFields = {
4815
5146
  }
4816
5147
  }
4817
5148
  }),
4818
- entityType: () => p29.select({
5149
+ entityType: () => p31.select({
4819
5150
  message: "Entity type",
4820
5151
  options: [
4821
5152
  {
@@ -4826,7 +5157,7 @@ var sharedFields = {
4826
5157
  { value: "individual", label: "I'm an Individual" }
4827
5158
  ]
4828
5159
  }),
4829
- businessName: ({ results }) => results?.entityType === "business" ? p29.text({
5160
+ businessName: ({ results }) => results?.entityType === "business" ? p31.text({
4830
5161
  message: "What is the name of the business?",
4831
5162
  placeholder: "My Company LLC",
4832
5163
  validate: (value) => {
@@ -4835,7 +5166,7 @@ var sharedFields = {
4835
5166
  }
4836
5167
  }
4837
5168
  }) : void 0,
4838
- businessAddress: ({ results }) => results?.entityType === "business" ? p29.text({
5169
+ businessAddress: ({ results }) => results?.entityType === "business" ? p31.text({
4839
5170
  message: "What is the address of the business?",
4840
5171
  placeholder: "1 Cupertino, CA 95014",
4841
5172
  validate: (value) => {
@@ -4844,7 +5175,7 @@ var sharedFields = {
4844
5175
  }
4845
5176
  }
4846
5177
  }) : void 0,
4847
- country: () => p29.text({
5178
+ country: () => p31.text({
4848
5179
  message: "Enter the country",
4849
5180
  validate: (value) => {
4850
5181
  if (!value) {
@@ -4852,7 +5183,7 @@ var sharedFields = {
4852
5183
  }
4853
5184
  }
4854
5185
  }),
4855
- state: () => p29.text({
5186
+ state: () => p31.text({
4856
5187
  message: "Enter the state",
4857
5188
  validate: (value) => {
4858
5189
  if (!value) {
@@ -4862,11 +5193,11 @@ var sharedFields = {
4862
5193
  })
4863
5194
  };
4864
5195
  var onCancel = () => {
4865
- p29.cancel("Operation cancelled.");
4866
- process16.exit(0);
5196
+ p31.cancel("Operation cancelled.");
5197
+ process18.exit(0);
4867
5198
  };
4868
5199
  async function contactMethods(type) {
4869
- const selection = await p29.multiselect({
5200
+ const selection = await p31.multiselect({
4870
5201
  message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
4871
5202
  options: [
4872
5203
  { value: "email", label: "By email" },
@@ -4875,11 +5206,11 @@ async function contactMethods(type) {
4875
5206
  { value: "mail", label: "By sending post mail" }
4876
5207
  ]
4877
5208
  });
4878
- if (p29.isCancel(selection)) onCancel();
5209
+ if (p31.isCancel(selection)) onCancel();
4879
5210
  const contact = selection;
4880
5211
  const details = {};
4881
5212
  if (contact.includes("email")) {
4882
- const email3 = await p29.text({
5213
+ const email3 = await p31.text({
4883
5214
  message: "What's the email?",
4884
5215
  placeholder: "office@mycompany.com",
4885
5216
  validate: (value) => {
@@ -4888,11 +5219,11 @@ async function contactMethods(type) {
4888
5219
  }
4889
5220
  }
4890
5221
  });
4891
- if (p29.isCancel(email3)) onCancel();
5222
+ if (p31.isCancel(email3)) onCancel();
4892
5223
  details.email = email3;
4893
5224
  }
4894
5225
  if (contact.includes("page")) {
4895
- const page = await p29.text({
5226
+ const page = await p31.text({
4896
5227
  message: "What's the link?",
4897
5228
  placeholder: "http://www.mycompany.com/contact",
4898
5229
  validate: (value) => {
@@ -4901,11 +5232,11 @@ async function contactMethods(type) {
4901
5232
  }
4902
5233
  }
4903
5234
  });
4904
- if (p29.isCancel(page)) onCancel();
5235
+ if (p31.isCancel(page)) onCancel();
4905
5236
  details.page = page;
4906
5237
  }
4907
5238
  if (contact.includes("phone")) {
4908
- const phone = await p29.text({
5239
+ const phone = await p31.text({
4909
5240
  message: "What's the phone number?",
4910
5241
  placeholder: "408.996.1010",
4911
5242
  validate: (value) => {
@@ -4914,11 +5245,11 @@ async function contactMethods(type) {
4914
5245
  }
4915
5246
  }
4916
5247
  });
4917
- if (p29.isCancel(phone)) onCancel();
5248
+ if (p31.isCancel(phone)) onCancel();
4918
5249
  details.phone = phone;
4919
5250
  }
4920
5251
  if (contact.includes("mail")) {
4921
- const address = await p29.text({
5252
+ const address = await p31.text({
4922
5253
  message: "What's the address?",
4923
5254
  placeholder: "767 Fifth Avenue New York, NY 10153, United States",
4924
5255
  validate: (value) => {
@@ -4927,7 +5258,7 @@ async function contactMethods(type) {
4927
5258
  }
4928
5259
  }
4929
5260
  });
4930
- if (p29.isCancel(address)) onCancel();
5261
+ if (p31.isCancel(address)) onCancel();
4931
5262
  details.address = address;
4932
5263
  }
4933
5264
  return { methods: contact, details };
@@ -5323,7 +5654,7 @@ var generateTermsHtml = (answers) => {
5323
5654
  };
5324
5655
  async function termsAction() {
5325
5656
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
5326
- const core = await p30.group(
5657
+ const core = await p32.group(
5327
5658
  {
5328
5659
  websiteUrl: sharedFields.websiteUrl,
5329
5660
  websiteName: sharedFields.websiteName,
@@ -5335,25 +5666,25 @@ async function termsAction() {
5335
5666
  },
5336
5667
  { onCancel }
5337
5668
  );
5338
- const accounts = await p30.select({
5669
+ const accounts = await p32.select({
5339
5670
  message: "Can users create accounts?",
5340
5671
  options: [
5341
5672
  { value: "yes", label: "Yes, users can create accounts" },
5342
5673
  { value: "no", label: "No" }
5343
5674
  ]
5344
5675
  });
5345
- if (p30.isCancel(accounts)) onCancel();
5346
- const userContent = await p30.select({
5676
+ if (p32.isCancel(accounts)) onCancel();
5677
+ const userContent = await p32.select({
5347
5678
  message: "Can users create and/or upload content (ie. text, images)?",
5348
5679
  options: [
5349
5680
  { value: "yes", label: "Yes, users can create and/or upload content" },
5350
5681
  { value: "no", label: "No" }
5351
5682
  ]
5352
5683
  });
5353
- if (p30.isCancel(userContent)) onCancel();
5684
+ if (p32.isCancel(userContent)) onCancel();
5354
5685
  let infringementEmail;
5355
5686
  if (userContent === "yes") {
5356
- const email3 = await p30.text({
5687
+ const email3 = await p32.text({
5357
5688
  message: "What's the email address where you will receive infringements notices?",
5358
5689
  placeholder: "dmca@website.com",
5359
5690
  validate: (value) => {
@@ -5362,10 +5693,10 @@ async function termsAction() {
5362
5693
  }
5363
5694
  }
5364
5695
  });
5365
- if (p30.isCancel(email3)) onCancel();
5696
+ if (p32.isCancel(email3)) onCancel();
5366
5697
  infringementEmail = email3;
5367
5698
  }
5368
- const canBuyGoods = await p30.select({
5699
+ const canBuyGoods = await p32.select({
5369
5700
  message: "Can users buy goods (products, items)?",
5370
5701
  options: [
5371
5702
  {
@@ -5375,28 +5706,28 @@ async function termsAction() {
5375
5706
  { value: "no", label: "No" }
5376
5707
  ]
5377
5708
  });
5378
- if (p30.isCancel(canBuyGoods)) onCancel();
5379
- const subscriptions2 = await p30.select({
5709
+ if (p32.isCancel(canBuyGoods)) onCancel();
5710
+ const subscriptions2 = await p32.select({
5380
5711
  message: "Do you offer subscription plans?",
5381
5712
  options: [
5382
5713
  { value: "yes", label: "Yes, we offer subscription plans" },
5383
5714
  { value: "no", label: "No" }
5384
5715
  ]
5385
5716
  });
5386
- if (p30.isCancel(subscriptions2)) onCancel();
5717
+ if (p32.isCancel(subscriptions2)) onCancel();
5387
5718
  let freeTrial;
5388
5719
  if (subscriptions2 === "yes") {
5389
- const ft = await p30.select({
5720
+ const ft = await p32.select({
5390
5721
  message: "Do you offer a free trial?",
5391
5722
  options: [
5392
5723
  { value: "yes", label: "Yes" },
5393
5724
  { value: "no", label: "No" }
5394
5725
  ]
5395
5726
  });
5396
- if (p30.isCancel(ft)) onCancel();
5727
+ if (p32.isCancel(ft)) onCancel();
5397
5728
  freeTrial = ft;
5398
5729
  }
5399
- const exclusiveContent = await p30.select({
5730
+ const exclusiveContent = await p32.select({
5400
5731
  message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
5401
5732
  options: [
5402
5733
  {
@@ -5406,24 +5737,24 @@ async function termsAction() {
5406
5737
  { value: "no", label: "No" }
5407
5738
  ]
5408
5739
  });
5409
- if (p30.isCancel(exclusiveContent)) onCancel();
5410
- const feedbackReuse = await p30.select({
5740
+ if (p32.isCancel(exclusiveContent)) onCancel();
5741
+ const feedbackReuse = await p32.select({
5411
5742
  message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
5412
5743
  options: [
5413
5744
  { value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
5414
5745
  { value: "no", label: "No" }
5415
5746
  ]
5416
5747
  });
5417
- if (p30.isCancel(feedbackReuse)) onCancel();
5418
- const promotions = await p30.select({
5748
+ if (p32.isCancel(feedbackReuse)) onCancel();
5749
+ const promotions = await p32.select({
5419
5750
  message: "Do you plan to offer promotions, contests, sweepstakes?",
5420
5751
  options: [
5421
5752
  { value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
5422
5753
  { value: "no", label: "No" }
5423
5754
  ]
5424
5755
  });
5425
- if (p30.isCancel(promotions)) onCancel();
5426
- const mobileAppRaw = await p30.multiselect({
5756
+ if (p32.isCancel(promotions)) onCancel();
5757
+ const mobileAppRaw = await p32.multiselect({
5427
5758
  message: "Is the Service distributed through any mobile app stores? Check all that apply",
5428
5759
  options: [
5429
5760
  { value: "apple", label: "Apple App Store" },
@@ -5431,7 +5762,7 @@ async function termsAction() {
5431
5762
  ],
5432
5763
  required: false
5433
5764
  });
5434
- if (p30.isCancel(mobileAppRaw)) onCancel();
5765
+ if (p32.isCancel(mobileAppRaw)) onCancel();
5435
5766
  const mobileApp = mobileAppRaw ?? [];
5436
5767
  const contact = await contactMethods("terms");
5437
5768
  const html = generateTermsHtml({
@@ -5448,22 +5779,22 @@ async function termsAction() {
5448
5779
  mobileApp,
5449
5780
  contact
5450
5781
  });
5451
- const termsPage = path21.join(
5782
+ const termsPage = path22.join(
5452
5783
  workspaceRootDir,
5453
5784
  publicRoutesDir,
5454
5785
  LEGAL_DIR,
5455
5786
  "terms",
5456
5787
  "+page.svelte"
5457
5788
  );
5458
- const termsPageTs = path21.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
5459
- fs23.mkdirSync(path21.dirname(termsPage), { recursive: true });
5460
- fs23.writeFileSync(termsPage, html);
5461
- fs23.writeFileSync(
5789
+ const termsPageTs = path22.join(workspaceRootDir, publicRoutesDir, LEGAL_DIR, "terms", "+page.ts");
5790
+ fs24.mkdirSync(path22.dirname(termsPage), { recursive: true });
5791
+ fs24.writeFileSync(termsPage, html);
5792
+ fs24.writeFileSync(
5462
5793
  termsPageTs,
5463
5794
  pageMetaTagsLoader("Terms of Service", `Terms of Service for ${core.websiteName}`)
5464
5795
  );
5465
- const relativeTermsPage = path21.relative(workspaceRootDir, termsPage);
5466
- const relativeTermsPageTs = path21.relative(workspaceRootDir, termsPageTs);
5796
+ const relativeTermsPage = path22.relative(workspaceRootDir, termsPage);
5797
+ const relativeTermsPageTs = path22.relative(workspaceRootDir, termsPageTs);
5467
5798
  reportResult({
5468
5799
  summary: "Generated placeholder terms and conditions.",
5469
5800
  filesCreated: [relativeTermsPage, relativeTermsPageTs],
@@ -5474,13 +5805,13 @@ async function termsAction() {
5474
5805
  ]
5475
5806
  });
5476
5807
  }
5477
- var terms = new Command47("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
5808
+ var terms = new Command48("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
5478
5809
 
5479
5810
  // src/commands/legal/privacy.ts
5480
- import fs24 from "node:fs";
5481
- import path22 from "node:path";
5482
- import { Command as Command48 } from "commander";
5483
- import * as p31 from "@clack/prompts";
5811
+ import fs25 from "node:fs";
5812
+ import path23 from "node:path";
5813
+ import { Command as Command49 } from "commander";
5814
+ import * as p33 from "@clack/prompts";
5484
5815
  var mapLabels = {
5485
5816
  personalInfo: {
5486
5817
  email: "Email address",
@@ -5898,12 +6229,12 @@ var generatePrivacyHtml = (answers) => {
5898
6229
  return `<section data-role="content">${sections.join("")}</section>`;
5899
6230
  };
5900
6231
  async function promptWithCustom(message, options, customMessage) {
5901
- const selection = await p31.multiselect({ message, options });
5902
- if (p31.isCancel(selection)) onCancel();
6232
+ const selection = await p33.multiselect({ message, options });
6233
+ if (p33.isCancel(selection)) onCancel();
5903
6234
  const values = selection;
5904
6235
  if (values.includes("custom")) {
5905
- const custom = await p31.text({ message: customMessage });
5906
- if (p31.isCancel(custom)) onCancel();
6236
+ const custom = await p33.text({ message: customMessage });
6237
+ if (p33.isCancel(custom)) onCancel();
5907
6238
  const idx = values.indexOf("custom");
5908
6239
  if (idx !== -1) values.splice(idx, 1);
5909
6240
  if (custom) values.push(String(custom));
@@ -5912,7 +6243,7 @@ async function promptWithCustom(message, options, customMessage) {
5912
6243
  }
5913
6244
  async function privacyAction() {
5914
6245
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
5915
- const core = await p31.group(
6246
+ const core = await p33.group(
5916
6247
  {
5917
6248
  websiteUrl: sharedFields.websiteUrl,
5918
6249
  websiteName: sharedFields.websiteName,
@@ -5924,7 +6255,7 @@ async function privacyAction() {
5924
6255
  },
5925
6256
  { onCancel }
5926
6257
  );
5927
- const personalInfo = await p31.multiselect({
6258
+ const personalInfo = await p33.multiselect({
5928
6259
  message: "What kind of personal information do you collect from users? Check all that apply",
5929
6260
  options: [
5930
6261
  { value: "email", label: "Email address" },
@@ -5939,16 +6270,16 @@ async function privacyAction() {
5939
6270
  ],
5940
6271
  required: false
5941
6272
  });
5942
- if (p31.isCancel(personalInfo)) onCancel();
6273
+ if (p33.isCancel(personalInfo)) onCancel();
5943
6274
  const contact = await contactMethods("privacy");
5944
- const tracking = await p31.select({
6275
+ const tracking = await p33.select({
5945
6276
  message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
5946
6277
  options: [
5947
6278
  { value: "yes", label: "Yes, we use Google Analytics or other related tools" },
5948
6279
  { value: "no", label: "No" }
5949
6280
  ]
5950
6281
  });
5951
- if (p31.isCancel(tracking)) onCancel();
6282
+ if (p33.isCancel(tracking)) onCancel();
5952
6283
  let trackingTools;
5953
6284
  if (tracking === "yes") {
5954
6285
  trackingTools = await promptWithCustom(
@@ -5967,7 +6298,7 @@ async function privacyAction() {
5967
6298
  "Enter your custom tracking/analytics tool name"
5968
6299
  );
5969
6300
  }
5970
- const sendEmails = await p31.select({
6301
+ const sendEmails = await p33.select({
5971
6302
  message: "Do you send emails to users?",
5972
6303
  options: [
5973
6304
  {
@@ -5977,7 +6308,7 @@ async function privacyAction() {
5977
6308
  { value: "no", label: "No" }
5978
6309
  ]
5979
6310
  });
5980
- if (p31.isCancel(sendEmails)) onCancel();
6311
+ if (p33.isCancel(sendEmails)) onCancel();
5981
6312
  let emailPlatforms;
5982
6313
  if (sendEmails === "yes") {
5983
6314
  emailPlatforms = await promptWithCustom(
@@ -5992,14 +6323,14 @@ async function privacyAction() {
5992
6323
  "Enter your custom email platform"
5993
6324
  );
5994
6325
  }
5995
- const showAds = await p31.select({
6326
+ const showAds = await p33.select({
5996
6327
  message: "Do you show ads?",
5997
6328
  options: [
5998
6329
  { value: "yes", label: "Yes, we show ads" },
5999
6330
  { value: "no", label: "No" }
6000
6331
  ]
6001
6332
  });
6002
- if (p31.isCancel(showAds)) onCancel();
6333
+ if (p33.isCancel(showAds)) onCancel();
6003
6334
  let adsPlatforms;
6004
6335
  if (showAds === "yes") {
6005
6336
  adsPlatforms = await promptWithCustom(
@@ -6022,7 +6353,7 @@ async function privacyAction() {
6022
6353
  "Enter your custom ads platform"
6023
6354
  );
6024
6355
  }
6025
- const canPay = await p31.select({
6356
+ const canPay = await p33.select({
6026
6357
  message: "Can users pay for products or services?",
6027
6358
  options: [
6028
6359
  { value: "yes", label: "Yes, users can pay for our products/services" },
@@ -6032,7 +6363,7 @@ async function privacyAction() {
6032
6363
  }
6033
6364
  ]
6034
6365
  });
6035
- if (p31.isCancel(canPay)) onCancel();
6366
+ if (p33.isCancel(canPay)) onCancel();
6036
6367
  let paymentProcessors;
6037
6368
  if (canPay === "yes") {
6038
6369
  paymentProcessors = await promptWithCustom(
@@ -6063,14 +6394,14 @@ async function privacyAction() {
6063
6394
  "Enter your custom payment processor/method"
6064
6395
  );
6065
6396
  }
6066
- const remarketing = await p31.select({
6397
+ const remarketing = await p33.select({
6067
6398
  message: "Do you use remarketing services for marketing & advertising purposes?",
6068
6399
  options: [
6069
6400
  { value: "yes", label: "Yes, we use remarketing services to advertise our business" },
6070
6401
  { value: "no", label: "No" }
6071
6402
  ]
6072
6403
  });
6073
- if (p31.isCancel(remarketing)) onCancel();
6404
+ if (p33.isCancel(remarketing)) onCancel();
6074
6405
  let remarketingPlatforms;
6075
6406
  if (remarketing === "yes") {
6076
6407
  remarketingPlatforms = await promptWithCustom(
@@ -6089,7 +6420,7 @@ async function privacyAction() {
6089
6420
  "Enter your custom remarketing platform"
6090
6421
  );
6091
6422
  }
6092
- const providersRaw = await p31.multiselect({
6423
+ const providersRaw = await p33.multiselect({
6093
6424
  message: "Select if you use any of the following providers",
6094
6425
  options: [
6095
6426
  { value: "recaptcha", label: "Invisible reCAPTCHA" },
@@ -6100,16 +6431,16 @@ async function privacyAction() {
6100
6431
  ],
6101
6432
  required: false
6102
6433
  });
6103
- if (p31.isCancel(providersRaw)) onCancel();
6434
+ if (p33.isCancel(providersRaw)) onCancel();
6104
6435
  const providers = providersRaw;
6105
6436
  if (providers.includes("custom")) {
6106
- const custom = await p31.text({ message: "Enter your custom provider" });
6107
- if (p31.isCancel(custom)) onCancel();
6437
+ const custom = await p33.text({ message: "Enter your custom provider" });
6438
+ if (p33.isCancel(custom)) onCancel();
6108
6439
  const idx = providers.indexOf("custom");
6109
6440
  if (idx !== -1) providers.splice(idx, 1);
6110
6441
  if (custom) providers.push(String(custom));
6111
6442
  }
6112
- const usStates = await p31.select({
6443
+ const usStates = await p33.select({
6113
6444
  message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
6114
6445
  options: [
6115
6446
  {
@@ -6120,55 +6451,55 @@ async function privacyAction() {
6120
6451
  ],
6121
6452
  initialValue: "yes"
6122
6453
  });
6123
- if (p31.isCancel(usStates)) onCancel();
6124
- const gdpr = await p31.select({
6454
+ if (p33.isCancel(usStates)) onCancel();
6455
+ const gdpr = await p33.select({
6125
6456
  message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
6126
6457
  options: [
6127
6458
  { value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
6128
6459
  { value: "no", label: "No" }
6129
6460
  ]
6130
6461
  });
6131
- if (p31.isCancel(gdpr)) onCancel();
6462
+ if (p33.isCancel(gdpr)) onCancel();
6132
6463
  let facebookFanPage = "no";
6133
6464
  const facebookDetails = { name: "", url: "" };
6134
6465
  if (gdpr === "yes") {
6135
- const fan = await p31.select({
6466
+ const fan = await p33.select({
6136
6467
  message: "Do you have a Facebook Fan Page?",
6137
6468
  options: [
6138
6469
  { value: "yes", label: "Yes, we have a Facebook Fan Page" },
6139
6470
  { value: "no", label: "No" }
6140
6471
  ]
6141
6472
  });
6142
- if (p31.isCancel(fan)) onCancel();
6473
+ if (p33.isCancel(fan)) onCancel();
6143
6474
  facebookFanPage = fan;
6144
6475
  if (facebookFanPage === "yes") {
6145
- const name = await p31.text({
6476
+ const name = await p33.text({
6146
6477
  message: "What is the name of the Facebook Fan Page?",
6147
6478
  placeholder: "My Facebook Page"
6148
6479
  });
6149
- if (p31.isCancel(name)) onCancel();
6480
+ if (p33.isCancel(name)) onCancel();
6150
6481
  facebookDetails.name = name;
6151
- const url = await p31.text({
6482
+ const url = await p33.text({
6152
6483
  message: "What is the URL of the Facebook Fan Page?",
6153
6484
  placeholder: "https://facebook.com/my-facebook-page"
6154
6485
  });
6155
- if (p31.isCancel(url)) onCancel();
6486
+ if (p33.isCancel(url)) onCancel();
6156
6487
  facebookDetails.url = url;
6157
6488
  }
6158
6489
  }
6159
- const kids = await p31.select({
6490
+ const kids = await p33.select({
6160
6491
  message: "Do you collect information from kids under the age of 13?",
6161
6492
  options: [
6162
6493
  { value: "yes", label: "Yes. We collect information from children under the age of 13" },
6163
6494
  { value: "no", label: "No" }
6164
6495
  ]
6165
6496
  });
6166
- if (p31.isCancel(kids)) onCancel();
6167
- const retention = await p31.text({
6497
+ if (p33.isCancel(kids)) onCancel();
6498
+ const retention = await p33.text({
6168
6499
  message: "How long do you retain personal information? (leave blank for default wording)",
6169
6500
  placeholder: "e.g. 12 months after account closure"
6170
6501
  });
6171
- if (p31.isCancel(retention)) onCancel();
6502
+ if (p33.isCancel(retention)) onCancel();
6172
6503
  const html = generatePrivacyHtml({
6173
6504
  core,
6174
6505
  personalInfo: personalInfo ?? [],
@@ -6191,28 +6522,28 @@ async function privacyAction() {
6191
6522
  kids,
6192
6523
  retention
6193
6524
  });
6194
- const privacyPage = path22.join(
6525
+ const privacyPage = path23.join(
6195
6526
  workspaceRootDir,
6196
6527
  publicRoutesDir,
6197
6528
  LEGAL_DIR,
6198
6529
  "privacy",
6199
6530
  "+page.svelte"
6200
6531
  );
6201
- const privacyPageTs = path22.join(
6532
+ const privacyPageTs = path23.join(
6202
6533
  workspaceRootDir,
6203
6534
  publicRoutesDir,
6204
6535
  LEGAL_DIR,
6205
6536
  "privacy",
6206
6537
  "+page.ts"
6207
6538
  );
6208
- fs24.mkdirSync(path22.dirname(privacyPage), { recursive: true });
6209
- fs24.writeFileSync(privacyPage, html);
6210
- fs24.writeFileSync(
6539
+ fs25.mkdirSync(path23.dirname(privacyPage), { recursive: true });
6540
+ fs25.writeFileSync(privacyPage, html);
6541
+ fs25.writeFileSync(
6211
6542
  privacyPageTs,
6212
6543
  pageMetaTagsLoader("Privacy Policy", `Privacy Policy for ${core.websiteName}`)
6213
6544
  );
6214
- const relativePrivacyPage = path22.relative(workspaceRootDir, privacyPage);
6215
- const relativePrivacyPageTs = path22.relative(workspaceRootDir, privacyPageTs);
6545
+ const relativePrivacyPage = path23.relative(workspaceRootDir, privacyPage);
6546
+ const relativePrivacyPageTs = path23.relative(workspaceRootDir, privacyPageTs);
6216
6547
  reportResult({
6217
6548
  summary: "Generated placeholder privacy policy.",
6218
6549
  filesCreated: [relativePrivacyPage, relativePrivacyPageTs],
@@ -6223,20 +6554,20 @@ async function privacyAction() {
6223
6554
  ]
6224
6555
  });
6225
6556
  }
6226
- var privacy = new Command48("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
6557
+ var privacy = new Command49("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
6227
6558
 
6228
6559
  // src/commands/legal.ts
6229
- var legal = new Command49("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
6560
+ var legal = new Command50("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
6230
6561
 
6231
6562
  // src/commands/fixtures.ts
6232
- import { Command as Command55 } from "commander";
6563
+ import { Command as Command56 } from "commander";
6233
6564
 
6234
6565
  // src/commands/fixtures/load.ts
6235
- import { Command as Command50 } from "commander";
6566
+ import { Command as Command51 } from "commander";
6236
6567
 
6237
6568
  // src/lib/data.ts
6238
- import fs25 from "node:fs";
6239
- import path23 from "node:path";
6569
+ import fs26 from "node:fs";
6570
+ import path24 from "node:path";
6240
6571
  import { ClientResponseError } from "pocketbase";
6241
6572
 
6242
6573
  // src/lib/collections.ts
@@ -6273,14 +6604,14 @@ function dependencyOrder(collections2, startingCollectionId) {
6273
6604
 
6274
6605
  // src/lib/data.ts
6275
6606
  function dataDir(cwd, kind) {
6276
- return path23.join(cwd, DATA_DIR, kind);
6607
+ return path24.join(cwd, DATA_DIR, kind);
6277
6608
  }
6278
6609
  function getDataFiles(cwd, kind) {
6279
6610
  const dir = dataDir(cwd, kind);
6280
- if (!fs25.existsSync(dir)) return [];
6281
- return fs25.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
6611
+ if (!fs26.existsSync(dir)) return [];
6612
+ return fs26.readdirSync(dir).filter((file) => file.endsWith(".json")).sort((a, b) => a.localeCompare(b)).map((file) => ({
6282
6613
  collectionName: file.replace(/\.json$/i, "").replace(/^\d+[-_]?/, ""),
6283
- filePath: path23.join(dir, file)
6614
+ filePath: path24.join(dir, file)
6284
6615
  }));
6285
6616
  }
6286
6617
  function getSeedFiles(cwd) {
@@ -6290,7 +6621,7 @@ function getFixtureFiles(cwd) {
6290
6621
  return getDataFiles(cwd, "fixtures");
6291
6622
  }
6292
6623
  function readRecords(filePath) {
6293
- return JSON.parse(fs25.readFileSync(filePath, "utf8"));
6624
+ return JSON.parse(fs26.readFileSync(filePath, "utf8"));
6294
6625
  }
6295
6626
  function readSeedIds(cwd) {
6296
6627
  const ids = /* @__PURE__ */ new Map();
@@ -6327,7 +6658,7 @@ function describeError(e) {
6327
6658
  return e instanceof Error ? e.message : String(e);
6328
6659
  }
6329
6660
  function label3(cwd, filePath, count) {
6330
- return `${path23.relative(cwd, filePath)} (${count} records)`;
6661
+ return `${path24.relative(cwd, filePath)} (${count} records)`;
6331
6662
  }
6332
6663
  async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
6333
6664
  const records = readRecords(filePath);
@@ -6335,7 +6666,7 @@ async function createRecords(pb, kind, cwd, { collectionName, filePath }) {
6335
6666
  try {
6336
6667
  await pb.collection(collectionName).create(record);
6337
6668
  } catch (e) {
6338
- throw new DataLoadError(kind, path23.relative(cwd, filePath), index, e);
6669
+ throw new DataLoadError(kind, path24.relative(cwd, filePath), index, e);
6339
6670
  }
6340
6671
  }
6341
6672
  return records.length;
@@ -6422,7 +6753,7 @@ async function hasLoadedFixtures(pb) {
6422
6753
  }
6423
6754
 
6424
6755
  // src/commands/fixtures/load.ts
6425
- var load = new Command50("load").description("load fixtures into the database").configureHelp(helpConfig).action(
6756
+ var load = new Command51("load").description("load fixtures into the database").configureHelp(helpConfig).action(
6426
6757
  () => runCommand(async () => {
6427
6758
  const { workspaceRootDir } = await getWorkspace();
6428
6759
  let loaded = [];
@@ -6448,8 +6779,8 @@ var load = new Command50("load").description("load fixtures into the database").
6448
6779
  );
6449
6780
 
6450
6781
  // src/commands/fixtures/clear.ts
6451
- import { Command as Command51 } from "commander";
6452
- var clear = new Command51("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
6782
+ import { Command as Command52 } from "commander";
6783
+ var clear = new Command52("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
6453
6784
  () => runCommand(async () => {
6454
6785
  const { workspaceRootDir } = await getWorkspace();
6455
6786
  let cleared = [];
@@ -6478,8 +6809,8 @@ var clear = new Command51("clear").description("clear loaded fixtures").configur
6478
6809
  );
6479
6810
 
6480
6811
  // src/commands/fixtures/reset.ts
6481
- import { Command as Command52 } from "commander";
6482
- var reset = new Command52("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
6812
+ import { Command as Command53 } from "commander";
6813
+ var reset = new Command53("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
6483
6814
  () => runCommand(async () => {
6484
6815
  const { workspaceRootDir } = await getWorkspace();
6485
6816
  let cleared = [];
@@ -6509,10 +6840,10 @@ var reset = new Command52("reset").description("clear and reload fixtures").conf
6509
6840
  );
6510
6841
 
6511
6842
  // src/commands/fixtures/generate.ts
6512
- import fs26 from "node:fs";
6513
- import path24 from "node:path";
6514
- import { Command as Command53, InvalidArgumentError } from "commander";
6515
- import * as p32 from "@clack/prompts";
6843
+ import fs27 from "node:fs";
6844
+ import path25 from "node:path";
6845
+ import { Command as Command54, InvalidArgumentError } from "commander";
6846
+ import * as p34 from "@clack/prompts";
6516
6847
  import { annotate } from "annotate-json-schema";
6517
6848
  import { createGenerator } from "json-schema-faker";
6518
6849
  import { faker } from "@faker-js/faker";
@@ -6547,9 +6878,9 @@ async function loadCollections(pb) {
6547
6878
  }
6548
6879
  async function generateFixtureFiles(pb, workspaceRootDir, opts) {
6549
6880
  const fixturesDir = dataDir(workspaceRootDir, "fixtures");
6550
- fs26.mkdirSync(fixturesDir, { recursive: true });
6551
- for (const file of fs26.readdirSync(fixturesDir)) {
6552
- if (file.endsWith(".json")) fs26.unlinkSync(path24.join(fixturesDir, file));
6881
+ fs27.mkdirSync(fixturesDir, { recursive: true });
6882
+ for (const file of fs27.readdirSync(fixturesDir)) {
6883
+ if (file.endsWith(".json")) fs27.unlinkSync(path25.join(fixturesDir, file));
6553
6884
  }
6554
6885
  if (opts.seed !== void 0) faker.seed(opts.seed);
6555
6886
  const generator = createGenerator({
@@ -6616,13 +6947,13 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
6616
6947
  items.push(record);
6617
6948
  }
6618
6949
  const filename = `${padZeros(fileIndex, 2)}-${collection.name}.json`;
6619
- fs26.writeFileSync(path24.join(fixturesDir, filename), JSON.stringify(items, null, 2));
6620
- writtenFiles.push(`${path24.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
6950
+ fs27.writeFileSync(path25.join(fixturesDir, filename), JSON.stringify(items, null, 2));
6951
+ writtenFiles.push(`${path25.join(DATA_DIR, "fixtures", filename)} (${items.length} records)`);
6621
6952
  fileIndex++;
6622
6953
  }
6623
6954
  return { writtenFiles, warnings };
6624
6955
  }
6625
- var generate2 = new Command53("generate").description("generate fixture data").option("-c, --count <count>", "number of records per collection", parseCount, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed).option("-f, --force", "overwrite existing fixture files and clear loaded fixtures").configureHelp(helpConfig).action(
6956
+ var generate2 = new Command54("generate").description("generate fixture data").option("-c, --count <count>", "number of records per collection", parseCount, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed).option("-f, --force", "overwrite existing fixture files and clear loaded fixtures").configureHelp(helpConfig).action(
6626
6957
  (opts) => runCommand(async () => {
6627
6958
  const { workspaceRootDir } = await getWorkspace();
6628
6959
  const existing = getFixtureFiles(workspaceRootDir);
@@ -6651,7 +6982,7 @@ var generate2 = new Command53("generate").description("generate fixture data").o
6651
6982
  seed: opts.seed
6652
6983
  });
6653
6984
  });
6654
- for (const warning of result.warnings) p32.log.warn(warning);
6985
+ for (const warning of result.warnings) p34.log.warn(warning);
6655
6986
  if (result.writtenFiles.length === 0) {
6656
6987
  reportResult({
6657
6988
  summary: "No eligible collections found to generate fixtures for.",
@@ -6675,8 +7006,8 @@ var generate2 = new Command53("generate").description("generate fixture data").o
6675
7006
  );
6676
7007
 
6677
7008
  // src/commands/fixtures/regen.ts
6678
- import { Command as Command54, InvalidArgumentError as InvalidArgumentError2 } from "commander";
6679
- import * as p33 from "@clack/prompts";
7009
+ import { Command as Command55, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7010
+ import * as p35 from "@clack/prompts";
6680
7011
  function parseCount2(value) {
6681
7012
  const n = parseInt(value, 10);
6682
7013
  if (!Number.isFinite(n) || n <= 0 || n > 999) {
@@ -6691,7 +7022,7 @@ function parseSeed2(value) {
6691
7022
  }
6692
7023
  return n;
6693
7024
  }
6694
- var regen = new Command54("regen").description("clear the database, regenerate fixture files, and reload them").option("-c, --count <count>", "number of records per collection", parseCount2, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed2).configureHelp(helpConfig).action(
7025
+ var regen = new Command55("regen").description("clear the database, regenerate fixture files, and reload them").option("-c, --count <count>", "number of records per collection", parseCount2, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed2).configureHelp(helpConfig).action(
6695
7026
  (opts) => runCommand(async () => {
6696
7027
  const { workspaceRootDir } = await getWorkspace();
6697
7028
  let cleared = [];
@@ -6705,7 +7036,7 @@ var regen = new Command54("regen").description("clear the database, regenerate f
6705
7036
  });
6706
7037
  loaded = await loadFixtures(pb, workspaceRootDir);
6707
7038
  });
6708
- for (const warning of result.warnings) p33.log.warn(warning);
7039
+ for (const warning of result.warnings) p35.log.warn(warning);
6709
7040
  reportResult({
6710
7041
  summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
6711
7042
  filesCreated: result.writtenFiles,
@@ -6720,14 +7051,14 @@ var regen = new Command54("regen").description("clear the database, regenerate f
6720
7051
  );
6721
7052
 
6722
7053
  // src/commands/fixtures.ts
6723
- var fixtures = new Command55("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7054
+ var fixtures = new Command56("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
6724
7055
 
6725
7056
  // src/commands/seeds.ts
6726
- import { Command as Command59 } from "commander";
7057
+ import { Command as Command60 } from "commander";
6727
7058
 
6728
7059
  // src/commands/seeds/load.ts
6729
- import { Command as Command56 } from "commander";
6730
- var load2 = new Command56("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
7060
+ import { Command as Command57 } from "commander";
7061
+ var load2 = new Command57("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
6731
7062
  (opts) => runCommand(async () => {
6732
7063
  const { workspaceRootDir } = await getWorkspace();
6733
7064
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -6764,9 +7095,9 @@ var load2 = new Command56("load").description("load seeds into the database").op
6764
7095
  );
6765
7096
 
6766
7097
  // src/commands/seeds/save.ts
6767
- import fs27 from "node:fs";
6768
- import path25 from "node:path";
6769
- import { Command as Command57 } from "commander";
7098
+ import fs28 from "node:fs";
7099
+ import path26 from "node:path";
7100
+ import { Command as Command58 } from "commander";
6770
7101
  var padZeros2 = (num, length) => num.toString().padStart(length, "0");
6771
7102
  function filterSystemFields(record, systemFieldNames) {
6772
7103
  const out = {};
@@ -6777,7 +7108,7 @@ function filterSystemFields(record, systemFieldNames) {
6777
7108
  }
6778
7109
  return out;
6779
7110
  }
6780
- var save = new Command57("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7111
+ var save = new Command58("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
6781
7112
  (opts) => runCommand(async () => {
6782
7113
  const { workspaceRootDir } = await getWorkspace();
6783
7114
  const seedsPath = dataDir(workspaceRootDir, "seeds");
@@ -6785,10 +7116,10 @@ var save = new Command57("save").description("save the current data as seeds").o
6785
7116
  if (existing.length > 0 && !opts.force) {
6786
7117
  throw new Error("Existing seed files found in data/seeds. Pass --force to overwrite.");
6787
7118
  }
6788
- fs27.mkdirSync(seedsPath, { recursive: true });
7119
+ fs28.mkdirSync(seedsPath, { recursive: true });
6789
7120
  if (opts.force) {
6790
- for (const file of fs27.readdirSync(seedsPath)) {
6791
- if (file.endsWith(".json")) fs27.unlinkSync(path25.join(seedsPath, file));
7121
+ for (const file of fs28.readdirSync(seedsPath)) {
7122
+ if (file.endsWith(".json")) fs28.unlinkSync(path26.join(seedsPath, file));
6792
7123
  }
6793
7124
  }
6794
7125
  const saved = [];
@@ -6817,13 +7148,13 @@ var save = new Command57("save").description("save the current data as seeds").o
6817
7148
  const filtered = records.map(
6818
7149
  (r) => filterSystemFields(r, systemFieldNames)
6819
7150
  );
6820
- const relativeSeedPath = path25.join(
7151
+ const relativeSeedPath = path26.join(
6821
7152
  DATA_DIR,
6822
7153
  "seeds",
6823
7154
  `${padZeros2(count, 2)}-${collectionName}.json`
6824
7155
  );
6825
- const seedPath = path25.join(workspaceRootDir, relativeSeedPath);
6826
- fs27.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
7156
+ const seedPath = path26.join(workspaceRootDir, relativeSeedPath);
7157
+ fs28.writeFileSync(seedPath, JSON.stringify(filtered, null, 2));
6827
7158
  saved.push(`${relativeSeedPath} (${filtered.length} records)`);
6828
7159
  count++;
6829
7160
  }
@@ -6849,8 +7180,8 @@ var save = new Command57("save").description("save the current data as seeds").o
6849
7180
  );
6850
7181
 
6851
7182
  // src/commands/seeds/clear.ts
6852
- import { Command as Command58 } from "commander";
6853
- var clear2 = new Command58("clear").description("clear seeded records").configureHelp(helpConfig).action(
7183
+ import { Command as Command59 } from "commander";
7184
+ var clear2 = new Command59("clear").description("clear seeded records").configureHelp(helpConfig).action(
6854
7185
  () => runCommand(async () => {
6855
7186
  const { workspaceRootDir } = await getWorkspace();
6856
7187
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -6881,23 +7212,23 @@ var clear2 = new Command58("clear").description("clear seeded records").configur
6881
7212
  );
6882
7213
 
6883
7214
  // src/commands/seeds.ts
6884
- var seeds = new Command59("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7215
+ var seeds = new Command60("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
6885
7216
 
6886
7217
  // src/commands/signup.ts
6887
- import { Command as Command61 } from "commander";
6888
- import * as p35 from "@clack/prompts";
7218
+ import { Command as Command62 } from "commander";
7219
+ import * as p37 from "@clack/prompts";
6889
7220
  import makeFetchCookie2 from "fetch-cookie";
6890
7221
 
6891
7222
  // src/commands/login.ts
6892
7223
  import os3 from "node:os";
6893
- import { Command as Command60 } from "commander";
6894
- import * as p34 from "@clack/prompts";
7224
+ import { Command as Command61 } from "commander";
7225
+ import * as p36 from "@clack/prompts";
6895
7226
  import makeFetchCookie from "fetch-cookie";
6896
- var login = new Command60("login").description("login to velastack.dev").configureHelp(helpConfig).action(
7227
+ var login = new Command61("login").description("login to velastack.dev").configureHelp(helpConfig).action(
6897
7228
  () => runCommand(async () => {
6898
- const { email: email3, password: password11 } = await p34.group({
6899
- email: () => p34.text({ message: "Email" }),
6900
- password: () => p34.password({ message: "Password" })
7229
+ const { email: email3, password: password11 } = await p36.group({
7230
+ email: () => p36.text({ message: "Email" }),
7231
+ password: () => p36.password({ message: "Password" })
6901
7232
  });
6902
7233
  const fetchCookie = makeFetchCookie(fetch);
6903
7234
  const loginRes = await fetchCookie(`${API_URL}/login`, {
@@ -6919,7 +7250,7 @@ var login = new Command60("login").description("login to velastack.dev").configu
6919
7250
  }
6920
7251
  const apiKey = await issueApiKey(fetchCookie);
6921
7252
  writeConfig({ apiKey });
6922
- p34.log.success("Logged in to velastack.dev");
7253
+ p36.log.success("Logged in to velastack.dev");
6923
7254
  }, "Failed to login.")
6924
7255
  );
6925
7256
  async function issueApiKey(fetchCookie) {
@@ -6960,12 +7291,12 @@ function extractApiKey(cookie) {
6960
7291
  }
6961
7292
 
6962
7293
  // src/commands/signup.ts
6963
- var signup = new Command61("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7294
+ var signup = new Command62("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
6964
7295
  () => runCommand(async () => {
6965
- const { email: email3, password: password11, passwordConfirm } = await p35.group({
6966
- email: () => p35.text({ message: "Email" }),
6967
- password: () => p35.password({ message: "Password" }),
6968
- passwordConfirm: () => p35.password({ message: "Confirm password" })
7296
+ const { email: email3, password: password11, passwordConfirm } = await p37.group({
7297
+ email: () => p37.text({ message: "Email" }),
7298
+ password: () => p37.password({ message: "Password" }),
7299
+ passwordConfirm: () => p37.password({ message: "Confirm password" })
6969
7300
  });
6970
7301
  if (password11 !== passwordConfirm) {
6971
7302
  throw new Error("Passwords do not match.");
@@ -6989,33 +7320,33 @@ var signup = new Command61("signup").description("signup to velastack.dev").conf
6989
7320
  }
6990
7321
  const apiKey = await issueApiKey(fetchCookie);
6991
7322
  writeConfig({ apiKey });
6992
- p35.log.success("Signed up to velastack.dev");
6993
- p35.log.info("Check your email for a confirmation link.");
7323
+ p37.log.success("Signed up to velastack.dev");
7324
+ p37.log.info("Check your email for a confirmation link.");
6994
7325
  }, "Failed to signup.")
6995
7326
  );
6996
7327
 
6997
7328
  // src/commands/logout.ts
6998
- import { Command as Command62 } from "commander";
6999
- import * as p36 from "@clack/prompts";
7000
- var logout = new Command62("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7329
+ import { Command as Command63 } from "commander";
7330
+ import * as p38 from "@clack/prompts";
7331
+ var logout = new Command63("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7001
7332
  () => runCommand(() => {
7002
7333
  if (!readConfig()) {
7003
- p36.log.info("Not logged in");
7334
+ p38.log.info("Not logged in");
7004
7335
  return;
7005
7336
  }
7006
7337
  clearConfig();
7007
- p36.log.success("Logged out of velastack.dev");
7338
+ p38.log.success("Logged out of velastack.dev");
7008
7339
  })
7009
7340
  );
7010
7341
 
7011
7342
  // src/commands/whoami.ts
7012
- import { Command as Command63 } from "commander";
7013
- import * as p37 from "@clack/prompts";
7014
- var whoami = new Command63("whoami").description("show the current user").configureHelp(helpConfig).action(
7343
+ import { Command as Command64 } from "commander";
7344
+ import * as p39 from "@clack/prompts";
7345
+ var whoami = new Command64("whoami").description("show the current user").configureHelp(helpConfig).action(
7015
7346
  () => runCommand(async () => {
7016
7347
  const apiKey = readConfig()?.apiKey;
7017
7348
  if (!apiKey) {
7018
- p37.log.info("Not logged in. Run `vela login` to login.");
7349
+ p39.log.info("Not logged in. Run `vela login` to login.");
7019
7350
  return;
7020
7351
  }
7021
7352
  const res = await fetch(`${API_URL}/api/collections/users/records`, {
@@ -7023,31 +7354,31 @@ var whoami = new Command63("whoami").description("show the current user").config
7023
7354
  });
7024
7355
  const data = await res.json();
7025
7356
  if (!data.items.length) throw new Error("No user found. Run `vela login` to login.");
7026
- p37.log.success(`Logged in as ${data.items[0].email}`);
7357
+ p39.log.success(`Logged in as ${data.items[0].email}`);
7027
7358
  })
7028
7359
  );
7029
7360
 
7030
7361
  // src/commands/migrate.ts
7031
- import { Command as Command69 } from "commander";
7362
+ import { Command as Command70 } from "commander";
7032
7363
 
7033
7364
  // src/commands/migrate/up.ts
7034
- import { Command as Command64 } from "commander";
7365
+ import { Command as Command65 } from "commander";
7035
7366
 
7036
7367
  // src/lib/migrate.ts
7037
- import path26 from "node:path";
7038
- import process17 from "node:process";
7368
+ import path27 from "node:path";
7369
+ import process19 from "node:process";
7039
7370
  import { x as x2 } from "tinyexec";
7040
7371
  async function runPocketbaseMigrate(args) {
7041
- const cwd = process17.cwd();
7372
+ const cwd = process19.cwd();
7042
7373
  const { getBinaryPath } = await import("pocketbase-server");
7043
7374
  const binaryPath = getBinaryPath();
7044
7375
  await x2(
7045
7376
  binaryPath,
7046
7377
  [
7047
7378
  "--dir",
7048
- path26.join(cwd, DATA_DIR),
7379
+ path27.join(cwd, DATA_DIR),
7049
7380
  "--migrationsDir",
7050
- path26.join(cwd, MIGRATIONS_DIR),
7381
+ path27.join(cwd, MIGRATIONS_DIR),
7051
7382
  "migrate",
7052
7383
  ...args
7053
7384
  ],
@@ -7070,10 +7401,10 @@ async function runMigrateUp() {
7070
7401
  ]
7071
7402
  });
7072
7403
  }
7073
- var up = new Command64("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
7404
+ var up = new Command65("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
7074
7405
 
7075
7406
  // src/commands/migrate/down.ts
7076
- import { Command as Command65, InvalidArgumentError as InvalidArgumentError3 } from "commander";
7407
+ import { Command as Command66, InvalidArgumentError as InvalidArgumentError3 } from "commander";
7077
7408
  function parseSteps(value) {
7078
7409
  const n = parseInt(value, 10);
7079
7410
  if (!Number.isFinite(n) || n <= 0) {
@@ -7081,7 +7412,7 @@ function parseSteps(value) {
7081
7412
  }
7082
7413
  return n;
7083
7414
  }
7084
- var down = new Command65("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
7415
+ var down = new Command66("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
7085
7416
  (n) => runCommand(async () => {
7086
7417
  await runPocketbaseMigrate(["down", String(n)]);
7087
7418
  reportResult({
@@ -7095,20 +7426,20 @@ var down = new Command65("down").alias("rollback").description("revert the last
7095
7426
  );
7096
7427
 
7097
7428
  // src/commands/migrate/create.ts
7098
- import fs28 from "node:fs";
7099
- import path27 from "node:path";
7100
- import process18 from "node:process";
7101
- import { Command as Command66 } from "commander";
7102
- var create2 = new Command66("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
7429
+ import fs29 from "node:fs";
7430
+ import path28 from "node:path";
7431
+ import process20 from "node:process";
7432
+ import { Command as Command67 } from "commander";
7433
+ var create2 = new Command67("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
7103
7434
  (name) => runCommand(async () => {
7104
- const cwd = process18.cwd();
7435
+ const cwd = process20.cwd();
7105
7436
  const before = listMigrationFiles(cwd);
7106
7437
  await runPocketbaseMigrate(["create", name]);
7107
7438
  const after = listMigrationFiles(cwd);
7108
7439
  const added = [...after].filter((f) => !before.has(f));
7109
7440
  reportResult({
7110
7441
  summary: `Created blank migration ${name}.`,
7111
- filesCreated: added.map((f) => path27.join(MIGRATIONS_DIR, f)),
7442
+ filesCreated: added.map((f) => path28.join(MIGRATIONS_DIR, f)),
7112
7443
  nextSteps: [
7113
7444
  `Open the new file in ${MIGRATIONS_DIR}/ and fill in the up/down handlers.`,
7114
7445
  "Run `vela migrate up` to apply the migration once the handlers are written."
@@ -7117,19 +7448,19 @@ var create2 = new Command66("create").alias("new").description("create a new bla
7117
7448
  }, "Failed to create migration.")
7118
7449
  );
7119
7450
  function listMigrationFiles(cwd) {
7120
- const dir = path27.join(cwd, MIGRATIONS_DIR);
7121
- if (!fs28.existsSync(dir)) return /* @__PURE__ */ new Set();
7122
- return new Set(fs28.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
7451
+ const dir = path28.join(cwd, MIGRATIONS_DIR);
7452
+ if (!fs29.existsSync(dir)) return /* @__PURE__ */ new Set();
7453
+ return new Set(fs29.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
7123
7454
  }
7124
7455
 
7125
7456
  // src/commands/migrate/collections.ts
7126
- import fs29 from "node:fs";
7127
- import path28 from "node:path";
7128
- import process19 from "node:process";
7129
- import { Command as Command67 } from "commander";
7130
- var collections = new Command67("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
7457
+ import fs30 from "node:fs";
7458
+ import path29 from "node:path";
7459
+ import process21 from "node:process";
7460
+ import { Command as Command68 } from "commander";
7461
+ var collections = new Command68("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
7131
7462
  () => runCommand(async () => {
7132
- const cwd = process19.cwd();
7463
+ const cwd = process21.cwd();
7133
7464
  const before = listMigrationFiles2(cwd);
7134
7465
  await runPocketbaseMigrate(["collections"]);
7135
7466
  const after = listMigrationFiles2(cwd);
@@ -7142,7 +7473,7 @@ var collections = new Command67("collections").alias("snapshot").description("sn
7142
7473
  }
7143
7474
  reportResult({
7144
7475
  summary: "Snapshotted local collections into a new migration.",
7145
- filesCreated: added.map((f) => path28.join(MIGRATIONS_DIR, f)),
7476
+ filesCreated: added.map((f) => path29.join(MIGRATIONS_DIR, f)),
7146
7477
  nextSteps: [
7147
7478
  `Review the generated snapshot in ${MIGRATIONS_DIR}/.`,
7148
7479
  "Commit the snapshot so teammates pick up the new schema.",
@@ -7152,14 +7483,14 @@ var collections = new Command67("collections").alias("snapshot").description("sn
7152
7483
  }, "Failed to snapshot collections.")
7153
7484
  );
7154
7485
  function listMigrationFiles2(cwd) {
7155
- const dir = path28.join(cwd, MIGRATIONS_DIR);
7156
- if (!fs29.existsSync(dir)) return /* @__PURE__ */ new Set();
7157
- return new Set(fs29.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
7486
+ const dir = path29.join(cwd, MIGRATIONS_DIR);
7487
+ if (!fs30.existsSync(dir)) return /* @__PURE__ */ new Set();
7488
+ return new Set(fs30.readdirSync(dir).filter((f) => /\.[jt]s$/.test(f)));
7158
7489
  }
7159
7490
 
7160
7491
  // src/commands/migrate/history-sync.ts
7161
- import { Command as Command68 } from "commander";
7162
- var historySync = new Command68("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
7492
+ import { Command as Command69 } from "commander";
7493
+ var historySync = new Command69("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
7163
7494
  () => runCommand(async () => {
7164
7495
  await runPocketbaseMigrate(["history-sync"]);
7165
7496
  reportResult({
@@ -7170,23 +7501,23 @@ var historySync = new Command68("history-sync").description("drop _migrations ro
7170
7501
  );
7171
7502
 
7172
7503
  // src/commands/migrate.ts
7173
- var migrate = new Command69("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
7504
+ var migrate = new Command70("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
7174
7505
 
7175
7506
  // src/commands/dev.ts
7176
- import fs30 from "node:fs";
7177
- import path30 from "node:path";
7178
- import process21 from "node:process";
7507
+ import fs31 from "node:fs";
7508
+ import path31 from "node:path";
7509
+ import process23 from "node:process";
7179
7510
  import { performance } from "node:perf_hooks";
7180
- import { Command as Command70, InvalidArgumentError as InvalidArgumentError4 } from "commander";
7181
- import pc13 from "picocolors";
7511
+ import { Command as Command71, InvalidArgumentError as InvalidArgumentError4 } from "commander";
7512
+ import pc15 from "picocolors";
7182
7513
  import PocketBase4 from "pocketbase";
7183
7514
 
7184
7515
  // src/lib/vite.ts
7185
- import path29 from "node:path";
7186
- import process20 from "node:process";
7516
+ import path30 from "node:path";
7517
+ import process22 from "node:process";
7187
7518
  import { createRequire as createRequire2 } from "node:module";
7188
7519
  import { pathToFileURL as pathToFileURL2 } from "node:url";
7189
- import pc12 from "picocolors";
7520
+ import pc14 from "picocolors";
7190
7521
  var REQUIRED_VITE_MAJOR = 8;
7191
7522
  function viteVersionError(version) {
7192
7523
  const major = Number.parseInt(version, 10);
@@ -7202,18 +7533,18 @@ function viteVersionError(version) {
7202
7533
  }
7203
7534
  function resolveProjectVite(cwd) {
7204
7535
  try {
7205
- return createRequire2(path29.join(cwd, "package.json")).resolve("vite");
7536
+ return createRequire2(path30.join(cwd, "package.json")).resolve("vite");
7206
7537
  } catch {
7207
7538
  return null;
7208
7539
  }
7209
7540
  }
7210
- async function loadVite(cwd = process20.cwd()) {
7541
+ async function loadVite(cwd = process22.cwd()) {
7211
7542
  const entry = resolveProjectVite(cwd);
7212
7543
  const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
7213
7544
  const error = viteVersionError(vite.version);
7214
7545
  if (error) {
7215
- console.error(`${pc12.redBright("\u2717")} ${error}`);
7216
- process20.exit(1);
7546
+ console.error(`${pc14.redBright("\u2717")} ${error}`);
7547
+ process22.exit(1);
7217
7548
  }
7218
7549
  return vite;
7219
7550
  }
@@ -7226,39 +7557,39 @@ function parsePort(value) {
7226
7557
  }
7227
7558
  return port;
7228
7559
  }
7229
- var dev = new Command70("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
7230
- const cwd = process21.cwd();
7231
- process21.env.VELA_DATA_DIR ??= localDataDir(cwd);
7560
+ var dev = new Command71("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
7561
+ const cwd = process23.cwd();
7562
+ process23.env.VELA_DATA_DIR ??= localDataDir(cwd);
7232
7563
  const startTime = performance.now();
7233
7564
  const { createServer, version } = await loadVite(cwd);
7234
- const viteMetadataDir = path30.join(cwd, "node_modules", ".vite");
7235
- const viteMetadataFile = path30.join(viteMetadataDir, "_pocketbase_metadata.json");
7565
+ const viteMetadataDir = path31.join(cwd, "node_modules", ".vite");
7566
+ const viteMetadataFile = path31.join(viteMetadataDir, "_pocketbase_metadata.json");
7236
7567
  let pbProc;
7237
7568
  const backend3 = hasBackend(cwd);
7238
- const needsStart = backend3 && !process21.env.POCKETBASE_URL;
7569
+ const needsStart = backend3 && !process23.env.POCKETBASE_URL;
7239
7570
  const cleanup = () => {
7240
7571
  if (pbProc?.pid) pbProc.kill();
7241
- if (fs30.existsSync(viteMetadataFile)) fs30.rmSync(viteMetadataFile);
7572
+ if (fs31.existsSync(viteMetadataFile)) fs31.rmSync(viteMetadataFile);
7242
7573
  };
7243
7574
  if (needsStart) {
7244
- const dataDir2 = path30.join(cwd, DATA_DIR);
7575
+ const dataDir2 = path31.join(cwd, DATA_DIR);
7245
7576
  const started = await startPocketbaseServe({
7246
7577
  dataDir: dataDir2,
7247
7578
  migrationsDir: MIGRATIONS_DIR,
7248
- hooksDir: path30.join(dataDir2, "hooks"),
7579
+ hooksDir: path31.join(dataDir2, "hooks"),
7249
7580
  dev: true,
7250
7581
  stdio: "pipe"
7251
7582
  });
7252
7583
  pbProc = started.proc;
7253
- process21.env.POCKETBASE_URL = started.url;
7254
- pbProc.stdout?.pipe(process21.stdout);
7255
- pbProc.stderr?.pipe(process21.stderr);
7584
+ process23.env.POCKETBASE_URL = started.url;
7585
+ pbProc.stdout?.pipe(process23.stdout);
7586
+ pbProc.stderr?.pipe(process23.stderr);
7256
7587
  pbProc.on("error", (err) => console.error("PocketBase error:", err));
7257
7588
  pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
7258
- process21.on("exit", cleanup);
7259
- process21.on("SIGINT", () => {
7589
+ process23.on("exit", cleanup);
7590
+ process23.on("SIGINT", () => {
7260
7591
  cleanup();
7261
- process21.exit(0);
7592
+ process23.exit(0);
7262
7593
  });
7263
7594
  }
7264
7595
  const serverOptions = {};
@@ -7276,31 +7607,31 @@ var dev = new Command70("dev").description("start the development server").optio
7276
7607
  if (!backend3) return;
7277
7608
  const { address, port: vitePort } = server.httpServer.address();
7278
7609
  const viteHost = address === "::1" ? "localhost" : address;
7279
- await fs30.promises.mkdir(viteMetadataDir, { recursive: true });
7280
- await fs30.promises.writeFile(
7610
+ await fs31.promises.mkdir(viteMetadataDir, { recursive: true });
7611
+ await fs31.promises.writeFile(
7281
7612
  viteMetadataFile,
7282
7613
  JSON.stringify({
7283
- pocketbaseUrl: process21.env.POCKETBASE_URL,
7614
+ pocketbaseUrl: process23.env.POCKETBASE_URL,
7284
7615
  vitePort,
7285
7616
  viteHost
7286
7617
  })
7287
7618
  );
7288
- const pb = new PocketBase4(process21.env.POCKETBASE_URL);
7619
+ const pb = new PocketBase4(process23.env.POCKETBASE_URL);
7289
7620
  await pb.collection("_superusers").authWithPassword(
7290
- process21.env.POCKETBASE_SUPERUSER_EMAIL,
7291
- process21.env.POCKETBASE_SUPERUSER_PASSWORD
7621
+ process23.env.POCKETBASE_SUPERUSER_EMAIL,
7622
+ process23.env.POCKETBASE_SUPERUSER_PASSWORD
7292
7623
  );
7293
7624
  await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
7294
7625
  await startWatchingTypes(cwd, pb);
7295
7626
  });
7296
7627
  await server.listen();
7297
- const hasExistingLogs = process21.stdout.bytesWritten > 0 || process21.stderr.bytesWritten > 0;
7298
- const startupDurationString = pc13.dim(
7299
- `ready in ${pc13.reset(pc13.bold(Math.ceil(performance.now() - startTime)))} ms`
7628
+ const hasExistingLogs = process23.stdout.bytesWritten > 0 || process23.stderr.bytesWritten > 0;
7629
+ const startupDurationString = pc15.dim(
7630
+ `ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
7300
7631
  );
7301
7632
  server.config.logger.info(
7302
7633
  `
7303
- ${pc13.green(`${pc13.bold("VITE")} v${version}`)} ${startupDurationString}
7634
+ ${pc15.green(`${pc15.bold("VITE")} v${version}`)} ${startupDurationString}
7304
7635
  `,
7305
7636
  { clear: !hasExistingLogs }
7306
7637
  );
@@ -7309,18 +7640,18 @@ var dev = new Command70("dev").description("start the development server").optio
7309
7640
  });
7310
7641
  async function startWatchingTypes(cwd, pb) {
7311
7642
  const { processTypes } = await import("@velastack/pocketbase-codegen");
7312
- const typesDir = path30.resolve(cwd, ".svelte-kit", "types");
7313
- const pocketbaseDir = path30.join(typesDir, "pocketbase");
7314
- const pocketbaseTypes = path30.join(pocketbaseDir, "$types.d.ts");
7643
+ const typesDir = path31.resolve(cwd, ".svelte-kit", "types");
7644
+ const pocketbaseDir = path31.join(typesDir, "pocketbase");
7645
+ const pocketbaseTypes = path31.join(pocketbaseDir, "$types.d.ts");
7315
7646
  const regenerate = () => processTypes(pb, typesDir).catch(() => {
7316
7647
  });
7317
7648
  await regenerate();
7318
7649
  void (async () => {
7319
7650
  for (; ; ) {
7320
7651
  try {
7321
- await fs30.promises.mkdir(pocketbaseDir, { recursive: true });
7322
- for await (const event of fs30.promises.watch(pocketbaseDir)) {
7323
- if (event.eventType === "rename" && event.filename === "$types.d.ts" && !fs30.existsSync(pocketbaseTypes)) {
7652
+ await fs31.promises.mkdir(pocketbaseDir, { recursive: true });
7653
+ for await (const event of fs31.promises.watch(pocketbaseDir)) {
7654
+ if (event.eventType === "rename" && event.filename === "$types.d.ts" && !fs31.existsSync(pocketbaseTypes)) {
7324
7655
  setTimeout(regenerate, 100);
7325
7656
  }
7326
7657
  }
@@ -7332,15 +7663,15 @@ async function startWatchingTypes(cwd, pb) {
7332
7663
  }
7333
7664
 
7334
7665
  // src/commands/build.ts
7335
- import fs31 from "node:fs";
7336
- import path31 from "node:path";
7337
- import process23 from "node:process";
7338
- import { Command as Command71 } from "commander";
7339
- import * as p38 from "@clack/prompts";
7340
- import pc14 from "picocolors";
7666
+ import fs32 from "node:fs";
7667
+ import path32 from "node:path";
7668
+ import process25 from "node:process";
7669
+ import { Command as Command72 } from "commander";
7670
+ import * as p40 from "@clack/prompts";
7671
+ import pc16 from "picocolors";
7341
7672
  import { x as x3 } from "tinyexec";
7342
- import { detect as detect4 } from "package-manager-detector";
7343
- import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
7673
+ import { detect as detect5 } from "package-manager-detector";
7674
+ import { resolveCommand as resolveCommand5 } from "package-manager-detector/commands";
7344
7675
 
7345
7676
  // src/lib/build-env.ts
7346
7677
  function applyBuildEnv(cwd, env2 = process.env) {
@@ -7349,10 +7680,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
7349
7680
  }
7350
7681
 
7351
7682
  // src/lib/origin.ts
7352
- import process22 from "node:process";
7683
+ import process24 from "node:process";
7353
7684
  function resolveOrigin(workspaceRootDir, envTag, config = {}) {
7354
7685
  return normalizeOrigin(
7355
- process22.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
7686
+ process24.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
7356
7687
  );
7357
7688
  }
7358
7689
  function normalizeOrigin(value) {
@@ -7366,39 +7697,42 @@ function normalizeOrigin(value) {
7366
7697
  return null;
7367
7698
  }
7368
7699
  }
7700
+ function splitHosts(value) {
7701
+ return (value ?? "").split(",").map((host) => host.trim()).filter(Boolean);
7702
+ }
7369
7703
 
7370
7704
  // src/commands/build.ts
7371
- var PRERENDERED_DIR = path31.join(".svelte-kit", "output", "prerendered");
7372
- var build = new Command71("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
7373
- const cwd = process23.cwd();
7705
+ var PRERENDERED_DIR = path32.join(".svelte-kit", "output", "prerendered");
7706
+ var build = new Command72("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
7707
+ const cwd = process25.cwd();
7374
7708
  applyBuildEnv(cwd);
7375
7709
  const origin = await originForBuild(cwd, options.target);
7376
- if (origin) process23.env.VELA_ORIGIN = origin;
7710
+ if (origin) process25.env.VELA_ORIGIN = origin;
7377
7711
  let pbProc;
7378
- const needsStart = hasBackend(cwd) && !process23.env.POCKETBASE_URL;
7712
+ const needsStart = hasBackend(cwd) && !process25.env.POCKETBASE_URL;
7379
7713
  const cleanup = () => {
7380
7714
  if (pbProc?.pid) pbProc.kill();
7381
7715
  };
7382
7716
  if (needsStart) {
7383
7717
  await ensureSuperuser(cwd);
7384
- const dataDir2 = path31.join(cwd, DATA_DIR);
7718
+ const dataDir2 = path32.join(cwd, DATA_DIR);
7385
7719
  const started = await startPocketbaseServe({
7386
7720
  dataDir: dataDir2,
7387
7721
  migrationsDir: MIGRATIONS_DIR,
7388
- hooksDir: path31.join(dataDir2, "hooks"),
7722
+ hooksDir: path32.join(dataDir2, "hooks"),
7389
7723
  dev: true
7390
7724
  });
7391
7725
  pbProc = started.proc;
7392
- process23.env.POCKETBASE_URL = started.url;
7393
- process23.on("exit", cleanup);
7394
- process23.on("SIGINT", () => {
7726
+ process25.env.POCKETBASE_URL = started.url;
7727
+ process25.on("exit", cleanup);
7728
+ process25.on("SIGINT", () => {
7395
7729
  cleanup();
7396
- process23.exit(0);
7730
+ process25.exit(0);
7397
7731
  });
7398
7732
  }
7399
7733
  try {
7400
- const pm = (await detect4({ cwd }))?.name ?? "npm";
7401
- const resolved = resolveCommand4(pm, "execute", ["vite", "build"]);
7734
+ const pm = (await detect5({ cwd }))?.name ?? "npm";
7735
+ const resolved = resolveCommand5(pm, "execute", ["vite", "build"]);
7402
7736
  const args = resolved.args.slice();
7403
7737
  if (pm === "npm") args.unshift("--yes");
7404
7738
  await x3(resolved.command, args, {
@@ -7415,7 +7749,8 @@ async function originForBuild(cwd, target) {
7415
7749
  if (!workspaceRootDir) return null;
7416
7750
  try {
7417
7751
  const parsed = parseTarget(target, PRODUCTION_TARGET);
7418
- if (parsed.kind !== "remote") return null;
7752
+ if (parsed.kind === "local") return null;
7753
+ if (parsed.kind === "preview") return resolveOrigin(workspaceRootDir, bindingKey(parsed), {});
7419
7754
  const config = await loadDeployConfig(workspaceRootDir);
7420
7755
  return resolveOrigin(workspaceRootDir, parsed.envTag, config);
7421
7756
  } catch {
@@ -7423,50 +7758,50 @@ async function originForBuild(cwd, target) {
7423
7758
  }
7424
7759
  }
7425
7760
  function warnIfPrerendered(cwd) {
7426
- const dir = path31.join(cwd, PRERENDERED_DIR);
7427
- if (!fs31.existsSync(dir) || fs31.readdirSync(dir).length === 0) return;
7428
- p38.log.warn(
7761
+ const dir = path32.join(cwd, PRERENDERED_DIR);
7762
+ if (!fs32.existsSync(dir) || fs32.readdirSync(dir).length === 0) return;
7763
+ p40.log.warn(
7429
7764
  `Prerendered pages were built with no domain configured, so their canonical
7430
7765
  links point at SvelteKit's placeholder host rather than at this site.
7431
7766
 
7432
- Set one with ${pc14.cyan("vela deploy --domain example.com")}, or pass ${pc14.cyan("VELA_ORIGIN")}.`
7767
+ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cyan("VELA_ORIGIN")}.`
7433
7768
  );
7434
7769
  }
7435
7770
 
7436
7771
  // src/commands/preview.ts
7437
- import path32 from "node:path";
7438
- import process24 from "node:process";
7439
- import { Command as Command72 } from "commander";
7772
+ import path33 from "node:path";
7773
+ import process26 from "node:process";
7774
+ import { Command as Command73 } from "commander";
7440
7775
  import { x as x4 } from "tinyexec";
7441
- import { detect as detect5 } from "package-manager-detector";
7442
- import { resolveCommand as resolveCommand5 } from "package-manager-detector/commands";
7443
- var preview = new Command72("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
7444
- const cwd = process24.cwd();
7445
- process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
7776
+ import { detect as detect6 } from "package-manager-detector";
7777
+ import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
7778
+ var preview = new Command73("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
7779
+ const cwd = process26.cwd();
7780
+ process26.env.VELA_DATA_DIR ??= localDataDir(cwd);
7446
7781
  let pbProc;
7447
- const needsStart = hasBackend(cwd) && !process24.env.POCKETBASE_URL;
7782
+ const needsStart = hasBackend(cwd) && !process26.env.POCKETBASE_URL;
7448
7783
  const cleanup = () => {
7449
7784
  if (pbProc?.pid) pbProc.kill();
7450
7785
  };
7451
7786
  if (needsStart) {
7452
- const dataDir2 = path32.join(cwd, DATA_DIR);
7787
+ const dataDir2 = path33.join(cwd, DATA_DIR);
7453
7788
  const started = await startPocketbaseServe({
7454
7789
  dataDir: dataDir2,
7455
7790
  migrationsDir: MIGRATIONS_DIR,
7456
- hooksDir: path32.join(dataDir2, "hooks"),
7791
+ hooksDir: path33.join(dataDir2, "hooks"),
7457
7792
  dev: true
7458
7793
  });
7459
7794
  pbProc = started.proc;
7460
- process24.env.POCKETBASE_URL = started.url;
7461
- process24.on("exit", cleanup);
7462
- process24.on("SIGINT", () => {
7795
+ process26.env.POCKETBASE_URL = started.url;
7796
+ process26.on("exit", cleanup);
7797
+ process26.on("SIGINT", () => {
7463
7798
  cleanup();
7464
- process24.exit(0);
7799
+ process26.exit(0);
7465
7800
  });
7466
7801
  }
7467
7802
  try {
7468
- const pm = (await detect5({ cwd }))?.name ?? "npm";
7469
- const resolved = resolveCommand5(pm, "execute", ["vite", "preview"]);
7803
+ const pm = (await detect6({ cwd }))?.name ?? "npm";
7804
+ const resolved = resolveCommand6(pm, "execute", ["vite", "preview"]);
7470
7805
  const args = resolved.args.slice();
7471
7806
  if (pm === "npm") args.unshift("--yes");
7472
7807
  await x4(resolved.command, args, {
@@ -7479,12 +7814,12 @@ var preview = new Command72("preview").description("preview the built app").conf
7479
7814
  });
7480
7815
 
7481
7816
  // src/commands/sync.ts
7482
- import path33 from "node:path";
7483
- import { Command as Command73 } from "commander";
7484
- var sync = new Command73("sync").description("sync types from the database").configureHelp(helpConfig).action(
7817
+ import path34 from "node:path";
7818
+ import { Command as Command74 } from "commander";
7819
+ var sync = new Command74("sync").description("sync types from the database").configureHelp(helpConfig).action(
7485
7820
  () => runCommand(async () => {
7486
7821
  const { workspaceRootDir } = await getWorkspace();
7487
- const typesDir = path33.join(workspaceRootDir, ".svelte-kit", "types");
7822
+ const typesDir = path34.join(workspaceRootDir, ".svelte-kit", "types");
7488
7823
  const { processTypes } = await import("@velastack/pocketbase-codegen");
7489
7824
  await withPocketbase(workspaceRootDir, async (pb) => {
7490
7825
  await processTypes(pb, typesDir);
@@ -7494,9 +7829,9 @@ var sync = new Command73("sync").description("sync types from the database").con
7494
7829
  );
7495
7830
 
7496
7831
  // src/commands/provision.ts
7497
- import { Command as Command74 } from "commander";
7498
- import * as p39 from "@clack/prompts";
7499
- import pc15 from "picocolors";
7832
+ import { Command as Command75 } from "commander";
7833
+ import * as p41 from "@clack/prompts";
7834
+ import pc17 from "picocolors";
7500
7835
  import * as v6 from "valibot";
7501
7836
  var OptionsSchema2 = v6.object({
7502
7837
  ...SSH_OPTION_SCHEMA,
@@ -7504,24 +7839,24 @@ var OptionsSchema2 = v6.object({
7504
7839
  nodeMajor: v6.optional(v6.string())
7505
7840
  });
7506
7841
  var provision = addSshOptions(
7507
- new Command74("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
7842
+ new Command75("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
7508
7843
  ).option("--pb-version <version>", "PocketBase version to install").option("--node-major <version>", "Node.js major version to install", "22").action(
7509
7844
  (target, raw) => runCommand(async () => {
7510
7845
  const options = parseOptions(OptionsSchema2, raw);
7511
7846
  const pbVersion = options.pbVersion ?? pocketbaseVersion();
7512
- p39.intro(pc15.bgCyan(pc15.black(" vela provision ")));
7513
- p39.log.info(`Target ${pc15.cyan(target)}`);
7847
+ p41.intro(pc17.bgCyan(pc17.black(" vela provision ")));
7848
+ p41.log.info(`Target ${pc17.cyan(target)}`);
7514
7849
  await withSsh(target, sshOptionsFrom(options), async (session) => {
7515
7850
  await session.detectElevation();
7516
7851
  const existing = await readServerInfo(session);
7517
7852
  if (existing) {
7518
- p39.log.info(
7853
+ p41.log.info(
7519
7854
  `Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
7520
7855
  );
7521
7856
  }
7522
- p39.log.step("Uploading server scripts");
7857
+ p41.log.step("Uploading server scripts");
7523
7858
  await syncServerScripts(session);
7524
- p39.log.step("Running provision");
7859
+ p41.log.step("Running provision");
7525
7860
  const result = await runServerScript(session, "provision.sh", {
7526
7861
  args: [
7527
7862
  "--pb-version",
@@ -7533,7 +7868,7 @@ var provision = addSshOptions(
7533
7868
  ],
7534
7869
  stream: true
7535
7870
  });
7536
- p39.log.success(
7871
+ p41.log.success(
7537
7872
  `${target} is ready.
7538
7873
 
7539
7874
  Node ${result?.node ?? "installed"}
@@ -7541,36 +7876,36 @@ var provision = addSshOptions(
7541
7876
  PocketBase ${result?.pocketbase ?? pbVersion}`
7542
7877
  );
7543
7878
  });
7544
- p39.outro(`Deploy with ${pc15.cyan(`vela deploy --server ${target}`)}`);
7879
+ p41.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
7545
7880
  }, "Failed to provision.")
7546
7881
  );
7547
7882
 
7548
7883
  // src/commands/deploy.ts
7549
7884
  import path36 from "node:path";
7550
7885
  import fs34 from "node:fs";
7551
- import { Command as Command75, Option as Option2 } from "commander";
7552
- import * as p40 from "@clack/prompts";
7553
- import pc16 from "picocolors";
7886
+ import { Command as Command76, Option as Option2 } from "commander";
7887
+ import * as p42 from "@clack/prompts";
7888
+ import pc18 from "picocolors";
7554
7889
  import * as v7 from "valibot";
7555
7890
 
7556
7891
  // src/lib/pocketbase-settings.ts
7557
- import fs32 from "node:fs";
7558
- import path34 from "node:path";
7559
- import process25 from "node:process";
7892
+ import fs33 from "node:fs";
7893
+ import path35 from "node:path";
7894
+ import process27 from "node:process";
7560
7895
  import PocketBase5 from "pocketbase";
7561
7896
  var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
7562
7897
  async function readLocalMeta(cwd) {
7563
- const dataDir2 = path34.join(cwd, DATA_DIR);
7564
- if (!fs32.existsSync(dataDir2)) return null;
7565
- const email3 = process25.env.POCKETBASE_SUPERUSER_EMAIL;
7566
- const password11 = process25.env.POCKETBASE_SUPERUSER_PASSWORD;
7898
+ const dataDir2 = path35.join(cwd, DATA_DIR);
7899
+ if (!fs33.existsSync(dataDir2)) return null;
7900
+ const email3 = process27.env.POCKETBASE_SUPERUSER_EMAIL;
7901
+ const password11 = process27.env.POCKETBASE_SUPERUSER_PASSWORD;
7567
7902
  if (!email3 || !password11) return null;
7568
7903
  let proc;
7569
7904
  try {
7570
7905
  const started = await startPocketbaseServe({
7571
7906
  dataDir: dataDir2,
7572
7907
  migrationsDir: MIGRATIONS_DIR,
7573
- hooksDir: path34.join(dataDir2, "hooks")
7908
+ hooksDir: path35.join(dataDir2, "hooks")
7574
7909
  });
7575
7910
  proc = started.proc;
7576
7911
  const pb = new PocketBase5(started.url);
@@ -7611,72 +7946,6 @@ async function seedRemoteMeta(session, instance, local, appURL) {
7611
7946
  return Object.keys(patch);
7612
7947
  }
7613
7948
 
7614
- // src/lib/artifact.ts
7615
- import fs33 from "node:fs";
7616
- import path35 from "node:path";
7617
- import { detect as detect6 } from "package-manager-detector";
7618
- import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
7619
- var DEFAULT_OUTPUT_DIR = "build";
7620
- var BuildError = class extends Error {
7621
- };
7622
- async function runBuild(cwd, buildCommand, env2) {
7623
- if (buildCommand) {
7624
- const result2 = await spawnCapture("bash", ["-lc", buildCommand], {
7625
- cwd,
7626
- stream: true,
7627
- streamStdout: true,
7628
- env: env2
7629
- });
7630
- if (result2.exitCode !== 0)
7631
- throw new BuildError(`\`${buildCommand}\` exited ${result2.exitCode}.`);
7632
- return;
7633
- }
7634
- const pm = (await detect6({ cwd }))?.name ?? "npm";
7635
- const resolved = resolveCommand6(pm, "run", ["build"]);
7636
- if (!resolved) throw new BuildError(`Could not work out how to run a build with ${pm}.`);
7637
- const result = await spawnCapture(resolved.command, resolved.args, {
7638
- cwd,
7639
- stream: true,
7640
- streamStdout: true,
7641
- env: env2
7642
- });
7643
- if (result.exitCode !== 0) {
7644
- throw new BuildError(
7645
- `\`${resolved.command} ${resolved.args.join(" ")}\` exited ${result.exitCode}.`
7646
- );
7647
- }
7648
- }
7649
- function collectArtifact(cwd, config = {}) {
7650
- const outputDir = config.outputDir ?? DEFAULT_OUTPUT_DIR;
7651
- const entries = [];
7652
- const add2 = (rel, remoteDir = "") => {
7653
- const localPath = path35.join(cwd, rel);
7654
- if (fs33.existsSync(localPath)) entries.push({ localPath, remoteDir });
7655
- };
7656
- const buildPath = path35.join(cwd, outputDir);
7657
- if (!fs33.existsSync(path35.join(buildPath, "index.js"))) {
7658
- throw new BuildError(
7659
- `No ${outputDir}/index.js after the build.
7660
-
7661
- Deploying to a server needs @sveltejs/adapter-node. Install it and set it as
7662
- the adapter in your Vite or Svelte config, then build again.`
7663
- );
7664
- }
7665
- entries.push({ localPath: buildPath, remoteDir: "" });
7666
- add2("package.json");
7667
- add2("package-lock.json");
7668
- add2(".npmrc");
7669
- add2(MIGRATIONS_DIR);
7670
- const hooks = path35.join(cwd, DATA_DIR, "hooks");
7671
- if (fs33.existsSync(hooks)) entries.push({ localPath: hooks, remoteDir: "hooks" });
7672
- for (const extra of config.include ?? []) add2(extra);
7673
- return entries;
7674
- }
7675
- async function gitSha(cwd) {
7676
- const result = await spawnCapture("git", ["rev-parse", "HEAD"], { cwd });
7677
- return result.exitCode === 0 ? result.stdout.trim() : "";
7678
- }
7679
-
7680
7949
  // src/commands/deploy.ts
7681
7950
  var OptionsSchema3 = v7.object({
7682
7951
  ...SSH_OPTION_SCHEMA,
@@ -7690,7 +7959,7 @@ var OptionsSchema3 = v7.object({
7690
7959
  build: v7.optional(v7.boolean())
7691
7960
  });
7692
7961
  var deploy = addTargetOptions(
7693
- new Command75("deploy").description("deploy the app").configureHelp(helpConfig),
7962
+ new Command76("deploy").description("deploy the app").configureHelp(helpConfig),
7694
7963
  "production"
7695
7964
  ).option("--project <name>", "override the project name").option("--domain <hosts>", "hostname(s) to serve on, comma separated").option("--health-path <path>", "path the health check requests").option("--keep <count>", "how many old releases to keep on the server").option("--pb-version <version>", "PocketBase version to run").option("--no-build", "deploy the existing build output without rebuilding").addOption(
7696
7965
  new Option2(
@@ -7706,119 +7975,172 @@ var deploy = addTargetOptions(
7706
7975
  const options = parseOptions(OptionsSchema3, raw);
7707
7976
  const backend3 = hasBackend();
7708
7977
  const release = releaseId();
7709
- p40.intro(pc16.bgCyan(pc16.black(" vela deploy ")));
7978
+ p42.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
7710
7979
  await withTarget(
7711
7980
  raw,
7712
7981
  {
7713
7982
  remote: async (ctx) => {
7714
7983
  const { session, instance, workspaceRootDir, config } = ctx;
7715
- p40.log.info(
7716
- `${pc16.cyan(ctx.appName)} ${pc16.dim("\u2192")} ${pc16.cyan(ctx.targetName)} ${pc16.dim(`(${ctx.server})`)}`
7984
+ p42.log.info(
7985
+ `${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
7717
7986
  );
7718
7987
  const [existing] = await readInstanceStates(session, instance);
7719
- const domain = options.domain ?? ctx.binding.domain ?? config.deploy?.domain ?? existing?.domain ?? "";
7988
+ const isPreview = ctx.target.kind === "preview";
7989
+ const configured = options.domain ?? (isPreview ? existing?.domain : ctx.binding.domain ?? config.deploy?.domain ?? existing?.domain) ?? "";
7720
7990
  const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
7721
7991
  const remoteDb = askedForRemoteDb ?? Boolean(existing?.pbPort);
7722
- if (options.build !== false) {
7723
- const origin = normalizeOrigin(process.env.VELA_ORIGIN ?? domain);
7724
- let buildEnv = origin ? { VELA_ORIGIN: origin } : {};
7725
- let tunnel = null;
7726
- if (backend3 && remoteDb) {
7727
- try {
7728
- tunnel = await openDatabaseTunnel(session, instance, existing);
7729
- } catch (err) {
7730
- if (askedForRemoteDb) throw err;
7731
- p40.log.warn(
7732
- `Could not build against the ${pc16.cyan(ctx.targetName)} database, using a local one instead.
7733
- ${pc16.dim(String(err))}`
7992
+ const sha = await gitSha(workspaceRootDir);
7993
+ const reporter = createDeployReporter(workspaceRootDir);
7994
+ const server = await reporter.identifyServer(session);
7995
+ const started = await reporter.start({
7996
+ target: ctx.target.kind === "preview" ? "preview" : ctx.targetName,
7997
+ env_tag: ctx.envTag,
7998
+ branch: ctx.target.kind === "preview" ? ctx.target.branch : void 0,
7999
+ git_sha: sha || void 0,
8000
+ hostnames: splitHosts(configured),
8001
+ server: server ? { id: server.serverId, token: server.token } : void 0
8002
+ });
8003
+ const directHosts = [
8004
+ .../* @__PURE__ */ new Set([...splitHosts(configured), ...started?.environment.direct ?? []])
8005
+ ];
8006
+ const managedHosts = started?.environment.managed ?? [];
8007
+ const domain = directHosts.join(",");
8008
+ const managed = managedHosts.join(",");
8009
+ const primaryHost = directHosts[0] ?? managedHosts[0] ?? "";
8010
+ const primaryUrl = started?.environment.primaryUrl || normalizeOrigin(primaryHost) || "";
8011
+ if (isPreview && !primaryHost) {
8012
+ throw new Error(
8013
+ `Nothing routes to this preview.
8014
+
8015
+ Previews get a free velastack.app hostname from velastack.dev: ${pc18.cyan("vela link")} the
8016
+ project and ${pc18.cyan("vela login")} (or set ${pc18.cyan("VELA_API_KEY")}). Or pass ${pc18.cyan("--domain <host>")}
8017
+ with DNS of your own pointing at ${ctx.server}.`
8018
+ );
8019
+ }
8020
+ let result = null;
8021
+ try {
8022
+ if (options.build !== false) {
8023
+ const origin = normalizeOrigin(process.env.VELA_ORIGIN ?? primaryUrl);
8024
+ let buildEnv = origin ? { VELA_ORIGIN: origin } : {};
8025
+ let tunnel = null;
8026
+ if (backend3 && remoteDb) {
8027
+ try {
8028
+ tunnel = await openDatabaseTunnel(session, instance, existing);
8029
+ } catch (err) {
8030
+ if (askedForRemoteDb) throw err;
8031
+ p42.log.warn(
8032
+ `Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
8033
+ ${pc18.dim(String(err))}`
8034
+ );
8035
+ }
8036
+ }
8037
+ if (tunnel) {
8038
+ buildEnv = { ...buildEnv, ...tunnel.env };
8039
+ p42.log.info(
8040
+ `Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
7734
8041
  );
8042
+ } else if (backend3) {
8043
+ await ensureSuperuser(workspaceRootDir);
8044
+ }
8045
+ p42.log.step("Building");
8046
+ try {
8047
+ await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
8048
+ } finally {
8049
+ if (tunnel) await tunnel.close();
7735
8050
  }
7736
8051
  }
7737
- if (tunnel) {
7738
- buildEnv = { ...buildEnv, ...tunnel.env };
7739
- p40.log.info(
7740
- `Building against the ${pc16.cyan(ctx.targetName)} database on ${ctx.server} ${pc16.dim(`(port ${tunnel.pbPort})`)}`
7741
- );
7742
- } else if (backend3) {
7743
- await ensureSuperuser(workspaceRootDir);
7744
- }
7745
- p40.log.step("Building");
7746
- try {
7747
- await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
7748
- } finally {
7749
- if (tunnel) await tunnel.close();
7750
- }
8052
+ const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
8053
+ p42.log.step(`Uploading release ${pc18.dim(release)}`);
8054
+ await uploadRelease(session, instance, release, entries);
8055
+ p42.log.step("Activating");
8056
+ result = await runServerScript(session, "apply.sh", {
8057
+ args: [
8058
+ instance,
8059
+ release,
8060
+ "--name",
8061
+ ctx.appName,
8062
+ "--app-id",
8063
+ ctx.appId,
8064
+ "--env",
8065
+ ctx.envTag,
8066
+ "--domain",
8067
+ domain,
8068
+ "--managed",
8069
+ managed,
8070
+ "--health-path",
8071
+ options.healthPath ?? config.deploy?.healthCheckPath ?? "/",
8072
+ "--keep",
8073
+ options.keep ?? String(config.deploy?.keepReleases ?? 5),
8074
+ "--backend",
8075
+ backend3 ? "1" : "0",
8076
+ "--pb-version",
8077
+ options.pbVersion ?? config.deploy?.pocketbaseVersion ?? pocketbaseVersion(),
8078
+ "--git-sha",
8079
+ sha
8080
+ ],
8081
+ stream: true
8082
+ });
8083
+ } catch (err) {
8084
+ await reporter.finish({
8085
+ status: "failed",
8086
+ error: err instanceof Error ? err.message : String(err)
8087
+ });
8088
+ throw err;
7751
8089
  }
7752
- const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
7753
- const sha = await gitSha(workspaceRootDir);
7754
- p40.log.step(`Uploading release ${pc16.dim(release)}`);
7755
- await uploadRelease(session, instance, release, entries);
7756
- p40.log.step("Activating");
7757
- const result = await runServerScript(session, "apply.sh", {
7758
- args: [
7759
- instance,
7760
- release,
7761
- "--name",
7762
- ctx.appName,
7763
- "--app-id",
7764
- ctx.appId,
7765
- "--env",
7766
- ctx.envTag,
7767
- "--domain",
7768
- domain,
7769
- "--health-path",
7770
- options.healthPath ?? config.deploy?.healthCheckPath ?? "/",
7771
- "--keep",
7772
- options.keep ?? String(config.deploy?.keepReleases ?? 5),
7773
- "--backend",
7774
- backend3 ? "1" : "0",
7775
- "--pb-version",
7776
- options.pbVersion ?? config.deploy?.pocketbaseVersion ?? pocketbaseVersion(),
7777
- "--git-sha",
7778
- sha
7779
- ],
7780
- stream: true
7781
- });
7782
- writeBinding(workspaceRootDir, ctx.envTag, {
7783
- server: ctx.server,
7784
- domain: domain || void 0
7785
- });
8090
+ writeBinding(
8091
+ workspaceRootDir,
8092
+ bindingKey(ctx.target),
8093
+ isPreview ? { server: ctx.server } : { server: ctx.server, domain: domain || void 0 }
8094
+ );
7786
8095
  if (!existing) await reportEmptyEnvironment(session, instance, workspaceRootDir);
7787
8096
  const url = result?.url ?? "";
7788
- p40.log.success(
7789
- `Deployed ${pc16.cyan(ctx.appName)} ${pc16.dim(release)}
8097
+ await reporter.finish({
8098
+ status: "deployed",
8099
+ release,
8100
+ // Without a host the server answers with a loopback URL, which
8101
+ // is nothing to link to from a dashboard.
8102
+ url: primaryHost ? url : void 0
8103
+ });
8104
+ const redirects = started?.environment.redirects ?? [];
8105
+ p42.log.success(
8106
+ `Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
7790
8107
 
7791
8108
  URL ${url}
7792
- Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
8109
+ ` + (redirects.length ? ` Also ${redirects.map((h) => `https://${h}`).join(", ")} ${pc18.dim("(redirects here)")}
8110
+ ` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
7793
8111
  );
8112
+ if (managed && managed !== existing?.managed) {
8113
+ p42.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
8114
+ }
7794
8115
  if (result?.superuserCreated) {
7795
8116
  await copyLocalBranding(
7796
8117
  session,
7797
8118
  instance,
7798
8119
  workspaceRootDir,
7799
- domain ? result?.url ?? "" : ""
8120
+ primaryHost ? result?.url ?? "" : ""
7800
8121
  );
7801
- p40.log.info(
8122
+ p42.log.info(
7802
8123
  `Created the PocketBase superuser this app authenticates as.
7803
8124
 
7804
8125
  Its credentials are stored in the environment on the server. To use
7805
- your own instead, ${pc16.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
8126
+ your own instead, ${pc18.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
7806
8127
  and deploy again.`
7807
8128
  );
7808
- } else if (backend3 && domain) {
7809
- await reportAppURLDrift(session, instance, domain);
8129
+ } else if (backend3 && primaryHost) {
8130
+ await reportAppURLDrift(session, instance, primaryHost);
7810
8131
  }
7811
- if (!domain) {
7812
- p40.log.warn(
8132
+ if (!primaryHost) {
8133
+ p42.log.warn(
7813
8134
  `No domain configured, so nothing is proxied to this app yet.
7814
- Redeploy with ${pc16.cyan("--domain example.com")} once DNS points at ${ctx.server}.`
8135
+ Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
8136
+ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
7815
8137
  );
7816
8138
  }
7817
8139
  }
7818
8140
  },
7819
8141
  { project: options.project, askDomain: true, label: "deploy" }
7820
8142
  );
7821
- p40.outro(`${pc16.cyan("vela status")} to see what is running`);
8143
+ p42.outro(`${pc18.cyan("vela status")} to see what is running`);
7822
8144
  }, "Failed to deploy.")
7823
8145
  );
7824
8146
  async function reportAppURLDrift(session, instance, domain) {
@@ -7826,8 +8148,8 @@ async function reportAppURLDrift(session, instance, domain) {
7826
8148
  if (!expected) return;
7827
8149
  const current = await readRemoteAppURL(session, instance);
7828
8150
  if (!current || normalizeOrigin(current) === expected) return;
7829
- p40.log.warn(
7830
- `This app's PocketBase ${pc16.cyan("appURL")} is ${pc16.dim(current)}, but it is served on ${pc16.dim(expected)}.
8151
+ p42.log.warn(
8152
+ `This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
7831
8153
 
7832
8154
  Emails and anything else PocketBase links to will use the former. Update it in
7833
8155
  the admin panel if that is not deliberate.`
@@ -7841,17 +8163,17 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
7841
8163
  if (copied.length === 0) return;
7842
8164
  const outcome = await restartInstance(session, instance);
7843
8165
  if (outcome.deployed && !outcome.restarted) {
7844
- p40.log.warn(
8166
+ p42.log.warn(
7845
8167
  `Copied ${copied.join(", ")}, but the app did not restart to pick them up.
7846
- ${pc16.dim(outcome.error ?? "")}`
8168
+ ${pc18.dim(outcome.error ?? "")}`
7847
8169
  );
7848
8170
  return;
7849
8171
  }
7850
- p40.log.success(`Copied ${copied.join(", ")} from this project's database`);
8172
+ p42.log.success(`Copied ${copied.join(", ")} from this project's database`);
7851
8173
  } catch (err) {
7852
- p40.log.warn(
8174
+ p42.log.warn(
7853
8175
  `Could not copy this project's PocketBase settings across.
7854
- Set them in the admin panel instead. ${pc16.dim(String(err))}`
8176
+ Set them in the admin panel instead. ${pc18.dim(String(err))}`
7855
8177
  );
7856
8178
  }
7857
8179
  }
@@ -7883,13 +8205,13 @@ Set them with \`vela env set POCKETBASE_SUPERUSER_EMAIL\` and \`vela env set POC
7883
8205
 
7884
8206
  They are what \`--remote-db\` renders the build as. The usual cause is a password
7885
8207
  changed in the PocketBase admin panel, which leaves the database and
7886
- ${pc16.cyan(`/etc/vela/apps/${instance}/env`)} disagreeing.
8208
+ ${pc18.cyan(`/etc/vela/apps/${instance}/env`)} disagreeing.
7887
8209
 
7888
8210
  Point the environment at the password the database has:
7889
- ${pc16.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
8211
+ ${pc18.cyan("vela env set POCKETBASE_SUPERUSER_PASSWORD")}
7890
8212
 
7891
8213
  or build against a throwaway local database instead:
7892
- ${pc16.cyan("vela deploy --no-remote-db")}`
8214
+ ${pc18.cyan("vela deploy --no-remote-db")}`
7893
8215
  );
7894
8216
  }
7895
8217
  return {
@@ -7942,75 +8264,26 @@ async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
7942
8264
  const remote = await readRemoteEnv(session, instance);
7943
8265
  if (Object.keys(remote).length > 0) return;
7944
8266
  if (!fs34.existsSync(path36.join(workspaceRootDir, ".env"))) return;
7945
- p40.log.warn(
8267
+ p42.log.warn(
7946
8268
  `This app has no production environment variables yet.
7947
8269
 
7948
- Local ${pc16.cyan(".env")} values are not uploaded by a deploy. Set them with
7949
- ${pc16.cyan("vela env set KEY")}, or copy a file across with ${pc16.cyan("vela env import .env.production")}.`
8270
+ Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
8271
+ ${pc18.cyan("vela env set KEY")}, or copy a file across with ${pc18.cyan("vela env import .env.production")}.`
7950
8272
  );
7951
8273
  }
7952
8274
 
7953
8275
  // src/commands/link.ts
7954
8276
  import path37 from "node:path";
7955
- import process26 from "node:process";
7956
- import { Command as Command76 } from "commander";
7957
- import * as p41 from "@clack/prompts";
7958
-
7959
- // src/lib/velastack-api.ts
7960
- async function apiFetch(apiKey, pathAndQuery, init) {
7961
- const headers = new Headers(init?.headers);
7962
- headers.set("Authorization", `Bearer ${apiKey}`);
7963
- if (init?.body && !headers.has("Content-Type")) {
7964
- headers.set("Content-Type", "application/json");
7965
- }
7966
- const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
7967
- if (res.status === 401 || res.status === 403) {
7968
- throw new Error("API key invalid \u2014 run `vela login`");
7969
- }
7970
- if (!res.ok) {
7971
- const body = await res.text().catch(() => "");
7972
- throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
7973
- }
7974
- return await res.json();
7975
- }
7976
- async function getCurrentUser(apiKey) {
7977
- const data = await apiFetch(
7978
- apiKey,
7979
- "/api/collections/users/records?perPage=1"
7980
- );
7981
- const user = data.items[0];
7982
- if (!user) throw new Error("No user found. Run `vela login` to login.");
7983
- return user;
7984
- }
7985
- async function listTeams(apiKey) {
7986
- const data = await apiFetch(
7987
- apiKey,
7988
- "/api/collections/teams/records?perPage=200"
7989
- );
7990
- return data.items;
7991
- }
7992
- async function listProjects(apiKey) {
7993
- const data = await apiFetch(
7994
- apiKey,
7995
- "/api/collections/projects/records?perPage=200&expand=team"
7996
- );
7997
- return data.items;
7998
- }
7999
- async function createProject2(apiKey, args) {
8000
- return apiFetch(apiKey, "/api/collections/projects/records", {
8001
- method: "POST",
8002
- body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
8003
- });
8004
- }
8005
-
8006
- // src/commands/link.ts
8277
+ import process28 from "node:process";
8278
+ import { Command as Command77 } from "commander";
8279
+ import * as p43 from "@clack/prompts";
8007
8280
  var CREATE_NEW = "__new__";
8008
- var link = new Command76("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
8281
+ var link = new Command77("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
8009
8282
  async function linkProject() {
8010
8283
  const { workspaceRootDir } = await getWorkspace();
8011
8284
  const existing = readProjectConfig(workspaceRootDir);
8012
8285
  if (existing) {
8013
- p41.log.success(`Linked to ${existing.projectName}.`);
8286
+ p43.log.success(`Linked to ${existing.projectName}.`);
8014
8287
  return;
8015
8288
  }
8016
8289
  const apiKey = requireApiKey();
@@ -8037,10 +8310,10 @@ async function linkProject() {
8037
8310
  projectName = created.name;
8038
8311
  }
8039
8312
  writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
8040
- p41.log.success(`Linked to ${projectName}.`);
8313
+ p43.log.success(`Linked to ${projectName}.`);
8041
8314
  }
8042
8315
  async function pickExistingProject(projects) {
8043
- const choice = await p41.select({
8316
+ const choice = await p43.select({
8044
8317
  message: "Select a project",
8045
8318
  options: [
8046
8319
  ...projects.map((pr) => ({
@@ -8050,39 +8323,39 @@ async function pickExistingProject(projects) {
8050
8323
  { value: CREATE_NEW, label: "Create a new project" }
8051
8324
  ]
8052
8325
  });
8053
- if (p41.isCancel(choice)) {
8054
- p41.cancel("Operation cancelled.");
8055
- process26.exit(0);
8326
+ if (p43.isCancel(choice)) {
8327
+ p43.cancel("Operation cancelled.");
8328
+ process28.exit(0);
8056
8329
  }
8057
8330
  return choice;
8058
8331
  }
8059
8332
  async function pickTeam(teams3) {
8060
8333
  if (teams3.length === 1) return teams3[0];
8061
- const choice = await p41.select({
8334
+ const choice = await p43.select({
8062
8335
  message: "Select a team",
8063
8336
  options: teams3.map((team) => ({
8064
8337
  value: team.id,
8065
8338
  label: team.is_personal ? `${team.name} (personal)` : team.name
8066
8339
  }))
8067
8340
  });
8068
- if (p41.isCancel(choice)) {
8069
- p41.cancel("Operation cancelled.");
8070
- process26.exit(0);
8341
+ if (p43.isCancel(choice)) {
8342
+ p43.cancel("Operation cancelled.");
8343
+ process28.exit(0);
8071
8344
  }
8072
8345
  return teams3.find((team) => team.id === choice);
8073
8346
  }
8074
8347
  async function promptProjectName(workspaceRootDir) {
8075
8348
  const defaultValue = defaultProjectName2(workspaceRootDir);
8076
- const value = await p41.text({
8349
+ const value = await p43.text({
8077
8350
  message: "Project name",
8078
8351
  defaultValue,
8079
8352
  initialValue: defaultValue,
8080
8353
  placeholder: defaultValue,
8081
8354
  validate: (v9) => !v9?.trim() ? "Required" : void 0
8082
8355
  });
8083
- if (p41.isCancel(value)) {
8084
- p41.cancel("Operation cancelled.");
8085
- process26.exit(0);
8356
+ if (p43.isCancel(value)) {
8357
+ p43.cancel("Operation cancelled.");
8358
+ process28.exit(0);
8086
8359
  }
8087
8360
  return value.trim();
8088
8361
  }
@@ -8097,14 +8370,14 @@ function defaultProjectName2(workspaceRootDir) {
8097
8370
  }
8098
8371
 
8099
8372
  // src/commands/env.ts
8100
- import { Command as Command81 } from "commander";
8373
+ import { Command as Command82 } from "commander";
8101
8374
 
8102
8375
  // src/commands/env/list.ts
8103
- import { Command as Command77 } from "commander";
8104
- import * as p42 from "@clack/prompts";
8105
- import pc17 from "picocolors";
8376
+ import { Command as Command78 } from "commander";
8377
+ import * as p44 from "@clack/prompts";
8378
+ import pc19 from "picocolors";
8106
8379
  var envList = addTargetOptions(
8107
- new Command77("list").description("list environment variable names").configureHelp(helpConfig),
8380
+ new Command78("list").description("list environment variable names").configureHelp(helpConfig),
8108
8381
  "local"
8109
8382
  ).action(
8110
8383
  (raw) => runCommand(
@@ -8126,23 +8399,23 @@ var envList = addTargetOptions(
8126
8399
  );
8127
8400
  function report(keys, where) {
8128
8401
  if (keys.length === 0) {
8129
- p42.log.info(`No environment variables configured ${pc17.dim(`(${where})`)}.`);
8402
+ p44.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
8130
8403
  return;
8131
8404
  }
8132
- p42.log.info(
8133
- `Environment ${pc17.dim(`(${where})`)}
8405
+ p44.log.info(
8406
+ `Environment ${pc19.dim(`(${where})`)}
8134
8407
 
8135
8408
  ` + keys.sort().map((key) => ` ${key}`).join("\n")
8136
8409
  );
8137
8410
  }
8138
8411
 
8139
8412
  // src/commands/env/set.ts
8140
- import process27 from "node:process";
8141
- import { Command as Command78 } from "commander";
8142
- import * as p43 from "@clack/prompts";
8143
- import pc18 from "picocolors";
8413
+ import process29 from "node:process";
8414
+ import { Command as Command79 } from "commander";
8415
+ import * as p45 from "@clack/prompts";
8416
+ import pc20 from "picocolors";
8144
8417
  var envSet = addTargetOptions(
8145
- new Command78("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
8418
+ new Command79("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
8146
8419
  "local"
8147
8420
  ).action(
8148
8421
  (key, value, raw) => runCommand(
@@ -8152,14 +8425,14 @@ var envSet = addTargetOptions(
8152
8425
  local: async (ctx) => {
8153
8426
  const resolved = await resolveValue(key, value);
8154
8427
  setLocalEnv(ctx.envFile, key, resolved);
8155
- p43.log.success(`${key} updated ${pc18.dim("(local)")}`);
8428
+ p45.log.success(`${key} updated ${pc20.dim("(local)")}`);
8156
8429
  await applyLocalEnvChange(ctx, [key]);
8157
8430
  },
8158
8431
  remote: async (ctx) => {
8159
8432
  const resolved = await resolveValue(key, value);
8160
8433
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
8161
8434
  await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
8162
- p43.log.success(`${key} updated ${pc18.dim(`(${ctx.targetName})`)}`);
8435
+ p45.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
8163
8436
  await applyEnvRestart(ctx, [key]);
8164
8437
  }
8165
8438
  },
@@ -8173,23 +8446,23 @@ async function resolveValue(key, value) {
8173
8446
  return value ?? await promptValue(key);
8174
8447
  }
8175
8448
  async function promptValue(key) {
8176
- const value = await p43.password({
8177
- message: `Value for ${pc18.cyan(key)}`,
8449
+ const value = await p45.password({
8450
+ message: `Value for ${pc20.cyan(key)}`,
8178
8451
  validate: (input) => !input?.length ? "Required" : void 0
8179
8452
  });
8180
- if (p43.isCancel(value)) {
8181
- p43.cancel("Operation cancelled.");
8182
- process27.exit(0);
8453
+ if (p45.isCancel(value)) {
8454
+ p45.cancel("Operation cancelled.");
8455
+ process29.exit(0);
8183
8456
  }
8184
8457
  return value;
8185
8458
  }
8186
8459
 
8187
8460
  // src/commands/env/unset.ts
8188
- import { Command as Command79 } from "commander";
8189
- import * as p44 from "@clack/prompts";
8190
- import pc19 from "picocolors";
8461
+ import { Command as Command80 } from "commander";
8462
+ import * as p46 from "@clack/prompts";
8463
+ import pc21 from "picocolors";
8191
8464
  var envUnset = addTargetOptions(
8192
- new Command79("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
8465
+ new Command80("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
8193
8466
  "local"
8194
8467
  ).action(
8195
8468
  (key, raw) => runCommand(
@@ -8198,22 +8471,22 @@ var envUnset = addTargetOptions(
8198
8471
  {
8199
8472
  local: async (ctx) => {
8200
8473
  if (!(key in readLocalEnv(ctx.envFile))) {
8201
- p44.log.info(`${key} is not set \u2014 nothing to remove.`);
8474
+ p46.log.info(`${key} is not set \u2014 nothing to remove.`);
8202
8475
  return;
8203
8476
  }
8204
8477
  unsetLocalEnv(ctx.envFile, key);
8205
- p44.log.success(`${key} removed ${pc19.dim("(local)")}`);
8478
+ p46.log.success(`${key} removed ${pc21.dim("(local)")}`);
8206
8479
  await applyLocalEnvChange(ctx, [key]);
8207
8480
  },
8208
8481
  remote: async (ctx) => {
8209
8482
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
8210
8483
  if (!(key in env2)) {
8211
- p44.log.info(`${key} is not set \u2014 nothing to remove.`);
8484
+ p46.log.info(`${key} is not set \u2014 nothing to remove.`);
8212
8485
  return;
8213
8486
  }
8214
8487
  delete env2[key];
8215
8488
  await writeRemoteEnv(ctx.session, ctx.instance, env2);
8216
- p44.log.success(`${key} removed ${pc19.dim(`(${ctx.targetName})`)}`);
8489
+ p46.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
8217
8490
  await applyEnvRestart(ctx, [key]);
8218
8491
  }
8219
8492
  },
@@ -8226,12 +8499,12 @@ var envUnset = addTargetOptions(
8226
8499
  // src/commands/env/import.ts
8227
8500
  import fs35 from "node:fs";
8228
8501
  import path38 from "node:path";
8229
- import process28 from "node:process";
8230
- import { Command as Command80 } from "commander";
8231
- import * as p45 from "@clack/prompts";
8232
- import pc20 from "picocolors";
8502
+ import process30 from "node:process";
8503
+ import { Command as Command81 } from "commander";
8504
+ import * as p47 from "@clack/prompts";
8505
+ import pc22 from "picocolors";
8233
8506
  var envImport = addTargetOptions(
8234
- new Command80("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
8507
+ new Command81("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
8235
8508
  "local"
8236
8509
  ).action(
8237
8510
  (file, raw) => runCommand(
@@ -8246,22 +8519,22 @@ var envImport = addTargetOptions(
8246
8519
  const incoming = read(source, file);
8247
8520
  const keys = Object.keys(incoming);
8248
8521
  if (keys.length === 0) return;
8249
- p45.log.step(`Importing ${keys.length} variable(s) from ${pc20.cyan(file)}`);
8522
+ p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
8250
8523
  editLocalEnv(
8251
8524
  ctx.envFile,
8252
8525
  (content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
8253
8526
  );
8254
- p45.log.success(`${keys.length} variable(s) updated ${pc20.dim("(local)")}`);
8527
+ p47.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
8255
8528
  await applyLocalEnvChange(ctx, keys);
8256
8529
  },
8257
8530
  remote: async (ctx) => {
8258
8531
  const incoming = read(resolve(file), file);
8259
8532
  const keys = Object.keys(incoming);
8260
8533
  if (keys.length === 0) return;
8261
- p45.log.step(`Importing ${keys.length} variable(s) from ${pc20.cyan(file)}`);
8534
+ p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
8262
8535
  const existing = await readRemoteEnv(ctx.session, ctx.instance);
8263
8536
  await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
8264
- p45.log.success(`${keys.length} variable(s) updated ${pc20.dim(`(${ctx.targetName})`)}`);
8537
+ p47.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
8265
8538
  await applyEnvRestart(ctx, keys);
8266
8539
  }
8267
8540
  },
@@ -8271,24 +8544,24 @@ var envImport = addTargetOptions(
8271
8544
  )
8272
8545
  );
8273
8546
  function resolve(file) {
8274
- return path38.resolve(process28.cwd(), file);
8547
+ return path38.resolve(process30.cwd(), file);
8275
8548
  }
8276
8549
  function read(resolved, shown) {
8277
8550
  if (!fs35.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
8278
8551
  const incoming = readLocalEnvFile(resolved);
8279
- if (Object.keys(incoming).length === 0) p45.log.info(`${shown} has no variables to import.`);
8552
+ if (Object.keys(incoming).length === 0) p47.log.info(`${shown} has no variables to import.`);
8280
8553
  return incoming;
8281
8554
  }
8282
8555
 
8283
8556
  // src/commands/env.ts
8284
- var env = new Command81("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
8557
+ var env = new Command82("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
8285
8558
 
8286
8559
  // src/commands/status.ts
8287
- import { Command as Command82 } from "commander";
8288
- import * as p46 from "@clack/prompts";
8289
- import pc21 from "picocolors";
8560
+ import { Command as Command83 } from "commander";
8561
+ import * as p48 from "@clack/prompts";
8562
+ import pc23 from "picocolors";
8290
8563
  var status = addTargetOptions(
8291
- new Command82("status").description("show what is deployed").configureHelp(helpConfig),
8564
+ new Command83("status").description("show what is deployed").configureHelp(helpConfig),
8292
8565
  "production"
8293
8566
  ).option("--all", "show every app on the server, not just this project").option("--json", "print raw JSON").action(
8294
8567
  (raw) => runCommand(async () => {
@@ -8319,21 +8592,22 @@ function report2(states, json) {
8319
8592
  return;
8320
8593
  }
8321
8594
  if (states.length === 0) {
8322
- p46.log.info("Nothing is deployed here yet.");
8595
+ p48.log.info("Nothing is deployed here yet.");
8323
8596
  return;
8324
8597
  }
8325
8598
  for (const state of states) {
8326
- p46.log.info(describe(state));
8599
+ p48.log.info(describe(state));
8327
8600
  }
8328
8601
  }
8329
8602
  function describe(state) {
8330
- const health = (value) => value === "active" ? pc21.green(value) : pc21.red(value || "inactive");
8603
+ const health = (value) => value === "active" ? pc23.green(value) : pc23.red(value || "inactive");
8331
8604
  const rows = [
8332
8605
  ["Instance", state.instance],
8333
8606
  ["Environment", state.env],
8334
8607
  ["Release", state.activeRelease ?? "\u2014"],
8335
8608
  ["Previous", state.previousRelease || "\u2014"],
8336
8609
  ["Domain", state.domain || "\u2014"],
8610
+ ...state.managed ? [["Managed", state.managed]] : [],
8337
8611
  ["Ports", `web ${state.webPort ?? "?"}${state.backend ? `, pb ${state.pbPort ?? "?"}` : ""}`],
8338
8612
  ["App", health(state.services?.web)],
8339
8613
  ...state.backend ? [["PocketBase", health(state.services?.pocketbase)]] : [],
@@ -8342,15 +8616,15 @@ function describe(state) {
8342
8616
  ...state.gitSha ? [["Commit", state.gitSha.slice(0, 12)]] : []
8343
8617
  ];
8344
8618
  const width = Math.max(...rows.map(([label4]) => label4.length));
8345
- return pc21.cyan(state.name) + "\n\n" + rows.map(([label4, value]) => ` ${label4.padEnd(width)} ${value}`).join("\n");
8619
+ return pc23.cyan(state.name) + "\n\n" + rows.map(([label4, value]) => ` ${label4.padEnd(width)} ${value}`).join("\n");
8346
8620
  }
8347
8621
 
8348
8622
  // src/commands/rollback.ts
8349
- import { Command as Command83 } from "commander";
8350
- import * as p47 from "@clack/prompts";
8351
- import pc22 from "picocolors";
8623
+ import { Command as Command84 } from "commander";
8624
+ import * as p49 from "@clack/prompts";
8625
+ import pc24 from "picocolors";
8352
8626
  var rollback = addTargetOptions(
8353
- new Command83("rollback").description("put the previous release back").configureHelp(helpConfig),
8627
+ new Command84("rollback").description("put the previous release back").configureHelp(helpConfig),
8354
8628
  "production"
8355
8629
  ).option("--to <release>", "roll back to a specific release instead of the previous one").action(
8356
8630
  (raw) => runCommand(async () => {
@@ -8359,8 +8633,8 @@ var rollback = addTargetOptions(
8359
8633
  raw,
8360
8634
  {
8361
8635
  remote: async (ctx) => {
8362
- p47.log.step(
8363
- `Rolling back ${pc22.cyan(ctx.appName)} ${pc22.dim(`(${ctx.targetName})`)} on ${ctx.server}`
8636
+ p49.log.step(
8637
+ `Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
8364
8638
  );
8365
8639
  const result = await runServerScript(
8366
8640
  ctx.session,
@@ -8370,8 +8644,8 @@ var rollback = addTargetOptions(
8370
8644
  stream: true
8371
8645
  }
8372
8646
  );
8373
- p47.log.success(
8374
- `Rolled back to ${pc22.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc22.dim(`(was ${result.from})`)}` : "")
8647
+ p49.log.success(
8648
+ `Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
8375
8649
  );
8376
8650
  }
8377
8651
  },
@@ -8384,9 +8658,9 @@ var rollback = addTargetOptions(
8384
8658
  );
8385
8659
 
8386
8660
  // src/commands/logs.ts
8387
- import { Command as Command84 } from "commander";
8661
+ import { Command as Command85 } from "commander";
8388
8662
  var logs = addTargetOptions(
8389
- new Command84("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
8663
+ new Command85("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
8390
8664
  "production"
8391
8665
  ).option("-f, --follow", "keep streaming new output").option("-n, --lines <count>", "how many lines of history to show", "100").option("--pocketbase", "show the PocketBase service instead of the app").action(
8392
8666
  (raw) => runCommand(async () => {
@@ -8420,16 +8694,16 @@ var logs = addTargetOptions(
8420
8694
  );
8421
8695
 
8422
8696
  // src/commands/admin.ts
8423
- import { Command as Command86 } from "commander";
8697
+ import { Command as Command87 } from "commander";
8424
8698
 
8425
8699
  // src/commands/admin/create.ts
8426
- import process29 from "node:process";
8427
- import { Command as Command85 } from "commander";
8428
- import * as p48 from "@clack/prompts";
8429
- import pc23 from "picocolors";
8700
+ import process31 from "node:process";
8701
+ import { Command as Command86 } from "commander";
8702
+ import * as p50 from "@clack/prompts";
8703
+ import pc25 from "picocolors";
8430
8704
  var MIN_PASSWORD = 10;
8431
8705
  var adminCreate = addTargetOptions(
8432
- new Command85("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
8706
+ new Command86("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
8433
8707
  "local"
8434
8708
  ).action(
8435
8709
  (email3, raw) => runCommand(
@@ -8457,8 +8731,8 @@ var adminCreate = addTargetOptions(
8457
8731
  const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
8458
8732
  if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
8459
8733
  }
8460
- p48.log.info(
8461
- signIn ? `Sign in at ${pc23.cyan(`${signIn}/admin`)}` : `Sign in at ${pc23.cyan("/admin")} once ${pc23.cyan("vela dev")} is running.`
8734
+ p50.log.info(
8735
+ signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
8462
8736
  );
8463
8737
  },
8464
8738
  remote: async (ctx) => {
@@ -8471,8 +8745,8 @@ var adminCreate = addTargetOptions(
8471
8745
  (pb) => upsertSuperuser(pb, address, password11)
8472
8746
  );
8473
8747
  const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
8474
- p48.log.info(
8475
- base2 ? `Sign in at ${pc23.cyan(`${base2}/admin`)}` : `Sign in at ${pc23.cyan("/admin")} once a domain is configured for this target.`
8748
+ p50.log.info(
8749
+ base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
8476
8750
  );
8477
8751
  }
8478
8752
  },
@@ -8484,20 +8758,20 @@ var adminCreate = addTargetOptions(
8484
8758
  async function upsertSuperuser(pb, email3, password11) {
8485
8759
  const existing = await findSuperuser(pb, email3);
8486
8760
  if (existing) {
8487
- const confirmed = await p48.confirm({
8761
+ const confirmed = await p50.confirm({
8488
8762
  message: `${email3} already has an account, update its password?`,
8489
8763
  initialValue: false
8490
8764
  });
8491
- if (p48.isCancel(confirmed) || !confirmed) {
8492
- p48.cancel("Operation cancelled.");
8493
- process29.exit(0);
8765
+ if (p50.isCancel(confirmed) || !confirmed) {
8766
+ p50.cancel("Operation cancelled.");
8767
+ process31.exit(0);
8494
8768
  }
8495
8769
  await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
8496
- p48.log.success(`Password updated for ${pc23.cyan(email3)}, you can sign in now`);
8770
+ p50.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
8497
8771
  return;
8498
8772
  }
8499
8773
  await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
8500
- p48.log.success(`${pc23.cyan(email3)} can now sign in`);
8774
+ p50.log.success(`${pc25.cyan(email3)} can now sign in`);
8501
8775
  }
8502
8776
  async function findSuperuser(pb, email3) {
8503
8777
  try {
@@ -8508,48 +8782,48 @@ async function findSuperuser(pb, email3) {
8508
8782
  }
8509
8783
  }
8510
8784
  async function promptEmail() {
8511
- const value = await p48.text({
8785
+ const value = await p50.text({
8512
8786
  message: "Email to sign in with",
8513
8787
  validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
8514
8788
  });
8515
- if (p48.isCancel(value)) {
8516
- p48.cancel("Operation cancelled.");
8517
- process29.exit(0);
8789
+ if (p50.isCancel(value)) {
8790
+ p50.cancel("Operation cancelled.");
8791
+ process31.exit(0);
8518
8792
  }
8519
8793
  return value.trim();
8520
8794
  }
8521
8795
  async function promptPassword2() {
8522
- const value = await p48.password({
8796
+ const value = await p50.password({
8523
8797
  message: "Password",
8524
8798
  validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
8525
8799
  });
8526
- if (p48.isCancel(value)) {
8527
- p48.cancel("Operation cancelled.");
8528
- process29.exit(0);
8800
+ if (p50.isCancel(value)) {
8801
+ p50.cancel("Operation cancelled.");
8802
+ process31.exit(0);
8529
8803
  }
8530
- const again = await p48.password({
8804
+ const again = await p50.password({
8531
8805
  message: "Password again",
8532
8806
  validate: (input) => input === value ? void 0 : "The two do not match"
8533
8807
  });
8534
- if (p48.isCancel(again)) {
8535
- p48.cancel("Operation cancelled.");
8536
- process29.exit(0);
8808
+ if (p50.isCancel(again)) {
8809
+ p50.cancel("Operation cancelled.");
8810
+ process31.exit(0);
8537
8811
  }
8538
8812
  return value;
8539
8813
  }
8540
8814
 
8541
8815
  // src/commands/admin.ts
8542
- var admin = new Command86("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
8816
+ var admin = new Command87("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
8543
8817
 
8544
8818
  // src/commands/backup.ts
8545
- import { Command as Command92 } from "commander";
8819
+ import { Command as Command93 } from "commander";
8546
8820
 
8547
8821
  // src/commands/backup/create.ts
8548
8822
  import fs36 from "node:fs";
8549
8823
  import path39 from "node:path";
8550
- import { Command as Command87 } from "commander";
8551
- import * as p49 from "@clack/prompts";
8552
- import pc24 from "picocolors";
8824
+ import { Command as Command88 } from "commander";
8825
+ import * as p51 from "@clack/prompts";
8826
+ import pc26 from "picocolors";
8553
8827
 
8554
8828
  // src/lib/backups.ts
8555
8829
  var BACKUP_KEY = /^[a-z0-9_-]+\.zip$/;
@@ -8636,7 +8910,7 @@ async function writeSchedule(pb, cron, maxKeep) {
8636
8910
  // src/commands/backup/create.ts
8637
8911
  var DEFAULT_BACKUP_DIR = "backups";
8638
8912
  var backupCreate = addTargetOptions(
8639
- new Command87("create").description("take a backup of the database and uploads").argument("[name]", "name for the archive \u2014 generated when omitted").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).option("--no-download", "leave the archive on the server").configureHelp(helpConfig),
8913
+ new Command88("create").description("take a backup of the database and uploads").argument("[name]", "name for the archive \u2014 generated when omitted").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).option("--no-download", "leave the archive on the server").configureHelp(helpConfig),
8640
8914
  "production"
8641
8915
  ).action(
8642
8916
  (name, raw) => runCommand(() => {
@@ -8645,22 +8919,22 @@ var backupCreate = addTargetOptions(
8645
8919
  const key = name ?? backupName(ctx.instance);
8646
8920
  if (!isBackupKey(key)) {
8647
8921
  throw new Error(
8648
- `${pc24.cyan(key)} is not a name PocketBase will accept.
8922
+ `${pc26.cyan(key)} is not a name PocketBase will accept.
8649
8923
 
8650
- Backup names are lowercase letters, digits, ${pc24.cyan("-")} and ${pc24.cyan("_")}, ending in ${pc24.cyan(".zip")}.`
8924
+ Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_")}, ending in ${pc26.cyan(".zip")}.`
8651
8925
  );
8652
8926
  }
8653
8927
  const storage = await readStorageSettings(ctx.pb);
8654
8928
  if (storage.s3Enabled) {
8655
- p49.log.warn(
8929
+ p51.log.warn(
8656
8930
  `Uploads are stored in S3, so this archive holds the database only.
8657
8931
 
8658
- PocketBase leaves ${pc24.cyan("storage/")} out of a backup whenever S3 is on.
8932
+ PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
8659
8933
  Your bucket's own versioning is what protects the uploaded files.`
8660
8934
  );
8661
8935
  }
8662
8936
  if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
8663
- const spinner7 = p49.spinner();
8937
+ const spinner7 = p51.spinner();
8664
8938
  spinner7.start(`Backing up ${ctx.targetName}`);
8665
8939
  try {
8666
8940
  await createBackup(ctx.pb, key);
@@ -8707,7 +8981,7 @@ async function download(ctx, key, outputDir) {
8707
8981
  fs36.copyFileSync(path39.join(ctx.workspaceRootDir, "data", "backups", key), destination);
8708
8982
  return path39.relative(ctx.workspaceRootDir, destination);
8709
8983
  }
8710
- const spinner7 = p49.spinner();
8984
+ const spinner7 = p51.spinner();
8711
8985
  spinner7.start(`Downloading ${key}`);
8712
8986
  try {
8713
8987
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -8720,28 +8994,28 @@ async function download(ctx, key, outputDir) {
8720
8994
  }
8721
8995
 
8722
8996
  // src/commands/backup/list.ts
8723
- import { Command as Command88 } from "commander";
8724
- import * as p50 from "@clack/prompts";
8725
- import pc25 from "picocolors";
8997
+ import { Command as Command89 } from "commander";
8998
+ import * as p52 from "@clack/prompts";
8999
+ import pc27 from "picocolors";
8726
9000
  var backupList = addTargetOptions(
8727
- new Command88("list").description("list the backups on a target").configureHelp(helpConfig),
9001
+ new Command89("list").description("list the backups on a target").configureHelp(helpConfig),
8728
9002
  "production"
8729
9003
  ).action(
8730
9004
  (raw) => runCommand(
8731
9005
  () => withBackupTarget(raw, "backup list", async (ctx) => {
8732
9006
  const backups = await listBackups(ctx.pb);
8733
9007
  if (backups.length === 0) {
8734
- p50.log.info(
8735
- `${pc25.cyan(ctx.targetName)} has no backups yet.
9008
+ p52.log.info(
9009
+ `${pc27.cyan(ctx.targetName)} has no backups yet.
8736
9010
 
8737
- Take one with ${pc25.cyan("vela backup create")}.`
9011
+ Take one with ${pc27.cyan("vela backup create")}.`
8738
9012
  );
8739
9013
  return;
8740
9014
  }
8741
9015
  const width = Math.max(...backups.map((b) => b.key.length));
8742
- p50.log.message(
9016
+ p52.log.message(
8743
9017
  backups.map(
8744
- (b) => `${b.key.padEnd(width)} ${pc25.dim(formatBytes(b.size).padStart(8))} ${pc25.dim(b.modified)}`
9018
+ (b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
8745
9019
  ).join("\n")
8746
9020
  );
8747
9021
  }),
@@ -8752,11 +9026,11 @@ Take one with ${pc25.cyan("vela backup create")}.`
8752
9026
  // src/commands/backup/download.ts
8753
9027
  import fs37 from "node:fs";
8754
9028
  import path40 from "node:path";
8755
- import { Command as Command89 } from "commander";
8756
- import * as p51 from "@clack/prompts";
8757
- import pc26 from "picocolors";
9029
+ import { Command as Command90 } from "commander";
9030
+ import * as p53 from "@clack/prompts";
9031
+ import pc28 from "picocolors";
8758
9032
  var backupDownload = addTargetOptions(
8759
- new Command89("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
9033
+ new Command90("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
8760
9034
  "production"
8761
9035
  ).action(
8762
9036
  (key, raw) => runCommand(() => {
@@ -8765,9 +9039,9 @@ var backupDownload = addTargetOptions(
8765
9039
  const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
8766
9040
  if (!found) {
8767
9041
  throw new Error(
8768
- `${ctx.targetName} has no backup called ${pc26.cyan(key)}.
9042
+ `${ctx.targetName} has no backup called ${pc28.cyan(key)}.
8769
9043
 
8770
- Run ${pc26.cyan("vela backup list")} to see what it does have.`
9044
+ Run ${pc28.cyan("vela backup list")} to see what it does have.`
8771
9045
  );
8772
9046
  }
8773
9047
  const storage = await readStorageSettings(ctx.pb);
@@ -8784,7 +9058,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
8784
9058
  if (!ctx.session) {
8785
9059
  fs37.copyFileSync(path40.join(ctx.workspaceRootDir, "data", "backups", key), destination);
8786
9060
  } else {
8787
- const spinner7 = p51.spinner();
9061
+ const spinner7 = p53.spinner();
8788
9062
  spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
8789
9063
  try {
8790
9064
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -8803,12 +9077,12 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
8803
9077
  );
8804
9078
 
8805
9079
  // src/commands/backup/delete.ts
8806
- import process30 from "node:process";
8807
- import { Command as Command90 } from "commander";
8808
- import * as p52 from "@clack/prompts";
8809
- import pc27 from "picocolors";
9080
+ import process32 from "node:process";
9081
+ import { Command as Command91 } from "commander";
9082
+ import * as p54 from "@clack/prompts";
9083
+ import pc29 from "picocolors";
8810
9084
  var backupDelete = addTargetOptions(
8811
- new Command90("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
9085
+ new Command91("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
8812
9086
  "production"
8813
9087
  ).action(
8814
9088
  (key, raw) => runCommand(() => {
@@ -8817,19 +9091,19 @@ var backupDelete = addTargetOptions(
8817
9091
  const found = (await listBackups(ctx.pb)).find((b) => b.key === key);
8818
9092
  if (!found) {
8819
9093
  throw new Error(
8820
- `${ctx.targetName} has no backup called ${pc27.cyan(key)}.
9094
+ `${ctx.targetName} has no backup called ${pc29.cyan(key)}.
8821
9095
 
8822
- Run ${pc27.cyan("vela backup list")} to see what it does have.`
9096
+ Run ${pc29.cyan("vela backup list")} to see what it does have.`
8823
9097
  );
8824
9098
  }
8825
9099
  if (!options.yes) {
8826
- const confirmed = await p52.confirm({
9100
+ const confirmed = await p54.confirm({
8827
9101
  message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
8828
9102
  initialValue: false
8829
9103
  });
8830
- if (p52.isCancel(confirmed) || !confirmed) {
8831
- p52.cancel("Operation cancelled.");
8832
- process30.exit(0);
9104
+ if (p54.isCancel(confirmed) || !confirmed) {
9105
+ p54.cancel("Operation cancelled.");
9106
+ process32.exit(0);
8833
9107
  }
8834
9108
  }
8835
9109
  await ctx.pb.backups.delete(key);
@@ -8839,12 +9113,12 @@ Run ${pc27.cyan("vela backup list")} to see what it does have.`
8839
9113
  );
8840
9114
 
8841
9115
  // src/commands/backup/schedule.ts
8842
- import { Command as Command91 } from "commander";
8843
- import * as p53 from "@clack/prompts";
8844
- import pc28 from "picocolors";
9116
+ import { Command as Command92 } from "commander";
9117
+ import * as p55 from "@clack/prompts";
9118
+ import pc30 from "picocolors";
8845
9119
  var DEFAULT_KEEP = 7;
8846
9120
  var backupSchedule = addTargetOptions(
8847
- new Command91("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
9121
+ new Command92("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
8848
9122
  "production"
8849
9123
  ).action(
8850
9124
  (cron, raw) => runCommand(() => {
@@ -8857,17 +9131,17 @@ var backupSchedule = addTargetOptions(
8857
9131
  }
8858
9132
  if (!cron) {
8859
9133
  const current = await readSchedule(ctx.pb);
8860
- p53.log.info(
8861
- current.cron ? `${ctx.targetName} backs up on ${pc28.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
9134
+ p55.log.info(
9135
+ current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
8862
9136
 
8863
- Set one with ${pc28.cyan('vela backup schedule "0 3 * * *"')}.`
9137
+ Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
8864
9138
  );
8865
9139
  return;
8866
9140
  }
8867
9141
  const keep = Number.parseInt(options.keep, 10);
8868
9142
  if (!Number.isInteger(keep) || keep < 1) {
8869
9143
  throw new Error(
8870
- `${pc28.cyan(options.keep)} is not a number of backups to keep \u2014 pass at least 1.`
9144
+ `${pc30.cyan(options.keep)} is not a number of backups to keep \u2014 pass at least 1.`
8871
9145
  );
8872
9146
  }
8873
9147
  await writeSchedule(ctx.pb, cron, keep);
@@ -8888,17 +9162,17 @@ Set one with ${pc28.cyan('vela backup schedule "0 3 * * *"')}.`
8888
9162
  );
8889
9163
 
8890
9164
  // src/commands/backup.ts
8891
- var backup = new Command92("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
9165
+ var backup = new Command93("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
8892
9166
 
8893
9167
  // src/commands/restore.ts
8894
9168
  import fs38 from "node:fs";
8895
9169
  import path41 from "node:path";
8896
- import process31 from "node:process";
8897
- import { Command as Command93 } from "commander";
8898
- import * as p54 from "@clack/prompts";
8899
- import pc29 from "picocolors";
9170
+ import process33 from "node:process";
9171
+ import { Command as Command94 } from "commander";
9172
+ import * as p56 from "@clack/prompts";
9173
+ import pc31 from "picocolors";
8900
9174
  var restore = addTargetOptions(
8901
- new Command93("restore").description("replace a deployment\u2019s database and uploads from a backup").argument("[source]", "a backup key on the target, or a path to a local archive").configureHelp(helpConfig),
9175
+ new Command94("restore").description("replace a deployment\u2019s database and uploads from a backup").argument("[source]", "a backup key on the target, or a path to a local archive").configureHelp(helpConfig),
8902
9176
  "production"
8903
9177
  ).option("-y, --yes", "skip the confirmation prompt").option("--no-migrate", "do not run migrations against the restored database").option("--keep-previous <n>", "how many replaced databases to keep", "1").action(
8904
9178
  (source, raw) => runCommand(async () => {
@@ -8933,19 +9207,19 @@ var restore = addTargetOptions(
8933
9207
  ],
8934
9208
  stream: true
8935
9209
  });
8936
- p54.log.success(
8937
- `Restored ${pc29.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc29.cyan(
9210
+ p56.log.success(
9211
+ `Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
8938
9212
  local ? path41.basename(local) : key
8939
9213
  )}.`
8940
9214
  );
8941
9215
  if (result?.storageCarriedOver) {
8942
- p54.log.info(
9216
+ p56.log.info(
8943
9217
  "The archive held no uploads, so the files already on the server were kept."
8944
9218
  );
8945
9219
  }
8946
9220
  if (result?.previousDataDir) {
8947
- p54.log.info(
8948
- `The database this replaced is at ${pc29.cyan(result.previousDataDir)}.
9221
+ p56.log.info(
9222
+ `The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
8949
9223
 
8950
9224
  It is the only way back. Remove it once you are satisfied with the restore.`
8951
9225
  );
@@ -8962,18 +9236,18 @@ It is the only way back. Remove it once you are satisfied with the restore.`
8962
9236
  async function resolveKey(ctx, source) {
8963
9237
  if (source && !isBackupKey(source)) {
8964
9238
  throw new Error(
8965
- `${pc29.cyan(source)} is neither a file on this machine nor a backup key.
9239
+ `${pc31.cyan(source)} is neither a file on this machine nor a backup key.
8966
9240
 
8967
- Run ${pc29.cyan("vela backup list")} to see what ${ctx.targetName} has.`
9241
+ Run ${pc31.cyan("vela backup list")} to see what ${ctx.targetName} has.`
8968
9242
  );
8969
9243
  }
8970
9244
  const backups = await withRemotePocketbase(ctx.session, ctx.instance, listBackups);
8971
9245
  if (source) {
8972
9246
  if (!backups.some((b) => b.key === source)) {
8973
9247
  throw new Error(
8974
- `${ctx.targetName} has no backup called ${pc29.cyan(source)}.
9248
+ `${ctx.targetName} has no backup called ${pc31.cyan(source)}.
8975
9249
 
8976
- Run ${pc29.cyan("vela backup list")} to see what it does have.`
9250
+ Run ${pc31.cyan("vela backup list")} to see what it does have.`
8977
9251
  );
8978
9252
  }
8979
9253
  return source;
@@ -8982,10 +9256,10 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
8982
9256
  throw new Error(
8983
9257
  `${ctx.targetName} has no backups to restore from.
8984
9258
 
8985
- Take one with ${pc29.cyan("vela backup create")}, or pass the path to an archive on this machine.`
9259
+ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
8986
9260
  );
8987
9261
  }
8988
- const chosen = await p54.select({
9262
+ const chosen = await p56.select({
8989
9263
  message: `Which backup should ${ctx.targetName} be restored from?`,
8990
9264
  options: backups.map((b) => ({
8991
9265
  value: b.key,
@@ -8993,16 +9267,16 @@ Take one with ${pc29.cyan("vela backup create")}, or pass the path to an archive
8993
9267
  hint: `${formatBytes(b.size)}, ${b.modified}`
8994
9268
  }))
8995
9269
  });
8996
- if (p54.isCancel(chosen)) {
8997
- p54.cancel("Operation cancelled.");
8998
- process31.exit(0);
9270
+ if (p56.isCancel(chosen)) {
9271
+ p56.cancel("Operation cancelled.");
9272
+ process33.exit(0);
8999
9273
  }
9000
9274
  return chosen;
9001
9275
  }
9002
9276
  async function stage(ctx, file) {
9003
9277
  const dir = remotePaths.restoreStage(ctx.instance);
9004
9278
  const remote = `${dir}/${path41.basename(file)}`;
9005
- const spinner7 = p54.spinner();
9279
+ const spinner7 = p56.spinner();
9006
9280
  spinner7.start(`Uploading ${path41.basename(file)}`);
9007
9281
  try {
9008
9282
  await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
@@ -9015,32 +9289,32 @@ async function stage(ctx, file) {
9015
9289
  return remote;
9016
9290
  }
9017
9291
  async function confirm12(appName, targetName, envTag, from) {
9018
- const what = `${pc29.cyan(`${appName} (${targetName})`)} from ${pc29.cyan(path41.basename(from))}`;
9292
+ const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path41.basename(from))}`;
9019
9293
  if (isProd(envTag)) {
9020
- const answer = await p54.text({
9294
+ const answer = await p56.text({
9021
9295
  message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
9022
9296
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
9023
9297
  });
9024
- if (p54.isCancel(answer)) {
9025
- p54.cancel("Operation cancelled.");
9026
- process31.exit(0);
9298
+ if (p56.isCancel(answer)) {
9299
+ p56.cancel("Operation cancelled.");
9300
+ process33.exit(0);
9027
9301
  }
9028
9302
  return;
9029
9303
  }
9030
- const ok = await p54.confirm({
9304
+ const ok = await p56.confirm({
9031
9305
  message: `Replace the database and uploads of ${what}?`,
9032
9306
  initialValue: false
9033
9307
  });
9034
- if (p54.isCancel(ok) || !ok) {
9035
- p54.cancel("Operation cancelled.");
9036
- process31.exit(0);
9308
+ if (p56.isCancel(ok) || !ok) {
9309
+ p56.cancel("Operation cancelled.");
9310
+ process33.exit(0);
9037
9311
  }
9038
9312
  }
9039
9313
 
9040
9314
  // src/commands/targets.ts
9041
- import { Command as Command94 } from "commander";
9042
- import * as p55 from "@clack/prompts";
9043
- import pc30 from "picocolors";
9315
+ import { Command as Command95 } from "commander";
9316
+ import * as p57 from "@clack/prompts";
9317
+ import pc32 from "picocolors";
9044
9318
  import * as v8 from "valibot";
9045
9319
  var OptionsSchema4 = v8.object({
9046
9320
  ...SSH_OPTION_SCHEMA,
@@ -9048,7 +9322,7 @@ var OptionsSchema4 = v8.object({
9048
9322
  offline: v8.optional(v8.boolean())
9049
9323
  });
9050
9324
  var targets = addSshOptions(
9051
- new Command94("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
9325
+ new Command95("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
9052
9326
  ).option("--json", "print raw JSON").option("--offline", "skip connecting to servers").action(
9053
9327
  (raw) => runCommand(async () => {
9054
9328
  const options = parseOptions(OptionsSchema4, raw);
@@ -9112,13 +9386,13 @@ function report3(rows, offline) {
9112
9386
  const domain = width("DOMAIN", (row) => row.domain);
9113
9387
  const header = `${"TARGET".padEnd(target)} ${"SERVER".padEnd(server)} ${"DOMAIN".padEnd(domain)} RELEASE`;
9114
9388
  const lines = rows.map(
9115
- (row) => `${row.kind === "local" ? pc30.dim(row.target.padEnd(target)) : pc30.cyan(row.target.padEnd(target))} ${row.server.padEnd(server)} ${row.domain.padEnd(domain)} ${row.release}`
9389
+ (row) => `${row.kind === "local" ? pc32.dim(row.target.padEnd(target)) : pc32.cyan(row.target.padEnd(target))} ${row.server.padEnd(server)} ${row.domain.padEnd(domain)} ${row.release}`
9116
9390
  );
9117
- p55.log.info(`${pc30.dim(header)}
9391
+ p57.log.info(`${pc32.dim(header)}
9118
9392
  ${lines.join("\n")}`);
9119
9393
  const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
9120
9394
  if (!offline && unreachable.length > 0) {
9121
- p55.log.warn(
9395
+ p57.log.warn(
9122
9396
  `Could not reach ${unreachable.map((row) => row.server).join(", ")}.
9123
9397
  Release and domain are shown from what this project recorded.`
9124
9398
  );
@@ -9127,16 +9401,16 @@ Release and domain are shown from what this project recorded.`
9127
9401
 
9128
9402
  // src/commands/test.ts
9129
9403
  import path42 from "node:path";
9130
- import process32 from "node:process";
9131
- import { Command as Command95 } from "commander";
9404
+ import process34 from "node:process";
9405
+ import { Command as Command96 } from "commander";
9132
9406
  import PocketBase6 from "pocketbase";
9133
- import pc31 from "picocolors";
9407
+ import pc33 from "picocolors";
9134
9408
  import { x as x5 } from "tinyexec";
9135
9409
  import { detect as detect7 } from "package-manager-detector";
9136
9410
  import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
9137
9411
  import fs39 from "node:fs";
9138
- var testServer = new Command95("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
9139
- const cwd = process32.cwd();
9412
+ var testServer = new Command96("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
9413
+ const cwd = process34.cwd();
9140
9414
  const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
9141
9415
  const password11 = "password";
9142
9416
  const testDataDir = path42.join(cwd, "test-data");
@@ -9151,12 +9425,12 @@ var testServer = new Command95("test:server").description("run server tests").al
9151
9425
  email: email3,
9152
9426
  password: password11
9153
9427
  });
9154
- process32.env.POCKETBASE_URL = url;
9155
- process32.env.POCKETBASE_SUPERUSER_EMAIL = email3;
9156
- process32.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
9157
- process32.env.VELA_DATA_DIR = testDataDir;
9158
- process32.env.TEST = "true";
9159
- console.log(`${pc31.greenBright("\u2713")} Created test database`);
9428
+ process34.env.POCKETBASE_URL = url;
9429
+ process34.env.POCKETBASE_SUPERUSER_EMAIL = email3;
9430
+ process34.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
9431
+ process34.env.VELA_DATA_DIR = testDataDir;
9432
+ process34.env.TEST = "true";
9433
+ console.log(`${pc33.greenBright("\u2713")} Created test database`);
9160
9434
  let vite;
9161
9435
  let cleanedUp = false;
9162
9436
  const cleanupSync = () => {
@@ -9172,14 +9446,14 @@ var testServer = new Command95("test:server").description("run server tests").al
9172
9446
  cleanupSync();
9173
9447
  };
9174
9448
  const fail = async (message) => {
9175
- console.error(`${pc31.redBright("\u2717")} ${message}`);
9449
+ console.error(`${pc33.redBright("\u2717")} ${message}`);
9176
9450
  await cleanup();
9177
- process32.exit(1);
9451
+ process34.exit(1);
9178
9452
  };
9179
- process32.on("exit", cleanupSync);
9180
- process32.on("SIGINT", () => {
9453
+ process34.on("exit", cleanupSync);
9454
+ process34.on("SIGINT", () => {
9181
9455
  cleanupSync();
9182
- process32.exit(130);
9456
+ process34.exit(130);
9183
9457
  });
9184
9458
  const pb = new PocketBase6(url);
9185
9459
  try {
@@ -9190,11 +9464,11 @@ var testServer = new Command95("test:server").description("run server tests").al
9190
9464
  try {
9191
9465
  const seeds2 = await loadSeeds(pb, cwd);
9192
9466
  if (seeds2.length > 0) {
9193
- console.log(`${pc31.greenBright("\u2713")} Loaded ${seeds2.length} seed file(s)`);
9467
+ console.log(`${pc33.greenBright("\u2713")} Loaded ${seeds2.length} seed file(s)`);
9194
9468
  }
9195
9469
  const fixtures2 = await loadFixtures(pb, cwd);
9196
9470
  if (fixtures2.length > 0) {
9197
- console.log(`${pc31.greenBright("\u2713")} Loaded ${fixtures2.length} fixture file(s)`);
9471
+ console.log(`${pc33.greenBright("\u2713")} Loaded ${fixtures2.length} fixture file(s)`);
9198
9472
  }
9199
9473
  } catch (e) {
9200
9474
  await fail(describeLoadFailure(e));
@@ -9207,9 +9481,9 @@ var testServer = new Command95("test:server").description("run server tests").al
9207
9481
  });
9208
9482
  const vitePort = await findFreePort();
9209
9483
  await vite.listen(vitePort);
9210
- process32.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
9211
- console.log(`${pc31.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
9212
- console.log(`${pc31.greenBright("\u2713")} Started PocketBase: ${url}`);
9484
+ process34.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
9485
+ console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
9486
+ console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
9213
9487
  const extraArgs = (cmd.parent?.args ?? []).slice(1);
9214
9488
  let filter = extraArgs.find((arg) => !arg.startsWith("-"));
9215
9489
  const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
@@ -9226,12 +9500,12 @@ var testServer = new Command95("test:server").description("run server tests").al
9226
9500
  const resolvedArgs = resolved.args.slice();
9227
9501
  if (pm === "npm") resolvedArgs.unshift("--yes");
9228
9502
  const result = await x5(resolved.command, resolvedArgs, {
9229
- nodeOptions: { cwd, stdio: "inherit", env: { ...process32.env, CI: "1" } }
9503
+ nodeOptions: { cwd, stdio: "inherit", env: { ...process34.env, CI: "1" } }
9230
9504
  });
9231
- process32.exitCode = result.exitCode ?? 1;
9505
+ process34.exitCode = result.exitCode ?? 1;
9232
9506
  } catch (e) {
9233
- console.error(`${pc31.redBright("\u2717")} ${e.message}`);
9234
- process32.exitCode = 1;
9507
+ console.error(`${pc33.redBright("\u2717")} ${e.message}`);
9508
+ process34.exitCode = 1;
9235
9509
  } finally {
9236
9510
  await cleanup();
9237
9511
  }
@@ -9264,7 +9538,7 @@ function stubPagesPlugin() {
9264
9538
  // src/commands/routes.ts
9265
9539
  import fs40 from "node:fs";
9266
9540
  import path43 from "node:path";
9267
- import { Command as Command96 } from "commander";
9541
+ import { Command as Command97 } from "commander";
9268
9542
  var HTTP_METHODS = /* @__PURE__ */ new Set([
9269
9543
  "GET",
9270
9544
  "POST",
@@ -9275,7 +9549,7 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
9275
9549
  "HEAD",
9276
9550
  "fallback"
9277
9551
  ]);
9278
- var routes = new Command96("routes").description("list routes").configureHelp(helpConfig).action(async () => {
9552
+ var routes = new Command97("routes").description("list routes").configureHelp(helpConfig).action(async () => {
9279
9553
  const { workspaceRootDir, routesDir } = await getWorkspace();
9280
9554
  const routesRoot = path43.join(workspaceRootDir, routesDir);
9281
9555
  const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
@@ -9350,13 +9624,13 @@ function printTable(routes2) {
9350
9624
  }
9351
9625
 
9352
9626
  // src/commands/i18n.ts
9353
- import process33 from "node:process";
9354
- import { Command as Command97 } from "commander";
9627
+ import process35 from "node:process";
9628
+ import { Command as Command98 } from "commander";
9355
9629
  import { x as x6 } from "tinyexec";
9356
9630
  import { detect as detect8 } from "package-manager-detector";
9357
9631
  import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
9358
9632
  async function runWuchale(extraArgs) {
9359
- const cwd = process33.cwd();
9633
+ const cwd = process35.cwd();
9360
9634
  const pm = (await detect8({ cwd }))?.name ?? "npm";
9361
9635
  const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
9362
9636
  const args = resolved.args.slice();
@@ -9366,11 +9640,11 @@ async function runWuchale(extraArgs) {
9366
9640
  throwOnError: true
9367
9641
  });
9368
9642
  }
9369
- var extract = new Command97("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
9370
- var watch = new Command97("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
9371
- var status2 = new Command97("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
9372
- var clean = new Command97("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
9373
- var i18n3 = new Command97("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
9643
+ var extract = new Command98("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
9644
+ var watch = new Command98("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
9645
+ var status2 = new Command98("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
9646
+ var clean = new Command98("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
9647
+ var i18n3 = new Command98("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
9374
9648
 
9375
9649
  // src/commands/oauth.ts
9376
9650
  var oauth = stubCommand("oauth", "configure OAuth providers");
@@ -9379,23 +9653,23 @@ var oauth = stubCommand("oauth", "configure OAuth providers");
9379
9653
  var schemas = stubCommand("schemas", "manage database schemas");
9380
9654
 
9381
9655
  // src/commands/cms.ts
9382
- import { Command as Command102 } from "commander";
9656
+ import { Command as Command103 } from "commander";
9383
9657
 
9384
9658
  // src/commands/cms/editor.ts
9385
- import { Command as Command101 } from "commander";
9659
+ import { Command as Command102 } from "commander";
9386
9660
 
9387
9661
  // src/commands/cms/editor/add.ts
9388
9662
  import { randomBytes } from "node:crypto";
9389
- import { Command as Command98 } from "commander";
9390
- import * as p56 from "@clack/prompts";
9391
- import pc33 from "picocolors";
9663
+ import { Command as Command99 } from "commander";
9664
+ import * as p58 from "@clack/prompts";
9665
+ import pc35 from "picocolors";
9392
9666
 
9393
9667
  // src/lib/cms-backend.ts
9394
9668
  import { createRequire as createRequire3 } from "node:module";
9395
9669
  import path44 from "node:path";
9396
- import process34 from "node:process";
9670
+ import process36 from "node:process";
9397
9671
  import { pathToFileURL as pathToFileURL3 } from "node:url";
9398
- import pc32 from "picocolors";
9672
+ import pc34 from "picocolors";
9399
9673
  var DEFAULT_PROJECT = "default";
9400
9674
  async function loadBackendModule(root) {
9401
9675
  let entry;
@@ -9405,12 +9679,12 @@ async function loadBackendModule(root) {
9405
9679
  throw new Error(
9406
9680
  `@velastack/cms is not installed in this project.
9407
9681
 
9408
- Run ${pc32.cyan("vela enable cms")} first.`
9682
+ Run ${pc34.cyan("vela enable cms")} first.`
9409
9683
  );
9410
9684
  }
9411
9685
  return await import(pathToFileURL3(entry).href);
9412
9686
  }
9413
- async function withCmsBackend(fn, cwd = process34.cwd()) {
9687
+ async function withCmsBackend(fn, cwd = process36.cwd()) {
9414
9688
  const root = findWorkspaceRoot(cwd);
9415
9689
  if (!root) {
9416
9690
  throw new Error("Could not find workspace root (no package.json found)");
@@ -9429,42 +9703,42 @@ async function withCmsBackend(fn, cwd = process34.cwd()) {
9429
9703
  }
9430
9704
 
9431
9705
  // src/commands/cms/editor/add.ts
9432
- var editorAdd = new Command98("add").description("create an editor who can sign in to the admin bar").argument("<email>", "email the editor signs in with").option("--password <password>", "password to set \u2014 generated and shown once when omitted").option("--project <id>", "project the editor may edit", DEFAULT_PROJECT).configureHelp(helpConfig).action(
9706
+ var editorAdd = new Command99("add").description("create an editor who can sign in to the admin bar").argument("<email>", "email the editor signs in with").option("--password <password>", "password to set \u2014 generated and shown once when omitted").option("--project <id>", "project the editor may edit", DEFAULT_PROJECT).configureHelp(helpConfig).action(
9433
9707
  (email3, options) => runCommand(async () => {
9434
9708
  const generated = options.password === void 0;
9435
9709
  const password11 = options.password ?? randomBytes(12).toString("base64url");
9436
9710
  const editor2 = await withCmsBackend(
9437
9711
  (cms3) => cms3.editors.create({ email: email3, password: password11, projects: [options.project] })
9438
9712
  );
9439
- const lines = [`Added ${pc33.cyan(editor2.email)} as an editor of ${pc33.cyan(options.project)}.`];
9713
+ const lines = [`Added ${pc35.cyan(editor2.email)} as an editor of ${pc35.cyan(options.project)}.`];
9440
9714
  if (generated) {
9441
- lines.push("", `Password: ${pc33.bold(password11)}`, "", "It is shown once; copy it now.");
9715
+ lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
9442
9716
  }
9443
- p56.log.success(lines.join("\n"));
9444
- p56.log.info(
9445
- `Run ${pc33.cyan("vela dev")}, open any page with ${pc33.cyan("?edit")} on the URL (or press ${pc33.cyan("Ctrl+E")}), and sign in.`
9717
+ p58.log.success(lines.join("\n"));
9718
+ p58.log.info(
9719
+ `Run ${pc35.cyan("vela dev")}, open any page with ${pc35.cyan("?edit")} on the URL (or press ${pc35.cyan("Ctrl+E")}), and sign in.`
9446
9720
  );
9447
9721
  }, "Failed to add the editor.")
9448
9722
  );
9449
9723
 
9450
9724
  // src/commands/cms/editor/password.ts
9451
- import { Command as Command99 } from "commander";
9452
- import * as p57 from "@clack/prompts";
9453
- import pc34 from "picocolors";
9454
- var editorPassword = new Command99("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
9725
+ import { Command as Command100 } from "commander";
9726
+ import * as p59 from "@clack/prompts";
9727
+ import pc36 from "picocolors";
9728
+ var editorPassword = new Command100("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
9455
9729
  (email3, password11) => runCommand(async () => {
9456
9730
  await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
9457
- p57.log.success(
9458
- `Updated the password for ${pc34.cyan(email3)}. Existing sessions were signed out.`
9731
+ p59.log.success(
9732
+ `Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
9459
9733
  );
9460
9734
  }, "Failed to set the password.")
9461
9735
  );
9462
9736
 
9463
9737
  // src/commands/cms/editor/list.ts
9464
- import { Command as Command100 } from "commander";
9465
- import * as p58 from "@clack/prompts";
9466
- import pc35 from "picocolors";
9467
- var editorList = new Command100("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
9738
+ import { Command as Command101 } from "commander";
9739
+ import * as p60 from "@clack/prompts";
9740
+ import pc37 from "picocolors";
9741
+ var editorList = new Command101("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
9468
9742
  () => runCommand(async () => {
9469
9743
  const rows = await withCmsBackend(
9470
9744
  async (cms3) => cms3.editors.list().map((editor2) => ({
@@ -9473,25 +9747,25 @@ var editorList = new Command100("list").description("list editors and the projec
9473
9747
  }))
9474
9748
  );
9475
9749
  if (rows.length === 0) {
9476
- p58.log.info(`No editors yet. Add one with ${pc35.cyan("vela cms editor add <email>")}.`);
9750
+ p60.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
9477
9751
  return;
9478
9752
  }
9479
9753
  const width = Math.max(...rows.map((row) => row.email.length));
9480
- p58.log.info(
9754
+ p60.log.info(
9481
9755
  `Editors
9482
9756
 
9483
9757
  ` + rows.map(
9484
- (row) => ` ${row.email.padEnd(width)} ${pc35.dim(row.projects.join(", ") || "no projects")}`
9758
+ (row) => ` ${row.email.padEnd(width)} ${pc37.dim(row.projects.join(", ") || "no projects")}`
9485
9759
  ).join("\n")
9486
9760
  );
9487
9761
  }, "Failed to list editors.")
9488
9762
  );
9489
9763
 
9490
9764
  // src/commands/cms/editor.ts
9491
- var editor = new Command101("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
9765
+ var editor = new Command102("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
9492
9766
 
9493
9767
  // src/commands/cms.ts
9494
- var cms2 = new Command102("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
9768
+ var cms2 = new Command103("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
9495
9769
 
9496
9770
  // src/program.ts
9497
9771
  var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
@@ -9526,10 +9800,10 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
9526
9800
  ]);
9527
9801
  var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
9528
9802
  var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
9529
- var program = new Command103().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
9803
+ var program = new Command104().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
9530
9804
  program.hook("preAction", (_thisCommand, actionCommand) => {
9531
9805
  if (isStub(actionCommand)) return;
9532
- const envRoot = findWorkspaceRoot() ?? process35.cwd();
9806
+ const envRoot = findWorkspaceRoot() ?? process37.cwd();
9533
9807
  dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
9534
9808
  const path45 = getCommandPath(actionCommand);
9535
9809
  if (NO_BACKEND_COMMMANDS.has(path45)) return;
@@ -9537,30 +9811,30 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
9537
9811
  if (NO_BACKEND_COMMMANDS.has(top)) return;
9538
9812
  if (!hasBackend()) {
9539
9813
  if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
9540
- p59.log.error(
9541
- `${pc36.cyan(`vela ${path45}`)} needs a backend, and this project does not have one.
9814
+ p61.log.error(
9815
+ `${pc38.cyan(`vela ${path45}`)} needs a backend, and this project does not have one.
9542
9816
 
9543
9817
  Static projects have no database to talk to.
9544
9818
 
9545
- To add a backend to this project, run ${pc36.cyan("vela bless")}.`
9819
+ To add a backend to this project, run ${pc38.cyan("vela bless")}.`
9546
9820
  );
9547
- p59.log.message();
9548
- p59.cancel("Operation failed.");
9549
- process35.exit(1);
9821
+ p61.log.message();
9822
+ p61.cancel("Operation failed.");
9823
+ process37.exit(1);
9550
9824
  }
9551
9825
  if (SELF_CREDENTIALED_COMMANDS.has(path45)) return;
9552
- if (!process35.env.POCKETBASE_SUPERUSER_EMAIL || !process35.env.POCKETBASE_SUPERUSER_PASSWORD) {
9553
- p59.log.error(
9826
+ if (!process37.env.POCKETBASE_SUPERUSER_EMAIL || !process37.env.POCKETBASE_SUPERUSER_PASSWORD) {
9827
+ p61.log.error(
9554
9828
  `PocketBase superuser credentials are required.
9555
9829
 
9556
- Set ${pc36.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc36.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
9830
+ Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
9557
9831
 
9558
- To set up a new project, run ${pc36.cyan("vela create")}.
9559
- To set up an existing project, run ${pc36.cyan("vela bless")}.`
9832
+ To set up a new project, run ${pc38.cyan("vela create")}.
9833
+ To set up an existing project, run ${pc38.cyan("vela bless")}.`
9560
9834
  );
9561
- p59.log.message();
9562
- p59.cancel("Operation failed.");
9563
- process35.exit(1);
9835
+ p61.log.message();
9836
+ p61.cancel("Operation failed.");
9837
+ process37.exit(1);
9564
9838
  }
9565
9839
  });
9566
9840
  function getCommandPath(cmd) {
@@ -9614,5 +9888,5 @@ for (const command of [
9614
9888
  }
9615
9889
 
9616
9890
  // src/bin.ts
9617
- program.parse(normalizeArgv(process36.argv.slice(2)), { from: "user" });
9891
+ program.parse(normalizeArgv(process38.argv.slice(2)), { from: "user" });
9618
9892
  //# sourceMappingURL=bin.js.map