vela 0.11.6 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/bin.ts
4
- import process40 from "node:process";
4
+ import process42 from "node:process";
5
5
 
6
6
  // src/lib/argv.ts
7
7
  function normalizeArgv(argv) {
@@ -11,8 +11,8 @@ function normalizeArgv(argv) {
11
11
  }
12
12
 
13
13
  // src/program.ts
14
- import process39 from "node:process";
15
- import * as p62 from "@clack/prompts";
14
+ import process41 from "node:process";
15
+ import * as p63 from "@clack/prompts";
16
16
  import { Command as Command105 } from "commander";
17
17
  import nodePath from "node:path";
18
18
  import dotenv2 from "dotenv";
@@ -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.6",
24
+ version: "0.12.0",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -321,10 +321,15 @@ function readPackageJson(path47) {
321
321
  var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
322
322
  var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
323
323
  var CLI_VERSION_PLACEHOLDER = /~VELA_VERSION~/g;
324
+ var SITE_URL_PLACEHOLDER = /~SITE_URL~/g;
325
+ var CMS_ENDPOINT_PLACEHOLDER = /~CMS_ENDPOINT~/g;
326
+ var LOCAL_SITE_URL = "http://localhost:5173";
324
327
  function fillTemplatePlaceholders(raw, values) {
325
328
  const packageName = toValidPackageName(values.appName);
326
329
  const appName = escapeSingleQuoted(values.appName);
327
- return raw.replace(PACKAGE_NAME_PLACEHOLDER, () => packageName).replace(APP_NAME_PLACEHOLDER, () => appName).replace(CLI_VERSION_PLACEHOLDER, () => values.cliVersion);
330
+ const siteUrl = escapeSingleQuoted(values.siteUrl ?? LOCAL_SITE_URL);
331
+ const cmsEndpoint = escapeSingleQuoted(values.cmsEndpoint ?? "");
332
+ return raw.replace(PACKAGE_NAME_PLACEHOLDER, () => packageName).replace(APP_NAME_PLACEHOLDER, () => appName).replace(CLI_VERSION_PLACEHOLDER, () => values.cliVersion).replace(SITE_URL_PLACEHOLDER, () => siteUrl).replace(CMS_ENDPOINT_PLACEHOLDER, () => cmsEndpoint);
328
333
  }
329
334
  function escapeSingleQuoted(value) {
330
335
  return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
@@ -562,6 +567,10 @@ var entrySchema = v2.object({
562
567
  price: v2.optional(v2.number()),
563
568
  previewUrl: v2.optional(v2.string()),
564
569
  nextSteps: v2.optional(v2.array(v2.string())),
570
+ /** Reads its copy from a hosted CMS through `site.cmsEndpoint`. */
571
+ cms: v2.optional(v2.boolean()),
572
+ /** A prebuilt static build is published for velastack.dev's instant deploys. */
573
+ instantDeploy: v2.optional(v2.boolean()),
565
574
  /** Tarball location, relative to the index URL. */
566
575
  file: v2.string(),
567
576
  sha256: v2.pipe(v2.string(), v2.regex(/^[0-9a-f]{64}$/)),
@@ -753,6 +762,7 @@ async function listAllTemplates(options = {}) {
753
762
  tags: entry.tags,
754
763
  price: entry.price,
755
764
  nextSteps: entry.nextSteps,
765
+ cms: entry.cms,
756
766
  entry,
757
767
  indexUrl
758
768
  });
@@ -833,6 +843,7 @@ function readManifest(root, name) {
833
843
  tags: optionalStringArray(manifest.tags),
834
844
  price: typeof manifest.price === "number" ? manifest.price : void 0,
835
845
  nextSteps: optionalStringArray(manifest.nextSteps),
846
+ cms: typeof manifest.cms === "boolean" ? manifest.cms : void 0,
836
847
  dir: path5.join(root, name)
837
848
  };
838
849
  }
@@ -968,7 +979,7 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
968
979
  };
969
980
  proc.once("exit", onExit);
970
981
  let attempts = 0;
971
- const check = async () => {
982
+ const check2 = async () => {
972
983
  if (settled) return;
973
984
  attempts++;
974
985
  try {
@@ -989,9 +1000,9 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
989
1000
  reject(new Error(`Timed out waiting for health at ${url}`));
990
1001
  return;
991
1002
  }
992
- setTimeout(check, 250);
1003
+ setTimeout(check2, 250);
993
1004
  };
994
- check();
1005
+ check2();
995
1006
  });
996
1007
  }
