vela 0.11.4 → 0.11.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/bin.ts
4
- import process39 from "node:process";
4
+ import process40 from "node:process";
5
5
 
6
6
  // src/lib/argv.ts
7
7
  function normalizeArgv(argv) {
@@ -11,9 +11,9 @@ function normalizeArgv(argv) {
11
11
  }
12
12
 
13
13
  // src/program.ts
14
- import process38 from "node:process";
15
- import * as p61 from "@clack/prompts";
16
- import { Command as Command104 } from "commander";
14
+ import process39 from "node:process";
15
+ import * as p62 from "@clack/prompts";
16
+ import { Command as Command105 } from "commander";
17
17
  import nodePath from "node:path";
18
18
  import dotenv2 from "dotenv";
19
19
  import pc38 from "picocolors";
@@ -21,7 +21,7 @@ import pc38 from "picocolors";
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "vela",
24
- version: "0.11.4",
24
+ version: "0.11.6",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -57,7 +57,7 @@ var package_default = {
57
57
  dependencies: {
58
58
  "@clack/prompts": "^1.7.0",
59
59
  "@faker-js/faker": "^10.6.0",
60
- "@velastack/patterns": "^0.2.3",
60
+ "@velastack/patterns": "^0.2.5",
61
61
  "@velastack/pocketbase-codegen": "^0.1.0",
62
62
  "annotate-json-schema": "^0.1.0",
63
63
  commander: "^13.1.0",
@@ -66,7 +66,7 @@ var package_default = {
66
66
  dotenv: "^17.4.2",
67
67
  "fetch-cookie": "^3.2.0",
68
68
  "json-schema-faker": "^0.6.3",
69
- "magic-string": "^0.30.21",
69
+ "magic-string": "^1.2.3",
70
70
  "package-manager-detector": "^1.8.0",
71
71
  picocolors: "^1.1.1",
72
72
  pocketbase: "^0.28.0",
@@ -83,10 +83,10 @@ var package_default = {
83
83
  "@types/node": "^22.0.0",
84
84
  esbuild: "^0.28.2",
85
85
  prettier: "^3.9.6",
86
+ shellcheck: "^4.1.0",
86
87
  typescript: "^5.6.0",
87
88
  vite: "^8.2.2",
88
- vitest: "^4.1.11",
89
- shellcheck: "^4.1.0"
89
+ vitest: "^4.1.11"
90
90
  },
91
91
  peerDependencies: {
92
92
  "@sveltejs/kit": "^2.57.1",
@@ -100,6 +100,18 @@ var package_default = {
100
100
  optional: true
101
101
  }
102
102
  },
103
+ overrides: {
104
+ "global-agent": "^4.1.3",
105
+ "@xhmikosr/decompress-unzip": {
106
+ "file-type": "^21.3.1"
107
+ },
108
+ "@xhmikosr/decompress-tar": {
109
+ "file-type": "^21.3.1"
110
+ },
111
+ "@felipecrs/decompress-tarxz": {
112
+ "file-type": "^21.3.1"
113
+ }
114
+ },
103
115
  keywords: [
104
116
  "svelte",
105
117
  "sveltekit",
@@ -291,8 +303,20 @@ function mergePackageJson(user, template) {
291
303
  }
292
304
  return { merged, added, conflicts, replaced };
293
305
  }
294
- function readPackageJson(path46) {
295
- return JSON.parse(fs.readFileSync(path46, "utf8"));
306
+ function dropTemplateAdapters(user, template) {
307
+ const isAdapter = (name) => name.startsWith("@sveltejs/adapter-");
308
+ const userHasOne = DEP_KINDS.some((kind) => Object.keys(user[kind] ?? {}).some(isAdapter));
309
+ if (!userHasOne) return template;
310
+ const copy = { ...template };
311
+ for (const kind of DEP_KINDS) {
312
+ const deps = template[kind];
313
+ if (!deps) continue;
314
+ copy[kind] = Object.fromEntries(Object.entries(deps).filter(([name]) => !isAdapter(name)));
315
+ }
316
+ return copy;
317
+ }
318
+ function readPackageJson(path47) {
319
+ return JSON.parse(fs.readFileSync(path47, "utf8"));
296
320
  }
297
321
  var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
298
322
  var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
@@ -305,12 +329,12 @@ function fillTemplatePlaceholders(raw, values) {
305
329
  function escapeSingleQuoted(value) {
306
330
  return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
307
331
  }
308
- function readTemplatePackageJson(path46, values) {
309
- const raw = fillTemplatePlaceholders(fs.readFileSync(path46, "utf8"), values);
332
+ function readTemplatePackageJson(path47, values) {
333
+ const raw = fillTemplatePlaceholders(fs.readFileSync(path47, "utf8"), values);
310
334
  return JSON.parse(raw);
311
335
  }
312
- function writePackageJson(path46, pkg) {
313
- fs.writeFileSync(path46, JSON.stringify(pkg, null, " ") + "\n");
336
+ function writePackageJson(path47, pkg) {
337
+ fs.writeFileSync(path47, JSON.stringify(pkg, null, " ") + "\n");
314
338
  }
315
339
  function toValidPackageName(name) {
316
340
  return name.trim().toLowerCase().replace(/\s+/g, "-").replace(/^[._]/, "").replace(/[^a-z0-9~.-]+/g, "-");
@@ -569,10 +593,10 @@ function writeCachedIndex(cached2) {
569
593
  fs5.mkdirSync(cacheRoot(), { recursive: true });
570
594
  fs5.writeFileSync(indexCachePath(), JSON.stringify(cached2, null, 2));
571
595
  }
572
- function parseTemplateIndex(text18, url) {
596
+ function parseTemplateIndex(text19, url) {
573
597
  let parsed;
574
598
  try {
575
- parsed = JSON.parse(text18);
599
+ parsed = JSON.parse(text19);
576
600
  } catch (e) {
577
601
  throw new Error(`Template index at ${url} is not valid JSON: ${e.message}`);
578
602
  }
@@ -866,7 +890,7 @@ async function packageManagerPrompt(cwd) {
866
890
  }
867
891
  return pm;
868
892
  }
869
- async function installDependencies(agent, cwd) {
893
+ async function installDependencies(agent, cwd, { exitOnFailure = true } = {}) {
870
894
  const task = p2.taskLog({
871
895
  title: `Installing dependencies with ${agent}...`,
872
896
  limit: Math.ceil(process5.stdout.rows / 2),
@@ -883,14 +907,16 @@ async function installDependencies(agent, cwd) {
883
907
  proc.process?.stderr?.on("data", (data) => task.message(data.toString(), { raw: true }));
884
908
  await proc;
885
909
  task.success("Successfully installed dependencies");
910
+ return true;
886
911
  } catch {
887
912
  task.error("Failed to install dependencies");
913
+ if (!exitOnFailure) return false;
888
914
  p2.cancel("Operation failed.");
889
915
  process5.exit(2);
890
916
  }
891
917
  }
892
- function addPnpmBuildDependencies(cwd, packageManager, allowedPackages) {
893
- if (!packageManager || packageManager !== "pnpm") return;
918
+ function addPnpmBuildDependencies(cwd, packageManager2, allowedPackages) {
919
+ if (!packageManager2 || packageManager2 !== "pnpm") return;
894
920
  const pkgPath = path6.join(cwd, "package.json");
895
921
  if (!fs7.existsSync(pkgPath)) return;
896
922
  const pkg = JSON.parse(fs7.readFileSync(pkgPath, "utf-8"));
@@ -1027,11 +1053,11 @@ function getPocketbaseMetadata(cwd) {
1027
1053
  return null;
1028
1054
  }
1029
1055
  async function execPackageBin(cwd, args, stdio = "pipe") {
1030
- const packageManager = (await detect2({ cwd }))?.name ?? "npm";
1031
- const resolved = resolveCommand(packageManager, "execute", args);
1032
- if (!resolved) throw new Error(`Could not resolve command for ${packageManager}`);
1056
+ const packageManager2 = (await detect2({ cwd }))?.name ?? "npm";
1057
+ const resolved = resolveCommand(packageManager2, "execute", args);
1058
+ if (!resolved) throw new Error(`Could not resolve command for ${packageManager2}`);
1033
1059
  const { command, args: resolvedArgs } = resolved;
1034
- if (packageManager === "npm") resolvedArgs.unshift("--yes");
1060
+ if (packageManager2 === "npm") resolvedArgs.unshift("--yes");
1035
1061
  return x(command, resolvedArgs, { nodeOptions: { cwd, stdio }, throwOnError: true });
1036
1062
  }
1037
1063
  async function withPocketbase(cwd, fn, creds) {
@@ -1479,7 +1505,14 @@ var GITIGNORE_ENTRIES = [
1479
1505
  "!.env.example",
1480
1506
  "!.env.test",
1481
1507
  "vite.config.js.timestamp-*",
1482
- "vite.config.ts.timestamp-*"
1508
+ "vite.config.ts.timestamp-*",
1509
+ // The local database, minus the parts that are source. Same block as the
1510
+ // template's _gitignore; without it a blessed project commits its SQLite.
1511
+ "/data/*",
1512
+ "!/data/fixtures",
1513
+ "!/data/seeds",
1514
+ "!/data/hooks",
1515
+ "/backups"
1483
1516
  ];
1484
1517
  function mergeGitignore(filePath) {
1485
1518
  const existing = fs13.existsSync(filePath) ? fs13.readFileSync(filePath, "utf8") : "";
@@ -1647,13 +1680,13 @@ async function blessProject(cwdArg, options) {
1647
1680
  mergeAppDts(templateDir, projectPath);
1648
1681
  maybeReplaceRoutes(projectPath, templateDir, options);
1649
1682
  p4.log.success("Vela files in place");
1650
- let packageManager;
1683
+ let packageManager2;
1651
1684
  if (options.install !== false) {
1652
1685
  const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
1653
1686
  if (pm) {
1654
1687
  addPnpmBuildDependencies(projectPath, pm, ["esbuild", "pocketbase-server"]);
1655
1688
  await installDependencies(pm, projectPath);
1656
- packageManager = pm;
1689
+ packageManager2 = pm;
1657
1690
  }
1658
1691
  }
1659
1692
  p4.log.step("Initializing PocketBase...");
@@ -1667,7 +1700,7 @@ async function blessProject(cwdArg, options) {
1667
1700
  ["PocketBase superuser credentials \u2014 used by `vela` commands"]
1668
1701
  );
1669
1702
  p4.log.success("PocketBase initialized");
1670
- printNextSteps(projectPath, packageManager);
1703
+ printNextSteps(projectPath, packageManager2);
1671
1704
  }
1672
1705
  function ensureShadcnCss(projectPath) {
1673
1706
  if (ensureShadcnImport(path13.join(projectPath, "src", "app.css"))) {
@@ -1713,7 +1746,10 @@ function mergeDependencies(projectPath, templateDir) {
1713
1746
  appName,
1714
1747
  cliVersion: package_default.version
1715
1748
  });
1716
- const { merged, added, conflicts, replaced } = mergePackageJson(userPkg, templatePkg);
1749
+ const { merged, added, conflicts, replaced } = mergePackageJson(
1750
+ userPkg,
1751
+ dropTemplateAdapters(userPkg, templatePkg)
1752
+ );
1717
1753
  writePackageJson(userPkgPath, merged);
1718
1754
  if (added.length > 0) {
1719
1755
  p4.log.info(
@@ -1851,9 +1887,9 @@ function summarize(names) {
1851
1887
  if (names.length <= 4) return names.join(", ");
1852
1888
  return `${names.slice(0, 3).join(", ")}, and ${names.length - 3} more`;
1853
1889
  }
1854
- function printNextSteps(projectPath, packageManager) {
1890
+ function printNextSteps(projectPath, packageManager2) {
1855
1891
  const relative = path13.relative(process7.cwd(), projectPath);
1856
- const pm = packageManager ?? getUserAgent() ?? "npm";
1892
+ const pm = packageManager2 ?? getUserAgent() ?? "npm";
1857
1893
  const nextSteps = [];
1858
1894
  if (relative !== "") {
1859
1895
  const hasSpaces = relative.includes(" ");
@@ -1885,13 +1921,13 @@ import * as p5 from "@clack/prompts";
1885
1921
  import { detect as detect3, resolveCommand as resolveCommand3 } from "package-manager-detector";
1886
1922
  function optionsSchema2(listing) {
1887
1923
  const names = listing.templates.map((template) => template.name);
1888
- let choices = `must be one of: ${templateChoicesMessage(listing.templates)}`;
1924
+ let choices2 = `must be one of: ${templateChoicesMessage(listing.templates)}`;
1889
1925
  if (listing.registryError) {
1890
- choices += ` (could not reach the template registry: ${listing.registryError})`;
1926
+ choices2 += ` (could not reach the template registry: ${listing.registryError})`;
1891
1927
  }
1892
1928
  return v4.strictObject({
1893
1929
  install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
1894
- template: v4.optional(v4.picklist(names, choices)),
1930
+ template: v4.optional(v4.picklist(names, choices2)),
1895
1931
  name: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
1896
1932
  email: v4.optional(v4.pipe(v4.string(), v4.email("must be a valid email address"))),
1897
1933
  password: v4.optional(v4.pipe(v4.string(), v4.minLength(8, "must be at least 8 characters long")))
@@ -1901,19 +1937,19 @@ var create = new Command3("create").description("scaffold a new velastack projec
1901
1937
  return runCommand(async () => {
1902
1938
  const listing = await listAllTemplates();
1903
1939
  const options = parseOptions(optionsSchema2(listing), rawOpts);
1904
- const { directory, packageManager, name, template } = await createProject(
1940
+ const { directory, packageManager: packageManager2, name, template } = await createProject(
1905
1941
  projectPath,
1906
1942
  options,
1907
1943
  listing
1908
1944
  );
1909
1945
  const relative = path14.relative(process8.cwd(), directory);
1910
- const pm = packageManager ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
1946
+ const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
1911
1947
  const nextSteps = [];
1912
1948
  if (relative !== "") {
1913
1949
  const hasSpaces = relative.includes(" ");
1914
1950
  nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
1915
1951
  }
1916
- if (!packageManager) {
1952
+ if (!packageManager2) {
1917
1953
  const resolved = resolveCommand3(pm, "install", []);
1918
1954
  if (resolved) {
1919
1955
  nextSteps.push(
@@ -2002,14 +2038,14 @@ async function createProject(cwdArg, options, listing) {
2002
2038
  throw new Error(`Template ${template.name} is missing package.template.json`);
2003
2039
  }
2004
2040
  p5.log.success("Project created");
2005
- let packageManager;
2041
+ let packageManager2;
2006
2042
  if (options.install !== false) {
2007
2043
  const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
2008
2044
  if (pm) {
2009
2045
  const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
2010
2046
  addPnpmBuildDependencies(projectPath, pm, builds);
2011
2047
  await installDependencies(pm, projectPath);
2012
- packageManager = pm;
2048
+ packageManager2 = pm;
2013
2049
  }
2014
2050
  }
2015
2051
  if (credentials) {
@@ -2035,7 +2071,7 @@ async function createProject(cwdArg, options, listing) {
2035
2071
  );
2036
2072
  p5.log.success("PocketBase initialized");
2037
2073
  }
2038
- return { directory: projectPath, packageManager, name, template };
2074
+ return { directory: projectPath, packageManager: packageManager2, name, template };
2039
2075
  }
2040
2076
  function promptCredentials(options, onCancel2) {
2041
2077
  return p5.group(
@@ -2065,23 +2101,135 @@ import { Command as Command9 } from "commander";
2065
2101
 
2066
2102
  // src/commands/generate/form.ts
2067
2103
  import { Command as Command4 } from "commander";
2068
- import * as p11 from "@clack/prompts";
2104
+ import * as p12 from "@clack/prompts";
2069
2105
 
2070
2106
  // src/lib/pattern-runner.ts
2071
2107
  import path15 from "node:path";
2108
+ import * as p7 from "@clack/prompts";
2109
+ import { bySlug as bySlug2 } from "@velastack/patterns";
2110
+
2111
+ // src/lib/providers.ts
2112
+ import process9 from "node:process";
2072
2113
  import * as p6 from "@clack/prompts";
2073
2114
  import { bySlug } from "@velastack/patterns";
2115
+ function capabilityName(slug2) {
2116
+ return slug2.replace(/^enable-/, "");
2117
+ }
2118
+ function choices(providers) {
2119
+ return `--provider <${providers.map((provider) => provider.id).join("|")}>`;
2120
+ }
2121
+ function unknownProviderMessage(name, raw, providers) {
2122
+ return [
2123
+ `Unknown provider "${raw}" for ${name}.`,
2124
+ "",
2125
+ "Available providers:",
2126
+ ...providers.map((provider) => ` ${provider.id}`)
2127
+ ].join("\n");
2128
+ }
2129
+ function decideProvider(request) {
2130
+ const { patternName, providers, flagValue, interactive } = request;
2131
+ if (flagValue !== void 0) {
2132
+ const provider = providers.find((candidate) => candidate.id === flagValue);
2133
+ if (!provider) {
2134
+ return { kind: "error", message: unknownProviderMessage(patternName, flagValue, providers) };
2135
+ }
2136
+ return { kind: "use", provider };
2137
+ }
2138
+ if (interactive) return { kind: "prompt" };
2139
+ return {
2140
+ kind: "error",
2141
+ message: `Choose ${article(patternName)} ${patternName} provider: pass ${choices(providers)}. There is no terminal to ask on.`
2142
+ };
2143
+ }
2144
+ function article(word) {
2145
+ return /^[aeiou]/i.test(word) ? "an" : "a";
2146
+ }
2147
+ function isInteractive() {
2148
+ return Boolean(process9.stdout.isTTY) && !process9.env.CI;
2149
+ }
2150
+ function providerFlagInArgv(argv) {
2151
+ return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
2152
+ }
2153
+ function checkProviderInput(pattern, argv, input) {
2154
+ const providers = pattern.providers ?? [];
2155
+ if (providers.length > 0) {
2156
+ if (typeof input.provider !== "string" || input.provider.length === 0) {
2157
+ throw new Error(`${pattern.title} needs a provider. Pass ${choices(providers)}.`);
2158
+ }
2159
+ return;
2160
+ }
2161
+ if (providerFlagInArgv(argv)) {
2162
+ throw new Error(`${pattern.title} does not support --provider.`);
2163
+ }
2164
+ }
2165
+ async function resolveProvider(slug2, flagValue) {
2166
+ const pattern = bySlug[slug2];
2167
+ const providers = pattern.providers ?? [];
2168
+ if (providers.length === 0) {
2169
+ throw new Error(`${pattern.title} does not support --provider.`);
2170
+ }
2171
+ const patternName = capabilityName(slug2);
2172
+ const decision = decideProvider({
2173
+ patternName,
2174
+ providers,
2175
+ flagValue,
2176
+ interactive: isInteractive()
2177
+ });
2178
+ if (decision.kind === "error") throw new Error(decision.message);
2179
+ if (decision.kind === "use") return decision.provider;
2180
+ const selected = await p6.select({
2181
+ message: `Select ${patternName} provider`,
2182
+ options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
2183
+ });
2184
+ if (p6.isCancel(selected)) {
2185
+ p6.cancel("Operation cancelled.");
2186
+ process9.exit(0);
2187
+ }
2188
+ return providers.find((provider) => provider.id === selected);
2189
+ }
2190
+ async function collectProviderEnv(provider) {
2191
+ const values = {};
2192
+ const interactive = isInteractive();
2193
+ for (const variable of provider.env ?? []) {
2194
+ const existing = process9.env[variable.key];
2195
+ if (existing) {
2196
+ values[variable.key] = existing;
2197
+ continue;
2198
+ }
2199
+ if (!interactive) {
2200
+ values[variable.key] = variable.default ?? "";
2201
+ continue;
2202
+ }
2203
+ const value = await p6.text({
2204
+ message: variable.label,
2205
+ placeholder: variable.placeholder,
2206
+ initialValue: variable.default
2207
+ });
2208
+ if (p6.isCancel(value)) {
2209
+ p6.cancel("Operation cancelled.");
2210
+ process9.exit(0);
2211
+ }
2212
+ values[variable.key] = (value ?? "").trim();
2213
+ }
2214
+ return values;
2215
+ }
2216
+ function missingEnvKeys(provider, values) {
2217
+ return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
2218
+ }
2219
+
2220
+ // src/lib/pattern-runner.ts
2074
2221
  function toRelative(root, filePath) {
2075
2222
  return path15.isAbsolute(filePath) ? path15.relative(root, filePath) : filePath;
2076
2223
  }
2077
2224
  var isSuccess = (f) => (f.status ?? "success") === "success";
2078
2225
  async function runPattern(slug2, argv, input, report4) {
2079
- const pattern = bySlug[slug2];
2226
+ const pattern = bySlug2[slug2];
2080
2227
  if (!pattern) {
2081
2228
  throw new Error(`Unknown pattern: ${slug2}`);
2082
2229
  }
2230
+ checkProviderInput(pattern, argv, input);
2083
2231
  const { workspaceRootDir, features } = await getWorkspace();
2084
- const log45 = p6.taskLog({ title: report4.task.title });
2232
+ const log45 = p7.taskLog({ title: report4.task.title });
2085
2233
  let result;
2086
2234
  try {
2087
2235
  result = await pattern.generate({
@@ -2120,7 +2268,7 @@ async function runPattern(slug2, argv, input, report4) {
2120
2268
  const deleted = result.deletes.filter(isSuccess);
2121
2269
  const totalChanges = created.length + modified.length + deleted.length + result.components.length + result.packages.length + result.collections.length;
2122
2270
  if (totalChanges === 0 && failures.length === 0) {
2123
- p6.log.info(`${pattern.title ?? slug2} produced no changes.`);
2271
+ p7.log.info(`${pattern.title ?? slug2} produced no changes.`);
2124
2272
  return;
2125
2273
  }
2126
2274
  reportResult({
@@ -2141,7 +2289,7 @@ async function runPattern(slug2, argv, input, report4) {
2141
2289
  // src/lib/ai-flow.ts
2142
2290
  import fs18 from "node:fs";
2143
2291
  import path17 from "node:path";
2144
- import * as p10 from "@clack/prompts";
2292
+ import * as p11 from "@clack/prompts";
2145
2293
  import pc4 from "picocolors";
2146
2294
 
2147
2295
  // src/lib/project-config.ts
@@ -2214,14 +2362,14 @@ var aiSchema = (workspaceRootDir, body) => aiPost(workspaceRootDir, "schema", bo
2214
2362
  var aiForm = (workspaceRootDir, body) => aiPost(workspaceRootDir, "form", body);
2215
2363
 
2216
2364
  // src/lib/ai-loop.ts
2217
- import * as p7 from "@clack/prompts";
2365
+ import * as p8 from "@clack/prompts";
2218
2366
  async function aiLoop(opts) {
2219
2367
  let prompt = opts.initialPrompt;
2220
2368
  let history = [];
2221
2369
  let attempt = 0;
2222
2370
  while (true) {
2223
2371
  attempt++;
2224
- const spinner7 = p7.spinner();
2372
+ const spinner7 = p8.spinner();
2225
2373
  spinner7.start(`${opts.stageLabel} (${attempt > 1 ? "iteration " + attempt : "first pass"})\u2026`);
2226
2374
  let result;
2227
2375
  let turn;
@@ -2235,12 +2383,12 @@ async function aiLoop(opts) {
2235
2383
  throw e;
2236
2384
  }
2237
2385
  opts.renderPreview(result);
2238
- const next = await p7.text({
2386
+ const next = await p8.text({
2239
2387
  message: "Refine the result, or press Enter to apply.",
2240
2388
  placeholder: opts.refinePlaceholder,
2241
2389
  defaultValue: ""
2242
2390
  });
2243
- if (p7.isCancel(next)) return null;
2391
+ if (p8.isCancel(next)) return null;
2244
2392
  const trimmed = (typeof next === "string" ? next : "").trim();
2245
2393
  if (trimmed === "") return result;
2246
2394
  history = turn;
@@ -2249,7 +2397,7 @@ async function aiLoop(opts) {
2249
2397
  }
2250
2398
 
2251
2399
  // src/lib/ai-existing-models.ts
2252
- import * as p8 from "@clack/prompts";
2400
+ import * as p9 from "@clack/prompts";
2253
2401
  async function loadExistingModels(workspaceRootDir) {
2254
2402
  let result = [];
2255
2403
  try {
@@ -2274,7 +2422,7 @@ async function loadExistingModels(workspaceRootDir) {
2274
2422
  });
2275
2423
  } catch (e) {
2276
2424
  const msg = e instanceof Error ? e.message : String(e);
2277
- p8.log.warn(
2425
+ p9.log.warn(
2278
2426
  `Could not load existing schema from PocketBase (${msg}). The AI agent will design without that context.`
2279
2427
  );
2280
2428
  return [];
@@ -2283,7 +2431,7 @@ async function loadExistingModels(workspaceRootDir) {
2283
2431
  }
2284
2432
 
2285
2433
  // src/lib/ai-to-argv.ts
2286
- import * as p9 from "@clack/prompts";
2434
+ import * as p10 from "@clack/prompts";
2287
2435
  var PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["text", "number", "bool", "email", "date", "url", "file"]);
2288
2436
  function singularize(name) {
2289
2437
  if (name.endsWith("ies") && name.length > 3) return `${name.slice(0, -3)}y`;
@@ -2306,7 +2454,7 @@ function collectionSpecToArgv(spec) {
2306
2454
  for (const field of spec.fields) {
2307
2455
  const type = typeArg(field);
2308
2456
  if (type === null) {
2309
- p9.log.warn(
2457
+ p10.log.warn(
2310
2458
  `Skipping field "${field.name}" (type "${field.type}" cannot be represented as a pattern argument)`
2311
2459
  );
2312
2460
  continue;
@@ -2409,10 +2557,10 @@ function renderModel(spec) {
2409
2557
  const tail = extra.length > 0 ? " " + pc4.dim(extra.join(" ")) : "";
2410
2558
  lines.push(` ${f.name.padEnd(nameWidth)} ${f.type.padEnd(typeWidth)} ${required}${tail}`);
2411
2559
  }
2412
- p10.log.message(lines.join("\n"));
2560
+ p11.log.message(lines.join("\n"));
2413
2561
  }
2414
2562
  function renderLayout(layout) {
2415
- p10.log.message(renderGrid(layout));
2563
+ p11.log.message(renderGrid(layout));
2416
2564
  }
2417
2565
  async function runSchemaStage(opts) {
2418
2566
  const { workspaceRootDir } = await getWorkspace();
@@ -2476,12 +2624,12 @@ var form = new Command4("form").description("generate a form from a model").argu
2476
2624
  }
2477
2625
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "form" });
2478
2626
  if (!stage2) {
2479
- p11.cancel("Aborted before any files were written.");
2627
+ p12.cancel("Aborted before any files were written.");
2480
2628
  return;
2481
2629
  }
2482
2630
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2483
2631
  if (!layout) {
2484
- p11.cancel("Aborted before any files were written.");
2632
+ p12.cancel("Aborted before any files were written.");
2485
2633
  return;
2486
2634
  }
2487
2635
  argv = specToArgv(stage2.model);
@@ -2523,7 +2671,7 @@ var form = new Command4("form").description("generate a form from a model").argu
2523
2671
 
2524
2672
  // src/commands/generate/schema.ts
2525
2673
  import { Command as Command5 } from "commander";
2526
- import * as p12 from "@clack/prompts";
2674
+ import * as p13 from "@clack/prompts";
2527
2675
  var schema = new Command5("schema").description("generate a schema from a model").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--ai <description>", "design the schema with AI from a natural-language description").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2528
2676
  (model, fields, options) => runCommand(async () => {
2529
2677
  let argv;
@@ -2534,7 +2682,7 @@ var schema = new Command5("schema").description("generate a schema from a model"
2534
2682
  }
2535
2683
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "schema" });
2536
2684
  if (!stage2) {
2537
- p12.cancel("Aborted before any files were written.");
2685
+ p13.cancel("Aborted before any files were written.");
2538
2686
  return;
2539
2687
  }
2540
2688
  argv = specToArgv(stage2.model);
@@ -2594,7 +2742,7 @@ var resource = new Command6("resource").description("generate a resource (model
2594
2742
 
2595
2743
  // src/commands/generate/scaffold.ts
2596
2744
  import { Command as Command7 } from "commander";
2597
- import * as p13 from "@clack/prompts";
2745
+ import * as p14 from "@clack/prompts";
2598
2746
  var scaffold = new Command7("scaffold").description("generate a full CRUD scaffold (model, forms, list, detail)").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--remote", "generate a scaffold backed by a remote PocketBase collection").option(
2599
2747
  "--route <route>",
2600
2748
  'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under (app)/(public).'
@@ -2612,12 +2760,12 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2612
2760
  }
2613
2761
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "scaffold" });
2614
2762
  if (!stage2) {
2615
- p13.cancel("Aborted before any files were written.");
2763
+ p14.cancel("Aborted before any files were written.");
2616
2764
  return;
2617
2765
  }
2618
2766
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2619
2767
  if (!layout) {
2620
- p13.cancel("Aborted before any files were written.");
2768
+ p14.cancel("Aborted before any files were written.");
2621
2769
  return;
2622
2770
  }
2623
2771
  argv = specToArgv(stage2.model);
@@ -2687,11 +2835,42 @@ var migration = new Command8("migration").description("generate a migration for
2687
2835
  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);
2688
2836
 
2689
2837
  // src/commands/enable.ts
2690
- import { Command as Command24 } from "commander";
2838
+ import { Command as Command25 } from "commander";
2691
2839
 
2692
- // src/commands/enable/auth.ts
2840
+ // src/commands/enable/analytics.ts
2693
2841
  import { Command as Command10 } from "commander";
2694
- var auth = new Command10("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2842
+ var analytics = new Command10("analytics").description("enable web analytics (Plausible, Google Analytics or PostHog)").option("--provider <provider>", "analytics provider: plausible, google or posthog").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2843
+ (opts, cmd) => runCommand(async () => {
2844
+ const provider = await resolveProvider("enable-analytics", opts.provider);
2845
+ const providerEnv = await collectProviderEnv(provider);
2846
+ const blank = missingEnvKeys(provider, providerEnv);
2847
+ await runPattern(
2848
+ "enable-analytics",
2849
+ cmd.args,
2850
+ { provider: provider.id, providerEnv },
2851
+ {
2852
+ summary: `Enabled analytics with ${provider.label}.`,
2853
+ nextSteps: [
2854
+ ...blank.map(
2855
+ (key) => `Set ${key} in .env; the analytics component renders nothing until it is set.`
2856
+ ),
2857
+ `Run \`vela dev\` and look for a page view in ${provider.label}.`,
2858
+ "Set the same PUBLIC_* variables on each deploy target with `vela env set`.",
2859
+ "The component lives in src/lib/components/analytics/analytics.svelte; edit it freely."
2860
+ ],
2861
+ task: {
2862
+ title: "Enabling analytics",
2863
+ success: `Enabled analytics with ${provider.label}`,
2864
+ error: "Failed to enable analytics"
2865
+ }
2866
+ }
2867
+ );
2868
+ }, "Failed to enable analytics.")
2869
+ );
2870
+
2871
+ // src/commands/enable/auth.ts
2872
+ import { Command as Command11 } from "commander";
2873
+ var auth = new Command11("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2695
2874
  (_opts, cmd) => runCommand(
2696
2875
  () => runPattern(
2697
2876
  "enable-auth",
@@ -2716,8 +2895,8 @@ var auth = new Command10("auth").description("enable authentication (email/passw
2716
2895
  );
2717
2896
 
2718
2897
  // src/commands/enable/api.ts
2719
- import { Command as Command11 } from "commander";
2720
- var api = new Command11("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2898
+ import { Command as Command12 } from "commander";
2899
+ var api = new Command12("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2721
2900
  (_opts, cmd) => runCommand(
2722
2901
  () => runPattern(
2723
2902
  "enable-api",
@@ -2742,8 +2921,8 @@ var api = new Command11("api").description("enable the PocketBase REST API").all
2742
2921
  );
2743
2922
 
2744
2923
  // src/commands/enable/api-keys.ts
2745
- import { Command as Command12 } from "commander";
2746
- var apiKeys = new Command12("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2924
+ import { Command as Command13 } from "commander";
2925
+ var apiKeys = new Command13("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2747
2926
  (_opts, cmd) => runCommand(
2748
2927
  () => runPattern(
2749
2928
  "enable-api-keys",
@@ -2768,8 +2947,8 @@ var apiKeys = new Command12("api-keys").description("enable API key management")
2768
2947
  );
2769
2948
 
2770
2949
  // src/commands/enable/backend.ts
2771
- import { Command as Command13 } from "commander";
2772
- var backend = new Command13("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2950
+ import { Command as Command14 } from "commander";
2951
+ var backend = new Command14("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2773
2952
  (_opts, cmd) => runCommand(
2774
2953
  () => runPattern(
2775
2954
  "enable-backend",
@@ -2794,8 +2973,8 @@ var backend = new Command13("backend").description("enable the PocketBase backen
2794
2973
  );
2795
2974
 
2796
2975
  // src/commands/enable/i18n.ts
2797
- import { Command as Command14 } from "commander";
2798
- var i18n = new Command14("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2976
+ import { Command as Command15 } from "commander";
2977
+ var i18n = new Command15("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2799
2978
  (_opts, cmd) => runCommand(
2800
2979
  () => runPattern(
2801
2980
  "enable-i18n",
@@ -2820,8 +2999,8 @@ var i18n = new Command14("i18n").description("enable internationalization").allo
2820
2999
  );
2821
3000
 
2822
3001
  // src/commands/enable/teams.ts
2823
- import { Command as Command15 } from "commander";
2824
- var teams = new Command15("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3002
+ import { Command as Command16 } from "commander";
3003
+ var teams = new Command16("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2825
3004
  (_opts, cmd) => runCommand(
2826
3005
  () => runPattern(
2827
3006
  "enable-teams",
@@ -2846,13 +3025,13 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
2846
3025
  );
2847
3026
 
2848
3027
  // src/commands/enable/payments.ts
2849
- import process9 from "node:process";
2850
- import { Command as Command16 } from "commander";
2851
- import * as p14 from "@clack/prompts";
3028
+ import process10 from "node:process";
3029
+ import { Command as Command17 } from "commander";
3030
+ import * as p15 from "@clack/prompts";
2852
3031
  var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
2853
- var payments = new Command16("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3032
+ var payments = new Command17("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2854
3033
  (opts, cmd) => runCommand(async () => {
2855
- const provider = await resolveProvider(opts.provider, cmd.getOptionValueSource("provider"));
3034
+ const provider = await resolveProvider2(opts.provider, cmd.getOptionValueSource("provider"));
2856
3035
  const input = {
2857
3036
  provider,
2858
3037
  stripeSecretKey: await ensureKey("STRIPE_SECRET_KEY", "Stripe secret key (sk_...)"),
@@ -2878,28 +3057,28 @@ var payments = new Command16("payments").description("enable payments").option("
2878
3057
  });
2879
3058
  }, "Failed to enable payments.")
2880
3059
  );
2881
- async function resolveProvider(value, source) {
3060
+ async function resolveProvider2(value, source) {
2882
3061
  if (source && source !== "default") {
2883
3062
  if (!PROVIDERS.some((o) => o.value === value)) {
2884
3063
  throw new Error(`Unknown payment provider: ${value}`);
2885
3064
  }
2886
3065
  return value;
2887
3066
  }
2888
- const selected = await p14.select({
3067
+ const selected = await p15.select({
2889
3068
  message: "Which payment provider?",
2890
3069
  options: PROVIDERS,
2891
3070
  initialValue: "stripe"
2892
3071
  });
2893
- if (p14.isCancel(selected)) {
2894
- p14.cancel("Operation cancelled.");
2895
- process9.exit(0);
3072
+ if (p15.isCancel(selected)) {
3073
+ p15.cancel("Operation cancelled.");
3074
+ process10.exit(0);
2896
3075
  }
2897
3076
  return selected;
2898
3077
  }
2899
3078
  async function ensureWebhookSecret() {
2900
- const existing = process9.env.STRIPE_WEBHOOK_SECRET;
3079
+ const existing = process10.env.STRIPE_WEBHOOK_SECRET;
2901
3080
  if (existing) return existing;
2902
- p14.note(
3081
+ p15.note(
2903
3082
  [
2904
3083
  "Download the Stripe CLI (https://stripe.com/docs/stripe-cli), then run:",
2905
3084
  " stripe listen --forward-to localhost:5173/webhooks/stripe",
@@ -2911,7 +3090,7 @@ async function ensureWebhookSecret() {
2911
3090
  return promptPassword("Stripe webhook signing secret (whsec_...)");
2912
3091
  }
2913
3092
  async function ensurePriceId() {
2914
- p14.note(
3093
+ p15.note(
2915
3094
  [
2916
3095
  "Stripe checkout requires a product and price_id.",
2917
3096
  "If you have a demo product price_id, enter it below, or leave blank to create a demo one for you."
@@ -2919,36 +3098,36 @@ async function ensurePriceId() {
2919
3098
  "Stripe demo product",
2920
3099
  { format: (line) => line }
2921
3100
  );
2922
- const value = await p14.text({
3101
+ const value = await p15.text({
2923
3102
  message: "Stripe price_id (price_...)",
2924
3103
  placeholder: "leave blank to create a demo product"
2925
3104
  });
2926
- if (p14.isCancel(value)) {
2927
- p14.cancel("Operation cancelled.");
2928
- process9.exit(0);
3105
+ if (p15.isCancel(value)) {
3106
+ p15.cancel("Operation cancelled.");
3107
+ process10.exit(0);
2929
3108
  }
2930
3109
  return (value ?? "").trim();
2931
3110
  }
2932
3111
  async function ensureKey(envVar, message) {
2933
- const existing = process9.env[envVar];
3112
+ const existing = process10.env[envVar];
2934
3113
  if (existing) return existing;
2935
3114
  return promptPassword(message);
2936
3115
  }
2937
3116
  async function promptPassword(message) {
2938
- const value = await p14.password({
3117
+ const value = await p15.password({
2939
3118
  message,
2940
3119
  validate: (v10) => v10 && v10.length ? void 0 : "Required"
2941
3120
  });
2942
- if (p14.isCancel(value)) {
2943
- p14.cancel("Operation cancelled.");
2944
- process9.exit(0);
3121
+ if (p15.isCancel(value)) {
3122
+ p15.cancel("Operation cancelled.");
3123
+ process10.exit(0);
2945
3124
  }
2946
3125
  return value;
2947
3126
  }
2948
3127
 
2949
3128
  // src/commands/enable/subscriptions.ts
2950
- import { Command as Command17 } from "commander";
2951
- var subscriptions = new Command17("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3129
+ import { Command as Command18 } from "commander";
3130
+ var subscriptions = new Command18("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2952
3131
  (_opts, cmd) => runCommand(
2953
3132
  () => runPattern(
2954
3133
  "enable-subscriptions",
@@ -2973,8 +3152,8 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
2973
3152
  );
2974
3153
 
2975
3154
  // src/commands/enable/notifications.ts
2976
- import { Command as Command18 } from "commander";
2977
- var notifications = new Command18("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3155
+ import { Command as Command19 } from "commander";
3156
+ var notifications = new Command19("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2978
3157
  (_opts, cmd) => runCommand(
2979
3158
  () => runPattern(
2980
3159
  "enable-notifications",
@@ -2999,15 +3178,15 @@ var notifications = new Command18("notifications").description("enable in-app no
2999
3178
  );
3000
3179
 
3001
3180
  // src/commands/enable/s3.ts
3002
- import process13 from "node:process";
3003
- import { Command as Command19 } from "commander";
3004
- import * as p17 from "@clack/prompts";
3181
+ import process14 from "node:process";
3182
+ import { Command as Command20 } from "commander";
3183
+ import * as p18 from "@clack/prompts";
3005
3184
  import pc8 from "picocolors";
3006
3185
 
3007
3186
  // src/lib/server-command.ts
3008
- import process12 from "node:process";
3187
+ import process13 from "node:process";
3009
3188
  import * as v6 from "valibot";
3010
- import * as p15 from "@clack/prompts";
3189
+ import * as p16 from "@clack/prompts";
3011
3190
  import pc5 from "picocolors";
3012
3191
 
3013
3192
  // src/lib/deploy-config.ts
@@ -3184,7 +3363,7 @@ import fs20 from "node:fs";
3184
3363
  import os3 from "node:os";
3185
3364
  import path19 from "node:path";
3186
3365
  import crypto3 from "node:crypto";
3187
- import process10 from "node:process";
3366
+ import process11 from "node:process";
3188
3367
  import { spawn as spawn2 } from "node:child_process";
3189
3368
  var RemoteCommandError = class extends Error {
3190
3369
  exitCode;
@@ -3462,17 +3641,17 @@ function spawnCapture(command, args, opts = {}) {
3462
3641
  const child = spawn2(command, args, {
3463
3642
  stdio,
3464
3643
  cwd: opts.cwd,
3465
- env: opts.env ? { ...process10.env, ...opts.env } : void 0
3644
+ env: opts.env ? { ...process11.env, ...opts.env } : void 0
3466
3645
  });
3467
3646
  let stdout = "";
3468
3647
  let stderr = "";
3469
3648
  child.stdout?.on("data", (chunk) => {
3470
3649
  stdout += chunk;
3471
- if (opts.streamStdout) process10.stdout.write(chunk);
3650
+ if (opts.streamStdout) process11.stdout.write(chunk);
3472
3651
  });
3473
3652
  child.stderr?.on("data", (chunk) => {
3474
3653
  stderr += chunk;
3475
- if (opts.stream) process10.stderr.write(chunk);
3654
+ if (opts.stream) process11.stderr.write(chunk);
3476
3655
  });
3477
3656
  child.on("error", reject);
3478
3657
  child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
@@ -3523,10 +3702,11 @@ function collectArtifact(cwd, config = {}) {
3523
3702
  const buildPath = path20.join(cwd, outputDir);
3524
3703
  if (!fs21.existsSync(path20.join(buildPath, "index.js"))) {
3525
3704
  throw new BuildError(
3526
- `No ${outputDir}/index.js after the build.
3705
+ `No ${outputDir}/index.js to deploy.
3527
3706
 
3528
- Deploying to a server needs @sveltejs/adapter-node. Install it and set it as
3529
- the adapter in your Vite or Svelte config, then build again.`
3707
+ Deploying to a server needs the output of @sveltejs/adapter-node. Check that the
3708
+ build ran with it as the adapter (and that \`outputDir\` in velastack.config
3709
+ matches where it writes), then deploy again.`
3530
3710
  );
3531
3711
  }
3532
3712
  entries.push({ localPath: buildPath, remoteDir: "" });
@@ -3578,13 +3758,17 @@ function sshOptionsFrom(options) {
3578
3758
  import crypto4 from "node:crypto";
3579
3759
  import fs22 from "node:fs";
3580
3760
  import path21 from "node:path";
3581
- import process11 from "node:process";
3761
+ import process12 from "node:process";
3582
3762
  var VELA_ROOT = "/var/lib/vela";
3583
3763
  var VELA_ETC = "/etc/vela";
3584
3764
  var VELA_USER = "vela";
3585
3765
  var SCRIPT_VERSIONS_DIR = `${VELA_ROOT}/script-versions`;
3586
3766
  var PROVISIONED_MARKER = `${VELA_ETC}/provisioned`;
3587
3767
  var ORIGIN_FILE = `${VELA_ETC}/origin.json`;
3768
+ function instanceHasBackend(state) {
3769
+ if (!state) return false;
3770
+ return state.backend ?? Boolean(state.pbPort);
3771
+ }
3588
3772
  function serverTemplatesDir() {
3589
3773
  return path21.join(templatesDir(), "server");
3590
3774
  }
@@ -3611,7 +3795,7 @@ async function syncServerScripts(session) {
3611
3795
  const dir = `${SCRIPT_VERSIONS_DIR}/${digest}`;
3612
3796
  const present = await session.script(`[ -d "$1" ] && echo yes || echo no`, { args: [dir] });
3613
3797
  if (present.stdout.trim() !== "yes") {
3614
- const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process11.pid}.${Date.now()}`;
3798
+ const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process12.pid}.${Date.now()}`;
3615
3799
  await session.script(`mkdir -p "$1" && chmod 0755 "$(dirname "$1")" "$1"`, {
3616
3800
  args: [incoming]
3617
3801
  });
@@ -3870,8 +4054,8 @@ function describeTarget(target) {
3870
4054
  return target.name;
3871
4055
  }
3872
4056
  }
3873
- function bold(text18) {
3874
- return `\`${text18}\``;
4057
+ function bold(text19) {
4058
+ return `\`${text19}\``;
3875
4059
  }
3876
4060
 
3877
4061
  // src/lib/server-command.ts
@@ -3975,7 +4159,7 @@ async function ensureBinding(workspaceRootDir, target, request = {}) {
3975
4159
  writeBinding(workspaceRootDir, key, binding);
3976
4160
  }
3977
4161
  if (moving) {
3978
- p15.log.warn(
4162
+ p16.log.warn(
3979
4163
  `${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
3980
4164
 
3981
4165
  Whatever is running on ${existing.server} is left there, and this project can no
@@ -3986,7 +4170,7 @@ longer reach it. Remove it there first if that was not intended.`
3986
4170
  }
3987
4171
  async function confirmMove(target, from, to) {
3988
4172
  const name = bindingName(target);
3989
- if (!process12.stdout.isTTY || process12.env.CI) {
4173
+ if (!process13.stdout.isTTY || process13.env.CI) {
3990
4174
  throw new Error(
3991
4175
  `${pc5.cyan(`--server ${to}`)} does not match the server recorded for ${pc5.cyan(name)}, ${pc5.cyan(from)}.
3992
4176
 
@@ -3994,13 +4178,13 @@ Drop ${pc5.cyan("--server")} to use the recorded one, or move the binding on pur
3994
4178
  this command once from a terminal (or editing .vela/project.json).`
3995
4179
  );
3996
4180
  }
3997
- const ok = await p15.confirm({
4181
+ const ok = await p16.confirm({
3998
4182
  message: `${name} ${target.kind === "preview" ? "run" : "runs"} on ${from}. Point ${name} at ${to} instead?`,
3999
4183
  initialValue: false
4000
4184
  });
4001
- if (p15.isCancel(ok) || !ok) {
4002
- p15.cancel("Operation cancelled.");
4003
- process12.exit(0);
4185
+ if (p16.isCancel(ok) || !ok) {
4186
+ p16.cancel("Operation cancelled.");
4187
+ process13.exit(0);
4004
4188
  }
4005
4189
  }
4006
4190
  function bindingName(target) {
@@ -4008,7 +4192,7 @@ function bindingName(target) {
4008
4192
  }
4009
4193
  async function promptServer(target) {
4010
4194
  const name = bindingName(target);
4011
- if (!process12.stdout.isTTY || process12.env.CI) {
4195
+ if (!process13.stdout.isTTY || process13.env.CI) {
4012
4196
  throw new Error(
4013
4197
  `${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
4014
4198
 
@@ -4016,29 +4200,29 @@ Pass ${pc5.cyan("--server user@host")}, or run the command once from your own ma
4016
4200
  and commit ${pc5.cyan(".vela/project.json")}.`
4017
4201
  );
4018
4202
  }
4019
- p15.log.info(
4203
+ p16.log.info(
4020
4204
  `${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
4021
4205
  );
4022
- const value = await p15.text({
4206
+ const value = await p16.text({
4023
4207
  message: `Which server should ${name} run on?`,
4024
4208
  placeholder: "root@203.0.113.10",
4025
4209
  validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
4026
4210
  });
4027
- if (p15.isCancel(value)) {
4028
- p15.cancel("Operation cancelled.");
4029
- process12.exit(0);
4211
+ if (p16.isCancel(value)) {
4212
+ p16.cancel("Operation cancelled.");
4213
+ process13.exit(0);
4030
4214
  }
4031
4215
  return value.trim();
4032
4216
  }
4033
4217
  async function promptDomain(target) {
4034
- if (!process12.stdout.isTTY || process12.env.CI) return void 0;
4035
- const value = await p15.text({
4218
+ if (!process13.stdout.isTTY || process13.env.CI) return void 0;
4219
+ const value = await p16.text({
4036
4220
  message: `Which hostname should ${target.name} be served on?`,
4037
4221
  placeholder: "example.com \u2014 leave blank to decide later"
4038
4222
  });
4039
- if (p15.isCancel(value)) {
4040
- p15.cancel("Operation cancelled.");
4041
- process12.exit(0);
4223
+ if (p16.isCancel(value)) {
4224
+ p16.cancel("Operation cancelled.");
4225
+ process13.exit(0);
4042
4226
  }
4043
4227
  return value.trim() || void 0;
4044
4228
  }
@@ -4046,10 +4230,10 @@ async function applyRestart(ctx) {
4046
4230
  const outcome = await restartInstance(ctx.session, ctx.instance);
4047
4231
  if (!outcome.deployed) return;
4048
4232
  if (outcome.restarted) {
4049
- p15.log.success("App restarted");
4233
+ p16.log.success("App restarted");
4050
4234
  return;
4051
4235
  }
4052
- p15.log.error(
4236
+ p16.log.error(
4053
4237
  `App restart failed.
4054
4238
 
4055
4239
  The new value is stored and will be used the next time the app starts.
@@ -4058,7 +4242,7 @@ ${pc5.dim(outcome.error ?? "")}`
4058
4242
  }
4059
4243
  async function applyEnvRestart(ctx, changed) {
4060
4244
  if (touchesSuperuser(changed)) {
4061
- p15.log.warn(
4245
+ p16.log.warn(
4062
4246
  `PocketBase superuser credentials changed.
4063
4247
 
4064
4248
  The database still holds the old ones, so the app has not been restarted.
@@ -4095,7 +4279,7 @@ import pc7 from "picocolors";
4095
4279
 
4096
4280
  // src/lib/local-env.ts
4097
4281
  import fs24 from "node:fs";
4098
- import * as p16 from "@clack/prompts";
4282
+ import * as p17 from "@clack/prompts";
4099
4283
  import pc6 from "picocolors";
4100
4284
  function readLocalEnv(envFile) {
4101
4285
  if (!fs24.existsSync(envFile)) return {};
@@ -4121,16 +4305,16 @@ async function applyLocalEnvChange(ctx, changed) {
4121
4305
  process.env.POCKETBASE_SUPERUSER_EMAIL = email3;
4122
4306
  process.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
4123
4307
  await ensureSuperuser(ctx.workspaceRootDir);
4124
- p16.log.success("Local superuser updated to match");
4308
+ p17.log.success("Local superuser updated to match");
4125
4309
  } else {
4126
- p16.log.warn(
4310
+ p17.log.warn(
4127
4311
  `The local database still has the old superuser.
4128
4312
  Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SUPERUSER_PASSWORD")} to reconcile it.`
4129
4313
  );
4130
4314
  }
4131
4315
  }
4132
4316
  if (getPocketbaseMetadata(ctx.workspaceRootDir)) {
4133
- p16.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4317
+ p17.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4134
4318
  }
4135
4319
  }
4136
4320
 
@@ -4138,12 +4322,13 @@ Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SU
4138
4322
  import PocketBase2 from "pocketbase";
4139
4323
  async function openRemoteDatabase(session, instance) {
4140
4324
  const [state] = await readInstanceStates(session, instance);
4141
- const pbPort = state?.pbPort;
4325
+ const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
4142
4326
  if (!pbPort) {
4143
4327
  throw new Error(
4144
4328
  `${instance} has no deployed database yet.
4145
4329
 
4146
- Run \`vela deploy\` first \u2014 the database is created by the first deploy.`
4330
+ Run \`vela deploy\` first \u2014 the database is created by the first deploy of a
4331
+ project with a backend (\`vela bless\` adds one).`
4147
4332
  );
4148
4333
  }
4149
4334
  const env2 = await readRemoteEnv(session, instance);
@@ -4293,7 +4478,7 @@ function hasFile(dir) {
4293
4478
 
4294
4479
  // src/commands/enable/s3.ts
4295
4480
  var s3 = addTargetOptions(
4296
- 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),
4481
+ new Command20("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),
4297
4482
  "local"
4298
4483
  ).action(
4299
4484
  (raw) => runCommand(() => {
@@ -4311,7 +4496,7 @@ var s3 = addTargetOptions(
4311
4496
  failure = error instanceof Error ? error.message : String(error);
4312
4497
  }
4313
4498
  if (failure) {
4314
- p17.log.warn(
4499
+ p18.log.warn(
4315
4500
  `The connection test failed \u2014 the settings are saved but may be wrong.
4316
4501
 
4317
4502
  ${pc8.dim(failure)}
@@ -4355,64 +4540,64 @@ Do that first, then re-run with ${pc8.cyan("--force")}.`
4355
4540
  );
4356
4541
  }
4357
4542
  async function promptConfig(options, existing) {
4358
- const endpoint = options.endpoint ?? await text7("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4359
- const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
4360
- const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
4361
- const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
4362
- const secret = options.secret ?? process13.env.VELA_S3_SECRET ?? await password5("S3 secret key");
4543
+ const endpoint = options.endpoint ?? await text8("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4544
+ const bucket = options.bucket ?? await text8("S3 bucket name", existing.bucket);
4545
+ const region = options.region ?? await text8("S3 region", existing.region || "us-east-1");
4546
+ const accessKey = options.accessKey ?? await text8("S3 access key", existing.accessKey);
4547
+ const secret = options.secret ?? process14.env.VELA_S3_SECRET ?? await password5("S3 secret key");
4363
4548
  const forcePathStyle = options.forcePathStyle ?? await confirm4(
4364
4549
  "Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
4365
4550
  defaultForcePathStyle(endpoint)
4366
4551
  );
4367
4552
  return { endpoint, bucket, region, accessKey, secret, forcePathStyle };
4368
4553
  }
4369
- async function text7(message, initialValue = "") {
4370
- const value = await p17.text({
4554
+ async function text8(message, initialValue = "") {
4555
+ const value = await p18.text({
4371
4556
  message,
4372
4557
  initialValue,
4373
4558
  validate: (input) => input?.trim() ? void 0 : `${message} is required`
4374
4559
  });
4375
- if (p17.isCancel(value)) {
4376
- p17.cancel("Operation cancelled.");
4377
- process13.exit(0);
4560
+ if (p18.isCancel(value)) {
4561
+ p18.cancel("Operation cancelled.");
4562
+ process14.exit(0);
4378
4563
  }
4379
4564
  return value.trim();
4380
4565
  }
4381
4566
  async function password5(message) {
4382
- const value = await p17.password({
4567
+ const value = await p18.password({
4383
4568
  message,
4384
4569
  validate: (input) => input ? void 0 : `${message} is required`
4385
4570
  });
4386
- if (p17.isCancel(value)) {
4387
- p17.cancel("Operation cancelled.");
4388
- process13.exit(0);
4571
+ if (p18.isCancel(value)) {
4572
+ p18.cancel("Operation cancelled.");
4573
+ process14.exit(0);
4389
4574
  }
4390
4575
  return value;
4391
4576
  }
4392
4577
  async function confirm4(message, initialValue) {
4393
- const value = await p17.confirm({ message, initialValue });
4394
- if (p17.isCancel(value)) {
4395
- p17.cancel("Operation cancelled.");
4396
- process13.exit(0);
4578
+ const value = await p18.confirm({ message, initialValue });
4579
+ if (p18.isCancel(value)) {
4580
+ p18.cancel("Operation cancelled.");
4581
+ process14.exit(0);
4397
4582
  }
4398
4583
  return value;
4399
4584
  }
4400
4585
 
4401
4586
  // src/commands/enable/smtp.ts
4402
- import process14 from "node:process";
4403
- import { Command as Command20 } from "commander";
4404
- import * as p18 from "@clack/prompts";
4405
- var smtp = new Command20("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4587
+ import process15 from "node:process";
4588
+ import { Command as Command21 } from "commander";
4589
+ import * as p19 from "@clack/prompts";
4590
+ var smtp = new Command21("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4406
4591
  () => runCommand(async () => {
4407
4592
  const { workspaceRootDir } = await getWorkspace();
4408
- const config = await p18.group(
4593
+ const config = await p19.group(
4409
4594
  {
4410
- host: () => p18.text({
4595
+ host: () => p19.text({
4411
4596
  message: "SMTP host",
4412
4597
  placeholder: "smtp.example.com",
4413
4598
  validate: (v10) => v10 ? void 0 : "Host is required"
4414
4599
  }),
4415
- port: () => p18.text({
4600
+ port: () => p19.text({
4416
4601
  message: "SMTP port",
4417
4602
  initialValue: "587",
4418
4603
  validate: (v10) => {
@@ -4422,13 +4607,13 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
4422
4607
  return void 0;
4423
4608
  }
4424
4609
  }),
4425
- username: () => p18.text({ message: "SMTP username" }),
4426
- password: () => p18.password({ message: "SMTP password" })
4610
+ username: () => p19.text({ message: "SMTP username" }),
4611
+ password: () => p19.password({ message: "SMTP password" })
4427
4612
  },
4428
4613
  {
4429
4614
  onCancel: () => {
4430
- p18.cancel("Operation cancelled.");
4431
- process14.exit(0);
4615
+ p19.cancel("Operation cancelled.");
4616
+ process15.exit(0);
4432
4617
  }
4433
4618
  }
4434
4619
  );
@@ -4455,24 +4640,24 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
4455
4640
  );
4456
4641
 
4457
4642
  // src/commands/enable/cms.ts
4458
- import process15 from "node:process";
4459
- import { Command as Command21 } from "commander";
4460
- import * as p19 from "@clack/prompts";
4643
+ import process16 from "node:process";
4644
+ import { Command as Command22 } from "commander";
4645
+ import * as p20 from "@clack/prompts";
4461
4646
  import pc9 from "picocolors";
4462
- var cms = new Command21("cms").description("enable an inline-editing CMS with an admin bar").option(
4647
+ var cms = new Command22("cms").description("enable an inline-editing CMS with an admin bar").option(
4463
4648
  "--endpoint <url>",
4464
4649
  "read from a hosted CMS at this URL instead of installing the backend in this app"
4465
4650
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4466
4651
  (opts, cmd) => runCommand(async () => {
4467
4652
  if (!opts.endpoint && !hasBackend()) {
4468
- p19.log.error(
4653
+ p20.log.error(
4469
4654
  `${pc9.cyan("vela enable cms")} needs a server to host the CMS backend, and this project is static.
4470
4655
 
4471
4656
  Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${pc9.cyan("vela enable cms --endpoint <url>")}.`
4472
4657
  );
4473
- p19.log.message();
4474
- p19.cancel("Operation failed.");
4475
- process15.exitCode = 1;
4658
+ p20.log.message();
4659
+ p20.cancel("Operation failed.");
4660
+ process16.exitCode = 1;
4476
4661
  return;
4477
4662
  }
4478
4663
  await runPattern("enable-cms", cmd.args, opts.endpoint ? { endpoint: opts.endpoint } : {}, {
@@ -4492,8 +4677,8 @@ Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${
4492
4677
  );
4493
4678
 
4494
4679
  // src/commands/enable/blog.ts
4495
- import { Command as Command22 } from "commander";
4496
- var blog = new Command22("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4680
+ import { Command as Command23 } from "commander";
4681
+ var blog = new Command23("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4497
4682
  (_opts, cmd) => runCommand(
4498
4683
  () => runPattern(
4499
4684
  "enable-blog",
@@ -4518,8 +4703,8 @@ var blog = new Command22("blog").description("enable an mdsvex blog with posts,
4518
4703
  );
4519
4704
 
4520
4705
  // src/commands/enable/content-negotiation.ts
4521
- import { Command as Command23 } from "commander";
4522
- var contentNegotiation = new Command23("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4706
+ import { Command as Command24 } from "commander";
4707
+ var contentNegotiation = new Command24("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4523
4708
  (_opts, cmd) => runCommand(
4524
4709
  () => runPattern(
4525
4710
  "enable-content-negotiation",
@@ -4543,33 +4728,33 @@ var contentNegotiation = new Command23("content-negotiation").description("enabl
4543
4728
  );
4544
4729
 
4545
4730
  // src/commands/enable.ts
4546
- 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);
4731
+ var enable = new Command25("enable").description("enable features").configureHelp(helpConfig).addCommand(analytics).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);
4547
4732
 
4548
4733
  // src/commands/disable.ts
4549
- import { Command as Command35 } from "commander";
4734
+ import { Command as Command36 } from "commander";
4550
4735
 
4551
4736
  // src/commands/disable/auth.ts
4552
- import { Command as Command25 } from "commander";
4737
+ import { Command as Command26 } from "commander";
4553
4738
 
4554
4739
  // src/commands/disable/_shared.ts
4555
- import process16 from "node:process";
4556
- import * as p20 from "@clack/prompts";
4740
+ import process17 from "node:process";
4741
+ import * as p21 from "@clack/prompts";
4557
4742
  async function runDisable(opts, flags, cmdArgs) {
4558
4743
  if (!flags.yes) {
4559
- const ok = await p20.confirm({
4744
+ const ok = await p21.confirm({
4560
4745
  message: opts.confirmMessage,
4561
4746
  initialValue: false
4562
4747
  });
4563
- if (p20.isCancel(ok) || !ok) {
4564
- p20.cancel("Operation cancelled.");
4565
- process16.exit(0);
4748
+ if (p21.isCancel(ok) || !ok) {
4749
+ p21.cancel("Operation cancelled.");
4750
+ process17.exit(0);
4566
4751
  }
4567
4752
  }
4568
4753
  await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
4569
4754
  }
4570
4755
 
4571
4756
  // src/commands/disable/auth.ts
4572
- var auth2 = new Command25("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4757
+ var auth2 = new Command26("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4573
4758
  (opts, cmd) => runCommand(
4574
4759
  () => runDisable(
4575
4760
  {
@@ -4595,8 +4780,8 @@ var auth2 = new Command25("auth").description("disable authentication").option("
4595
4780
  );
4596
4781
 
4597
4782
  // src/commands/disable/api.ts
4598
- import { Command as Command26 } from "commander";
4599
- var api2 = new Command26("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4783
+ import { Command as Command27 } from "commander";
4784
+ var api2 = new Command27("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4600
4785
  (opts, cmd) => runCommand(
4601
4786
  () => runDisable(
4602
4787
  {
@@ -4619,8 +4804,8 @@ var api2 = new Command26("api").description("disable the REST API").option("-y,
4619
4804
  );
4620
4805
 
4621
4806
  // src/commands/disable/api-keys.ts
4622
- import { Command as Command27 } from "commander";
4623
- var apiKeys2 = new Command27("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4807
+ import { Command as Command28 } from "commander";
4808
+ var apiKeys2 = new Command28("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4624
4809
  (opts, cmd) => runCommand(
4625
4810
  () => runDisable(
4626
4811
  {
@@ -4643,8 +4828,8 @@ var apiKeys2 = new Command27("api-keys").description("disable API key management
4643
4828
  );
4644
4829
 
4645
4830
  // src/commands/disable/backend.ts
4646
- import { Command as Command28 } from "commander";
4647
- var backend2 = new Command28("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4831
+ import { Command as Command29 } from "commander";
4832
+ var backend2 = new Command29("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4648
4833
  (opts, cmd) => runCommand(
4649
4834
  () => runDisable(
4650
4835
  {
@@ -4667,8 +4852,8 @@ var backend2 = new Command28("backend").description("disable the PocketBase back
4667
4852
  );
4668
4853
 
4669
4854
  // src/commands/disable/content-negotiation.ts
4670
- import { Command as Command29 } from "commander";
4671
- var contentNegotiation2 = new Command29("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4855
+ import { Command as Command30 } from "commander";
4856
+ var contentNegotiation2 = new Command30("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4672
4857
  (opts, cmd) => runCommand(
4673
4858
  () => runDisable(
4674
4859
  {
@@ -4691,8 +4876,8 @@ var contentNegotiation2 = new Command29("content-negotiation").description("disa
4691
4876
  );
4692
4877
 
4693
4878
  // src/commands/disable/i18n.ts
4694
- import { Command as Command30 } from "commander";
4695
- var i18n2 = new Command30("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4879
+ import { Command as Command31 } from "commander";
4880
+ var i18n2 = new Command31("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4696
4881
  (opts, cmd) => runCommand(
4697
4882
  () => runDisable(
4698
4883
  {
@@ -4718,8 +4903,8 @@ var i18n2 = new Command30("i18n").description("disable internationalization").op
4718
4903
  );
4719
4904
 
4720
4905
  // src/commands/disable/teams.ts
4721
- import { Command as Command31 } from "commander";
4722
- var teams2 = new Command31("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4906
+ import { Command as Command32 } from "commander";
4907
+ var teams2 = new Command32("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4723
4908
  (opts, cmd) => runCommand(
4724
4909
  () => runDisable(
4725
4910
  {
@@ -4745,8 +4930,8 @@ var teams2 = new Command31("teams").description("disable teams").option("-y, --y
4745
4930
  );
4746
4931
 
4747
4932
  // src/commands/disable/payments.ts
4748
- import { Command as Command32 } from "commander";
4749
- var payments2 = new Command32("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4933
+ import { Command as Command33 } from "commander";
4934
+ var payments2 = new Command33("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4750
4935
  (opts, cmd) => runCommand(
4751
4936
  () => runDisable(
4752
4937
  {
@@ -4773,11 +4958,11 @@ var payments2 = new Command32("payments").description("disable payments").option
4773
4958
  );
4774
4959
 
4775
4960
  // src/commands/disable/s3.ts
4776
- import { Command as Command33 } from "commander";
4777
- import * as p21 from "@clack/prompts";
4961
+ import { Command as Command34 } from "commander";
4962
+ import * as p22 from "@clack/prompts";
4778
4963
  import pc10 from "picocolors";
4779
4964
  var s32 = addTargetOptions(
4780
- new Command33("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4965
+ new Command34("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4781
4966
  "local"
4782
4967
  ).action(
4783
4968
  (raw) => runCommand(() => {
@@ -4786,7 +4971,7 @@ var s32 = addTargetOptions(
4786
4971
  return withBackupTarget(raw, "disable s3", async (ctx) => {
4787
4972
  const existing = await readS3(ctx.pb, filesystem);
4788
4973
  if (!existing.enabled) {
4789
- p21.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
4974
+ p22.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
4790
4975
  return;
4791
4976
  }
4792
4977
  await disableS3(ctx.pb, filesystem);
@@ -4806,8 +4991,8 @@ function label2(filesystem) {
4806
4991
  }
4807
4992
 
4808
4993
  // src/commands/disable/smtp.ts
4809
- import { Command as Command34 } from "commander";
4810
- var smtp2 = new Command34("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4994
+ import { Command as Command35 } from "commander";
4995
+ var smtp2 = new Command35("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4811
4996
  () => runCommand(async () => {
4812
4997
  const { workspaceRootDir } = await getWorkspace();
4813
4998
  await withPocketbase(workspaceRootDir, async (pb) => {
@@ -4824,30 +5009,30 @@ var smtp2 = new Command34("smtp").description("disable SMTP configuration").conf
4824
5009
  );
4825
5010
 
4826
5011
  // src/commands/disable.ts
4827
- 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);
5012
+ var disable = new Command36("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);
4828
5013
 
4829
5014
  // src/commands/destroy.ts
4830
- import { Command as Command41 } from "commander";
5015
+ import { Command as Command42 } from "commander";
4831
5016
 
4832
5017
  // src/commands/destroy/form.ts
4833
- import { Command as Command36 } from "commander";
5018
+ import { Command as Command37 } from "commander";
4834
5019
 
4835
5020
  // src/commands/destroy/_shared.ts
4836
- import process17 from "node:process";
4837
- import * as p22 from "@clack/prompts";
5021
+ import process18 from "node:process";
5022
+ import * as p23 from "@clack/prompts";
4838
5023
  async function runDestroy(slug2, model, confirmMessage, report4, flags) {
4839
5024
  if (!flags.yes) {
4840
- const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
4841
- if (p22.isCancel(ok) || !ok) {
4842
- p22.cancel("Operation cancelled.");
4843
- process17.exit(0);
5025
+ const ok = await p23.confirm({ message: confirmMessage, initialValue: false });
5026
+ if (p23.isCancel(ok) || !ok) {
5027
+ p23.cancel("Operation cancelled.");
5028
+ process18.exit(0);
4844
5029
  }
4845
5030
  }
4846
5031
  await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
4847
5032
  }
4848
5033
 
4849
5034
  // src/commands/destroy/form.ts
4850
- 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(
5035
+ var form2 = new Command37("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(
4851
5036
  "--route <route>",
4852
5037
  "custom route the form was generated at (must match the --route used at generation)"
4853
5038
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -4871,8 +5056,8 @@ var form2 = new Command36("form").description("destroy a form generated by `vela
4871
5056
  );
4872
5057
 
4873
5058
  // src/commands/destroy/schema.ts
4874
- import { Command as Command37 } from "commander";
4875
- 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).allowExcessArguments(true).configureHelp(helpConfig).action(
5059
+ import { Command as Command38 } from "commander";
5060
+ var schema2 = new Command38("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).allowExcessArguments(true).configureHelp(helpConfig).action(
4876
5061
  (model, opts) => runCommand(
4877
5062
  () => runDestroy(
4878
5063
  "destroy-schema",
@@ -4893,8 +5078,8 @@ var schema2 = new Command37("schema").description("destroy a zod schema generate
4893
5078
  );
4894
5079
 
4895
5080
  // src/commands/destroy/resource.ts
4896
- import { Command as Command38 } from "commander";
4897
- 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).allowExcessArguments(true).configureHelp(helpConfig).action(
5081
+ import { Command as Command39 } from "commander";
5082
+ var resource2 = new Command39("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).allowExcessArguments(true).configureHelp(helpConfig).action(
4898
5083
  (model, opts) => runCommand(
4899
5084
  () => runDestroy(
4900
5085
  "destroy-resource",
@@ -4915,8 +5100,8 @@ var resource2 = new Command38("resource").description("destroy a resource genera
4915
5100
  );
4916
5101
 
4917
5102
  // src/commands/destroy/scaffold.ts
4918
- import { Command as Command39 } from "commander";
4919
- 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(
5103
+ import { Command as Command40 } from "commander";
5104
+ var scaffold2 = new Command40("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(
4920
5105
  "--route <route>",
4921
5106
  "custom route the scaffold was generated at (must match the --route used at generation)"
4922
5107
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -4943,9 +5128,9 @@ var scaffold2 = new Command39("scaffold").description("destroy a scaffold genera
4943
5128
  );
4944
5129
 
4945
5130
  // src/commands/destroy/deployment.ts
4946
- import process18 from "node:process";
4947
- import { Command as Command40 } from "commander";
4948
- import * as p25 from "@clack/prompts";
5131
+ import process19 from "node:process";
5132
+ import { Command as Command41 } from "commander";
5133
+ import * as p26 from "@clack/prompts";
4949
5134
  import pc13 from "picocolors";
4950
5135
 
4951
5136
  // src/lib/destroy-guard.ts
@@ -4993,11 +5178,11 @@ function describe({ appName, envTag, purge }) {
4993
5178
  }
4994
5179
 
4995
5180
  // src/lib/deploy-report.ts
4996
- import * as p24 from "@clack/prompts";
5181
+ import * as p25 from "@clack/prompts";
4997
5182
  import pc12 from "picocolors";
4998
5183
 
4999
5184
  // src/lib/server-identity.ts
5000
- import * as p23 from "@clack/prompts";
5185
+ import * as p24 from "@clack/prompts";
5001
5186
  import pc11 from "picocolors";
5002
5187
 
5003
5188
  // src/lib/velastack-api.ts
@@ -5087,7 +5272,7 @@ async function ensureServerIdentity(session, apiKey) {
5087
5272
  if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
5088
5273
  await writeServerIdentity(session, registered);
5089
5274
  if (existing) {
5090
- p23.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5275
+ p24.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5091
5276
  }
5092
5277
  }
5093
5278
  await runServerScript(session, "origin.sh");
@@ -5127,7 +5312,7 @@ function createDeployReporter(workspaceRootDir) {
5127
5312
  const link2 = readProjectConfig(workspaceRootDir);
5128
5313
  const apiKey = link2 ? readApiKey() : null;
5129
5314
  if (link2 && !apiKey) {
5130
- p24.log.warn(
5315
+ p25.log.warn(
5131
5316
  `This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
5132
5317
  API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
5133
5318
  ${pc12.cyan("VELA_API_KEY")}.`
@@ -5177,7 +5362,7 @@ async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
5177
5362
  }
5178
5363
  }
5179
5364
  function warn(what, err) {
5180
- p24.log.warn(
5365
+ p25.log.warn(
5181
5366
  `velastack.dev could not ${what}.
5182
5367
  ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5183
5368
  );
@@ -5186,7 +5371,7 @@ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5186
5371
  // src/commands/destroy/deployment.ts
5187
5372
  var deployment = addLockWaitOption(
5188
5373
  addTargetOptions(
5189
- new Command40("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5374
+ new Command41("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5190
5375
  "production"
5191
5376
  )
5192
5377
  ).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").option(
@@ -5205,7 +5390,7 @@ var deployment = addLockWaitOption(
5205
5390
  purge: options.purge === true,
5206
5391
  yes: options.yes === true,
5207
5392
  confirm: options.confirm,
5208
- interactive: Boolean(process18.stdin.isTTY && process18.stdout.isTTY)
5393
+ interactive: Boolean(process19.stdin.isTTY && process19.stdout.isTTY)
5209
5394
  });
5210
5395
  if (decision.kind === "refuse") throw new Error(decision.message);
5211
5396
  if (decision.kind === "prompt") {
@@ -5220,13 +5405,13 @@ var deployment = addLockWaitOption(
5220
5405
  stream: true
5221
5406
  });
5222
5407
  if (result?.existed === false) {
5223
- p25.log.info(
5408
+ p26.log.info(
5224
5409
  `Nothing named ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} on ${ctx.server}; nothing to remove.`
5225
5410
  );
5226
5411
  return;
5227
5412
  }
5228
5413
  await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
5229
- p25.log.success(
5414
+ p26.log.success(
5230
5415
  `Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? result.trash ? `
5231
5416
 
5232
5417
  A snapshot of its data is at ${pc13.cyan(result.trash)} on the server for two weeks.` : "" : `
@@ -5244,35 +5429,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
5244
5429
  );
5245
5430
  async function confirm8(appName, targetName, byName) {
5246
5431
  if (byName) {
5247
- const answer = await p25.text({
5432
+ const answer = await p26.text({
5248
5433
  message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}. Type the app name to confirm`,
5249
5434
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
5250
5435
  });
5251
- if (p25.isCancel(answer)) {
5252
- p25.cancel("Operation cancelled.");
5253
- process18.exit(0);
5436
+ if (p26.isCancel(answer)) {
5437
+ p26.cancel("Operation cancelled.");
5438
+ process19.exit(0);
5254
5439
  }
5255
5440
  return;
5256
5441
  }
5257
- const ok = await p25.confirm({
5442
+ const ok = await p26.confirm({
5258
5443
  message: `Remove ${appName} (${targetName})?`,
5259
5444
  initialValue: false
5260
5445
  });
5261
- if (p25.isCancel(ok) || !ok) {
5262
- p25.cancel("Operation cancelled.");
5263
- process18.exit(0);
5446
+ if (p26.isCancel(ok) || !ok) {
5447
+ p26.cancel("Operation cancelled.");
5448
+ process19.exit(0);
5264
5449
  }
5265
5450
  }
5266
5451
 
5267
5452
  // src/commands/destroy.ts
5268
- var destroy = new Command41("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5453
+ var destroy = new Command42("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5269
5454
 
5270
5455
  // src/commands/ui.ts
5271
- import { Command as Command47 } from "commander";
5456
+ import { Command as Command48 } from "commander";
5272
5457
 
5273
5458
  // src/commands/ui/add.ts
5274
- import { Command as Command42 } from "commander";
5275
- import * as p26 from "@clack/prompts";
5459
+ import { Command as Command43 } from "commander";
5460
+ import * as p27 from "@clack/prompts";
5276
5461
  import { installComponents } from "@velastack/patterns";
5277
5462
 
5278
5463
  // src/lib/ui-add.ts
@@ -5321,10 +5506,10 @@ function uiAddReport(requested, outcome) {
5321
5506
  }
5322
5507
 
5323
5508
  // src/commands/ui/add.ts
5324
- 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(
5509
+ var add = new Command43("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(
5325
5510
  (components, options) => runCommand(async () => {
5326
5511
  const { workspaceRootDir } = await getWorkspace();
5327
- const log45 = p26.taskLog({ title: "Adding UI components..." });
5512
+ const log45 = p27.taskLog({ title: "Adding UI components..." });
5328
5513
  let outcome;
5329
5514
  try {
5330
5515
  outcome = await installComponents({
@@ -5343,13 +5528,13 @@ var add = new Command42("add").description("add ui components (shadcn-svelte ite
5343
5528
  );
5344
5529
 
5345
5530
  // src/commands/ui/base.ts
5346
- import { Command as Command43 } from "commander";
5347
- import * as p27 from "@clack/prompts";
5531
+ import { Command as Command44 } from "commander";
5532
+ import * as p28 from "@clack/prompts";
5348
5533
  import { applyBaseColor } from "@velastack/patterns";
5349
- var base = new Command43("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5534
+ var base = new Command44("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5350
5535
  (color) => runCommand(async () => {
5351
5536
  const { workspaceRootDir } = await getWorkspace();
5352
- const log45 = p27.taskLog({ title: `Applying the ${color} palette...` });
5537
+ const log45 = p28.taskLog({ title: `Applying the ${color} palette...` });
5353
5538
  let outcome;
5354
5539
  try {
5355
5540
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
@@ -5371,8 +5556,8 @@ var base = new Command43("base").description("change the base (gray) palette").a
5371
5556
  );
5372
5557
 
5373
5558
  // src/commands/ui/list.ts
5374
- import { Command as Command44 } from "commander";
5375
- import * as p28 from "@clack/prompts";
5559
+ import { Command as Command45 } from "commander";
5560
+ import * as p29 from "@clack/prompts";
5376
5561
  import { listComponents } from "@velastack/patterns";
5377
5562
 
5378
5563
  // src/lib/ui-list.ts
@@ -5403,7 +5588,7 @@ function uiListReport(result) {
5403
5588
  }
5404
5589
 
5405
5590
  // src/commands/ui/list.ts
5406
- 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(
5591
+ var list = new Command45("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
5407
5592
  (options) => runCommand(async () => {
5408
5593
  const { workspaceRootDir } = await getWorkspace();
5409
5594
  if (options.json) {
@@ -5411,7 +5596,7 @@ var list = new Command44("list").description("list installed ui components, vela
5411
5596
  console.log(JSON.stringify(result2, null, 2));
5412
5597
  return;
5413
5598
  }
5414
- const spinner7 = p28.spinner();
5599
+ const spinner7 = p29.spinner();
5415
5600
  spinner7.start("Reading the registry...");
5416
5601
  let result;
5417
5602
  try {
@@ -5423,15 +5608,15 @@ var list = new Command44("list").description("list installed ui components, vela
5423
5608
  spinner7.stop(`Read the ${result.style} registry`);
5424
5609
  reportResult(uiListReport(result));
5425
5610
  if (result.registryUnavailable) {
5426
- p28.log.warn(`${result.registryUnavailable}
5611
+ p29.log.warn(`${result.registryUnavailable}
5427
5612
  Registry components are not listed.`);
5428
5613
  }
5429
5614
  }, "Failed to list UI components.")
5430
5615
  );
5431
5616
 
5432
5617
  // src/commands/ui/style.ts
5433
- import { Command as Command45 } from "commander";
5434
- import * as p29 from "@clack/prompts";
5618
+ import { Command as Command46 } from "commander";
5619
+ import * as p30 from "@clack/prompts";
5435
5620
  import { switchStyle } from "@velastack/patterns";
5436
5621
 
5437
5622
  // src/lib/ui-style.ts
@@ -5457,10 +5642,10 @@ function uiStyleReport(result) {
5457
5642
  }
5458
5643
 
5459
5644
  // src/commands/ui/style.ts
5460
- 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(
5645
+ var style = new Command46("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(
5461
5646
  (name, options) => runCommand(async () => {
5462
5647
  const { workspaceRootDir } = await getWorkspace();
5463
- const spinner7 = p29.spinner();
5648
+ const spinner7 = p30.spinner();
5464
5649
  spinner7.start(`Reading the ${name} registry...`);
5465
5650
  let log45;
5466
5651
  let outcome;
@@ -5473,20 +5658,20 @@ var style = new Command45("style").description("switch the shadcn-svelte style,
5473
5658
  confirm: async (components) => {
5474
5659
  spinner7.stop(`Read the ${name} registry`);
5475
5660
  if (components.length > 0) {
5476
- p29.log.info(
5661
+ p30.log.info(
5477
5662
  `Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
5478
5663
  ${components.map((c) => `- ${c}`).join("\n")}`
5479
5664
  );
5480
5665
  } else {
5481
- p29.log.info(
5666
+ p30.log.info(
5482
5667
  `No installed component comes from the registry; only the config changes.`
5483
5668
  );
5484
5669
  }
5485
5670
  if (!options.yes) {
5486
- const ok = await p29.confirm({ message: `Switch to ${name}?`, initialValue: false });
5487
- if (p29.isCancel(ok) || !ok) return false;
5671
+ const ok = await p30.confirm({ message: `Switch to ${name}?`, initialValue: false });
5672
+ if (p30.isCancel(ok) || !ok) return false;
5488
5673
  }
5489
- log45 = p29.taskLog({ title: `Switching to the ${name} style...` });
5674
+ log45 = p30.taskLog({ title: `Switching to the ${name} style...` });
5490
5675
  return true;
5491
5676
  }
5492
5677
  });
@@ -5497,11 +5682,11 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5497
5682
  }
5498
5683
  spinner7.stop(`Read the ${name} registry`);
5499
5684
  if (outcome.status === "unchanged") {
5500
- p29.log.info(`Already using the ${name} style.`);
5685
+ p30.log.info(`Already using the ${name} style.`);
5501
5686
  return;
5502
5687
  }
5503
5688
  if (outcome.status === "cancelled") {
5504
- p29.cancel("Operation cancelled.");
5689
+ p30.cancel("Operation cancelled.");
5505
5690
  return;
5506
5691
  }
5507
5692
  log45?.success("Style switched");
@@ -5510,13 +5695,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5510
5695
  );
5511
5696
 
5512
5697
  // src/commands/ui/theme.ts
5513
- import { Command as Command46 } from "commander";
5514
- import * as p30 from "@clack/prompts";
5698
+ import { Command as Command47 } from "commander";
5699
+ import * as p31 from "@clack/prompts";
5515
5700
  import { applyTheme } from "@velastack/patterns";
5516
- var theme = new Command46("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
5701
+ var theme = new Command47("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
5517
5702
  (accent) => runCommand(async () => {
5518
5703
  const { workspaceRootDir } = await getWorkspace();
5519
- const log45 = p30.taskLog({ title: `Applying the ${accent} accent...` });
5704
+ const log45 = p31.taskLog({ title: `Applying the ${accent} accent...` });
5520
5705
  let outcome;
5521
5706
  try {
5522
5707
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
@@ -5538,22 +5723,22 @@ var theme = new Command46("theme").description("change the accent color, keeping
5538
5723
  );
5539
5724
 
5540
5725
  // src/commands/ui.ts
5541
- var ui = new Command47("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5726
+ var ui = new Command48("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5542
5727
 
5543
5728
  // src/commands/legal.ts
5544
- import { Command as Command50 } from "commander";
5729
+ import { Command as Command51 } from "commander";
5545
5730
 
5546
5731
  // src/commands/legal/terms.ts
5547
5732
  import fs26 from "node:fs";
5548
5733
  import path23 from "node:path";
5549
- import { Command as Command48 } from "commander";
5550
- import * as p32 from "@clack/prompts";
5734
+ import { Command as Command49 } from "commander";
5735
+ import * as p33 from "@clack/prompts";
5551
5736
 
5552
5737
  // src/commands/legal/shared.ts
5553
- import process19 from "node:process";
5554
- import * as p31 from "@clack/prompts";
5738
+ import process20 from "node:process";
5739
+ import * as p32 from "@clack/prompts";
5555
5740
  var sharedFields = {
5556
- websiteUrl: () => p31.text({
5741
+ websiteUrl: () => p32.text({
5557
5742
  message: "What is your website URL?",
5558
5743
  placeholder: "http://www.mysite.com",
5559
5744
  validate: (value) => {
@@ -5562,7 +5747,7 @@ var sharedFields = {
5562
5747
  }
5563
5748
  }
5564
5749
  }),
5565
- websiteName: () => p31.text({
5750
+ websiteName: () => p32.text({
5566
5751
  message: "What is your website name?",
5567
5752
  placeholder: "My Site",
5568
5753
  validate: (value) => {
@@ -5571,7 +5756,7 @@ var sharedFields = {
5571
5756
  }
5572
5757
  }
5573
5758
  }),
5574
- entityType: () => p31.select({
5759
+ entityType: () => p32.select({
5575
5760
  message: "Entity type",
5576
5761
  options: [
5577
5762
  {
@@ -5582,7 +5767,7 @@ var sharedFields = {
5582
5767
  { value: "individual", label: "I'm an Individual" }
5583
5768
  ]
5584
5769
  }),
5585
- businessName: ({ results }) => results?.entityType === "business" ? p31.text({
5770
+ businessName: ({ results }) => results?.entityType === "business" ? p32.text({
5586
5771
  message: "What is the name of the business?",
5587
5772
  placeholder: "My Company LLC",
5588
5773
  validate: (value) => {
@@ -5591,7 +5776,7 @@ var sharedFields = {
5591
5776
  }
5592
5777
  }
5593
5778
  }) : void 0,
5594
- businessAddress: ({ results }) => results?.entityType === "business" ? p31.text({
5779
+ businessAddress: ({ results }) => results?.entityType === "business" ? p32.text({
5595
5780
  message: "What is the address of the business?",
5596
5781
  placeholder: "1 Cupertino, CA 95014",
5597
5782
  validate: (value) => {
@@ -5600,7 +5785,7 @@ var sharedFields = {
5600
5785
  }
5601
5786
  }
5602
5787
  }) : void 0,
5603
- country: () => p31.text({
5788
+ country: () => p32.text({
5604
5789
  message: "Enter the country",
5605
5790
  validate: (value) => {
5606
5791
  if (!value) {
@@ -5608,7 +5793,7 @@ var sharedFields = {
5608
5793
  }
5609
5794
  }
5610
5795
  }),
5611
- state: () => p31.text({
5796
+ state: () => p32.text({
5612
5797
  message: "Enter the state",
5613
5798
  validate: (value) => {
5614
5799
  if (!value) {
@@ -5618,11 +5803,11 @@ var sharedFields = {
5618
5803
  })
5619
5804
  };
5620
5805
  var onCancel = () => {
5621
- p31.cancel("Operation cancelled.");
5622
- process19.exit(0);
5806
+ p32.cancel("Operation cancelled.");
5807
+ process20.exit(0);
5623
5808
  };
5624
5809
  async function contactMethods(type) {
5625
- const selection = await p31.multiselect({
5810
+ const selection = await p32.multiselect({
5626
5811
  message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
5627
5812
  options: [
5628
5813
  { value: "email", label: "By email" },
@@ -5631,11 +5816,11 @@ async function contactMethods(type) {
5631
5816
  { value: "mail", label: "By sending post mail" }
5632
5817
  ]
5633
5818
  });
5634
- if (p31.isCancel(selection)) onCancel();
5819
+ if (p32.isCancel(selection)) onCancel();
5635
5820
  const contact = selection;
5636
5821
  const details = {};
5637
5822
  if (contact.includes("email")) {
5638
- const email3 = await p31.text({
5823
+ const email3 = await p32.text({
5639
5824
  message: "What's the email?",
5640
5825
  placeholder: "office@mycompany.com",
5641
5826
  validate: (value) => {
@@ -5644,11 +5829,11 @@ async function contactMethods(type) {
5644
5829
  }
5645
5830
  }
5646
5831
  });
5647
- if (p31.isCancel(email3)) onCancel();
5832
+ if (p32.isCancel(email3)) onCancel();
5648
5833
  details.email = email3;
5649
5834
  }
5650
5835
  if (contact.includes("page")) {
5651
- const page = await p31.text({
5836
+ const page = await p32.text({
5652
5837
  message: "What's the link?",
5653
5838
  placeholder: "http://www.mycompany.com/contact",
5654
5839
  validate: (value) => {
@@ -5657,11 +5842,11 @@ async function contactMethods(type) {
5657
5842
  }
5658
5843
  }
5659
5844
  });
5660
- if (p31.isCancel(page)) onCancel();
5845
+ if (p32.isCancel(page)) onCancel();
5661
5846
  details.page = page;
5662
5847
  }
5663
5848
  if (contact.includes("phone")) {
5664
- const phone = await p31.text({
5849
+ const phone = await p32.text({
5665
5850
  message: "What's the phone number?",
5666
5851
  placeholder: "408.996.1010",
5667
5852
  validate: (value) => {
@@ -5670,11 +5855,11 @@ async function contactMethods(type) {
5670
5855
  }
5671
5856
  }
5672
5857
  });
5673
- if (p31.isCancel(phone)) onCancel();
5858
+ if (p32.isCancel(phone)) onCancel();
5674
5859
  details.phone = phone;
5675
5860
  }
5676
5861
  if (contact.includes("mail")) {
5677
- const address = await p31.text({
5862
+ const address = await p32.text({
5678
5863
  message: "What's the address?",
5679
5864
  placeholder: "767 Fifth Avenue New York, NY 10153, United States",
5680
5865
  validate: (value) => {
@@ -5683,7 +5868,7 @@ async function contactMethods(type) {
5683
5868
  }
5684
5869
  }
5685
5870
  });
5686
- if (p31.isCancel(address)) onCancel();
5871
+ if (p32.isCancel(address)) onCancel();
5687
5872
  details.address = address;
5688
5873
  }
5689
5874
  return { methods: contact, details };
@@ -6079,7 +6264,7 @@ var generateTermsHtml = (answers) => {
6079
6264
  };
6080
6265
  async function termsAction() {
6081
6266
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6082
- const core = await p32.group(
6267
+ const core = await p33.group(
6083
6268
  {
6084
6269
  websiteUrl: sharedFields.websiteUrl,
6085
6270
  websiteName: sharedFields.websiteName,
@@ -6091,25 +6276,25 @@ async function termsAction() {
6091
6276
  },
6092
6277
  { onCancel }
6093
6278
  );
6094
- const accounts = await p32.select({
6279
+ const accounts = await p33.select({
6095
6280
  message: "Can users create accounts?",
6096
6281
  options: [
6097
6282
  { value: "yes", label: "Yes, users can create accounts" },
6098
6283
  { value: "no", label: "No" }
6099
6284
  ]
6100
6285
  });
6101
- if (p32.isCancel(accounts)) onCancel();
6102
- const userContent = await p32.select({
6286
+ if (p33.isCancel(accounts)) onCancel();
6287
+ const userContent = await p33.select({
6103
6288
  message: "Can users create and/or upload content (ie. text, images)?",
6104
6289
  options: [
6105
6290
  { value: "yes", label: "Yes, users can create and/or upload content" },
6106
6291
  { value: "no", label: "No" }
6107
6292
  ]
6108
6293
  });
6109
- if (p32.isCancel(userContent)) onCancel();
6294
+ if (p33.isCancel(userContent)) onCancel();
6110
6295
  let infringementEmail;
6111
6296
  if (userContent === "yes") {
6112
- const email3 = await p32.text({
6297
+ const email3 = await p33.text({
6113
6298
  message: "What's the email address where you will receive infringements notices?",
6114
6299
  placeholder: "dmca@website.com",
6115
6300
  validate: (value) => {
@@ -6118,10 +6303,10 @@ async function termsAction() {
6118
6303
  }
6119
6304
  }
6120
6305
  });
6121
- if (p32.isCancel(email3)) onCancel();
6306
+ if (p33.isCancel(email3)) onCancel();
6122
6307
  infringementEmail = email3;
6123
6308
  }
6124
- const canBuyGoods = await p32.select({
6309
+ const canBuyGoods = await p33.select({
6125
6310
  message: "Can users buy goods (products, items)?",
6126
6311
  options: [
6127
6312
  {
@@ -6131,28 +6316,28 @@ async function termsAction() {
6131
6316
  { value: "no", label: "No" }
6132
6317
  ]
6133
6318
  });
6134
- if (p32.isCancel(canBuyGoods)) onCancel();
6135
- const subscriptions2 = await p32.select({
6319
+ if (p33.isCancel(canBuyGoods)) onCancel();
6320
+ const subscriptions2 = await p33.select({
6136
6321
  message: "Do you offer subscription plans?",
6137
6322
  options: [
6138
6323
  { value: "yes", label: "Yes, we offer subscription plans" },
6139
6324
  { value: "no", label: "No" }
6140
6325
  ]
6141
6326
  });
6142
- if (p32.isCancel(subscriptions2)) onCancel();
6327
+ if (p33.isCancel(subscriptions2)) onCancel();
6143
6328
  let freeTrial;
6144
6329
  if (subscriptions2 === "yes") {
6145
- const ft = await p32.select({
6330
+ const ft = await p33.select({
6146
6331
  message: "Do you offer a free trial?",
6147
6332
  options: [
6148
6333
  { value: "yes", label: "Yes" },
6149
6334
  { value: "no", label: "No" }
6150
6335
  ]
6151
6336
  });
6152
- if (p32.isCancel(ft)) onCancel();
6337
+ if (p33.isCancel(ft)) onCancel();
6153
6338
  freeTrial = ft;
6154
6339
  }
6155
- const exclusiveContent = await p32.select({
6340
+ const exclusiveContent = await p33.select({
6156
6341
  message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
6157
6342
  options: [
6158
6343
  {
@@ -6162,24 +6347,24 @@ async function termsAction() {
6162
6347
  { value: "no", label: "No" }
6163
6348
  ]
6164
6349
  });
6165
- if (p32.isCancel(exclusiveContent)) onCancel();
6166
- const feedbackReuse = await p32.select({
6350
+ if (p33.isCancel(exclusiveContent)) onCancel();
6351
+ const feedbackReuse = await p33.select({
6167
6352
  message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
6168
6353
  options: [
6169
6354
  { value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
6170
6355
  { value: "no", label: "No" }
6171
6356
  ]
6172
6357
  });
6173
- if (p32.isCancel(feedbackReuse)) onCancel();
6174
- const promotions = await p32.select({
6358
+ if (p33.isCancel(feedbackReuse)) onCancel();
6359
+ const promotions = await p33.select({
6175
6360
  message: "Do you plan to offer promotions, contests, sweepstakes?",
6176
6361
  options: [
6177
6362
  { value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
6178
6363
  { value: "no", label: "No" }
6179
6364
  ]
6180
6365
  });
6181
- if (p32.isCancel(promotions)) onCancel();
6182
- const mobileAppRaw = await p32.multiselect({
6366
+ if (p33.isCancel(promotions)) onCancel();
6367
+ const mobileAppRaw = await p33.multiselect({
6183
6368
  message: "Is the Service distributed through any mobile app stores? Check all that apply",
6184
6369
  options: [
6185
6370
  { value: "apple", label: "Apple App Store" },
@@ -6187,7 +6372,7 @@ async function termsAction() {
6187
6372
  ],
6188
6373
  required: false
6189
6374
  });
6190
- if (p32.isCancel(mobileAppRaw)) onCancel();
6375
+ if (p33.isCancel(mobileAppRaw)) onCancel();
6191
6376
  const mobileApp = mobileAppRaw ?? [];
6192
6377
  const contact = await contactMethods("terms");
6193
6378
  const html = generateTermsHtml({
@@ -6230,13 +6415,13 @@ async function termsAction() {
6230
6415
  ]
6231
6416
  });
6232
6417
  }
6233
- var terms = new Command48("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6418
+ var terms = new Command49("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6234
6419
 
6235
6420
  // src/commands/legal/privacy.ts
6236
6421
  import fs27 from "node:fs";
6237
6422
  import path24 from "node:path";
6238
- import { Command as Command49 } from "commander";
6239
- import * as p33 from "@clack/prompts";
6423
+ import { Command as Command50 } from "commander";
6424
+ import * as p34 from "@clack/prompts";
6240
6425
  var mapLabels = {
6241
6426
  personalInfo: {
6242
6427
  email: "Email address",
@@ -6654,12 +6839,12 @@ var generatePrivacyHtml = (answers) => {
6654
6839
  return `<section data-role="content">${sections.join("")}</section>`;
6655
6840
  };
6656
6841
  async function promptWithCustom(message, options, customMessage) {
6657
- const selection = await p33.multiselect({ message, options });
6658
- if (p33.isCancel(selection)) onCancel();
6842
+ const selection = await p34.multiselect({ message, options });
6843
+ if (p34.isCancel(selection)) onCancel();
6659
6844
  const values = selection;
6660
6845
  if (values.includes("custom")) {
6661
- const custom = await p33.text({ message: customMessage });
6662
- if (p33.isCancel(custom)) onCancel();
6846
+ const custom = await p34.text({ message: customMessage });
6847
+ if (p34.isCancel(custom)) onCancel();
6663
6848
  const idx = values.indexOf("custom");
6664
6849
  if (idx !== -1) values.splice(idx, 1);
6665
6850
  if (custom) values.push(String(custom));
@@ -6668,7 +6853,7 @@ async function promptWithCustom(message, options, customMessage) {
6668
6853
  }
6669
6854
  async function privacyAction() {
6670
6855
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6671
- const core = await p33.group(
6856
+ const core = await p34.group(
6672
6857
  {
6673
6858
  websiteUrl: sharedFields.websiteUrl,
6674
6859
  websiteName: sharedFields.websiteName,
@@ -6680,7 +6865,7 @@ async function privacyAction() {
6680
6865
  },
6681
6866
  { onCancel }
6682
6867
  );
6683
- const personalInfo = await p33.multiselect({
6868
+ const personalInfo = await p34.multiselect({
6684
6869
  message: "What kind of personal information do you collect from users? Check all that apply",
6685
6870
  options: [
6686
6871
  { value: "email", label: "Email address" },
@@ -6695,16 +6880,16 @@ async function privacyAction() {
6695
6880
  ],
6696
6881
  required: false
6697
6882
  });
6698
- if (p33.isCancel(personalInfo)) onCancel();
6883
+ if (p34.isCancel(personalInfo)) onCancel();
6699
6884
  const contact = await contactMethods("privacy");
6700
- const tracking = await p33.select({
6885
+ const tracking = await p34.select({
6701
6886
  message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
6702
6887
  options: [
6703
6888
  { value: "yes", label: "Yes, we use Google Analytics or other related tools" },
6704
6889
  { value: "no", label: "No" }
6705
6890
  ]
6706
6891
  });
6707
- if (p33.isCancel(tracking)) onCancel();
6892
+ if (p34.isCancel(tracking)) onCancel();
6708
6893
  let trackingTools;
6709
6894
  if (tracking === "yes") {
6710
6895
  trackingTools = await promptWithCustom(
@@ -6723,7 +6908,7 @@ async function privacyAction() {
6723
6908
  "Enter your custom tracking/analytics tool name"
6724
6909
  );
6725
6910
  }
6726
- const sendEmails = await p33.select({
6911
+ const sendEmails = await p34.select({
6727
6912
  message: "Do you send emails to users?",
6728
6913
  options: [
6729
6914
  {
@@ -6733,7 +6918,7 @@ async function privacyAction() {
6733
6918
  { value: "no", label: "No" }
6734
6919
  ]
6735
6920
  });
6736
- if (p33.isCancel(sendEmails)) onCancel();
6921
+ if (p34.isCancel(sendEmails)) onCancel();
6737
6922
  let emailPlatforms;
6738
6923
  if (sendEmails === "yes") {
6739
6924
  emailPlatforms = await promptWithCustom(
@@ -6748,14 +6933,14 @@ async function privacyAction() {
6748
6933
  "Enter your custom email platform"
6749
6934
  );
6750
6935
  }
6751
- const showAds = await p33.select({
6936
+ const showAds = await p34.select({
6752
6937
  message: "Do you show ads?",
6753
6938
  options: [
6754
6939
  { value: "yes", label: "Yes, we show ads" },
6755
6940
  { value: "no", label: "No" }
6756
6941
  ]
6757
6942
  });
6758
- if (p33.isCancel(showAds)) onCancel();
6943
+ if (p34.isCancel(showAds)) onCancel();
6759
6944
  let adsPlatforms;
6760
6945
  if (showAds === "yes") {
6761
6946
  adsPlatforms = await promptWithCustom(
@@ -6778,7 +6963,7 @@ async function privacyAction() {
6778
6963
  "Enter your custom ads platform"
6779
6964
  );
6780
6965
  }
6781
- const canPay = await p33.select({
6966
+ const canPay = await p34.select({
6782
6967
  message: "Can users pay for products or services?",
6783
6968
  options: [
6784
6969
  { value: "yes", label: "Yes, users can pay for our products/services" },
@@ -6788,7 +6973,7 @@ async function privacyAction() {
6788
6973
  }
6789
6974
  ]
6790
6975
  });
6791
- if (p33.isCancel(canPay)) onCancel();
6976
+ if (p34.isCancel(canPay)) onCancel();
6792
6977
  let paymentProcessors;
6793
6978
  if (canPay === "yes") {
6794
6979
  paymentProcessors = await promptWithCustom(
@@ -6819,14 +7004,14 @@ async function privacyAction() {
6819
7004
  "Enter your custom payment processor/method"
6820
7005
  );
6821
7006
  }
6822
- const remarketing = await p33.select({
7007
+ const remarketing = await p34.select({
6823
7008
  message: "Do you use remarketing services for marketing & advertising purposes?",
6824
7009
  options: [
6825
7010
  { value: "yes", label: "Yes, we use remarketing services to advertise our business" },
6826
7011
  { value: "no", label: "No" }
6827
7012
  ]
6828
7013
  });
6829
- if (p33.isCancel(remarketing)) onCancel();
7014
+ if (p34.isCancel(remarketing)) onCancel();
6830
7015
  let remarketingPlatforms;
6831
7016
  if (remarketing === "yes") {
6832
7017
  remarketingPlatforms = await promptWithCustom(
@@ -6845,7 +7030,7 @@ async function privacyAction() {
6845
7030
  "Enter your custom remarketing platform"
6846
7031
  );
6847
7032
  }
6848
- const providersRaw = await p33.multiselect({
7033
+ const providersRaw = await p34.multiselect({
6849
7034
  message: "Select if you use any of the following providers",
6850
7035
  options: [
6851
7036
  { value: "recaptcha", label: "Invisible reCAPTCHA" },
@@ -6856,16 +7041,16 @@ async function privacyAction() {
6856
7041
  ],
6857
7042
  required: false
6858
7043
  });
6859
- if (p33.isCancel(providersRaw)) onCancel();
7044
+ if (p34.isCancel(providersRaw)) onCancel();
6860
7045
  const providers = providersRaw;
6861
7046
  if (providers.includes("custom")) {
6862
- const custom = await p33.text({ message: "Enter your custom provider" });
6863
- if (p33.isCancel(custom)) onCancel();
7047
+ const custom = await p34.text({ message: "Enter your custom provider" });
7048
+ if (p34.isCancel(custom)) onCancel();
6864
7049
  const idx = providers.indexOf("custom");
6865
7050
  if (idx !== -1) providers.splice(idx, 1);
6866
7051
  if (custom) providers.push(String(custom));
6867
7052
  }
6868
- const usStates = await p33.select({
7053
+ const usStates = await p34.select({
6869
7054
  message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
6870
7055
  options: [
6871
7056
  {
@@ -6876,55 +7061,55 @@ async function privacyAction() {
6876
7061
  ],
6877
7062
  initialValue: "yes"
6878
7063
  });
6879
- if (p33.isCancel(usStates)) onCancel();
6880
- const gdpr = await p33.select({
7064
+ if (p34.isCancel(usStates)) onCancel();
7065
+ const gdpr = await p34.select({
6881
7066
  message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
6882
7067
  options: [
6883
7068
  { value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
6884
7069
  { value: "no", label: "No" }
6885
7070
  ]
6886
7071
  });
6887
- if (p33.isCancel(gdpr)) onCancel();
7072
+ if (p34.isCancel(gdpr)) onCancel();
6888
7073
  let facebookFanPage = "no";
6889
7074
  const facebookDetails = { name: "", url: "" };
6890
7075
  if (gdpr === "yes") {
6891
- const fan = await p33.select({
7076
+ const fan = await p34.select({
6892
7077
  message: "Do you have a Facebook Fan Page?",
6893
7078
  options: [
6894
7079
  { value: "yes", label: "Yes, we have a Facebook Fan Page" },
6895
7080
  { value: "no", label: "No" }
6896
7081
  ]
6897
7082
  });
6898
- if (p33.isCancel(fan)) onCancel();
7083
+ if (p34.isCancel(fan)) onCancel();
6899
7084
  facebookFanPage = fan;
6900
7085
  if (facebookFanPage === "yes") {
6901
- const name = await p33.text({
7086
+ const name = await p34.text({
6902
7087
  message: "What is the name of the Facebook Fan Page?",
6903
7088
  placeholder: "My Facebook Page"
6904
7089
  });
6905
- if (p33.isCancel(name)) onCancel();
7090
+ if (p34.isCancel(name)) onCancel();
6906
7091
  facebookDetails.name = name;
6907
- const url = await p33.text({
7092
+ const url = await p34.text({
6908
7093
  message: "What is the URL of the Facebook Fan Page?",
6909
7094
  placeholder: "https://facebook.com/my-facebook-page"
6910
7095
  });
6911
- if (p33.isCancel(url)) onCancel();
7096
+ if (p34.isCancel(url)) onCancel();
6912
7097
  facebookDetails.url = url;
6913
7098
  }
6914
7099
  }
6915
- const kids = await p33.select({
7100
+ const kids = await p34.select({
6916
7101
  message: "Do you collect information from kids under the age of 13?",
6917
7102
  options: [
6918
7103
  { value: "yes", label: "Yes. We collect information from children under the age of 13" },
6919
7104
  { value: "no", label: "No" }
6920
7105
  ]
6921
7106
  });
6922
- if (p33.isCancel(kids)) onCancel();
6923
- const retention = await p33.text({
7107
+ if (p34.isCancel(kids)) onCancel();
7108
+ const retention = await p34.text({
6924
7109
  message: "How long do you retain personal information? (leave blank for default wording)",
6925
7110
  placeholder: "e.g. 12 months after account closure"
6926
7111
  });
6927
- if (p33.isCancel(retention)) onCancel();
7112
+ if (p34.isCancel(retention)) onCancel();
6928
7113
  const html = generatePrivacyHtml({
6929
7114
  core,
6930
7115
  personalInfo: personalInfo ?? [],
@@ -6979,16 +7164,16 @@ async function privacyAction() {
6979
7164
  ]
6980
7165
  });
6981
7166
  }
6982
- var privacy = new Command49("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7167
+ var privacy = new Command50("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
6983
7168
 
6984
7169
  // src/commands/legal.ts
6985
- var legal = new Command50("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7170
+ var legal = new Command51("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
6986
7171
 
6987
7172
  // src/commands/fixtures.ts
6988
- import { Command as Command56 } from "commander";
7173
+ import { Command as Command57 } from "commander";
6989
7174
 
6990
7175
  // src/commands/fixtures/load.ts
6991
- import { Command as Command51 } from "commander";
7176
+ import { Command as Command52 } from "commander";
6992
7177
 
6993
7178
  // src/lib/data.ts
6994
7179
  import fs28 from "node:fs";
@@ -7178,7 +7363,7 @@ async function hasLoadedFixtures(pb) {
7178
7363
  }
7179
7364
 
7180
7365
  // src/commands/fixtures/load.ts
7181
- var load = new Command51("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7366
+ var load = new Command52("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7182
7367
  () => runCommand(async () => {
7183
7368
  const { workspaceRootDir } = await getWorkspace();
7184
7369
  let loaded = [];
@@ -7204,8 +7389,8 @@ var load = new Command51("load").description("load fixtures into the database").
7204
7389
  );
7205
7390
 
7206
7391
  // src/commands/fixtures/clear.ts
7207
- import { Command as Command52 } from "commander";
7208
- var clear = new Command52("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7392
+ import { Command as Command53 } from "commander";
7393
+ var clear = new Command53("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7209
7394
  () => runCommand(async () => {
7210
7395
  const { workspaceRootDir } = await getWorkspace();
7211
7396
  let cleared = [];
@@ -7234,8 +7419,8 @@ var clear = new Command52("clear").description("clear loaded fixtures").configur
7234
7419
  );
7235
7420
 
7236
7421
  // src/commands/fixtures/reset.ts
7237
- import { Command as Command53 } from "commander";
7238
- var reset = new Command53("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7422
+ import { Command as Command54 } from "commander";
7423
+ var reset = new Command54("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7239
7424
  () => runCommand(async () => {
7240
7425
  const { workspaceRootDir } = await getWorkspace();
7241
7426
  let cleared = [];
@@ -7267,8 +7452,8 @@ var reset = new Command53("reset").description("clear and reload fixtures").conf
7267
7452
  // src/commands/fixtures/generate.ts
7268
7453
  import fs29 from "node:fs";
7269
7454
  import path26 from "node:path";
7270
- import { Command as Command54, InvalidArgumentError } from "commander";
7271
- import * as p34 from "@clack/prompts";
7455
+ import { Command as Command55, InvalidArgumentError } from "commander";
7456
+ import * as p35 from "@clack/prompts";
7272
7457
  import { annotate } from "annotate-json-schema";
7273
7458
  import { createGenerator } from "json-schema-faker";
7274
7459
  import { faker } from "@faker-js/faker";
@@ -7378,7 +7563,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
7378
7563
  }
7379
7564
  return { writtenFiles, warnings };
7380
7565
  }
7381
- 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(
7566
+ var generate2 = new Command55("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(
7382
7567
  (opts) => runCommand(async () => {
7383
7568
  const { workspaceRootDir } = await getWorkspace();
7384
7569
  const existing = getFixtureFiles(workspaceRootDir);
@@ -7407,7 +7592,7 @@ var generate2 = new Command54("generate").description("generate fixture data").o
7407
7592
  seed: opts.seed
7408
7593
  });
7409
7594
  });
7410
- for (const warning of result.warnings) p34.log.warn(warning);
7595
+ for (const warning of result.warnings) p35.log.warn(warning);
7411
7596
  if (result.writtenFiles.length === 0) {
7412
7597
  reportResult({
7413
7598
  summary: "No eligible collections found to generate fixtures for.",
@@ -7431,8 +7616,8 @@ var generate2 = new Command54("generate").description("generate fixture data").o
7431
7616
  );
7432
7617
 
7433
7618
  // src/commands/fixtures/regen.ts
7434
- import { Command as Command55, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7435
- import * as p35 from "@clack/prompts";
7619
+ import { Command as Command56, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7620
+ import * as p36 from "@clack/prompts";
7436
7621
  function parseCount2(value) {
7437
7622
  const n = parseInt(value, 10);
7438
7623
  if (!Number.isFinite(n) || n <= 0 || n > 999) {
@@ -7447,7 +7632,7 @@ function parseSeed2(value) {
7447
7632
  }
7448
7633
  return n;
7449
7634
  }
7450
- 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(
7635
+ var regen = new Command56("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(
7451
7636
  (opts) => runCommand(async () => {
7452
7637
  const { workspaceRootDir } = await getWorkspace();
7453
7638
  let cleared = [];
@@ -7461,7 +7646,7 @@ var regen = new Command55("regen").description("clear the database, regenerate f
7461
7646
  });
7462
7647
  loaded = await loadFixtures(pb, workspaceRootDir);
7463
7648
  });
7464
- for (const warning of result.warnings) p35.log.warn(warning);
7649
+ for (const warning of result.warnings) p36.log.warn(warning);
7465
7650
  reportResult({
7466
7651
  summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
7467
7652
  filesCreated: result.writtenFiles,
@@ -7476,14 +7661,14 @@ var regen = new Command55("regen").description("clear the database, regenerate f
7476
7661
  );
7477
7662
 
7478
7663
  // src/commands/fixtures.ts
7479
- var fixtures = new Command56("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7664
+ var fixtures = new Command57("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7480
7665
 
7481
7666
  // src/commands/seeds.ts
7482
- import { Command as Command60 } from "commander";
7667
+ import { Command as Command61 } from "commander";
7483
7668
 
7484
7669
  // src/commands/seeds/load.ts
7485
- import { Command as Command57 } from "commander";
7486
- 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(
7670
+ import { Command as Command58 } from "commander";
7671
+ var load2 = new Command58("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
7487
7672
  (opts) => runCommand(async () => {
7488
7673
  const { workspaceRootDir } = await getWorkspace();
7489
7674
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7522,7 +7707,7 @@ var load2 = new Command57("load").description("load seeds into the database").op
7522
7707
  // src/commands/seeds/save.ts
7523
7708
  import fs30 from "node:fs";
7524
7709
  import path27 from "node:path";
7525
- import { Command as Command58 } from "commander";
7710
+ import { Command as Command59 } from "commander";
7526
7711
  var padZeros2 = (num, length) => num.toString().padStart(length, "0");
7527
7712
  function filterSystemFields(record, systemFieldNames) {
7528
7713
  const out = {};
@@ -7533,7 +7718,7 @@ function filterSystemFields(record, systemFieldNames) {
7533
7718
  }
7534
7719
  return out;
7535
7720
  }
7536
- var save = new Command58("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7721
+ var save = new Command59("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7537
7722
  (opts) => runCommand(async () => {
7538
7723
  const { workspaceRootDir } = await getWorkspace();
7539
7724
  const seedsPath = dataDir(workspaceRootDir, "seeds");
@@ -7605,8 +7790,8 @@ var save = new Command58("save").description("save the current data as seeds").o
7605
7790
  );
7606
7791
 
7607
7792
  // src/commands/seeds/clear.ts
7608
- import { Command as Command59 } from "commander";
7609
- var clear2 = new Command59("clear").description("clear seeded records").configureHelp(helpConfig).action(
7793
+ import { Command as Command60 } from "commander";
7794
+ var clear2 = new Command60("clear").description("clear seeded records").configureHelp(helpConfig).action(
7610
7795
  () => runCommand(async () => {
7611
7796
  const { workspaceRootDir } = await getWorkspace();
7612
7797
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7637,23 +7822,23 @@ var clear2 = new Command59("clear").description("clear seeded records").configur
7637
7822
  );
7638
7823
 
7639
7824
  // src/commands/seeds.ts
7640
- var seeds = new Command60("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7825
+ var seeds = new Command61("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7641
7826
 
7642
7827
  // src/commands/signup.ts
7643
- import { Command as Command62 } from "commander";
7644
- import * as p37 from "@clack/prompts";
7828
+ import { Command as Command63 } from "commander";
7829
+ import * as p38 from "@clack/prompts";
7645
7830
  import makeFetchCookie2 from "fetch-cookie";
7646
7831
 
7647
7832
  // src/commands/login.ts
7648
7833
  import os4 from "node:os";
7649
- import { Command as Command61 } from "commander";
7650
- import * as p36 from "@clack/prompts";
7834
+ import { Command as Command62 } from "commander";
7835
+ import * as p37 from "@clack/prompts";
7651
7836
  import makeFetchCookie from "fetch-cookie";
7652
- var login = new Command61("login").description("login to velastack.dev").configureHelp(helpConfig).action(
7837
+ var login = new Command62("login").description("login to velastack.dev").configureHelp(helpConfig).action(
7653
7838
  () => runCommand(async () => {
7654
- const { email: email3, password: password11 } = await p36.group({
7655
- email: () => p36.text({ message: "Email" }),
7656
- password: () => p36.password({ message: "Password" })
7839
+ const { email: email3, password: password11 } = await p37.group({
7840
+ email: () => p37.text({ message: "Email" }),
7841
+ password: () => p37.password({ message: "Password" })
7657
7842
  });
7658
7843
  const fetchCookie = makeFetchCookie(fetch);
7659
7844
  const loginRes = await fetchCookie(`${API_URL}/login`, {
@@ -7675,7 +7860,7 @@ var login = new Command61("login").description("login to velastack.dev").configu
7675
7860
  }
7676
7861
  const apiKey = await issueApiKey(fetchCookie);
7677
7862
  writeConfig({ apiKey });
7678
- p36.log.success("Logged in to velastack.dev");
7863
+ p37.log.success("Logged in to velastack.dev");
7679
7864
  }, "Failed to login.")
7680
7865
  );
7681
7866
  async function issueApiKey(fetchCookie) {
@@ -7716,12 +7901,12 @@ function extractApiKey(cookie) {
7716
7901
  }
7717
7902
 
7718
7903
  // src/commands/signup.ts
7719
- var signup = new Command62("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7904
+ var signup = new Command63("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7720
7905
  () => runCommand(async () => {
7721
- const { email: email3, password: password11, passwordConfirm } = await p37.group({
7722
- email: () => p37.text({ message: "Email" }),
7723
- password: () => p37.password({ message: "Password" }),
7724
- passwordConfirm: () => p37.password({ message: "Confirm password" })
7906
+ const { email: email3, password: password11, passwordConfirm } = await p38.group({
7907
+ email: () => p38.text({ message: "Email" }),
7908
+ password: () => p38.password({ message: "Password" }),
7909
+ passwordConfirm: () => p38.password({ message: "Confirm password" })
7725
7910
  });
7726
7911
  if (password11 !== passwordConfirm) {
7727
7912
  throw new Error("Passwords do not match.");
@@ -7745,33 +7930,33 @@ var signup = new Command62("signup").description("signup to velastack.dev").conf
7745
7930
  }
7746
7931
  const apiKey = await issueApiKey(fetchCookie);
7747
7932
  writeConfig({ apiKey });
7748
- p37.log.success("Signed up to velastack.dev");
7749
- p37.log.info("Check your email for a confirmation link.");
7933
+ p38.log.success("Signed up to velastack.dev");
7934
+ p38.log.info("Check your email for a confirmation link.");
7750
7935
  }, "Failed to signup.")
7751
7936
  );
7752
7937
 
7753
7938
  // src/commands/logout.ts
7754
- import { Command as Command63 } from "commander";
7755
- import * as p38 from "@clack/prompts";
7756
- var logout = new Command63("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7939
+ import { Command as Command64 } from "commander";
7940
+ import * as p39 from "@clack/prompts";
7941
+ var logout = new Command64("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7757
7942
  () => runCommand(() => {
7758
7943
  if (!readConfig()) {
7759
- p38.log.info("Not logged in");
7944
+ p39.log.info("Not logged in");
7760
7945
  return;
7761
7946
  }
7762
7947
  clearConfig();
7763
- p38.log.success("Logged out of velastack.dev");
7948
+ p39.log.success("Logged out of velastack.dev");
7764
7949
  })
7765
7950
  );
7766
7951
 
7767
7952
  // src/commands/whoami.ts
7768
- import { Command as Command64 } from "commander";
7769
- import * as p39 from "@clack/prompts";
7770
- var whoami = new Command64("whoami").description("show the current user").configureHelp(helpConfig).action(
7953
+ import { Command as Command65 } from "commander";
7954
+ import * as p40 from "@clack/prompts";
7955
+ var whoami = new Command65("whoami").description("show the current user").configureHelp(helpConfig).action(
7771
7956
  () => runCommand(async () => {
7772
7957
  const apiKey = readConfig()?.apiKey;
7773
7958
  if (!apiKey) {
7774
- p39.log.info("Not logged in. Run `vela login` to login.");
7959
+ p40.log.info("Not logged in. Run `vela login` to login.");
7775
7960
  return;
7776
7961
  }
7777
7962
  const res = await fetch(`${API_URL}/api/collections/users/records`, {
@@ -7779,22 +7964,22 @@ var whoami = new Command64("whoami").description("show the current user").config
7779
7964
  });
7780
7965
  const data = await res.json();
7781
7966
  if (!data.items.length) throw new Error("No user found. Run `vela login` to login.");
7782
- p39.log.success(`Logged in as ${data.items[0].email}`);
7967
+ p40.log.success(`Logged in as ${data.items[0].email}`);
7783
7968
  })
7784
7969
  );
7785
7970
 
7786
7971
  // src/commands/migrate.ts
7787
- import { Command as Command70 } from "commander";
7972
+ import { Command as Command71 } from "commander";
7788
7973
 
7789
7974
  // src/commands/migrate/up.ts
7790
- import { Command as Command65 } from "commander";
7975
+ import { Command as Command66 } from "commander";
7791
7976
 
7792
7977
  // src/lib/migrate.ts
7793
7978
  import path28 from "node:path";
7794
- import process20 from "node:process";
7979
+ import process21 from "node:process";
7795
7980
  import { x as x2 } from "tinyexec";
7796
7981
  async function runPocketbaseMigrate(args) {
7797
- const cwd = process20.cwd();
7982
+ const cwd = process21.cwd();
7798
7983
  const { getBinaryPath } = await import("pocketbase-server");
7799
7984
  const binaryPath = getBinaryPath();
7800
7985
  await x2(
@@ -7826,10 +8011,10 @@ async function runMigrateUp() {
7826
8011
  ]
7827
8012
  });
7828
8013
  }
7829
- var up = new Command65("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
8014
+ var up = new Command66("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
7830
8015
 
7831
8016
  // src/commands/migrate/down.ts
7832
- import { Command as Command66, InvalidArgumentError as InvalidArgumentError3 } from "commander";
8017
+ import { Command as Command67, InvalidArgumentError as InvalidArgumentError3 } from "commander";
7833
8018
  function parseSteps(value) {
7834
8019
  const n = parseInt(value, 10);
7835
8020
  if (!Number.isFinite(n) || n <= 0) {
@@ -7837,7 +8022,7 @@ function parseSteps(value) {
7837
8022
  }
7838
8023
  return n;
7839
8024
  }
7840
- 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(
8025
+ var down = new Command67("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
7841
8026
  (n) => runCommand(async () => {
7842
8027
  await runPocketbaseMigrate(["down", String(n)]);
7843
8028
  reportResult({
@@ -7853,11 +8038,11 @@ var down = new Command66("down").alias("rollback").description("revert the last
7853
8038
  // src/commands/migrate/create.ts
7854
8039
  import fs31 from "node:fs";
7855
8040
  import path29 from "node:path";
7856
- import process21 from "node:process";
7857
- import { Command as Command67 } from "commander";
7858
- var create2 = new Command67("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
8041
+ import process22 from "node:process";
8042
+ import { Command as Command68 } from "commander";
8043
+ var create2 = new Command68("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
7859
8044
  (name) => runCommand(async () => {
7860
- const cwd = process21.cwd();
8045
+ const cwd = process22.cwd();
7861
8046
  const before = listMigrationFiles(cwd);
7862
8047
  await runPocketbaseMigrate(["create", name]);
7863
8048
  const after = listMigrationFiles(cwd);
@@ -7881,11 +8066,11 @@ function listMigrationFiles(cwd) {
7881
8066
  // src/commands/migrate/collections.ts
7882
8067
  import fs32 from "node:fs";
7883
8068
  import path30 from "node:path";
7884
- import process22 from "node:process";
7885
- import { Command as Command68 } from "commander";
7886
- var collections = new Command68("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
8069
+ import process23 from "node:process";
8070
+ import { Command as Command69 } from "commander";
8071
+ var collections = new Command69("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
7887
8072
  () => runCommand(async () => {
7888
- const cwd = process22.cwd();
8073
+ const cwd = process23.cwd();
7889
8074
  const before = listMigrationFiles2(cwd);
7890
8075
  await runPocketbaseMigrate(["collections"]);
7891
8076
  const after = listMigrationFiles2(cwd);
@@ -7914,8 +8099,8 @@ function listMigrationFiles2(cwd) {
7914
8099
  }
7915
8100
 
7916
8101
  // src/commands/migrate/history-sync.ts
7917
- import { Command as Command69 } from "commander";
7918
- var historySync = new Command69("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
8102
+ import { Command as Command70 } from "commander";
8103
+ var historySync = new Command70("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
7919
8104
  () => runCommand(async () => {
7920
8105
  await runPocketbaseMigrate(["history-sync"]);
7921
8106
  reportResult({
@@ -7926,20 +8111,20 @@ var historySync = new Command69("history-sync").description("drop _migrations ro
7926
8111
  );
7927
8112
 
7928
8113
  // src/commands/migrate.ts
7929
- 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);
8114
+ var migrate = new Command71("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
7930
8115
 
7931
8116
  // src/commands/dev.ts
7932
8117
  import fs33 from "node:fs";
7933
8118
  import path32 from "node:path";
7934
- import process24 from "node:process";
8119
+ import process25 from "node:process";
7935
8120
  import { performance } from "node:perf_hooks";
7936
- import { Command as Command71, InvalidArgumentError as InvalidArgumentError4 } from "commander";
8121
+ import { Command as Command72, InvalidArgumentError as InvalidArgumentError4 } from "commander";
7937
8122
  import pc15 from "picocolors";
7938
8123
  import PocketBase4 from "pocketbase";
7939
8124
 
7940
8125
  // src/lib/vite.ts
7941
8126
  import path31 from "node:path";
7942
- import process23 from "node:process";
8127
+ import process24 from "node:process";
7943
8128
  import { createRequire as createRequire2 } from "node:module";
7944
8129
  import { pathToFileURL as pathToFileURL2 } from "node:url";
7945
8130
  import pc14 from "picocolors";
@@ -7963,13 +8148,13 @@ function resolveProjectVite(cwd) {
7963
8148
  return null;
7964
8149
  }
7965
8150
  }
7966
- async function loadVite(cwd = process23.cwd()) {
8151
+ async function loadVite(cwd = process24.cwd()) {
7967
8152
  const entry = resolveProjectVite(cwd);
7968
8153
  const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
7969
8154
  const error = viteVersionError(vite.version);
7970
8155
  if (error) {
7971
8156
  console.error(`${pc14.redBright("\u2717")} ${error}`);
7972
- process23.exit(1);
8157
+ process24.exit(1);
7973
8158
  }
7974
8159
  return vite;
7975
8160
  }
@@ -7982,16 +8167,16 @@ function parsePort(value) {
7982
8167
  }
7983
8168
  return port;
7984
8169
  }
7985
- 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) => {
7986
- const cwd = process24.cwd();
7987
- process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
8170
+ var dev = new Command72("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) => {
8171
+ const cwd = process25.cwd();
8172
+ process25.env.VELA_DATA_DIR ??= localDataDir(cwd);
7988
8173
  const startTime = performance.now();
7989
8174
  const { createServer, version } = await loadVite(cwd);
7990
8175
  const viteMetadataDir = path32.join(cwd, "node_modules", ".vite");
7991
8176
  const viteMetadataFile = path32.join(viteMetadataDir, "_pocketbase_metadata.json");
7992
8177
  let pbProc;
7993
8178
  const backend3 = hasBackend(cwd);
7994
- const needsStart = backend3 && !process24.env.POCKETBASE_URL;
8179
+ const needsStart = backend3 && !process25.env.POCKETBASE_URL;
7995
8180
  const cleanup = () => {
7996
8181
  if (pbProc?.pid) pbProc.kill();
7997
8182
  if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
@@ -8006,15 +8191,15 @@ var dev = new Command71("dev").description("start the development server").optio
8006
8191
  stdio: "pipe"
8007
8192
  });
8008
8193
  pbProc = started.proc;
8009
- process24.env.POCKETBASE_URL = started.url;
8010
- pbProc.stdout?.pipe(process24.stdout);
8011
- pbProc.stderr?.pipe(process24.stderr);
8194
+ process25.env.POCKETBASE_URL = started.url;
8195
+ pbProc.stdout?.pipe(process25.stdout);
8196
+ pbProc.stderr?.pipe(process25.stderr);
8012
8197
  pbProc.on("error", (err) => console.error("PocketBase error:", err));
8013
8198
  pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
8014
- process24.on("exit", cleanup);
8015
- process24.on("SIGINT", () => {
8199
+ process25.on("exit", cleanup);
8200
+ process25.on("SIGINT", () => {
8016
8201
  cleanup();
8017
- process24.exit(0);
8202
+ process25.exit(0);
8018
8203
  });
8019
8204
  }
8020
8205
  const serverOptions = {};
@@ -8036,21 +8221,21 @@ var dev = new Command71("dev").description("start the development server").optio
8036
8221
  await fs33.promises.writeFile(
8037
8222
  viteMetadataFile,
8038
8223
  JSON.stringify({
8039
- pocketbaseUrl: process24.env.POCKETBASE_URL,
8224
+ pocketbaseUrl: process25.env.POCKETBASE_URL,
8040
8225
  vitePort,
8041
8226
  viteHost
8042
8227
  })
8043
8228
  );
8044
- const pb = new PocketBase4(process24.env.POCKETBASE_URL);
8229
+ const pb = new PocketBase4(process25.env.POCKETBASE_URL);
8045
8230
  await pb.collection("_superusers").authWithPassword(
8046
- process24.env.POCKETBASE_SUPERUSER_EMAIL,
8047
- process24.env.POCKETBASE_SUPERUSER_PASSWORD
8231
+ process25.env.POCKETBASE_SUPERUSER_EMAIL,
8232
+ process25.env.POCKETBASE_SUPERUSER_PASSWORD
8048
8233
  );
8049
8234
  await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
8050
8235
  await startWatchingTypes(cwd, pb);
8051
8236
  });
8052
8237
  await server.listen();
8053
- const hasExistingLogs = process24.stdout.bytesWritten > 0 || process24.stderr.bytesWritten > 0;
8238
+ const hasExistingLogs = process25.stdout.bytesWritten > 0 || process25.stderr.bytesWritten > 0;
8054
8239
  const startupDurationString = pc15.dim(
8055
8240
  `ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
8056
8241
  );
@@ -8090,9 +8275,9 @@ async function startWatchingTypes(cwd, pb) {
8090
8275
  // src/commands/build.ts
8091
8276
  import fs34 from "node:fs";
8092
8277
  import path33 from "node:path";
8093
- import process26 from "node:process";
8094
- import { Command as Command72 } from "commander";
8095
- import * as p40 from "@clack/prompts";
8278
+ import process27 from "node:process";
8279
+ import { Command as Command73 } from "commander";
8280
+ import * as p41 from "@clack/prompts";
8096
8281
  import pc16 from "picocolors";
8097
8282
  import { x as x3 } from "tinyexec";
8098
8283
  import { detect as detect5 } from "package-manager-detector";
@@ -8105,10 +8290,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
8105
8290
  }
8106
8291
 
8107
8292
  // src/lib/origin.ts
8108
- import process25 from "node:process";
8293
+ import process26 from "node:process";
8109
8294
  function resolveOrigin(workspaceRootDir, envTag, config = {}) {
8110
8295
  return normalizeOrigin(
8111
- process25.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8296
+ process26.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8112
8297
  );
8113
8298
  }
8114
8299
  function normalizeOrigin(value) {
@@ -8128,13 +8313,13 @@ function splitHosts(value) {
8128
8313
 
8129
8314
  // src/commands/build.ts
8130
8315
  var PRERENDERED_DIR = path33.join(".svelte-kit", "output", "prerendered");
8131
- 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) => {
8132
- const cwd = process26.cwd();
8316
+ var build = new Command73("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
8317
+ const cwd = process27.cwd();
8133
8318
  applyBuildEnv(cwd);
8134
8319
  const origin = await originForBuild(cwd, options.target);
8135
- if (origin) process26.env.VELA_ORIGIN = origin;
8320
+ if (origin) process27.env.VELA_ORIGIN = origin;
8136
8321
  let pbProc;
8137
- const needsStart = hasBackend(cwd) && !process26.env.POCKETBASE_URL;
8322
+ const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
8138
8323
  const cleanup = () => {
8139
8324
  if (pbProc?.pid) pbProc.kill();
8140
8325
  };
@@ -8148,11 +8333,11 @@ var build = new Command72("build").description("build the app").configureHelp(he
8148
8333
  dev: true
8149
8334
  });
8150
8335
  pbProc = started.proc;
8151
- process26.env.POCKETBASE_URL = started.url;
8152
- process26.on("exit", cleanup);
8153
- process26.on("SIGINT", () => {
8336
+ process27.env.POCKETBASE_URL = started.url;
8337
+ process27.on("exit", cleanup);
8338
+ process27.on("SIGINT", () => {
8154
8339
  cleanup();
8155
- process26.exit(0);
8340
+ process27.exit(0);
8156
8341
  });
8157
8342
  }
8158
8343
  try {
@@ -8185,7 +8370,7 @@ async function originForBuild(cwd, target) {
8185
8370
  function warnIfPrerendered(cwd) {
8186
8371
  const dir = path33.join(cwd, PRERENDERED_DIR);
8187
8372
  if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
8188
- p40.log.warn(
8373
+ p41.log.warn(
8189
8374
  `Prerendered pages were built with no domain configured, so their canonical
8190
8375
  links point at SvelteKit's placeholder host rather than at this site.
8191
8376
 
@@ -8195,16 +8380,16 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
8195
8380
 
8196
8381
  // src/commands/preview.ts
8197
8382
  import path34 from "node:path";
8198
- import process27 from "node:process";
8199
- import { Command as Command73 } from "commander";
8383
+ import process28 from "node:process";
8384
+ import { Command as Command74 } from "commander";
8200
8385
  import { x as x4 } from "tinyexec";
8201
8386
  import { detect as detect6 } from "package-manager-detector";
8202
8387
  import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
8203
- var preview = new Command73("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
8204
- const cwd = process27.cwd();
8205
- process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
8388
+ var preview = new Command74("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
8389
+ const cwd = process28.cwd();
8390
+ process28.env.VELA_DATA_DIR ??= localDataDir(cwd);
8206
8391
  let pbProc;
8207
- const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
8392
+ const needsStart = hasBackend(cwd) && !process28.env.POCKETBASE_URL;
8208
8393
  const cleanup = () => {
8209
8394
  if (pbProc?.pid) pbProc.kill();
8210
8395
  };
@@ -8217,11 +8402,11 @@ var preview = new Command73("preview").description("preview the built app").conf
8217
8402
  dev: true
8218
8403
  });
8219
8404
  pbProc = started.proc;
8220
- process27.env.POCKETBASE_URL = started.url;
8221
- process27.on("exit", cleanup);
8222
- process27.on("SIGINT", () => {
8405
+ process28.env.POCKETBASE_URL = started.url;
8406
+ process28.on("exit", cleanup);
8407
+ process28.on("SIGINT", () => {
8223
8408
  cleanup();
8224
- process27.exit(0);
8409
+ process28.exit(0);
8225
8410
  });
8226
8411
  }
8227
8412
  try {
@@ -8240,8 +8425,8 @@ var preview = new Command73("preview").description("preview the built app").conf
8240
8425
 
8241
8426
  // src/commands/sync.ts
8242
8427
  import path35 from "node:path";
8243
- import { Command as Command74 } from "commander";
8244
- var sync = new Command74("sync").description("sync types from the database").configureHelp(helpConfig).action(
8428
+ import { Command as Command75 } from "commander";
8429
+ var sync = new Command75("sync").description("sync types from the database").configureHelp(helpConfig).action(
8245
8430
  () => runCommand(async () => {
8246
8431
  const { workspaceRootDir } = await getWorkspace();
8247
8432
  const typesDir = path35.join(workspaceRootDir, ".svelte-kit", "types");
@@ -8254,8 +8439,8 @@ var sync = new Command74("sync").description("sync types from the database").con
8254
8439
  );
8255
8440
 
8256
8441
  // src/commands/provision.ts
8257
- import { Command as Command75 } from "commander";
8258
- import * as p41 from "@clack/prompts";
8442
+ import { Command as Command76 } from "commander";
8443
+ import * as p42 from "@clack/prompts";
8259
8444
  import pc17 from "picocolors";
8260
8445
  import * as v7 from "valibot";
8261
8446
  var OptionsSchema2 = v7.object({
@@ -8264,24 +8449,24 @@ var OptionsSchema2 = v7.object({
8264
8449
  nodeMajor: v7.optional(v7.string())
8265
8450
  });
8266
8451
  var provision = addSshOptions(
8267
- 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)
8452
+ new Command76("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
8268
8453
  ).option("--pb-version <version>", "PocketBase version to install").option("--node-major <version>", "Node.js major version to install", "22").action(
8269
8454
  (target, raw) => runCommand(async () => {
8270
8455
  const options = parseOptions(OptionsSchema2, raw);
8271
8456
  const pbVersion = options.pbVersion ?? pocketbaseVersion();
8272
- p41.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8273
- p41.log.info(`Target ${pc17.cyan(target)}`);
8457
+ p42.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8458
+ p42.log.info(`Target ${pc17.cyan(target)}`);
8274
8459
  await withSsh(target, sshOptionsFrom(options), async (session) => {
8275
8460
  await session.detectElevation();
8276
8461
  const existing = await readServerInfo(session);
8277
8462
  if (existing) {
8278
- p41.log.info(
8463
+ p42.log.info(
8279
8464
  `Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
8280
8465
  );
8281
8466
  }
8282
- p41.log.step("Uploading server scripts");
8467
+ p42.log.step("Uploading server scripts");
8283
8468
  await syncServerScripts(session);
8284
- p41.log.step("Running provision");
8469
+ p42.log.step("Running provision");
8285
8470
  const result = await runServerScript(session, "provision.sh", {
8286
8471
  args: [
8287
8472
  "--pb-version",
@@ -8293,7 +8478,7 @@ var provision = addSshOptions(
8293
8478
  ],
8294
8479
  stream: true
8295
8480
  });
8296
- p41.log.success(
8481
+ p42.log.success(
8297
8482
  `${target} is ready.
8298
8483
 
8299
8484
  Node ${result?.node ?? "installed"}
@@ -8301,29 +8486,29 @@ var provision = addSshOptions(
8301
8486
  PocketBase ${result?.pocketbase ?? pbVersion}`
8302
8487
  );
8303
8488
  });
8304
- p41.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8489
+ p42.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8305
8490
  }, "Failed to provision.")
8306
8491
  );
8307
8492
 
8308
8493
  // src/commands/deploy.ts
8309
- import path37 from "node:path";
8310
- import fs36 from "node:fs";
8311
- import { Command as Command76, Option as Option2 } from "commander";
8312
- import * as p42 from "@clack/prompts";
8494
+ import path38 from "node:path";
8495
+ import fs37 from "node:fs";
8496
+ import { Command as Command77, Option as Option2 } from "commander";
8497
+ import * as p43 from "@clack/prompts";
8313
8498
  import pc18 from "picocolors";
8314
8499
  import * as v8 from "valibot";
8315
8500
 
8316
8501
  // src/lib/pocketbase-settings.ts
8317
8502
  import fs35 from "node:fs";
8318
8503
  import path36 from "node:path";
8319
- import process28 from "node:process";
8504
+ import process29 from "node:process";
8320
8505
  import PocketBase5 from "pocketbase";
8321
8506
  var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
8322
8507
  async function readLocalMeta(cwd) {
8323
8508
  const dataDir2 = path36.join(cwd, DATA_DIR);
8324
8509
  if (!fs35.existsSync(dataDir2)) return null;
8325
- const email3 = process28.env.POCKETBASE_SUPERUSER_EMAIL;
8326
- const password11 = process28.env.POCKETBASE_SUPERUSER_PASSWORD;
8510
+ const email3 = process29.env.POCKETBASE_SUPERUSER_EMAIL;
8511
+ const password11 = process29.env.POCKETBASE_SUPERUSER_PASSWORD;
8327
8512
  if (!email3 || !password11) return null;
8328
8513
  let proc;
8329
8514
  try {
@@ -8371,6 +8556,272 @@ async function seedRemoteMeta(session, instance, local, appURL) {
8371
8556
  return Object.keys(patch);
8372
8557
  }
8373
8558
 
8559
+ // src/lib/adapter.ts
8560
+ import fs36 from "node:fs";
8561
+ import path37 from "node:path";
8562
+ import {
8563
+ Project as Project2,
8564
+ QuoteKind as QuoteKind2,
8565
+ SyntaxKind as SyntaxKind2
8566
+ } from "ts-morph";
8567
+ import { detect as detect7 } from "package-manager-detector";
8568
+ var ADAPTER_NODE = "@sveltejs/adapter-node";
8569
+ var ADAPTER_AUTO = "@sveltejs/adapter-auto";
8570
+ var ADAPTER_STATIC = "@sveltejs/adapter-static";
8571
+ var ADAPTER_NODE_RANGE = "^5.5.7";
8572
+ var ADAPTER_SNIPPET = `import adapter from '${ADAPTER_NODE}';
8573
+
8574
+ // ...
8575
+ adapter: adapter()`;
8576
+ var AdapterError = class extends Error {
8577
+ constructor(message, snippet = ADAPTER_SNIPPET) {
8578
+ super(message);
8579
+ this.snippet = snippet;
8580
+ this.name = "AdapterError";
8581
+ }
8582
+ snippet;
8583
+ };
8584
+ function newProject() {
8585
+ return new Project2({
8586
+ compilerOptions: { allowJs: true },
8587
+ manipulationSettings: { quoteKind: QuoteKind2.Single }
8588
+ });
8589
+ }
8590
+ function getDefaultExportObject(sourceFile) {
8591
+ const exported = sourceFile.getExportAssignment((ea) => !ea.isExportEquals())?.getExpression();
8592
+ if (exported?.getKind() === SyntaxKind2.ObjectLiteralExpression) {
8593
+ return exported;
8594
+ }
8595
+ if (exported?.getKind() === SyntaxKind2.Identifier) {
8596
+ const init = sourceFile.getVariableDeclaration(exported.getText())?.getInitializer();
8597
+ if (init?.getKind() === SyntaxKind2.ObjectLiteralExpression) {
8598
+ return init;
8599
+ }
8600
+ }
8601
+ return null;
8602
+ }
8603
+ function resolveKitTarget(root) {
8604
+ const vite = inspectViteSveltekit(root);
8605
+ if (vite?.inlineArg) {
8606
+ return {
8607
+ sourceFile: vite.sourceFile,
8608
+ filePath: vite.filePath,
8609
+ container: "vite-inline",
8610
+ kit: vite.inlineArg,
8611
+ created: false,
8612
+ originalText: vite.sourceFile.getFullText()
8613
+ };
8614
+ }
8615
+ const sveltePath = probeFirstExisting(root, SVELTE_CONFIG_CANDIDATES);
8616
+ if (sveltePath) {
8617
+ const name = path37.basename(sveltePath);
8618
+ if (sveltePath.endsWith(".cjs")) {
8619
+ throw new AdapterError(`${name} is CommonJS, which vela does not edit.`);
8620
+ }
8621
+ const sourceFile = newProject().addSourceFileAtPath(sveltePath);
8622
+ const config = getDefaultExportObject(sourceFile);
8623
+ const kit = config && getOrCreateObjectLiteralProperty(config, "kit", "{}");
8624
+ if (!kit) {
8625
+ throw new AdapterError(`${name} has a shape vela does not understand.`);
8626
+ }
8627
+ return {
8628
+ sourceFile,
8629
+ filePath: sveltePath,
8630
+ container: "svelte-config",
8631
+ kit,
8632
+ created: false,
8633
+ originalText: sourceFile.getFullText()
8634
+ };
8635
+ }
8636
+ if (vite?.sveltekitCall) {
8637
+ const name = path37.basename(vite.filePath);
8638
+ if (vite.nonObjectArg) {
8639
+ throw new AdapterError(`${name} passes sveltekit() something other than an object literal.`);
8640
+ }
8641
+ const originalText = vite.sourceFile.getFullText();
8642
+ const kit = createSveltekitArg(vite);
8643
+ if (!kit)
8644
+ throw new AdapterError(`${name} has a sveltekit() call vela cannot add an argument to.`);
8645
+ return {
8646
+ sourceFile: vite.sourceFile,
8647
+ filePath: vite.filePath,
8648
+ container: "vite-inline",
8649
+ kit,
8650
+ created: true,
8651
+ originalText
8652
+ };
8653
+ }
8654
+ throw new AdapterError(
8655
+ `No svelte.config or vite.config with a sveltekit() plugin found in ${root}.`
8656
+ );
8657
+ }
8658
+ function classify(specifier) {
8659
+ if (specifier === ADAPTER_NODE) return "node";
8660
+ if (specifier === ADAPTER_AUTO) return "auto";
8661
+ if (specifier === ADAPTER_STATIC) return "static";
8662
+ return "other";
8663
+ }
8664
+ function importOf(sourceFile, identifier) {
8665
+ return sourceFile.getImportDeclarations().find((decl) => decl.getDefaultImport()?.getText() === identifier);
8666
+ }
8667
+ function inspectAdapter(target) {
8668
+ const base2 = { file: target.filePath, container: target.container };
8669
+ const prop = target.kit.getProperty("adapter");
8670
+ if (!prop) return { info: { ...base2, kind: "none" } };
8671
+ if (prop.getKind() !== SyntaxKind2.PropertyAssignment) {
8672
+ return { info: { ...base2, kind: "other" } };
8673
+ }
8674
+ const init = prop.asKindOrThrow(SyntaxKind2.PropertyAssignment).getInitializer();
8675
+ if (!init || init.getKind() !== SyntaxKind2.CallExpression) {
8676
+ return { info: { ...base2, kind: "other" } };
8677
+ }
8678
+ const callee = init.asKindOrThrow(SyntaxKind2.CallExpression).getExpression();
8679
+ if (callee.getKind() !== SyntaxKind2.Identifier) {
8680
+ return { info: { ...base2, kind: "other" } };
8681
+ }
8682
+ const importDecl = importOf(target.sourceFile, callee.getText());
8683
+ if (!importDecl) return { info: { ...base2, kind: "other" } };
8684
+ const specifier = importDecl.getModuleSpecifierValue();
8685
+ return { info: { ...base2, kind: classify(specifier), specifier }, importDecl };
8686
+ }
8687
+ async function ensureNodeAdapter(root, { install = true } = {}) {
8688
+ const target = resolveKitTarget(root);
8689
+ const { info, importDecl } = inspectAdapter(target);
8690
+ const name = path37.basename(target.filePath);
8691
+ const outcome = {
8692
+ previous: info.kind,
8693
+ removedDeps: [],
8694
+ packageJsonChanged: false
8695
+ };
8696
+ switch (info.kind) {
8697
+ case "node":
8698
+ break;
8699
+ case "static":
8700
+ throw new AdapterError(
8701
+ `This project builds a static site with ${ADAPTER_STATIC} (${name}).
8702
+
8703
+ vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}. Switch
8704
+ the adapter to deploy it here, or host the static output elsewhere.`
8705
+ );
8706
+ case "other":
8707
+ throw new AdapterError(
8708
+ `This project's adapter${info.specifier ? ` (${info.specifier})` : ""} in ${name} is not one
8709
+ vela will change for you.
8710
+
8711
+ vela deploy runs the app as a Node server, which needs ${ADAPTER_NODE}:`
8712
+ );
8713
+ case "auto":
8714
+ switchImport(target, importDecl);
8715
+ outcome.configFile = name;
8716
+ break;
8717
+ case "none":
8718
+ addAdapter(target);
8719
+ outcome.configFile = name;
8720
+ break;
8721
+ }
8722
+ if (outcome.configFile) saveTarget(target);
8723
+ const pkgPath = path37.join(root, "package.json");
8724
+ if (fs36.existsSync(pkgPath)) {
8725
+ const pkg = readPackageJson(pkgPath);
8726
+ const { changed, removed } = adoptNodeAdapter(pkg);
8727
+ if (changed) {
8728
+ writePackageJson(pkgPath, pkg);
8729
+ outcome.packageJsonChanged = true;
8730
+ outcome.removedDeps = removed;
8731
+ }
8732
+ }
8733
+ if (outcome.packageJsonChanged && install) {
8734
+ outcome.installedWith = await installAdapterDependencies(root);
8735
+ }
8736
+ return outcome;
8737
+ }
8738
+ async function installAdapterDependencies(root) {
8739
+ const agent = await packageManager(root);
8740
+ const ok = await installDependencies(agent, root, { exitOnFailure: false });
8741
+ if (!ok) {
8742
+ throw new AdapterError(
8743
+ `Installing ${ADAPTER_NODE} with ${agent} failed.
8744
+
8745
+ The config and package.json are already updated: run \`${agent} install\`, then deploy again.`,
8746
+ ""
8747
+ );
8748
+ }
8749
+ return agent;
8750
+ }
8751
+ function switchImport(target, importDecl) {
8752
+ importDecl.setModuleSpecifier(ADAPTER_NODE);
8753
+ const prop = target.kit.getPropertyOrThrow("adapter").asKindOrThrow(SyntaxKind2.PropertyAssignment);
8754
+ const call = prop.getInitializerIfKindOrThrow(SyntaxKind2.CallExpression);
8755
+ for (let i = call.getArguments().length - 1; i >= 0; i--) call.removeArgument(i);
8756
+ dropAdapterAutoComments(target);
8757
+ }
8758
+ var ADAPTER_AUTO_COMMENT = /adapter-auto|svelte\.dev\/docs\/kit\/adapters|switch out the adapter/;
8759
+ function dropAdapterAutoComments(target) {
8760
+ const prop = target.kit.getPropertyOrThrow("adapter");
8761
+ const ranges = prop.getLeadingCommentRanges();
8762
+ if (ranges.length === 0 || !ranges.every((r) => ADAPTER_AUTO_COMMENT.test(r.getText()))) return;
8763
+ const fullStart = prop.getFullStart();
8764
+ const start = prop.getStart();
8765
+ const trivia = target.sourceFile.getFullText().slice(fullStart, start);
8766
+ const lastNewline = trivia.lastIndexOf("\n");
8767
+ if (lastNewline === -1) return;
8768
+ const indent = trivia.slice(lastNewline + 1);
8769
+ target.sourceFile.replaceText([fullStart, start], `
8770
+ ${indent}`);
8771
+ }
8772
+ function addAdapter(target) {
8773
+ const taken = importOf(target.sourceFile, "adapter") ?? target.sourceFile.getVariableDeclaration("adapter");
8774
+ if (taken) {
8775
+ throw new AdapterError(
8776
+ `${path37.basename(target.filePath)} already binds the name \`adapter\` to something that is not the SvelteKit adapter.`
8777
+ );
8778
+ }
8779
+ target.sourceFile.addImportDeclaration({
8780
+ defaultImport: "adapter",
8781
+ moduleSpecifier: ADAPTER_NODE
8782
+ });
8783
+ target.kit.addPropertyAssignment({ name: "adapter", initializer: "adapter()" });
8784
+ }
8785
+ function saveTarget(target) {
8786
+ if (target.created) target.sourceFile.formatText();
8787
+ if (target.sourceFile.getFullText() === target.originalText) return;
8788
+ target.sourceFile.saveSync();
8789
+ }
8790
+ function adoptNodeAdapter(pkg) {
8791
+ const removed = [];
8792
+ let changed = false;
8793
+ for (const kind of ["dependencies", "devDependencies"]) {
8794
+ const deps = pkg[kind];
8795
+ if (deps && ADAPTER_AUTO in deps) {
8796
+ delete deps[ADAPTER_AUTO];
8797
+ removed.push(ADAPTER_AUTO);
8798
+ changed = true;
8799
+ }
8800
+ }
8801
+ if (!pkg.dependencies?.[ADAPTER_NODE] && !pkg.devDependencies?.[ADAPTER_NODE]) {
8802
+ pkg.devDependencies = sortKeys({ ...pkg.devDependencies, [ADAPTER_NODE]: ADAPTER_NODE_RANGE });
8803
+ changed = true;
8804
+ }
8805
+ return { changed, removed: [...new Set(removed)] };
8806
+ }
8807
+ function lockfileFor(agent) {
8808
+ switch (agent) {
8809
+ case "pnpm":
8810
+ return "pnpm-lock.yaml";
8811
+ case "yarn":
8812
+ return "yarn.lock";
8813
+ case "bun":
8814
+ return "bun.lock";
8815
+ case "deno":
8816
+ return "deno.lock";
8817
+ default:
8818
+ return "package-lock.json";
8819
+ }
8820
+ }
8821
+ async function packageManager(root) {
8822
+ return (await detect7({ cwd: root }))?.name ?? getUserAgent() ?? "npm";
8823
+ }
8824
+
8374
8825
  // src/commands/deploy.ts
8375
8826
  var OptionsSchema3 = v8.object({
8376
8827
  ...SSH_OPTION_SCHEMA,
@@ -8386,7 +8837,7 @@ var OptionsSchema3 = v8.object({
8386
8837
  });
8387
8838
  var deploy = addLockWaitOption(
8388
8839
  addTargetOptions(
8389
- new Command76("deploy").description("deploy the app").configureHelp(helpConfig),
8840
+ new Command77("deploy").description("deploy the app").configureHelp(helpConfig),
8390
8841
  "production"
8391
8842
  )
8392
8843
  ).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(
@@ -8402,13 +8853,17 @@ var deploy = addLockWaitOption(
8402
8853
  (raw) => runCommand(async () => {
8403
8854
  const options = parseOptions(OptionsSchema3, raw);
8404
8855
  const backend3 = hasBackend();
8405
- p42.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
8856
+ p43.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
8857
+ if (options.build !== false) {
8858
+ const { workspaceRootDir } = await getWorkspace();
8859
+ await prepareAdapter(workspaceRootDir);
8860
+ }
8406
8861
  await withTarget(
8407
8862
  raw,
8408
8863
  {
8409
8864
  remote: async (ctx) => {
8410
8865
  const { session, instance, workspaceRootDir, config } = ctx;
8411
- p42.log.info(
8866
+ p43.log.info(
8412
8867
  `${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
8413
8868
  );
8414
8869
  const [existing] = await readInstanceStates(session, instance);
@@ -8416,7 +8871,12 @@ var deploy = addLockWaitOption(
8416
8871
  const isPreview2 = ctx.target.kind === "preview";
8417
8872
  const configured = options.domain ?? (isPreview2 ? existing?.domain : ctx.binding.domain ?? config.deploy?.domain ?? existing?.domain) ?? "";
8418
8873
  const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
8419
- const remoteDb = askedForRemoteDb ?? Boolean(existing?.pbPort);
8874
+ const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
8875
+ if (existing && instanceHasBackend(existing) !== backend3) {
8876
+ p43.log.info(
8877
+ backend3 ? `${pc18.cyan(ctx.targetName)} was deployed without a backend before. This deploy adds PocketBase.` : `${pc18.cyan(ctx.targetName)} was deployed with a backend before. This deploy removes PocketBase; its database stays on the server.`
8878
+ );
8879
+ }
8420
8880
  const sha = await gitSha(workspaceRootDir);
8421
8881
  const reporter = createDeployReporter(workspaceRootDir);
8422
8882
  const server = await reporter.identifyServer(session);
@@ -8456,7 +8916,7 @@ with DNS of your own pointing at ${ctx.server}.`
8456
8916
  tunnel = await openDatabaseTunnel(session, instance, existing);
8457
8917
  } catch (err) {
8458
8918
  if (askedForRemoteDb) throw err;
8459
- p42.log.warn(
8919
+ p43.log.warn(
8460
8920
  `Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
8461
8921
  ${pc18.dim(String(err))}`
8462
8922
  );
@@ -8464,13 +8924,13 @@ ${pc18.dim(String(err))}`
8464
8924
  }
8465
8925
  if (tunnel) {
8466
8926
  buildEnv = { ...buildEnv, ...tunnel.env };
8467
- p42.log.info(
8927
+ p43.log.info(
8468
8928
  `Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
8469
8929
  );
8470
8930
  } else if (backend3) {
8471
8931
  await ensureSuperuser(workspaceRootDir);
8472
8932
  }
8473
- p42.log.step("Building");
8933
+ p43.log.step("Building");
8474
8934
  try {
8475
8935
  await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
8476
8936
  } finally {
@@ -8478,9 +8938,9 @@ ${pc18.dim(String(err))}`
8478
8938
  }
8479
8939
  }
8480
8940
  const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
8481
- p42.log.step(`Uploading release ${pc18.dim(release)}`);
8941
+ p43.log.step(`Uploading release ${pc18.dim(release)}`);
8482
8942
  await uploadRelease(session, instance, release, entries);
8483
- p42.log.step("Activating");
8943
+ p43.log.step("Activating");
8484
8944
  result = await runServerScript(session, "apply.sh", {
8485
8945
  args: [
8486
8946
  instance,
@@ -8531,7 +8991,7 @@ ${pc18.dim(String(err))}`
8531
8991
  url: primaryHost ? url : void 0
8532
8992
  });
8533
8993
  const redirects = started?.environment.redirects ?? [];
8534
- p42.log.success(
8994
+ p43.log.success(
8535
8995
  `Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
8536
8996
 
8537
8997
  URL ${url}
@@ -8539,7 +8999,7 @@ ${pc18.dim(String(err))}`
8539
8999
  ` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
8540
9000
  );
8541
9001
  if (managed && managed !== existing?.managed) {
8542
- p42.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9002
+ p43.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
8543
9003
  }
8544
9004
  if (result?.superuserCreated) {
8545
9005
  await copyLocalBranding(
@@ -8548,7 +9008,7 @@ ${pc18.dim(String(err))}`
8548
9008
  workspaceRootDir,
8549
9009
  primaryHost ? result?.url ?? "" : ""
8550
9010
  );
8551
- p42.log.info(
9011
+ p43.log.info(
8552
9012
  `Created the PocketBase superuser this app authenticates as.
8553
9013
 
8554
9014
  Its credentials are stored in the environment on the server. To use
@@ -8559,7 +9019,7 @@ and deploy again.`
8559
9019
  await reportAppURLDrift(session, instance, primaryHost);
8560
9020
  }
8561
9021
  if (!primaryHost) {
8562
- p42.log.warn(
9022
+ p43.log.warn(
8563
9023
  `No domain configured, so nothing is proxied to this app yet.
8564
9024
  Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
8565
9025
  or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
@@ -8569,15 +9029,47 @@ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
8569
9029
  },
8570
9030
  { project: options.project, askDomain: true, label: "deploy" }
8571
9031
  );
8572
- p42.outro(`${pc18.cyan("vela status")} to see what is running`);
9032
+ p43.outro(`${pc18.cyan("vela status")} to see what is running`);
8573
9033
  }, "Failed to deploy.")
8574
9034
  );
9035
+ async function prepareAdapter(workspaceRootDir) {
9036
+ const rethrow = (err) => {
9037
+ if (err instanceof AdapterError) {
9038
+ throw new Error(err.snippet ? `${err.message}
9039
+
9040
+ ${pc18.cyan(err.snippet)}` : err.message);
9041
+ }
9042
+ throw err;
9043
+ };
9044
+ const outcome = await ensureNodeAdapter(workspaceRootDir, { install: false }).catch(rethrow);
9045
+ if (!outcome.configFile && !outcome.packageJsonChanged) return;
9046
+ const changed = [
9047
+ outcome.configFile,
9048
+ outcome.packageJsonChanged ? "package.json" : void 0
9049
+ ].filter((f) => Boolean(f));
9050
+ const why = outcome.previous === "auto" ? `${ADAPTER_AUTO} builds nothing for a server of your own` : outcome.previous === "none" ? "No adapter was configured" : `${ADAPTER_NODE} was configured but not in package.json`;
9051
+ p43.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
9052
+ p43.log.info(
9053
+ `${why}, and vela deploy runs the app as a Node server.
9054
+
9055
+ Changed ${changed.join(", ")}` + (outcome.removedDeps.length ? `
9056
+ Removed ${outcome.removedDeps.join(", ")}` : "")
9057
+ );
9058
+ if (outcome.packageJsonChanged) {
9059
+ try {
9060
+ changed.push(lockfileFor(await installAdapterDependencies(workspaceRootDir)));
9061
+ } catch (err) {
9062
+ rethrow(err);
9063
+ }
9064
+ }
9065
+ p43.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9066
+ }
8575
9067
  async function reportAppURLDrift(session, instance, domain) {
8576
9068
  const expected = normalizeOrigin(domain);
8577
9069
  if (!expected) return;
8578
9070
  const current = await readRemoteAppURL(session, instance);
8579
9071
  if (!current || normalizeOrigin(current) === expected) return;
8580
- p42.log.warn(
9072
+ p43.log.warn(
8581
9073
  `This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
8582
9074
 
8583
9075
  Emails and anything else PocketBase links to will use the former. Update it in
@@ -8592,25 +9084,25 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
8592
9084
  if (copied.length === 0) return;
8593
9085
  const outcome = await restartInstance(session, instance);
8594
9086
  if (outcome.deployed && !outcome.restarted) {
8595
- p42.log.warn(
9087
+ p43.log.warn(
8596
9088
  `Copied ${copied.join(", ")}, but the app did not restart to pick them up.
8597
9089
  ${pc18.dim(outcome.error ?? "")}`
8598
9090
  );
8599
9091
  return;
8600
9092
  }
8601
- p42.log.success(`Copied ${copied.join(", ")} from this project's database`);
9093
+ p43.log.success(`Copied ${copied.join(", ")} from this project's database`);
8602
9094
  } catch (err) {
8603
- p42.log.warn(
9095
+ p43.log.warn(
8604
9096
  `Could not copy this project's PocketBase settings across.
8605
9097
  Set them in the admin panel instead. ${pc18.dim(String(err))}`
8606
9098
  );
8607
9099
  }
8608
9100
  }
8609
9101
  async function openDatabaseTunnel(session, instance, state) {
8610
- const pbPort = state?.pbPort;
9102
+ const pbPort = instanceHasBackend(state) ? state?.pbPort : void 0;
8611
9103
  if (!pbPort) {
8612
9104
  throw new Error(
8613
- `--remote-db needs an existing deployment to build against, and ${instance} has not been deployed yet.
9105
+ `--remote-db needs a deployed database to build against, and ${instance} ${state ? "has no backend" : "has not been deployed yet"}.
8614
9106
 
8615
9107
  Deploy once without it, then turn it on.`
8616
9108
  );
@@ -8684,7 +9176,7 @@ async function uploadRelease(session, instance, release, entries) {
8684
9176
  }
8685
9177
  function isDirectory(target) {
8686
9178
  try {
8687
- return fs36.statSync(target).isDirectory();
9179
+ return fs37.statSync(target).isDirectory();
8688
9180
  } catch {
8689
9181
  return false;
8690
9182
  }
@@ -8692,8 +9184,8 @@ function isDirectory(target) {
8692
9184
  async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
8693
9185
  const remote = await readRemoteEnv(session, instance);
8694
9186
  if (Object.keys(remote).length > 0) return;
8695
- if (!fs36.existsSync(path37.join(workspaceRootDir, ".env"))) return;
8696
- p42.log.warn(
9187
+ if (!fs37.existsSync(path38.join(workspaceRootDir, ".env"))) return;
9188
+ p43.log.warn(
8697
9189
  `This app has no production environment variables yet.
8698
9190
 
8699
9191
  Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
@@ -8704,23 +9196,23 @@ async function serverTimeOrLocal(session) {
8704
9196
  try {
8705
9197
  return await serverTime(session);
8706
9198
  } catch {
8707
- p42.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9199
+ p43.log.warn("Could not read the clock on the server; stamping this release from this machine.");
8708
9200
  return /* @__PURE__ */ new Date();
8709
9201
  }
8710
9202
  }
8711
9203
 
8712
9204
  // src/commands/link.ts
8713
- import path38 from "node:path";
8714
- import process29 from "node:process";
8715
- import { Command as Command77 } from "commander";
8716
- import * as p43 from "@clack/prompts";
9205
+ import path39 from "node:path";
9206
+ import process30 from "node:process";
9207
+ import { Command as Command78 } from "commander";
9208
+ import * as p44 from "@clack/prompts";
8717
9209
  var CREATE_NEW = "__new__";
8718
- var link = new Command77("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
9210
+ var link = new Command78("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
8719
9211
  async function linkProject() {
8720
9212
  const { workspaceRootDir } = await getWorkspace();
8721
9213
  const existing = readProjectConfig(workspaceRootDir);
8722
9214
  if (existing) {
8723
- p43.log.success(`Linked to ${existing.projectName}.`);
9215
+ p44.log.success(`Linked to ${existing.projectName}.`);
8724
9216
  return;
8725
9217
  }
8726
9218
  const apiKey = requireApiKey();
@@ -8747,10 +9239,10 @@ async function linkProject() {
8747
9239
  projectName = created.name;
8748
9240
  }
8749
9241
  writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
8750
- p43.log.success(`Linked to ${projectName}.`);
9242
+ p44.log.success(`Linked to ${projectName}.`);
8751
9243
  }
8752
9244
  async function pickExistingProject(projects) {
8753
- const choice = await p43.select({
9245
+ const choice = await p44.select({
8754
9246
  message: "Select a project",
8755
9247
  options: [
8756
9248
  ...projects.map((pr) => ({
@@ -8760,61 +9252,61 @@ async function pickExistingProject(projects) {
8760
9252
  { value: CREATE_NEW, label: "Create a new project" }
8761
9253
  ]
8762
9254
  });
8763
- if (p43.isCancel(choice)) {
8764
- p43.cancel("Operation cancelled.");
8765
- process29.exit(0);
9255
+ if (p44.isCancel(choice)) {
9256
+ p44.cancel("Operation cancelled.");
9257
+ process30.exit(0);
8766
9258
  }
8767
9259
  return choice;
8768
9260
  }
8769
9261
  async function pickTeam(teams3) {
8770
9262
  if (teams3.length === 1) return teams3[0];
8771
- const choice = await p43.select({
9263
+ const choice = await p44.select({
8772
9264
  message: "Select a team",
8773
9265
  options: teams3.map((team) => ({
8774
9266
  value: team.id,
8775
9267
  label: team.is_personal ? `${team.name} (personal)` : team.name
8776
9268
  }))
8777
9269
  });
8778
- if (p43.isCancel(choice)) {
8779
- p43.cancel("Operation cancelled.");
8780
- process29.exit(0);
9270
+ if (p44.isCancel(choice)) {
9271
+ p44.cancel("Operation cancelled.");
9272
+ process30.exit(0);
8781
9273
  }
8782
9274
  return teams3.find((team) => team.id === choice);
8783
9275
  }
8784
9276
  async function promptProjectName(workspaceRootDir) {
8785
9277
  const defaultValue = defaultProjectName2(workspaceRootDir);
8786
- const value = await p43.text({
9278
+ const value = await p44.text({
8787
9279
  message: "Project name",
8788
9280
  defaultValue,
8789
9281
  initialValue: defaultValue,
8790
9282
  placeholder: defaultValue,
8791
9283
  validate: (v10) => !v10?.trim() ? "Required" : void 0
8792
9284
  });
8793
- if (p43.isCancel(value)) {
8794
- p43.cancel("Operation cancelled.");
8795
- process29.exit(0);
9285
+ if (p44.isCancel(value)) {
9286
+ p44.cancel("Operation cancelled.");
9287
+ process30.exit(0);
8796
9288
  }
8797
9289
  return value.trim();
8798
9290
  }
8799
9291
  function defaultProjectName2(workspaceRootDir) {
8800
9292
  try {
8801
- const pkg = readPackageJson(path38.join(workspaceRootDir, "package.json"));
9293
+ const pkg = readPackageJson(path39.join(workspaceRootDir, "package.json"));
8802
9294
  const name = pkg.name;
8803
9295
  if (typeof name === "string" && name.trim()) return name.trim();
8804
9296
  } catch {
8805
9297
  }
8806
- return path38.basename(workspaceRootDir);
9298
+ return path39.basename(workspaceRootDir);
8807
9299
  }
8808
9300
 
8809
9301
  // src/commands/env.ts
8810
- import { Command as Command82 } from "commander";
9302
+ import { Command as Command83 } from "commander";
8811
9303
 
8812
9304
  // src/commands/env/list.ts
8813
- import { Command as Command78 } from "commander";
8814
- import * as p44 from "@clack/prompts";
9305
+ import { Command as Command79 } from "commander";
9306
+ import * as p45 from "@clack/prompts";
8815
9307
  import pc19 from "picocolors";
8816
9308
  var envList = addTargetOptions(
8817
- new Command78("list").description("list environment variable names").configureHelp(helpConfig),
9309
+ new Command79("list").description("list environment variable names").configureHelp(helpConfig),
8818
9310
  "local"
8819
9311
  ).action(
8820
9312
  (raw) => runCommand(
@@ -8836,10 +9328,10 @@ var envList = addTargetOptions(
8836
9328
  );
8837
9329
  function report(keys, where) {
8838
9330
  if (keys.length === 0) {
8839
- p44.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9331
+ p45.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
8840
9332
  return;
8841
9333
  }
8842
- p44.log.info(
9334
+ p45.log.info(
8843
9335
  `Environment ${pc19.dim(`(${where})`)}
8844
9336
 
8845
9337
  ` + keys.sort().map((key) => ` ${key}`).join("\n")
@@ -8847,12 +9339,12 @@ function report(keys, where) {
8847
9339
  }
8848
9340
 
8849
9341
  // src/commands/env/set.ts
8850
- import process30 from "node:process";
8851
- import { Command as Command79 } from "commander";
8852
- import * as p45 from "@clack/prompts";
9342
+ import process31 from "node:process";
9343
+ import { Command as Command80 } from "commander";
9344
+ import * as p46 from "@clack/prompts";
8853
9345
  import pc20 from "picocolors";
8854
9346
  var envSet = addTargetOptions(
8855
- new Command79("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
9347
+ new Command80("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
8856
9348
  "local"
8857
9349
  ).action(
8858
9350
  (key, value, raw) => runCommand(
@@ -8862,14 +9354,14 @@ var envSet = addTargetOptions(
8862
9354
  local: async (ctx) => {
8863
9355
  const resolved = await resolveValue(key, value);
8864
9356
  setLocalEnv(ctx.envFile, key, resolved);
8865
- p45.log.success(`${key} updated ${pc20.dim("(local)")}`);
9357
+ p46.log.success(`${key} updated ${pc20.dim("(local)")}`);
8866
9358
  await applyLocalEnvChange(ctx, [key]);
8867
9359
  },
8868
9360
  remote: async (ctx) => {
8869
9361
  const resolved = await resolveValue(key, value);
8870
9362
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
8871
9363
  await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
8872
- p45.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9364
+ p46.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
8873
9365
  await applyEnvRestart(ctx, [key]);
8874
9366
  }
8875
9367
  },
@@ -8883,23 +9375,23 @@ async function resolveValue(key, value) {
8883
9375
  return value ?? await promptValue(key);
8884
9376
  }
8885
9377
  async function promptValue(key) {
8886
- const value = await p45.password({
9378
+ const value = await p46.password({
8887
9379
  message: `Value for ${pc20.cyan(key)}`,
8888
9380
  validate: (input) => !input?.length ? "Required" : void 0
8889
9381
  });
8890
- if (p45.isCancel(value)) {
8891
- p45.cancel("Operation cancelled.");
8892
- process30.exit(0);
9382
+ if (p46.isCancel(value)) {
9383
+ p46.cancel("Operation cancelled.");
9384
+ process31.exit(0);
8893
9385
  }
8894
9386
  return value;
8895
9387
  }
8896
9388
 
8897
9389
  // src/commands/env/unset.ts
8898
- import { Command as Command80 } from "commander";
8899
- import * as p46 from "@clack/prompts";
9390
+ import { Command as Command81 } from "commander";
9391
+ import * as p47 from "@clack/prompts";
8900
9392
  import pc21 from "picocolors";
8901
9393
  var envUnset = addTargetOptions(
8902
- new Command80("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
9394
+ new Command81("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
8903
9395
  "local"
8904
9396
  ).action(
8905
9397
  (key, raw) => runCommand(
@@ -8908,22 +9400,22 @@ var envUnset = addTargetOptions(
8908
9400
  {
8909
9401
  local: async (ctx) => {
8910
9402
  if (!(key in readLocalEnv(ctx.envFile))) {
8911
- p46.log.info(`${key} is not set \u2014 nothing to remove.`);
9403
+ p47.log.info(`${key} is not set \u2014 nothing to remove.`);
8912
9404
  return;
8913
9405
  }
8914
9406
  unsetLocalEnv(ctx.envFile, key);
8915
- p46.log.success(`${key} removed ${pc21.dim("(local)")}`);
9407
+ p47.log.success(`${key} removed ${pc21.dim("(local)")}`);
8916
9408
  await applyLocalEnvChange(ctx, [key]);
8917
9409
  },
8918
9410
  remote: async (ctx) => {
8919
9411
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
8920
9412
  if (!(key in env2)) {
8921
- p46.log.info(`${key} is not set \u2014 nothing to remove.`);
9413
+ p47.log.info(`${key} is not set \u2014 nothing to remove.`);
8922
9414
  return;
8923
9415
  }
8924
9416
  delete env2[key];
8925
9417
  await writeRemoteEnv(ctx.session, ctx.instance, env2);
8926
- p46.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9418
+ p47.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
8927
9419
  await applyEnvRestart(ctx, [key]);
8928
9420
  }
8929
9421
  },
@@ -8934,14 +9426,14 @@ var envUnset = addTargetOptions(
8934
9426
  );
8935
9427
 
8936
9428
  // src/commands/env/import.ts
8937
- import fs37 from "node:fs";
8938
- import path39 from "node:path";
8939
- import process31 from "node:process";
8940
- import { Command as Command81 } from "commander";
8941
- import * as p47 from "@clack/prompts";
9429
+ import fs38 from "node:fs";
9430
+ import path40 from "node:path";
9431
+ import process32 from "node:process";
9432
+ import { Command as Command82 } from "commander";
9433
+ import * as p48 from "@clack/prompts";
8942
9434
  import pc22 from "picocolors";
8943
9435
  var envImport = addTargetOptions(
8944
- new Command81("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
9436
+ new Command82("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
8945
9437
  "local"
8946
9438
  ).action(
8947
9439
  (file, raw) => runCommand(
@@ -8956,22 +9448,22 @@ var envImport = addTargetOptions(
8956
9448
  const incoming = read(source, file);
8957
9449
  const keys = Object.keys(incoming);
8958
9450
  if (keys.length === 0) return;
8959
- p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9451
+ p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
8960
9452
  editLocalEnv(
8961
9453
  ctx.envFile,
8962
9454
  (content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
8963
9455
  );
8964
- p47.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9456
+ p48.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
8965
9457
  await applyLocalEnvChange(ctx, keys);
8966
9458
  },
8967
9459
  remote: async (ctx) => {
8968
9460
  const incoming = read(resolve(file), file);
8969
9461
  const keys = Object.keys(incoming);
8970
9462
  if (keys.length === 0) return;
8971
- p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9463
+ p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
8972
9464
  const existing = await readRemoteEnv(ctx.session, ctx.instance);
8973
9465
  await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
8974
- p47.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9466
+ p48.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
8975
9467
  await applyEnvRestart(ctx, keys);
8976
9468
  }
8977
9469
  },
@@ -8981,24 +9473,24 @@ var envImport = addTargetOptions(
8981
9473
  )
8982
9474
  );
8983
9475
  function resolve(file) {
8984
- return path39.resolve(process31.cwd(), file);
9476
+ return path40.resolve(process32.cwd(), file);
8985
9477
  }
8986
9478
  function read(resolved, shown) {
8987
- if (!fs37.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
9479
+ if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
8988
9480
  const incoming = readLocalEnvFile(resolved);
8989
- if (Object.keys(incoming).length === 0) p47.log.info(`${shown} has no variables to import.`);
9481
+ if (Object.keys(incoming).length === 0) p48.log.info(`${shown} has no variables to import.`);
8990
9482
  return incoming;
8991
9483
  }
8992
9484
 
8993
9485
  // src/commands/env.ts
8994
- var env = new Command82("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
9486
+ var env = new Command83("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
8995
9487
 
8996
9488
  // src/commands/status.ts
8997
- import { Command as Command83 } from "commander";
8998
- import * as p48 from "@clack/prompts";
9489
+ import { Command as Command84 } from "commander";
9490
+ import * as p49 from "@clack/prompts";
8999
9491
  import pc23 from "picocolors";
9000
9492
  var status = addTargetOptions(
9001
- new Command83("status").description("show what is deployed").configureHelp(helpConfig),
9493
+ new Command84("status").description("show what is deployed").configureHelp(helpConfig),
9002
9494
  "production"
9003
9495
  ).option("--all", "show every app on the server, not just this project").option("--json", "print raw JSON").action(
9004
9496
  (raw) => runCommand(async () => {
@@ -9029,11 +9521,11 @@ function report2(states, json) {
9029
9521
  return;
9030
9522
  }
9031
9523
  if (states.length === 0) {
9032
- p48.log.info("Nothing is deployed here yet.");
9524
+ p49.log.info("Nothing is deployed here yet.");
9033
9525
  return;
9034
9526
  }
9035
9527
  for (const state of states) {
9036
- p48.log.info(describe2(state));
9528
+ p49.log.info(describe2(state));
9037
9529
  }
9038
9530
  }
9039
9531
  function describe2(state) {
@@ -9057,12 +9549,12 @@ function describe2(state) {
9057
9549
  }
9058
9550
 
9059
9551
  // src/commands/rollback.ts
9060
- import { Command as Command84 } from "commander";
9061
- import * as p49 from "@clack/prompts";
9552
+ import { Command as Command85 } from "commander";
9553
+ import * as p50 from "@clack/prompts";
9062
9554
  import pc24 from "picocolors";
9063
9555
  var rollback = addLockWaitOption(
9064
9556
  addTargetOptions(
9065
- new Command84("rollback").description("put the previous release back").configureHelp(helpConfig),
9557
+ new Command85("rollback").description("put the previous release back").configureHelp(helpConfig),
9066
9558
  "production"
9067
9559
  )
9068
9560
  ).option("--to <release>", "roll back to a specific release instead of the previous one").action(
@@ -9072,7 +9564,7 @@ var rollback = addLockWaitOption(
9072
9564
  raw,
9073
9565
  {
9074
9566
  remote: async (ctx) => {
9075
- p49.log.step(
9567
+ p50.log.step(
9076
9568
  `Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
9077
9569
  );
9078
9570
  const result = await runServerScript(
@@ -9087,7 +9579,7 @@ var rollback = addLockWaitOption(
9087
9579
  stream: true
9088
9580
  }
9089
9581
  );
9090
- p49.log.success(
9582
+ p50.log.success(
9091
9583
  `Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
9092
9584
  );
9093
9585
  }
@@ -9101,9 +9593,9 @@ var rollback = addLockWaitOption(
9101
9593
  );
9102
9594
 
9103
9595
  // src/commands/logs.ts
9104
- import { Command as Command85 } from "commander";
9596
+ import { Command as Command86 } from "commander";
9105
9597
  var logs = addTargetOptions(
9106
- new Command85("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
9598
+ new Command86("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
9107
9599
  "production"
9108
9600
  ).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(
9109
9601
  (raw) => runCommand(async () => {
@@ -9137,16 +9629,16 @@ var logs = addTargetOptions(
9137
9629
  );
9138
9630
 
9139
9631
  // src/commands/admin.ts
9140
- import { Command as Command87 } from "commander";
9632
+ import { Command as Command88 } from "commander";
9141
9633
 
9142
9634
  // src/commands/admin/create.ts
9143
- import process32 from "node:process";
9144
- import { Command as Command86 } from "commander";
9145
- import * as p50 from "@clack/prompts";
9635
+ import process33 from "node:process";
9636
+ import { Command as Command87 } from "commander";
9637
+ import * as p51 from "@clack/prompts";
9146
9638
  import pc25 from "picocolors";
9147
9639
  var MIN_PASSWORD = 10;
9148
9640
  var adminCreate = addTargetOptions(
9149
- 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),
9641
+ new Command87("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
9150
9642
  "local"
9151
9643
  ).action(
9152
9644
  (email3, raw) => runCommand(
@@ -9174,7 +9666,7 @@ var adminCreate = addTargetOptions(
9174
9666
  const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
9175
9667
  if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
9176
9668
  }
9177
- p50.log.info(
9669
+ p51.log.info(
9178
9670
  signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
9179
9671
  );
9180
9672
  },
@@ -9188,7 +9680,7 @@ var adminCreate = addTargetOptions(
9188
9680
  (pb) => upsertSuperuser(pb, address, password11)
9189
9681
  );
9190
9682
  const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
9191
- p50.log.info(
9683
+ p51.log.info(
9192
9684
  base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
9193
9685
  );
9194
9686
  }
@@ -9201,20 +9693,20 @@ var adminCreate = addTargetOptions(
9201
9693
  async function upsertSuperuser(pb, email3, password11) {
9202
9694
  const existing = await findSuperuser(pb, email3);
9203
9695
  if (existing) {
9204
- const confirmed = await p50.confirm({
9696
+ const confirmed = await p51.confirm({
9205
9697
  message: `${email3} already has an account, update its password?`,
9206
9698
  initialValue: false
9207
9699
  });
9208
- if (p50.isCancel(confirmed) || !confirmed) {
9209
- p50.cancel("Operation cancelled.");
9210
- process32.exit(0);
9700
+ if (p51.isCancel(confirmed) || !confirmed) {
9701
+ p51.cancel("Operation cancelled.");
9702
+ process33.exit(0);
9211
9703
  }
9212
9704
  await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
9213
- p50.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9705
+ p51.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9214
9706
  return;
9215
9707
  }
9216
9708
  await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
9217
- p50.log.success(`${pc25.cyan(email3)} can now sign in`);
9709
+ p51.log.success(`${pc25.cyan(email3)} can now sign in`);
9218
9710
  }
9219
9711
  async function findSuperuser(pb, email3) {
9220
9712
  try {
@@ -9225,47 +9717,47 @@ async function findSuperuser(pb, email3) {
9225
9717
  }
9226
9718
  }
9227
9719
  async function promptEmail() {
9228
- const value = await p50.text({
9720
+ const value = await p51.text({
9229
9721
  message: "Email to sign in with",
9230
9722
  validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
9231
9723
  });
9232
- if (p50.isCancel(value)) {
9233
- p50.cancel("Operation cancelled.");
9234
- process32.exit(0);
9724
+ if (p51.isCancel(value)) {
9725
+ p51.cancel("Operation cancelled.");
9726
+ process33.exit(0);
9235
9727
  }
9236
9728
  return value.trim();
9237
9729
  }
9238
9730
  async function promptPassword2() {
9239
- const value = await p50.password({
9731
+ const value = await p51.password({
9240
9732
  message: "Password",
9241
9733
  validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
9242
9734
  });
9243
- if (p50.isCancel(value)) {
9244
- p50.cancel("Operation cancelled.");
9245
- process32.exit(0);
9735
+ if (p51.isCancel(value)) {
9736
+ p51.cancel("Operation cancelled.");
9737
+ process33.exit(0);
9246
9738
  }
9247
- const again = await p50.password({
9739
+ const again = await p51.password({
9248
9740
  message: "Password again",
9249
9741
  validate: (input) => input === value ? void 0 : "The two do not match"
9250
9742
  });
9251
- if (p50.isCancel(again)) {
9252
- p50.cancel("Operation cancelled.");
9253
- process32.exit(0);
9743
+ if (p51.isCancel(again)) {
9744
+ p51.cancel("Operation cancelled.");
9745
+ process33.exit(0);
9254
9746
  }
9255
9747
  return value;
9256
9748
  }
9257
9749
 
9258
9750
  // src/commands/admin.ts
9259
- var admin = new Command87("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
9751
+ var admin = new Command88("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
9260
9752
 
9261
9753
  // src/commands/backup.ts
9262
- import { Command as Command93 } from "commander";
9754
+ import { Command as Command94 } from "commander";
9263
9755
 
9264
9756
  // src/commands/backup/create.ts
9265
- import fs38 from "node:fs";
9266
- import path40 from "node:path";
9267
- import { Command as Command88 } from "commander";
9268
- import * as p51 from "@clack/prompts";
9757
+ import fs39 from "node:fs";
9758
+ import path41 from "node:path";
9759
+ import { Command as Command89 } from "commander";
9760
+ import * as p52 from "@clack/prompts";
9269
9761
  import pc26 from "picocolors";
9270
9762
 
9271
9763
  // src/lib/backups.ts
@@ -9353,7 +9845,7 @@ async function writeSchedule(pb, cron, maxKeep) {
9353
9845
  // src/commands/backup/create.ts
9354
9846
  var DEFAULT_BACKUP_DIR = "backups";
9355
9847
  var backupCreate = addTargetOptions(
9356
- 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),
9848
+ new Command89("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),
9357
9849
  "production"
9358
9850
  ).action(
9359
9851
  (name, raw) => runCommand(() => {
@@ -9369,7 +9861,7 @@ Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_
9369
9861
  }
9370
9862
  const storage = await readStorageSettings(ctx.pb);
9371
9863
  if (storage.s3Enabled) {
9372
- p51.log.warn(
9864
+ p52.log.warn(
9373
9865
  `Uploads are stored in S3, so this archive holds the database only.
9374
9866
 
9375
9867
  PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
@@ -9377,7 +9869,7 @@ Your bucket's own versioning is what protects the uploaded files.`
9377
9869
  );
9378
9870
  }
9379
9871
  if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
9380
- const spinner7 = p51.spinner();
9872
+ const spinner7 = p52.spinner();
9381
9873
  spinner7.start(`Backing up ${ctx.targetName}`);
9382
9874
  try {
9383
9875
  await createBackup(ctx.pb, key);
@@ -9417,14 +9909,14 @@ Your bucket's own versioning is what protects the uploaded files.`
9417
9909
  }, "Failed to create the backup.")
9418
9910
  );
9419
9911
  async function download(ctx, key, outputDir) {
9420
- const dir = path40.resolve(ctx.workspaceRootDir, outputDir);
9421
- fs38.mkdirSync(dir, { recursive: true });
9422
- const destination = path40.join(dir, key);
9912
+ const dir = path41.resolve(ctx.workspaceRootDir, outputDir);
9913
+ fs39.mkdirSync(dir, { recursive: true });
9914
+ const destination = path41.join(dir, key);
9423
9915
  if (!ctx.session) {
9424
- fs38.copyFileSync(path40.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9425
- return path40.relative(ctx.workspaceRootDir, destination);
9916
+ fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9917
+ return path41.relative(ctx.workspaceRootDir, destination);
9426
9918
  }
9427
- const spinner7 = p51.spinner();
9919
+ const spinner7 = p52.spinner();
9428
9920
  spinner7.start(`Downloading ${key}`);
9429
9921
  try {
9430
9922
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9433,22 +9925,22 @@ async function download(ctx, key, outputDir) {
9433
9925
  throw error;
9434
9926
  }
9435
9927
  spinner7.stop(`Downloaded ${key}`);
9436
- return path40.relative(ctx.workspaceRootDir, destination);
9928
+ return path41.relative(ctx.workspaceRootDir, destination);
9437
9929
  }
9438
9930
 
9439
9931
  // src/commands/backup/list.ts
9440
- import { Command as Command89 } from "commander";
9441
- import * as p52 from "@clack/prompts";
9932
+ import { Command as Command90 } from "commander";
9933
+ import * as p53 from "@clack/prompts";
9442
9934
  import pc27 from "picocolors";
9443
9935
  var backupList = addTargetOptions(
9444
- new Command89("list").description("list the backups on a target").configureHelp(helpConfig),
9936
+ new Command90("list").description("list the backups on a target").configureHelp(helpConfig),
9445
9937
  "production"
9446
9938
  ).action(
9447
9939
  (raw) => runCommand(
9448
9940
  () => withBackupTarget(raw, "backup list", async (ctx) => {
9449
9941
  const backups = await listBackups(ctx.pb);
9450
9942
  if (backups.length === 0) {
9451
- p52.log.info(
9943
+ p53.log.info(
9452
9944
  `${pc27.cyan(ctx.targetName)} has no backups yet.
9453
9945
 
9454
9946
  Take one with ${pc27.cyan("vela backup create")}.`
@@ -9456,7 +9948,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9456
9948
  return;
9457
9949
  }
9458
9950
  const width = Math.max(...backups.map((b) => b.key.length));
9459
- p52.log.message(
9951
+ p53.log.message(
9460
9952
  backups.map(
9461
9953
  (b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
9462
9954
  ).join("\n")
@@ -9467,13 +9959,13 @@ Take one with ${pc27.cyan("vela backup create")}.`
9467
9959
  );
9468
9960
 
9469
9961
  // src/commands/backup/download.ts
9470
- import fs39 from "node:fs";
9471
- import path41 from "node:path";
9472
- import { Command as Command90 } from "commander";
9473
- import * as p53 from "@clack/prompts";
9962
+ import fs40 from "node:fs";
9963
+ import path42 from "node:path";
9964
+ import { Command as Command91 } from "commander";
9965
+ import * as p54 from "@clack/prompts";
9474
9966
  import pc28 from "picocolors";
9475
9967
  var backupDownload = addTargetOptions(
9476
- 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),
9968
+ new Command91("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),
9477
9969
  "production"
9478
9970
  ).action(
9479
9971
  (key, raw) => runCommand(() => {
@@ -9495,13 +9987,13 @@ Run ${pc28.cyan("vela backup list")} to see what it does have.`
9495
9987
  Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9496
9988
  );
9497
9989
  }
9498
- const dir = path41.resolve(ctx.workspaceRootDir, options.output);
9499
- fs39.mkdirSync(dir, { recursive: true });
9500
- const destination = path41.join(dir, key);
9990
+ const dir = path42.resolve(ctx.workspaceRootDir, options.output);
9991
+ fs40.mkdirSync(dir, { recursive: true });
9992
+ const destination = path42.join(dir, key);
9501
9993
  if (!ctx.session) {
9502
- fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9994
+ fs40.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9503
9995
  } else {
9504
- const spinner7 = p53.spinner();
9996
+ const spinner7 = p54.spinner();
9505
9997
  spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
9506
9998
  try {
9507
9999
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9513,19 +10005,19 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9513
10005
  }
9514
10006
  reportResult({
9515
10007
  summary: `Saved ${key} from ${ctx.targetName}.`,
9516
- filesCreated: [path41.relative(ctx.workspaceRootDir, destination)]
10008
+ filesCreated: [path42.relative(ctx.workspaceRootDir, destination)]
9517
10009
  });
9518
10010
  });
9519
10011
  }, "Failed to download the backup.")
9520
10012
  );
9521
10013
 
9522
10014
  // src/commands/backup/delete.ts
9523
- import process33 from "node:process";
9524
- import { Command as Command91 } from "commander";
9525
- import * as p54 from "@clack/prompts";
10015
+ import process34 from "node:process";
10016
+ import { Command as Command92 } from "commander";
10017
+ import * as p55 from "@clack/prompts";
9526
10018
  import pc29 from "picocolors";
9527
10019
  var backupDelete = addTargetOptions(
9528
- 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),
10020
+ new Command92("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),
9529
10021
  "production"
9530
10022
  ).action(
9531
10023
  (key, raw) => runCommand(() => {
@@ -9540,13 +10032,13 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
9540
10032
  );
9541
10033
  }
9542
10034
  if (!options.yes) {
9543
- const confirmed = await p54.confirm({
10035
+ const confirmed = await p55.confirm({
9544
10036
  message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
9545
10037
  initialValue: false
9546
10038
  });
9547
- if (p54.isCancel(confirmed) || !confirmed) {
9548
- p54.cancel("Operation cancelled.");
9549
- process33.exit(0);
10039
+ if (p55.isCancel(confirmed) || !confirmed) {
10040
+ p55.cancel("Operation cancelled.");
10041
+ process34.exit(0);
9550
10042
  }
9551
10043
  }
9552
10044
  await ctx.pb.backups.delete(key);
@@ -9556,12 +10048,12 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
9556
10048
  );
9557
10049
 
9558
10050
  // src/commands/backup/schedule.ts
9559
- import { Command as Command92 } from "commander";
9560
- import * as p55 from "@clack/prompts";
10051
+ import { Command as Command93 } from "commander";
10052
+ import * as p56 from "@clack/prompts";
9561
10053
  import pc30 from "picocolors";
9562
10054
  var DEFAULT_KEEP = 7;
9563
10055
  var backupSchedule = addTargetOptions(
9564
- 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),
10056
+ new Command93("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),
9565
10057
  "production"
9566
10058
  ).action(
9567
10059
  (cron, raw) => runCommand(() => {
@@ -9574,7 +10066,7 @@ var backupSchedule = addTargetOptions(
9574
10066
  }
9575
10067
  if (!cron) {
9576
10068
  const current = await readSchedule(ctx.pb);
9577
- p55.log.info(
10069
+ p56.log.info(
9578
10070
  current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
9579
10071
 
9580
10072
  Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
@@ -9605,18 +10097,18 @@ Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
9605
10097
  );
9606
10098
 
9607
10099
  // src/commands/backup.ts
9608
- 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);
10100
+ var backup = new Command94("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);
9609
10101
 
9610
10102
  // src/commands/restore.ts
9611
- import fs40 from "node:fs";
9612
- import path42 from "node:path";
9613
- import process34 from "node:process";
9614
- import { Command as Command94 } from "commander";
9615
- import * as p56 from "@clack/prompts";
10103
+ import fs41 from "node:fs";
10104
+ import path43 from "node:path";
10105
+ import process35 from "node:process";
10106
+ import { Command as Command95 } from "commander";
10107
+ import * as p57 from "@clack/prompts";
9616
10108
  import pc31 from "picocolors";
9617
10109
  var restore = addLockWaitOption(
9618
10110
  addTargetOptions(
9619
- 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),
10111
+ new Command95("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),
9620
10112
  "production"
9621
10113
  )
9622
10114
  ).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(
@@ -9632,7 +10124,7 @@ var restore = addLockWaitOption(
9632
10124
  `${ctx.targetName} was deployed without a database, so there is nothing to restore.`
9633
10125
  );
9634
10126
  }
9635
- const local = source && fs40.existsSync(source) ? source : void 0;
10127
+ const local = source && fs41.existsSync(source) ? source : void 0;
9636
10128
  const key = local ? void 0 : await resolveKey(ctx, source);
9637
10129
  if (!options.yes) {
9638
10130
  await confirm13(ctx.appName, ctx.targetName, ctx.envTag, local ?? key);
@@ -9653,18 +10145,18 @@ var restore = addLockWaitOption(
9653
10145
  ],
9654
10146
  stream: true
9655
10147
  });
9656
- p56.log.success(
10148
+ p57.log.success(
9657
10149
  `Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
9658
- local ? path42.basename(local) : key
10150
+ local ? path43.basename(local) : key
9659
10151
  )}.`
9660
10152
  );
9661
10153
  if (result?.storageCarriedOver) {
9662
- p56.log.info(
10154
+ p57.log.info(
9663
10155
  "The archive held no uploads, so the files already on the server were kept."
9664
10156
  );
9665
10157
  }
9666
10158
  if (result?.previousDataDir) {
9667
- p56.log.info(
10159
+ p57.log.info(
9668
10160
  `The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
9669
10161
 
9670
10162
  It is the only way back. Remove it once you are satisfied with the restore.`
@@ -9705,7 +10197,7 @@ Run ${pc31.cyan("vela backup list")} to see what it does have.`
9705
10197
  Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
9706
10198
  );
9707
10199
  }
9708
- const chosen = await p56.select({
10200
+ const chosen = await p57.select({
9709
10201
  message: `Which backup should ${ctx.targetName} be restored from?`,
9710
10202
  options: backups.map((b) => ({
9711
10203
  value: b.key,
@@ -9713,53 +10205,53 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
9713
10205
  hint: `${formatBytes(b.size)}, ${b.modified}`
9714
10206
  }))
9715
10207
  });
9716
- if (p56.isCancel(chosen)) {
9717
- p56.cancel("Operation cancelled.");
9718
- process34.exit(0);
10208
+ if (p57.isCancel(chosen)) {
10209
+ p57.cancel("Operation cancelled.");
10210
+ process35.exit(0);
9719
10211
  }
9720
10212
  return chosen;
9721
10213
  }
9722
10214
  async function stage(ctx, file) {
9723
10215
  const dir = remotePaths.restoreStage(ctx.instance);
9724
- const remote = `${dir}/${path42.basename(file)}`;
9725
- const spinner7 = p56.spinner();
9726
- spinner7.start(`Uploading ${path42.basename(file)}`);
10216
+ const remote = `${dir}/${path43.basename(file)}`;
10217
+ const spinner7 = p57.spinner();
10218
+ spinner7.start(`Uploading ${path43.basename(file)}`);
9727
10219
  try {
9728
10220
  await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
9729
10221
  await ctx.session.upload([file], dir);
9730
10222
  } catch (error) {
9731
- spinner7.stop(`Could not upload ${path42.basename(file)}.`);
10223
+ spinner7.stop(`Could not upload ${path43.basename(file)}.`);
9732
10224
  throw error;
9733
10225
  }
9734
- spinner7.stop(`Uploaded ${path42.basename(file)}`);
10226
+ spinner7.stop(`Uploaded ${path43.basename(file)}`);
9735
10227
  return remote;
9736
10228
  }
9737
10229
  async function confirm13(appName, targetName, envTag, from) {
9738
- const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path42.basename(from))}`;
10230
+ const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path43.basename(from))}`;
9739
10231
  if (isProd(envTag)) {
9740
- const answer = await p56.text({
10232
+ const answer = await p57.text({
9741
10233
  message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
9742
10234
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
9743
10235
  });
9744
- if (p56.isCancel(answer)) {
9745
- p56.cancel("Operation cancelled.");
9746
- process34.exit(0);
10236
+ if (p57.isCancel(answer)) {
10237
+ p57.cancel("Operation cancelled.");
10238
+ process35.exit(0);
9747
10239
  }
9748
10240
  return;
9749
10241
  }
9750
- const ok = await p56.confirm({
10242
+ const ok = await p57.confirm({
9751
10243
  message: `Replace the database and uploads of ${what}?`,
9752
10244
  initialValue: false
9753
10245
  });
9754
- if (p56.isCancel(ok) || !ok) {
9755
- p56.cancel("Operation cancelled.");
9756
- process34.exit(0);
10246
+ if (p57.isCancel(ok) || !ok) {
10247
+ p57.cancel("Operation cancelled.");
10248
+ process35.exit(0);
9757
10249
  }
9758
10250
  }
9759
10251
 
9760
10252
  // src/commands/targets.ts
9761
- import { Command as Command95 } from "commander";
9762
- import * as p57 from "@clack/prompts";
10253
+ import { Command as Command96 } from "commander";
10254
+ import * as p58 from "@clack/prompts";
9763
10255
  import pc32 from "picocolors";
9764
10256
  import * as v9 from "valibot";
9765
10257
  var OptionsSchema4 = v9.object({
@@ -9768,7 +10260,7 @@ var OptionsSchema4 = v9.object({
9768
10260
  offline: v9.optional(v9.boolean())
9769
10261
  });
9770
10262
  var targets = addSshOptions(
9771
- new Command95("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
10263
+ new Command96("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
9772
10264
  ).option("--json", "print raw JSON").option("--offline", "skip connecting to servers").action(
9773
10265
  (raw) => runCommand(async () => {
9774
10266
  const options = parseOptions(OptionsSchema4, raw);
@@ -9834,11 +10326,11 @@ function report3(rows, offline) {
9834
10326
  const lines = rows.map(
9835
10327
  (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}`
9836
10328
  );
9837
- p57.log.info(`${pc32.dim(header)}
10329
+ p58.log.info(`${pc32.dim(header)}
9838
10330
  ${lines.join("\n")}`);
9839
10331
  const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
9840
10332
  if (!offline && unreachable.length > 0) {
9841
- p57.log.warn(
10333
+ p58.log.warn(
9842
10334
  `Could not reach ${unreachable.map((row) => row.server).join(", ")}.
9843
10335
  Release and domain are shown from what this project recorded.`
9844
10336
  );
@@ -9846,36 +10338,36 @@ Release and domain are shown from what this project recorded.`
9846
10338
  }
9847
10339
 
9848
10340
  // src/commands/test.ts
9849
- import path43 from "node:path";
9850
- import process35 from "node:process";
9851
- import { Command as Command96 } from "commander";
10341
+ import path44 from "node:path";
10342
+ import process36 from "node:process";
10343
+ import { Command as Command97 } from "commander";
9852
10344
  import PocketBase6 from "pocketbase";
9853
10345
  import pc33 from "picocolors";
9854
10346
  import { x as x5 } from "tinyexec";
9855
- import { detect as detect7 } from "package-manager-detector";
10347
+ import { detect as detect8 } from "package-manager-detector";
9856
10348
  import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
9857
- import fs41 from "node:fs";
9858
- var testServer = new Command96("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
9859
- const cwd = process35.cwd();
10349
+ import fs42 from "node:fs";
10350
+ var testServer = new Command97("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
10351
+ const cwd = process36.cwd();
9860
10352
  const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
9861
10353
  const password11 = "password";
9862
- const testDataDir = path43.join(cwd, "test-data");
9863
- fs41.rmSync(testDataDir, { recursive: true, force: true });
10354
+ const testDataDir = path44.join(cwd, "test-data");
10355
+ fs42.rmSync(testDataDir, { recursive: true, force: true });
9864
10356
  const { stop, url } = await launchPocketbase(cwd, {
9865
10357
  dir: testDataDir,
9866
- migrationsDir: path43.join(cwd, MIGRATIONS_DIR),
10358
+ migrationsDir: path44.join(cwd, MIGRATIONS_DIR),
9867
10359
  // The app's PocketBase hooks (slug generation, personal teams, …) are part
9868
10360
  // of its behaviour; the suite runs against the same server dev and build
9869
10361
  // start, so it loads them from the same place.
9870
- hooksDir: path43.join(cwd, DATA_DIR, "hooks"),
10362
+ hooksDir: path44.join(cwd, DATA_DIR, "hooks"),
9871
10363
  email: email3,
9872
10364
  password: password11
9873
10365
  });
9874
- process35.env.POCKETBASE_URL = url;
9875
- process35.env.POCKETBASE_SUPERUSER_EMAIL = email3;
9876
- process35.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
9877
- process35.env.VELA_DATA_DIR = testDataDir;
9878
- process35.env.TEST = "true";
10366
+ process36.env.POCKETBASE_URL = url;
10367
+ process36.env.POCKETBASE_SUPERUSER_EMAIL = email3;
10368
+ process36.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
10369
+ process36.env.VELA_DATA_DIR = testDataDir;
10370
+ process36.env.TEST = "true";
9879
10371
  console.log(`${pc33.greenBright("\u2713")} Created test database`);
9880
10372
  let vite;
9881
10373
  let cleanedUp = false;
@@ -9883,7 +10375,7 @@ var testServer = new Command96("test:server").description("run server tests").al
9883
10375
  if (cleanedUp) return;
9884
10376
  cleanedUp = true;
9885
10377
  stop();
9886
- fs41.rmSync(testDataDir, { recursive: true, force: true });
10378
+ fs42.rmSync(testDataDir, { recursive: true, force: true });
9887
10379
  };
9888
10380
  const cleanup = async () => {
9889
10381
  if (cleanedUp) return;
@@ -9894,12 +10386,12 @@ var testServer = new Command96("test:server").description("run server tests").al
9894
10386
  const fail = async (message) => {
9895
10387
  console.error(`${pc33.redBright("\u2717")} ${message}`);
9896
10388
  await cleanup();
9897
- process35.exit(1);
10389
+ process36.exit(1);
9898
10390
  };
9899
- process35.on("exit", cleanupSync);
9900
- process35.on("SIGINT", () => {
10391
+ process36.on("exit", cleanupSync);
10392
+ process36.on("SIGINT", () => {
9901
10393
  cleanupSync();
9902
- process35.exit(130);
10394
+ process36.exit(130);
9903
10395
  });
9904
10396
  const pb = new PocketBase6(url);
9905
10397
  try {
@@ -9927,7 +10419,7 @@ var testServer = new Command96("test:server").description("run server tests").al
9927
10419
  });
9928
10420
  const vitePort = await findFreePort();
9929
10421
  await vite.listen(vitePort);
9930
- process35.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10422
+ process36.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
9931
10423
  console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
9932
10424
  console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
9933
10425
  const extraArgs = (cmd.parent?.args ?? []).slice(1);
@@ -9935,7 +10427,7 @@ var testServer = new Command96("test:server").description("run server tests").al
9935
10427
  const passthrough = filter ? extraArgs.filter((a) => a !== filter) : extraArgs;
9936
10428
  if (!filter) filter = "server";
9937
10429
  try {
9938
- const pm = (await detect7({ cwd }))?.name ?? "npm";
10430
+ const pm = (await detect8({ cwd }))?.name ?? "npm";
9939
10431
  const resolved = resolveCommand7(pm, "execute", [
9940
10432
  "vitest",
9941
10433
  "run",
@@ -9946,12 +10438,12 @@ var testServer = new Command96("test:server").description("run server tests").al
9946
10438
  const resolvedArgs = resolved.args.slice();
9947
10439
  if (pm === "npm") resolvedArgs.unshift("--yes");
9948
10440
  const result = await x5(resolved.command, resolvedArgs, {
9949
- nodeOptions: { cwd, stdio: "inherit", env: { ...process35.env, CI: "1" } }
10441
+ nodeOptions: { cwd, stdio: "inherit", env: { ...process36.env, CI: "1" } }
9950
10442
  });
9951
- process35.exitCode = result.exitCode ?? 1;
10443
+ process36.exitCode = result.exitCode ?? 1;
9952
10444
  } catch (e) {
9953
10445
  console.error(`${pc33.redBright("\u2717")} ${e.message}`);
9954
- process35.exitCode = 1;
10446
+ process36.exitCode = 1;
9955
10447
  } finally {
9956
10448
  await cleanup();
9957
10449
  }
@@ -9982,9 +10474,9 @@ function stubPagesPlugin() {
9982
10474
  }
9983
10475
 
9984
10476
  // src/commands/routes.ts
9985
- import fs42 from "node:fs";
9986
- import path44 from "node:path";
9987
- import { Command as Command97 } from "commander";
10477
+ import fs43 from "node:fs";
10478
+ import path45 from "node:path";
10479
+ import { Command as Command98 } from "commander";
9988
10480
  var HTTP_METHODS = /* @__PURE__ */ new Set([
9989
10481
  "GET",
9990
10482
  "POST",
@@ -9995,32 +10487,32 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
9995
10487
  "HEAD",
9996
10488
  "fallback"
9997
10489
  ]);
9998
- var routes = new Command97("routes").description("list routes").configureHelp(helpConfig).action(async () => {
10490
+ var routes = new Command98("routes").description("list routes").configureHelp(helpConfig).action(async () => {
9999
10491
  const { workspaceRootDir, routesDir } = await getWorkspace();
10000
- const routesRoot = path44.join(workspaceRootDir, routesDir);
10492
+ const routesRoot = path45.join(workspaceRootDir, routesDir);
10001
10493
  const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
10002
10494
  found.sort((a, b) => a.urlPattern.localeCompare(b.urlPattern));
10003
10495
  printTable(found);
10004
10496
  });
10005
10497
  function walk(root, dir) {
10006
- const entries = fs42.readdirSync(dir, { withFileTypes: true });
10498
+ const entries = fs43.readdirSync(dir, { withFileTypes: true });
10007
10499
  const routes2 = [];
10008
10500
  const hasLeaf = entries.some((e) => e.isFile() && isRouteFile(e.name));
10009
10501
  if (hasLeaf) {
10010
- const id = "/" + path44.relative(root, dir).split(path44.sep).filter(Boolean).join("/");
10502
+ const id = "/" + path45.relative(root, dir).split(path45.sep).filter(Boolean).join("/");
10011
10503
  const urlPattern = id.replace(/\([^)]+\)\/?/g, "").replace(/\/$/, "") || "/";
10012
10504
  const methods = /* @__PURE__ */ new Set();
10013
10505
  for (const entry of entries) {
10014
10506
  if (!entry.isFile()) continue;
10015
10507
  if (entry.name.endsWith("+page.svelte")) methods.add("GET");
10016
10508
  if (entry.name.endsWith("+server.ts") || entry.name.endsWith("+server.js") || entry.name.endsWith("+page.server.ts") || entry.name.endsWith("+page.server.js")) {
10017
- extractMethods(path44.join(dir, entry.name)).forEach((m) => methods.add(m));
10509
+ extractMethods(path45.join(dir, entry.name)).forEach((m) => methods.add(m));
10018
10510
  }
10019
10511
  }
10020
10512
  routes2.push({ id: id || "/", urlPattern, methods: [...methods] });
10021
10513
  }
10022
10514
  for (const entry of entries) {
10023
- if (entry.isDirectory()) routes2.push(...walk(root, path44.join(dir, entry.name)));
10515
+ if (entry.isDirectory()) routes2.push(...walk(root, path45.join(dir, entry.name)));
10024
10516
  }
10025
10517
  return routes2;
10026
10518
  }
@@ -10029,7 +10521,7 @@ function isRouteFile(name) {
10029
10521
  }
10030
10522
  function extractMethods(file) {
10031
10523
  try {
10032
- const content = fs42.readFileSync(file, "utf8");
10524
+ const content = fs43.readFileSync(file, "utf8");
10033
10525
  const methods = [];
10034
10526
  const exportRegex = /export\s+(?:const|async\s+function|function)\s+(\w+)/g;
10035
10527
  let match;
@@ -10070,14 +10562,14 @@ function printTable(routes2) {
10070
10562
  }
10071
10563
 
10072
10564
  // src/commands/i18n.ts
10073
- import process36 from "node:process";
10074
- import { Command as Command98 } from "commander";
10565
+ import process37 from "node:process";
10566
+ import { Command as Command99 } from "commander";
10075
10567
  import { x as x6 } from "tinyexec";
10076
- import { detect as detect8 } from "package-manager-detector";
10568
+ import { detect as detect9 } from "package-manager-detector";
10077
10569
  import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
10078
10570
  async function runWuchale(extraArgs) {
10079
- const cwd = process36.cwd();
10080
- const pm = (await detect8({ cwd }))?.name ?? "npm";
10571
+ const cwd = process37.cwd();
10572
+ const pm = (await detect9({ cwd }))?.name ?? "npm";
10081
10573
  const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
10082
10574
  const args = resolved.args.slice();
10083
10575
  if (pm === "npm") args.unshift("--yes");
@@ -10086,11 +10578,11 @@ async function runWuchale(extraArgs) {
10086
10578
  throwOnError: true
10087
10579
  });
10088
10580
  }
10089
- var extract2 = new Command98("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
10090
- var watch = new Command98("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
10091
- var status2 = new Command98("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
10092
- var clean = new Command98("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
10093
- var i18n3 = new Command98("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract2, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
10581
+ var extract2 = new Command99("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
10582
+ var watch = new Command99("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
10583
+ var status2 = new Command99("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
10584
+ var clean = new Command99("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
10585
+ var i18n3 = new Command99("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract2, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
10094
10586
 
10095
10587
  // src/commands/oauth.ts
10096
10588
  var oauth = stubCommand("oauth", "configure OAuth providers");
@@ -10099,28 +10591,28 @@ var oauth = stubCommand("oauth", "configure OAuth providers");
10099
10591
  var schemas = stubCommand("schemas", "manage database schemas");
10100
10592
 
10101
10593
  // src/commands/cms.ts
10102
- import { Command as Command103 } from "commander";
10594
+ import { Command as Command104 } from "commander";
10103
10595
 
10104
10596
  // src/commands/cms/editor.ts
10105
- import { Command as Command102 } from "commander";
10597
+ import { Command as Command103 } from "commander";
10106
10598
 
10107
10599
  // src/commands/cms/editor/add.ts
10108
10600
  import { randomBytes } from "node:crypto";
10109
- import { Command as Command99 } from "commander";
10110
- import * as p58 from "@clack/prompts";
10601
+ import { Command as Command100 } from "commander";
10602
+ import * as p59 from "@clack/prompts";
10111
10603
  import pc35 from "picocolors";
10112
10604
 
10113
10605
  // src/lib/cms-backend.ts
10114
10606
  import { createRequire as createRequire3 } from "node:module";
10115
- import path45 from "node:path";
10116
- import process37 from "node:process";
10607
+ import path46 from "node:path";
10608
+ import process38 from "node:process";
10117
10609
  import { pathToFileURL as pathToFileURL3 } from "node:url";
10118
10610
  import pc34 from "picocolors";
10119
10611
  var DEFAULT_PROJECT = "default";
10120
10612
  async function loadBackendModule(root) {
10121
10613
  let entry;
10122
10614
  try {
10123
- entry = createRequire3(path45.join(root, "package.json")).resolve("@velastack/cms/backend");
10615
+ entry = createRequire3(path46.join(root, "package.json")).resolve("@velastack/cms/backend");
10124
10616
  } catch {
10125
10617
  throw new Error(
10126
10618
  `@velastack/cms is not installed in this project.
@@ -10130,7 +10622,7 @@ Run ${pc34.cyan("vela enable cms")} first.`
10130
10622
  }
10131
10623
  return await import(pathToFileURL3(entry).href);
10132
10624
  }
10133
- async function withCmsBackend(fn, cwd = process37.cwd()) {
10625
+ async function withCmsBackend(fn, cwd = process38.cwd()) {
10134
10626
  const root = findWorkspaceRoot(cwd);
10135
10627
  if (!root) {
10136
10628
  throw new Error("Could not find workspace root (no package.json found)");
@@ -10138,8 +10630,8 @@ async function withCmsBackend(fn, cwd = process37.cwd()) {
10138
10630
  const { createCmsBackend } = await loadBackendModule(root);
10139
10631
  const dataDir2 = localDataDir(root);
10140
10632
  const backend3 = createCmsBackend({
10141
- dbPath: path45.join(dataDir2, "cms.sqlite"),
10142
- uploadDir: path45.join(dataDir2, "uploads")
10633
+ dbPath: path46.join(dataDir2, "cms.sqlite"),
10634
+ uploadDir: path46.join(dataDir2, "uploads")
10143
10635
  });
10144
10636
  try {
10145
10637
  return await fn(backend3);
@@ -10149,7 +10641,7 @@ async function withCmsBackend(fn, cwd = process37.cwd()) {
10149
10641
  }
10150
10642
 
10151
10643
  // src/commands/cms/editor/add.ts
10152
- 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(
10644
+ var editorAdd = new Command100("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(
10153
10645
  (email3, options) => runCommand(async () => {
10154
10646
  const generated = options.password === void 0;
10155
10647
  const password11 = options.password ?? randomBytes(12).toString("base64url");
@@ -10160,31 +10652,31 @@ var editorAdd = new Command99("add").description("create an editor who can sign
10160
10652
  if (generated) {
10161
10653
  lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
10162
10654
  }
10163
- p58.log.success(lines.join("\n"));
10164
- p58.log.info(
10655
+ p59.log.success(lines.join("\n"));
10656
+ p59.log.info(
10165
10657
  `Run ${pc35.cyan("vela dev")}, open any page with ${pc35.cyan("?edit")} on the URL (or press ${pc35.cyan("Ctrl+E")}), and sign in.`
10166
10658
  );
10167
10659
  }, "Failed to add the editor.")
10168
10660
  );
10169
10661
 
10170
10662
  // src/commands/cms/editor/password.ts
10171
- import { Command as Command100 } from "commander";
10172
- import * as p59 from "@clack/prompts";
10663
+ import { Command as Command101 } from "commander";
10664
+ import * as p60 from "@clack/prompts";
10173
10665
  import pc36 from "picocolors";
10174
- var editorPassword = new Command100("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
10666
+ var editorPassword = new Command101("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
10175
10667
  (email3, password11) => runCommand(async () => {
10176
10668
  await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
10177
- p59.log.success(
10669
+ p60.log.success(
10178
10670
  `Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
10179
10671
  );
10180
10672
  }, "Failed to set the password.")
10181
10673
  );
10182
10674
 
10183
10675
  // src/commands/cms/editor/list.ts
10184
- import { Command as Command101 } from "commander";
10185
- import * as p60 from "@clack/prompts";
10676
+ import { Command as Command102 } from "commander";
10677
+ import * as p61 from "@clack/prompts";
10186
10678
  import pc37 from "picocolors";
10187
- var editorList = new Command101("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10679
+ var editorList = new Command102("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10188
10680
  () => runCommand(async () => {
10189
10681
  const rows = await withCmsBackend(
10190
10682
  async (cms3) => cms3.editors.list().map((editor2) => ({
@@ -10193,11 +10685,11 @@ var editorList = new Command101("list").description("list editors and the projec
10193
10685
  }))
10194
10686
  );
10195
10687
  if (rows.length === 0) {
10196
- p60.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10688
+ p61.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10197
10689
  return;
10198
10690
  }
10199
10691
  const width = Math.max(...rows.map((row) => row.email.length));
10200
- p60.log.info(
10692
+ p61.log.info(
10201
10693
  `Editors
10202
10694
 
10203
10695
  ` + rows.map(
@@ -10208,10 +10700,10 @@ var editorList = new Command101("list").description("list editors and the projec
10208
10700
  );
10209
10701
 
10210
10702
  // src/commands/cms/editor.ts
10211
- var editor = new Command102("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
10703
+ var editor = new Command103("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
10212
10704
 
10213
10705
  // src/commands/cms.ts
10214
- var cms2 = new Command103("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
10706
+ var cms2 = new Command104("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
10215
10707
 
10216
10708
  // src/program.ts
10217
10709
  var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
@@ -10229,6 +10721,8 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
10229
10721
  "generate form",
10230
10722
  // The CMS keeps its own SQLite database and editors; PocketBase is never involved.
10231
10723
  "enable cms",
10724
+ // Analytics only touches the root layout and .env; it must work on static sites.
10725
+ "enable analytics",
10232
10726
  "cms",
10233
10727
  // Server commands talk to a VPS over SSH, never to the local database.
10234
10728
  "provision",
@@ -10242,35 +10736,38 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
10242
10736
  // Acts on whichever target `-t` names; the local path reads the project's
10243
10737
  // own credentials rather than requiring them in this process.
10244
10738
  "backup",
10245
- "restore"
10739
+ "restore",
10740
+ // Removes a copy from its server; the other `destroy` subcommands edit the
10741
+ // local schema and stay gated.
10742
+ "destroy deployment"
10246
10743
  ]);
10247
10744
  var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
10248
10745
  var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
10249
- var program = new Command104().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10746
+ var program = new Command105().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10250
10747
  program.hook("preAction", (_thisCommand, actionCommand) => {
10251
10748
  if (isStub(actionCommand)) return;
10252
- const envRoot = findWorkspaceRoot() ?? process38.cwd();
10749
+ const envRoot = findWorkspaceRoot() ?? process39.cwd();
10253
10750
  dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
10254
- const path46 = getCommandPath(actionCommand);
10255
- if (NO_BACKEND_COMMMANDS.has(path46)) return;
10256
- const top = path46.split(" ", 1)[0];
10751
+ const path47 = getCommandPath(actionCommand);
10752
+ if (NO_BACKEND_COMMMANDS.has(path47)) return;
10753
+ const top = path47.split(" ", 1)[0];
10257
10754
  if (NO_BACKEND_COMMMANDS.has(top)) return;
10258
10755
  if (!hasBackend()) {
10259
10756
  if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
10260
- p61.log.error(
10261
- `${pc38.cyan(`vela ${path46}`)} needs a backend, and this project does not have one.
10757
+ p62.log.error(
10758
+ `${pc38.cyan(`vela ${path47}`)} needs a backend, and this project does not have one.
10262
10759
 
10263
10760
  Static projects have no database to talk to.
10264
10761
 
10265
10762
  To add a backend to this project, run ${pc38.cyan("vela bless")}.`
10266
10763
  );
10267
- p61.log.message();
10268
- p61.cancel("Operation failed.");
10269
- process38.exit(1);
10764
+ p62.log.message();
10765
+ p62.cancel("Operation failed.");
10766
+ process39.exit(1);
10270
10767
  }
10271
- if (SELF_CREDENTIALED_COMMANDS.has(path46)) return;
10272
- if (!process38.env.POCKETBASE_SUPERUSER_EMAIL || !process38.env.POCKETBASE_SUPERUSER_PASSWORD) {
10273
- p61.log.error(
10768
+ if (SELF_CREDENTIALED_COMMANDS.has(path47)) return;
10769
+ if (!process39.env.POCKETBASE_SUPERUSER_EMAIL || !process39.env.POCKETBASE_SUPERUSER_PASSWORD) {
10770
+ p62.log.error(
10274
10771
  `PocketBase superuser credentials are required.
10275
10772
 
10276
10773
  Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
@@ -10278,9 +10775,9 @@ Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPER
10278
10775
  To set up a new project, run ${pc38.cyan("vela create")}.
10279
10776
  To set up an existing project, run ${pc38.cyan("vela bless")}.`
10280
10777
  );
10281
- p61.log.message();
10282
- p61.cancel("Operation failed.");
10283
- process38.exit(1);
10778
+ p62.log.message();
10779
+ p62.cancel("Operation failed.");
10780
+ process39.exit(1);
10284
10781
  }
10285
10782
  });
10286
10783
  function getCommandPath(cmd) {
@@ -10334,5 +10831,5 @@ for (const command of [
10334
10831
  }
10335
10832
 
10336
10833
  // src/bin.ts
10337
- program.parse(normalizeArgv(process39.argv.slice(2)), { from: "user" });
10834
+ program.parse(normalizeArgv(process40.argv.slice(2)), { from: "user" });
10338
10835
  //# sourceMappingURL=bin.js.map