997
1008
  async function startPocketbaseServe(opts) {
@@ -1912,205 +1923,17 @@ function printNextSteps(projectPath, packageManager2) {
1912
1923
  }
1913
1924
 
1914
1925
  // src/commands/create.ts
1915
- import fs16 from "node:fs";
1916
- import path14 from "node:path";
1917
- import process8 from "node:process";
1926
+ import fs17 from "node:fs";
1927
+ import path15 from "node:path";
1928
+ import process11 from "node:process";
1918
1929
  import * as v4 from "valibot";
1919
- import { Command as Command3 } from "commander";
1920
- import * as p5 from "@clack/prompts";
1921
- import { detect as detect3, resolveCommand as resolveCommand3 } from "package-manager-detector";
1922
- function optionsSchema2(listing) {
1923
- const names = listing.templates.map((template) => template.name);
1924
- let choices2 = `must be one of: ${templateChoicesMessage(listing.templates)}`;
1925
- if (listing.registryError) {
1926
- choices2 += ` (could not reach the template registry: ${listing.registryError})`;
1927
- }
1928
- return v4.strictObject({
1929
- install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
1930
- template: v4.optional(v4.picklist(names, choices2)),
1931
- name: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
1932
- email: v4.optional(v4.pipe(v4.string(), v4.email("must be a valid email address"))),
1933
- password: v4.optional(v4.pipe(v4.string(), v4.minLength(8, "must be at least 8 characters long")))
1934
- });
1935
- }
1936
- var create = new Command3("create").description("scaffold a new velastack project").argument("[path]", "where the project will be created").option("--template <type>", "template to scaffold (built-in or from the registry)", "minimal").option("--no-install", "skip installing dependencies").option("--name <name>", "app name (used for emails, etc)").option("--email <email>", "email of the admin user").option("--password <password>", "password of the admin user").addOption(installOption).configureHelp(helpConfig).action((projectPath, rawOpts) => {
1937
- return runCommand(async () => {
1938
- const listing = await listAllTemplates();
1939
- const options = parseOptions(optionsSchema2(listing), rawOpts);
1940
- const { directory, packageManager: packageManager2, name, template } = await createProject(
1941
- projectPath,
1942
- options,
1943
- listing
1944
- );
1945
- const relative = path14.relative(process8.cwd(), directory);
1946
- const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
1947
- const nextSteps = [];
1948
- if (relative !== "") {
1949
- const hasSpaces = relative.includes(" ");
1950
- nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
1951
- }
1952
- if (!packageManager2) {
1953
- const resolved = resolveCommand3(pm, "install", []);
1954
- if (resolved) {
1955
- nextSteps.push(
1956
- `\`${resolved.command} ${resolved.args.join(" ")}\` to install dependencies`
1957
- );
1958
- }
1959
- }
1960
- const runDev = resolveCommand3(pm, "run", ["dev", "--open"]);
1961
- if (runDev) {
1962
- nextSteps.push(
1963
- `\`${runDev.command} ${runDev.args.join(" ")}\` to start the dev server (Ctrl-C to stop)`
1964
- );
1965
- }
1966
- if (template.nextSteps) {
1967
- nextSteps.push(...template.nextSteps);
1968
- } else if (template.backend) {
1969
- nextSteps.push("Run `vela generate scaffold <model>` to generate your first CRUD pages.");
1970
- } else {
1971
- nextSteps.push(
1972
- "Set your deployed URL in `src/lib/site.ts` before building for production."
1973
- );
1974
- nextSteps.push("Run `vela ui add <component>` to add UI components.");
1975
- }
1976
- nextSteps.push("Stuck? Visit https://docs.velastack.dev");
1977
- reportResult({
1978
- summary: `Created ${name} at ${directory}.`,
1979
- nextSteps
1980
- });
1981
- }, "Failed to create project.");
1982
- });
1983
- async function createProject(cwdArg, options, listing) {
1984
- const onCancel2 = () => {
1985
- p5.cancel("Operation cancelled.");
1986
- process8.exit(0);
1987
- };
1988
- const template = findTemplate(listing, options.template ?? DEFAULT_TEMPLATE);
1989
- if (!template.backend && (options.email || options.password)) {
1990
- throw new Error(
1991
- `--email and --password don't apply to the ${template.name} template \u2014 it has no backend.`
1992
- );
1993
- }
1994
- let directory;
1995
- if (cwdArg) {
1996
- directory = path14.resolve(cwdArg);
1997
- } else {
1998
- const answer = await p5.text({
1999
- message: "Where would you like your project to be created?",
2000
- placeholder: " (hit Enter to use current directory)",
2001
- defaultValue: "./"
2002
- });
2003
- if (p5.isCancel(answer)) onCancel2();
2004
- directory = path14.resolve(answer);
2005
- }
2006
- if (fs16.existsSync(directory) && fs16.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
2007
- const force = await p5.confirm({
2008
- message: "Directory not empty. Continue?",
2009
- initialValue: false
2010
- });
2011
- if (p5.isCancel(force) || !force) onCancel2();
2012
- }
2013
- const dirName = path14.basename(directory);
2014
- const { name } = await p5.group(
2015
- {
2016
- name: () => {
2017
- if (options.name) return Promise.resolve(options.name);
2018
- return p5.text({
2019
- message: "App name (used for emails, etc)",
2020
- initialValue: dirName || "SvelteKit",
2021
- validate: (value) => value?.trim() ? void 0 : "App name is required"
2022
- });
2023
- }
2024
- },
2025
- { onCancel: onCancel2 }
2026
- );
2027
- const credentials = template.backend ? await promptCredentials(options, onCancel2) : void 0;
2028
- const projectPath = directory;
2029
- if (template.source === "remote") p5.log.step(`Downloading template ${template.name}...`);
2030
- const resolved = await resolveTemplate(template);
2031
- try {
2032
- copyTemplate(resolved, projectPath);
2033
- applyTemplateFiles(projectPath, { appName: name, cliVersion: package_default.version });
2034
- } finally {
2035
- resolved.cleanup();
2036
- }
2037
- if (!fs16.existsSync(path14.join(projectPath, "package.json"))) {
2038
- throw new Error(`Template ${template.name} is missing package.template.json`);
2039
- }
2040
- p5.log.success("Project created");
2041
- let packageManager2;
2042
- if (options.install !== false) {
2043
- const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
2044
- if (pm) {
2045
- const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
2046
- addPnpmBuildDependencies(projectPath, pm, builds);
2047
- await installDependencies(pm, projectPath);
2048
- packageManager2 = pm;
2049
- }
2050
- }
2051
- if (credentials) {
2052
- const { email: email3, password: password11 } = credentials;
2053
- p5.log.step("Initializing PocketBase...");
2054
- await createSuperuser(projectPath, email3, password11);
2055
- await withPocketbase(
2056
- projectPath,
2057
- async (pb) => {
2058
- await pb.settings.update({
2059
- meta: { appName: name, appURL: "http://localhost:5173" }
2060
- });
2061
- },
2062
- { email: email3, password: password11 }
2063
- );
2064
- writeEnvFile(
2065
- projectPath,
2066
- {
2067
- POCKETBASE_SUPERUSER_EMAIL: email3,
2068
- POCKETBASE_SUPERUSER_PASSWORD: password11
2069
- },
2070
- ["PocketBase superuser credentials \u2014 used by `vela` commands"]
2071
- );
2072
- p5.log.success("PocketBase initialized");
2073
- }
2074
- return { directory: projectPath, packageManager: packageManager2, name, template };
2075
- }
2076
- function promptCredentials(options, onCancel2) {
2077
- return p5.group(
2078
- {
2079
- email: () => {
2080
- if (options.email) return Promise.resolve(options.email);
2081
- return p5.text({
2082
- message: "Enter an email for the admin user",
2083
- initialValue: "admin@example.com",
2084
- validate: (value) => !value ? "Email is required" : !value.includes("@") ? "Invalid email" : void 0
2085
- });
2086
- },
2087
- password: () => {
2088
- if (options.password) return Promise.resolve(options.password);
2089
- return p5.password({
2090
- message: "Enter a password for the admin user (at least 8 characters)",
2091
- validate: (value) => !value ? "Password is required" : value.length < 8 ? "Password must be at least 8 characters long" : void 0
2092
- });
2093
- }
2094
- },
2095
- { onCancel: onCancel2 }
2096
- );
2097
- }
2098
-
2099
- // src/commands/generate.ts
2100
- import { Command as Command9 } from "commander";
2101
-
2102
- // src/commands/generate/form.ts
2103
1930
  import { Command as Command4 } from "commander";
2104
- import * as p12 from "@clack/prompts";
2105
-
2106
- // src/lib/pattern-runner.ts
2107
- import path15 from "node:path";
2108
- import * as p7 from "@clack/prompts";
2109
- import { bySlug as bySlug2 } from "@velastack/patterns";
1931
+ import * as p8 from "@clack/prompts";
1932
+ import { detect as detect3, resolveCommand as resolveCommand3 } from "package-manager-detector";
2110
1933
 
2111
1934
  // src/lib/providers.ts
2112
- import process9 from "node:process";
2113
- import * as p6 from "@clack/prompts";
1935
+ import process8 from "node:process";
1936
+ import * as p5 from "@clack/prompts";
2114
1937
  import { bySlug } from "@velastack/patterns";
2115
1938
  function capabilityName(slug2) {
2116
1939
  return slug2.replace(/^enable-/, "");
@@ -2145,7 +1968,7 @@ function article(word) {
2145
1968
  return /^[aeiou]/i.test(word) ? "an" : "a";
2146
1969
  }
2147
1970
  function isInteractive() {
2148
- return Boolean(process9.stdout.isTTY) && !process9.env.CI;
1971
+ return Boolean(process8.stdout.isTTY) && !process8.env.CI;
2149
1972
  }
2150
1973
  function providerFlagInArgv(argv) {
2151
1974
  return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
@@ -2177,13 +2000,13 @@ async function resolveProvider(slug2, flagValue) {
2177
2000
  });
2178
2001
  if (decision.kind === "error") throw new Error(decision.message);
2179
2002
  if (decision.kind === "use") return decision.provider;
2180
- const selected = await p6.select({
2003
+ const selected = await p5.select({
2181
2004
  message: `Select ${patternName} provider`,
2182
2005
  options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
2183
2006
  });
2184
- if (p6.isCancel(selected)) {
2185
- p6.cancel("Operation cancelled.");
2186
- process9.exit(0);
2007
+ if (p5.isCancel(selected)) {
2008
+ p5.cancel("Operation cancelled.");
2009
+ process8.exit(0);
2187
2010
  }
2188
2011
  return providers.find((provider) => provider.id === selected);
2189
2012
  }
@@ -2191,7 +2014,7 @@ async function collectProviderEnv(provider) {
2191
2014
  const values = {};
2192
2015
  const interactive = isInteractive();
2193
2016
  for (const variable of provider.env ?? []) {
2194
- const existing = process9.env[variable.key];
2017
+ const existing = process8.env[variable.key];
2195
2018
  if (existing) {
2196
2019
  values[variable.key] = existing;
2197
2020
  continue;
@@ -2200,14 +2023,14 @@ async function collectProviderEnv(provider) {
2200
2023
  values[variable.key] = variable.default ?? "";
2201
2024
  continue;
2202
2025
  }
2203
- const value = await p6.text({
2026
+ const value = await p5.text({
2204
2027
  message: variable.label,
2205
2028
  placeholder: variable.placeholder,
2206
2029
  initialValue: variable.default
2207
2030
  });
2208
- if (p6.isCancel(value)) {
2209
- p6.cancel("Operation cancelled.");
2210
- process9.exit(0);
2031
+ if (p5.isCancel(value)) {
2032
+ p5.cancel("Operation cancelled.");
2033
+ process8.exit(0);
2211
2034
  }
2212
2035
  values[variable.key] = (value ?? "").trim();
2213
2036
  }
@@ -2217,92 +2040,212 @@ function missingEnvKeys(provider, values) {
2217
2040
  return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
2218
2041
  }
2219
2042
 
2220
- // src/lib/pattern-runner.ts
2221
- function toRelative(root, filePath) {
2222
- return path15.isAbsolute(filePath) ? path15.relative(root, filePath) : filePath;
2223
- }
2224
- var isSuccess = (f) => (f.status ?? "success") === "success";
2225
- async function runPattern(slug2, argv, input, report4) {
2226
- const pattern = bySlug2[slug2];
2227
- if (!pattern) {
2228
- throw new Error(`Unknown pattern: ${slug2}`);
2229
- }
2230
- checkProviderInput(pattern, argv, input);
2231
- const { workspaceRootDir, features } = await getWorkspace();
2232
- const log45 = p7.taskLog({ title: report4.task.title });
2233
- let result;
2234
- try {
2235
- result = await pattern.generate({
2236
- argv,
2237
- env: "runtime",
2238
- root: workspaceRootDir,
2239
- features,
2240
- input,
2241
- // Patterns no longer read the schema themselves: @velastack/pocketbase-codegen
2242
- // takes an injected client, and only the CLI knows how to reach (or spawn)
2243
- // a PocketBase for this workspace.
2244
- getCollections: async () => {
2245
- const { getCollections } = await import("@velastack/pocketbase-codegen");
2246
- let collections2 = [];
2247
- await withPocketbase(workspaceRootDir, async (pb) => {
2248
- collections2 = await getCollections(pb);
2249
- });
2250
- return collections2;
2251
- },
2252
- logger: { info: (message) => log45.message(message) }
2253
- });
2254
- log45.success(report4.task.success);
2255
- } catch (e) {
2256
- log45.error(report4.task.error);
2257
- throw e;
2043
+ // src/lib/link-on-create.ts
2044
+ var FREE_CMS_HINT = "Get a free CMS at https://velastack.dev";
2045
+ var PROJECT_ID_RE = /^[a-z0-9]{15}$/;
2046
+ var CMS_URL_RE = /^https?:\/\/\S+$/;
2047
+ var NOT_LOGGED_IN = "Not logged in. Run `vela login` to login, or set VELA_API_KEY.";
2048
+ var NO_CMS_WARNING = `No CMS configured: \`cmsEndpoint\` in src/lib/site.ts is empty, so the site shows its fallback copy. Pass \`--link new\`, \`--link <project-id>\` or \`--cms <url>\` to set it, or fill it in later. ${FREE_CMS_HINT}.`;
2049
+ function decideLink(request) {
2050
+ const { link: link2, needsCms, loggedIn, interactive } = request;
2051
+ if (link2 === "none") return { kind: "none" };
2052
+ if (link2 === "new") {
2053
+ return loggedIn ? { kind: "create" } : { kind: "error", message: NOT_LOGGED_IN };
2054
+ }
2055
+ if (link2 !== void 0) {
2056
+ return loggedIn ? { kind: "existing", projectId: link2 } : { kind: "error", message: NOT_LOGGED_IN };
2057
+ }
2058
+ if (!interactive) return { kind: "none", warn: needsCms ? NO_CMS_WARNING : void 0 };
2059
+ if (loggedIn) return { kind: "create" };
2060
+ return needsCms ? { kind: "prompt-cms" } : { kind: "none" };
2061
+ }
2062
+ function cmsEndpointFor(projectId) {
2063
+ return `${API_URL}/v1/projects/${projectId}/cms`;
2064
+ }
2065
+ function normalizeCmsUrl(url) {
2066
+ return url.trim().replace(/\/+$/, "");
2067
+ }
2068
+ function linkNextSteps(outcome) {
2069
+ const steps = [];
2070
+ const { linked, cmsEndpoint, cmsSource, templateCms, loggedIn, interactive } = outcome;
2071
+ if (templateCms && linked && cmsSource === "linked") {
2072
+ steps.push(
2073
+ `Add an editor at ${linked.dashboardUrl}/cms/editors, then open any page with \`?edit\` and sign in from the admin bar.`
2074
+ );
2075
+ } else if (cmsEndpoint) {
2076
+ steps.push("Open any page with `?edit` and sign in from the admin bar.");
2077
+ } else if (templateCms) {
2078
+ steps.push(
2079
+ `When you have a CMS, set \`cmsEndpoint\` in \`src/lib/site.ts\`. ${FREE_CMS_HINT}.`
2080
+ );
2258
2081
  }
2259
- const rel = (f) => toRelative(workspaceRootDir, f);
2260
- const files = [...result.creates, ...result.modifies, ...result.deletes];
2261
- const failures = files.filter((f) => !isSuccess(f)).map((f) => ({
2262
- path: rel(f.path),
2263
- status: f.status === "not-found" ? "not-found" : "failed",
2264
- message: f.message
2265
- }));
2266
- const created = result.creates.filter(isSuccess);
2267
- const modified = result.modifies.filter(isSuccess);
2268
- const deleted = result.deletes.filter(isSuccess);
2269
- const totalChanges = created.length + modified.length + deleted.length + result.components.length + result.packages.length + result.collections.length;
2270
- if (totalChanges === 0 && failures.length === 0) {
2271
- p7.log.info(`${pattern.title ?? slug2} produced no changes.`);
2272
- return;
2082
+ if (linked && !(templateCms && cmsSource === "linked")) {
2083
+ steps.push(
2084
+ `Run \`vela deploy\` when you're ready; the project is linked to ${linked.dashboardUrl}.`
2085
+ );
2086
+ } else if (!linked && interactive && !loggedIn && !templateCms) {
2087
+ steps.push("Run `vela login` then `vela link` to get a free velastack.app hostname on deploy.");
2273
2088
  }
2274
- reportResult({
2275
- summary: report4.summary ?? `Applied ${pattern.title ?? slug2}.`,
2276
- filesCreated: created.map((f) => rel(f.path)),
2277
- filesModified: modified.map((f) => rel(f.path)),
2278
- filesDeleted: deleted.map((f) => rel(f.path)),
2279
- componentsAdded: result.components,
2280
- packagesInstalled: result.packages,
2281
- collectionsAdded: result.collections.map((c) => c.name),
2282
- failures,
2283
- // Next steps assume the pattern applied; when part of it didn't, the
2284
- // remediation snippets above are the actual next step.
2285
- nextSteps: failures.length > 0 ? void 0 : report4.nextSteps
2286
- });
2089
+ return steps;
2287
2090
  }
2288
2091
 
2289
- // src/lib/ai-flow.ts
2290
- import fs18 from "node:fs";
2291
- import path17 from "node:path";
2292
- import * as p11 from "@clack/prompts";
2293
- import pc4 from "picocolors";
2092
+ // src/lib/link-project.ts
2093
+ import process9 from "node:process";
2094
+ import * as p6 from "@clack/prompts";
2095
+
2096
+ // src/lib/velastack-api.ts
2097
+ async function apiFetch(apiKey, pathAndQuery, init) {
2098
+ const headers = new Headers(init?.headers);
2099
+ headers.set("Authorization", `Bearer ${apiKey}`);
2100
+ if (init?.body && !headers.has("Content-Type")) {
2101
+ headers.set("Content-Type", "application/json");
2102
+ }
2103
+ const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
2104
+ if (res.status === 401) {
2105
+ throw new Error("API key invalid \u2014 run `vela login`");
2106
+ }
2107
+ if (res.status === 403) {
2108
+ const body = await res.text().catch(() => "");
2109
+ throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
2110
+ }
2111
+ if (!res.ok) {
2112
+ const body = await res.text().catch(() => "");
2113
+ throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
2114
+ }
2115
+ return await res.json();
2116
+ }
2117
+ async function getCurrentUser(apiKey) {
2118
+ const data = await apiFetch(
2119
+ apiKey,
2120
+ "/api/collections/users/records?perPage=1"
2121
+ );
2122
+ const user = data.items[0];
2123
+ if (!user) throw new Error("No user found. Run `vela login` to login.");
2124
+ return user;
2125
+ }
2126
+ async function listTeams(apiKey) {
2127
+ const data = await apiFetch(
2128
+ apiKey,
2129
+ "/api/collections/teams/records?perPage=200"
2130
+ );
2131
+ return data.items;
2132
+ }
2133
+ async function listProjects(apiKey) {
2134
+ const data = await apiFetch(
2135
+ apiKey,
2136
+ "/api/collections/projects/records?perPage=200&expand=team"
2137
+ );
2138
+ return data.items;
2139
+ }
2140
+ async function createProject(apiKey, args) {
2141
+ return apiFetch(apiKey, "/api/collections/projects/records", {
2142
+ method: "POST",
2143
+ body: JSON.stringify({
2144
+ name: args.name,
2145
+ team: args.teamId,
2146
+ user: args.userId,
2147
+ ...args.template ? { template: args.template } : {}
2148
+ })
2149
+ });
2150
+ }
2151
+ async function registerServer(apiKey, input) {
2152
+ return apiFetch(apiKey, "/v1/servers", {
2153
+ method: "POST",
2154
+ body: JSON.stringify(input)
2155
+ });
2156
+ }
2157
+ async function startDeployment(apiKey, projectId, input) {
2158
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
2159
+ method: "POST",
2160
+ body: JSON.stringify(input)
2161
+ });
2162
+ }
2163
+ async function finishDeployment(apiKey, projectId, deploymentId, input) {
2164
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
2165
+ method: "PATCH",
2166
+ body: JSON.stringify(input)
2167
+ });
2168
+ }
2169
+ async function destroyEnvironment(apiKey, projectId, envTag) {
2170
+ return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
2171
+ method: "DELETE"
2172
+ });
2173
+ }
2174
+
2175
+ // src/lib/link-project.ts
2176
+ function dashboardUrl(teamSlug, projectSlug) {
2177
+ return teamSlug && projectSlug ? `${API_URL}/${teamSlug}/${projectSlug}` : API_URL;
2178
+ }
2179
+ async function pickTeam(teams3) {
2180
+ if (teams3.length === 1) return teams3[0];
2181
+ const choice = await p6.select({
2182
+ message: "Select a team",
2183
+ options: teams3.map((team) => ({
2184
+ value: team.id,
2185
+ label: team.is_personal ? `${team.name} (personal)` : team.name
2186
+ }))
2187
+ });
2188
+ if (p6.isCancel(choice)) {
2189
+ p6.cancel("Operation cancelled.");
2190
+ process9.exit(0);
2191
+ }
2192
+ return teams3.find((team) => team.id === choice);
2193
+ }
2194
+ async function resolveTeam(teams3, options) {
2195
+ if (options.teamId) {
2196
+ const team = teams3.find((candidate) => candidate.id === options.teamId);
2197
+ if (!team) {
2198
+ throw new Error(
2199
+ `You are not a member of team ${options.teamId}. Omit --team to use your personal team.`
2200
+ );
2201
+ }
2202
+ return team;
2203
+ }
2204
+ if (teams3.length === 0) throw new Error("No team found on velastack.dev for this account.");
2205
+ const personal = teams3.find((team) => team.is_personal);
2206
+ if (personal) return personal;
2207
+ if (options.interactive) return pickTeam(teams3);
2208
+ throw new Error("Several teams and no personal one: pass --team <id>.");
2209
+ }
2210
+ async function linkNewProject(apiKey, args) {
2211
+ const [user, teams3] = await Promise.all([getCurrentUser(apiKey), listTeams(apiKey)]);
2212
+ const team = await resolveTeam(teams3, { teamId: args.teamId, interactive: args.interactive });
2213
+ const project = await createProject(apiKey, {
2214
+ name: args.name,
2215
+ teamId: team.id,
2216
+ userId: user.id,
2217
+ template: args.template
2218
+ });
2219
+ return toLinked(project, team);
2220
+ }
2221
+ async function linkExistingProject(apiKey, projectId) {
2222
+ const projects = await listProjects(apiKey);
2223
+ const project = projects.find((candidate) => candidate.id === projectId);
2224
+ if (!project) {
2225
+ throw new Error(`No project ${projectId} on velastack.dev for this account.`);
2226
+ }
2227
+ return toLinked(project, project.expand?.team);
2228
+ }
2229
+ function toLinked(project, team) {
2230
+ return {
2231
+ projectId: project.id,
2232
+ teamId: project.team,
2233
+ projectName: project.name,
2234
+ dashboardUrl: dashboardUrl(team?.slug, project.slug)
2235
+ };
2236
+ }
2294
2237
 
2295
2238
  // src/lib/project-config.ts
2296
- import fs17 from "node:fs";
2297
- import path16 from "node:path";
2239
+ import fs16 from "node:fs";
2240
+ import path14 from "node:path";
2298
2241
  function projectConfigPath(workspaceRootDir) {
2299
- return path16.join(workspaceRootDir, ".vela", "project.json");
2242
+ return path14.join(workspaceRootDir, ".vela", "project.json");
2300
2243
  }
2301
2244
  function readProjectConfig(workspaceRootDir) {
2302
2245
  const file = projectConfigPath(workspaceRootDir);
2303
- if (!fs17.existsSync(file)) return null;
2246
+ if (!fs16.existsSync(file)) return null;
2304
2247
  try {
2305
- const parsed = JSON.parse(fs17.readFileSync(file, "utf8"));
2248
+ const parsed = JSON.parse(fs16.readFileSync(file, "utf8"));
2306
2249
  if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
2307
2250
  return null;
2308
2251
  }
@@ -2317,17 +2260,483 @@ function readProjectConfig(workspaceRootDir) {
2317
2260
  }
2318
2261
  function writeProjectConfig(workspaceRootDir, config) {
2319
2262
  const file = projectConfigPath(workspaceRootDir);
2320
- fs17.mkdirSync(path16.dirname(file), { recursive: true });
2263
+ fs16.mkdirSync(path14.dirname(file), { recursive: true });
2321
2264
  let existing = {};
2322
- if (fs17.existsSync(file)) {
2265
+ if (fs16.existsSync(file)) {
2323
2266
  try {
2324
- existing = JSON.parse(fs17.readFileSync(file, "utf8"));
2267
+ existing = JSON.parse(fs16.readFileSync(file, "utf8"));
2325
2268
  } catch {
2326
2269
  }
2327
2270
  }
2328
- fs17.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2271
+ fs16.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2272
+ }
2273
+
2274
+ // src/commands/login.ts
2275
+ import os3 from "node:os";
2276
+ import process10 from "node:process";
2277
+ import { Command as Command3 } from "commander";
2278
+ import * as p7 from "@clack/prompts";
2279
+ import makeFetchCookie from "fetch-cookie";
2280
+ var login = new Command3("login").description("login to velastack.dev").configureHelp(helpConfig).action(
2281
+ () => runCommand(async () => {
2282
+ await loginInteractively();
2283
+ p7.log.success("Logged in to velastack.dev");
2284
+ }, "Failed to login.")
2285
+ );
2286
+ async function loginInteractively() {
2287
+ const { email: email3, password: password11 } = await p7.group(
2288
+ {
2289
+ email: () => p7.text({ message: "Email" }),
2290
+ password: () => p7.password({ message: "Password" })
2291
+ },
2292
+ {
2293
+ onCancel: () => {
2294
+ p7.cancel("Operation cancelled.");
2295
+ process10.exit(0);
2296
+ }
2297
+ }
2298
+ );
2299
+ const fetchCookie = makeFetchCookie(fetch);
2300
+ const loginRes = await fetchCookie(`${API_URL}/login`, {
2301
+ method: "POST",
2302
+ headers: {
2303
+ "Content-Type": "application/x-www-form-urlencoded",
2304
+ Origin: API_URL
2305
+ },
2306
+ body: new URLSearchParams({ type: "password", email: email3, password: password11 }).toString()
2307
+ });
2308
+ if (!loginRes.headers.get("Set-Cookie")) {
2309
+ throw new Error(
2310
+ "Run `vela signup` to create an account or reset at https://velastack.dev/reset"
2311
+ );
2312
+ }
2313
+ const apiKey = await issueApiKey(fetchCookie);
2314
+ writeConfig({ apiKey });
2315
+ return apiKey;
2316
+ }
2317
+ async function issueApiKey(fetchCookie) {
2318
+ const label4 = `CLI - ${os3.hostname()}`;
2319
+ await fetchCookie(`${API_URL}/api-keys/new`, {
2320
+ method: "POST",
2321
+ headers: {
2322
+ "Content-Type": "application/x-www-form-urlencoded",
2323
+ Origin: API_URL
2324
+ },
2325
+ body: new URLSearchParams({ label: label4 }).toString()
2326
+ });
2327
+ const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
2328
+ const apiKey = extractApiKey(cookie);
2329
+ if (!apiKey) {
2330
+ throw new Error("Failed to create API key. Try again or contact support.");
2331
+ }
2332
+ const [id] = apiKey.split(".");
2333
+ const res = await fetchCookie(`${API_URL}/api/collections/api_keys/records`, {
2334
+ headers: { Authorization: `Bearer ${apiKey}` }
2335
+ });
2336
+ const data = await res.json();
2337
+ for (const item of data.items) {
2338
+ if (item.label === label4 && item.id !== id) {
2339
+ await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
2340
+ method: "DELETE",
2341
+ headers: { Authorization: `Bearer ${apiKey}` }
2342
+ });
2343
+ }
2344
+ }
2345
+ return apiKey;
2346
+ }
2347
+ function extractApiKey(cookie) {
2348
+ const flashCookie = cookie.split(";").find((c) => c.trim().startsWith("flash="));
2349
+ if (!flashCookie) return null;
2350
+ const decoded = decodeURIComponent(flashCookie.split("=")[1]);
2351
+ return JSON.parse(decoded).apiKey;
2352
+ }
2353
+
2354
+ // src/commands/create.ts
2355
+ function optionsSchema2(listing) {
2356
+ const names = listing.templates.map((template) => template.name);
2357
+ let choices2 = `must be one of: ${templateChoicesMessage(listing.templates)}`;
2358
+ if (listing.registryError) {
2359
+ choices2 += ` (could not reach the template registry: ${listing.registryError})`;
2360
+ }
2361
+ return v4.strictObject({
2362
+ install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
2363
+ template: v4.optional(v4.picklist(names, choices2)),
2364
+ name: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
2365
+ email: v4.optional(v4.pipe(v4.string(), v4.email("must be a valid email address"))),
2366
+ password: v4.optional(v4.pipe(v4.string(), v4.minLength(8, "must be at least 8 characters long"))),
2367
+ link: v4.optional(
2368
+ v4.pipe(
2369
+ v4.string(),
2370
+ v4.check(
2371
+ (value) => value === "new" || value === "none" || PROJECT_ID_RE.test(value),
2372
+ "must be `new`, `none` or a velastack.dev project id"
2373
+ )
2374
+ )
2375
+ ),
2376
+ team: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
2377
+ cms: v4.optional(
2378
+ v4.pipe(v4.string(), v4.trim(), v4.regex(CMS_URL_RE, "must be an absolute CMS URL"))
2379
+ )
2380
+ });
2381
+ }
2382
+ function checkFlagsForTemplate(template, options) {
2383
+ if (!template.backend && (options.email || options.password)) {
2384
+ throw new Error(
2385
+ `--email and --password don't apply to the ${template.name} template \u2014 it has no backend.`
2386
+ );
2387
+ }
2388
+ if (options.cms !== void 0 && !template.cms) {
2389
+ throw new Error(
2390
+ `--cms doesn't apply to the ${template.name} template \u2014 it reads no copy from a CMS.`
2391
+ );
2392
+ }
2393
+ if (options.team !== void 0 && options.link !== "new") {
2394
+ throw new Error("--team only applies together with --link new.");
2395
+ }
2396
+ }
2397
+ var create = new Command4("create").description("scaffold a new velastack project").argument("[path]", "where the project will be created").option("--template <type>", "template to scaffold (built-in or from the registry)", "minimal").option("--no-install", "skip installing dependencies").option("--name <name>", "app name (used for emails, etc)").option("--email <email>", "email of the admin user").option("--password <password>", "password of the admin user").option(
2398
+ "--link <new|none|project-id>",
2399
+ "link to a velastack.dev project: create one, skip, or use an existing project id (default: create when logged in at a terminal)"
2400
+ ).option("--team <id>", "velastack.dev team for `--link new` (default: your personal team)").option(
2401
+ "--cms <url>",
2402
+ "read from a CMS at this URL instead of the linked project's (CMS-ready templates only)"
2403
+ ).addOption(installOption).configureHelp(helpConfig).action((projectPath, rawOpts) => {
2404
+ return runCommand(async () => {
2405
+ const listing = await listAllTemplates();
2406
+ const options = parseOptions(optionsSchema2(listing), rawOpts);
2407
+ const { directory, packageManager: packageManager2, name, template, link: link2 } = await createProject2(
2408
+ projectPath,
2409
+ options,
2410
+ listing
2411
+ );
2412
+ const relative = path15.relative(process11.cwd(), directory);
2413
+ const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
2414
+ const nextSteps = [];
2415
+ if (relative !== "") {
2416
+ const hasSpaces = relative.includes(" ");
2417
+ nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
2418
+ }
2419
+ if (!packageManager2) {
2420
+ const resolved = resolveCommand3(pm, "install", []);
2421
+ if (resolved) {
2422
+ nextSteps.push(
2423
+ `\`${resolved.command} ${resolved.args.join(" ")}\` to install dependencies`
2424
+ );
2425
+ }
2426
+ }
2427
+ const runDev = resolveCommand3(pm, "run", ["dev", "--open"]);
2428
+ if (runDev) {
2429
+ nextSteps.push(
2430
+ `\`${runDev.command} ${runDev.args.join(" ")}\` to start the dev server (Ctrl-C to stop)`
2431
+ );
2432
+ }
2433
+ if (template.nextSteps) {
2434
+ nextSteps.push(...template.nextSteps);
2435
+ } else if (template.backend) {
2436
+ nextSteps.push("Run `vela generate scaffold <model>` to generate your first CRUD pages.");
2437
+ } else {
2438
+ nextSteps.push(
2439
+ "Set your deployed URL in `src/lib/site.ts` before building for production."
2440
+ );
2441
+ nextSteps.push("Run `vela ui add <component>` to add UI components.");
2442
+ }
2443
+ nextSteps.push(...linkNextSteps(link2));
2444
+ nextSteps.push("Stuck? Visit https://docs.velastack.dev");
2445
+ reportResult({
2446
+ summary: `Created ${name} at ${directory}.`,
2447
+ nextSteps
2448
+ });
2449
+ }, "Failed to create project.");
2450
+ });
2451
+ async function createProject2(cwdArg, options, listing) {
2452
+ const onCancel2 = () => {
2453
+ p8.cancel("Operation cancelled.");
2454
+ process11.exit(0);
2455
+ };
2456
+ const template = findTemplate(listing, options.template ?? DEFAULT_TEMPLATE);
2457
+ checkFlagsForTemplate(template, options);
2458
+ let directory;
2459
+ if (cwdArg) {
2460
+ directory = path15.resolve(cwdArg);
2461
+ } else {
2462
+ const answer = await p8.text({
2463
+ message: "Where would you like your project to be created?",
2464
+ placeholder: " (hit Enter to use current directory)",
2465
+ defaultValue: "./"
2466
+ });
2467
+ if (p8.isCancel(answer)) onCancel2();
2468
+ directory = path15.resolve(answer);
2469
+ }
2470
+ if (fs17.existsSync(directory) && fs17.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
2471
+ const force = await p8.confirm({
2472
+ message: "Directory not empty. Continue?",
2473
+ initialValue: false
2474
+ });
2475
+ if (p8.isCancel(force) || !force) onCancel2();
2476
+ }
2477
+ const dirName = path15.basename(directory);
2478
+ const { name } = await p8.group(
2479
+ {
2480
+ name: () => {
2481
+ if (options.name) return Promise.resolve(options.name);
2482
+ return p8.text({
2483
+ message: "App name (used for emails, etc)",
2484
+ initialValue: dirName || "SvelteKit",
2485
+ validate: (value) => value?.trim() ? void 0 : "App name is required"
2486
+ });
2487
+ }
2488
+ },
2489
+ { onCancel: onCancel2 }
2490
+ );
2491
+ const credentials = template.backend ? await promptCredentials(options, onCancel2) : void 0;
2492
+ const link2 = await linkOnCreate(name, template, options, onCancel2);
2493
+ const projectPath = directory;
2494
+ if (template.source === "remote") p8.log.step(`Downloading template ${template.name}...`);
2495
+ const resolved = await resolveTemplate(template);
2496
+ try {
2497
+ copyTemplate(resolved, projectPath);
2498
+ applyTemplateFiles(projectPath, {
2499
+ appName: name,
2500
+ cliVersion: package_default.version,
2501
+ cmsEndpoint: link2.cmsEndpoint
2502
+ });
2503
+ } finally {
2504
+ resolved.cleanup();
2505
+ }
2506
+ if (!fs17.existsSync(path15.join(projectPath, "package.json"))) {
2507
+ throw new Error(`Template ${template.name} is missing package.template.json`);
2508
+ }
2509
+ if (link2.linked) {
2510
+ const { projectId, teamId, projectName } = link2.linked;
2511
+ writeProjectConfig(projectPath, { projectId, teamId, projectName });
2512
+ }
2513
+ p8.log.success("Project created");
2514
+ let packageManager2;
2515
+ if (options.install !== false) {
2516
+ const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
2517
+ if (pm) {
2518
+ const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
2519
+ addPnpmBuildDependencies(projectPath, pm, builds);
2520
+ await installDependencies(pm, projectPath);
2521
+ packageManager2 = pm;
2522
+ }
2523
+ }
2524
+ if (credentials) {
2525
+ const { email: email3, password: password11 } = credentials;
2526
+ p8.log.step("Initializing PocketBase...");
2527
+ await createSuperuser(projectPath, email3, password11);
2528
+ await withPocketbase(
2529
+ projectPath,
2530
+ async (pb) => {
2531
+ await pb.settings.update({
2532
+ meta: { appName: name, appURL: "http://localhost:5173" }
2533
+ });
2534
+ },
2535
+ { email: email3, password: password11 }
2536
+ );
2537
+ writeEnvFile(
2538
+ projectPath,
2539
+ {
2540
+ POCKETBASE_SUPERUSER_EMAIL: email3,
2541
+ POCKETBASE_SUPERUSER_PASSWORD: password11
2542
+ },
2543
+ ["PocketBase superuser credentials \u2014 used by `vela` commands"]
2544
+ );
2545
+ p8.log.success("PocketBase initialized");
2546
+ }
2547
+ return { directory: projectPath, packageManager: packageManager2, name, template, link: link2 };
2548
+ }
2549
+ async function linkOnCreate(name, template, options, onCancel2) {
2550
+ const templateCms = template.cms === true;
2551
+ const interactive = isInteractive();
2552
+ const loggedIn = readApiKey() !== null;
2553
+ const outcome = {
2554
+ cmsEndpoint: options.cms ? normalizeCmsUrl(options.cms) : "",
2555
+ cmsSource: options.cms ? "flag" : "none",
2556
+ templateCms,
2557
+ loggedIn,
2558
+ interactive
2559
+ };
2560
+ let decision = decideLink({
2561
+ link: options.link,
2562
+ needsCms: templateCms && !options.cms,
2563
+ loggedIn,
2564
+ interactive
2565
+ });
2566
+ if (decision.kind === "prompt-cms") {
2567
+ const choice = await promptCms(onCancel2);
2568
+ if (choice.kind === "url") {
2569
+ outcome.cmsEndpoint = choice.url;
2570
+ outcome.cmsSource = "prompt";
2571
+ decision = { kind: "none" };
2572
+ } else {
2573
+ decision = { kind: choice.kind === "login" ? "login-then-create" : "none" };
2574
+ }
2575
+ }
2576
+ if (decision.kind === "error") throw new Error(decision.message);
2577
+ let apiKey;
2578
+ if (decision.kind === "login-then-create") {
2579
+ apiKey = await loginInteractively();
2580
+ outcome.loggedIn = true;
2581
+ decision = { kind: "create" };
2582
+ }
2583
+ let linked;
2584
+ if (decision.kind === "create") {
2585
+ p8.log.step(
2586
+ options.link === "new" ? "Linking to a new velastack.dev project..." : "Linking to a new velastack.dev project (pass `--link none` to skip)..."
2587
+ );
2588
+ linked = await linkNewProject(apiKey ?? requireApiKey(), {
2589
+ name,
2590
+ template: template.name,
2591
+ teamId: options.team,
2592
+ interactive
2593
+ });
2594
+ } else if (decision.kind === "existing") {
2595
+ p8.log.step("Linking to velastack.dev...");
2596
+ linked = await linkExistingProject(requireApiKey(), decision.projectId);
2597
+ } else if (decision.kind === "none" && decision.warn) {
2598
+ p8.log.warn(decision.warn);
2599
+ }
2600
+ if (linked) {
2601
+ outcome.linked = linked;
2602
+ p8.log.success(`Linked to ${linked.projectName} (${linked.dashboardUrl})`);
2603
+ if (templateCms && !outcome.cmsEndpoint) {
2604
+ outcome.cmsEndpoint = cmsEndpointFor(linked.projectId);
2605
+ outcome.cmsSource = "linked";
2606
+ p8.log.success(`CMS: ${outcome.cmsEndpoint}`);
2607
+ }
2608
+ }
2609
+ return outcome;
2610
+ }
2611
+ async function promptCms(onCancel2) {
2612
+ p8.note(`This template reads its copy from a hosted CMS.
2613
+ ${FREE_CMS_HINT}.`, "CMS");
2614
+ const choice = await p8.select({
2615
+ message: "Where should the site read its content from?",
2616
+ options: [
2617
+ { value: "login", label: "Log in to velastack.dev and create one", hint: "free" },
2618
+ { value: "url", label: "Use an existing CMS URL" },
2619
+ { value: "skip", label: "Skip for now", hint: "the site shows its fallback copy" }
2620
+ ]
2621
+ });
2622
+ if (p8.isCancel(choice)) onCancel2();
2623
+ if (choice !== "url") return { kind: choice };
2624
+ const url = await p8.text({
2625
+ message: "CMS URL",
2626
+ placeholder: "https://velastack.dev/v1/projects/<project>/cms",
2627
+ validate: (value) => CMS_URL_RE.test(value?.trim() ?? "") ? void 0 : "Enter an absolute http(s) URL"
2628
+ });
2629
+ if (p8.isCancel(url)) onCancel2();
2630
+ return { kind: "url", url: normalizeCmsUrl(url) };
2631
+ }
2632
+ function promptCredentials(options, onCancel2) {
2633
+ return p8.group(
2634
+ {
2635
+ email: () => {
2636
+ if (options.email) return Promise.resolve(options.email);
2637
+ return p8.text({
2638
+ message: "Enter an email for the admin user",
2639
+ initialValue: "admin@example.com",
2640
+ validate: (value) => !value ? "Email is required" : !value.includes("@") ? "Invalid email" : void 0
2641
+ });
2642
+ },
2643
+ password: () => {
2644
+ if (options.password) return Promise.resolve(options.password);
2645
+ return p8.password({
2646
+ message: "Enter a password for the admin user (at least 8 characters)",
2647
+ validate: (value) => !value ? "Password is required" : value.length < 8 ? "Password must be at least 8 characters long" : void 0
2648
+ });
2649
+ }
2650
+ },
2651
+ { onCancel: onCancel2 }
2652
+ );
2653
+ }
2654
+
2655
+ // src/commands/generate.ts
2656
+ import { Command as Command10 } from "commander";
2657
+
2658
+ // src/commands/generate/form.ts
2659
+ import { Command as Command5 } from "commander";
2660
+ import * as p14 from "@clack/prompts";
2661
+
2662
+ // src/lib/pattern-runner.ts
2663
+ import path16 from "node:path";
2664
+ import * as p9 from "@clack/prompts";
2665
+ import { bySlug as bySlug2 } from "@velastack/patterns";
2666
+ function toRelative(root, filePath) {
2667
+ return path16.isAbsolute(filePath) ? path16.relative(root, filePath) : filePath;
2668
+ }
2669
+ var isSuccess = (f) => (f.status ?? "success") === "success";
2670
+ async function runPattern(slug2, argv, input, report4) {
2671
+ const pattern = bySlug2[slug2];
2672
+ if (!pattern) {
2673
+ throw new Error(`Unknown pattern: ${slug2}`);
2674
+ }
2675
+ checkProviderInput(pattern, argv, input);
2676
+ const { workspaceRootDir, features } = await getWorkspace();
2677
+ const log45 = p9.taskLog({ title: report4.task.title });
2678
+ let result;
2679
+ try {
2680
+ result = await pattern.generate({
2681
+ argv,
2682
+ env: "runtime",
2683
+ root: workspaceRootDir,
2684
+ features,
2685
+ input,
2686
+ // Patterns no longer read the schema themselves: @velastack/pocketbase-codegen
2687
+ // takes an injected client, and only the CLI knows how to reach (or spawn)
2688
+ // a PocketBase for this workspace.
2689
+ getCollections: async () => {
2690
+ const { getCollections } = await import("@velastack/pocketbase-codegen");
2691
+ let collections2 = [];
2692
+ await withPocketbase(workspaceRootDir, async (pb) => {
2693
+ collections2 = await getCollections(pb);
2694
+ });
2695
+ return collections2;
2696
+ },
2697
+ logger: { info: (message) => log45.message(message) }
2698
+ });
2699
+ log45.success(report4.task.success);
2700
+ } catch (e) {
2701
+ log45.error(report4.task.error);
2702
+ throw e;
2703
+ }
2704
+ const rel = (f) => toRelative(workspaceRootDir, f);
2705
+ const files = [...result.creates, ...result.modifies, ...result.deletes];
2706
+ const failures = files.filter((f) => !isSuccess(f)).map((f) => ({
2707
+ path: rel(f.path),
2708
+ status: f.status === "not-found" ? "not-found" : "failed",
2709
+ message: f.message
2710
+ }));
2711
+ const created = result.creates.filter(isSuccess);
2712
+ const modified = result.modifies.filter(isSuccess);
2713
+ const deleted = result.deletes.filter(isSuccess);
2714
+ const totalChanges = created.length + modified.length + deleted.length + result.components.length + result.packages.length + result.collections.length;
2715
+ if (totalChanges === 0 && failures.length === 0) {
2716
+ p9.log.info(`${pattern.title ?? slug2} produced no changes.`);
2717
+ return;
2718
+ }
2719
+ reportResult({
2720
+ summary: report4.summary ?? `Applied ${pattern.title ?? slug2}.`,
2721
+ filesCreated: created.map((f) => rel(f.path)),
2722
+ filesModified: modified.map((f) => rel(f.path)),
2723
+ filesDeleted: deleted.map((f) => rel(f.path)),
2724
+ componentsAdded: result.components,
2725
+ packagesInstalled: result.packages,
2726
+ collectionsAdded: result.collections.map((c) => c.name),
2727
+ failures,
2728
+ // Next steps assume the pattern applied; when part of it didn't, the
2729
+ // remediation snippets above are the actual next step.
2730
+ nextSteps: failures.length > 0 ? void 0 : report4.nextSteps
2731
+ });
2329
2732
  }
2330
2733
 
2734
+ // src/lib/ai-flow.ts
2735
+ import fs18 from "node:fs";
2736
+ import path17 from "node:path";
2737
+ import * as p13 from "@clack/prompts";
2738
+ import pc4 from "picocolors";
2739
+
2331
2740
  // src/lib/ai-client.ts
2332
2741
  async function aiPost(workspaceRootDir, endpoint, body) {
2333
2742
  const apiKey = requireApiKey();
@@ -2362,14 +2771,14 @@ var aiSchema = (workspaceRootDir, body) => aiPost(workspaceRootDir, "schema", bo
2362
2771
  var aiForm = (workspaceRootDir, body) => aiPost(workspaceRootDir, "form", body);
2363
2772
 
2364
2773
  // src/lib/ai-loop.ts
2365
- import * as p8 from "@clack/prompts";
2774
+ import * as p10 from "@clack/prompts";
2366
2775
  async function aiLoop(opts) {
2367
2776
  let prompt = opts.initialPrompt;
2368
2777
  let history = [];
2369
2778
  let attempt = 0;
2370
2779
  while (true) {
2371
2780
  attempt++;
2372
- const spinner7 = p8.spinner();
2781
+ const spinner7 = p10.spinner();
2373
2782
  spinner7.start(`${opts.stageLabel} (${attempt > 1 ? "iteration " + attempt : "first pass"})\u2026`);
2374
2783
  let result;
2375
2784
  let turn;
@@ -2383,12 +2792,12 @@ async function aiLoop(opts) {
2383
2792
  throw e;
2384
2793
  }
2385
2794
  opts.renderPreview(result);
2386
- const next = await p8.text({
2795
+ const next = await p10.text({
2387
2796
  message: "Refine the result, or press Enter to apply.",
2388
2797
  placeholder: opts.refinePlaceholder,
2389
2798
  defaultValue: ""
2390
2799
  });
2391
- if (p8.isCancel(next)) return null;
2800
+ if (p10.isCancel(next)) return null;
2392
2801
  const trimmed = (typeof next === "string" ? next : "").trim();
2393
2802
  if (trimmed === "") return result;
2394
2803
  history = turn;
@@ -2397,7 +2806,7 @@ async function aiLoop(opts) {
2397
2806
  }
2398
2807
 
2399
2808
  // src/lib/ai-existing-models.ts
2400
- import * as p9 from "@clack/prompts";
2809
+ import * as p11 from "@clack/prompts";
2401
2810
  async function loadExistingModels(workspaceRootDir) {
2402
2811
  let result = [];
2403
2812
  try {
@@ -2422,7 +2831,7 @@ async function loadExistingModels(workspaceRootDir) {
2422
2831
  });
2423
2832
  } catch (e) {
2424
2833
  const msg = e instanceof Error ? e.message : String(e);
2425
- p9.log.warn(
2834
+ p11.log.warn(
2426
2835
  `Could not load existing schema from PocketBase (${msg}). The AI agent will design without that context.`
2427
2836
  );
2428
2837
  return [];
@@ -2431,7 +2840,7 @@ async function loadExistingModels(workspaceRootDir) {
2431
2840
  }
2432
2841
 
2433
2842
  // src/lib/ai-to-argv.ts
2434
- import * as p10 from "@clack/prompts";
2843
+ import * as p12 from "@clack/prompts";
2435
2844
  var PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["text", "number", "bool", "email", "date", "url", "file"]);
2436
2845
  function singularize(name) {
2437
2846
  if (name.endsWith("ies") && name.length > 3) return `${name.slice(0, -3)}y`;
@@ -2454,7 +2863,7 @@ function collectionSpecToArgv(spec) {
2454
2863
  for (const field of spec.fields) {
2455
2864
  const type = typeArg(field);
2456
2865
  if (type === null) {
2457
- p10.log.warn(
2866
+ p12.log.warn(
2458
2867
  `Skipping field "${field.name}" (type "${field.type}" cannot be represented as a pattern argument)`
2459
2868
  );
2460
2869
  continue;
@@ -2557,10 +2966,10 @@ function renderModel(spec) {
2557
2966
  const tail = extra.length > 0 ? " " + pc4.dim(extra.join(" ")) : "";
2558
2967
  lines.push(` ${f.name.padEnd(nameWidth)} ${f.type.padEnd(typeWidth)} ${required}${tail}`);
2559
2968
  }
2560
- p11.log.message(lines.join("\n"));
2969
+ p13.log.message(lines.join("\n"));
2561
2970
  }
2562
2971
  function renderLayout(layout) {
2563
- p11.log.message(renderGrid(layout));
2972
+ p13.log.message(renderGrid(layout));
2564
2973
  }
2565
2974
  async function runSchemaStage(opts) {
2566
2975
  const { workspaceRootDir } = await getWorkspace();
@@ -2607,7 +3016,7 @@ function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
2607
3016
  }
2608
3017
 
2609
3018
  // src/commands/generate/form.ts
2610
- var form = new Command4("form").description("generate a form from a model").argument("[model]", 'model name (e.g. "contact")').argument("[fields...]", 'field definitions (e.g. "name:text", "email:email")').option("--remote", "generate a form backed by a remote PocketBase collection").option(
3019
+ var form = new Command5("form").description("generate a form from a model").argument("[model]", 'model name (e.g. "contact")').argument("[fields...]", 'field definitions (e.g. "name:text", "email:email")').option("--remote", "generate a form backed by a remote PocketBase collection").option(
2611
3020
  "--route <route>",
2612
3021
  'place the form at a custom route (e.g. "(app)/[team_id]/projects/new"). Defaults to the model name under (app)/(public).'
2613
3022
  ).option(
@@ -2624,12 +3033,12 @@ var form = new Command4("form").description("generate a form from a model").argu
2624
3033
  }
2625
3034
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "form" });
2626
3035
  if (!stage2) {
2627
- p12.cancel("Aborted before any files were written.");
3036
+ p14.cancel("Aborted before any files were written.");
2628
3037
  return;
2629
3038
  }
2630
3039
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2631
3040
  if (!layout) {
2632
- p12.cancel("Aborted before any files were written.");
3041
+ p14.cancel("Aborted before any files were written.");
2633
3042
  return;
2634
3043
  }
2635
3044
  argv = specToArgv(stage2.model);
@@ -2670,9 +3079,9 @@ var form = new Command4("form").description("generate a form from a model").argu
2670
3079
  );
2671
3080
 
2672
3081
  // src/commands/generate/schema.ts
2673
- import { Command as Command5 } from "commander";
2674
- import * as p13 from "@clack/prompts";
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(
3082
+ import { Command as Command6 } from "commander";
3083
+ import * as p15 from "@clack/prompts";
3084
+ var schema = new Command6("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(
2676
3085
  (model, fields, options) => runCommand(async () => {
2677
3086
  let argv;
2678
3087
  let modelName;
@@ -2682,7 +3091,7 @@ var schema = new Command5("schema").description("generate a schema from a model"
2682
3091
  }
2683
3092
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "schema" });
2684
3093
  if (!stage2) {
2685
- p13.cancel("Aborted before any files were written.");
3094
+ p15.cancel("Aborted before any files were written.");
2686
3095
  return;
2687
3096
  }
2688
3097
  argv = specToArgv(stage2.model);
@@ -2715,8 +3124,8 @@ var schema = new Command5("schema").description("generate a schema from a model"
2715
3124
  );
2716
3125
 
2717
3126
  // src/commands/generate/resource.ts
2718
- import { Command as Command6 } from "commander";
2719
- var resource = new Command6("resource").description("generate a resource (model + CRUD pages)").argument("<model>", "model name").argument("[fields...]", "field definitions").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3127
+ import { Command as Command7 } from "commander";
3128
+ var resource = new Command7("resource").description("generate a resource (model + CRUD pages)").argument("<model>", "model name").argument("[fields...]", "field definitions").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2720
3129
  (model, fields) => runCommand(
2721
3130
  () => runPattern(
2722
3131
  "generate-resource",
@@ -2741,9 +3150,9 @@ var resource = new Command6("resource").description("generate a resource (model
2741
3150
  );
2742
3151
 
2743
3152
  // src/commands/generate/scaffold.ts
2744
- import { Command as Command7 } from "commander";
2745
- import * as p14 from "@clack/prompts";
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(
3153
+ import { Command as Command8 } from "commander";
3154
+ import * as p16 from "@clack/prompts";
3155
+ var scaffold = new Command8("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(
2747
3156
  "--route <route>",
2748
3157
  'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under (app)/(public).'
2749
3158
  ).option(
@@ -2760,12 +3169,12 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2760
3169
  }
2761
3170
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "scaffold" });
2762
3171
  if (!stage2) {
2763
- p14.cancel("Aborted before any files were written.");
3172
+ p16.cancel("Aborted before any files were written.");
2764
3173
  return;
2765
3174
  }
2766
3175
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2767
3176
  if (!layout) {
2768
- p14.cancel("Aborted before any files were written.");
3177
+ p16.cancel("Aborted before any files were written.");
2769
3178
  return;
2770
3179
  }
2771
3180
  argv = specToArgv(stage2.model);
@@ -2807,8 +3216,8 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2807
3216
  );
2808
3217
 
2809
3218
  // src/commands/generate/migration.ts
2810
- import { Command as Command8 } from "commander";
2811
- var migration = new Command8("migration").description("generate a migration for an existing collection").argument("<collection>", "collection name").argument("<op>", "operation (add, remove, rename, references)").argument("[args...]", 'operation arguments (e.g. "birthday:date")').allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3219
+ import { Command as Command9 } from "commander";
3220
+ var migration = new Command9("migration").description("generate a migration for an existing collection").argument("<collection>", "collection name").argument("<op>", "operation (add, remove, rename, references)").argument("[args...]", 'operation arguments (e.g. "birthday:date")').allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2812
3221
  (collection, op, args) => runCommand(
2813
3222
  () => runPattern(
2814
3223
  "generate-migration",
@@ -2832,14 +3241,14 @@ var migration = new Command8("migration").description("generate a migration for
2832
3241
  );
2833
3242
 
2834
3243
  // src/commands/generate.ts
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);
3244
+ var generate = new Command10("generate").description("generate scaffolding for database models and forms").configureHelp(helpConfig).addCommand(form).addCommand(schema).addCommand(resource).addCommand(scaffold).addCommand(migration);
2836
3245
 
2837
3246
  // src/commands/enable.ts
2838
- import { Command as Command25 } from "commander";
3247
+ import { Command as Command26 } from "commander";
2839
3248
 
2840
3249
  // src/commands/enable/analytics.ts
2841
- import { Command as Command10 } from "commander";
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(
3250
+ import { Command as Command11 } from "commander";
3251
+ var analytics = new Command11("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
3252
  (opts, cmd) => runCommand(async () => {
2844
3253
  const provider = await resolveProvider("enable-analytics", opts.provider);
2845
3254
  const providerEnv = await collectProviderEnv(provider);
@@ -2869,8 +3278,8 @@ var analytics = new Command10("analytics").description("enable web analytics (Pl
2869
3278
  );
2870
3279
 
2871
3280
  // 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(
3281
+ import { Command as Command12 } from "commander";
3282
+ var auth = new Command12("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2874
3283
  (_opts, cmd) => runCommand(
2875
3284
  () => runPattern(
2876
3285
  "enable-auth",
@@ -2895,8 +3304,8 @@ var auth = new Command11("auth").description("enable authentication (email/passw
2895
3304
  );
2896
3305
 
2897
3306
  // src/commands/enable/api.ts
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(
3307
+ import { Command as Command13 } from "commander";
3308
+ var api = new Command13("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2900
3309
  (_opts, cmd) => runCommand(
2901
3310
  () => runPattern(
2902
3311
  "enable-api",
@@ -2921,8 +3330,8 @@ var api = new Command12("api").description("enable the PocketBase REST API").all
2921
3330
  );
2922
3331
 
2923
3332
  // src/commands/enable/api-keys.ts
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(
3333
+ import { Command as Command14 } from "commander";
3334
+ var apiKeys = new Command14("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2926
3335
  (_opts, cmd) => runCommand(
2927
3336
  () => runPattern(
2928
3337
  "enable-api-keys",
@@ -2947,8 +3356,8 @@ var apiKeys = new Command13("api-keys").description("enable API key management")
2947
3356
  );
2948
3357
 
2949
3358
  // src/commands/enable/backend.ts
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(
3359
+ import { Command as Command15 } from "commander";
3360
+ var backend = new Command15("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2952
3361
  (_opts, cmd) => runCommand(
2953
3362
  () => runPattern(
2954
3363
  "enable-backend",
@@ -2973,8 +3382,8 @@ var backend = new Command14("backend").description("enable the PocketBase backen
2973
3382
  );
2974
3383
 
2975
3384
  // src/commands/enable/i18n.ts
2976
- import { Command as Command15 } from "commander";
2977
- var i18n = new Command15("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3385
+ import { Command as Command16 } from "commander";
3386
+ var i18n = new Command16("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2978
3387
  (_opts, cmd) => runCommand(
2979
3388
  () => runPattern(
2980
3389
  "enable-i18n",
@@ -2999,8 +3408,8 @@ var i18n = new Command15("i18n").description("enable internationalization").allo
2999
3408
  );
3000
3409
 
3001
3410
  // src/commands/enable/teams.ts
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(
3411
+ import { Command as Command17 } from "commander";
3412
+ var teams = new Command17("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3004
3413
  (_opts, cmd) => runCommand(
3005
3414
  () => runPattern(
3006
3415
  "enable-teams",
@@ -3025,11 +3434,11 @@ var teams = new Command16("teams").description("enable team / multi-tenant suppo
3025
3434
  );
3026
3435
 
3027
3436
  // src/commands/enable/payments.ts
3028
- import process10 from "node:process";
3029
- import { Command as Command17 } from "commander";
3030
- import * as p15 from "@clack/prompts";
3437
+ import process12 from "node:process";
3438
+ import { Command as Command18 } from "commander";
3439
+ import * as p17 from "@clack/prompts";
3031
3440
  var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
3032
- var payments = new Command17("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3441
+ var payments = new Command18("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3033
3442
  (opts, cmd) => runCommand(async () => {
3034
3443
  const provider = await resolveProvider2(opts.provider, cmd.getOptionValueSource("provider"));
3035
3444
  const input = {
@@ -3064,21 +3473,21 @@ async function resolveProvider2(value, source) {
3064
3473
  }
3065
3474
  return value;
3066
3475
  }
3067
- const selected = await p15.select({
3476
+ const selected = await p17.select({
3068
3477
  message: "Which payment provider?",
3069
3478
  options: PROVIDERS,
3070
3479
  initialValue: "stripe"
3071
3480
  });
3072
- if (p15.isCancel(selected)) {
3073
- p15.cancel("Operation cancelled.");
3074
- process10.exit(0);
3481
+ if (p17.isCancel(selected)) {
3482
+ p17.cancel("Operation cancelled.");
3483
+ process12.exit(0);
3075
3484
  }
3076
3485
  return selected;
3077
3486
  }
3078
3487
  async function ensureWebhookSecret() {
3079
- const existing = process10.env.STRIPE_WEBHOOK_SECRET;
3488
+ const existing = process12.env.STRIPE_WEBHOOK_SECRET;
3080
3489
  if (existing) return existing;
3081
- p15.note(
3490
+ p17.note(
3082
3491
  [
3083
3492
  "Download the Stripe CLI (https://stripe.com/docs/stripe-cli), then run:",
3084
3493
  " stripe listen --forward-to localhost:5173/webhooks/stripe",
@@ -3090,7 +3499,7 @@ async function ensureWebhookSecret() {
3090
3499
  return promptPassword("Stripe webhook signing secret (whsec_...)");
3091
3500
  }
3092
3501
  async function ensurePriceId() {
3093
- p15.note(
3502
+ p17.note(
3094
3503
  [
3095
3504
  "Stripe checkout requires a product and price_id.",
3096
3505
  "If you have a demo product price_id, enter it below, or leave blank to create a demo one for you."
@@ -3098,36 +3507,36 @@ async function ensurePriceId() {
3098
3507
  "Stripe demo product",
3099
3508
  { format: (line) => line }
3100
3509
  );
3101
- const value = await p15.text({
3510
+ const value = await p17.text({
3102
3511
  message: "Stripe price_id (price_...)",
3103
3512
  placeholder: "leave blank to create a demo product"
3104
3513
  });
3105
- if (p15.isCancel(value)) {
3106
- p15.cancel("Operation cancelled.");
3107
- process10.exit(0);
3514
+ if (p17.isCancel(value)) {
3515
+ p17.cancel("Operation cancelled.");
3516
+ process12.exit(0);
3108
3517
  }
3109
3518
  return (value ?? "").trim();
3110
3519
  }
3111
3520
  async function ensureKey(envVar, message) {
3112
- const existing = process10.env[envVar];
3521
+ const existing = process12.env[envVar];
3113
3522
  if (existing) return existing;
3114
3523
  return promptPassword(message);
3115
3524
  }
3116
3525
  async function promptPassword(message) {
3117
- const value = await p15.password({
3526
+ const value = await p17.password({
3118
3527
  message,
3119
3528
  validate: (v10) => v10 && v10.length ? void 0 : "Required"
3120
3529
  });
3121
- if (p15.isCancel(value)) {
3122
- p15.cancel("Operation cancelled.");
3123
- process10.exit(0);
3530
+ if (p17.isCancel(value)) {
3531
+ p17.cancel("Operation cancelled.");
3532
+ process12.exit(0);
3124
3533
  }
3125
3534
  return value;
3126
3535
  }
3127
3536
 
3128
3537
  // src/commands/enable/subscriptions.ts
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(
3538
+ import { Command as Command19 } from "commander";
3539
+ var subscriptions = new Command19("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3131
3540
  (_opts, cmd) => runCommand(
3132
3541
  () => runPattern(
3133
3542
  "enable-subscriptions",
@@ -3152,8 +3561,8 @@ var subscriptions = new Command18("subscriptions").description("enable Stripe su
3152
3561
  );
3153
3562
 
3154
3563
  // src/commands/enable/notifications.ts
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(
3564
+ import { Command as Command20 } from "commander";
3565
+ var notifications = new Command20("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3157
3566
  (_opts, cmd) => runCommand(
3158
3567
  () => runPattern(
3159
3568
  "enable-notifications",
@@ -3178,15 +3587,15 @@ var notifications = new Command19("notifications").description("enable in-app no
3178
3587
  );
3179
3588
 
3180
3589
  // src/commands/enable/s3.ts
3181
- import process14 from "node:process";
3182
- import { Command as Command20 } from "commander";
3183
- import * as p18 from "@clack/prompts";
3590
+ import process16 from "node:process";
3591
+ import { Command as Command21 } from "commander";
3592
+ import * as p20 from "@clack/prompts";
3184
3593
  import pc8 from "picocolors";
3185
3594
 
3186
3595
  // src/lib/server-command.ts
3187
- import process13 from "node:process";
3596
+ import process15 from "node:process";
3188
3597
  import * as v6 from "valibot";
3189
- import * as p16 from "@clack/prompts";
3598
+ import * as p18 from "@clack/prompts";
3190
3599
  import pc5 from "picocolors";
3191
3600
 
3192
3601
  // src/lib/deploy-config.ts
@@ -3360,10 +3769,10 @@ import { resolveCommand as resolveCommand4 } from "package-manager-detector/comm
3360
3769
 
3361
3770
  // src/lib/ssh.ts
3362
3771
  import fs20 from "node:fs";
3363
- import os3 from "node:os";
3772
+ import os4 from "node:os";
3364
3773
  import path19 from "node:path";
3365
3774
  import crypto3 from "node:crypto";
3366
- import process11 from "node:process";
3775
+ import process13 from "node:process";
3367
3776
  import { spawn as spawn2 } from "node:child_process";
3368
3777
  var RemoteCommandError = class extends Error {
3369
3778
  exitCode;
@@ -3404,7 +3813,7 @@ var SshSession = class {
3404
3813
  }
3405
3814
  async open() {
3406
3815
  if (this.controlPath) return;
3407
- const dir = path19.join(os3.tmpdir(), "vela-ssh");
3816
+ const dir = path19.join(os4.tmpdir(), "vela-ssh");
3408
3817
  fs20.mkdirSync(dir, { recursive: true, mode: 448 });
3409
3818
  const socket = path19.join(dir, `${crypto3.randomBytes(6).toString("hex")}.sock`);
3410
3819
  this.controlPath = socket;
@@ -3641,17 +4050,17 @@ function spawnCapture(command, args, opts = {}) {
3641
4050
  const child = spawn2(command, args, {
3642
4051
  stdio,
3643
4052
  cwd: opts.cwd,
3644
- env: opts.env ? { ...process11.env, ...opts.env } : void 0
4053
+ env: opts.env ? { ...process13.env, ...opts.env } : void 0
3645
4054
  });
3646
4055
  let stdout = "";
3647
4056
  let stderr = "";
3648
4057
  child.stdout?.on("data", (chunk) => {
3649
4058
  stdout += chunk;
3650
- if (opts.streamStdout) process11.stdout.write(chunk);
4059
+ if (opts.streamStdout) process13.stdout.write(chunk);
3651
4060
  });
3652
4061
  child.stderr?.on("data", (chunk) => {
3653
4062
  stderr += chunk;
3654
- if (opts.stream) process11.stderr.write(chunk);
4063
+ if (opts.stream) process13.stderr.write(chunk);
3655
4064
  });
3656
4065
  child.on("error", reject);
3657
4066
  child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
@@ -3758,7 +4167,7 @@ function sshOptionsFrom(options) {
3758
4167
  import crypto4 from "node:crypto";
3759
4168
  import fs22 from "node:fs";
3760
4169
  import path21 from "node:path";
3761
- import process12 from "node:process";
4170
+ import process14 from "node:process";
3762
4171
  var VELA_ROOT = "/var/lib/vela";
3763
4172
  var VELA_ETC = "/etc/vela";
3764
4173
  var VELA_USER = "vela";
@@ -3795,7 +4204,7 @@ async function syncServerScripts(session) {
3795
4204
  const dir = `${SCRIPT_VERSIONS_DIR}/${digest}`;
3796
4205
  const present = await session.script(`[ -d "$1" ] && echo yes || echo no`, { args: [dir] });
3797
4206
  if (present.stdout.trim() !== "yes") {
3798
- const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process12.pid}.${Date.now()}`;
4207
+ const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process14.pid}.${Date.now()}`;
3799
4208
  await session.script(`mkdir -p "$1" && chmod 0755 "$(dirname "$1")" "$1"`, {
3800
4209
  args: [incoming]
3801
4210
  });
@@ -4159,7 +4568,7 @@ async function ensureBinding(workspaceRootDir, target, request = {}) {
4159
4568
  writeBinding(workspaceRootDir, key, binding);
4160
4569
  }
4161
4570
  if (moving) {
4162
- p16.log.warn(
4571
+ p18.log.warn(
4163
4572
  `${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
4164
4573
 
4165
4574
  Whatever is running on ${existing.server} is left there, and this project can no
@@ -4170,7 +4579,7 @@ longer reach it. Remove it there first if that was not intended.`
4170
4579
  }
4171
4580
  async function confirmMove(target, from, to) {
4172
4581
  const name = bindingName(target);
4173
- if (!process13.stdout.isTTY || process13.env.CI) {
4582
+ if (!process15.stdout.isTTY || process15.env.CI) {
4174
4583
  throw new Error(
4175
4584
  `${pc5.cyan(`--server ${to}`)} does not match the server recorded for ${pc5.cyan(name)}, ${pc5.cyan(from)}.
4176
4585
 
@@ -4178,13 +4587,13 @@ Drop ${pc5.cyan("--server")} to use the recorded one, or move the binding on pur
4178
4587
  this command once from a terminal (or editing .vela/project.json).`
4179
4588
  );
4180
4589
  }
4181
- const ok = await p16.confirm({
4590
+ const ok = await p18.confirm({
4182
4591
  message: `${name} ${target.kind === "preview" ? "run" : "runs"} on ${from}. Point ${name} at ${to} instead?`,
4183
4592
  initialValue: false
4184
4593
  });
4185
- if (p16.isCancel(ok) || !ok) {
4186
- p16.cancel("Operation cancelled.");
4187
- process13.exit(0);
4594
+ if (p18.isCancel(ok) || !ok) {
4595
+ p18.cancel("Operation cancelled.");
4596
+ process15.exit(0);
4188
4597
  }
4189
4598
  }
4190
4599
  function bindingName(target) {
@@ -4192,7 +4601,7 @@ function bindingName(target) {
4192
4601
  }
4193
4602
  async function promptServer(target) {
4194
4603
  const name = bindingName(target);
4195
- if (!process13.stdout.isTTY || process13.env.CI) {
4604
+ if (!process15.stdout.isTTY || process15.env.CI) {
4196
4605
  throw new Error(
4197
4606
  `${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
4198
4607
 
@@ -4200,29 +4609,29 @@ Pass ${pc5.cyan("--server user@host")}, or run the command once from your own ma
4200
4609
  and commit ${pc5.cyan(".vela/project.json")}.`
4201
4610
  );
4202
4611
  }
4203
- p16.log.info(
4612
+ p18.log.info(
4204
4613
  `${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
4205
4614
  );
4206
- const value = await p16.text({
4615
+ const value = await p18.text({
4207
4616
  message: `Which server should ${name} run on?`,
4208
4617
  placeholder: "root@203.0.113.10",
4209
4618
  validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
4210
4619
  });
4211
- if (p16.isCancel(value)) {
4212
- p16.cancel("Operation cancelled.");
4213
- process13.exit(0);
4620
+ if (p18.isCancel(value)) {
4621
+ p18.cancel("Operation cancelled.");
4622
+ process15.exit(0);
4214
4623
  }
4215
4624
  return value.trim();
4216
4625
  }
4217
4626
  async function promptDomain(target) {
4218
- if (!process13.stdout.isTTY || process13.env.CI) return void 0;
4219
- const value = await p16.text({
4627
+ if (!process15.stdout.isTTY || process15.env.CI) return void 0;
4628
+ const value = await p18.text({
4220
4629
  message: `Which hostname should ${target.name} be served on?`,
4221
4630
  placeholder: "example.com \u2014 leave blank to decide later"
4222
4631
  });
4223
- if (p16.isCancel(value)) {
4224
- p16.cancel("Operation cancelled.");
4225
- process13.exit(0);
4632
+ if (p18.isCancel(value)) {
4633
+ p18.cancel("Operation cancelled.");
4634
+ process15.exit(0);
4226
4635
  }
4227
4636
  return value.trim() || void 0;
4228
4637
  }
@@ -4230,10 +4639,10 @@ async function applyRestart(ctx) {
4230
4639
  const outcome = await restartInstance(ctx.session, ctx.instance);
4231
4640
  if (!outcome.deployed) return;
4232
4641
  if (outcome.restarted) {
4233
- p16.log.success("App restarted");
4642
+ p18.log.success("App restarted");
4234
4643
  return;
4235
4644
  }
4236
- p16.log.error(
4645
+ p18.log.error(
4237
4646
  `App restart failed.
4238
4647
 
4239
4648
  The new value is stored and will be used the next time the app starts.
@@ -4242,7 +4651,7 @@ ${pc5.dim(outcome.error ?? "")}`
4242
4651
  }
4243
4652
  async function applyEnvRestart(ctx, changed) {
4244
4653
  if (touchesSuperuser(changed)) {
4245
- p16.log.warn(
4654
+ p18.log.warn(
4246
4655
  `PocketBase superuser credentials changed.
4247
4656
 
4248
4657
  The database still holds the old ones, so the app has not been restarted.
@@ -4279,7 +4688,7 @@ import pc7 from "picocolors";
4279
4688
 
4280
4689
  // src/lib/local-env.ts
4281
4690
  import fs24 from "node:fs";
4282
- import * as p17 from "@clack/prompts";
4691
+ import * as p19 from "@clack/prompts";
4283
4692
  import pc6 from "picocolors";
4284
4693
  function readLocalEnv(envFile) {
4285
4694
  if (!fs24.existsSync(envFile)) return {};
@@ -4305,16 +4714,16 @@ async function applyLocalEnvChange(ctx, changed) {
4305
4714
  process.env.POCKETBASE_SUPERUSER_EMAIL = email3;
4306
4715
  process.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
4307
4716
  await ensureSuperuser(ctx.workspaceRootDir);
4308
- p17.log.success("Local superuser updated to match");
4717
+ p19.log.success("Local superuser updated to match");
4309
4718
  } else {
4310
- p17.log.warn(
4719
+ p19.log.warn(
4311
4720
  `The local database still has the old superuser.
4312
4721
  Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SUPERUSER_PASSWORD")} to reconcile it.`
4313
4722
  );
4314
4723
  }
4315
4724
  }
4316
4725
  if (getPocketbaseMetadata(ctx.workspaceRootDir)) {
4317
- p17.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4726
+ p19.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4318
4727
  }
4319
4728
  }
4320
4729
 
@@ -4478,7 +4887,7 @@ function hasFile(dir) {
4478
4887
 
4479
4888
  // src/commands/enable/s3.ts
4480
4889
  var s3 = addTargetOptions(
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),
4890
+ new Command21("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),
4482
4891
  "local"
4483
4892
  ).action(
4484
4893
  (raw) => runCommand(() => {
@@ -4496,7 +4905,7 @@ var s3 = addTargetOptions(
4496
4905
  failure = error instanceof Error ? error.message : String(error);
4497
4906
  }
4498
4907
  if (failure) {
4499
- p18.log.warn(
4908
+ p20.log.warn(
4500
4909
  `The connection test failed \u2014 the settings are saved but may be wrong.
4501
4910
 
4502
4911
  ${pc8.dim(failure)}
@@ -4540,64 +4949,64 @@ Do that first, then re-run with ${pc8.cyan("--force")}.`
4540
4949
  );
4541
4950
  }
4542
4951
  async function promptConfig(options, existing) {
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");
4952
+ const endpoint = options.endpoint ?? await text9("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4953
+ const bucket = options.bucket ?? await text9("S3 bucket name", existing.bucket);
4954
+ const region = options.region ?? await text9("S3 region", existing.region || "us-east-1");
4955
+ const accessKey = options.accessKey ?? await text9("S3 access key", existing.accessKey);
4956
+ const secret = options.secret ?? process16.env.VELA_S3_SECRET ?? await password6("S3 secret key");
4548
4957
  const forcePathStyle = options.forcePathStyle ?? await confirm4(
4549
4958
  "Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
4550
4959
  defaultForcePathStyle(endpoint)
4551
4960
  );
4552
4961
  return { endpoint, bucket, region, accessKey, secret, forcePathStyle };
4553
4962
  }
4554
- async function text8(message, initialValue = "") {
4555
- const value = await p18.text({
4963
+ async function text9(message, initialValue = "") {
4964
+ const value = await p20.text({
4556
4965
  message,
4557
4966
  initialValue,
4558
4967
  validate: (input) => input?.trim() ? void 0 : `${message} is required`
4559
4968
  });
4560
- if (p18.isCancel(value)) {
4561
- p18.cancel("Operation cancelled.");
4562
- process14.exit(0);
4969
+ if (p20.isCancel(value)) {
4970
+ p20.cancel("Operation cancelled.");
4971
+ process16.exit(0);
4563
4972
  }
4564
4973
  return value.trim();
4565
4974
  }
4566
- async function password5(message) {
4567
- const value = await p18.password({
4975
+ async function password6(message) {
4976
+ const value = await p20.password({
4568
4977
  message,
4569
4978
  validate: (input) => input ? void 0 : `${message} is required`
4570
4979
  });
4571
- if (p18.isCancel(value)) {
4572
- p18.cancel("Operation cancelled.");
4573
- process14.exit(0);
4980
+ if (p20.isCancel(value)) {
4981
+ p20.cancel("Operation cancelled.");
4982
+ process16.exit(0);
4574
4983
  }
4575
4984
  return value;
4576
4985
  }
4577
4986
  async function confirm4(message, initialValue) {
4578
- const value = await p18.confirm({ message, initialValue });
4579
- if (p18.isCancel(value)) {
4580
- p18.cancel("Operation cancelled.");
4581
- process14.exit(0);
4987
+ const value = await p20.confirm({ message, initialValue });
4988
+ if (p20.isCancel(value)) {
4989
+ p20.cancel("Operation cancelled.");
4990
+ process16.exit(0);
4582
4991
  }
4583
4992
  return value;
4584
4993
  }
4585
4994
 
4586
4995
  // src/commands/enable/smtp.ts
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(
4996
+ import process17 from "node:process";
4997
+ import { Command as Command22 } from "commander";
4998
+ import * as p21 from "@clack/prompts";
4999
+ var smtp = new Command22("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4591
5000
  () => runCommand(async () => {
4592
5001
  const { workspaceRootDir } = await getWorkspace();
4593
- const config = await p19.group(
5002
+ const config = await p21.group(
4594
5003
  {
4595
- host: () => p19.text({
5004
+ host: () => p21.text({
4596
5005
  message: "SMTP host",
4597
5006
  placeholder: "smtp.example.com",
4598
5007
  validate: (v10) => v10 ? void 0 : "Host is required"
4599
5008
  }),
4600
- port: () => p19.text({
5009
+ port: () => p21.text({
4601
5010
  message: "SMTP port",
4602
5011
  initialValue: "587",
4603
5012
  validate: (v10) => {
@@ -4607,13 +5016,13 @@ var smtp = new Command21("smtp").description("configure SMTP for transactional e
4607
5016
  return void 0;
4608
5017
  }
4609
5018
  }),
4610
- username: () => p19.text({ message: "SMTP username" }),
4611
- password: () => p19.password({ message: "SMTP password" })
5019
+ username: () => p21.text({ message: "SMTP username" }),
5020
+ password: () => p21.password({ message: "SMTP password" })
4612
5021
  },
4613
5022
  {
4614
5023
  onCancel: () => {
4615
- p19.cancel("Operation cancelled.");
4616
- process15.exit(0);
5024
+ p21.cancel("Operation cancelled.");
5025
+ process17.exit(0);
4617
5026
  }
4618
5027
  }
4619
5028
  );
@@ -4640,24 +5049,24 @@ var smtp = new Command21("smtp").description("configure SMTP for transactional e
4640
5049
  );
4641
5050
 
4642
5051
  // src/commands/enable/cms.ts
4643
- import process16 from "node:process";
4644
- import { Command as Command22 } from "commander";
4645
- import * as p20 from "@clack/prompts";
5052
+ import process18 from "node:process";
5053
+ import { Command as Command23 } from "commander";
5054
+ import * as p22 from "@clack/prompts";
4646
5055
  import pc9 from "picocolors";
4647
- var cms = new Command22("cms").description("enable an inline-editing CMS with an admin bar").option(
5056
+ var cms = new Command23("cms").description("enable an inline-editing CMS with an admin bar").option(
4648
5057
  "--endpoint <url>",
4649
5058
  "read from a hosted CMS at this URL instead of installing the backend in this app"
4650
5059
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4651
5060
  (opts, cmd) => runCommand(async () => {
4652
5061
  if (!opts.endpoint && !hasBackend()) {
4653
- p20.log.error(
5062
+ p22.log.error(
4654
5063
  `${pc9.cyan("vela enable cms")} needs a server to host the CMS backend, and this project is static.
4655
5064
 
4656
5065
  Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${pc9.cyan("vela enable cms --endpoint <url>")}.`
4657
5066
  );
4658
- p20.log.message();
4659
- p20.cancel("Operation failed.");
4660
- process16.exitCode = 1;
5067
+ p22.log.message();
5068
+ p22.cancel("Operation failed.");
5069
+ process18.exitCode = 1;
4661
5070
  return;
4662
5071
  }
4663
5072
  await runPattern("enable-cms", cmd.args, opts.endpoint ? { endpoint: opts.endpoint } : {}, {
@@ -4677,8 +5086,8 @@ Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${
4677
5086
  );
4678
5087
 
4679
5088
  // src/commands/enable/blog.ts
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(
5089
+ import { Command as Command24 } from "commander";
5090
+ var blog = new Command24("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4682
5091
  (_opts, cmd) => runCommand(
4683
5092
  () => runPattern(
4684
5093
  "enable-blog",
@@ -4703,8 +5112,8 @@ var blog = new Command23("blog").description("enable an mdsvex blog with posts,
4703
5112
  );
4704
5113
 
4705
5114
  // src/commands/enable/content-negotiation.ts
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(
5115
+ import { Command as Command25 } from "commander";
5116
+ var contentNegotiation = new Command25("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4708
5117
  (_opts, cmd) => runCommand(
4709
5118
  () => runPattern(
4710
5119
  "enable-content-negotiation",
@@ -4728,33 +5137,33 @@ var contentNegotiation = new Command24("content-negotiation").description("enabl
4728
5137
  );
4729
5138
 
4730
5139
  // src/commands/enable.ts
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);
5140
+ var enable = new Command26("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);
4732
5141
 
4733
5142
  // src/commands/disable.ts
4734
- import { Command as Command36 } from "commander";
5143
+ import { Command as Command37 } from "commander";
4735
5144
 
4736
5145
  // src/commands/disable/auth.ts
4737
- import { Command as Command26 } from "commander";
5146
+ import { Command as Command27 } from "commander";
4738
5147
 
4739
5148
  // src/commands/disable/_shared.ts
4740
- import process17 from "node:process";
4741
- import * as p21 from "@clack/prompts";
5149
+ import process19 from "node:process";
5150
+ import * as p23 from "@clack/prompts";
4742
5151
  async function runDisable(opts, flags, cmdArgs) {
4743
5152
  if (!flags.yes) {
4744
- const ok = await p21.confirm({
5153
+ const ok = await p23.confirm({
4745
5154
  message: opts.confirmMessage,
4746
5155
  initialValue: false
4747
5156
  });
4748
- if (p21.isCancel(ok) || !ok) {
4749
- p21.cancel("Operation cancelled.");
4750
- process17.exit(0);
5157
+ if (p23.isCancel(ok) || !ok) {
5158
+ p23.cancel("Operation cancelled.");
5159
+ process19.exit(0);
4751
5160
  }
4752
5161
  }
4753
5162
  await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
4754
5163
  }
4755
5164
 
4756
5165
  // src/commands/disable/auth.ts
4757
- var auth2 = new Command26("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5166
+ var auth2 = new Command27("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4758
5167
  (opts, cmd) => runCommand(
4759
5168
  () => runDisable(
4760
5169
  {
@@ -4780,8 +5189,8 @@ var auth2 = new Command26("auth").description("disable authentication").option("
4780
5189
  );
4781
5190
 
4782
5191
  // src/commands/disable/api.ts
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(
5192
+ import { Command as Command28 } from "commander";
5193
+ var api2 = new Command28("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4785
5194
  (opts, cmd) => runCommand(
4786
5195
  () => runDisable(
4787
5196
  {
@@ -4804,8 +5213,8 @@ var api2 = new Command27("api").description("disable the REST API").option("-y,
4804
5213
  );
4805
5214
 
4806
5215
  // src/commands/disable/api-keys.ts
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(
5216
+ import { Command as Command29 } from "commander";
5217
+ var apiKeys2 = new Command29("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4809
5218
  (opts, cmd) => runCommand(
4810
5219
  () => runDisable(
4811
5220
  {
@@ -4828,8 +5237,8 @@ var apiKeys2 = new Command28("api-keys").description("disable API key management
4828
5237
  );
4829
5238
 
4830
5239
  // src/commands/disable/backend.ts
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(
5240
+ import { Command as Command30 } from "commander";
5241
+ var backend2 = new Command30("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4833
5242
  (opts, cmd) => runCommand(
4834
5243
  () => runDisable(
4835
5244
  {
@@ -4852,8 +5261,8 @@ var backend2 = new Command29("backend").description("disable the PocketBase back
4852
5261
  );
4853
5262
 
4854
5263
  // src/commands/disable/content-negotiation.ts
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(
5264
+ import { Command as Command31 } from "commander";
5265
+ var contentNegotiation2 = new Command31("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4857
5266
  (opts, cmd) => runCommand(
4858
5267
  () => runDisable(
4859
5268
  {
@@ -4876,8 +5285,8 @@ var contentNegotiation2 = new Command30("content-negotiation").description("disa
4876
5285
  );
4877
5286
 
4878
5287
  // src/commands/disable/i18n.ts
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(
5288
+ import { Command as Command32 } from "commander";
5289
+ var i18n2 = new Command32("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4881
5290
  (opts, cmd) => runCommand(
4882
5291
  () => runDisable(
4883
5292
  {
@@ -4903,8 +5312,8 @@ var i18n2 = new Command31("i18n").description("disable internationalization").op
4903
5312
  );
4904
5313
 
4905
5314
  // src/commands/disable/teams.ts
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(
5315
+ import { Command as Command33 } from "commander";
5316
+ var teams2 = new Command33("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4908
5317
  (opts, cmd) => runCommand(
4909
5318
  () => runDisable(
4910
5319
  {
@@ -4930,8 +5339,8 @@ var teams2 = new Command32("teams").description("disable teams").option("-y, --y
4930
5339
  );
4931
5340
 
4932
5341
  // src/commands/disable/payments.ts
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(
5342
+ import { Command as Command34 } from "commander";
5343
+ var payments2 = new Command34("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4935
5344
  (opts, cmd) => runCommand(
4936
5345
  () => runDisable(
4937
5346
  {
@@ -4958,11 +5367,11 @@ var payments2 = new Command33("payments").description("disable payments").option
4958
5367
  );
4959
5368
 
4960
5369
  // src/commands/disable/s3.ts
4961
- import { Command as Command34 } from "commander";
4962
- import * as p22 from "@clack/prompts";
5370
+ import { Command as Command35 } from "commander";
5371
+ import * as p24 from "@clack/prompts";
4963
5372
  import pc10 from "picocolors";
4964
5373
  var s32 = addTargetOptions(
4965
- new Command34("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
5374
+ new Command35("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4966
5375
  "local"
4967
5376
  ).action(
4968
5377
  (raw) => runCommand(() => {
@@ -4971,7 +5380,7 @@ var s32 = addTargetOptions(
4971
5380
  return withBackupTarget(raw, "disable s3", async (ctx) => {
4972
5381
  const existing = await readS3(ctx.pb, filesystem);
4973
5382
  if (!existing.enabled) {
4974
- p22.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
5383
+ p24.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
4975
5384
  return;
4976
5385
  }
4977
5386
  await disableS3(ctx.pb, filesystem);
@@ -4991,8 +5400,8 @@ function label2(filesystem) {
4991
5400
  }
4992
5401
 
4993
5402
  // src/commands/disable/smtp.ts
4994
- import { Command as Command35 } from "commander";
4995
- var smtp2 = new Command35("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
5403
+ import { Command as Command36 } from "commander";
5404
+ var smtp2 = new Command36("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4996
5405
  () => runCommand(async () => {
4997
5406
  const { workspaceRootDir } = await getWorkspace();
4998
5407
  await withPocketbase(workspaceRootDir, async (pb) => {
@@ -5009,30 +5418,30 @@ var smtp2 = new Command35("smtp").description("disable SMTP configuration").conf
5009
5418
  );
5010
5419
 
5011
5420
  // src/commands/disable.ts
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);
5421
+ var disable = new Command37("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);
5013
5422
 
5014
5423
  // src/commands/destroy.ts
5015
- import { Command as Command42 } from "commander";
5424
+ import { Command as Command43 } from "commander";
5016
5425
 
5017
5426
  // src/commands/destroy/form.ts
5018
- import { Command as Command37 } from "commander";
5427
+ import { Command as Command38 } from "commander";
5019
5428
 
5020
5429
  // src/commands/destroy/_shared.ts
5021
- import process18 from "node:process";
5022
- import * as p23 from "@clack/prompts";
5430
+ import process20 from "node:process";
5431
+ import * as p25 from "@clack/prompts";
5023
5432
  async function runDestroy(slug2, model, confirmMessage, report4, flags) {
5024
5433
  if (!flags.yes) {
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);
5434
+ const ok = await p25.confirm({ message: confirmMessage, initialValue: false });
5435
+ if (p25.isCancel(ok) || !ok) {
5436
+ p25.cancel("Operation cancelled.");
5437
+ process20.exit(0);
5029
5438
  }
5030
5439
  }
5031
5440
  await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
5032
5441
  }
5033
5442
 
5034
5443
  // src/commands/destroy/form.ts
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(
5444
+ var form2 = new Command38("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(
5036
5445
  "--route <route>",
5037
5446
  "custom route the form was generated at (must match the --route used at generation)"
5038
5447
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -5056,8 +5465,8 @@ var form2 = new Command37("form").description("destroy a form generated by `vela
5056
5465
  );
5057
5466
 
5058
5467
  // src/commands/destroy/schema.ts
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(
5468
+ import { Command as Command39 } from "commander";
5469
+ var schema2 = new Command39("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(
5061
5470
  (model, opts) => runCommand(
5062
5471
  () => runDestroy(
5063
5472
  "destroy-schema",
@@ -5078,8 +5487,8 @@ var schema2 = new Command38("schema").description("destroy a zod schema generate
5078
5487
  );
5079
5488
 
5080
5489
  // src/commands/destroy/resource.ts
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(
5490
+ import { Command as Command40 } from "commander";
5491
+ var resource2 = new Command40("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(
5083
5492
  (model, opts) => runCommand(
5084
5493
  () => runDestroy(
5085
5494
  "destroy-resource",
@@ -5100,8 +5509,8 @@ var resource2 = new Command39("resource").description("destroy a resource genera
5100
5509
  );
5101
5510
 
5102
5511
  // src/commands/destroy/scaffold.ts
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(
5512
+ import { Command as Command41 } from "commander";
5513
+ var scaffold2 = new Command41("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(
5105
5514
  "--route <route>",
5106
5515
  "custom route the scaffold was generated at (must match the --route used at generation)"
5107
5516
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -5128,9 +5537,9 @@ var scaffold2 = new Command40("scaffold").description("destroy a scaffold genera
5128
5537
  );
5129
5538
 
5130
5539
  // src/commands/destroy/deployment.ts
5131
- import process19 from "node:process";
5132
- import { Command as Command41 } from "commander";
5133
- import * as p26 from "@clack/prompts";
5540
+ import process21 from "node:process";
5541
+ import { Command as Command42 } from "commander";
5542
+ import * as p28 from "@clack/prompts";
5134
5543
  import pc13 from "picocolors";
5135
5544
 
5136
5545
  // src/lib/destroy-guard.ts
@@ -5163,103 +5572,27 @@ Pass \`--confirm ${appName}\` as well \u2014 the app name, the same thing a term
5163
5572
  message: `Removing ${what} needs a confirmation, and there is no terminal to ask on.
5164
5573
 
5165
5574
  Pass \`--confirm ${appName}\` \u2014 the app name, the same thing a terminal would ask you to type.`
5166
- };
5167
- }
5168
- if (yes) return { kind: "proceed" };
5169
- if (interactive) return { kind: "prompt", byName: false };
5170
- return {
5171
- kind: "refuse",
5172
- message: `Removing ${what} needs a confirmation, and there is no terminal to ask on. Pass \`--yes\`.`
5173
- };
5174
- }
5175
- function describe({ appName, envTag, purge }) {
5176
- const target = isProd(envTag) ? "production" : `the ${envTag} environment`;
5177
- return purge ? `${target} of ${appName} and its database` : `${target} of ${appName}`;
5178
- }
5179
-
5180
- // src/lib/deploy-report.ts
5181
- import * as p25 from "@clack/prompts";
5182
- import pc12 from "picocolors";
5183
-
5184
- // src/lib/server-identity.ts
5185
- import * as p24 from "@clack/prompts";
5186
- import pc11 from "picocolors";
5187
-
5188
- // src/lib/velastack-api.ts
5189
- async function apiFetch(apiKey, pathAndQuery, init) {
5190
- const headers = new Headers(init?.headers);
5191
- headers.set("Authorization", `Bearer ${apiKey}`);
5192
- if (init?.body && !headers.has("Content-Type")) {
5193
- headers.set("Content-Type", "application/json");
5194
- }
5195
- const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
5196
- if (res.status === 401) {
5197
- throw new Error("API key invalid \u2014 run `vela login`");
5198
- }
5199
- if (res.status === 403) {
5200
- const body = await res.text().catch(() => "");
5201
- throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
5202
- }
5203
- if (!res.ok) {
5204
- const body = await res.text().catch(() => "");
5205
- throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
5206
- }
5207
- return await res.json();
5208
- }
5209
- async function getCurrentUser(apiKey) {
5210
- const data = await apiFetch(
5211
- apiKey,
5212
- "/api/collections/users/records?perPage=1"
5213
- );
5214
- const user = data.items[0];
5215
- if (!user) throw new Error("No user found. Run `vela login` to login.");
5216
- return user;
5217
- }
5218
- async function listTeams(apiKey) {
5219
- const data = await apiFetch(
5220
- apiKey,
5221
- "/api/collections/teams/records?perPage=200"
5222
- );
5223
- return data.items;
5224
- }
5225
- async function listProjects(apiKey) {
5226
- const data = await apiFetch(
5227
- apiKey,
5228
- "/api/collections/projects/records?perPage=200&expand=team"
5229
- );
5230
- return data.items;
5231
- }
5232
- async function createProject2(apiKey, args) {
5233
- return apiFetch(apiKey, "/api/collections/projects/records", {
5234
- method: "POST",
5235
- body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
5236
- });
5237
- }
5238
- async function registerServer(apiKey, input) {
5239
- return apiFetch(apiKey, "/v1/servers", {
5240
- method: "POST",
5241
- body: JSON.stringify(input)
5242
- });
5243
- }
5244
- async function startDeployment(apiKey, projectId, input) {
5245
- return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
5246
- method: "POST",
5247
- body: JSON.stringify(input)
5248
- });
5249
- }
5250
- async function finishDeployment(apiKey, projectId, deploymentId, input) {
5251
- return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
5252
- method: "PATCH",
5253
- body: JSON.stringify(input)
5254
- });
5575
+ };
5576
+ }
5577
+ if (yes) return { kind: "proceed" };
5578
+ if (interactive) return { kind: "prompt", byName: false };
5579
+ return {
5580
+ kind: "refuse",
5581
+ message: `Removing ${what} needs a confirmation, and there is no terminal to ask on. Pass \`--yes\`.`
5582
+ };
5255
5583
  }
5256
- async function destroyEnvironment(apiKey, projectId, envTag) {
5257
- return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
5258
- method: "DELETE"
5259
- });
5584
+ function describe({ appName, envTag, purge }) {
5585
+ const target = isProd(envTag) ? "production" : `the ${envTag} environment`;
5586
+ return purge ? `${target} of ${appName} and its database` : `${target} of ${appName}`;
5260
5587
  }
5261
5588
 
5589
+ // src/lib/deploy-report.ts
5590
+ import * as p27 from "@clack/prompts";
5591
+ import pc12 from "picocolors";
5592
+
5262
5593
  // src/lib/server-identity.ts
5594
+ import * as p26 from "@clack/prompts";
5595
+ import pc11 from "picocolors";
5263
5596
  var IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
5264
5597
  async function ensureServerIdentity(session, apiKey) {
5265
5598
  const existing = await readServerIdentity(session);
@@ -5272,7 +5605,7 @@ async function ensureServerIdentity(session, apiKey) {
5272
5605
  if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
5273
5606
  await writeServerIdentity(session, registered);
5274
5607
  if (existing) {
5275
- p24.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5608
+ p26.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5276
5609
  }
5277
5610
  }
5278
5611
  await runServerScript(session, "origin.sh");
@@ -5312,7 +5645,7 @@ function createDeployReporter(workspaceRootDir) {
5312
5645
  const link2 = readProjectConfig(workspaceRootDir);
5313
5646
  const apiKey = link2 ? readApiKey() : null;
5314
5647
  if (link2 && !apiKey) {
5315
- p25.log.warn(
5648
+ p27.log.warn(
5316
5649
  `This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
5317
5650
  API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
5318
5651
  ${pc12.cyan("VELA_API_KEY")}.`
@@ -5362,7 +5695,7 @@ async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
5362
5695
  }
5363
5696
  }
5364
5697
  function warn(what, err) {
5365
- p25.log.warn(
5698
+ p27.log.warn(
5366
5699
  `velastack.dev could not ${what}.
5367
5700
  ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5368
5701
  );
@@ -5371,7 +5704,7 @@ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5371
5704
  // src/commands/destroy/deployment.ts
5372
5705
  var deployment = addLockWaitOption(
5373
5706
  addTargetOptions(
5374
- new Command41("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5707
+ new Command42("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5375
5708
  "production"
5376
5709
  )
5377
5710
  ).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").option(
@@ -5390,7 +5723,7 @@ var deployment = addLockWaitOption(
5390
5723
  purge: options.purge === true,
5391
5724
  yes: options.yes === true,
5392
5725
  confirm: options.confirm,
5393
- interactive: Boolean(process19.stdin.isTTY && process19.stdout.isTTY)
5726
+ interactive: Boolean(process21.stdin.isTTY && process21.stdout.isTTY)
5394
5727
  });
5395
5728
  if (decision.kind === "refuse") throw new Error(decision.message);
5396
5729
  if (decision.kind === "prompt") {
@@ -5405,13 +5738,13 @@ var deployment = addLockWaitOption(
5405
5738
  stream: true
5406
5739
  });
5407
5740
  if (result?.existed === false) {
5408
- p26.log.info(
5741
+ p28.log.info(
5409
5742
  `Nothing named ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} on ${ctx.server}; nothing to remove.`
5410
5743
  );
5411
5744
  return;
5412
5745
  }
5413
5746
  await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
5414
- p26.log.success(
5747
+ p28.log.success(
5415
5748
  `Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? result.trash ? `
5416
5749
 
5417
5750
  A snapshot of its data is at ${pc13.cyan(result.trash)} on the server for two weeks.` : "" : `
@@ -5429,35 +5762,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
5429
5762
  );
5430
5763
  async function confirm8(appName, targetName, byName) {
5431
5764
  if (byName) {
5432
- const answer = await p26.text({
5765
+ const answer = await p28.text({
5433
5766
  message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}. Type the app name to confirm`,
5434
5767
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
5435
5768
  });
5436
- if (p26.isCancel(answer)) {
5437
- p26.cancel("Operation cancelled.");
5438
- process19.exit(0);
5769
+ if (p28.isCancel(answer)) {
5770
+ p28.cancel("Operation cancelled.");
5771
+ process21.exit(0);
5439
5772
  }
5440
5773
  return;
5441
5774
  }
5442
- const ok = await p26.confirm({
5775
+ const ok = await p28.confirm({
5443
5776
  message: `Remove ${appName} (${targetName})?`,
5444
5777
  initialValue: false
5445
5778
  });
5446
- if (p26.isCancel(ok) || !ok) {
5447
- p26.cancel("Operation cancelled.");
5448
- process19.exit(0);
5779
+ if (p28.isCancel(ok) || !ok) {
5780
+ p28.cancel("Operation cancelled.");
5781
+ process21.exit(0);
5449
5782
  }
5450
5783
  }
5451
5784
 
5452
5785
  // src/commands/destroy.ts
5453
- var destroy = new Command42("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5786
+ var destroy = new Command43("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5454
5787
 
5455
5788
  // src/commands/ui.ts
5456
- import { Command as Command48 } from "commander";
5789
+ import { Command as Command49 } from "commander";
5457
5790
 
5458
5791
  // src/commands/ui/add.ts
5459
- import { Command as Command43 } from "commander";
5460
- import * as p27 from "@clack/prompts";
5792
+ import { Command as Command44 } from "commander";
5793
+ import * as p29 from "@clack/prompts";
5461
5794
  import { installComponents } from "@velastack/patterns";
5462
5795
 
5463
5796
  // src/lib/ui-add.ts
@@ -5506,10 +5839,10 @@ function uiAddReport(requested, outcome) {
5506
5839
  }
5507
5840
 
5508
5841
  // src/commands/ui/add.ts
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(
5842
+ var add = new Command44("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(
5510
5843
  (components, options) => runCommand(async () => {
5511
5844
  const { workspaceRootDir } = await getWorkspace();
5512
- const log45 = p27.taskLog({ title: "Adding UI components..." });
5845
+ const log45 = p29.taskLog({ title: "Adding UI components..." });
5513
5846
  let outcome;
5514
5847
  try {
5515
5848
  outcome = await installComponents({
@@ -5528,13 +5861,13 @@ var add = new Command43("add").description("add ui components (shadcn-svelte ite
5528
5861
  );
5529
5862
 
5530
5863
  // src/commands/ui/base.ts
5531
- import { Command as Command44 } from "commander";
5532
- import * as p28 from "@clack/prompts";
5864
+ import { Command as Command45 } from "commander";
5865
+ import * as p30 from "@clack/prompts";
5533
5866
  import { applyBaseColor } from "@velastack/patterns";
5534
- var base = new Command44("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5867
+ var base = new Command45("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5535
5868
  (color) => runCommand(async () => {
5536
5869
  const { workspaceRootDir } = await getWorkspace();
5537
- const log45 = p28.taskLog({ title: `Applying the ${color} palette...` });
5870
+ const log45 = p30.taskLog({ title: `Applying the ${color} palette...` });
5538
5871
  let outcome;
5539
5872
  try {
5540
5873
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
@@ -5556,8 +5889,8 @@ var base = new Command44("base").description("change the base (gray) palette").a
5556
5889
  );
5557
5890
 
5558
5891
  // src/commands/ui/list.ts
5559
- import { Command as Command45 } from "commander";
5560
- import * as p29 from "@clack/prompts";
5892
+ import { Command as Command46 } from "commander";
5893
+ import * as p31 from "@clack/prompts";
5561
5894
  import { listComponents } from "@velastack/patterns";
5562
5895
 
5563
5896
  // src/lib/ui-list.ts
@@ -5588,7 +5921,7 @@ function uiListReport(result) {
5588
5921
  }
5589
5922
 
5590
5923
  // src/commands/ui/list.ts
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(
5924
+ var list = new Command46("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
5592
5925
  (options) => runCommand(async () => {
5593
5926
  const { workspaceRootDir } = await getWorkspace();
5594
5927
  if (options.json) {
@@ -5596,7 +5929,7 @@ var list = new Command45("list").description("list installed ui components, vela
5596
5929
  console.log(JSON.stringify(result2, null, 2));
5597
5930
  return;
5598
5931
  }
5599
- const spinner7 = p29.spinner();
5932
+ const spinner7 = p31.spinner();
5600
5933
  spinner7.start("Reading the registry...");
5601
5934
  let result;
5602
5935
  try {
@@ -5608,15 +5941,15 @@ var list = new Command45("list").description("list installed ui components, vela
5608
5941
  spinner7.stop(`Read the ${result.style} registry`);
5609
5942
  reportResult(uiListReport(result));
5610
5943
  if (result.registryUnavailable) {
5611
- p29.log.warn(`${result.registryUnavailable}
5944
+ p31.log.warn(`${result.registryUnavailable}
5612
5945
  Registry components are not listed.`);
5613
5946
  }
5614
5947
  }, "Failed to list UI components.")
5615
5948
  );
5616
5949
 
5617
5950
  // src/commands/ui/style.ts
5618
- import { Command as Command46 } from "commander";
5619
- import * as p30 from "@clack/prompts";
5951
+ import { Command as Command47 } from "commander";
5952
+ import * as p32 from "@clack/prompts";
5620
5953
  import { switchStyle } from "@velastack/patterns";
5621
5954
 
5622
5955
  // src/lib/ui-style.ts
@@ -5642,10 +5975,10 @@ function uiStyleReport(result) {
5642
5975
  }
5643
5976
 
5644
5977
  // src/commands/ui/style.ts
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(
5978
+ var style = new Command47("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(
5646
5979
  (name, options) => runCommand(async () => {
5647
5980
  const { workspaceRootDir } = await getWorkspace();
5648
- const spinner7 = p30.spinner();
5981
+ const spinner7 = p32.spinner();
5649
5982
  spinner7.start(`Reading the ${name} registry...`);
5650
5983
  let log45;
5651
5984
  let outcome;
@@ -5658,20 +5991,20 @@ var style = new Command46("style").description("switch the shadcn-svelte style,
5658
5991
  confirm: async (components) => {
5659
5992
  spinner7.stop(`Read the ${name} registry`);
5660
5993
  if (components.length > 0) {
5661
- p30.log.info(
5994
+ p32.log.info(
5662
5995
  `Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
5663
5996
  ${components.map((c) => `- ${c}`).join("\n")}`
5664
5997
  );
5665
5998
  } else {
5666
- p30.log.info(
5999
+ p32.log.info(
5667
6000
  `No installed component comes from the registry; only the config changes.`
5668
6001
  );
5669
6002
  }
5670
6003
  if (!options.yes) {
5671
- const ok = await p30.confirm({ message: `Switch to ${name}?`, initialValue: false });
5672
- if (p30.isCancel(ok) || !ok) return false;
6004
+ const ok = await p32.confirm({ message: `Switch to ${name}?`, initialValue: false });
6005
+ if (p32.isCancel(ok) || !ok) return false;
5673
6006
  }
5674
- log45 = p30.taskLog({ title: `Switching to the ${name} style...` });
6007
+ log45 = p32.taskLog({ title: `Switching to the ${name} style...` });
5675
6008
  return true;
5676
6009
  }
5677
6010
  });
@@ -5682,11 +6015,11 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5682
6015
  }
5683
6016
  spinner7.stop(`Read the ${name} registry`);
5684
6017
  if (outcome.status === "unchanged") {
5685
- p30.log.info(`Already using the ${name} style.`);
6018
+ p32.log.info(`Already using the ${name} style.`);
5686
6019
  return;
5687
6020
  }
5688
6021
  if (outcome.status === "cancelled") {
5689
- p30.cancel("Operation cancelled.");
6022
+ p32.cancel("Operation cancelled.");
5690
6023
  return;
5691
6024
  }
5692
6025
  log45?.success("Style switched");
@@ -5695,13 +6028,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5695
6028
  );
5696
6029
 
5697
6030
  // src/commands/ui/theme.ts
5698
- import { Command as Command47 } from "commander";
5699
- import * as p31 from "@clack/prompts";
6031
+ import { Command as Command48 } from "commander";
6032
+ import * as p33 from "@clack/prompts";
5700
6033
  import { applyTheme } from "@velastack/patterns";
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(
6034
+ var theme = new Command48("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
5702
6035
  (accent) => runCommand(async () => {
5703
6036
  const { workspaceRootDir } = await getWorkspace();
5704
- const log45 = p31.taskLog({ title: `Applying the ${accent} accent...` });
6037
+ const log45 = p33.taskLog({ title: `Applying the ${accent} accent...` });
5705
6038
  let outcome;
5706
6039
  try {
5707
6040
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
@@ -5723,22 +6056,22 @@ var theme = new Command47("theme").description("change the accent color, keeping
5723
6056
  );
5724
6057
 
5725
6058
  // src/commands/ui.ts
5726
- var ui = new Command48("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
6059
+ var ui = new Command49("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5727
6060
 
5728
6061
  // src/commands/legal.ts
5729
- import { Command as Command51 } from "commander";
6062
+ import { Command as Command52 } from "commander";
5730
6063
 
5731
6064
  // src/commands/legal/terms.ts
5732
6065
  import fs26 from "node:fs";
5733
6066
  import path23 from "node:path";
5734
- import { Command as Command49 } from "commander";
5735
- import * as p33 from "@clack/prompts";
6067
+ import { Command as Command50 } from "commander";
6068
+ import * as p35 from "@clack/prompts";
5736
6069
 
5737
6070
  // src/commands/legal/shared.ts
5738
- import process20 from "node:process";
5739
- import * as p32 from "@clack/prompts";
6071
+ import process22 from "node:process";
6072
+ import * as p34 from "@clack/prompts";
5740
6073
  var sharedFields = {
5741
- websiteUrl: () => p32.text({
6074
+ websiteUrl: () => p34.text({
5742
6075
  message: "What is your website URL?",
5743
6076
  placeholder: "http://www.mysite.com",
5744
6077
  validate: (value) => {
@@ -5747,7 +6080,7 @@ var sharedFields = {
5747
6080
  }
5748
6081
  }
5749
6082
  }),
5750
- websiteName: () => p32.text({
6083
+ websiteName: () => p34.text({
5751
6084
  message: "What is your website name?",
5752
6085
  placeholder: "My Site",
5753
6086
  validate: (value) => {
@@ -5756,7 +6089,7 @@ var sharedFields = {
5756
6089
  }
5757
6090
  }
5758
6091
  }),
5759
- entityType: () => p32.select({
6092
+ entityType: () => p34.select({
5760
6093
  message: "Entity type",
5761
6094
  options: [
5762
6095
  {
@@ -5767,7 +6100,7 @@ var sharedFields = {
5767
6100
  { value: "individual", label: "I'm an Individual" }
5768
6101
  ]
5769
6102
  }),
5770
- businessName: ({ results }) => results?.entityType === "business" ? p32.text({
6103
+ businessName: ({ results }) => results?.entityType === "business" ? p34.text({
5771
6104
  message: "What is the name of the business?",
5772
6105
  placeholder: "My Company LLC",
5773
6106
  validate: (value) => {
@@ -5776,7 +6109,7 @@ var sharedFields = {
5776
6109
  }
5777
6110
  }
5778
6111
  }) : void 0,
5779
- businessAddress: ({ results }) => results?.entityType === "business" ? p32.text({
6112
+ businessAddress: ({ results }) => results?.entityType === "business" ? p34.text({
5780
6113
  message: "What is the address of the business?",
5781
6114
  placeholder: "1 Cupertino, CA 95014",
5782
6115
  validate: (value) => {
@@ -5785,7 +6118,7 @@ var sharedFields = {
5785
6118
  }
5786
6119
  }
5787
6120
  }) : void 0,
5788
- country: () => p32.text({
6121
+ country: () => p34.text({
5789
6122
  message: "Enter the country",
5790
6123
  validate: (value) => {
5791
6124
  if (!value) {
@@ -5793,7 +6126,7 @@ var sharedFields = {
5793
6126
  }
5794
6127
  }
5795
6128
  }),
5796
- state: () => p32.text({
6129
+ state: () => p34.text({
5797
6130
  message: "Enter the state",
5798
6131
  validate: (value) => {
5799
6132
  if (!value) {
@@ -5803,11 +6136,11 @@ var sharedFields = {
5803
6136
  })
5804
6137
  };
5805
6138
  var onCancel = () => {
5806
- p32.cancel("Operation cancelled.");
5807
- process20.exit(0);
6139
+ p34.cancel("Operation cancelled.");
6140
+ process22.exit(0);
5808
6141
  };
5809
6142
  async function contactMethods(type) {
5810
- const selection = await p32.multiselect({
6143
+ const selection = await p34.multiselect({
5811
6144
  message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
5812
6145
  options: [
5813
6146
  { value: "email", label: "By email" },
@@ -5816,11 +6149,11 @@ async function contactMethods(type) {
5816
6149
  { value: "mail", label: "By sending post mail" }
5817
6150
  ]
5818
6151
  });
5819
- if (p32.isCancel(selection)) onCancel();
6152
+ if (p34.isCancel(selection)) onCancel();
5820
6153
  const contact = selection;
5821
6154
  const details = {};
5822
6155
  if (contact.includes("email")) {
5823
- const email3 = await p32.text({
6156
+ const email3 = await p34.text({
5824
6157
  message: "What's the email?",
5825
6158
  placeholder: "office@mycompany.com",
5826
6159
  validate: (value) => {
@@ -5829,11 +6162,11 @@ async function contactMethods(type) {
5829
6162
  }
5830
6163
  }
5831
6164
  });
5832
- if (p32.isCancel(email3)) onCancel();
6165
+ if (p34.isCancel(email3)) onCancel();
5833
6166
  details.email = email3;
5834
6167
  }
5835
6168
  if (contact.includes("page")) {
5836
- const page = await p32.text({
6169
+ const page = await p34.text({
5837
6170
  message: "What's the link?",
5838
6171
  placeholder: "http://www.mycompany.com/contact",
5839
6172
  validate: (value) => {
@@ -5842,11 +6175,11 @@ async function contactMethods(type) {
5842
6175
  }
5843
6176
  }
5844
6177
  });
5845
- if (p32.isCancel(page)) onCancel();
6178
+ if (p34.isCancel(page)) onCancel();
5846
6179
  details.page = page;
5847
6180
  }
5848
6181
  if (contact.includes("phone")) {
5849
- const phone = await p32.text({
6182
+ const phone = await p34.text({
5850
6183
  message: "What's the phone number?",
5851
6184
  placeholder: "408.996.1010",
5852
6185
  validate: (value) => {
@@ -5855,11 +6188,11 @@ async function contactMethods(type) {
5855
6188
  }
5856
6189
  }
5857
6190
  });
5858
- if (p32.isCancel(phone)) onCancel();
6191
+ if (p34.isCancel(phone)) onCancel();
5859
6192
  details.phone = phone;
5860
6193
  }
5861
6194
  if (contact.includes("mail")) {
5862
- const address = await p32.text({
6195
+ const address = await p34.text({
5863
6196
  message: "What's the address?",
5864
6197
  placeholder: "767 Fifth Avenue New York, NY 10153, United States",
5865
6198
  validate: (value) => {
@@ -5868,7 +6201,7 @@ async function contactMethods(type) {
5868
6201
  }
5869
6202
  }
5870
6203
  });
5871
- if (p32.isCancel(address)) onCancel();
6204
+ if (p34.isCancel(address)) onCancel();
5872
6205
  details.address = address;
5873
6206
  }
5874
6207
  return { methods: contact, details };
@@ -6264,7 +6597,7 @@ var generateTermsHtml = (answers) => {
6264
6597
  };
6265
6598
  async function termsAction() {
6266
6599
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6267
- const core = await p33.group(
6600
+ const core = await p35.group(
6268
6601
  {
6269
6602
  websiteUrl: sharedFields.websiteUrl,
6270
6603
  websiteName: sharedFields.websiteName,
@@ -6276,25 +6609,25 @@ async function termsAction() {
6276
6609
  },
6277
6610
  { onCancel }
6278
6611
  );
6279
- const accounts = await p33.select({
6612
+ const accounts = await p35.select({
6280
6613
  message: "Can users create accounts?",
6281
6614
  options: [
6282
6615
  { value: "yes", label: "Yes, users can create accounts" },
6283
6616
  { value: "no", label: "No" }
6284
6617
  ]
6285
6618
  });
6286
- if (p33.isCancel(accounts)) onCancel();
6287
- const userContent = await p33.select({
6619
+ if (p35.isCancel(accounts)) onCancel();
6620
+ const userContent = await p35.select({
6288
6621
  message: "Can users create and/or upload content (ie. text, images)?",
6289
6622
  options: [
6290
6623
  { value: "yes", label: "Yes, users can create and/or upload content" },
6291
6624
  { value: "no", label: "No" }
6292
6625
  ]
6293
6626
  });
6294
- if (p33.isCancel(userContent)) onCancel();
6627
+ if (p35.isCancel(userContent)) onCancel();
6295
6628
  let infringementEmail;
6296
6629
  if (userContent === "yes") {
6297
- const email3 = await p33.text({
6630
+ const email3 = await p35.text({
6298
6631
  message: "What's the email address where you will receive infringements notices?",
6299
6632
  placeholder: "dmca@website.com",
6300
6633
  validate: (value) => {
@@ -6303,10 +6636,10 @@ async function termsAction() {
6303
6636
  }
6304
6637
  }
6305
6638
  });
6306
- if (p33.isCancel(email3)) onCancel();
6639
+ if (p35.isCancel(email3)) onCancel();
6307
6640
  infringementEmail = email3;
6308
6641
  }
6309
- const canBuyGoods = await p33.select({
6642
+ const canBuyGoods = await p35.select({
6310
6643
  message: "Can users buy goods (products, items)?",
6311
6644
  options: [
6312
6645
  {
@@ -6316,28 +6649,28 @@ async function termsAction() {
6316
6649
  { value: "no", label: "No" }
6317
6650
  ]
6318
6651
  });
6319
- if (p33.isCancel(canBuyGoods)) onCancel();
6320
- const subscriptions2 = await p33.select({
6652
+ if (p35.isCancel(canBuyGoods)) onCancel();
6653
+ const subscriptions2 = await p35.select({
6321
6654
  message: "Do you offer subscription plans?",
6322
6655
  options: [
6323
6656
  { value: "yes", label: "Yes, we offer subscription plans" },
6324
6657
  { value: "no", label: "No" }
6325
6658
  ]
6326
6659
  });
6327
- if (p33.isCancel(subscriptions2)) onCancel();
6660
+ if (p35.isCancel(subscriptions2)) onCancel();
6328
6661
  let freeTrial;
6329
6662
  if (subscriptions2 === "yes") {
6330
- const ft = await p33.select({
6663
+ const ft = await p35.select({
6331
6664
  message: "Do you offer a free trial?",
6332
6665
  options: [
6333
6666
  { value: "yes", label: "Yes" },
6334
6667
  { value: "no", label: "No" }
6335
6668
  ]
6336
6669
  });
6337
- if (p33.isCancel(ft)) onCancel();
6670
+ if (p35.isCancel(ft)) onCancel();
6338
6671
  freeTrial = ft;
6339
6672
  }
6340
- const exclusiveContent = await p33.select({
6673
+ const exclusiveContent = await p35.select({
6341
6674
  message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
6342
6675
  options: [
6343
6676
  {
@@ -6347,24 +6680,24 @@ async function termsAction() {
6347
6680
  { value: "no", label: "No" }
6348
6681
  ]
6349
6682
  });
6350
- if (p33.isCancel(exclusiveContent)) onCancel();
6351
- const feedbackReuse = await p33.select({
6683
+ if (p35.isCancel(exclusiveContent)) onCancel();
6684
+ const feedbackReuse = await p35.select({
6352
6685
  message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
6353
6686
  options: [
6354
6687
  { value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
6355
6688
  { value: "no", label: "No" }
6356
6689
  ]
6357
6690
  });
6358
- if (p33.isCancel(feedbackReuse)) onCancel();
6359
- const promotions = await p33.select({
6691
+ if (p35.isCancel(feedbackReuse)) onCancel();
6692
+ const promotions = await p35.select({
6360
6693
  message: "Do you plan to offer promotions, contests, sweepstakes?",
6361
6694
  options: [
6362
6695
  { value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
6363
6696
  { value: "no", label: "No" }
6364
6697
  ]
6365
6698
  });
6366
- if (p33.isCancel(promotions)) onCancel();
6367
- const mobileAppRaw = await p33.multiselect({
6699
+ if (p35.isCancel(promotions)) onCancel();
6700
+ const mobileAppRaw = await p35.multiselect({
6368
6701
  message: "Is the Service distributed through any mobile app stores? Check all that apply",
6369
6702
  options: [
6370
6703
  { value: "apple", label: "Apple App Store" },
@@ -6372,7 +6705,7 @@ async function termsAction() {
6372
6705
  ],
6373
6706
  required: false
6374
6707
  });
6375
- if (p33.isCancel(mobileAppRaw)) onCancel();
6708
+ if (p35.isCancel(mobileAppRaw)) onCancel();
6376
6709
  const mobileApp = mobileAppRaw ?? [];
6377
6710
  const contact = await contactMethods("terms");
6378
6711
  const html = generateTermsHtml({
@@ -6415,13 +6748,13 @@ async function termsAction() {
6415
6748
  ]
6416
6749
  });
6417
6750
  }
6418
- var terms = new Command49("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6751
+ var terms = new Command50("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6419
6752
 
6420
6753
  // src/commands/legal/privacy.ts
6421
6754
  import fs27 from "node:fs";
6422
6755
  import path24 from "node:path";
6423
- import { Command as Command50 } from "commander";
6424
- import * as p34 from "@clack/prompts";
6756
+ import { Command as Command51 } from "commander";
6757
+ import * as p36 from "@clack/prompts";
6425
6758
  var mapLabels = {
6426
6759
  personalInfo: {
6427
6760
  email: "Email address",
@@ -6839,12 +7172,12 @@ var generatePrivacyHtml = (answers) => {
6839
7172
  return `<section data-role="content">${sections.join("")}</section>`;
6840
7173
  };
6841
7174
  async function promptWithCustom(message, options, customMessage) {
6842
- const selection = await p34.multiselect({ message, options });
6843
- if (p34.isCancel(selection)) onCancel();
7175
+ const selection = await p36.multiselect({ message, options });
7176
+ if (p36.isCancel(selection)) onCancel();
6844
7177
  const values = selection;
6845
7178
  if (values.includes("custom")) {
6846
- const custom = await p34.text({ message: customMessage });
6847
- if (p34.isCancel(custom)) onCancel();
7179
+ const custom = await p36.text({ message: customMessage });
7180
+ if (p36.isCancel(custom)) onCancel();
6848
7181
  const idx = values.indexOf("custom");
6849
7182
  if (idx !== -1) values.splice(idx, 1);
6850
7183
  if (custom) values.push(String(custom));
@@ -6853,7 +7186,7 @@ async function promptWithCustom(message, options, customMessage) {
6853
7186
  }
6854
7187
  async function privacyAction() {
6855
7188
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6856
- const core = await p34.group(
7189
+ const core = await p36.group(
6857
7190
  {
6858
7191
  websiteUrl: sharedFields.websiteUrl,
6859
7192
  websiteName: sharedFields.websiteName,
@@ -6865,7 +7198,7 @@ async function privacyAction() {
6865
7198
  },
6866
7199
  { onCancel }
6867
7200
  );
6868
- const personalInfo = await p34.multiselect({
7201
+ const personalInfo = await p36.multiselect({
6869
7202
  message: "What kind of personal information do you collect from users? Check all that apply",
6870
7203
  options: [
6871
7204
  { value: "email", label: "Email address" },
@@ -6880,16 +7213,16 @@ async function privacyAction() {
6880
7213
  ],
6881
7214
  required: false
6882
7215
  });
6883
- if (p34.isCancel(personalInfo)) onCancel();
7216
+ if (p36.isCancel(personalInfo)) onCancel();
6884
7217
  const contact = await contactMethods("privacy");
6885
- const tracking = await p34.select({
7218
+ const tracking = await p36.select({
6886
7219
  message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
6887
7220
  options: [
6888
7221
  { value: "yes", label: "Yes, we use Google Analytics or other related tools" },
6889
7222
  { value: "no", label: "No" }
6890
7223
  ]
6891
7224
  });
6892
- if (p34.isCancel(tracking)) onCancel();
7225
+ if (p36.isCancel(tracking)) onCancel();
6893
7226
  let trackingTools;
6894
7227
  if (tracking === "yes") {
6895
7228
  trackingTools = await promptWithCustom(
@@ -6908,7 +7241,7 @@ async function privacyAction() {
6908
7241
  "Enter your custom tracking/analytics tool name"
6909
7242
  );
6910
7243
  }
6911
- const sendEmails = await p34.select({
7244
+ const sendEmails = await p36.select({
6912
7245
  message: "Do you send emails to users?",
6913
7246
  options: [
6914
7247
  {
@@ -6918,7 +7251,7 @@ async function privacyAction() {
6918
7251
  { value: "no", label: "No" }
6919
7252
  ]
6920
7253
  });
6921
- if (p34.isCancel(sendEmails)) onCancel();
7254
+ if (p36.isCancel(sendEmails)) onCancel();
6922
7255
  let emailPlatforms;
6923
7256
  if (sendEmails === "yes") {
6924
7257
  emailPlatforms = await promptWithCustom(
@@ -6933,14 +7266,14 @@ async function privacyAction() {
6933
7266
  "Enter your custom email platform"
6934
7267
  );
6935
7268
  }
6936
- const showAds = await p34.select({
7269
+ const showAds = await p36.select({
6937
7270
  message: "Do you show ads?",
6938
7271
  options: [
6939
7272
  { value: "yes", label: "Yes, we show ads" },
6940
7273
  { value: "no", label: "No" }
6941
7274
  ]
6942
7275
  });
6943
- if (p34.isCancel(showAds)) onCancel();
7276
+ if (p36.isCancel(showAds)) onCancel();
6944
7277
  let adsPlatforms;
6945
7278
  if (showAds === "yes") {
6946
7279
  adsPlatforms = await promptWithCustom(
@@ -6963,7 +7296,7 @@ async function privacyAction() {
6963
7296
  "Enter your custom ads platform"
6964
7297
  );
6965
7298
  }
6966
- const canPay = await p34.select({
7299
+ const canPay = await p36.select({
6967
7300
  message: "Can users pay for products or services?",
6968
7301
  options: [
6969
7302
  { value: "yes", label: "Yes, users can pay for our products/services" },
@@ -6973,7 +7306,7 @@ async function privacyAction() {
6973
7306
  }
6974
7307
  ]
6975
7308
  });
6976
- if (p34.isCancel(canPay)) onCancel();
7309
+ if (p36.isCancel(canPay)) onCancel();
6977
7310
  let paymentProcessors;
6978
7311
  if (canPay === "yes") {
6979
7312
  paymentProcessors = await promptWithCustom(
@@ -7004,14 +7337,14 @@ async function privacyAction() {
7004
7337
  "Enter your custom payment processor/method"
7005
7338
  );
7006
7339
  }
7007
- const remarketing = await p34.select({
7340
+ const remarketing = await p36.select({
7008
7341
  message: "Do you use remarketing services for marketing & advertising purposes?",
7009
7342
  options: [
7010
7343
  { value: "yes", label: "Yes, we use remarketing services to advertise our business" },
7011
7344
  { value: "no", label: "No" }
7012
7345
  ]
7013
7346
  });
7014
- if (p34.isCancel(remarketing)) onCancel();
7347
+ if (p36.isCancel(remarketing)) onCancel();
7015
7348
  let remarketingPlatforms;
7016
7349
  if (remarketing === "yes") {
7017
7350
  remarketingPlatforms = await promptWithCustom(
@@ -7030,7 +7363,7 @@ async function privacyAction() {
7030
7363
  "Enter your custom remarketing platform"
7031
7364
  );
7032
7365
  }
7033
- const providersRaw = await p34.multiselect({
7366
+ const providersRaw = await p36.multiselect({
7034
7367
  message: "Select if you use any of the following providers",
7035
7368
  options: [
7036
7369
  { value: "recaptcha", label: "Invisible reCAPTCHA" },
@@ -7041,16 +7374,16 @@ async function privacyAction() {
7041
7374
  ],
7042
7375
  required: false
7043
7376
  });
7044
- if (p34.isCancel(providersRaw)) onCancel();
7377
+ if (p36.isCancel(providersRaw)) onCancel();
7045
7378
  const providers = providersRaw;
7046
7379
  if (providers.includes("custom")) {
7047
- const custom = await p34.text({ message: "Enter your custom provider" });
7048
- if (p34.isCancel(custom)) onCancel();
7380
+ const custom = await p36.text({ message: "Enter your custom provider" });
7381
+ if (p36.isCancel(custom)) onCancel();
7049
7382
  const idx = providers.indexOf("custom");
7050
7383
  if (idx !== -1) providers.splice(idx, 1);
7051
7384
  if (custom) providers.push(String(custom));
7052
7385
  }
7053
- const usStates = await p34.select({
7386
+ const usStates = await p36.select({
7054
7387
  message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
7055
7388
  options: [
7056
7389
  {
@@ -7061,55 +7394,55 @@ async function privacyAction() {
7061
7394
  ],
7062
7395
  initialValue: "yes"
7063
7396
  });
7064
- if (p34.isCancel(usStates)) onCancel();
7065
- const gdpr = await p34.select({
7397
+ if (p36.isCancel(usStates)) onCancel();
7398
+ const gdpr = await p36.select({
7066
7399
  message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
7067
7400
  options: [
7068
7401
  { value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
7069
7402
  { value: "no", label: "No" }
7070
7403
  ]
7071
7404
  });
7072
- if (p34.isCancel(gdpr)) onCancel();
7405
+ if (p36.isCancel(gdpr)) onCancel();
7073
7406
  let facebookFanPage = "no";
7074
7407
  const facebookDetails = { name: "", url: "" };
7075
7408
  if (gdpr === "yes") {
7076
- const fan = await p34.select({
7409
+ const fan = await p36.select({
7077
7410
  message: "Do you have a Facebook Fan Page?",
7078
7411
  options: [
7079
7412
  { value: "yes", label: "Yes, we have a Facebook Fan Page" },
7080
7413
  { value: "no", label: "No" }
7081
7414
  ]
7082
7415
  });
7083
- if (p34.isCancel(fan)) onCancel();
7416
+ if (p36.isCancel(fan)) onCancel();
7084
7417
  facebookFanPage = fan;
7085
7418
  if (facebookFanPage === "yes") {
7086
- const name = await p34.text({
7419
+ const name = await p36.text({
7087
7420
  message: "What is the name of the Facebook Fan Page?",
7088
7421
  placeholder: "My Facebook Page"
7089
7422
  });
7090
- if (p34.isCancel(name)) onCancel();
7423
+ if (p36.isCancel(name)) onCancel();
7091
7424
  facebookDetails.name = name;
7092
- const url = await p34.text({
7425
+ const url = await p36.text({
7093
7426
  message: "What is the URL of the Facebook Fan Page?",
7094
7427
  placeholder: "https://facebook.com/my-facebook-page"
7095
7428
  });
7096
- if (p34.isCancel(url)) onCancel();
7429
+ if (p36.isCancel(url)) onCancel();
7097
7430
  facebookDetails.url = url;
7098
7431
  }
7099
7432
  }
7100
- const kids = await p34.select({
7433
+ const kids = await p36.select({
7101
7434
  message: "Do you collect information from kids under the age of 13?",
7102
7435
  options: [
7103
7436
  { value: "yes", label: "Yes. We collect information from children under the age of 13" },
7104
7437
  { value: "no", label: "No" }
7105
7438
  ]
7106
7439
  });
7107
- if (p34.isCancel(kids)) onCancel();
7108
- const retention = await p34.text({
7440
+ if (p36.isCancel(kids)) onCancel();
7441
+ const retention = await p36.text({
7109
7442
  message: "How long do you retain personal information? (leave blank for default wording)",
7110
7443
  placeholder: "e.g. 12 months after account closure"
7111
7444
  });
7112
- if (p34.isCancel(retention)) onCancel();
7445
+ if (p36.isCancel(retention)) onCancel();
7113
7446
  const html = generatePrivacyHtml({
7114
7447
  core,
7115
7448
  personalInfo: personalInfo ?? [],
@@ -7164,16 +7497,16 @@ async function privacyAction() {
7164
7497
  ]
7165
7498
  });
7166
7499
  }
7167
- var privacy = new Command50("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7500
+ var privacy = new Command51("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7168
7501
 
7169
7502
  // src/commands/legal.ts
7170
- var legal = new Command51("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7503
+ var legal = new Command52("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7171
7504
 
7172
7505
  // src/commands/fixtures.ts
7173
- import { Command as Command57 } from "commander";
7506
+ import { Command as Command58 } from "commander";
7174
7507
 
7175
7508
  // src/commands/fixtures/load.ts
7176
- import { Command as Command52 } from "commander";
7509
+ import { Command as Command53 } from "commander";
7177
7510
 
7178
7511
  // src/lib/data.ts
7179
7512
  import fs28 from "node:fs";
@@ -7363,7 +7696,7 @@ async function hasLoadedFixtures(pb) {
7363
7696
  }
7364
7697
 
7365
7698
  // src/commands/fixtures/load.ts
7366
- var load = new Command52("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7699
+ var load = new Command53("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7367
7700
  () => runCommand(async () => {
7368
7701
  const { workspaceRootDir } = await getWorkspace();
7369
7702
  let loaded = [];
@@ -7389,8 +7722,8 @@ var load = new Command52("load").description("load fixtures into the database").
7389
7722
  );
7390
7723
 
7391
7724
  // src/commands/fixtures/clear.ts
7392
- import { Command as Command53 } from "commander";
7393
- var clear = new Command53("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7725
+ import { Command as Command54 } from "commander";
7726
+ var clear = new Command54("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7394
7727
  () => runCommand(async () => {
7395
7728
  const { workspaceRootDir } = await getWorkspace();
7396
7729
  let cleared = [];
@@ -7419,8 +7752,8 @@ var clear = new Command53("clear").description("clear loaded fixtures").configur
7419
7752
  );
7420
7753
 
7421
7754
  // src/commands/fixtures/reset.ts
7422
- import { Command as Command54 } from "commander";
7423
- var reset = new Command54("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7755
+ import { Command as Command55 } from "commander";
7756
+ var reset = new Command55("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7424
7757
  () => runCommand(async () => {
7425
7758
  const { workspaceRootDir } = await getWorkspace();
7426
7759
  let cleared = [];
@@ -7452,8 +7785,8 @@ var reset = new Command54("reset").description("clear and reload fixtures").conf
7452
7785
  // src/commands/fixtures/generate.ts
7453
7786
  import fs29 from "node:fs";
7454
7787
  import path26 from "node:path";
7455
- import { Command as Command55, InvalidArgumentError } from "commander";
7456
- import * as p35 from "@clack/prompts";
7788
+ import { Command as Command56, InvalidArgumentError } from "commander";
7789
+ import * as p37 from "@clack/prompts";
7457
7790
  import { annotate } from "annotate-json-schema";
7458
7791
  import { createGenerator } from "json-schema-faker";
7459
7792
  import { faker } from "@faker-js/faker";
@@ -7563,7 +7896,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
7563
7896
  }
7564
7897
  return { writtenFiles, warnings };
7565
7898
  }
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(
7899
+ var generate2 = new Command56("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(
7567
7900
  (opts) => runCommand(async () => {
7568
7901
  const { workspaceRootDir } = await getWorkspace();
7569
7902
  const existing = getFixtureFiles(workspaceRootDir);
@@ -7592,7 +7925,7 @@ var generate2 = new Command55("generate").description("generate fixture data").o
7592
7925
  seed: opts.seed
7593
7926
  });
7594
7927
  });
7595
- for (const warning of result.warnings) p35.log.warn(warning);
7928
+ for (const warning of result.warnings) p37.log.warn(warning);
7596
7929
  if (result.writtenFiles.length === 0) {
7597
7930
  reportResult({
7598
7931
  summary: "No eligible collections found to generate fixtures for.",
@@ -7616,8 +7949,8 @@ var generate2 = new Command55("generate").description("generate fixture data").o
7616
7949
  );
7617
7950
 
7618
7951
  // src/commands/fixtures/regen.ts
7619
- import { Command as Command56, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7620
- import * as p36 from "@clack/prompts";
7952
+ import { Command as Command57, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7953
+ import * as p38 from "@clack/prompts";
7621
7954
  function parseCount2(value) {
7622
7955
  const n = parseInt(value, 10);
7623
7956
  if (!Number.isFinite(n) || n <= 0 || n > 999) {
@@ -7632,7 +7965,7 @@ function parseSeed2(value) {
7632
7965
  }
7633
7966
  return n;
7634
7967
  }
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(
7968
+ var regen = new Command57("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(
7636
7969
  (opts) => runCommand(async () => {
7637
7970
  const { workspaceRootDir } = await getWorkspace();
7638
7971
  let cleared = [];
@@ -7646,7 +7979,7 @@ var regen = new Command56("regen").description("clear the database, regenerate f
7646
7979
  });
7647
7980
  loaded = await loadFixtures(pb, workspaceRootDir);
7648
7981
  });
7649
- for (const warning of result.warnings) p36.log.warn(warning);
7982
+ for (const warning of result.warnings) p38.log.warn(warning);
7650
7983
  reportResult({
7651
7984
  summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
7652
7985
  filesCreated: result.writtenFiles,
@@ -7661,14 +7994,14 @@ var regen = new Command56("regen").description("clear the database, regenerate f
7661
7994
  );
7662
7995
 
7663
7996
  // src/commands/fixtures.ts
7664
- var fixtures = new Command57("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7997
+ var fixtures = new Command58("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7665
7998
 
7666
7999
  // src/commands/seeds.ts
7667
- import { Command as Command61 } from "commander";
8000
+ import { Command as Command62 } from "commander";
7668
8001
 
7669
8002
  // src/commands/seeds/load.ts
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(
8003
+ import { Command as Command59 } from "commander";
8004
+ var load2 = new Command59("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
7672
8005
  (opts) => runCommand(async () => {
7673
8006
  const { workspaceRootDir } = await getWorkspace();
7674
8007
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7707,7 +8040,7 @@ var load2 = new Command58("load").description("load seeds into the database").op
7707
8040
  // src/commands/seeds/save.ts
7708
8041
  import fs30 from "node:fs";
7709
8042
  import path27 from "node:path";
7710
- import { Command as Command59 } from "commander";
8043
+ import { Command as Command60 } from "commander";
7711
8044
  var padZeros2 = (num, length) => num.toString().padStart(length, "0");
7712
8045
  function filterSystemFields(record, systemFieldNames) {
7713
8046
  const out = {};
@@ -7718,7 +8051,7 @@ function filterSystemFields(record, systemFieldNames) {
7718
8051
  }
7719
8052
  return out;
7720
8053
  }
7721
- var save = new Command59("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
8054
+ var save = new Command60("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7722
8055
  (opts) => runCommand(async () => {
7723
8056
  const { workspaceRootDir } = await getWorkspace();
7724
8057
  const seedsPath = dataDir(workspaceRootDir, "seeds");
@@ -7790,8 +8123,8 @@ var save = new Command59("save").description("save the current data as seeds").o
7790
8123
  );
7791
8124
 
7792
8125
  // src/commands/seeds/clear.ts
7793
- import { Command as Command60 } from "commander";
7794
- var clear2 = new Command60("clear").description("clear seeded records").configureHelp(helpConfig).action(
8126
+ import { Command as Command61 } from "commander";
8127
+ var clear2 = new Command61("clear").description("clear seeded records").configureHelp(helpConfig).action(
7795
8128
  () => runCommand(async () => {
7796
8129
  const { workspaceRootDir } = await getWorkspace();
7797
8130
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7822,91 +8155,18 @@ var clear2 = new Command60("clear").description("clear seeded records").configur
7822
8155
  );
7823
8156
 
7824
8157
  // src/commands/seeds.ts
7825
- var seeds = new Command61("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
8158
+ var seeds = new Command62("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7826
8159
 
7827
8160
  // src/commands/signup.ts
7828
8161
  import { Command as Command63 } from "commander";
7829
- import * as p38 from "@clack/prompts";
8162
+ import * as p39 from "@clack/prompts";
7830
8163
  import makeFetchCookie2 from "fetch-cookie";
7831
-
7832
- // src/commands/login.ts
7833
- import os4 from "node:os";
7834
- import { Command as Command62 } from "commander";
7835
- import * as p37 from "@clack/prompts";
7836
- import makeFetchCookie from "fetch-cookie";
7837
- var login = new Command62("login").description("login to velastack.dev").configureHelp(helpConfig).action(
7838
- () => runCommand(async () => {
7839
- const { email: email3, password: password11 } = await p37.group({
7840
- email: () => p37.text({ message: "Email" }),
7841
- password: () => p37.password({ message: "Password" })
7842
- });
7843
- const fetchCookie = makeFetchCookie(fetch);
7844
- const loginRes = await fetchCookie(`${API_URL}/login`, {
7845
- method: "POST",
7846
- headers: {
7847
- "Content-Type": "application/x-www-form-urlencoded",
7848
- Origin: API_URL
7849
- },
7850
- body: new URLSearchParams({
7851
- type: "password",
7852
- email: email3,
7853
- password: password11
7854
- }).toString()
7855
- });
7856
- if (!loginRes.headers.get("Set-Cookie")) {
7857
- throw new Error(
7858
- "Run `vela signup` to create an account or reset at https://velastack.dev/reset"
7859
- );
7860
- }
7861
- const apiKey = await issueApiKey(fetchCookie);
7862
- writeConfig({ apiKey });
7863
- p37.log.success("Logged in to velastack.dev");
7864
- }, "Failed to login.")
7865
- );
7866
- async function issueApiKey(fetchCookie) {
7867
- const label4 = `CLI - ${os4.hostname()}`;
7868
- await fetchCookie(`${API_URL}/api-keys/new`, {
7869
- method: "POST",
7870
- headers: {
7871
- "Content-Type": "application/x-www-form-urlencoded",
7872
- Origin: API_URL
7873
- },
7874
- body: new URLSearchParams({ label: label4 }).toString()
7875
- });
7876
- const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
7877
- const apiKey = extractApiKey(cookie);
7878
- if (!apiKey) {
7879
- throw new Error("Failed to create API key. Try again or contact support.");
7880
- }
7881
- const [id] = apiKey.split(".");
7882
- const res = await fetchCookie(`${API_URL}/api/collections/api_keys/records`, {
7883
- headers: { Authorization: `Bearer ${apiKey}` }
7884
- });
7885
- const data = await res.json();
7886
- for (const item of data.items) {
7887
- if (item.label === label4 && item.id !== id) {
7888
- await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
7889
- method: "DELETE",
7890
- headers: { Authorization: `Bearer ${apiKey}` }
7891
- });
7892
- }
7893
- }
7894
- return apiKey;
7895
- }
7896
- function extractApiKey(cookie) {
7897
- const flashCookie = cookie.split(";").find((c) => c.trim().startsWith("flash="));
7898
- if (!flashCookie) return null;
7899
- const decoded = decodeURIComponent(flashCookie.split("=")[1]);
7900
- return JSON.parse(decoded).apiKey;
7901
- }
7902
-
7903
- // src/commands/signup.ts
7904
8164
  var signup = new Command63("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7905
8165
  () => runCommand(async () => {
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" })
8166
+ const { email: email3, password: password11, passwordConfirm } = await p39.group({
8167
+ email: () => p39.text({ message: "Email" }),
8168
+ password: () => p39.password({ message: "Password" }),
8169
+ passwordConfirm: () => p39.password({ message: "Confirm password" })
7910
8170
  });
7911
8171
  if (password11 !== passwordConfirm) {
7912
8172
  throw new Error("Passwords do not match.");
@@ -7930,33 +8190,33 @@ var signup = new Command63("signup").description("signup to velastack.dev").conf
7930
8190
  }
7931
8191
  const apiKey = await issueApiKey(fetchCookie);
7932
8192
  writeConfig({ apiKey });
7933
- p38.log.success("Signed up to velastack.dev");
7934
- p38.log.info("Check your email for a confirmation link.");
8193
+ p39.log.success("Signed up to velastack.dev");
8194
+ p39.log.info("Check your email for a confirmation link.");
7935
8195
  }, "Failed to signup.")
7936
8196
  );
7937
8197
 
7938
8198
  // src/commands/logout.ts
7939
8199
  import { Command as Command64 } from "commander";
7940
- import * as p39 from "@clack/prompts";
8200
+ import * as p40 from "@clack/prompts";
7941
8201
  var logout = new Command64("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7942
8202
  () => runCommand(() => {
7943
8203
  if (!readConfig()) {
7944
- p39.log.info("Not logged in");
8204
+ p40.log.info("Not logged in");
7945
8205
  return;
7946
8206
  }
7947
8207
  clearConfig();
7948
- p39.log.success("Logged out of velastack.dev");
8208
+ p40.log.success("Logged out of velastack.dev");
7949
8209
  })
7950
8210
  );
7951
8211
 
7952
8212
  // src/commands/whoami.ts
7953
8213
  import { Command as Command65 } from "commander";
7954
- import * as p40 from "@clack/prompts";
8214
+ import * as p41 from "@clack/prompts";
7955
8215
  var whoami = new Command65("whoami").description("show the current user").configureHelp(helpConfig).action(
7956
8216
  () => runCommand(async () => {
7957
8217
  const apiKey = readConfig()?.apiKey;
7958
8218
  if (!apiKey) {
7959
- p40.log.info("Not logged in. Run `vela login` to login.");
8219
+ p41.log.info("Not logged in. Run `vela login` to login.");
7960
8220
  return;
7961
8221
  }
7962
8222
  const res = await fetch(`${API_URL}/api/collections/users/records`, {
@@ -7964,7 +8224,7 @@ var whoami = new Command65("whoami").description("show the current user").config
7964
8224
  });
7965
8225
  const data = await res.json();
7966
8226
  if (!data.items.length) throw new Error("No user found. Run `vela login` to login.");
7967
- p40.log.success(`Logged in as ${data.items[0].email}`);
8227
+ p41.log.success(`Logged in as ${data.items[0].email}`);
7968
8228
  })
7969
8229
  );
7970
8230
 
@@ -7976,10 +8236,10 @@ import { Command as Command66 } from "commander";
7976
8236
 
7977
8237
  // src/lib/migrate.ts
7978
8238
  import path28 from "node:path";
7979
- import process21 from "node:process";
8239
+ import process23 from "node:process";
7980
8240
  import { x as x2 } from "tinyexec";
7981
8241
  async function runPocketbaseMigrate(args) {
7982
- const cwd = process21.cwd();
8242
+ const cwd = process23.cwd();
7983
8243
  const { getBinaryPath } = await import("pocketbase-server");
7984
8244
  const binaryPath = getBinaryPath();
7985
8245
  await x2(
@@ -8038,11 +8298,11 @@ var down = new Command67("down").alias("rollback").description("revert the last
8038
8298
  // src/commands/migrate/create.ts
8039
8299
  import fs31 from "node:fs";
8040
8300
  import path29 from "node:path";
8041
- import process22 from "node:process";
8301
+ import process24 from "node:process";
8042
8302
  import { Command as Command68 } from "commander";
8043
8303
  var create2 = new Command68("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
8044
8304
  (name) => runCommand(async () => {
8045
- const cwd = process22.cwd();
8305
+ const cwd = process24.cwd();
8046
8306
  const before = listMigrationFiles(cwd);
8047
8307
  await runPocketbaseMigrate(["create", name]);
8048
8308
  const after = listMigrationFiles(cwd);
@@ -8066,11 +8326,11 @@ function listMigrationFiles(cwd) {
8066
8326
  // src/commands/migrate/collections.ts
8067
8327
  import fs32 from "node:fs";
8068
8328
  import path30 from "node:path";
8069
- import process23 from "node:process";
8329
+ import process25 from "node:process";
8070
8330
  import { Command as Command69 } from "commander";
8071
8331
  var collections = new Command69("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
8072
8332
  () => runCommand(async () => {
8073
- const cwd = process23.cwd();
8333
+ const cwd = process25.cwd();
8074
8334
  const before = listMigrationFiles2(cwd);
8075
8335
  await runPocketbaseMigrate(["collections"]);
8076
8336
  const after = listMigrationFiles2(cwd);
@@ -8116,7 +8376,7 @@ var migrate = new Command71("migrate").description("manage database migrations")
8116
8376
  // src/commands/dev.ts
8117
8377
  import fs33 from "node:fs";
8118
8378
  import path32 from "node:path";
8119
- import process25 from "node:process";
8379
+ import process27 from "node:process";
8120
8380
  import { performance } from "node:perf_hooks";
8121
8381
  import { Command as Command72, InvalidArgumentError as InvalidArgumentError4 } from "commander";
8122
8382
  import pc15 from "picocolors";
@@ -8124,7 +8384,7 @@ import PocketBase4 from "pocketbase";
8124
8384
 
8125
8385
  // src/lib/vite.ts
8126
8386
  import path31 from "node:path";
8127
- import process24 from "node:process";
8387
+ import process26 from "node:process";
8128
8388
  import { createRequire as createRequire2 } from "node:module";
8129
8389
  import { pathToFileURL as pathToFileURL2 } from "node:url";
8130
8390
  import pc14 from "picocolors";
@@ -8148,13 +8408,13 @@ function resolveProjectVite(cwd) {
8148
8408
  return null;
8149
8409
  }
8150
8410
  }
8151
- async function loadVite(cwd = process24.cwd()) {
8411
+ async function loadVite(cwd = process26.cwd()) {
8152
8412
  const entry = resolveProjectVite(cwd);
8153
8413
  const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
8154
8414
  const error = viteVersionError(vite.version);
8155
8415
  if (error) {
8156
8416
  console.error(`${pc14.redBright("\u2717")} ${error}`);
8157
- process24.exit(1);
8417
+ process26.exit(1);
8158
8418
  }
8159
8419
  return vite;
8160
8420
  }
@@ -8168,15 +8428,15 @@ function parsePort(value) {
8168
8428
  return port;
8169
8429
  }
8170
8430
  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);
8431
+ const cwd = process27.cwd();
8432
+ process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
8173
8433
  const startTime = performance.now();
8174
8434
  const { createServer, version } = await loadVite(cwd);
8175
8435
  const viteMetadataDir = path32.join(cwd, "node_modules", ".vite");
8176
8436
  const viteMetadataFile = path32.join(viteMetadataDir, "_pocketbase_metadata.json");
8177
8437
  let pbProc;
8178
8438
  const backend3 = hasBackend(cwd);
8179
- const needsStart = backend3 && !process25.env.POCKETBASE_URL;
8439
+ const needsStart = backend3 && !process27.env.POCKETBASE_URL;
8180
8440
  const cleanup = () => {
8181
8441
  if (pbProc?.pid) pbProc.kill();
8182
8442
  if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
@@ -8191,15 +8451,15 @@ var dev = new Command72("dev").description("start the development server").optio
8191
8451
  stdio: "pipe"
8192
8452
  });
8193
8453
  pbProc = started.proc;
8194
- process25.env.POCKETBASE_URL = started.url;
8195
- pbProc.stdout?.pipe(process25.stdout);
8196
- pbProc.stderr?.pipe(process25.stderr);
8454
+ process27.env.POCKETBASE_URL = started.url;
8455
+ pbProc.stdout?.pipe(process27.stdout);
8456
+ pbProc.stderr?.pipe(process27.stderr);
8197
8457
  pbProc.on("error", (err) => console.error("PocketBase error:", err));
8198
8458
  pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
8199
- process25.on("exit", cleanup);
8200
- process25.on("SIGINT", () => {
8459
+ process27.on("exit", cleanup);
8460
+ process27.on("SIGINT", () => {
8201
8461
  cleanup();
8202
- process25.exit(0);
8462
+ process27.exit(0);
8203
8463
  });
8204
8464
  }
8205
8465
  const serverOptions = {};
@@ -8221,21 +8481,21 @@ var dev = new Command72("dev").description("start the development server").optio
8221
8481
  await fs33.promises.writeFile(
8222
8482
  viteMetadataFile,
8223
8483
  JSON.stringify({
8224
- pocketbaseUrl: process25.env.POCKETBASE_URL,
8484
+ pocketbaseUrl: process27.env.POCKETBASE_URL,
8225
8485
  vitePort,
8226
8486
  viteHost
8227
8487
  })
8228
8488
  );
8229
- const pb = new PocketBase4(process25.env.POCKETBASE_URL);
8489
+ const pb = new PocketBase4(process27.env.POCKETBASE_URL);
8230
8490
  await pb.collection("_superusers").authWithPassword(
8231
- process25.env.POCKETBASE_SUPERUSER_EMAIL,
8232
- process25.env.POCKETBASE_SUPERUSER_PASSWORD
8491
+ process27.env.POCKETBASE_SUPERUSER_EMAIL,
8492
+ process27.env.POCKETBASE_SUPERUSER_PASSWORD
8233
8493
  );
8234
8494
  await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
8235
8495
  await startWatchingTypes(cwd, pb);
8236
8496
  });
8237
8497
  await server.listen();
8238
- const hasExistingLogs = process25.stdout.bytesWritten > 0 || process25.stderr.bytesWritten > 0;
8498
+ const hasExistingLogs = process27.stdout.bytesWritten > 0 || process27.stderr.bytesWritten > 0;
8239
8499
  const startupDurationString = pc15.dim(
8240
8500
  `ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
8241
8501
  );
@@ -8275,9 +8535,9 @@ async function startWatchingTypes(cwd, pb) {
8275
8535
  // src/commands/build.ts
8276
8536
  import fs34 from "node:fs";
8277
8537
  import path33 from "node:path";
8278
- import process27 from "node:process";
8538
+ import process29 from "node:process";
8279
8539
  import { Command as Command73 } from "commander";
8280
- import * as p41 from "@clack/prompts";
8540
+ import * as p42 from "@clack/prompts";
8281
8541
  import pc16 from "picocolors";
8282
8542
  import { x as x3 } from "tinyexec";
8283
8543
  import { detect as detect5 } from "package-manager-detector";
@@ -8290,10 +8550,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
8290
8550
  }
8291
8551
 
8292
8552
  // src/lib/origin.ts
8293
- import process26 from "node:process";
8553
+ import process28 from "node:process";
8294
8554
  function resolveOrigin(workspaceRootDir, envTag, config = {}) {
8295
8555
  return normalizeOrigin(
8296
- process26.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8556
+ process28.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8297
8557
  );
8298
8558
  }
8299
8559
  function normalizeOrigin(value) {
@@ -8314,12 +8574,12 @@ function splitHosts(value) {
8314
8574
  // src/commands/build.ts
8315
8575
  var PRERENDERED_DIR = path33.join(".svelte-kit", "output", "prerendered");
8316
8576
  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();
8577
+ const cwd = process29.cwd();
8318
8578
  applyBuildEnv(cwd);
8319
8579
  const origin = await originForBuild(cwd, options.target);
8320
- if (origin) process27.env.VELA_ORIGIN = origin;
8580
+ if (origin) process29.env.VELA_ORIGIN = origin;
8321
8581
  let pbProc;
8322
- const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
8582
+ const needsStart = hasBackend(cwd) && !process29.env.POCKETBASE_URL;
8323
8583
  const cleanup = () => {
8324
8584
  if (pbProc?.pid) pbProc.kill();
8325
8585
  };
@@ -8333,11 +8593,11 @@ var build = new Command73("build").description("build the app").configureHelp(he
8333
8593
  dev: true
8334
8594
  });
8335
8595
  pbProc = started.proc;
8336
- process27.env.POCKETBASE_URL = started.url;
8337
- process27.on("exit", cleanup);
8338
- process27.on("SIGINT", () => {
8596
+ process29.env.POCKETBASE_URL = started.url;
8597
+ process29.on("exit", cleanup);
8598
+ process29.on("SIGINT", () => {
8339
8599
  cleanup();
8340
- process27.exit(0);
8600
+ process29.exit(0);
8341
8601
  });
8342
8602
  }
8343
8603
  try {
@@ -8370,7 +8630,7 @@ async function originForBuild(cwd, target) {
8370
8630
  function warnIfPrerendered(cwd) {
8371
8631
  const dir = path33.join(cwd, PRERENDERED_DIR);
8372
8632
  if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
8373
- p41.log.warn(
8633
+ p42.log.warn(
8374
8634
  `Prerendered pages were built with no domain configured, so their canonical
8375
8635
  links point at SvelteKit's placeholder host rather than at this site.
8376
8636
 
@@ -8380,16 +8640,16 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
8380
8640
 
8381
8641
  // src/commands/preview.ts
8382
8642
  import path34 from "node:path";
8383
- import process28 from "node:process";
8643
+ import process30 from "node:process";
8384
8644
  import { Command as Command74 } from "commander";
8385
8645
  import { x as x4 } from "tinyexec";
8386
8646
  import { detect as detect6 } from "package-manager-detector";
8387
8647
  import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
8388
8648
  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);
8649
+ const cwd = process30.cwd();
8650
+ process30.env.VELA_DATA_DIR ??= localDataDir(cwd);
8391
8651
  let pbProc;
8392
- const needsStart = hasBackend(cwd) && !process28.env.POCKETBASE_URL;
8652
+ const needsStart = hasBackend(cwd) && !process30.env.POCKETBASE_URL;
8393
8653
  const cleanup = () => {
8394
8654
  if (pbProc?.pid) pbProc.kill();
8395
8655
  };
@@ -8402,11 +8662,11 @@ var preview = new Command74("preview").description("preview the built app").conf
8402
8662
  dev: true
8403
8663
  });
8404
8664
  pbProc = started.proc;
8405
- process28.env.POCKETBASE_URL = started.url;
8406
- process28.on("exit", cleanup);
8407
- process28.on("SIGINT", () => {
8665
+ process30.env.POCKETBASE_URL = started.url;
8666
+ process30.on("exit", cleanup);
8667
+ process30.on("SIGINT", () => {
8408
8668
  cleanup();
8409
- process28.exit(0);
8669
+ process30.exit(0);
8410
8670
  });
8411
8671
  }
8412
8672
  try {
@@ -8440,7 +8700,7 @@ var sync = new Command75("sync").description("sync types from the database").con
8440
8700
 
8441
8701
  // src/commands/provision.ts
8442
8702
  import { Command as Command76 } from "commander";
8443
- import * as p42 from "@clack/prompts";
8703
+ import * as p43 from "@clack/prompts";
8444
8704
  import pc17 from "picocolors";
8445
8705
  import * as v7 from "valibot";
8446
8706
  var OptionsSchema2 = v7.object({
@@ -8454,19 +8714,19 @@ var provision = addSshOptions(
8454
8714
  (target, raw) => runCommand(async () => {
8455
8715
  const options = parseOptions(OptionsSchema2, raw);
8456
8716
  const pbVersion = options.pbVersion ?? pocketbaseVersion();
8457
- p42.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8458
- p42.log.info(`Target ${pc17.cyan(target)}`);
8717
+ p43.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8718
+ p43.log.info(`Target ${pc17.cyan(target)}`);
8459
8719
  await withSsh(target, sshOptionsFrom(options), async (session) => {
8460
8720
  await session.detectElevation();
8461
8721
  const existing = await readServerInfo(session);
8462
8722
  if (existing) {
8463
- p42.log.info(
8723
+ p43.log.info(
8464
8724
  `Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
8465
8725
  );
8466
8726
  }
8467
- p42.log.step("Uploading server scripts");
8727
+ p43.log.step("Uploading server scripts");
8468
8728
  await syncServerScripts(session);
8469
- p42.log.step("Running provision");
8729
+ p43.log.step("Running provision");
8470
8730
  const result = await runServerScript(session, "provision.sh", {
8471
8731
  args: [
8472
8732
  "--pb-version",
@@ -8478,7 +8738,7 @@ var provision = addSshOptions(
8478
8738
  ],
8479
8739
  stream: true
8480
8740
  });
8481
- p42.log.success(
8741
+ p43.log.success(
8482
8742
  `${target} is ready.
8483
8743
 
8484
8744
  Node ${result?.node ?? "installed"}
@@ -8486,7 +8746,7 @@ var provision = addSshOptions(
8486
8746
  PocketBase ${result?.pocketbase ?? pbVersion}`
8487
8747
  );
8488
8748
  });
8489
- p42.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8749
+ p43.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8490
8750
  }, "Failed to provision.")
8491
8751
  );
8492
8752
 
@@ -8494,21 +8754,21 @@ var provision = addSshOptions(
8494
8754
  import path38 from "node:path";
8495
8755
  import fs37 from "node:fs";
8496
8756
  import { Command as Command77, Option as Option2 } from "commander";
8497
- import * as p43 from "@clack/prompts";
8757
+ import * as p44 from "@clack/prompts";
8498
8758
  import pc18 from "picocolors";
8499
8759
  import * as v8 from "valibot";
8500
8760
 
8501
8761
  // src/lib/pocketbase-settings.ts
8502
8762
  import fs35 from "node:fs";
8503
8763
  import path36 from "node:path";
8504
- import process29 from "node:process";
8764
+ import process31 from "node:process";
8505
8765
  import PocketBase5 from "pocketbase";
8506
8766
  var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
8507
8767
  async function readLocalMeta(cwd) {
8508
8768
  const dataDir2 = path36.join(cwd, DATA_DIR);
8509
8769
  if (!fs35.existsSync(dataDir2)) return null;
8510
- const email3 = process29.env.POCKETBASE_SUPERUSER_EMAIL;
8511
- const password11 = process29.env.POCKETBASE_SUPERUSER_PASSWORD;
8770
+ const email3 = process31.env.POCKETBASE_SUPERUSER_EMAIL;
8771
+ const password11 = process31.env.POCKETBASE_SUPERUSER_PASSWORD;
8512
8772
  if (!email3 || !password11) return null;
8513
8773
  let proc;
8514
8774
  try {
@@ -8853,7 +9113,7 @@ var deploy = addLockWaitOption(
8853
9113
  (raw) => runCommand(async () => {
8854
9114
  const options = parseOptions(OptionsSchema3, raw);
8855
9115
  const backend3 = hasBackend();
8856
- p43.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
9116
+ p44.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
8857
9117
  if (options.build !== false) {
8858
9118
  const { workspaceRootDir } = await getWorkspace();
8859
9119
  await prepareAdapter(workspaceRootDir);
@@ -8863,7 +9123,7 @@ var deploy = addLockWaitOption(
8863
9123
  {
8864
9124
  remote: async (ctx) => {
8865
9125
  const { session, instance, workspaceRootDir, config } = ctx;
8866
- p43.log.info(
9126
+ p44.log.info(
8867
9127
  `${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
8868
9128
  );
8869
9129
  const [existing] = await readInstanceStates(session, instance);
@@ -8873,7 +9133,7 @@ var deploy = addLockWaitOption(
8873
9133
  const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
8874
9134
  const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
8875
9135
  if (existing && instanceHasBackend(existing) !== backend3) {
8876
- p43.log.info(
9136
+ p44.log.info(
8877
9137
  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
9138
  );
8879
9139
  }
@@ -8916,7 +9176,7 @@ with DNS of your own pointing at ${ctx.server}.`
8916
9176
  tunnel = await openDatabaseTunnel(session, instance, existing);
8917
9177
  } catch (err) {
8918
9178
  if (askedForRemoteDb) throw err;
8919
- p43.log.warn(
9179
+ p44.log.warn(
8920
9180
  `Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
8921
9181
  ${pc18.dim(String(err))}`
8922
9182
  );
@@ -8924,13 +9184,13 @@ ${pc18.dim(String(err))}`
8924
9184
  }
8925
9185
  if (tunnel) {
8926
9186
  buildEnv = { ...buildEnv, ...tunnel.env };
8927
- p43.log.info(
9187
+ p44.log.info(
8928
9188
  `Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
8929
9189
  );
8930
9190
  } else if (backend3) {
8931
9191
  await ensureSuperuser(workspaceRootDir);
8932
9192
  }
8933
- p43.log.step("Building");
9193
+ p44.log.step("Building");
8934
9194
  try {
8935
9195
  await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
8936
9196
  } finally {
@@ -8938,9 +9198,9 @@ ${pc18.dim(String(err))}`
8938
9198
  }
8939
9199
  }
8940
9200
  const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
8941
- p43.log.step(`Uploading release ${pc18.dim(release)}`);
9201
+ p44.log.step(`Uploading release ${pc18.dim(release)}`);
8942
9202
  await uploadRelease(session, instance, release, entries);
8943
- p43.log.step("Activating");
9203
+ p44.log.step("Activating");
8944
9204
  result = await runServerScript(session, "apply.sh", {
8945
9205
  args: [
8946
9206
  instance,
@@ -8991,7 +9251,7 @@ ${pc18.dim(String(err))}`
8991
9251
  url: primaryHost ? url : void 0
8992
9252
  });
8993
9253
  const redirects = started?.environment.redirects ?? [];
8994
- p43.log.success(
9254
+ p44.log.success(
8995
9255
  `Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
8996
9256
 
8997
9257
  URL ${url}
@@ -8999,7 +9259,7 @@ ${pc18.dim(String(err))}`
8999
9259
  ` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
9000
9260
  );
9001
9261
  if (managed && managed !== existing?.managed) {
9002
- p43.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9262
+ p44.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9003
9263
  }
9004
9264
  if (result?.superuserCreated) {
9005
9265
  await copyLocalBranding(
@@ -9008,7 +9268,7 @@ ${pc18.dim(String(err))}`
9008
9268
  workspaceRootDir,
9009
9269
  primaryHost ? result?.url ?? "" : ""
9010
9270
  );
9011
- p43.log.info(
9271
+ p44.log.info(
9012
9272
  `Created the PocketBase superuser this app authenticates as.
9013
9273
 
9014
9274
  Its credentials are stored in the environment on the server. To use
@@ -9019,7 +9279,7 @@ and deploy again.`
9019
9279
  await reportAppURLDrift(session, instance, primaryHost);
9020
9280
  }
9021
9281
  if (!primaryHost) {
9022
- p43.log.warn(
9282
+ p44.log.warn(
9023
9283
  `No domain configured, so nothing is proxied to this app yet.
9024
9284
  Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
9025
9285
  or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
@@ -9029,7 +9289,7 @@ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
9029
9289
  },
9030
9290
  { project: options.project, askDomain: true, label: "deploy" }
9031
9291
  );
9032
- p43.outro(`${pc18.cyan("vela status")} to see what is running`);
9292
+ p44.outro(`${pc18.cyan("vela status")} to see what is running`);
9033
9293
  }, "Failed to deploy.")
9034
9294
  );
9035
9295
  async function prepareAdapter(workspaceRootDir) {
@@ -9048,8 +9308,8 @@ ${pc18.cyan(err.snippet)}` : err.message);
9048
9308
  outcome.packageJsonChanged ? "package.json" : void 0
9049
9309
  ].filter((f) => Boolean(f));
9050
9310
  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(
9311
+ p44.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
9312
+ p44.log.info(
9053
9313
  `${why}, and vela deploy runs the app as a Node server.
9054
9314
 
9055
9315
  Changed ${changed.join(", ")}` + (outcome.removedDeps.length ? `
@@ -9062,14 +9322,14 @@ ${pc18.cyan(err.snippet)}` : err.message);
9062
9322
  rethrow(err);
9063
9323
  }
9064
9324
  }
9065
- p43.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9325
+ p44.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9066
9326
  }
9067
9327
  async function reportAppURLDrift(session, instance, domain) {
9068
9328
  const expected = normalizeOrigin(domain);
9069
9329
  if (!expected) return;
9070
9330
  const current = await readRemoteAppURL(session, instance);
9071
9331
  if (!current || normalizeOrigin(current) === expected) return;
9072
- p43.log.warn(
9332
+ p44.log.warn(
9073
9333
  `This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
9074
9334
 
9075
9335
  Emails and anything else PocketBase links to will use the former. Update it in
@@ -9084,15 +9344,15 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
9084
9344
  if (copied.length === 0) return;
9085
9345
  const outcome = await restartInstance(session, instance);
9086
9346
  if (outcome.deployed && !outcome.restarted) {
9087
- p43.log.warn(
9347
+ p44.log.warn(
9088
9348
  `Copied ${copied.join(", ")}, but the app did not restart to pick them up.
9089
9349
  ${pc18.dim(outcome.error ?? "")}`
9090
9350
  );
9091
9351
  return;
9092
9352
  }
9093
- p43.log.success(`Copied ${copied.join(", ")} from this project's database`);
9353
+ p44.log.success(`Copied ${copied.join(", ")} from this project's database`);
9094
9354
  } catch (err) {
9095
- p43.log.warn(
9355
+ p44.log.warn(
9096
9356
  `Could not copy this project's PocketBase settings across.
9097
9357
  Set them in the admin panel instead. ${pc18.dim(String(err))}`
9098
9358
  );
@@ -9185,7 +9445,7 @@ async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
9185
9445
  const remote = await readRemoteEnv(session, instance);
9186
9446
  if (Object.keys(remote).length > 0) return;
9187
9447
  if (!fs37.existsSync(path38.join(workspaceRootDir, ".env"))) return;
9188
- p43.log.warn(
9448
+ p44.log.warn(
9189
9449
  `This app has no production environment variables yet.
9190
9450
 
9191
9451
  Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
@@ -9196,53 +9456,43 @@ async function serverTimeOrLocal(session) {
9196
9456
  try {
9197
9457
  return await serverTime(session);
9198
9458
  } catch {
9199
- p43.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9459
+ p44.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9200
9460
  return /* @__PURE__ */ new Date();
9201
9461
  }
9202
9462
  }
9203
9463
 
9204
9464
  // src/commands/link.ts
9205
9465
  import path39 from "node:path";
9206
- import process30 from "node:process";
9466
+ import process32 from "node:process";
9207
9467
  import { Command as Command78 } from "commander";
9208
- import * as p44 from "@clack/prompts";
9468
+ import * as p45 from "@clack/prompts";
9209
9469
  var CREATE_NEW = "__new__";
9210
9470
  var link = new Command78("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
9211
9471
  async function linkProject() {
9212
9472
  const { workspaceRootDir } = await getWorkspace();
9213
9473
  const existing = readProjectConfig(workspaceRootDir);
9214
9474
  if (existing) {
9215
- p44.log.success(`Linked to ${existing.projectName}.`);
9475
+ p45.log.success(`Linked to ${existing.projectName}.`);
9216
9476
  return;
9217
9477
  }
9218
9478
  const apiKey = requireApiKey();
9219
- const [user, teams3, projects] = await Promise.all([
9220
- getCurrentUser(apiKey),
9221
- listTeams(apiKey),
9222
- listProjects(apiKey)
9223
- ]);
9224
- let projectId;
9225
- let teamId;
9226
- let projectName;
9479
+ const [teams3, projects] = await Promise.all([listTeams(apiKey), listProjects(apiKey)]);
9227
9480
  const picked = projects.length > 0 ? await pickExistingProject(projects) : CREATE_NEW;
9481
+ let linked;
9228
9482
  if (picked !== CREATE_NEW) {
9229
9483
  const project = projects.find((pr) => pr.id === picked);
9230
- projectId = project.id;
9231
- teamId = project.team;
9232
- projectName = project.name;
9484
+ linked = toLinked(project, project.expand?.team);
9233
9485
  } else {
9234
9486
  const team = await pickTeam(teams3);
9235
9487
  const name = await promptProjectName(workspaceRootDir);
9236
- const created = await createProject2(apiKey, { name, teamId: team.id, userId: user.id });
9237
- projectId = created.id;
9238
- teamId = team.id;
9239
- projectName = created.name;
9488
+ linked = await linkNewProject(apiKey, { name, teamId: team.id, interactive: true });
9240
9489
  }
9490
+ const { projectId, teamId, projectName } = linked;
9241
9491
  writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
9242
- p44.log.success(`Linked to ${projectName}.`);
9492
+ p45.log.success(`Linked to ${projectName} (${linked.dashboardUrl}).`);
9243
9493
  }
9244
9494
  async function pickExistingProject(projects) {
9245
- const choice = await p44.select({
9495
+ const choice = await p45.select({
9246
9496
  message: "Select a project",
9247
9497
  options: [
9248
9498
  ...projects.map((pr) => ({
@@ -9252,39 +9502,24 @@ async function pickExistingProject(projects) {
9252
9502
  { value: CREATE_NEW, label: "Create a new project" }
9253
9503
  ]
9254
9504
  });
9255
- if (p44.isCancel(choice)) {
9256
- p44.cancel("Operation cancelled.");
9257
- process30.exit(0);
9505
+ if (p45.isCancel(choice)) {
9506
+ p45.cancel("Operation cancelled.");
9507
+ process32.exit(0);
9258
9508
  }
9259
9509
  return choice;
9260
9510
  }
9261
- async function pickTeam(teams3) {
9262
- if (teams3.length === 1) return teams3[0];
9263
- const choice = await p44.select({
9264
- message: "Select a team",
9265
- options: teams3.map((team) => ({
9266
- value: team.id,
9267
- label: team.is_personal ? `${team.name} (personal)` : team.name
9268
- }))
9269
- });
9270
- if (p44.isCancel(choice)) {
9271
- p44.cancel("Operation cancelled.");
9272
- process30.exit(0);
9273
- }
9274
- return teams3.find((team) => team.id === choice);
9275
- }
9276
9511
  async function promptProjectName(workspaceRootDir) {
9277
9512
  const defaultValue = defaultProjectName2(workspaceRootDir);
9278
- const value = await p44.text({
9513
+ const value = await p45.text({
9279
9514
  message: "Project name",
9280
9515
  defaultValue,
9281
9516
  initialValue: defaultValue,
9282
9517
  placeholder: defaultValue,
9283
9518
  validate: (v10) => !v10?.trim() ? "Required" : void 0
9284
9519
  });
9285
- if (p44.isCancel(value)) {
9286
- p44.cancel("Operation cancelled.");
9287
- process30.exit(0);
9520
+ if (p45.isCancel(value)) {
9521
+ p45.cancel("Operation cancelled.");
9522
+ process32.exit(0);
9288
9523
  }
9289
9524
  return value.trim();
9290
9525
  }
@@ -9303,7 +9538,7 @@ import { Command as Command83 } from "commander";
9303
9538
 
9304
9539
  // src/commands/env/list.ts
9305
9540
  import { Command as Command79 } from "commander";
9306
- import * as p45 from "@clack/prompts";
9541
+ import * as p46 from "@clack/prompts";
9307
9542
  import pc19 from "picocolors";
9308
9543
  var envList = addTargetOptions(
9309
9544
  new Command79("list").description("list environment variable names").configureHelp(helpConfig),
@@ -9328,10 +9563,10 @@ var envList = addTargetOptions(
9328
9563
  );
9329
9564
  function report(keys, where) {
9330
9565
  if (keys.length === 0) {
9331
- p45.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9566
+ p46.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9332
9567
  return;
9333
9568
  }
9334
- p45.log.info(
9569
+ p46.log.info(
9335
9570
  `Environment ${pc19.dim(`(${where})`)}
9336
9571
 
9337
9572
  ` + keys.sort().map((key) => ` ${key}`).join("\n")
@@ -9339,9 +9574,9 @@ function report(keys, where) {
9339
9574
  }
9340
9575
 
9341
9576
  // src/commands/env/set.ts
9342
- import process31 from "node:process";
9577
+ import process33 from "node:process";
9343
9578
  import { Command as Command80 } from "commander";
9344
- import * as p46 from "@clack/prompts";
9579
+ import * as p47 from "@clack/prompts";
9345
9580
  import pc20 from "picocolors";
9346
9581
  var envSet = addTargetOptions(
9347
9582
  new Command80("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
@@ -9354,14 +9589,14 @@ var envSet = addTargetOptions(
9354
9589
  local: async (ctx) => {
9355
9590
  const resolved = await resolveValue(key, value);
9356
9591
  setLocalEnv(ctx.envFile, key, resolved);
9357
- p46.log.success(`${key} updated ${pc20.dim("(local)")}`);
9592
+ p47.log.success(`${key} updated ${pc20.dim("(local)")}`);
9358
9593
  await applyLocalEnvChange(ctx, [key]);
9359
9594
  },
9360
9595
  remote: async (ctx) => {
9361
9596
  const resolved = await resolveValue(key, value);
9362
9597
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9363
9598
  await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
9364
- p46.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9599
+ p47.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9365
9600
  await applyEnvRestart(ctx, [key]);
9366
9601
  }
9367
9602
  },
@@ -9375,20 +9610,20 @@ async function resolveValue(key, value) {
9375
9610
  return value ?? await promptValue(key);
9376
9611
  }
9377
9612
  async function promptValue(key) {
9378
- const value = await p46.password({
9613
+ const value = await p47.password({
9379
9614
  message: `Value for ${pc20.cyan(key)}`,
9380
9615
  validate: (input) => !input?.length ? "Required" : void 0
9381
9616
  });
9382
- if (p46.isCancel(value)) {
9383
- p46.cancel("Operation cancelled.");
9384
- process31.exit(0);
9617
+ if (p47.isCancel(value)) {
9618
+ p47.cancel("Operation cancelled.");
9619
+ process33.exit(0);
9385
9620
  }
9386
9621
  return value;
9387
9622
  }
9388
9623
 
9389
9624
  // src/commands/env/unset.ts
9390
9625
  import { Command as Command81 } from "commander";
9391
- import * as p47 from "@clack/prompts";
9626
+ import * as p48 from "@clack/prompts";
9392
9627
  import pc21 from "picocolors";
9393
9628
  var envUnset = addTargetOptions(
9394
9629
  new Command81("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
@@ -9400,22 +9635,22 @@ var envUnset = addTargetOptions(
9400
9635
  {
9401
9636
  local: async (ctx) => {
9402
9637
  if (!(key in readLocalEnv(ctx.envFile))) {
9403
- p47.log.info(`${key} is not set \u2014 nothing to remove.`);
9638
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9404
9639
  return;
9405
9640
  }
9406
9641
  unsetLocalEnv(ctx.envFile, key);
9407
- p47.log.success(`${key} removed ${pc21.dim("(local)")}`);
9642
+ p48.log.success(`${key} removed ${pc21.dim("(local)")}`);
9408
9643
  await applyLocalEnvChange(ctx, [key]);
9409
9644
  },
9410
9645
  remote: async (ctx) => {
9411
9646
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9412
9647
  if (!(key in env2)) {
9413
- p47.log.info(`${key} is not set \u2014 nothing to remove.`);
9648
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9414
9649
  return;
9415
9650
  }
9416
9651
  delete env2[key];
9417
9652
  await writeRemoteEnv(ctx.session, ctx.instance, env2);
9418
- p47.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9653
+ p48.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9419
9654
  await applyEnvRestart(ctx, [key]);
9420
9655
  }
9421
9656
  },
@@ -9428,9 +9663,9 @@ var envUnset = addTargetOptions(
9428
9663
  // src/commands/env/import.ts
9429
9664
  import fs38 from "node:fs";
9430
9665
  import path40 from "node:path";
9431
- import process32 from "node:process";
9666
+ import process34 from "node:process";
9432
9667
  import { Command as Command82 } from "commander";
9433
- import * as p48 from "@clack/prompts";
9668
+ import * as p49 from "@clack/prompts";
9434
9669
  import pc22 from "picocolors";
9435
9670
  var envImport = addTargetOptions(
9436
9671
  new Command82("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
@@ -9448,22 +9683,22 @@ var envImport = addTargetOptions(
9448
9683
  const incoming = read(source, file);
9449
9684
  const keys = Object.keys(incoming);
9450
9685
  if (keys.length === 0) return;
9451
- p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9686
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9452
9687
  editLocalEnv(
9453
9688
  ctx.envFile,
9454
9689
  (content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
9455
9690
  );
9456
- p48.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9691
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9457
9692
  await applyLocalEnvChange(ctx, keys);
9458
9693
  },
9459
9694
  remote: async (ctx) => {
9460
9695
  const incoming = read(resolve(file), file);
9461
9696
  const keys = Object.keys(incoming);
9462
9697
  if (keys.length === 0) return;
9463
- p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9698
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9464
9699
  const existing = await readRemoteEnv(ctx.session, ctx.instance);
9465
9700
  await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
9466
- p48.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9701
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9467
9702
  await applyEnvRestart(ctx, keys);
9468
9703
  }
9469
9704
  },
@@ -9473,12 +9708,12 @@ var envImport = addTargetOptions(
9473
9708
  )
9474
9709
  );
9475
9710
  function resolve(file) {
9476
- return path40.resolve(process32.cwd(), file);
9711
+ return path40.resolve(process34.cwd(), file);
9477
9712
  }
9478
9713
  function read(resolved, shown) {
9479
9714
  if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
9480
9715
  const incoming = readLocalEnvFile(resolved);
9481
- if (Object.keys(incoming).length === 0) p48.log.info(`${shown} has no variables to import.`);
9716
+ if (Object.keys(incoming).length === 0) p49.log.info(`${shown} has no variables to import.`);
9482
9717
  return incoming;
9483
9718
  }
9484
9719
 
@@ -9487,7 +9722,7 @@ var env = new Command83("env").description("manage environment variables, locall
9487
9722
 
9488
9723
  // src/commands/status.ts
9489
9724
  import { Command as Command84 } from "commander";
9490
- import * as p49 from "@clack/prompts";
9725
+ import * as p50 from "@clack/prompts";
9491
9726
  import pc23 from "picocolors";
9492
9727
  var status = addTargetOptions(
9493
9728
  new Command84("status").description("show what is deployed").configureHelp(helpConfig),
@@ -9521,11 +9756,11 @@ function report2(states, json) {
9521
9756
  return;
9522
9757
  }
9523
9758
  if (states.length === 0) {
9524
- p49.log.info("Nothing is deployed here yet.");
9759
+ p50.log.info("Nothing is deployed here yet.");
9525
9760
  return;
9526
9761
  }
9527
9762
  for (const state of states) {
9528
- p49.log.info(describe2(state));
9763
+ p50.log.info(describe2(state));
9529
9764
  }
9530
9765
  }
9531
9766
  function describe2(state) {
@@ -9550,7 +9785,7 @@ function describe2(state) {
9550
9785
 
9551
9786
  // src/commands/rollback.ts
9552
9787
  import { Command as Command85 } from "commander";
9553
- import * as p50 from "@clack/prompts";
9788
+ import * as p51 from "@clack/prompts";
9554
9789
  import pc24 from "picocolors";
9555
9790
  var rollback = addLockWaitOption(
9556
9791
  addTargetOptions(
@@ -9564,7 +9799,7 @@ var rollback = addLockWaitOption(
9564
9799
  raw,
9565
9800
  {
9566
9801
  remote: async (ctx) => {
9567
- p50.log.step(
9802
+ p51.log.step(
9568
9803
  `Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
9569
9804
  );
9570
9805
  const result = await runServerScript(
@@ -9579,7 +9814,7 @@ var rollback = addLockWaitOption(
9579
9814
  stream: true
9580
9815
  }
9581
9816
  );
9582
- p50.log.success(
9817
+ p51.log.success(
9583
9818
  `Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
9584
9819
  );
9585
9820
  }
@@ -9632,9 +9867,9 @@ var logs = addTargetOptions(
9632
9867
  import { Command as Command88 } from "commander";
9633
9868
 
9634
9869
  // src/commands/admin/create.ts
9635
- import process33 from "node:process";
9870
+ import process35 from "node:process";
9636
9871
  import { Command as Command87 } from "commander";
9637
- import * as p51 from "@clack/prompts";
9872
+ import * as p52 from "@clack/prompts";
9638
9873
  import pc25 from "picocolors";
9639
9874
  var MIN_PASSWORD = 10;
9640
9875
  var adminCreate = addTargetOptions(
@@ -9666,7 +9901,7 @@ var adminCreate = addTargetOptions(
9666
9901
  const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
9667
9902
  if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
9668
9903
  }
9669
- p51.log.info(
9904
+ p52.log.info(
9670
9905
  signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
9671
9906
  );
9672
9907
  },
@@ -9680,7 +9915,7 @@ var adminCreate = addTargetOptions(
9680
9915
  (pb) => upsertSuperuser(pb, address, password11)
9681
9916
  );
9682
9917
  const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
9683
- p51.log.info(
9918
+ p52.log.info(
9684
9919
  base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
9685
9920
  );
9686
9921
  }
@@ -9693,20 +9928,20 @@ var adminCreate = addTargetOptions(
9693
9928
  async function upsertSuperuser(pb, email3, password11) {
9694
9929
  const existing = await findSuperuser(pb, email3);
9695
9930
  if (existing) {
9696
- const confirmed = await p51.confirm({
9931
+ const confirmed = await p52.confirm({
9697
9932
  message: `${email3} already has an account, update its password?`,
9698
9933
  initialValue: false
9699
9934
  });
9700
- if (p51.isCancel(confirmed) || !confirmed) {
9701
- p51.cancel("Operation cancelled.");
9702
- process33.exit(0);
9935
+ if (p52.isCancel(confirmed) || !confirmed) {
9936
+ p52.cancel("Operation cancelled.");
9937
+ process35.exit(0);
9703
9938
  }
9704
9939
  await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
9705
- p51.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9940
+ p52.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9706
9941
  return;
9707
9942
  }
9708
9943
  await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
9709
- p51.log.success(`${pc25.cyan(email3)} can now sign in`);
9944
+ p52.log.success(`${pc25.cyan(email3)} can now sign in`);
9710
9945
  }
9711
9946
  async function findSuperuser(pb, email3) {
9712
9947
  try {
@@ -9717,32 +9952,32 @@ async function findSuperuser(pb, email3) {
9717
9952
  }
9718
9953
  }
9719
9954
  async function promptEmail() {
9720
- const value = await p51.text({
9955
+ const value = await p52.text({
9721
9956
  message: "Email to sign in with",
9722
9957
  validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
9723
9958
  });
9724
- if (p51.isCancel(value)) {
9725
- p51.cancel("Operation cancelled.");
9726
- process33.exit(0);
9959
+ if (p52.isCancel(value)) {
9960
+ p52.cancel("Operation cancelled.");
9961
+ process35.exit(0);
9727
9962
  }
9728
9963
  return value.trim();
9729
9964
  }
9730
9965
  async function promptPassword2() {
9731
- const value = await p51.password({
9966
+ const value = await p52.password({
9732
9967
  message: "Password",
9733
9968
  validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
9734
9969
  });
9735
- if (p51.isCancel(value)) {
9736
- p51.cancel("Operation cancelled.");
9737
- process33.exit(0);
9970
+ if (p52.isCancel(value)) {
9971
+ p52.cancel("Operation cancelled.");
9972
+ process35.exit(0);
9738
9973
  }
9739
- const again = await p51.password({
9974
+ const again = await p52.password({
9740
9975
  message: "Password again",
9741
9976
  validate: (input) => input === value ? void 0 : "The two do not match"
9742
9977
  });
9743
- if (p51.isCancel(again)) {
9744
- p51.cancel("Operation cancelled.");
9745
- process33.exit(0);
9978
+ if (p52.isCancel(again)) {
9979
+ p52.cancel("Operation cancelled.");
9980
+ process35.exit(0);
9746
9981
  }
9747
9982
  return value;
9748
9983
  }
@@ -9757,7 +9992,7 @@ import { Command as Command94 } from "commander";
9757
9992
  import fs39 from "node:fs";
9758
9993
  import path41 from "node:path";
9759
9994
  import { Command as Command89 } from "commander";
9760
- import * as p52 from "@clack/prompts";
9995
+ import * as p53 from "@clack/prompts";
9761
9996
  import pc26 from "picocolors";
9762
9997
 
9763
9998
  // src/lib/backups.ts
@@ -9861,7 +10096,7 @@ Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_
9861
10096
  }
9862
10097
  const storage = await readStorageSettings(ctx.pb);
9863
10098
  if (storage.s3Enabled) {
9864
- p52.log.warn(
10099
+ p53.log.warn(
9865
10100
  `Uploads are stored in S3, so this archive holds the database only.
9866
10101
 
9867
10102
  PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
@@ -9869,7 +10104,7 @@ Your bucket's own versioning is what protects the uploaded files.`
9869
10104
  );
9870
10105
  }
9871
10106
  if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
9872
- const spinner7 = p52.spinner();
10107
+ const spinner7 = p53.spinner();
9873
10108
  spinner7.start(`Backing up ${ctx.targetName}`);
9874
10109
  try {
9875
10110
  await createBackup(ctx.pb, key);
@@ -9916,7 +10151,7 @@ async function download(ctx, key, outputDir) {
9916
10151
  fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9917
10152
  return path41.relative(ctx.workspaceRootDir, destination);
9918
10153
  }
9919
- const spinner7 = p52.spinner();
10154
+ const spinner7 = p53.spinner();
9920
10155
  spinner7.start(`Downloading ${key}`);
9921
10156
  try {
9922
10157
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9930,7 +10165,7 @@ async function download(ctx, key, outputDir) {
9930
10165
 
9931
10166
  // src/commands/backup/list.ts
9932
10167
  import { Command as Command90 } from "commander";
9933
- import * as p53 from "@clack/prompts";
10168
+ import * as p54 from "@clack/prompts";
9934
10169
  import pc27 from "picocolors";
9935
10170
  var backupList = addTargetOptions(
9936
10171
  new Command90("list").description("list the backups on a target").configureHelp(helpConfig),
@@ -9940,7 +10175,7 @@ var backupList = addTargetOptions(
9940
10175
  () => withBackupTarget(raw, "backup list", async (ctx) => {
9941
10176
  const backups = await listBackups(ctx.pb);
9942
10177
  if (backups.length === 0) {
9943
- p53.log.info(
10178
+ p54.log.info(
9944
10179
  `${pc27.cyan(ctx.targetName)} has no backups yet.
9945
10180
 
9946
10181
  Take one with ${pc27.cyan("vela backup create")}.`
@@ -9948,7 +10183,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9948
10183
  return;
9949
10184
  }
9950
10185
  const width = Math.max(...backups.map((b) => b.key.length));
9951
- p53.log.message(
10186
+ p54.log.message(
9952
10187
  backups.map(
9953
10188
  (b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
9954
10189
  ).join("\n")
@@ -9962,7 +10197,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9962
10197
  import fs40 from "node:fs";
9963
10198
  import path42 from "node:path";
9964
10199
  import { Command as Command91 } from "commander";
9965
- import * as p54 from "@clack/prompts";
10200
+ import * as p55 from "@clack/prompts";
9966
10201
  import pc28 from "picocolors";
9967
10202
  var backupDownload = addTargetOptions(
9968
10203
  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),
@@ -9993,7 +10228,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9993
10228
  if (!ctx.session) {
9994
10229
  fs40.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9995
10230
  } else {
9996
- const spinner7 = p54.spinner();
10231
+ const spinner7 = p55.spinner();
9997
10232
  spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
9998
10233
  try {
9999
10234
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -10012,9 +10247,9 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
10012
10247
  );
10013
10248
 
10014
10249
  // src/commands/backup/delete.ts
10015
- import process34 from "node:process";
10250
+ import process36 from "node:process";
10016
10251
  import { Command as Command92 } from "commander";
10017
- import * as p55 from "@clack/prompts";
10252
+ import * as p56 from "@clack/prompts";
10018
10253
  import pc29 from "picocolors";
10019
10254
  var backupDelete = addTargetOptions(
10020
10255
  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),
@@ -10032,13 +10267,13 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
10032
10267
  );
10033
10268
  }
10034
10269
  if (!options.yes) {
10035
- const confirmed = await p55.confirm({
10270
+ const confirmed = await p56.confirm({
10036
10271
  message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
10037
10272
  initialValue: false
10038
10273
  });
10039
- if (p55.isCancel(confirmed) || !confirmed) {
10040
- p55.cancel("Operation cancelled.");
10041
- process34.exit(0);
10274
+ if (p56.isCancel(confirmed) || !confirmed) {
10275
+ p56.cancel("Operation cancelled.");
10276
+ process36.exit(0);
10042
10277
  }
10043
10278
  }
10044
10279
  await ctx.pb.backups.delete(key);
@@ -10049,7 +10284,7 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
10049
10284
 
10050
10285
  // src/commands/backup/schedule.ts
10051
10286
  import { Command as Command93 } from "commander";
10052
- import * as p56 from "@clack/prompts";
10287
+ import * as p57 from "@clack/prompts";
10053
10288
  import pc30 from "picocolors";
10054
10289
  var DEFAULT_KEEP = 7;
10055
10290
  var backupSchedule = addTargetOptions(
@@ -10066,7 +10301,7 @@ var backupSchedule = addTargetOptions(
10066
10301
  }
10067
10302
  if (!cron) {
10068
10303
  const current = await readSchedule(ctx.pb);
10069
- p56.log.info(
10304
+ p57.log.info(
10070
10305
  current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
10071
10306
 
10072
10307
  Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
@@ -10102,9 +10337,9 @@ var backup = new Command94("backup").description("back up the database and uploa
10102
10337
  // src/commands/restore.ts
10103
10338
  import fs41 from "node:fs";
10104
10339
  import path43 from "node:path";
10105
- import process35 from "node:process";
10340
+ import process37 from "node:process";
10106
10341
  import { Command as Command95 } from "commander";
10107
- import * as p57 from "@clack/prompts";
10342
+ import * as p58 from "@clack/prompts";
10108
10343
  import pc31 from "picocolors";
10109
10344
  var restore = addLockWaitOption(
10110
10345
  addTargetOptions(
@@ -10145,18 +10380,18 @@ var restore = addLockWaitOption(
10145
10380
  ],
10146
10381
  stream: true
10147
10382
  });
10148
- p57.log.success(
10383
+ p58.log.success(
10149
10384
  `Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
10150
10385
  local ? path43.basename(local) : key
10151
10386
  )}.`
10152
10387
  );
10153
10388
  if (result?.storageCarriedOver) {
10154
- p57.log.info(
10389
+ p58.log.info(
10155
10390
  "The archive held no uploads, so the files already on the server were kept."
10156
10391
  );
10157
10392
  }
10158
10393
  if (result?.previousDataDir) {
10159
- p57.log.info(
10394
+ p58.log.info(
10160
10395
  `The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
10161
10396
 
10162
10397
  It is the only way back. Remove it once you are satisfied with the restore.`
@@ -10197,7 +10432,7 @@ Run ${pc31.cyan("vela backup list")} to see what it does have.`
10197
10432
  Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
10198
10433
  );
10199
10434
  }
10200
- const chosen = await p57.select({
10435
+ const chosen = await p58.select({
10201
10436
  message: `Which backup should ${ctx.targetName} be restored from?`,
10202
10437
  options: backups.map((b) => ({
10203
10438
  value: b.key,
@@ -10205,16 +10440,16 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
10205
10440
  hint: `${formatBytes(b.size)}, ${b.modified}`
10206
10441
  }))
10207
10442
  });
10208
- if (p57.isCancel(chosen)) {
10209
- p57.cancel("Operation cancelled.");
10210
- process35.exit(0);
10443
+ if (p58.isCancel(chosen)) {
10444
+ p58.cancel("Operation cancelled.");
10445
+ process37.exit(0);
10211
10446
  }
10212
10447
  return chosen;
10213
10448
  }
10214
10449
  async function stage(ctx, file) {
10215
10450
  const dir = remotePaths.restoreStage(ctx.instance);
10216
10451
  const remote = `${dir}/${path43.basename(file)}`;
10217
- const spinner7 = p57.spinner();
10452
+ const spinner7 = p58.spinner();
10218
10453
  spinner7.start(`Uploading ${path43.basename(file)}`);
10219
10454
  try {
10220
10455
  await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
@@ -10229,29 +10464,29 @@ async function stage(ctx, file) {
10229
10464
  async function confirm13(appName, targetName, envTag, from) {
10230
10465
  const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path43.basename(from))}`;
10231
10466
  if (isProd(envTag)) {
10232
- const answer = await p57.text({
10467
+ const answer = await p58.text({
10233
10468
  message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
10234
10469
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
10235
10470
  });
10236
- if (p57.isCancel(answer)) {
10237
- p57.cancel("Operation cancelled.");
10238
- process35.exit(0);
10471
+ if (p58.isCancel(answer)) {
10472
+ p58.cancel("Operation cancelled.");
10473
+ process37.exit(0);
10239
10474
  }
10240
10475
  return;
10241
10476
  }
10242
- const ok = await p57.confirm({
10477
+ const ok = await p58.confirm({
10243
10478
  message: `Replace the database and uploads of ${what}?`,
10244
10479
  initialValue: false
10245
10480
  });
10246
- if (p57.isCancel(ok) || !ok) {
10247
- p57.cancel("Operation cancelled.");
10248
- process35.exit(0);
10481
+ if (p58.isCancel(ok) || !ok) {
10482
+ p58.cancel("Operation cancelled.");
10483
+ process37.exit(0);
10249
10484
  }
10250
10485
  }
10251
10486
 
10252
10487
  // src/commands/targets.ts
10253
10488
  import { Command as Command96 } from "commander";
10254
- import * as p58 from "@clack/prompts";
10489
+ import * as p59 from "@clack/prompts";
10255
10490
  import pc32 from "picocolors";
10256
10491
  import * as v9 from "valibot";
10257
10492
  var OptionsSchema4 = v9.object({
@@ -10326,11 +10561,11 @@ function report3(rows, offline) {
10326
10561
  const lines = rows.map(
10327
10562
  (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}`
10328
10563
  );
10329
- p58.log.info(`${pc32.dim(header)}
10564
+ p59.log.info(`${pc32.dim(header)}
10330
10565
  ${lines.join("\n")}`);
10331
10566
  const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
10332
10567
  if (!offline && unreachable.length > 0) {
10333
- p58.log.warn(
10568
+ p59.log.warn(
10334
10569
  `Could not reach ${unreachable.map((row) => row.server).join(", ")}.
10335
10570
  Release and domain are shown from what this project recorded.`
10336
10571
  );
@@ -10339,7 +10574,7 @@ Release and domain are shown from what this project recorded.`
10339
10574
 
10340
10575
  // src/commands/test.ts
10341
10576
  import path44 from "node:path";
10342
- import process36 from "node:process";
10577
+ import process38 from "node:process";
10343
10578
  import { Command as Command97 } from "commander";
10344
10579
  import PocketBase6 from "pocketbase";
10345
10580
  import pc33 from "picocolors";
@@ -10348,7 +10583,7 @@ import { detect as detect8 } from "package-manager-detector";
10348
10583
  import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
10349
10584
  import fs42 from "node:fs";
10350
10585
  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();
10586
+ const cwd = process38.cwd();
10352
10587
  const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
10353
10588
  const password11 = "password";
10354
10589
  const testDataDir = path44.join(cwd, "test-data");
@@ -10363,11 +10598,11 @@ var testServer = new Command97("test:server").description("run server tests").al
10363
10598
  email: email3,
10364
10599
  password: password11
10365
10600
  });
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";
10601
+ process38.env.POCKETBASE_URL = url;
10602
+ process38.env.POCKETBASE_SUPERUSER_EMAIL = email3;
10603
+ process38.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
10604
+ process38.env.VELA_DATA_DIR = testDataDir;
10605
+ process38.env.TEST = "true";
10371
10606
  console.log(`${pc33.greenBright("\u2713")} Created test database`);
10372
10607
  let vite;
10373
10608
  let cleanedUp = false;
@@ -10386,12 +10621,12 @@ var testServer = new Command97("test:server").description("run server tests").al
10386
10621
  const fail = async (message) => {
10387
10622
  console.error(`${pc33.redBright("\u2717")} ${message}`);
10388
10623
  await cleanup();
10389
- process36.exit(1);
10624
+ process38.exit(1);
10390
10625
  };
10391
- process36.on("exit", cleanupSync);
10392
- process36.on("SIGINT", () => {
10626
+ process38.on("exit", cleanupSync);
10627
+ process38.on("SIGINT", () => {
10393
10628
  cleanupSync();
10394
- process36.exit(130);
10629
+ process38.exit(130);
10395
10630
  });
10396
10631
  const pb = new PocketBase6(url);
10397
10632
  try {
@@ -10419,7 +10654,7 @@ var testServer = new Command97("test:server").description("run server tests").al
10419
10654
  });
10420
10655
  const vitePort = await findFreePort();
10421
10656
  await vite.listen(vitePort);
10422
- process36.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10657
+ process38.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10423
10658
  console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
10424
10659
  console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
10425
10660
  const extraArgs = (cmd.parent?.args ?? []).slice(1);
@@ -10438,12 +10673,12 @@ var testServer = new Command97("test:server").description("run server tests").al
10438
10673
  const resolvedArgs = resolved.args.slice();
10439
10674
  if (pm === "npm") resolvedArgs.unshift("--yes");
10440
10675
  const result = await x5(resolved.command, resolvedArgs, {
10441
- nodeOptions: { cwd, stdio: "inherit", env: { ...process36.env, CI: "1" } }
10676
+ nodeOptions: { cwd, stdio: "inherit", env: { ...process38.env, CI: "1" } }
10442
10677
  });
10443
- process36.exitCode = result.exitCode ?? 1;
10678
+ process38.exitCode = result.exitCode ?? 1;
10444
10679
  } catch (e) {
10445
10680
  console.error(`${pc33.redBright("\u2717")} ${e.message}`);
10446
- process36.exitCode = 1;
10681
+ process38.exitCode = 1;
10447
10682
  } finally {
10448
10683
  await cleanup();
10449
10684
  }
@@ -10562,13 +10797,13 @@ function printTable(routes2) {
10562
10797
  }
10563
10798
 
10564
10799
  // src/commands/i18n.ts
10565
- import process37 from "node:process";
10800
+ import process39 from "node:process";
10566
10801
  import { Command as Command99 } from "commander";
10567
10802
  import { x as x6 } from "tinyexec";
10568
10803
  import { detect as detect9 } from "package-manager-detector";
10569
10804
  import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
10570
10805
  async function runWuchale(extraArgs) {
10571
- const cwd = process37.cwd();
10806
+ const cwd = process39.cwd();
10572
10807
  const pm = (await detect9({ cwd }))?.name ?? "npm";
10573
10808
  const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
10574
10809
  const args = resolved.args.slice();
@@ -10599,13 +10834,13 @@ import { Command as Command103 } from "commander";
10599
10834
  // src/commands/cms/editor/add.ts
10600
10835
  import { randomBytes } from "node:crypto";
10601
10836
  import { Command as Command100 } from "commander";
10602
- import * as p59 from "@clack/prompts";
10837
+ import * as p60 from "@clack/prompts";
10603
10838
  import pc35 from "picocolors";
10604
10839
 
10605
10840
  // src/lib/cms-backend.ts
10606
10841
  import { createRequire as createRequire3 } from "node:module";
10607
10842
  import path46 from "node:path";
10608
- import process38 from "node:process";
10843
+ import process40 from "node:process";
10609
10844
  import { pathToFileURL as pathToFileURL3 } from "node:url";
10610
10845
  import pc34 from "picocolors";
10611
10846
  var DEFAULT_PROJECT = "default";
@@ -10622,7 +10857,7 @@ Run ${pc34.cyan("vela enable cms")} first.`
10622
10857
  }
10623
10858
  return await import(pathToFileURL3(entry).href);
10624
10859
  }
10625
- async function withCmsBackend(fn, cwd = process38.cwd()) {
10860
+ async function withCmsBackend(fn, cwd = process40.cwd()) {
10626
10861
  const root = findWorkspaceRoot(cwd);
10627
10862
  if (!root) {
10628
10863
  throw new Error("Could not find workspace root (no package.json found)");
@@ -10652,8 +10887,8 @@ var editorAdd = new Command100("add").description("create an editor who can sign
10652
10887
  if (generated) {
10653
10888
  lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
10654
10889
  }
10655
- p59.log.success(lines.join("\n"));
10656
- p59.log.info(
10890
+ p60.log.success(lines.join("\n"));
10891
+ p60.log.info(
10657
10892
  `Run ${pc35.cyan("vela dev")}, open any page with ${pc35.cyan("?edit")} on the URL (or press ${pc35.cyan("Ctrl+E")}), and sign in.`
10658
10893
  );
10659
10894
  }, "Failed to add the editor.")
@@ -10661,12 +10896,12 @@ var editorAdd = new Command100("add").description("create an editor who can sign
10661
10896
 
10662
10897
  // src/commands/cms/editor/password.ts
10663
10898
  import { Command as Command101 } from "commander";
10664
- import * as p60 from "@clack/prompts";
10899
+ import * as p61 from "@clack/prompts";
10665
10900
  import pc36 from "picocolors";
10666
10901
  var editorPassword = new Command101("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
10667
10902
  (email3, password11) => runCommand(async () => {
10668
10903
  await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
10669
- p60.log.success(
10904
+ p61.log.success(
10670
10905
  `Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
10671
10906
  );
10672
10907
  }, "Failed to set the password.")
@@ -10674,7 +10909,7 @@ var editorPassword = new Command101("password").description("set an editor's pas
10674
10909
 
10675
10910
  // src/commands/cms/editor/list.ts
10676
10911
  import { Command as Command102 } from "commander";
10677
- import * as p61 from "@clack/prompts";
10912
+ import * as p62 from "@clack/prompts";
10678
10913
  import pc37 from "picocolors";
10679
10914
  var editorList = new Command102("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10680
10915
  () => runCommand(async () => {
@@ -10685,11 +10920,11 @@ var editorList = new Command102("list").description("list editors and the projec
10685
10920
  }))
10686
10921
  );
10687
10922
  if (rows.length === 0) {
10688
- p61.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10923
+ p62.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10689
10924
  return;
10690
10925
  }
10691
10926
  const width = Math.max(...rows.map((row) => row.email.length));
10692
- p61.log.info(
10927
+ p62.log.info(
10693
10928
  `Editors
10694
10929
 
10695
10930
  ` + rows.map(
@@ -10746,7 +10981,7 @@ var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
10746
10981
  var program = new Command105().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10747
10982
  program.hook("preAction", (_thisCommand, actionCommand) => {
10748
10983
  if (isStub(actionCommand)) return;
10749
- const envRoot = findWorkspaceRoot() ?? process39.cwd();
10984
+ const envRoot = findWorkspaceRoot() ?? process41.cwd();
10750
10985
  dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
10751
10986
  const path47 = getCommandPath(actionCommand);
10752
10987
  if (NO_BACKEND_COMMMANDS.has(path47)) return;
@@ -10754,20 +10989,20 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
10754
10989
  if (NO_BACKEND_COMMMANDS.has(top)) return;
10755
10990
  if (!hasBackend()) {
10756
10991
  if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
10757
- p62.log.error(
10992
+ p63.log.error(
10758
10993
  `${pc38.cyan(`vela ${path47}`)} needs a backend, and this project does not have one.
10759
10994
 
10760
10995
  Static projects have no database to talk to.
10761
10996
 
10762
10997
  To add a backend to this project, run ${pc38.cyan("vela bless")}.`
10763
10998
  );
10764
- p62.log.message();
10765
- p62.cancel("Operation failed.");
10766
- process39.exit(1);
10999
+ p63.log.message();
11000
+ p63.cancel("Operation failed.");
11001
+ process41.exit(1);
10767
11002
  }
10768
11003
  if (SELF_CREDENTIALED_COMMANDS.has(path47)) return;
10769
- if (!process39.env.POCKETBASE_SUPERUSER_EMAIL || !process39.env.POCKETBASE_SUPERUSER_PASSWORD) {
10770
- p62.log.error(
11004
+ if (!process41.env.POCKETBASE_SUPERUSER_EMAIL || !process41.env.POCKETBASE_SUPERUSER_PASSWORD) {
11005
+ p63.log.error(
10771
11006
  `PocketBase superuser credentials are required.
10772
11007
 
10773
11008
  Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
@@ -10775,9 +11010,9 @@ Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPER
10775
11010
  To set up a new project, run ${pc38.cyan("vela create")}.
10776
11011
  To set up an existing project, run ${pc38.cyan("vela bless")}.`
10777
11012
  );
10778
- p62.log.message();
10779
- p62.cancel("Operation failed.");
10780
- process39.exit(1);
11013
+ p63.log.message();
11014
+ p63.cancel("Operation failed.");
11015
+ process41.exit(1);
10781
11016
  }
10782
11017
  });
10783
11018
  function getCommandPath(cmd) {
@@ -10831,5 +11066,5 @@ for (const command of [
10831
11066
  }
10832
11067
 
10833
11068
  // src/bin.ts
10834
- program.parse(normalizeArgv(process40.argv.slice(2)), { from: "user" });
11069
+ program.parse(normalizeArgv(process42.argv.slice(2)), { from: "user" });
10835
11070
  //# sourceMappingURL=bin.js.map