vela 0.11.6 → 0.12.1

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.1",
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, "\\'");
@@ -358,6 +363,11 @@ function hasBackend(from = process3.cwd()) {
358
363
  const root = findWorkspaceRoot(from);
359
364
  return root !== null && fs2.existsSync(path.join(root, DATA_DIR));
360
365
  }
366
+ function hasApiRoutes(root) {
367
+ const dir = path.join(root, "src", "routes", "api");
368
+ if (!fs2.existsSync(dir)) return false;
369
+ return fs2.readdirSync(dir).some((entry) => entry !== "README.md");
370
+ }
361
371
  function localDataDir(from = process3.cwd()) {
362
372
  return path.join(findWorkspaceRoot(from) ?? from, DATA_DIR);
363
373
  }
@@ -399,7 +409,7 @@ function detectFeatures(root, { isAppMode, isPaymentsMode }) {
399
409
  const hasDep = (name) => Boolean(pkg.dependencies?.[name] || pkg.devDependencies?.[name]);
400
410
  return {
401
411
  auth: isAppMode,
402
- api: has("src/routes/api"),
412
+ api: hasApiRoutes(root),
403
413
  apiKeys: has("src/routes/api/api-keys") || has("src/routes/(app)/api-keys"),
404
414
  backend: has(DATA_DIR),
405
415
  i18n: has("wuchale.config.js") || hasDep("wuchale"),
@@ -562,6 +572,10 @@ var entrySchema = v2.object({
562
572
  price: v2.optional(v2.number()),
563
573
  previewUrl: v2.optional(v2.string()),
564
574
  nextSteps: v2.optional(v2.array(v2.string())),
575
+ /** Reads its copy from a hosted CMS through `site.cmsEndpoint`. */
576
+ cms: v2.optional(v2.boolean()),
577
+ /** A prebuilt static build is published for velastack.dev's instant deploys. */
578
+ instantDeploy: v2.optional(v2.boolean()),
565
579
  /** Tarball location, relative to the index URL. */
566
580
  file: v2.string(),
567
581
  sha256: v2.pipe(v2.string(), v2.regex(/^[0-9a-f]{64}$/)),
@@ -753,6 +767,7 @@ async function listAllTemplates(options = {}) {
753
767
  tags: entry.tags,
754
768
  price: entry.price,
755
769
  nextSteps: entry.nextSteps,
770
+ cms: entry.cms,
756
771
  entry,
757
772
  indexUrl
758
773
  });
@@ -833,6 +848,7 @@ function readManifest(root, name) {
833
848
  tags: optionalStringArray(manifest.tags),
834
849
  price: typeof manifest.price === "number" ? manifest.price : void 0,
835
850
  nextSteps: optionalStringArray(manifest.nextSteps),
851
+ cms: typeof manifest.cms === "boolean" ? manifest.cms : void 0,
836
852
  dir: path5.join(root, name)
837
853
  };
838
854
  }
@@ -968,7 +984,7 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
968
984
  };
969
985
  proc.once("exit", onExit);
970
986
  let attempts = 0;
971
- const check = async () => {
987
+ const check2 = async () => {
972
988
  if (settled) return;
973
989
  attempts++;
974
990
  try {
@@ -989,9 +1005,9 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
989
1005
  reject(new Error(`Timed out waiting for health at ${url}`));
990
1006
  return;
991
1007
  }
992
- setTimeout(check, 250);
1008
+ setTimeout(check2, 250);
993
1009
  };
994
- check();
1010
+ check2();
995
1011
  });
996
1012
  }
997
1013
  async function startPocketbaseServe(opts) {
@@ -1912,205 +1928,17 @@ function printNextSteps(projectPath, packageManager2) {
1912
1928
  }
1913
1929
 
1914
1930
  // src/commands/create.ts
1915
- import fs16 from "node:fs";
1916
- import path14 from "node:path";
1917
- import process8 from "node:process";
1931
+ import fs17 from "node:fs";
1932
+ import path15 from "node:path";
1933
+ import process11 from "node:process";
1918
1934
  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
1935
  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";
1936
+ import * as p8 from "@clack/prompts";
1937
+ import { detect as detect3, resolveCommand as resolveCommand3 } from "package-manager-detector";
2110
1938
 
2111
1939
  // src/lib/providers.ts
2112
- import process9 from "node:process";
2113
- import * as p6 from "@clack/prompts";
1940
+ import process8 from "node:process";
1941
+ import * as p5 from "@clack/prompts";
2114
1942
  import { bySlug } from "@velastack/patterns";
2115
1943
  function capabilityName(slug2) {
2116
1944
  return slug2.replace(/^enable-/, "");
@@ -2145,7 +1973,7 @@ function article(word) {
2145
1973
  return /^[aeiou]/i.test(word) ? "an" : "a";
2146
1974
  }
2147
1975
  function isInteractive() {
2148
- return Boolean(process9.stdout.isTTY) && !process9.env.CI;
1976
+ return Boolean(process8.stdout.isTTY) && !process8.env.CI;
2149
1977
  }
2150
1978
  function providerFlagInArgv(argv) {
2151
1979
  return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
@@ -2177,13 +2005,13 @@ async function resolveProvider(slug2, flagValue) {
2177
2005
  });
2178
2006
  if (decision.kind === "error") throw new Error(decision.message);
2179
2007
  if (decision.kind === "use") return decision.provider;
2180
- const selected = await p6.select({
2008
+ const selected = await p5.select({
2181
2009
  message: `Select ${patternName} provider`,
2182
2010
  options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
2183
2011
  });
2184
- if (p6.isCancel(selected)) {
2185
- p6.cancel("Operation cancelled.");
2186
- process9.exit(0);
2012
+ if (p5.isCancel(selected)) {
2013
+ p5.cancel("Operation cancelled.");
2014
+ process8.exit(0);
2187
2015
  }
2188
2016
  return providers.find((provider) => provider.id === selected);
2189
2017
  }
@@ -2191,7 +2019,7 @@ async function collectProviderEnv(provider) {
2191
2019
  const values = {};
2192
2020
  const interactive = isInteractive();
2193
2021
  for (const variable of provider.env ?? []) {
2194
- const existing = process9.env[variable.key];
2022
+ const existing = process8.env[variable.key];
2195
2023
  if (existing) {
2196
2024
  values[variable.key] = existing;
2197
2025
  continue;
@@ -2200,14 +2028,14 @@ async function collectProviderEnv(provider) {
2200
2028
  values[variable.key] = variable.default ?? "";
2201
2029
  continue;
2202
2030
  }
2203
- const value = await p6.text({
2031
+ const value = await p5.text({
2204
2032
  message: variable.label,
2205
2033
  placeholder: variable.placeholder,
2206
2034
  initialValue: variable.default
2207
2035
  });
2208
- if (p6.isCancel(value)) {
2209
- p6.cancel("Operation cancelled.");
2210
- process9.exit(0);
2036
+ if (p5.isCancel(value)) {
2037
+ p5.cancel("Operation cancelled.");
2038
+ process8.exit(0);
2211
2039
  }
2212
2040
  values[variable.key] = (value ?? "").trim();
2213
2041
  }
@@ -2217,92 +2045,212 @@ function missingEnvKeys(provider, values) {
2217
2045
  return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
2218
2046
  }
2219
2047
 
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;
2048
+ // src/lib/link-on-create.ts
2049
+ var FREE_CMS_HINT = "Get a free CMS at https://velastack.dev";
2050
+ var PROJECT_ID_RE = /^[a-z0-9]{15}$/;
2051
+ var CMS_URL_RE = /^https?:\/\/\S+$/;
2052
+ var NOT_LOGGED_IN = "Not logged in. Run `vela login` to login, or set VELA_API_KEY.";
2053
+ 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}.`;
2054
+ function decideLink(request) {
2055
+ const { link: link2, needsCms, loggedIn, interactive } = request;
2056
+ if (link2 === "none") return { kind: "none" };
2057
+ if (link2 === "new") {
2058
+ return loggedIn ? { kind: "create" } : { kind: "error", message: NOT_LOGGED_IN };
2059
+ }
2060
+ if (link2 !== void 0) {
2061
+ return loggedIn ? { kind: "existing", projectId: link2 } : { kind: "error", message: NOT_LOGGED_IN };
2062
+ }
2063
+ if (!interactive) return { kind: "none", warn: needsCms ? NO_CMS_WARNING : void 0 };
2064
+ if (loggedIn) return { kind: "create" };
2065
+ return needsCms ? { kind: "prompt-cms" } : { kind: "none" };
2066
+ }
2067
+ function cmsEndpointFor(projectId) {
2068
+ return `${API_URL}/v1/projects/${projectId}/cms`;
2069
+ }
2070
+ function normalizeCmsUrl(url) {
2071
+ return url.trim().replace(/\/+$/, "");
2072
+ }
2073
+ function linkNextSteps(outcome) {
2074
+ const steps = [];
2075
+ const { linked, cmsEndpoint, cmsSource, templateCms, loggedIn, interactive } = outcome;
2076
+ if (templateCms && linked && cmsSource === "linked") {
2077
+ steps.push(
2078
+ `Add an editor at ${linked.dashboardUrl}/cms/editors, then open any page with \`?edit\` and sign in from the admin bar.`
2079
+ );
2080
+ } else if (cmsEndpoint) {
2081
+ steps.push("Open any page with `?edit` and sign in from the admin bar.");
2082
+ } else if (templateCms) {
2083
+ steps.push(
2084
+ `When you have a CMS, set \`cmsEndpoint\` in \`src/lib/site.ts\`. ${FREE_CMS_HINT}.`
2085
+ );
2258
2086
  }
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;
2087
+ if (linked && !(templateCms && cmsSource === "linked")) {
2088
+ steps.push(
2089
+ `Run \`vela deploy\` when you're ready; the project is linked to ${linked.dashboardUrl}.`
2090
+ );
2091
+ } else if (!linked && interactive && !loggedIn && !templateCms) {
2092
+ steps.push("Run `vela login` then `vela link` to get a free velastack.app hostname on deploy.");
2273
2093
  }
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
- });
2094
+ return steps;
2095
+ }
2096
+
2097
+ // src/lib/link-project.ts
2098
+ import process9 from "node:process";
2099
+ import * as p6 from "@clack/prompts";
2100
+
2101
+ // src/lib/velastack-api.ts
2102
+ async function apiFetch(apiKey, pathAndQuery, init) {
2103
+ const headers = new Headers(init?.headers);
2104
+ headers.set("Authorization", `Bearer ${apiKey}`);
2105
+ if (init?.body && !headers.has("Content-Type")) {
2106
+ headers.set("Content-Type", "application/json");
2107
+ }
2108
+ const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
2109
+ if (res.status === 401) {
2110
+ throw new Error("API key invalid \u2014 run `vela login`");
2111
+ }
2112
+ if (res.status === 403) {
2113
+ const body = await res.text().catch(() => "");
2114
+ throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
2115
+ }
2116
+ if (!res.ok) {
2117
+ const body = await res.text().catch(() => "");
2118
+ throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
2119
+ }
2120
+ return await res.json();
2121
+ }
2122
+ async function getCurrentUser(apiKey) {
2123
+ const data = await apiFetch(
2124
+ apiKey,
2125
+ "/api/collections/users/records?perPage=1"
2126
+ );
2127
+ const user = data.items[0];
2128
+ if (!user) throw new Error("No user found. Run `vela login` to login.");
2129
+ return user;
2130
+ }
2131
+ async function listTeams(apiKey) {
2132
+ const data = await apiFetch(
2133
+ apiKey,
2134
+ "/api/collections/teams/records?perPage=200"
2135
+ );
2136
+ return data.items;
2137
+ }
2138
+ async function listProjects(apiKey) {
2139
+ const data = await apiFetch(
2140
+ apiKey,
2141
+ "/api/collections/projects/records?perPage=200&expand=team"
2142
+ );
2143
+ return data.items;
2144
+ }
2145
+ async function createProject(apiKey, args) {
2146
+ return apiFetch(apiKey, "/api/collections/projects/records", {
2147
+ method: "POST",
2148
+ body: JSON.stringify({
2149
+ name: args.name,
2150
+ team: args.teamId,
2151
+ user: args.userId,
2152
+ ...args.template ? { template: args.template } : {}
2153
+ })
2154
+ });
2155
+ }
2156
+ async function registerServer(apiKey, input) {
2157
+ return apiFetch(apiKey, "/v1/servers", {
2158
+ method: "POST",
2159
+ body: JSON.stringify(input)
2160
+ });
2161
+ }
2162
+ async function startDeployment(apiKey, projectId, input) {
2163
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
2164
+ method: "POST",
2165
+ body: JSON.stringify(input)
2166
+ });
2167
+ }
2168
+ async function finishDeployment(apiKey, projectId, deploymentId, input) {
2169
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
2170
+ method: "PATCH",
2171
+ body: JSON.stringify(input)
2172
+ });
2173
+ }
2174
+ async function destroyEnvironment(apiKey, projectId, envTag) {
2175
+ return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
2176
+ method: "DELETE"
2177
+ });
2178
+ }
2179
+
2180
+ // src/lib/link-project.ts
2181
+ function dashboardUrl(teamSlug, projectSlug) {
2182
+ return teamSlug && projectSlug ? `${API_URL}/${teamSlug}/${projectSlug}` : API_URL;
2183
+ }
2184
+ async function pickTeam(teams3) {
2185
+ if (teams3.length === 1) return teams3[0];
2186
+ const choice = await p6.select({
2187
+ message: "Select a team",
2188
+ options: teams3.map((team) => ({
2189
+ value: team.id,
2190
+ label: team.is_personal ? `${team.name} (personal)` : team.name
2191
+ }))
2192
+ });
2193
+ if (p6.isCancel(choice)) {
2194
+ p6.cancel("Operation cancelled.");
2195
+ process9.exit(0);
2196
+ }
2197
+ return teams3.find((team) => team.id === choice);
2198
+ }
2199
+ async function resolveTeam(teams3, options) {
2200
+ if (options.teamId) {
2201
+ const team = teams3.find((candidate) => candidate.id === options.teamId);
2202
+ if (!team) {
2203
+ throw new Error(
2204
+ `You are not a member of team ${options.teamId}. Omit --team to use your personal team.`
2205
+ );
2206
+ }
2207
+ return team;
2208
+ }
2209
+ if (teams3.length === 0) throw new Error("No team found on velastack.dev for this account.");
2210
+ const personal = teams3.find((team) => team.is_personal);
2211
+ if (personal) return personal;
2212
+ if (options.interactive) return pickTeam(teams3);
2213
+ throw new Error("Several teams and no personal one: pass --team <id>.");
2214
+ }
2215
+ async function linkNewProject(apiKey, args) {
2216
+ const [user, teams3] = await Promise.all([getCurrentUser(apiKey), listTeams(apiKey)]);
2217
+ const team = await resolveTeam(teams3, { teamId: args.teamId, interactive: args.interactive });
2218
+ const project = await createProject(apiKey, {
2219
+ name: args.name,
2220
+ teamId: team.id,
2221
+ userId: user.id,
2222
+ template: args.template
2223
+ });
2224
+ return toLinked(project, team);
2225
+ }
2226
+ async function linkExistingProject(apiKey, projectId) {
2227
+ const projects = await listProjects(apiKey);
2228
+ const project = projects.find((candidate) => candidate.id === projectId);
2229
+ if (!project) {
2230
+ throw new Error(`No project ${projectId} on velastack.dev for this account.`);
2231
+ }
2232
+ return toLinked(project, project.expand?.team);
2233
+ }
2234
+ function toLinked(project, team) {
2235
+ return {
2236
+ projectId: project.id,
2237
+ teamId: project.team,
2238
+ projectName: project.name,
2239
+ dashboardUrl: dashboardUrl(team?.slug, project.slug)
2240
+ };
2287
2241
  }
2288
2242
 
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";
2294
-
2295
2243
  // src/lib/project-config.ts
2296
- import fs17 from "node:fs";
2297
- import path16 from "node:path";
2244
+ import fs16 from "node:fs";
2245
+ import path14 from "node:path";
2298
2246
  function projectConfigPath(workspaceRootDir) {
2299
- return path16.join(workspaceRootDir, ".vela", "project.json");
2247
+ return path14.join(workspaceRootDir, ".vela", "project.json");
2300
2248
  }
2301
2249
  function readProjectConfig(workspaceRootDir) {
2302
2250
  const file = projectConfigPath(workspaceRootDir);
2303
- if (!fs17.existsSync(file)) return null;
2251
+ if (!fs16.existsSync(file)) return null;
2304
2252
  try {
2305
- const parsed = JSON.parse(fs17.readFileSync(file, "utf8"));
2253
+ const parsed = JSON.parse(fs16.readFileSync(file, "utf8"));
2306
2254
  if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
2307
2255
  return null;
2308
2256
  }
@@ -2317,17 +2265,483 @@ function readProjectConfig(workspaceRootDir) {
2317
2265
  }
2318
2266
  function writeProjectConfig(workspaceRootDir, config) {
2319
2267
  const file = projectConfigPath(workspaceRootDir);
2320
- fs17.mkdirSync(path16.dirname(file), { recursive: true });
2268
+ fs16.mkdirSync(path14.dirname(file), { recursive: true });
2321
2269
  let existing = {};
2322
- if (fs17.existsSync(file)) {
2270
+ if (fs16.existsSync(file)) {
2323
2271
  try {
2324
- existing = JSON.parse(fs17.readFileSync(file, "utf8"));
2272
+ existing = JSON.parse(fs16.readFileSync(file, "utf8"));
2325
2273
  } catch {
2326
2274
  }
2327
2275
  }
2328
- fs17.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2276
+ fs16.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2277
+ }
2278
+
2279
+ // src/commands/login.ts
2280
+ import os3 from "node:os";
2281
+ import process10 from "node:process";
2282
+ import { Command as Command3 } from "commander";
2283
+ import * as p7 from "@clack/prompts";
2284
+ import makeFetchCookie from "fetch-cookie";
2285
+ var login = new Command3("login").description("login to velastack.dev").configureHelp(helpConfig).action(
2286
+ () => runCommand(async () => {
2287
+ await loginInteractively();
2288
+ p7.log.success("Logged in to velastack.dev");
2289
+ }, "Failed to login.")
2290
+ );
2291
+ async function loginInteractively() {
2292
+ const { email: email3, password: password11 } = await p7.group(
2293
+ {
2294
+ email: () => p7.text({ message: "Email" }),
2295
+ password: () => p7.password({ message: "Password" })
2296
+ },
2297
+ {
2298
+ onCancel: () => {
2299
+ p7.cancel("Operation cancelled.");
2300
+ process10.exit(0);
2301
+ }
2302
+ }
2303
+ );
2304
+ const fetchCookie = makeFetchCookie(fetch);
2305
+ const loginRes = await fetchCookie(`${API_URL}/login`, {
2306
+ method: "POST",
2307
+ headers: {
2308
+ "Content-Type": "application/x-www-form-urlencoded",
2309
+ Origin: API_URL
2310
+ },
2311
+ body: new URLSearchParams({ type: "password", email: email3, password: password11 }).toString()
2312
+ });
2313
+ if (!loginRes.headers.get("Set-Cookie")) {
2314
+ throw new Error(
2315
+ "Run `vela signup` to create an account or reset at https://velastack.dev/reset"
2316
+ );
2317
+ }
2318
+ const apiKey = await issueApiKey(fetchCookie);
2319
+ writeConfig({ apiKey });
2320
+ return apiKey;
2321
+ }
2322
+ async function issueApiKey(fetchCookie) {
2323
+ const label4 = `CLI - ${os3.hostname()}`;
2324
+ await fetchCookie(`${API_URL}/api-keys/new`, {
2325
+ method: "POST",
2326
+ headers: {
2327
+ "Content-Type": "application/x-www-form-urlencoded",
2328
+ Origin: API_URL
2329
+ },
2330
+ body: new URLSearchParams({ label: label4 }).toString()
2331
+ });
2332
+ const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
2333
+ const apiKey = extractApiKey(cookie);
2334
+ if (!apiKey) {
2335
+ throw new Error("Failed to create API key. Try again or contact support.");
2336
+ }
2337
+ const [id] = apiKey.split(".");
2338
+ const res = await fetchCookie(`${API_URL}/api/collections/api_keys/records`, {
2339
+ headers: { Authorization: `Bearer ${apiKey}` }
2340
+ });
2341
+ const data = await res.json();
2342
+ for (const item of data.items) {
2343
+ if (item.label === label4 && item.id !== id) {
2344
+ await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
2345
+ method: "DELETE",
2346
+ headers: { Authorization: `Bearer ${apiKey}` }
2347
+ });
2348
+ }
2349
+ }
2350
+ return apiKey;
2351
+ }
2352
+ function extractApiKey(cookie) {
2353
+ const flashCookie = cookie.split(";").find((c) => c.trim().startsWith("flash="));
2354
+ if (!flashCookie) return null;
2355
+ const decoded = decodeURIComponent(flashCookie.split("=")[1]);
2356
+ return JSON.parse(decoded).apiKey;
2357
+ }
2358
+
2359
+ // src/commands/create.ts
2360
+ function optionsSchema2(listing) {
2361
+ const names = listing.templates.map((template) => template.name);
2362
+ let choices2 = `must be one of: ${templateChoicesMessage(listing.templates)}`;
2363
+ if (listing.registryError) {
2364
+ choices2 += ` (could not reach the template registry: ${listing.registryError})`;
2365
+ }
2366
+ return v4.strictObject({
2367
+ install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
2368
+ template: v4.optional(v4.picklist(names, choices2)),
2369
+ name: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
2370
+ email: v4.optional(v4.pipe(v4.string(), v4.email("must be a valid email address"))),
2371
+ password: v4.optional(v4.pipe(v4.string(), v4.minLength(8, "must be at least 8 characters long"))),
2372
+ link: v4.optional(
2373
+ v4.pipe(
2374
+ v4.string(),
2375
+ v4.check(
2376
+ (value) => value === "new" || value === "none" || PROJECT_ID_RE.test(value),
2377
+ "must be `new`, `none` or a velastack.dev project id"
2378
+ )
2379
+ )
2380
+ ),
2381
+ team: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
2382
+ cms: v4.optional(
2383
+ v4.pipe(v4.string(), v4.trim(), v4.regex(CMS_URL_RE, "must be an absolute CMS URL"))
2384
+ )
2385
+ });
2386
+ }
2387
+ function checkFlagsForTemplate(template, options) {
2388
+ if (!template.backend && (options.email || options.password)) {
2389
+ throw new Error(
2390
+ `--email and --password don't apply to the ${template.name} template \u2014 it has no backend.`
2391
+ );
2392
+ }
2393
+ if (options.cms !== void 0 && !template.cms) {
2394
+ throw new Error(
2395
+ `--cms doesn't apply to the ${template.name} template \u2014 it reads no copy from a CMS.`
2396
+ );
2397
+ }
2398
+ if (options.team !== void 0 && options.link !== "new") {
2399
+ throw new Error("--team only applies together with --link new.");
2400
+ }
2401
+ }
2402
+ 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(
2403
+ "--link <new|none|project-id>",
2404
+ "link to a velastack.dev project: create one, skip, or use an existing project id (default: create when logged in at a terminal)"
2405
+ ).option("--team <id>", "velastack.dev team for `--link new` (default: your personal team)").option(
2406
+ "--cms <url>",
2407
+ "read from a CMS at this URL instead of the linked project's (CMS-ready templates only)"
2408
+ ).addOption(installOption).configureHelp(helpConfig).action((projectPath, rawOpts) => {
2409
+ return runCommand(async () => {
2410
+ const listing = await listAllTemplates();
2411
+ const options = parseOptions(optionsSchema2(listing), rawOpts);
2412
+ const { directory, packageManager: packageManager2, name, template, link: link2 } = await createProject2(
2413
+ projectPath,
2414
+ options,
2415
+ listing
2416
+ );
2417
+ const relative = path15.relative(process11.cwd(), directory);
2418
+ const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
2419
+ const nextSteps = [];
2420
+ if (relative !== "") {
2421
+ const hasSpaces = relative.includes(" ");
2422
+ nextSteps.push(`\`cd ${hasSpaces ? `"${relative}"` : relative}\``);
2423
+ }
2424
+ if (!packageManager2) {
2425
+ const resolved = resolveCommand3(pm, "install", []);
2426
+ if (resolved) {
2427
+ nextSteps.push(
2428
+ `\`${resolved.command} ${resolved.args.join(" ")}\` to install dependencies`
2429
+ );
2430
+ }
2431
+ }
2432
+ const runDev = resolveCommand3(pm, "run", ["dev", "--open"]);
2433
+ if (runDev) {
2434
+ nextSteps.push(
2435
+ `\`${runDev.command} ${runDev.args.join(" ")}\` to start the dev server (Ctrl-C to stop)`
2436
+ );
2437
+ }
2438
+ if (template.nextSteps) {
2439
+ nextSteps.push(...template.nextSteps);
2440
+ } else if (template.backend) {
2441
+ nextSteps.push("Run `vela generate scaffold <model>` to generate your first CRUD pages.");
2442
+ } else {
2443
+ nextSteps.push(
2444
+ "Set your deployed URL in `src/lib/site.ts` before building for production."
2445
+ );
2446
+ nextSteps.push("Run `vela ui add <component>` to add UI components.");
2447
+ }
2448
+ nextSteps.push(...linkNextSteps(link2));
2449
+ nextSteps.push("Stuck? Visit https://docs.velastack.dev");
2450
+ reportResult({
2451
+ summary: `Created ${name} at ${directory}.`,
2452
+ nextSteps
2453
+ });
2454
+ }, "Failed to create project.");
2455
+ });
2456
+ async function createProject2(cwdArg, options, listing) {
2457
+ const onCancel2 = () => {
2458
+ p8.cancel("Operation cancelled.");
2459
+ process11.exit(0);
2460
+ };
2461
+ const template = findTemplate(listing, options.template ?? DEFAULT_TEMPLATE);
2462
+ checkFlagsForTemplate(template, options);
2463
+ let directory;
2464
+ if (cwdArg) {
2465
+ directory = path15.resolve(cwdArg);
2466
+ } else {
2467
+ const answer = await p8.text({
2468
+ message: "Where would you like your project to be created?",
2469
+ placeholder: " (hit Enter to use current directory)",
2470
+ defaultValue: "./"
2471
+ });
2472
+ if (p8.isCancel(answer)) onCancel2();
2473
+ directory = path15.resolve(answer);
2474
+ }
2475
+ if (fs17.existsSync(directory) && fs17.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
2476
+ const force = await p8.confirm({
2477
+ message: "Directory not empty. Continue?",
2478
+ initialValue: false
2479
+ });
2480
+ if (p8.isCancel(force) || !force) onCancel2();
2481
+ }
2482
+ const dirName = path15.basename(directory);
2483
+ const { name } = await p8.group(
2484
+ {
2485
+ name: () => {
2486
+ if (options.name) return Promise.resolve(options.name);
2487
+ return p8.text({
2488
+ message: "App name (used for emails, etc)",
2489
+ initialValue: dirName || "SvelteKit",
2490
+ validate: (value) => value?.trim() ? void 0 : "App name is required"
2491
+ });
2492
+ }
2493
+ },
2494
+ { onCancel: onCancel2 }
2495
+ );
2496
+ const credentials = template.backend ? await promptCredentials(options, onCancel2) : void 0;
2497
+ const link2 = await linkOnCreate(name, template, options, onCancel2);
2498
+ const projectPath = directory;
2499
+ if (template.source === "remote") p8.log.step(`Downloading template ${template.name}...`);
2500
+ const resolved = await resolveTemplate(template);
2501
+ try {
2502
+ copyTemplate(resolved, projectPath);
2503
+ applyTemplateFiles(projectPath, {
2504
+ appName: name,
2505
+ cliVersion: package_default.version,
2506
+ cmsEndpoint: link2.cmsEndpoint
2507
+ });
2508
+ } finally {
2509
+ resolved.cleanup();
2510
+ }
2511
+ if (!fs17.existsSync(path15.join(projectPath, "package.json"))) {
2512
+ throw new Error(`Template ${template.name} is missing package.template.json`);
2513
+ }
2514
+ if (link2.linked) {
2515
+ const { projectId, teamId, projectName } = link2.linked;
2516
+ writeProjectConfig(projectPath, { projectId, teamId, projectName });
2517
+ }
2518
+ p8.log.success("Project created");
2519
+ let packageManager2;
2520
+ if (options.install !== false) {
2521
+ const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
2522
+ if (pm) {
2523
+ const builds = template.backend ? ["esbuild", "pocketbase-server"] : ["esbuild"];
2524
+ addPnpmBuildDependencies(projectPath, pm, builds);
2525
+ await installDependencies(pm, projectPath);
2526
+ packageManager2 = pm;
2527
+ }
2528
+ }
2529
+ if (credentials) {
2530
+ const { email: email3, password: password11 } = credentials;
2531
+ p8.log.step("Initializing PocketBase...");
2532
+ await createSuperuser(projectPath, email3, password11);
2533
+ await withPocketbase(
2534
+ projectPath,
2535
+ async (pb) => {
2536
+ await pb.settings.update({
2537
+ meta: { appName: name, appURL: "http://localhost:5173" }
2538
+ });
2539
+ },
2540
+ { email: email3, password: password11 }
2541
+ );
2542
+ writeEnvFile(
2543
+ projectPath,
2544
+ {
2545
+ POCKETBASE_SUPERUSER_EMAIL: email3,
2546
+ POCKETBASE_SUPERUSER_PASSWORD: password11
2547
+ },
2548
+ ["PocketBase superuser credentials \u2014 used by `vela` commands"]
2549
+ );
2550
+ p8.log.success("PocketBase initialized");
2551
+ }
2552
+ return { directory: projectPath, packageManager: packageManager2, name, template, link: link2 };
2553
+ }
2554
+ async function linkOnCreate(name, template, options, onCancel2) {
2555
+ const templateCms = template.cms === true;
2556
+ const interactive = isInteractive();
2557
+ const loggedIn = readApiKey() !== null;
2558
+ const outcome = {
2559
+ cmsEndpoint: options.cms ? normalizeCmsUrl(options.cms) : "",
2560
+ cmsSource: options.cms ? "flag" : "none",
2561
+ templateCms,
2562
+ loggedIn,
2563
+ interactive
2564
+ };
2565
+ let decision = decideLink({
2566
+ link: options.link,
2567
+ needsCms: templateCms && !options.cms,
2568
+ loggedIn,
2569
+ interactive
2570
+ });
2571
+ if (decision.kind === "prompt-cms") {
2572
+ const choice = await promptCms(onCancel2);
2573
+ if (choice.kind === "url") {
2574
+ outcome.cmsEndpoint = choice.url;
2575
+ outcome.cmsSource = "prompt";
2576
+ decision = { kind: "none" };
2577
+ } else {
2578
+ decision = { kind: choice.kind === "login" ? "login-then-create" : "none" };
2579
+ }
2580
+ }
2581
+ if (decision.kind === "error") throw new Error(decision.message);
2582
+ let apiKey;
2583
+ if (decision.kind === "login-then-create") {
2584
+ apiKey = await loginInteractively();
2585
+ outcome.loggedIn = true;
2586
+ decision = { kind: "create" };
2587
+ }
2588
+ let linked;
2589
+ if (decision.kind === "create") {
2590
+ p8.log.step(
2591
+ options.link === "new" ? "Linking to a new velastack.dev project..." : "Linking to a new velastack.dev project (pass `--link none` to skip)..."
2592
+ );
2593
+ linked = await linkNewProject(apiKey ?? requireApiKey(), {
2594
+ name,
2595
+ template: template.name,
2596
+ teamId: options.team,
2597
+ interactive
2598
+ });
2599
+ } else if (decision.kind === "existing") {
2600
+ p8.log.step("Linking to velastack.dev...");
2601
+ linked = await linkExistingProject(requireApiKey(), decision.projectId);
2602
+ } else if (decision.kind === "none" && decision.warn) {
2603
+ p8.log.warn(decision.warn);
2604
+ }
2605
+ if (linked) {
2606
+ outcome.linked = linked;
2607
+ p8.log.success(`Linked to ${linked.projectName} (${linked.dashboardUrl})`);
2608
+ if (templateCms && !outcome.cmsEndpoint) {
2609
+ outcome.cmsEndpoint = cmsEndpointFor(linked.projectId);
2610
+ outcome.cmsSource = "linked";
2611
+ p8.log.success(`CMS: ${outcome.cmsEndpoint}`);
2612
+ }
2613
+ }
2614
+ return outcome;
2615
+ }
2616
+ async function promptCms(onCancel2) {
2617
+ p8.note(`This template reads its copy from a hosted CMS.
2618
+ ${FREE_CMS_HINT}.`, "CMS");
2619
+ const choice = await p8.select({
2620
+ message: "Where should the site read its content from?",
2621
+ options: [
2622
+ { value: "login", label: "Log in to velastack.dev and create one", hint: "free" },
2623
+ { value: "url", label: "Use an existing CMS URL" },
2624
+ { value: "skip", label: "Skip for now", hint: "the site shows its fallback copy" }
2625
+ ]
2626
+ });
2627
+ if (p8.isCancel(choice)) onCancel2();
2628
+ if (choice !== "url") return { kind: choice };
2629
+ const url = await p8.text({
2630
+ message: "CMS URL",
2631
+ placeholder: "https://velastack.dev/v1/projects/<project>/cms",
2632
+ validate: (value) => CMS_URL_RE.test(value?.trim() ?? "") ? void 0 : "Enter an absolute http(s) URL"
2633
+ });
2634
+ if (p8.isCancel(url)) onCancel2();
2635
+ return { kind: "url", url: normalizeCmsUrl(url) };
2636
+ }
2637
+ function promptCredentials(options, onCancel2) {
2638
+ return p8.group(
2639
+ {
2640
+ email: () => {
2641
+ if (options.email) return Promise.resolve(options.email);
2642
+ return p8.text({
2643
+ message: "Enter an email for the admin user",
2644
+ initialValue: "admin@example.com",
2645
+ validate: (value) => !value ? "Email is required" : !value.includes("@") ? "Invalid email" : void 0
2646
+ });
2647
+ },
2648
+ password: () => {
2649
+ if (options.password) return Promise.resolve(options.password);
2650
+ return p8.password({
2651
+ message: "Enter a password for the admin user (at least 8 characters)",
2652
+ validate: (value) => !value ? "Password is required" : value.length < 8 ? "Password must be at least 8 characters long" : void 0
2653
+ });
2654
+ }
2655
+ },
2656
+ { onCancel: onCancel2 }
2657
+ );
2658
+ }
2659
+
2660
+ // src/commands/generate.ts
2661
+ import { Command as Command10 } from "commander";
2662
+
2663
+ // src/commands/generate/form.ts
2664
+ import { Command as Command5 } from "commander";
2665
+ import * as p14 from "@clack/prompts";
2666
+
2667
+ // src/lib/pattern-runner.ts
2668
+ import path16 from "node:path";
2669
+ import * as p9 from "@clack/prompts";
2670
+ import { bySlug as bySlug2 } from "@velastack/patterns";
2671
+ function toRelative(root, filePath) {
2672
+ return path16.isAbsolute(filePath) ? path16.relative(root, filePath) : filePath;
2673
+ }
2674
+ var isSuccess = (f) => (f.status ?? "success") === "success";
2675
+ async function runPattern(slug2, argv, input, report4) {
2676
+ const pattern = bySlug2[slug2];
2677
+ if (!pattern) {
2678
+ throw new Error(`Unknown pattern: ${slug2}`);
2679
+ }
2680
+ checkProviderInput(pattern, argv, input);
2681
+ const { workspaceRootDir, features } = await getWorkspace();
2682
+ const log45 = p9.taskLog({ title: report4.task.title });
2683
+ let result;
2684
+ try {
2685
+ result = await pattern.generate({
2686
+ argv,
2687
+ env: "runtime",
2688
+ root: workspaceRootDir,
2689
+ features,
2690
+ input,
2691
+ // Patterns no longer read the schema themselves: @velastack/pocketbase-codegen
2692
+ // takes an injected client, and only the CLI knows how to reach (or spawn)
2693
+ // a PocketBase for this workspace.
2694
+ getCollections: async () => {
2695
+ const { getCollections } = await import("@velastack/pocketbase-codegen");
2696
+ let collections2 = [];
2697
+ await withPocketbase(workspaceRootDir, async (pb) => {
2698
+ collections2 = await getCollections(pb);
2699
+ });
2700
+ return collections2;
2701
+ },
2702
+ logger: { info: (message) => log45.message(message) }
2703
+ });
2704
+ log45.success(report4.task.success);
2705
+ } catch (e) {
2706
+ log45.error(report4.task.error);
2707
+ throw e;
2708
+ }
2709
+ const rel = (f) => toRelative(workspaceRootDir, f);
2710
+ const files = [...result.creates, ...result.modifies, ...result.deletes];
2711
+ const failures = files.filter((f) => !isSuccess(f)).map((f) => ({
2712
+ path: rel(f.path),
2713
+ status: f.status === "not-found" ? "not-found" : "failed",
2714
+ message: f.message
2715
+ }));
2716
+ const created = result.creates.filter(isSuccess);
2717
+ const modified = result.modifies.filter(isSuccess);
2718
+ const deleted = result.deletes.filter(isSuccess);
2719
+ const totalChanges = created.length + modified.length + deleted.length + result.components.length + result.packages.length + result.collections.length;
2720
+ if (totalChanges === 0 && failures.length === 0) {
2721
+ p9.log.info(`${pattern.title ?? slug2} produced no changes.`);
2722
+ return;
2723
+ }
2724
+ reportResult({
2725
+ summary: report4.summary ?? `Applied ${pattern.title ?? slug2}.`,
2726
+ filesCreated: created.map((f) => rel(f.path)),
2727
+ filesModified: modified.map((f) => rel(f.path)),
2728
+ filesDeleted: deleted.map((f) => rel(f.path)),
2729
+ componentsAdded: result.components,
2730
+ packagesInstalled: result.packages,
2731
+ collectionsAdded: result.collections.map((c) => c.name),
2732
+ failures,
2733
+ // Next steps assume the pattern applied; when part of it didn't, the
2734
+ // remediation snippets above are the actual next step.
2735
+ nextSteps: failures.length > 0 ? void 0 : report4.nextSteps
2736
+ });
2329
2737
  }
2330
2738
 
2739
+ // src/lib/ai-flow.ts
2740
+ import fs18 from "node:fs";
2741
+ import path17 from "node:path";
2742
+ import * as p13 from "@clack/prompts";
2743
+ import pc4 from "picocolors";
2744
+
2331
2745
  // src/lib/ai-client.ts
2332
2746
  async function aiPost(workspaceRootDir, endpoint, body) {
2333
2747
  const apiKey = requireApiKey();
@@ -2362,14 +2776,14 @@ var aiSchema = (workspaceRootDir, body) => aiPost(workspaceRootDir, "schema", bo
2362
2776
  var aiForm = (workspaceRootDir, body) => aiPost(workspaceRootDir, "form", body);
2363
2777
 
2364
2778
  // src/lib/ai-loop.ts
2365
- import * as p8 from "@clack/prompts";
2779
+ import * as p10 from "@clack/prompts";
2366
2780
  async function aiLoop(opts) {
2367
2781
  let prompt = opts.initialPrompt;
2368
2782
  let history = [];
2369
2783
  let attempt = 0;
2370
2784
  while (true) {
2371
2785
  attempt++;
2372
- const spinner7 = p8.spinner();
2786
+ const spinner7 = p10.spinner();
2373
2787
  spinner7.start(`${opts.stageLabel} (${attempt > 1 ? "iteration " + attempt : "first pass"})\u2026`);
2374
2788
  let result;
2375
2789
  let turn;
@@ -2383,12 +2797,12 @@ async function aiLoop(opts) {
2383
2797
  throw e;
2384
2798
  }
2385
2799
  opts.renderPreview(result);
2386
- const next = await p8.text({
2800
+ const next = await p10.text({
2387
2801
  message: "Refine the result, or press Enter to apply.",
2388
2802
  placeholder: opts.refinePlaceholder,
2389
2803
  defaultValue: ""
2390
2804
  });
2391
- if (p8.isCancel(next)) return null;
2805
+ if (p10.isCancel(next)) return null;
2392
2806
  const trimmed = (typeof next === "string" ? next : "").trim();
2393
2807
  if (trimmed === "") return result;
2394
2808
  history = turn;
@@ -2397,7 +2811,7 @@ async function aiLoop(opts) {
2397
2811
  }
2398
2812
 
2399
2813
  // src/lib/ai-existing-models.ts
2400
- import * as p9 from "@clack/prompts";
2814
+ import * as p11 from "@clack/prompts";
2401
2815
  async function loadExistingModels(workspaceRootDir) {
2402
2816
  let result = [];
2403
2817
  try {
@@ -2422,7 +2836,7 @@ async function loadExistingModels(workspaceRootDir) {
2422
2836
  });
2423
2837
  } catch (e) {
2424
2838
  const msg = e instanceof Error ? e.message : String(e);
2425
- p9.log.warn(
2839
+ p11.log.warn(
2426
2840
  `Could not load existing schema from PocketBase (${msg}). The AI agent will design without that context.`
2427
2841
  );
2428
2842
  return [];
@@ -2431,7 +2845,7 @@ async function loadExistingModels(workspaceRootDir) {
2431
2845
  }
2432
2846
 
2433
2847
  // src/lib/ai-to-argv.ts
2434
- import * as p10 from "@clack/prompts";
2848
+ import * as p12 from "@clack/prompts";
2435
2849
  var PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["text", "number", "bool", "email", "date", "url", "file"]);
2436
2850
  function singularize(name) {
2437
2851
  if (name.endsWith("ies") && name.length > 3) return `${name.slice(0, -3)}y`;
@@ -2454,7 +2868,7 @@ function collectionSpecToArgv(spec) {
2454
2868
  for (const field of spec.fields) {
2455
2869
  const type = typeArg(field);
2456
2870
  if (type === null) {
2457
- p10.log.warn(
2871
+ p12.log.warn(
2458
2872
  `Skipping field "${field.name}" (type "${field.type}" cannot be represented as a pattern argument)`
2459
2873
  );
2460
2874
  continue;
@@ -2557,10 +2971,10 @@ function renderModel(spec) {
2557
2971
  const tail = extra.length > 0 ? " " + pc4.dim(extra.join(" ")) : "";
2558
2972
  lines.push(` ${f.name.padEnd(nameWidth)} ${f.type.padEnd(typeWidth)} ${required}${tail}`);
2559
2973
  }
2560
- p11.log.message(lines.join("\n"));
2974
+ p13.log.message(lines.join("\n"));
2561
2975
  }
2562
2976
  function renderLayout(layout) {
2563
- p11.log.message(renderGrid(layout));
2977
+ p13.log.message(renderGrid(layout));
2564
2978
  }
2565
2979
  async function runSchemaStage(opts) {
2566
2980
  const { workspaceRootDir } = await getWorkspace();
@@ -2607,7 +3021,7 @@ function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
2607
3021
  }
2608
3022
 
2609
3023
  // 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(
3024
+ 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
3025
  "--route <route>",
2612
3026
  'place the form at a custom route (e.g. "(app)/[team_id]/projects/new"). Defaults to the model name under (app)/(public).'
2613
3027
  ).option(
@@ -2624,12 +3038,12 @@ var form = new Command4("form").description("generate a form from a model").argu
2624
3038
  }
2625
3039
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "form" });
2626
3040
  if (!stage2) {
2627
- p12.cancel("Aborted before any files were written.");
3041
+ p14.cancel("Aborted before any files were written.");
2628
3042
  return;
2629
3043
  }
2630
3044
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2631
3045
  if (!layout) {
2632
- p12.cancel("Aborted before any files were written.");
3046
+ p14.cancel("Aborted before any files were written.");
2633
3047
  return;
2634
3048
  }
2635
3049
  argv = specToArgv(stage2.model);
@@ -2670,9 +3084,9 @@ var form = new Command4("form").description("generate a form from a model").argu
2670
3084
  );
2671
3085
 
2672
3086
  // 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(
3087
+ import { Command as Command6 } from "commander";
3088
+ import * as p15 from "@clack/prompts";
3089
+ 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
3090
  (model, fields, options) => runCommand(async () => {
2677
3091
  let argv;
2678
3092
  let modelName;
@@ -2682,7 +3096,7 @@ var schema = new Command5("schema").description("generate a schema from a model"
2682
3096
  }
2683
3097
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "schema" });
2684
3098
  if (!stage2) {
2685
- p13.cancel("Aborted before any files were written.");
3099
+ p15.cancel("Aborted before any files were written.");
2686
3100
  return;
2687
3101
  }
2688
3102
  argv = specToArgv(stage2.model);
@@ -2715,8 +3129,8 @@ var schema = new Command5("schema").description("generate a schema from a model"
2715
3129
  );
2716
3130
 
2717
3131
  // 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(
3132
+ import { Command as Command7 } from "commander";
3133
+ 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
3134
  (model, fields) => runCommand(
2721
3135
  () => runPattern(
2722
3136
  "generate-resource",
@@ -2741,9 +3155,9 @@ var resource = new Command6("resource").description("generate a resource (model
2741
3155
  );
2742
3156
 
2743
3157
  // 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(
3158
+ import { Command as Command8 } from "commander";
3159
+ import * as p16 from "@clack/prompts";
3160
+ 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
3161
  "--route <route>",
2748
3162
  'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under (app)/(public).'
2749
3163
  ).option(
@@ -2760,12 +3174,12 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2760
3174
  }
2761
3175
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "scaffold" });
2762
3176
  if (!stage2) {
2763
- p14.cancel("Aborted before any files were written.");
3177
+ p16.cancel("Aborted before any files were written.");
2764
3178
  return;
2765
3179
  }
2766
3180
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2767
3181
  if (!layout) {
2768
- p14.cancel("Aborted before any files were written.");
3182
+ p16.cancel("Aborted before any files were written.");
2769
3183
  return;
2770
3184
  }
2771
3185
  argv = specToArgv(stage2.model);
@@ -2807,8 +3221,8 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2807
3221
  );
2808
3222
 
2809
3223
  // 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(
3224
+ import { Command as Command9 } from "commander";
3225
+ 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
3226
  (collection, op, args) => runCommand(
2813
3227
  () => runPattern(
2814
3228
  "generate-migration",
@@ -2832,14 +3246,14 @@ var migration = new Command8("migration").description("generate a migration for
2832
3246
  );
2833
3247
 
2834
3248
  // 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);
3249
+ 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
3250
 
2837
3251
  // src/commands/enable.ts
2838
- import { Command as Command25 } from "commander";
3252
+ import { Command as Command26 } from "commander";
2839
3253
 
2840
3254
  // 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(
3255
+ import { Command as Command11 } from "commander";
3256
+ 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
3257
  (opts, cmd) => runCommand(async () => {
2844
3258
  const provider = await resolveProvider("enable-analytics", opts.provider);
2845
3259
  const providerEnv = await collectProviderEnv(provider);
@@ -2869,8 +3283,8 @@ var analytics = new Command10("analytics").description("enable web analytics (Pl
2869
3283
  );
2870
3284
 
2871
3285
  // 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(
3286
+ import { Command as Command12 } from "commander";
3287
+ var auth = new Command12("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2874
3288
  (_opts, cmd) => runCommand(
2875
3289
  () => runPattern(
2876
3290
  "enable-auth",
@@ -2895,8 +3309,8 @@ var auth = new Command11("auth").description("enable authentication (email/passw
2895
3309
  );
2896
3310
 
2897
3311
  // 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(
3312
+ import { Command as Command13 } from "commander";
3313
+ var api = new Command13("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2900
3314
  (_opts, cmd) => runCommand(
2901
3315
  () => runPattern(
2902
3316
  "enable-api",
@@ -2921,8 +3335,8 @@ var api = new Command12("api").description("enable the PocketBase REST API").all
2921
3335
  );
2922
3336
 
2923
3337
  // 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(
3338
+ import { Command as Command14 } from "commander";
3339
+ var apiKeys = new Command14("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2926
3340
  (_opts, cmd) => runCommand(
2927
3341
  () => runPattern(
2928
3342
  "enable-api-keys",
@@ -2947,8 +3361,8 @@ var apiKeys = new Command13("api-keys").description("enable API key management")
2947
3361
  );
2948
3362
 
2949
3363
  // 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(
3364
+ import { Command as Command15 } from "commander";
3365
+ var backend = new Command15("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2952
3366
  (_opts, cmd) => runCommand(
2953
3367
  () => runPattern(
2954
3368
  "enable-backend",
@@ -2973,8 +3387,8 @@ var backend = new Command14("backend").description("enable the PocketBase backen
2973
3387
  );
2974
3388
 
2975
3389
  // 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(
3390
+ import { Command as Command16 } from "commander";
3391
+ var i18n = new Command16("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2978
3392
  (_opts, cmd) => runCommand(
2979
3393
  () => runPattern(
2980
3394
  "enable-i18n",
@@ -2999,8 +3413,8 @@ var i18n = new Command15("i18n").description("enable internationalization").allo
2999
3413
  );
3000
3414
 
3001
3415
  // 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(
3416
+ import { Command as Command17 } from "commander";
3417
+ var teams = new Command17("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3004
3418
  (_opts, cmd) => runCommand(
3005
3419
  () => runPattern(
3006
3420
  "enable-teams",
@@ -3025,11 +3439,11 @@ var teams = new Command16("teams").description("enable team / multi-tenant suppo
3025
3439
  );
3026
3440
 
3027
3441
  // 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";
3442
+ import process12 from "node:process";
3443
+ import { Command as Command18 } from "commander";
3444
+ import * as p17 from "@clack/prompts";
3031
3445
  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(
3446
+ var payments = new Command18("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3033
3447
  (opts, cmd) => runCommand(async () => {
3034
3448
  const provider = await resolveProvider2(opts.provider, cmd.getOptionValueSource("provider"));
3035
3449
  const input = {
@@ -3064,21 +3478,21 @@ async function resolveProvider2(value, source) {
3064
3478
  }
3065
3479
  return value;
3066
3480
  }
3067
- const selected = await p15.select({
3481
+ const selected = await p17.select({
3068
3482
  message: "Which payment provider?",
3069
3483
  options: PROVIDERS,
3070
3484
  initialValue: "stripe"
3071
3485
  });
3072
- if (p15.isCancel(selected)) {
3073
- p15.cancel("Operation cancelled.");
3074
- process10.exit(0);
3486
+ if (p17.isCancel(selected)) {
3487
+ p17.cancel("Operation cancelled.");
3488
+ process12.exit(0);
3075
3489
  }
3076
3490
  return selected;
3077
3491
  }
3078
3492
  async function ensureWebhookSecret() {
3079
- const existing = process10.env.STRIPE_WEBHOOK_SECRET;
3493
+ const existing = process12.env.STRIPE_WEBHOOK_SECRET;
3080
3494
  if (existing) return existing;
3081
- p15.note(
3495
+ p17.note(
3082
3496
  [
3083
3497
  "Download the Stripe CLI (https://stripe.com/docs/stripe-cli), then run:",
3084
3498
  " stripe listen --forward-to localhost:5173/webhooks/stripe",
@@ -3090,7 +3504,7 @@ async function ensureWebhookSecret() {
3090
3504
  return promptPassword("Stripe webhook signing secret (whsec_...)");
3091
3505
  }
3092
3506
  async function ensurePriceId() {
3093
- p15.note(
3507
+ p17.note(
3094
3508
  [
3095
3509
  "Stripe checkout requires a product and price_id.",
3096
3510
  "If you have a demo product price_id, enter it below, or leave blank to create a demo one for you."
@@ -3098,36 +3512,36 @@ async function ensurePriceId() {
3098
3512
  "Stripe demo product",
3099
3513
  { format: (line) => line }
3100
3514
  );
3101
- const value = await p15.text({
3515
+ const value = await p17.text({
3102
3516
  message: "Stripe price_id (price_...)",
3103
3517
  placeholder: "leave blank to create a demo product"
3104
3518
  });
3105
- if (p15.isCancel(value)) {
3106
- p15.cancel("Operation cancelled.");
3107
- process10.exit(0);
3519
+ if (p17.isCancel(value)) {
3520
+ p17.cancel("Operation cancelled.");
3521
+ process12.exit(0);
3108
3522
  }
3109
3523
  return (value ?? "").trim();
3110
3524
  }
3111
3525
  async function ensureKey(envVar, message) {
3112
- const existing = process10.env[envVar];
3526
+ const existing = process12.env[envVar];
3113
3527
  if (existing) return existing;
3114
3528
  return promptPassword(message);
3115
3529
  }
3116
3530
  async function promptPassword(message) {
3117
- const value = await p15.password({
3531
+ const value = await p17.password({
3118
3532
  message,
3119
3533
  validate: (v10) => v10 && v10.length ? void 0 : "Required"
3120
3534
  });
3121
- if (p15.isCancel(value)) {
3122
- p15.cancel("Operation cancelled.");
3123
- process10.exit(0);
3535
+ if (p17.isCancel(value)) {
3536
+ p17.cancel("Operation cancelled.");
3537
+ process12.exit(0);
3124
3538
  }
3125
3539
  return value;
3126
3540
  }
3127
3541
 
3128
3542
  // 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(
3543
+ import { Command as Command19 } from "commander";
3544
+ var subscriptions = new Command19("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3131
3545
  (_opts, cmd) => runCommand(
3132
3546
  () => runPattern(
3133
3547
  "enable-subscriptions",
@@ -3152,8 +3566,8 @@ var subscriptions = new Command18("subscriptions").description("enable Stripe su
3152
3566
  );
3153
3567
 
3154
3568
  // 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(
3569
+ import { Command as Command20 } from "commander";
3570
+ var notifications = new Command20("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3157
3571
  (_opts, cmd) => runCommand(
3158
3572
  () => runPattern(
3159
3573
  "enable-notifications",
@@ -3178,15 +3592,15 @@ var notifications = new Command19("notifications").description("enable in-app no
3178
3592
  );
3179
3593
 
3180
3594
  // 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";
3595
+ import process16 from "node:process";
3596
+ import { Command as Command21 } from "commander";
3597
+ import * as p20 from "@clack/prompts";
3184
3598
  import pc8 from "picocolors";
3185
3599
 
3186
3600
  // src/lib/server-command.ts
3187
- import process13 from "node:process";
3601
+ import process15 from "node:process";
3188
3602
  import * as v6 from "valibot";
3189
- import * as p16 from "@clack/prompts";
3603
+ import * as p18 from "@clack/prompts";
3190
3604
  import pc5 from "picocolors";
3191
3605
 
3192
3606
  // src/lib/deploy-config.ts
@@ -3360,10 +3774,10 @@ import { resolveCommand as resolveCommand4 } from "package-manager-detector/comm
3360
3774
 
3361
3775
  // src/lib/ssh.ts
3362
3776
  import fs20 from "node:fs";
3363
- import os3 from "node:os";
3777
+ import os4 from "node:os";
3364
3778
  import path19 from "node:path";
3365
3779
  import crypto3 from "node:crypto";
3366
- import process11 from "node:process";
3780
+ import process13 from "node:process";
3367
3781
  import { spawn as spawn2 } from "node:child_process";
3368
3782
  var RemoteCommandError = class extends Error {
3369
3783
  exitCode;
@@ -3404,7 +3818,7 @@ var SshSession = class {
3404
3818
  }
3405
3819
  async open() {
3406
3820
  if (this.controlPath) return;
3407
- const dir = path19.join(os3.tmpdir(), "vela-ssh");
3821
+ const dir = path19.join(os4.tmpdir(), "vela-ssh");
3408
3822
  fs20.mkdirSync(dir, { recursive: true, mode: 448 });
3409
3823
  const socket = path19.join(dir, `${crypto3.randomBytes(6).toString("hex")}.sock`);
3410
3824
  this.controlPath = socket;
@@ -3641,17 +4055,17 @@ function spawnCapture(command, args, opts = {}) {
3641
4055
  const child = spawn2(command, args, {
3642
4056
  stdio,
3643
4057
  cwd: opts.cwd,
3644
- env: opts.env ? { ...process11.env, ...opts.env } : void 0
4058
+ env: opts.env ? { ...process13.env, ...opts.env } : void 0
3645
4059
  });
3646
4060
  let stdout = "";
3647
4061
  let stderr = "";
3648
4062
  child.stdout?.on("data", (chunk) => {
3649
4063
  stdout += chunk;
3650
- if (opts.streamStdout) process11.stdout.write(chunk);
4064
+ if (opts.streamStdout) process13.stdout.write(chunk);
3651
4065
  });
3652
4066
  child.stderr?.on("data", (chunk) => {
3653
4067
  stderr += chunk;
3654
- if (opts.stream) process11.stderr.write(chunk);
4068
+ if (opts.stream) process13.stderr.write(chunk);
3655
4069
  });
3656
4070
  child.on("error", reject);
3657
4071
  child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
@@ -3758,7 +4172,7 @@ function sshOptionsFrom(options) {
3758
4172
  import crypto4 from "node:crypto";
3759
4173
  import fs22 from "node:fs";
3760
4174
  import path21 from "node:path";
3761
- import process12 from "node:process";
4175
+ import process14 from "node:process";
3762
4176
  var VELA_ROOT = "/var/lib/vela";
3763
4177
  var VELA_ETC = "/etc/vela";
3764
4178
  var VELA_USER = "vela";
@@ -3795,7 +4209,7 @@ async function syncServerScripts(session) {
3795
4209
  const dir = `${SCRIPT_VERSIONS_DIR}/${digest}`;
3796
4210
  const present = await session.script(`[ -d "$1" ] && echo yes || echo no`, { args: [dir] });
3797
4211
  if (present.stdout.trim() !== "yes") {
3798
- const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process12.pid}.${Date.now()}`;
4212
+ const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process14.pid}.${Date.now()}`;
3799
4213
  await session.script(`mkdir -p "$1" && chmod 0755 "$(dirname "$1")" "$1"`, {
3800
4214
  args: [incoming]
3801
4215
  });
@@ -4159,7 +4573,7 @@ async function ensureBinding(workspaceRootDir, target, request = {}) {
4159
4573
  writeBinding(workspaceRootDir, key, binding);
4160
4574
  }
4161
4575
  if (moving) {
4162
- p16.log.warn(
4576
+ p18.log.warn(
4163
4577
  `${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
4164
4578
 
4165
4579
  Whatever is running on ${existing.server} is left there, and this project can no
@@ -4170,7 +4584,7 @@ longer reach it. Remove it there first if that was not intended.`
4170
4584
  }
4171
4585
  async function confirmMove(target, from, to) {
4172
4586
  const name = bindingName(target);
4173
- if (!process13.stdout.isTTY || process13.env.CI) {
4587
+ if (!process15.stdout.isTTY || process15.env.CI) {
4174
4588
  throw new Error(
4175
4589
  `${pc5.cyan(`--server ${to}`)} does not match the server recorded for ${pc5.cyan(name)}, ${pc5.cyan(from)}.
4176
4590
 
@@ -4178,13 +4592,13 @@ Drop ${pc5.cyan("--server")} to use the recorded one, or move the binding on pur
4178
4592
  this command once from a terminal (or editing .vela/project.json).`
4179
4593
  );
4180
4594
  }
4181
- const ok = await p16.confirm({
4595
+ const ok = await p18.confirm({
4182
4596
  message: `${name} ${target.kind === "preview" ? "run" : "runs"} on ${from}. Point ${name} at ${to} instead?`,
4183
4597
  initialValue: false
4184
4598
  });
4185
- if (p16.isCancel(ok) || !ok) {
4186
- p16.cancel("Operation cancelled.");
4187
- process13.exit(0);
4599
+ if (p18.isCancel(ok) || !ok) {
4600
+ p18.cancel("Operation cancelled.");
4601
+ process15.exit(0);
4188
4602
  }
4189
4603
  }
4190
4604
  function bindingName(target) {
@@ -4192,7 +4606,7 @@ function bindingName(target) {
4192
4606
  }
4193
4607
  async function promptServer(target) {
4194
4608
  const name = bindingName(target);
4195
- if (!process13.stdout.isTTY || process13.env.CI) {
4609
+ if (!process15.stdout.isTTY || process15.env.CI) {
4196
4610
  throw new Error(
4197
4611
  `${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
4198
4612
 
@@ -4200,29 +4614,29 @@ Pass ${pc5.cyan("--server user@host")}, or run the command once from your own ma
4200
4614
  and commit ${pc5.cyan(".vela/project.json")}.`
4201
4615
  );
4202
4616
  }
4203
- p16.log.info(
4617
+ p18.log.info(
4204
4618
  `${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
4205
4619
  );
4206
- const value = await p16.text({
4620
+ const value = await p18.text({
4207
4621
  message: `Which server should ${name} run on?`,
4208
4622
  placeholder: "root@203.0.113.10",
4209
4623
  validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
4210
4624
  });
4211
- if (p16.isCancel(value)) {
4212
- p16.cancel("Operation cancelled.");
4213
- process13.exit(0);
4625
+ if (p18.isCancel(value)) {
4626
+ p18.cancel("Operation cancelled.");
4627
+ process15.exit(0);
4214
4628
  }
4215
4629
  return value.trim();
4216
4630
  }
4217
4631
  async function promptDomain(target) {
4218
- if (!process13.stdout.isTTY || process13.env.CI) return void 0;
4219
- const value = await p16.text({
4632
+ if (!process15.stdout.isTTY || process15.env.CI) return void 0;
4633
+ const value = await p18.text({
4220
4634
  message: `Which hostname should ${target.name} be served on?`,
4221
4635
  placeholder: "example.com \u2014 leave blank to decide later"
4222
4636
  });
4223
- if (p16.isCancel(value)) {
4224
- p16.cancel("Operation cancelled.");
4225
- process13.exit(0);
4637
+ if (p18.isCancel(value)) {
4638
+ p18.cancel("Operation cancelled.");
4639
+ process15.exit(0);
4226
4640
  }
4227
4641
  return value.trim() || void 0;
4228
4642
  }
@@ -4230,10 +4644,10 @@ async function applyRestart(ctx) {
4230
4644
  const outcome = await restartInstance(ctx.session, ctx.instance);
4231
4645
  if (!outcome.deployed) return;
4232
4646
  if (outcome.restarted) {
4233
- p16.log.success("App restarted");
4647
+ p18.log.success("App restarted");
4234
4648
  return;
4235
4649
  }
4236
- p16.log.error(
4650
+ p18.log.error(
4237
4651
  `App restart failed.
4238
4652
 
4239
4653
  The new value is stored and will be used the next time the app starts.
@@ -4242,7 +4656,7 @@ ${pc5.dim(outcome.error ?? "")}`
4242
4656
  }
4243
4657
  async function applyEnvRestart(ctx, changed) {
4244
4658
  if (touchesSuperuser(changed)) {
4245
- p16.log.warn(
4659
+ p18.log.warn(
4246
4660
  `PocketBase superuser credentials changed.
4247
4661
 
4248
4662
  The database still holds the old ones, so the app has not been restarted.
@@ -4279,7 +4693,7 @@ import pc7 from "picocolors";
4279
4693
 
4280
4694
  // src/lib/local-env.ts
4281
4695
  import fs24 from "node:fs";
4282
- import * as p17 from "@clack/prompts";
4696
+ import * as p19 from "@clack/prompts";
4283
4697
  import pc6 from "picocolors";
4284
4698
  function readLocalEnv(envFile) {
4285
4699
  if (!fs24.existsSync(envFile)) return {};
@@ -4305,16 +4719,16 @@ async function applyLocalEnvChange(ctx, changed) {
4305
4719
  process.env.POCKETBASE_SUPERUSER_EMAIL = email3;
4306
4720
  process.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
4307
4721
  await ensureSuperuser(ctx.workspaceRootDir);
4308
- p17.log.success("Local superuser updated to match");
4722
+ p19.log.success("Local superuser updated to match");
4309
4723
  } else {
4310
- p17.log.warn(
4724
+ p19.log.warn(
4311
4725
  `The local database still has the old superuser.
4312
4726
  Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SUPERUSER_PASSWORD")} to reconcile it.`
4313
4727
  );
4314
4728
  }
4315
4729
  }
4316
4730
  if (getPocketbaseMetadata(ctx.workspaceRootDir)) {
4317
- p17.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4731
+ p19.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4318
4732
  }
4319
4733
  }
4320
4734
 
@@ -4478,7 +4892,7 @@ function hasFile(dir) {
4478
4892
 
4479
4893
  // src/commands/enable/s3.ts
4480
4894
  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),
4895
+ 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
4896
  "local"
4483
4897
  ).action(
4484
4898
  (raw) => runCommand(() => {
@@ -4496,7 +4910,7 @@ var s3 = addTargetOptions(
4496
4910
  failure = error instanceof Error ? error.message : String(error);
4497
4911
  }
4498
4912
  if (failure) {
4499
- p18.log.warn(
4913
+ p20.log.warn(
4500
4914
  `The connection test failed \u2014 the settings are saved but may be wrong.
4501
4915
 
4502
4916
  ${pc8.dim(failure)}
@@ -4540,64 +4954,64 @@ Do that first, then re-run with ${pc8.cyan("--force")}.`
4540
4954
  );
4541
4955
  }
4542
4956
  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");
4957
+ const endpoint = options.endpoint ?? await text9("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4958
+ const bucket = options.bucket ?? await text9("S3 bucket name", existing.bucket);
4959
+ const region = options.region ?? await text9("S3 region", existing.region || "us-east-1");
4960
+ const accessKey = options.accessKey ?? await text9("S3 access key", existing.accessKey);
4961
+ const secret = options.secret ?? process16.env.VELA_S3_SECRET ?? await password6("S3 secret key");
4548
4962
  const forcePathStyle = options.forcePathStyle ?? await confirm4(
4549
4963
  "Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
4550
4964
  defaultForcePathStyle(endpoint)
4551
4965
  );
4552
4966
  return { endpoint, bucket, region, accessKey, secret, forcePathStyle };
4553
4967
  }
4554
- async function text8(message, initialValue = "") {
4555
- const value = await p18.text({
4968
+ async function text9(message, initialValue = "") {
4969
+ const value = await p20.text({
4556
4970
  message,
4557
4971
  initialValue,
4558
4972
  validate: (input) => input?.trim() ? void 0 : `${message} is required`
4559
4973
  });
4560
- if (p18.isCancel(value)) {
4561
- p18.cancel("Operation cancelled.");
4562
- process14.exit(0);
4974
+ if (p20.isCancel(value)) {
4975
+ p20.cancel("Operation cancelled.");
4976
+ process16.exit(0);
4563
4977
  }
4564
4978
  return value.trim();
4565
4979
  }
4566
- async function password5(message) {
4567
- const value = await p18.password({
4980
+ async function password6(message) {
4981
+ const value = await p20.password({
4568
4982
  message,
4569
4983
  validate: (input) => input ? void 0 : `${message} is required`
4570
4984
  });
4571
- if (p18.isCancel(value)) {
4572
- p18.cancel("Operation cancelled.");
4573
- process14.exit(0);
4985
+ if (p20.isCancel(value)) {
4986
+ p20.cancel("Operation cancelled.");
4987
+ process16.exit(0);
4574
4988
  }
4575
4989
  return value;
4576
4990
  }
4577
4991
  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);
4992
+ const value = await p20.confirm({ message, initialValue });
4993
+ if (p20.isCancel(value)) {
4994
+ p20.cancel("Operation cancelled.");
4995
+ process16.exit(0);
4582
4996
  }
4583
4997
  return value;
4584
4998
  }
4585
4999
 
4586
5000
  // 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(
5001
+ import process17 from "node:process";
5002
+ import { Command as Command22 } from "commander";
5003
+ import * as p21 from "@clack/prompts";
5004
+ var smtp = new Command22("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4591
5005
  () => runCommand(async () => {
4592
5006
  const { workspaceRootDir } = await getWorkspace();
4593
- const config = await p19.group(
5007
+ const config = await p21.group(
4594
5008
  {
4595
- host: () => p19.text({
5009
+ host: () => p21.text({
4596
5010
  message: "SMTP host",
4597
5011
  placeholder: "smtp.example.com",
4598
5012
  validate: (v10) => v10 ? void 0 : "Host is required"
4599
5013
  }),
4600
- port: () => p19.text({
5014
+ port: () => p21.text({
4601
5015
  message: "SMTP port",
4602
5016
  initialValue: "587",
4603
5017
  validate: (v10) => {
@@ -4607,13 +5021,13 @@ var smtp = new Command21("smtp").description("configure SMTP for transactional e
4607
5021
  return void 0;
4608
5022
  }
4609
5023
  }),
4610
- username: () => p19.text({ message: "SMTP username" }),
4611
- password: () => p19.password({ message: "SMTP password" })
5024
+ username: () => p21.text({ message: "SMTP username" }),
5025
+ password: () => p21.password({ message: "SMTP password" })
4612
5026
  },
4613
5027
  {
4614
5028
  onCancel: () => {
4615
- p19.cancel("Operation cancelled.");
4616
- process15.exit(0);
5029
+ p21.cancel("Operation cancelled.");
5030
+ process17.exit(0);
4617
5031
  }
4618
5032
  }
4619
5033
  );
@@ -4640,24 +5054,24 @@ var smtp = new Command21("smtp").description("configure SMTP for transactional e
4640
5054
  );
4641
5055
 
4642
5056
  // 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";
5057
+ import process18 from "node:process";
5058
+ import { Command as Command23 } from "commander";
5059
+ import * as p22 from "@clack/prompts";
4646
5060
  import pc9 from "picocolors";
4647
- var cms = new Command22("cms").description("enable an inline-editing CMS with an admin bar").option(
5061
+ var cms = new Command23("cms").description("enable an inline-editing CMS with an admin bar").option(
4648
5062
  "--endpoint <url>",
4649
5063
  "read from a hosted CMS at this URL instead of installing the backend in this app"
4650
5064
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4651
5065
  (opts, cmd) => runCommand(async () => {
4652
5066
  if (!opts.endpoint && !hasBackend()) {
4653
- p20.log.error(
5067
+ p22.log.error(
4654
5068
  `${pc9.cyan("vela enable cms")} needs a server to host the CMS backend, and this project is static.
4655
5069
 
4656
5070
  Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${pc9.cyan("vela enable cms --endpoint <url>")}.`
4657
5071
  );
4658
- p20.log.message();
4659
- p20.cancel("Operation failed.");
4660
- process16.exitCode = 1;
5072
+ p22.log.message();
5073
+ p22.cancel("Operation failed.");
5074
+ process18.exitCode = 1;
4661
5075
  return;
4662
5076
  }
4663
5077
  await runPattern("enable-cms", cmd.args, opts.endpoint ? { endpoint: opts.endpoint } : {}, {
@@ -4677,8 +5091,8 @@ Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${
4677
5091
  );
4678
5092
 
4679
5093
  // 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(
5094
+ import { Command as Command24 } from "commander";
5095
+ var blog = new Command24("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4682
5096
  (_opts, cmd) => runCommand(
4683
5097
  () => runPattern(
4684
5098
  "enable-blog",
@@ -4703,8 +5117,8 @@ var blog = new Command23("blog").description("enable an mdsvex blog with posts,
4703
5117
  );
4704
5118
 
4705
5119
  // 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(
5120
+ import { Command as Command25 } from "commander";
5121
+ var contentNegotiation = new Command25("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4708
5122
  (_opts, cmd) => runCommand(
4709
5123
  () => runPattern(
4710
5124
  "enable-content-negotiation",
@@ -4728,33 +5142,33 @@ var contentNegotiation = new Command24("content-negotiation").description("enabl
4728
5142
  );
4729
5143
 
4730
5144
  // 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);
5145
+ 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
5146
 
4733
5147
  // src/commands/disable.ts
4734
- import { Command as Command36 } from "commander";
5148
+ import { Command as Command37 } from "commander";
4735
5149
 
4736
5150
  // src/commands/disable/auth.ts
4737
- import { Command as Command26 } from "commander";
5151
+ import { Command as Command27 } from "commander";
4738
5152
 
4739
5153
  // src/commands/disable/_shared.ts
4740
- import process17 from "node:process";
4741
- import * as p21 from "@clack/prompts";
5154
+ import process19 from "node:process";
5155
+ import * as p23 from "@clack/prompts";
4742
5156
  async function runDisable(opts, flags, cmdArgs) {
4743
5157
  if (!flags.yes) {
4744
- const ok = await p21.confirm({
5158
+ const ok = await p23.confirm({
4745
5159
  message: opts.confirmMessage,
4746
5160
  initialValue: false
4747
5161
  });
4748
- if (p21.isCancel(ok) || !ok) {
4749
- p21.cancel("Operation cancelled.");
4750
- process17.exit(0);
5162
+ if (p23.isCancel(ok) || !ok) {
5163
+ p23.cancel("Operation cancelled.");
5164
+ process19.exit(0);
4751
5165
  }
4752
5166
  }
4753
5167
  await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
4754
5168
  }
4755
5169
 
4756
5170
  // 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(
5171
+ var auth2 = new Command27("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4758
5172
  (opts, cmd) => runCommand(
4759
5173
  () => runDisable(
4760
5174
  {
@@ -4780,8 +5194,8 @@ var auth2 = new Command26("auth").description("disable authentication").option("
4780
5194
  );
4781
5195
 
4782
5196
  // 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(
5197
+ import { Command as Command28 } from "commander";
5198
+ var api2 = new Command28("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4785
5199
  (opts, cmd) => runCommand(
4786
5200
  () => runDisable(
4787
5201
  {
@@ -4804,8 +5218,8 @@ var api2 = new Command27("api").description("disable the REST API").option("-y,
4804
5218
  );
4805
5219
 
4806
5220
  // 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(
5221
+ import { Command as Command29 } from "commander";
5222
+ 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
5223
  (opts, cmd) => runCommand(
4810
5224
  () => runDisable(
4811
5225
  {
@@ -4828,8 +5242,8 @@ var apiKeys2 = new Command28("api-keys").description("disable API key management
4828
5242
  );
4829
5243
 
4830
5244
  // 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(
5245
+ import { Command as Command30 } from "commander";
5246
+ var backend2 = new Command30("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4833
5247
  (opts, cmd) => runCommand(
4834
5248
  () => runDisable(
4835
5249
  {
@@ -4852,8 +5266,8 @@ var backend2 = new Command29("backend").description("disable the PocketBase back
4852
5266
  );
4853
5267
 
4854
5268
  // 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(
5269
+ import { Command as Command31 } from "commander";
5270
+ var contentNegotiation2 = new Command31("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4857
5271
  (opts, cmd) => runCommand(
4858
5272
  () => runDisable(
4859
5273
  {
@@ -4876,8 +5290,8 @@ var contentNegotiation2 = new Command30("content-negotiation").description("disa
4876
5290
  );
4877
5291
 
4878
5292
  // 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(
5293
+ import { Command as Command32 } from "commander";
5294
+ var i18n2 = new Command32("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4881
5295
  (opts, cmd) => runCommand(
4882
5296
  () => runDisable(
4883
5297
  {
@@ -4903,8 +5317,8 @@ var i18n2 = new Command31("i18n").description("disable internationalization").op
4903
5317
  );
4904
5318
 
4905
5319
  // 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(
5320
+ import { Command as Command33 } from "commander";
5321
+ var teams2 = new Command33("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4908
5322
  (opts, cmd) => runCommand(
4909
5323
  () => runDisable(
4910
5324
  {
@@ -4930,8 +5344,8 @@ var teams2 = new Command32("teams").description("disable teams").option("-y, --y
4930
5344
  );
4931
5345
 
4932
5346
  // 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(
5347
+ import { Command as Command34 } from "commander";
5348
+ var payments2 = new Command34("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4935
5349
  (opts, cmd) => runCommand(
4936
5350
  () => runDisable(
4937
5351
  {
@@ -4958,11 +5372,11 @@ var payments2 = new Command33("payments").description("disable payments").option
4958
5372
  );
4959
5373
 
4960
5374
  // src/commands/disable/s3.ts
4961
- import { Command as Command34 } from "commander";
4962
- import * as p22 from "@clack/prompts";
5375
+ import { Command as Command35 } from "commander";
5376
+ import * as p24 from "@clack/prompts";
4963
5377
  import pc10 from "picocolors";
4964
5378
  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),
5379
+ new Command35("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4966
5380
  "local"
4967
5381
  ).action(
4968
5382
  (raw) => runCommand(() => {
@@ -4971,7 +5385,7 @@ var s32 = addTargetOptions(
4971
5385
  return withBackupTarget(raw, "disable s3", async (ctx) => {
4972
5386
  const existing = await readS3(ctx.pb, filesystem);
4973
5387
  if (!existing.enabled) {
4974
- p22.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
5388
+ p24.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
4975
5389
  return;
4976
5390
  }
4977
5391
  await disableS3(ctx.pb, filesystem);
@@ -4991,8 +5405,8 @@ function label2(filesystem) {
4991
5405
  }
4992
5406
 
4993
5407
  // 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(
5408
+ import { Command as Command36 } from "commander";
5409
+ var smtp2 = new Command36("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4996
5410
  () => runCommand(async () => {
4997
5411
  const { workspaceRootDir } = await getWorkspace();
4998
5412
  await withPocketbase(workspaceRootDir, async (pb) => {
@@ -5009,30 +5423,30 @@ var smtp2 = new Command35("smtp").description("disable SMTP configuration").conf
5009
5423
  );
5010
5424
 
5011
5425
  // 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);
5426
+ 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
5427
 
5014
5428
  // src/commands/destroy.ts
5015
- import { Command as Command42 } from "commander";
5429
+ import { Command as Command43 } from "commander";
5016
5430
 
5017
5431
  // src/commands/destroy/form.ts
5018
- import { Command as Command37 } from "commander";
5432
+ import { Command as Command38 } from "commander";
5019
5433
 
5020
5434
  // src/commands/destroy/_shared.ts
5021
- import process18 from "node:process";
5022
- import * as p23 from "@clack/prompts";
5435
+ import process20 from "node:process";
5436
+ import * as p25 from "@clack/prompts";
5023
5437
  async function runDestroy(slug2, model, confirmMessage, report4, flags) {
5024
5438
  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);
5439
+ const ok = await p25.confirm({ message: confirmMessage, initialValue: false });
5440
+ if (p25.isCancel(ok) || !ok) {
5441
+ p25.cancel("Operation cancelled.");
5442
+ process20.exit(0);
5029
5443
  }
5030
5444
  }
5031
5445
  await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
5032
5446
  }
5033
5447
 
5034
5448
  // 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(
5449
+ 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
5450
  "--route <route>",
5037
5451
  "custom route the form was generated at (must match the --route used at generation)"
5038
5452
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -5056,8 +5470,8 @@ var form2 = new Command37("form").description("destroy a form generated by `vela
5056
5470
  );
5057
5471
 
5058
5472
  // 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(
5473
+ import { Command as Command39 } from "commander";
5474
+ 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
5475
  (model, opts) => runCommand(
5062
5476
  () => runDestroy(
5063
5477
  "destroy-schema",
@@ -5078,8 +5492,8 @@ var schema2 = new Command38("schema").description("destroy a zod schema generate
5078
5492
  );
5079
5493
 
5080
5494
  // 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(
5495
+ import { Command as Command40 } from "commander";
5496
+ 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
5497
  (model, opts) => runCommand(
5084
5498
  () => runDestroy(
5085
5499
  "destroy-resource",
@@ -5100,8 +5514,8 @@ var resource2 = new Command39("resource").description("destroy a resource genera
5100
5514
  );
5101
5515
 
5102
5516
  // 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(
5517
+ import { Command as Command41 } from "commander";
5518
+ 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
5519
  "--route <route>",
5106
5520
  "custom route the scaffold was generated at (must match the --route used at generation)"
5107
5521
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -5128,9 +5542,9 @@ var scaffold2 = new Command40("scaffold").description("destroy a scaffold genera
5128
5542
  );
5129
5543
 
5130
5544
  // 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";
5545
+ import process21 from "node:process";
5546
+ import { Command as Command42 } from "commander";
5547
+ import * as p28 from "@clack/prompts";
5134
5548
  import pc13 from "picocolors";
5135
5549
 
5136
5550
  // src/lib/destroy-guard.ts
@@ -5163,103 +5577,27 @@ Pass \`--confirm ${appName}\` as well \u2014 the app name, the same thing a term
5163
5577
  message: `Removing ${what} needs a confirmation, and there is no terminal to ask on.
5164
5578
 
5165
5579
  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
- });
5580
+ };
5581
+ }
5582
+ if (yes) return { kind: "proceed" };
5583
+ if (interactive) return { kind: "prompt", byName: false };
5584
+ return {
5585
+ kind: "refuse",
5586
+ message: `Removing ${what} needs a confirmation, and there is no terminal to ask on. Pass \`--yes\`.`
5587
+ };
5255
5588
  }
5256
- async function destroyEnvironment(apiKey, projectId, envTag) {
5257
- return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
5258
- method: "DELETE"
5259
- });
5589
+ function describe({ appName, envTag, purge }) {
5590
+ const target = isProd(envTag) ? "production" : `the ${envTag} environment`;
5591
+ return purge ? `${target} of ${appName} and its database` : `${target} of ${appName}`;
5260
5592
  }
5261
5593
 
5594
+ // src/lib/deploy-report.ts
5595
+ import * as p27 from "@clack/prompts";
5596
+ import pc12 from "picocolors";
5597
+
5262
5598
  // src/lib/server-identity.ts
5599
+ import * as p26 from "@clack/prompts";
5600
+ import pc11 from "picocolors";
5263
5601
  var IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
5264
5602
  async function ensureServerIdentity(session, apiKey) {
5265
5603
  const existing = await readServerIdentity(session);
@@ -5272,7 +5610,7 @@ async function ensureServerIdentity(session, apiKey) {
5272
5610
  if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
5273
5611
  await writeServerIdentity(session, registered);
5274
5612
  if (existing) {
5275
- p24.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5613
+ p26.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5276
5614
  }
5277
5615
  }
5278
5616
  await runServerScript(session, "origin.sh");
@@ -5312,7 +5650,7 @@ function createDeployReporter(workspaceRootDir) {
5312
5650
  const link2 = readProjectConfig(workspaceRootDir);
5313
5651
  const apiKey = link2 ? readApiKey() : null;
5314
5652
  if (link2 && !apiKey) {
5315
- p25.log.warn(
5653
+ p27.log.warn(
5316
5654
  `This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
5317
5655
  API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
5318
5656
  ${pc12.cyan("VELA_API_KEY")}.`
@@ -5362,7 +5700,7 @@ async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
5362
5700
  }
5363
5701
  }
5364
5702
  function warn(what, err) {
5365
- p25.log.warn(
5703
+ p27.log.warn(
5366
5704
  `velastack.dev could not ${what}.
5367
5705
  ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5368
5706
  );
@@ -5371,7 +5709,7 @@ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5371
5709
  // src/commands/destroy/deployment.ts
5372
5710
  var deployment = addLockWaitOption(
5373
5711
  addTargetOptions(
5374
- new Command41("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5712
+ new Command42("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5375
5713
  "production"
5376
5714
  )
5377
5715
  ).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").option(
@@ -5390,7 +5728,7 @@ var deployment = addLockWaitOption(
5390
5728
  purge: options.purge === true,
5391
5729
  yes: options.yes === true,
5392
5730
  confirm: options.confirm,
5393
- interactive: Boolean(process19.stdin.isTTY && process19.stdout.isTTY)
5731
+ interactive: Boolean(process21.stdin.isTTY && process21.stdout.isTTY)
5394
5732
  });
5395
5733
  if (decision.kind === "refuse") throw new Error(decision.message);
5396
5734
  if (decision.kind === "prompt") {
@@ -5405,13 +5743,13 @@ var deployment = addLockWaitOption(
5405
5743
  stream: true
5406
5744
  });
5407
5745
  if (result?.existed === false) {
5408
- p26.log.info(
5746
+ p28.log.info(
5409
5747
  `Nothing named ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} on ${ctx.server}; nothing to remove.`
5410
5748
  );
5411
5749
  return;
5412
5750
  }
5413
5751
  await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
5414
- p26.log.success(
5752
+ p28.log.success(
5415
5753
  `Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? result.trash ? `
5416
5754
 
5417
5755
  A snapshot of its data is at ${pc13.cyan(result.trash)} on the server for two weeks.` : "" : `
@@ -5429,35 +5767,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
5429
5767
  );
5430
5768
  async function confirm8(appName, targetName, byName) {
5431
5769
  if (byName) {
5432
- const answer = await p26.text({
5770
+ const answer = await p28.text({
5433
5771
  message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}. Type the app name to confirm`,
5434
5772
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
5435
5773
  });
5436
- if (p26.isCancel(answer)) {
5437
- p26.cancel("Operation cancelled.");
5438
- process19.exit(0);
5774
+ if (p28.isCancel(answer)) {
5775
+ p28.cancel("Operation cancelled.");
5776
+ process21.exit(0);
5439
5777
  }
5440
5778
  return;
5441
5779
  }
5442
- const ok = await p26.confirm({
5780
+ const ok = await p28.confirm({
5443
5781
  message: `Remove ${appName} (${targetName})?`,
5444
5782
  initialValue: false
5445
5783
  });
5446
- if (p26.isCancel(ok) || !ok) {
5447
- p26.cancel("Operation cancelled.");
5448
- process19.exit(0);
5784
+ if (p28.isCancel(ok) || !ok) {
5785
+ p28.cancel("Operation cancelled.");
5786
+ process21.exit(0);
5449
5787
  }
5450
5788
  }
5451
5789
 
5452
5790
  // 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);
5791
+ var destroy = new Command43("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5454
5792
 
5455
5793
  // src/commands/ui.ts
5456
- import { Command as Command48 } from "commander";
5794
+ import { Command as Command49 } from "commander";
5457
5795
 
5458
5796
  // src/commands/ui/add.ts
5459
- import { Command as Command43 } from "commander";
5460
- import * as p27 from "@clack/prompts";
5797
+ import { Command as Command44 } from "commander";
5798
+ import * as p29 from "@clack/prompts";
5461
5799
  import { installComponents } from "@velastack/patterns";
5462
5800
 
5463
5801
  // src/lib/ui-add.ts
@@ -5506,10 +5844,10 @@ function uiAddReport(requested, outcome) {
5506
5844
  }
5507
5845
 
5508
5846
  // 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(
5847
+ 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
5848
  (components, options) => runCommand(async () => {
5511
5849
  const { workspaceRootDir } = await getWorkspace();
5512
- const log45 = p27.taskLog({ title: "Adding UI components..." });
5850
+ const log45 = p29.taskLog({ title: "Adding UI components..." });
5513
5851
  let outcome;
5514
5852
  try {
5515
5853
  outcome = await installComponents({
@@ -5528,13 +5866,13 @@ var add = new Command43("add").description("add ui components (shadcn-svelte ite
5528
5866
  );
5529
5867
 
5530
5868
  // src/commands/ui/base.ts
5531
- import { Command as Command44 } from "commander";
5532
- import * as p28 from "@clack/prompts";
5869
+ import { Command as Command45 } from "commander";
5870
+ import * as p30 from "@clack/prompts";
5533
5871
  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(
5872
+ var base = new Command45("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5535
5873
  (color) => runCommand(async () => {
5536
5874
  const { workspaceRootDir } = await getWorkspace();
5537
- const log45 = p28.taskLog({ title: `Applying the ${color} palette...` });
5875
+ const log45 = p30.taskLog({ title: `Applying the ${color} palette...` });
5538
5876
  let outcome;
5539
5877
  try {
5540
5878
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
@@ -5556,8 +5894,8 @@ var base = new Command44("base").description("change the base (gray) palette").a
5556
5894
  );
5557
5895
 
5558
5896
  // src/commands/ui/list.ts
5559
- import { Command as Command45 } from "commander";
5560
- import * as p29 from "@clack/prompts";
5897
+ import { Command as Command46 } from "commander";
5898
+ import * as p31 from "@clack/prompts";
5561
5899
  import { listComponents } from "@velastack/patterns";
5562
5900
 
5563
5901
  // src/lib/ui-list.ts
@@ -5588,7 +5926,7 @@ function uiListReport(result) {
5588
5926
  }
5589
5927
 
5590
5928
  // 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(
5929
+ 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
5930
  (options) => runCommand(async () => {
5593
5931
  const { workspaceRootDir } = await getWorkspace();
5594
5932
  if (options.json) {
@@ -5596,7 +5934,7 @@ var list = new Command45("list").description("list installed ui components, vela
5596
5934
  console.log(JSON.stringify(result2, null, 2));
5597
5935
  return;
5598
5936
  }
5599
- const spinner7 = p29.spinner();
5937
+ const spinner7 = p31.spinner();
5600
5938
  spinner7.start("Reading the registry...");
5601
5939
  let result;
5602
5940
  try {
@@ -5608,15 +5946,15 @@ var list = new Command45("list").description("list installed ui components, vela
5608
5946
  spinner7.stop(`Read the ${result.style} registry`);
5609
5947
  reportResult(uiListReport(result));
5610
5948
  if (result.registryUnavailable) {
5611
- p29.log.warn(`${result.registryUnavailable}
5949
+ p31.log.warn(`${result.registryUnavailable}
5612
5950
  Registry components are not listed.`);
5613
5951
  }
5614
5952
  }, "Failed to list UI components.")
5615
5953
  );
5616
5954
 
5617
5955
  // src/commands/ui/style.ts
5618
- import { Command as Command46 } from "commander";
5619
- import * as p30 from "@clack/prompts";
5956
+ import { Command as Command47 } from "commander";
5957
+ import * as p32 from "@clack/prompts";
5620
5958
  import { switchStyle } from "@velastack/patterns";
5621
5959
 
5622
5960
  // src/lib/ui-style.ts
@@ -5642,10 +5980,10 @@ function uiStyleReport(result) {
5642
5980
  }
5643
5981
 
5644
5982
  // 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(
5983
+ 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
5984
  (name, options) => runCommand(async () => {
5647
5985
  const { workspaceRootDir } = await getWorkspace();
5648
- const spinner7 = p30.spinner();
5986
+ const spinner7 = p32.spinner();
5649
5987
  spinner7.start(`Reading the ${name} registry...`);
5650
5988
  let log45;
5651
5989
  let outcome;
@@ -5658,20 +5996,20 @@ var style = new Command46("style").description("switch the shadcn-svelte style,
5658
5996
  confirm: async (components) => {
5659
5997
  spinner7.stop(`Read the ${name} registry`);
5660
5998
  if (components.length > 0) {
5661
- p30.log.info(
5999
+ p32.log.info(
5662
6000
  `Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
5663
6001
  ${components.map((c) => `- ${c}`).join("\n")}`
5664
6002
  );
5665
6003
  } else {
5666
- p30.log.info(
6004
+ p32.log.info(
5667
6005
  `No installed component comes from the registry; only the config changes.`
5668
6006
  );
5669
6007
  }
5670
6008
  if (!options.yes) {
5671
- const ok = await p30.confirm({ message: `Switch to ${name}?`, initialValue: false });
5672
- if (p30.isCancel(ok) || !ok) return false;
6009
+ const ok = await p32.confirm({ message: `Switch to ${name}?`, initialValue: false });
6010
+ if (p32.isCancel(ok) || !ok) return false;
5673
6011
  }
5674
- log45 = p30.taskLog({ title: `Switching to the ${name} style...` });
6012
+ log45 = p32.taskLog({ title: `Switching to the ${name} style...` });
5675
6013
  return true;
5676
6014
  }
5677
6015
  });
@@ -5682,11 +6020,11 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5682
6020
  }
5683
6021
  spinner7.stop(`Read the ${name} registry`);
5684
6022
  if (outcome.status === "unchanged") {
5685
- p30.log.info(`Already using the ${name} style.`);
6023
+ p32.log.info(`Already using the ${name} style.`);
5686
6024
  return;
5687
6025
  }
5688
6026
  if (outcome.status === "cancelled") {
5689
- p30.cancel("Operation cancelled.");
6027
+ p32.cancel("Operation cancelled.");
5690
6028
  return;
5691
6029
  }
5692
6030
  log45?.success("Style switched");
@@ -5695,13 +6033,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5695
6033
  );
5696
6034
 
5697
6035
  // src/commands/ui/theme.ts
5698
- import { Command as Command47 } from "commander";
5699
- import * as p31 from "@clack/prompts";
6036
+ import { Command as Command48 } from "commander";
6037
+ import * as p33 from "@clack/prompts";
5700
6038
  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(
6039
+ 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
6040
  (accent) => runCommand(async () => {
5703
6041
  const { workspaceRootDir } = await getWorkspace();
5704
- const log45 = p31.taskLog({ title: `Applying the ${accent} accent...` });
6042
+ const log45 = p33.taskLog({ title: `Applying the ${accent} accent...` });
5705
6043
  let outcome;
5706
6044
  try {
5707
6045
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
@@ -5723,22 +6061,22 @@ var theme = new Command47("theme").description("change the accent color, keeping
5723
6061
  );
5724
6062
 
5725
6063
  // 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);
6064
+ var ui = new Command49("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5727
6065
 
5728
6066
  // src/commands/legal.ts
5729
- import { Command as Command51 } from "commander";
6067
+ import { Command as Command52 } from "commander";
5730
6068
 
5731
6069
  // src/commands/legal/terms.ts
5732
6070
  import fs26 from "node:fs";
5733
6071
  import path23 from "node:path";
5734
- import { Command as Command49 } from "commander";
5735
- import * as p33 from "@clack/prompts";
6072
+ import { Command as Command50 } from "commander";
6073
+ import * as p35 from "@clack/prompts";
5736
6074
 
5737
6075
  // src/commands/legal/shared.ts
5738
- import process20 from "node:process";
5739
- import * as p32 from "@clack/prompts";
6076
+ import process22 from "node:process";
6077
+ import * as p34 from "@clack/prompts";
5740
6078
  var sharedFields = {
5741
- websiteUrl: () => p32.text({
6079
+ websiteUrl: () => p34.text({
5742
6080
  message: "What is your website URL?",
5743
6081
  placeholder: "http://www.mysite.com",
5744
6082
  validate: (value) => {
@@ -5747,7 +6085,7 @@ var sharedFields = {
5747
6085
  }
5748
6086
  }
5749
6087
  }),
5750
- websiteName: () => p32.text({
6088
+ websiteName: () => p34.text({
5751
6089
  message: "What is your website name?",
5752
6090
  placeholder: "My Site",
5753
6091
  validate: (value) => {
@@ -5756,7 +6094,7 @@ var sharedFields = {
5756
6094
  }
5757
6095
  }
5758
6096
  }),
5759
- entityType: () => p32.select({
6097
+ entityType: () => p34.select({
5760
6098
  message: "Entity type",
5761
6099
  options: [
5762
6100
  {
@@ -5767,7 +6105,7 @@ var sharedFields = {
5767
6105
  { value: "individual", label: "I'm an Individual" }
5768
6106
  ]
5769
6107
  }),
5770
- businessName: ({ results }) => results?.entityType === "business" ? p32.text({
6108
+ businessName: ({ results }) => results?.entityType === "business" ? p34.text({
5771
6109
  message: "What is the name of the business?",
5772
6110
  placeholder: "My Company LLC",
5773
6111
  validate: (value) => {
@@ -5776,7 +6114,7 @@ var sharedFields = {
5776
6114
  }
5777
6115
  }
5778
6116
  }) : void 0,
5779
- businessAddress: ({ results }) => results?.entityType === "business" ? p32.text({
6117
+ businessAddress: ({ results }) => results?.entityType === "business" ? p34.text({
5780
6118
  message: "What is the address of the business?",
5781
6119
  placeholder: "1 Cupertino, CA 95014",
5782
6120
  validate: (value) => {
@@ -5785,7 +6123,7 @@ var sharedFields = {
5785
6123
  }
5786
6124
  }
5787
6125
  }) : void 0,
5788
- country: () => p32.text({
6126
+ country: () => p34.text({
5789
6127
  message: "Enter the country",
5790
6128
  validate: (value) => {
5791
6129
  if (!value) {
@@ -5793,7 +6131,7 @@ var sharedFields = {
5793
6131
  }
5794
6132
  }
5795
6133
  }),
5796
- state: () => p32.text({
6134
+ state: () => p34.text({
5797
6135
  message: "Enter the state",
5798
6136
  validate: (value) => {
5799
6137
  if (!value) {
@@ -5803,11 +6141,11 @@ var sharedFields = {
5803
6141
  })
5804
6142
  };
5805
6143
  var onCancel = () => {
5806
- p32.cancel("Operation cancelled.");
5807
- process20.exit(0);
6144
+ p34.cancel("Operation cancelled.");
6145
+ process22.exit(0);
5808
6146
  };
5809
6147
  async function contactMethods(type) {
5810
- const selection = await p32.multiselect({
6148
+ const selection = await p34.multiselect({
5811
6149
  message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
5812
6150
  options: [
5813
6151
  { value: "email", label: "By email" },
@@ -5816,11 +6154,11 @@ async function contactMethods(type) {
5816
6154
  { value: "mail", label: "By sending post mail" }
5817
6155
  ]
5818
6156
  });
5819
- if (p32.isCancel(selection)) onCancel();
6157
+ if (p34.isCancel(selection)) onCancel();
5820
6158
  const contact = selection;
5821
6159
  const details = {};
5822
6160
  if (contact.includes("email")) {
5823
- const email3 = await p32.text({
6161
+ const email3 = await p34.text({
5824
6162
  message: "What's the email?",
5825
6163
  placeholder: "office@mycompany.com",
5826
6164
  validate: (value) => {
@@ -5829,11 +6167,11 @@ async function contactMethods(type) {
5829
6167
  }
5830
6168
  }
5831
6169
  });
5832
- if (p32.isCancel(email3)) onCancel();
6170
+ if (p34.isCancel(email3)) onCancel();
5833
6171
  details.email = email3;
5834
6172
  }
5835
6173
  if (contact.includes("page")) {
5836
- const page = await p32.text({
6174
+ const page = await p34.text({
5837
6175
  message: "What's the link?",
5838
6176
  placeholder: "http://www.mycompany.com/contact",
5839
6177
  validate: (value) => {
@@ -5842,11 +6180,11 @@ async function contactMethods(type) {
5842
6180
  }
5843
6181
  }
5844
6182
  });
5845
- if (p32.isCancel(page)) onCancel();
6183
+ if (p34.isCancel(page)) onCancel();
5846
6184
  details.page = page;
5847
6185
  }
5848
6186
  if (contact.includes("phone")) {
5849
- const phone = await p32.text({
6187
+ const phone = await p34.text({
5850
6188
  message: "What's the phone number?",
5851
6189
  placeholder: "408.996.1010",
5852
6190
  validate: (value) => {
@@ -5855,11 +6193,11 @@ async function contactMethods(type) {
5855
6193
  }
5856
6194
  }
5857
6195
  });
5858
- if (p32.isCancel(phone)) onCancel();
6196
+ if (p34.isCancel(phone)) onCancel();
5859
6197
  details.phone = phone;
5860
6198
  }
5861
6199
  if (contact.includes("mail")) {
5862
- const address = await p32.text({
6200
+ const address = await p34.text({
5863
6201
  message: "What's the address?",
5864
6202
  placeholder: "767 Fifth Avenue New York, NY 10153, United States",
5865
6203
  validate: (value) => {
@@ -5868,7 +6206,7 @@ async function contactMethods(type) {
5868
6206
  }
5869
6207
  }
5870
6208
  });
5871
- if (p32.isCancel(address)) onCancel();
6209
+ if (p34.isCancel(address)) onCancel();
5872
6210
  details.address = address;
5873
6211
  }
5874
6212
  return { methods: contact, details };
@@ -6264,7 +6602,7 @@ var generateTermsHtml = (answers) => {
6264
6602
  };
6265
6603
  async function termsAction() {
6266
6604
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6267
- const core = await p33.group(
6605
+ const core = await p35.group(
6268
6606
  {
6269
6607
  websiteUrl: sharedFields.websiteUrl,
6270
6608
  websiteName: sharedFields.websiteName,
@@ -6276,25 +6614,25 @@ async function termsAction() {
6276
6614
  },
6277
6615
  { onCancel }
6278
6616
  );
6279
- const accounts = await p33.select({
6617
+ const accounts = await p35.select({
6280
6618
  message: "Can users create accounts?",
6281
6619
  options: [
6282
6620
  { value: "yes", label: "Yes, users can create accounts" },
6283
6621
  { value: "no", label: "No" }
6284
6622
  ]
6285
6623
  });
6286
- if (p33.isCancel(accounts)) onCancel();
6287
- const userContent = await p33.select({
6624
+ if (p35.isCancel(accounts)) onCancel();
6625
+ const userContent = await p35.select({
6288
6626
  message: "Can users create and/or upload content (ie. text, images)?",
6289
6627
  options: [
6290
6628
  { value: "yes", label: "Yes, users can create and/or upload content" },
6291
6629
  { value: "no", label: "No" }
6292
6630
  ]
6293
6631
  });
6294
- if (p33.isCancel(userContent)) onCancel();
6632
+ if (p35.isCancel(userContent)) onCancel();
6295
6633
  let infringementEmail;
6296
6634
  if (userContent === "yes") {
6297
- const email3 = await p33.text({
6635
+ const email3 = await p35.text({
6298
6636
  message: "What's the email address where you will receive infringements notices?",
6299
6637
  placeholder: "dmca@website.com",
6300
6638
  validate: (value) => {
@@ -6303,10 +6641,10 @@ async function termsAction() {
6303
6641
  }
6304
6642
  }
6305
6643
  });
6306
- if (p33.isCancel(email3)) onCancel();
6644
+ if (p35.isCancel(email3)) onCancel();
6307
6645
  infringementEmail = email3;
6308
6646
  }
6309
- const canBuyGoods = await p33.select({
6647
+ const canBuyGoods = await p35.select({
6310
6648
  message: "Can users buy goods (products, items)?",
6311
6649
  options: [
6312
6650
  {
@@ -6316,28 +6654,28 @@ async function termsAction() {
6316
6654
  { value: "no", label: "No" }
6317
6655
  ]
6318
6656
  });
6319
- if (p33.isCancel(canBuyGoods)) onCancel();
6320
- const subscriptions2 = await p33.select({
6657
+ if (p35.isCancel(canBuyGoods)) onCancel();
6658
+ const subscriptions2 = await p35.select({
6321
6659
  message: "Do you offer subscription plans?",
6322
6660
  options: [
6323
6661
  { value: "yes", label: "Yes, we offer subscription plans" },
6324
6662
  { value: "no", label: "No" }
6325
6663
  ]
6326
6664
  });
6327
- if (p33.isCancel(subscriptions2)) onCancel();
6665
+ if (p35.isCancel(subscriptions2)) onCancel();
6328
6666
  let freeTrial;
6329
6667
  if (subscriptions2 === "yes") {
6330
- const ft = await p33.select({
6668
+ const ft = await p35.select({
6331
6669
  message: "Do you offer a free trial?",
6332
6670
  options: [
6333
6671
  { value: "yes", label: "Yes" },
6334
6672
  { value: "no", label: "No" }
6335
6673
  ]
6336
6674
  });
6337
- if (p33.isCancel(ft)) onCancel();
6675
+ if (p35.isCancel(ft)) onCancel();
6338
6676
  freeTrial = ft;
6339
6677
  }
6340
- const exclusiveContent = await p33.select({
6678
+ const exclusiveContent = await p35.select({
6341
6679
  message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
6342
6680
  options: [
6343
6681
  {
@@ -6347,24 +6685,24 @@ async function termsAction() {
6347
6685
  { value: "no", label: "No" }
6348
6686
  ]
6349
6687
  });
6350
- if (p33.isCancel(exclusiveContent)) onCancel();
6351
- const feedbackReuse = await p33.select({
6688
+ if (p35.isCancel(exclusiveContent)) onCancel();
6689
+ const feedbackReuse = await p35.select({
6352
6690
  message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
6353
6691
  options: [
6354
6692
  { value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
6355
6693
  { value: "no", label: "No" }
6356
6694
  ]
6357
6695
  });
6358
- if (p33.isCancel(feedbackReuse)) onCancel();
6359
- const promotions = await p33.select({
6696
+ if (p35.isCancel(feedbackReuse)) onCancel();
6697
+ const promotions = await p35.select({
6360
6698
  message: "Do you plan to offer promotions, contests, sweepstakes?",
6361
6699
  options: [
6362
6700
  { value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
6363
6701
  { value: "no", label: "No" }
6364
6702
  ]
6365
6703
  });
6366
- if (p33.isCancel(promotions)) onCancel();
6367
- const mobileAppRaw = await p33.multiselect({
6704
+ if (p35.isCancel(promotions)) onCancel();
6705
+ const mobileAppRaw = await p35.multiselect({
6368
6706
  message: "Is the Service distributed through any mobile app stores? Check all that apply",
6369
6707
  options: [
6370
6708
  { value: "apple", label: "Apple App Store" },
@@ -6372,7 +6710,7 @@ async function termsAction() {
6372
6710
  ],
6373
6711
  required: false
6374
6712
  });
6375
- if (p33.isCancel(mobileAppRaw)) onCancel();
6713
+ if (p35.isCancel(mobileAppRaw)) onCancel();
6376
6714
  const mobileApp = mobileAppRaw ?? [];
6377
6715
  const contact = await contactMethods("terms");
6378
6716
  const html = generateTermsHtml({
@@ -6415,13 +6753,13 @@ async function termsAction() {
6415
6753
  ]
6416
6754
  });
6417
6755
  }
6418
- var terms = new Command49("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6756
+ var terms = new Command50("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6419
6757
 
6420
6758
  // src/commands/legal/privacy.ts
6421
6759
  import fs27 from "node:fs";
6422
6760
  import path24 from "node:path";
6423
- import { Command as Command50 } from "commander";
6424
- import * as p34 from "@clack/prompts";
6761
+ import { Command as Command51 } from "commander";
6762
+ import * as p36 from "@clack/prompts";
6425
6763
  var mapLabels = {
6426
6764
  personalInfo: {
6427
6765
  email: "Email address",
@@ -6839,12 +7177,12 @@ var generatePrivacyHtml = (answers) => {
6839
7177
  return `<section data-role="content">${sections.join("")}</section>`;
6840
7178
  };
6841
7179
  async function promptWithCustom(message, options, customMessage) {
6842
- const selection = await p34.multiselect({ message, options });
6843
- if (p34.isCancel(selection)) onCancel();
7180
+ const selection = await p36.multiselect({ message, options });
7181
+ if (p36.isCancel(selection)) onCancel();
6844
7182
  const values = selection;
6845
7183
  if (values.includes("custom")) {
6846
- const custom = await p34.text({ message: customMessage });
6847
- if (p34.isCancel(custom)) onCancel();
7184
+ const custom = await p36.text({ message: customMessage });
7185
+ if (p36.isCancel(custom)) onCancel();
6848
7186
  const idx = values.indexOf("custom");
6849
7187
  if (idx !== -1) values.splice(idx, 1);
6850
7188
  if (custom) values.push(String(custom));
@@ -6853,7 +7191,7 @@ async function promptWithCustom(message, options, customMessage) {
6853
7191
  }
6854
7192
  async function privacyAction() {
6855
7193
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6856
- const core = await p34.group(
7194
+ const core = await p36.group(
6857
7195
  {
6858
7196
  websiteUrl: sharedFields.websiteUrl,
6859
7197
  websiteName: sharedFields.websiteName,
@@ -6865,7 +7203,7 @@ async function privacyAction() {
6865
7203
  },
6866
7204
  { onCancel }
6867
7205
  );
6868
- const personalInfo = await p34.multiselect({
7206
+ const personalInfo = await p36.multiselect({
6869
7207
  message: "What kind of personal information do you collect from users? Check all that apply",
6870
7208
  options: [
6871
7209
  { value: "email", label: "Email address" },
@@ -6880,16 +7218,16 @@ async function privacyAction() {
6880
7218
  ],
6881
7219
  required: false
6882
7220
  });
6883
- if (p34.isCancel(personalInfo)) onCancel();
7221
+ if (p36.isCancel(personalInfo)) onCancel();
6884
7222
  const contact = await contactMethods("privacy");
6885
- const tracking = await p34.select({
7223
+ const tracking = await p36.select({
6886
7224
  message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
6887
7225
  options: [
6888
7226
  { value: "yes", label: "Yes, we use Google Analytics or other related tools" },
6889
7227
  { value: "no", label: "No" }
6890
7228
  ]
6891
7229
  });
6892
- if (p34.isCancel(tracking)) onCancel();
7230
+ if (p36.isCancel(tracking)) onCancel();
6893
7231
  let trackingTools;
6894
7232
  if (tracking === "yes") {
6895
7233
  trackingTools = await promptWithCustom(
@@ -6908,7 +7246,7 @@ async function privacyAction() {
6908
7246
  "Enter your custom tracking/analytics tool name"
6909
7247
  );
6910
7248
  }
6911
- const sendEmails = await p34.select({
7249
+ const sendEmails = await p36.select({
6912
7250
  message: "Do you send emails to users?",
6913
7251
  options: [
6914
7252
  {
@@ -6918,7 +7256,7 @@ async function privacyAction() {
6918
7256
  { value: "no", label: "No" }
6919
7257
  ]
6920
7258
  });
6921
- if (p34.isCancel(sendEmails)) onCancel();
7259
+ if (p36.isCancel(sendEmails)) onCancel();
6922
7260
  let emailPlatforms;
6923
7261
  if (sendEmails === "yes") {
6924
7262
  emailPlatforms = await promptWithCustom(
@@ -6933,14 +7271,14 @@ async function privacyAction() {
6933
7271
  "Enter your custom email platform"
6934
7272
  );
6935
7273
  }
6936
- const showAds = await p34.select({
7274
+ const showAds = await p36.select({
6937
7275
  message: "Do you show ads?",
6938
7276
  options: [
6939
7277
  { value: "yes", label: "Yes, we show ads" },
6940
7278
  { value: "no", label: "No" }
6941
7279
  ]
6942
7280
  });
6943
- if (p34.isCancel(showAds)) onCancel();
7281
+ if (p36.isCancel(showAds)) onCancel();
6944
7282
  let adsPlatforms;
6945
7283
  if (showAds === "yes") {
6946
7284
  adsPlatforms = await promptWithCustom(
@@ -6963,7 +7301,7 @@ async function privacyAction() {
6963
7301
  "Enter your custom ads platform"
6964
7302
  );
6965
7303
  }
6966
- const canPay = await p34.select({
7304
+ const canPay = await p36.select({
6967
7305
  message: "Can users pay for products or services?",
6968
7306
  options: [
6969
7307
  { value: "yes", label: "Yes, users can pay for our products/services" },
@@ -6973,7 +7311,7 @@ async function privacyAction() {
6973
7311
  }
6974
7312
  ]
6975
7313
  });
6976
- if (p34.isCancel(canPay)) onCancel();
7314
+ if (p36.isCancel(canPay)) onCancel();
6977
7315
  let paymentProcessors;
6978
7316
  if (canPay === "yes") {
6979
7317
  paymentProcessors = await promptWithCustom(
@@ -7004,14 +7342,14 @@ async function privacyAction() {
7004
7342
  "Enter your custom payment processor/method"
7005
7343
  );
7006
7344
  }
7007
- const remarketing = await p34.select({
7345
+ const remarketing = await p36.select({
7008
7346
  message: "Do you use remarketing services for marketing & advertising purposes?",
7009
7347
  options: [
7010
7348
  { value: "yes", label: "Yes, we use remarketing services to advertise our business" },
7011
7349
  { value: "no", label: "No" }
7012
7350
  ]
7013
7351
  });
7014
- if (p34.isCancel(remarketing)) onCancel();
7352
+ if (p36.isCancel(remarketing)) onCancel();
7015
7353
  let remarketingPlatforms;
7016
7354
  if (remarketing === "yes") {
7017
7355
  remarketingPlatforms = await promptWithCustom(
@@ -7030,7 +7368,7 @@ async function privacyAction() {
7030
7368
  "Enter your custom remarketing platform"
7031
7369
  );
7032
7370
  }
7033
- const providersRaw = await p34.multiselect({
7371
+ const providersRaw = await p36.multiselect({
7034
7372
  message: "Select if you use any of the following providers",
7035
7373
  options: [
7036
7374
  { value: "recaptcha", label: "Invisible reCAPTCHA" },
@@ -7041,16 +7379,16 @@ async function privacyAction() {
7041
7379
  ],
7042
7380
  required: false
7043
7381
  });
7044
- if (p34.isCancel(providersRaw)) onCancel();
7382
+ if (p36.isCancel(providersRaw)) onCancel();
7045
7383
  const providers = providersRaw;
7046
7384
  if (providers.includes("custom")) {
7047
- const custom = await p34.text({ message: "Enter your custom provider" });
7048
- if (p34.isCancel(custom)) onCancel();
7385
+ const custom = await p36.text({ message: "Enter your custom provider" });
7386
+ if (p36.isCancel(custom)) onCancel();
7049
7387
  const idx = providers.indexOf("custom");
7050
7388
  if (idx !== -1) providers.splice(idx, 1);
7051
7389
  if (custom) providers.push(String(custom));
7052
7390
  }
7053
- const usStates = await p34.select({
7391
+ const usStates = await p36.select({
7054
7392
  message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
7055
7393
  options: [
7056
7394
  {
@@ -7061,55 +7399,55 @@ async function privacyAction() {
7061
7399
  ],
7062
7400
  initialValue: "yes"
7063
7401
  });
7064
- if (p34.isCancel(usStates)) onCancel();
7065
- const gdpr = await p34.select({
7402
+ if (p36.isCancel(usStates)) onCancel();
7403
+ const gdpr = await p36.select({
7066
7404
  message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
7067
7405
  options: [
7068
7406
  { value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
7069
7407
  { value: "no", label: "No" }
7070
7408
  ]
7071
7409
  });
7072
- if (p34.isCancel(gdpr)) onCancel();
7410
+ if (p36.isCancel(gdpr)) onCancel();
7073
7411
  let facebookFanPage = "no";
7074
7412
  const facebookDetails = { name: "", url: "" };
7075
7413
  if (gdpr === "yes") {
7076
- const fan = await p34.select({
7414
+ const fan = await p36.select({
7077
7415
  message: "Do you have a Facebook Fan Page?",
7078
7416
  options: [
7079
7417
  { value: "yes", label: "Yes, we have a Facebook Fan Page" },
7080
7418
  { value: "no", label: "No" }
7081
7419
  ]
7082
7420
  });
7083
- if (p34.isCancel(fan)) onCancel();
7421
+ if (p36.isCancel(fan)) onCancel();
7084
7422
  facebookFanPage = fan;
7085
7423
  if (facebookFanPage === "yes") {
7086
- const name = await p34.text({
7424
+ const name = await p36.text({
7087
7425
  message: "What is the name of the Facebook Fan Page?",
7088
7426
  placeholder: "My Facebook Page"
7089
7427
  });
7090
- if (p34.isCancel(name)) onCancel();
7428
+ if (p36.isCancel(name)) onCancel();
7091
7429
  facebookDetails.name = name;
7092
- const url = await p34.text({
7430
+ const url = await p36.text({
7093
7431
  message: "What is the URL of the Facebook Fan Page?",
7094
7432
  placeholder: "https://facebook.com/my-facebook-page"
7095
7433
  });
7096
- if (p34.isCancel(url)) onCancel();
7434
+ if (p36.isCancel(url)) onCancel();
7097
7435
  facebookDetails.url = url;
7098
7436
  }
7099
7437
  }
7100
- const kids = await p34.select({
7438
+ const kids = await p36.select({
7101
7439
  message: "Do you collect information from kids under the age of 13?",
7102
7440
  options: [
7103
7441
  { value: "yes", label: "Yes. We collect information from children under the age of 13" },
7104
7442
  { value: "no", label: "No" }
7105
7443
  ]
7106
7444
  });
7107
- if (p34.isCancel(kids)) onCancel();
7108
- const retention = await p34.text({
7445
+ if (p36.isCancel(kids)) onCancel();
7446
+ const retention = await p36.text({
7109
7447
  message: "How long do you retain personal information? (leave blank for default wording)",
7110
7448
  placeholder: "e.g. 12 months after account closure"
7111
7449
  });
7112
- if (p34.isCancel(retention)) onCancel();
7450
+ if (p36.isCancel(retention)) onCancel();
7113
7451
  const html = generatePrivacyHtml({
7114
7452
  core,
7115
7453
  personalInfo: personalInfo ?? [],
@@ -7164,16 +7502,16 @@ async function privacyAction() {
7164
7502
  ]
7165
7503
  });
7166
7504
  }
7167
- var privacy = new Command50("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7505
+ var privacy = new Command51("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7168
7506
 
7169
7507
  // src/commands/legal.ts
7170
- var legal = new Command51("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7508
+ var legal = new Command52("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7171
7509
 
7172
7510
  // src/commands/fixtures.ts
7173
- import { Command as Command57 } from "commander";
7511
+ import { Command as Command58 } from "commander";
7174
7512
 
7175
7513
  // src/commands/fixtures/load.ts
7176
- import { Command as Command52 } from "commander";
7514
+ import { Command as Command53 } from "commander";
7177
7515
 
7178
7516
  // src/lib/data.ts
7179
7517
  import fs28 from "node:fs";
@@ -7363,7 +7701,7 @@ async function hasLoadedFixtures(pb) {
7363
7701
  }
7364
7702
 
7365
7703
  // src/commands/fixtures/load.ts
7366
- var load = new Command52("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7704
+ var load = new Command53("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7367
7705
  () => runCommand(async () => {
7368
7706
  const { workspaceRootDir } = await getWorkspace();
7369
7707
  let loaded = [];
@@ -7389,8 +7727,8 @@ var load = new Command52("load").description("load fixtures into the database").
7389
7727
  );
7390
7728
 
7391
7729
  // 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(
7730
+ import { Command as Command54 } from "commander";
7731
+ var clear = new Command54("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7394
7732
  () => runCommand(async () => {
7395
7733
  const { workspaceRootDir } = await getWorkspace();
7396
7734
  let cleared = [];
@@ -7419,8 +7757,8 @@ var clear = new Command53("clear").description("clear loaded fixtures").configur
7419
7757
  );
7420
7758
 
7421
7759
  // 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(
7760
+ import { Command as Command55 } from "commander";
7761
+ var reset = new Command55("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7424
7762
  () => runCommand(async () => {
7425
7763
  const { workspaceRootDir } = await getWorkspace();
7426
7764
  let cleared = [];
@@ -7452,8 +7790,8 @@ var reset = new Command54("reset").description("clear and reload fixtures").conf
7452
7790
  // src/commands/fixtures/generate.ts
7453
7791
  import fs29 from "node:fs";
7454
7792
  import path26 from "node:path";
7455
- import { Command as Command55, InvalidArgumentError } from "commander";
7456
- import * as p35 from "@clack/prompts";
7793
+ import { Command as Command56, InvalidArgumentError } from "commander";
7794
+ import * as p37 from "@clack/prompts";
7457
7795
  import { annotate } from "annotate-json-schema";
7458
7796
  import { createGenerator } from "json-schema-faker";
7459
7797
  import { faker } from "@faker-js/faker";
@@ -7563,7 +7901,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
7563
7901
  }
7564
7902
  return { writtenFiles, warnings };
7565
7903
  }
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(
7904
+ 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
7905
  (opts) => runCommand(async () => {
7568
7906
  const { workspaceRootDir } = await getWorkspace();
7569
7907
  const existing = getFixtureFiles(workspaceRootDir);
@@ -7592,7 +7930,7 @@ var generate2 = new Command55("generate").description("generate fixture data").o
7592
7930
  seed: opts.seed
7593
7931
  });
7594
7932
  });
7595
- for (const warning of result.warnings) p35.log.warn(warning);
7933
+ for (const warning of result.warnings) p37.log.warn(warning);
7596
7934
  if (result.writtenFiles.length === 0) {
7597
7935
  reportResult({
7598
7936
  summary: "No eligible collections found to generate fixtures for.",
@@ -7616,8 +7954,8 @@ var generate2 = new Command55("generate").description("generate fixture data").o
7616
7954
  );
7617
7955
 
7618
7956
  // src/commands/fixtures/regen.ts
7619
- import { Command as Command56, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7620
- import * as p36 from "@clack/prompts";
7957
+ import { Command as Command57, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7958
+ import * as p38 from "@clack/prompts";
7621
7959
  function parseCount2(value) {
7622
7960
  const n = parseInt(value, 10);
7623
7961
  if (!Number.isFinite(n) || n <= 0 || n > 999) {
@@ -7632,7 +7970,7 @@ function parseSeed2(value) {
7632
7970
  }
7633
7971
  return n;
7634
7972
  }
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(
7973
+ 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
7974
  (opts) => runCommand(async () => {
7637
7975
  const { workspaceRootDir } = await getWorkspace();
7638
7976
  let cleared = [];
@@ -7646,7 +7984,7 @@ var regen = new Command56("regen").description("clear the database, regenerate f
7646
7984
  });
7647
7985
  loaded = await loadFixtures(pb, workspaceRootDir);
7648
7986
  });
7649
- for (const warning of result.warnings) p36.log.warn(warning);
7987
+ for (const warning of result.warnings) p38.log.warn(warning);
7650
7988
  reportResult({
7651
7989
  summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
7652
7990
  filesCreated: result.writtenFiles,
@@ -7661,14 +7999,14 @@ var regen = new Command56("regen").description("clear the database, regenerate f
7661
7999
  );
7662
8000
 
7663
8001
  // 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);
8002
+ var fixtures = new Command58("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7665
8003
 
7666
8004
  // src/commands/seeds.ts
7667
- import { Command as Command61 } from "commander";
8005
+ import { Command as Command62 } from "commander";
7668
8006
 
7669
8007
  // 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(
8008
+ import { Command as Command59 } from "commander";
8009
+ 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
8010
  (opts) => runCommand(async () => {
7673
8011
  const { workspaceRootDir } = await getWorkspace();
7674
8012
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7707,7 +8045,7 @@ var load2 = new Command58("load").description("load seeds into the database").op
7707
8045
  // src/commands/seeds/save.ts
7708
8046
  import fs30 from "node:fs";
7709
8047
  import path27 from "node:path";
7710
- import { Command as Command59 } from "commander";
8048
+ import { Command as Command60 } from "commander";
7711
8049
  var padZeros2 = (num, length) => num.toString().padStart(length, "0");
7712
8050
  function filterSystemFields(record, systemFieldNames) {
7713
8051
  const out = {};
@@ -7718,7 +8056,7 @@ function filterSystemFields(record, systemFieldNames) {
7718
8056
  }
7719
8057
  return out;
7720
8058
  }
7721
- var save = new Command59("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
8059
+ var save = new Command60("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7722
8060
  (opts) => runCommand(async () => {
7723
8061
  const { workspaceRootDir } = await getWorkspace();
7724
8062
  const seedsPath = dataDir(workspaceRootDir, "seeds");
@@ -7790,8 +8128,8 @@ var save = new Command59("save").description("save the current data as seeds").o
7790
8128
  );
7791
8129
 
7792
8130
  // 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(
8131
+ import { Command as Command61 } from "commander";
8132
+ var clear2 = new Command61("clear").description("clear seeded records").configureHelp(helpConfig).action(
7795
8133
  () => runCommand(async () => {
7796
8134
  const { workspaceRootDir } = await getWorkspace();
7797
8135
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7822,91 +8160,18 @@ var clear2 = new Command60("clear").description("clear seeded records").configur
7822
8160
  );
7823
8161
 
7824
8162
  // src/commands/seeds.ts
7825
- var seeds = new Command61("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
8163
+ var seeds = new Command62("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7826
8164
 
7827
8165
  // src/commands/signup.ts
7828
8166
  import { Command as Command63 } from "commander";
7829
- import * as p38 from "@clack/prompts";
8167
+ import * as p39 from "@clack/prompts";
7830
8168
  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
8169
  var signup = new Command63("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7905
8170
  () => 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" })
8171
+ const { email: email3, password: password11, passwordConfirm } = await p39.group({
8172
+ email: () => p39.text({ message: "Email" }),
8173
+ password: () => p39.password({ message: "Password" }),
8174
+ passwordConfirm: () => p39.password({ message: "Confirm password" })
7910
8175
  });
7911
8176
  if (password11 !== passwordConfirm) {
7912
8177
  throw new Error("Passwords do not match.");
@@ -7930,33 +8195,33 @@ var signup = new Command63("signup").description("signup to velastack.dev").conf
7930
8195
  }
7931
8196
  const apiKey = await issueApiKey(fetchCookie);
7932
8197
  writeConfig({ apiKey });
7933
- p38.log.success("Signed up to velastack.dev");
7934
- p38.log.info("Check your email for a confirmation link.");
8198
+ p39.log.success("Signed up to velastack.dev");
8199
+ p39.log.info("Check your email for a confirmation link.");
7935
8200
  }, "Failed to signup.")
7936
8201
  );
7937
8202
 
7938
8203
  // src/commands/logout.ts
7939
8204
  import { Command as Command64 } from "commander";
7940
- import * as p39 from "@clack/prompts";
8205
+ import * as p40 from "@clack/prompts";
7941
8206
  var logout = new Command64("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7942
8207
  () => runCommand(() => {
7943
8208
  if (!readConfig()) {
7944
- p39.log.info("Not logged in");
8209
+ p40.log.info("Not logged in");
7945
8210
  return;
7946
8211
  }
7947
8212
  clearConfig();
7948
- p39.log.success("Logged out of velastack.dev");
8213
+ p40.log.success("Logged out of velastack.dev");
7949
8214
  })
7950
8215
  );
7951
8216
 
7952
8217
  // src/commands/whoami.ts
7953
8218
  import { Command as Command65 } from "commander";
7954
- import * as p40 from "@clack/prompts";
8219
+ import * as p41 from "@clack/prompts";
7955
8220
  var whoami = new Command65("whoami").description("show the current user").configureHelp(helpConfig).action(
7956
8221
  () => runCommand(async () => {
7957
8222
  const apiKey = readConfig()?.apiKey;
7958
8223
  if (!apiKey) {
7959
- p40.log.info("Not logged in. Run `vela login` to login.");
8224
+ p41.log.info("Not logged in. Run `vela login` to login.");
7960
8225
  return;
7961
8226
  }
7962
8227
  const res = await fetch(`${API_URL}/api/collections/users/records`, {
@@ -7964,7 +8229,7 @@ var whoami = new Command65("whoami").description("show the current user").config
7964
8229
  });
7965
8230
  const data = await res.json();
7966
8231
  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}`);
8232
+ p41.log.success(`Logged in as ${data.items[0].email}`);
7968
8233
  })
7969
8234
  );
7970
8235
 
@@ -7976,10 +8241,10 @@ import { Command as Command66 } from "commander";
7976
8241
 
7977
8242
  // src/lib/migrate.ts
7978
8243
  import path28 from "node:path";
7979
- import process21 from "node:process";
8244
+ import process23 from "node:process";
7980
8245
  import { x as x2 } from "tinyexec";
7981
8246
  async function runPocketbaseMigrate(args) {
7982
- const cwd = process21.cwd();
8247
+ const cwd = process23.cwd();
7983
8248
  const { getBinaryPath } = await import("pocketbase-server");
7984
8249
  const binaryPath = getBinaryPath();
7985
8250
  await x2(
@@ -8038,11 +8303,11 @@ var down = new Command67("down").alias("rollback").description("revert the last
8038
8303
  // src/commands/migrate/create.ts
8039
8304
  import fs31 from "node:fs";
8040
8305
  import path29 from "node:path";
8041
- import process22 from "node:process";
8306
+ import process24 from "node:process";
8042
8307
  import { Command as Command68 } from "commander";
8043
8308
  var create2 = new Command68("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
8044
8309
  (name) => runCommand(async () => {
8045
- const cwd = process22.cwd();
8310
+ const cwd = process24.cwd();
8046
8311
  const before = listMigrationFiles(cwd);
8047
8312
  await runPocketbaseMigrate(["create", name]);
8048
8313
  const after = listMigrationFiles(cwd);
@@ -8066,11 +8331,11 @@ function listMigrationFiles(cwd) {
8066
8331
  // src/commands/migrate/collections.ts
8067
8332
  import fs32 from "node:fs";
8068
8333
  import path30 from "node:path";
8069
- import process23 from "node:process";
8334
+ import process25 from "node:process";
8070
8335
  import { Command as Command69 } from "commander";
8071
8336
  var collections = new Command69("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
8072
8337
  () => runCommand(async () => {
8073
- const cwd = process23.cwd();
8338
+ const cwd = process25.cwd();
8074
8339
  const before = listMigrationFiles2(cwd);
8075
8340
  await runPocketbaseMigrate(["collections"]);
8076
8341
  const after = listMigrationFiles2(cwd);
@@ -8116,7 +8381,7 @@ var migrate = new Command71("migrate").description("manage database migrations")
8116
8381
  // src/commands/dev.ts
8117
8382
  import fs33 from "node:fs";
8118
8383
  import path32 from "node:path";
8119
- import process25 from "node:process";
8384
+ import process27 from "node:process";
8120
8385
  import { performance } from "node:perf_hooks";
8121
8386
  import { Command as Command72, InvalidArgumentError as InvalidArgumentError4 } from "commander";
8122
8387
  import pc15 from "picocolors";
@@ -8124,7 +8389,7 @@ import PocketBase4 from "pocketbase";
8124
8389
 
8125
8390
  // src/lib/vite.ts
8126
8391
  import path31 from "node:path";
8127
- import process24 from "node:process";
8392
+ import process26 from "node:process";
8128
8393
  import { createRequire as createRequire2 } from "node:module";
8129
8394
  import { pathToFileURL as pathToFileURL2 } from "node:url";
8130
8395
  import pc14 from "picocolors";
@@ -8148,13 +8413,13 @@ function resolveProjectVite(cwd) {
8148
8413
  return null;
8149
8414
  }
8150
8415
  }
8151
- async function loadVite(cwd = process24.cwd()) {
8416
+ async function loadVite(cwd = process26.cwd()) {
8152
8417
  const entry = resolveProjectVite(cwd);
8153
8418
  const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
8154
8419
  const error = viteVersionError(vite.version);
8155
8420
  if (error) {
8156
8421
  console.error(`${pc14.redBright("\u2717")} ${error}`);
8157
- process24.exit(1);
8422
+ process26.exit(1);
8158
8423
  }
8159
8424
  return vite;
8160
8425
  }
@@ -8168,15 +8433,15 @@ function parsePort(value) {
8168
8433
  return port;
8169
8434
  }
8170
8435
  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);
8436
+ const cwd = process27.cwd();
8437
+ process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
8173
8438
  const startTime = performance.now();
8174
8439
  const { createServer, version } = await loadVite(cwd);
8175
8440
  const viteMetadataDir = path32.join(cwd, "node_modules", ".vite");
8176
8441
  const viteMetadataFile = path32.join(viteMetadataDir, "_pocketbase_metadata.json");
8177
8442
  let pbProc;
8178
8443
  const backend3 = hasBackend(cwd);
8179
- const needsStart = backend3 && !process25.env.POCKETBASE_URL;
8444
+ const needsStart = backend3 && !process27.env.POCKETBASE_URL;
8180
8445
  const cleanup = () => {
8181
8446
  if (pbProc?.pid) pbProc.kill();
8182
8447
  if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
@@ -8191,15 +8456,15 @@ var dev = new Command72("dev").description("start the development server").optio
8191
8456
  stdio: "pipe"
8192
8457
  });
8193
8458
  pbProc = started.proc;
8194
- process25.env.POCKETBASE_URL = started.url;
8195
- pbProc.stdout?.pipe(process25.stdout);
8196
- pbProc.stderr?.pipe(process25.stderr);
8459
+ process27.env.POCKETBASE_URL = started.url;
8460
+ pbProc.stdout?.pipe(process27.stdout);
8461
+ pbProc.stderr?.pipe(process27.stderr);
8197
8462
  pbProc.on("error", (err) => console.error("PocketBase error:", err));
8198
8463
  pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
8199
- process25.on("exit", cleanup);
8200
- process25.on("SIGINT", () => {
8464
+ process27.on("exit", cleanup);
8465
+ process27.on("SIGINT", () => {
8201
8466
  cleanup();
8202
- process25.exit(0);
8467
+ process27.exit(0);
8203
8468
  });
8204
8469
  }
8205
8470
  const serverOptions = {};
@@ -8221,21 +8486,21 @@ var dev = new Command72("dev").description("start the development server").optio
8221
8486
  await fs33.promises.writeFile(
8222
8487
  viteMetadataFile,
8223
8488
  JSON.stringify({
8224
- pocketbaseUrl: process25.env.POCKETBASE_URL,
8489
+ pocketbaseUrl: process27.env.POCKETBASE_URL,
8225
8490
  vitePort,
8226
8491
  viteHost
8227
8492
  })
8228
8493
  );
8229
- const pb = new PocketBase4(process25.env.POCKETBASE_URL);
8494
+ const pb = new PocketBase4(process27.env.POCKETBASE_URL);
8230
8495
  await pb.collection("_superusers").authWithPassword(
8231
- process25.env.POCKETBASE_SUPERUSER_EMAIL,
8232
- process25.env.POCKETBASE_SUPERUSER_PASSWORD
8496
+ process27.env.POCKETBASE_SUPERUSER_EMAIL,
8497
+ process27.env.POCKETBASE_SUPERUSER_PASSWORD
8233
8498
  );
8234
8499
  await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
8235
8500
  await startWatchingTypes(cwd, pb);
8236
8501
  });
8237
8502
  await server.listen();
8238
- const hasExistingLogs = process25.stdout.bytesWritten > 0 || process25.stderr.bytesWritten > 0;
8503
+ const hasExistingLogs = process27.stdout.bytesWritten > 0 || process27.stderr.bytesWritten > 0;
8239
8504
  const startupDurationString = pc15.dim(
8240
8505
  `ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
8241
8506
  );
@@ -8275,9 +8540,9 @@ async function startWatchingTypes(cwd, pb) {
8275
8540
  // src/commands/build.ts
8276
8541
  import fs34 from "node:fs";
8277
8542
  import path33 from "node:path";
8278
- import process27 from "node:process";
8543
+ import process29 from "node:process";
8279
8544
  import { Command as Command73 } from "commander";
8280
- import * as p41 from "@clack/prompts";
8545
+ import * as p42 from "@clack/prompts";
8281
8546
  import pc16 from "picocolors";
8282
8547
  import { x as x3 } from "tinyexec";
8283
8548
  import { detect as detect5 } from "package-manager-detector";
@@ -8290,10 +8555,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
8290
8555
  }
8291
8556
 
8292
8557
  // src/lib/origin.ts
8293
- import process26 from "node:process";
8558
+ import process28 from "node:process";
8294
8559
  function resolveOrigin(workspaceRootDir, envTag, config = {}) {
8295
8560
  return normalizeOrigin(
8296
- process26.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8561
+ process28.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8297
8562
  );
8298
8563
  }
8299
8564
  function normalizeOrigin(value) {
@@ -8314,12 +8579,12 @@ function splitHosts(value) {
8314
8579
  // src/commands/build.ts
8315
8580
  var PRERENDERED_DIR = path33.join(".svelte-kit", "output", "prerendered");
8316
8581
  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();
8582
+ const cwd = process29.cwd();
8318
8583
  applyBuildEnv(cwd);
8319
8584
  const origin = await originForBuild(cwd, options.target);
8320
- if (origin) process27.env.VELA_ORIGIN = origin;
8585
+ if (origin) process29.env.VELA_ORIGIN = origin;
8321
8586
  let pbProc;
8322
- const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
8587
+ const needsStart = hasBackend(cwd) && !process29.env.POCKETBASE_URL;
8323
8588
  const cleanup = () => {
8324
8589
  if (pbProc?.pid) pbProc.kill();
8325
8590
  };
@@ -8333,11 +8598,11 @@ var build = new Command73("build").description("build the app").configureHelp(he
8333
8598
  dev: true
8334
8599
  });
8335
8600
  pbProc = started.proc;
8336
- process27.env.POCKETBASE_URL = started.url;
8337
- process27.on("exit", cleanup);
8338
- process27.on("SIGINT", () => {
8601
+ process29.env.POCKETBASE_URL = started.url;
8602
+ process29.on("exit", cleanup);
8603
+ process29.on("SIGINT", () => {
8339
8604
  cleanup();
8340
- process27.exit(0);
8605
+ process29.exit(0);
8341
8606
  });
8342
8607
  }
8343
8608
  try {
@@ -8370,7 +8635,7 @@ async function originForBuild(cwd, target) {
8370
8635
  function warnIfPrerendered(cwd) {
8371
8636
  const dir = path33.join(cwd, PRERENDERED_DIR);
8372
8637
  if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
8373
- p41.log.warn(
8638
+ p42.log.warn(
8374
8639
  `Prerendered pages were built with no domain configured, so their canonical
8375
8640
  links point at SvelteKit's placeholder host rather than at this site.
8376
8641
 
@@ -8380,16 +8645,16 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
8380
8645
 
8381
8646
  // src/commands/preview.ts
8382
8647
  import path34 from "node:path";
8383
- import process28 from "node:process";
8648
+ import process30 from "node:process";
8384
8649
  import { Command as Command74 } from "commander";
8385
8650
  import { x as x4 } from "tinyexec";
8386
8651
  import { detect as detect6 } from "package-manager-detector";
8387
8652
  import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
8388
8653
  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);
8654
+ const cwd = process30.cwd();
8655
+ process30.env.VELA_DATA_DIR ??= localDataDir(cwd);
8391
8656
  let pbProc;
8392
- const needsStart = hasBackend(cwd) && !process28.env.POCKETBASE_URL;
8657
+ const needsStart = hasBackend(cwd) && !process30.env.POCKETBASE_URL;
8393
8658
  const cleanup = () => {
8394
8659
  if (pbProc?.pid) pbProc.kill();
8395
8660
  };
@@ -8402,11 +8667,11 @@ var preview = new Command74("preview").description("preview the built app").conf
8402
8667
  dev: true
8403
8668
  });
8404
8669
  pbProc = started.proc;
8405
- process28.env.POCKETBASE_URL = started.url;
8406
- process28.on("exit", cleanup);
8407
- process28.on("SIGINT", () => {
8670
+ process30.env.POCKETBASE_URL = started.url;
8671
+ process30.on("exit", cleanup);
8672
+ process30.on("SIGINT", () => {
8408
8673
  cleanup();
8409
- process28.exit(0);
8674
+ process30.exit(0);
8410
8675
  });
8411
8676
  }
8412
8677
  try {
@@ -8440,7 +8705,7 @@ var sync = new Command75("sync").description("sync types from the database").con
8440
8705
 
8441
8706
  // src/commands/provision.ts
8442
8707
  import { Command as Command76 } from "commander";
8443
- import * as p42 from "@clack/prompts";
8708
+ import * as p43 from "@clack/prompts";
8444
8709
  import pc17 from "picocolors";
8445
8710
  import * as v7 from "valibot";
8446
8711
  var OptionsSchema2 = v7.object({
@@ -8454,19 +8719,19 @@ var provision = addSshOptions(
8454
8719
  (target, raw) => runCommand(async () => {
8455
8720
  const options = parseOptions(OptionsSchema2, raw);
8456
8721
  const pbVersion = options.pbVersion ?? pocketbaseVersion();
8457
- p42.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8458
- p42.log.info(`Target ${pc17.cyan(target)}`);
8722
+ p43.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8723
+ p43.log.info(`Target ${pc17.cyan(target)}`);
8459
8724
  await withSsh(target, sshOptionsFrom(options), async (session) => {
8460
8725
  await session.detectElevation();
8461
8726
  const existing = await readServerInfo(session);
8462
8727
  if (existing) {
8463
- p42.log.info(
8728
+ p43.log.info(
8464
8729
  `Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
8465
8730
  );
8466
8731
  }
8467
- p42.log.step("Uploading server scripts");
8732
+ p43.log.step("Uploading server scripts");
8468
8733
  await syncServerScripts(session);
8469
- p42.log.step("Running provision");
8734
+ p43.log.step("Running provision");
8470
8735
  const result = await runServerScript(session, "provision.sh", {
8471
8736
  args: [
8472
8737
  "--pb-version",
@@ -8478,7 +8743,7 @@ var provision = addSshOptions(
8478
8743
  ],
8479
8744
  stream: true
8480
8745
  });
8481
- p42.log.success(
8746
+ p43.log.success(
8482
8747
  `${target} is ready.
8483
8748
 
8484
8749
  Node ${result?.node ?? "installed"}
@@ -8486,7 +8751,7 @@ var provision = addSshOptions(
8486
8751
  PocketBase ${result?.pocketbase ?? pbVersion}`
8487
8752
  );
8488
8753
  });
8489
- p42.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8754
+ p43.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8490
8755
  }, "Failed to provision.")
8491
8756
  );
8492
8757
 
@@ -8494,21 +8759,21 @@ var provision = addSshOptions(
8494
8759
  import path38 from "node:path";
8495
8760
  import fs37 from "node:fs";
8496
8761
  import { Command as Command77, Option as Option2 } from "commander";
8497
- import * as p43 from "@clack/prompts";
8762
+ import * as p44 from "@clack/prompts";
8498
8763
  import pc18 from "picocolors";
8499
8764
  import * as v8 from "valibot";
8500
8765
 
8501
8766
  // src/lib/pocketbase-settings.ts
8502
8767
  import fs35 from "node:fs";
8503
8768
  import path36 from "node:path";
8504
- import process29 from "node:process";
8769
+ import process31 from "node:process";
8505
8770
  import PocketBase5 from "pocketbase";
8506
8771
  var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
8507
8772
  async function readLocalMeta(cwd) {
8508
8773
  const dataDir2 = path36.join(cwd, DATA_DIR);
8509
8774
  if (!fs35.existsSync(dataDir2)) return null;
8510
- const email3 = process29.env.POCKETBASE_SUPERUSER_EMAIL;
8511
- const password11 = process29.env.POCKETBASE_SUPERUSER_PASSWORD;
8775
+ const email3 = process31.env.POCKETBASE_SUPERUSER_EMAIL;
8776
+ const password11 = process31.env.POCKETBASE_SUPERUSER_PASSWORD;
8512
8777
  if (!email3 || !password11) return null;
8513
8778
  let proc;
8514
8779
  try {
@@ -8853,7 +9118,7 @@ var deploy = addLockWaitOption(
8853
9118
  (raw) => runCommand(async () => {
8854
9119
  const options = parseOptions(OptionsSchema3, raw);
8855
9120
  const backend3 = hasBackend();
8856
- p43.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
9121
+ p44.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
8857
9122
  if (options.build !== false) {
8858
9123
  const { workspaceRootDir } = await getWorkspace();
8859
9124
  await prepareAdapter(workspaceRootDir);
@@ -8863,7 +9128,7 @@ var deploy = addLockWaitOption(
8863
9128
  {
8864
9129
  remote: async (ctx) => {
8865
9130
  const { session, instance, workspaceRootDir, config } = ctx;
8866
- p43.log.info(
9131
+ p44.log.info(
8867
9132
  `${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
8868
9133
  );
8869
9134
  const [existing] = await readInstanceStates(session, instance);
@@ -8873,7 +9138,7 @@ var deploy = addLockWaitOption(
8873
9138
  const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
8874
9139
  const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
8875
9140
  if (existing && instanceHasBackend(existing) !== backend3) {
8876
- p43.log.info(
9141
+ p44.log.info(
8877
9142
  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
9143
  );
8879
9144
  }
@@ -8916,7 +9181,7 @@ with DNS of your own pointing at ${ctx.server}.`
8916
9181
  tunnel = await openDatabaseTunnel(session, instance, existing);
8917
9182
  } catch (err) {
8918
9183
  if (askedForRemoteDb) throw err;
8919
- p43.log.warn(
9184
+ p44.log.warn(
8920
9185
  `Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
8921
9186
  ${pc18.dim(String(err))}`
8922
9187
  );
@@ -8924,13 +9189,13 @@ ${pc18.dim(String(err))}`
8924
9189
  }
8925
9190
  if (tunnel) {
8926
9191
  buildEnv = { ...buildEnv, ...tunnel.env };
8927
- p43.log.info(
9192
+ p44.log.info(
8928
9193
  `Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
8929
9194
  );
8930
9195
  } else if (backend3) {
8931
9196
  await ensureSuperuser(workspaceRootDir);
8932
9197
  }
8933
- p43.log.step("Building");
9198
+ p44.log.step("Building");
8934
9199
  try {
8935
9200
  await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
8936
9201
  } finally {
@@ -8938,9 +9203,9 @@ ${pc18.dim(String(err))}`
8938
9203
  }
8939
9204
  }
8940
9205
  const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
8941
- p43.log.step(`Uploading release ${pc18.dim(release)}`);
9206
+ p44.log.step(`Uploading release ${pc18.dim(release)}`);
8942
9207
  await uploadRelease(session, instance, release, entries);
8943
- p43.log.step("Activating");
9208
+ p44.log.step("Activating");
8944
9209
  result = await runServerScript(session, "apply.sh", {
8945
9210
  args: [
8946
9211
  instance,
@@ -8991,7 +9256,7 @@ ${pc18.dim(String(err))}`
8991
9256
  url: primaryHost ? url : void 0
8992
9257
  });
8993
9258
  const redirects = started?.environment.redirects ?? [];
8994
- p43.log.success(
9259
+ p44.log.success(
8995
9260
  `Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
8996
9261
 
8997
9262
  URL ${url}
@@ -8999,7 +9264,7 @@ ${pc18.dim(String(err))}`
8999
9264
  ` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
9000
9265
  );
9001
9266
  if (managed && managed !== existing?.managed) {
9002
- p43.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9267
+ p44.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9003
9268
  }
9004
9269
  if (result?.superuserCreated) {
9005
9270
  await copyLocalBranding(
@@ -9008,7 +9273,7 @@ ${pc18.dim(String(err))}`
9008
9273
  workspaceRootDir,
9009
9274
  primaryHost ? result?.url ?? "" : ""
9010
9275
  );
9011
- p43.log.info(
9276
+ p44.log.info(
9012
9277
  `Created the PocketBase superuser this app authenticates as.
9013
9278
 
9014
9279
  Its credentials are stored in the environment on the server. To use
@@ -9019,7 +9284,7 @@ and deploy again.`
9019
9284
  await reportAppURLDrift(session, instance, primaryHost);
9020
9285
  }
9021
9286
  if (!primaryHost) {
9022
- p43.log.warn(
9287
+ p44.log.warn(
9023
9288
  `No domain configured, so nothing is proxied to this app yet.
9024
9289
  Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
9025
9290
  or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
@@ -9029,7 +9294,7 @@ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
9029
9294
  },
9030
9295
  { project: options.project, askDomain: true, label: "deploy" }
9031
9296
  );
9032
- p43.outro(`${pc18.cyan("vela status")} to see what is running`);
9297
+ p44.outro(`${pc18.cyan("vela status")} to see what is running`);
9033
9298
  }, "Failed to deploy.")
9034
9299
  );
9035
9300
  async function prepareAdapter(workspaceRootDir) {
@@ -9048,8 +9313,8 @@ ${pc18.cyan(err.snippet)}` : err.message);
9048
9313
  outcome.packageJsonChanged ? "package.json" : void 0
9049
9314
  ].filter((f) => Boolean(f));
9050
9315
  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(
9316
+ p44.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
9317
+ p44.log.info(
9053
9318
  `${why}, and vela deploy runs the app as a Node server.
9054
9319
 
9055
9320
  Changed ${changed.join(", ")}` + (outcome.removedDeps.length ? `
@@ -9062,14 +9327,14 @@ ${pc18.cyan(err.snippet)}` : err.message);
9062
9327
  rethrow(err);
9063
9328
  }
9064
9329
  }
9065
- p43.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9330
+ p44.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9066
9331
  }
9067
9332
  async function reportAppURLDrift(session, instance, domain) {
9068
9333
  const expected = normalizeOrigin(domain);
9069
9334
  if (!expected) return;
9070
9335
  const current = await readRemoteAppURL(session, instance);
9071
9336
  if (!current || normalizeOrigin(current) === expected) return;
9072
- p43.log.warn(
9337
+ p44.log.warn(
9073
9338
  `This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
9074
9339
 
9075
9340
  Emails and anything else PocketBase links to will use the former. Update it in
@@ -9084,15 +9349,15 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
9084
9349
  if (copied.length === 0) return;
9085
9350
  const outcome = await restartInstance(session, instance);
9086
9351
  if (outcome.deployed && !outcome.restarted) {
9087
- p43.log.warn(
9352
+ p44.log.warn(
9088
9353
  `Copied ${copied.join(", ")}, but the app did not restart to pick them up.
9089
9354
  ${pc18.dim(outcome.error ?? "")}`
9090
9355
  );
9091
9356
  return;
9092
9357
  }
9093
- p43.log.success(`Copied ${copied.join(", ")} from this project's database`);
9358
+ p44.log.success(`Copied ${copied.join(", ")} from this project's database`);
9094
9359
  } catch (err) {
9095
- p43.log.warn(
9360
+ p44.log.warn(
9096
9361
  `Could not copy this project's PocketBase settings across.
9097
9362
  Set them in the admin panel instead. ${pc18.dim(String(err))}`
9098
9363
  );
@@ -9185,7 +9450,7 @@ async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
9185
9450
  const remote = await readRemoteEnv(session, instance);
9186
9451
  if (Object.keys(remote).length > 0) return;
9187
9452
  if (!fs37.existsSync(path38.join(workspaceRootDir, ".env"))) return;
9188
- p43.log.warn(
9453
+ p44.log.warn(
9189
9454
  `This app has no production environment variables yet.
9190
9455
 
9191
9456
  Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
@@ -9196,53 +9461,43 @@ async function serverTimeOrLocal(session) {
9196
9461
  try {
9197
9462
  return await serverTime(session);
9198
9463
  } catch {
9199
- p43.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9464
+ p44.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9200
9465
  return /* @__PURE__ */ new Date();
9201
9466
  }
9202
9467
  }
9203
9468
 
9204
9469
  // src/commands/link.ts
9205
9470
  import path39 from "node:path";
9206
- import process30 from "node:process";
9471
+ import process32 from "node:process";
9207
9472
  import { Command as Command78 } from "commander";
9208
- import * as p44 from "@clack/prompts";
9473
+ import * as p45 from "@clack/prompts";
9209
9474
  var CREATE_NEW = "__new__";
9210
9475
  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
9476
  async function linkProject() {
9212
9477
  const { workspaceRootDir } = await getWorkspace();
9213
9478
  const existing = readProjectConfig(workspaceRootDir);
9214
9479
  if (existing) {
9215
- p44.log.success(`Linked to ${existing.projectName}.`);
9480
+ p45.log.success(`Linked to ${existing.projectName}.`);
9216
9481
  return;
9217
9482
  }
9218
9483
  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;
9484
+ const [teams3, projects] = await Promise.all([listTeams(apiKey), listProjects(apiKey)]);
9227
9485
  const picked = projects.length > 0 ? await pickExistingProject(projects) : CREATE_NEW;
9486
+ let linked;
9228
9487
  if (picked !== CREATE_NEW) {
9229
9488
  const project = projects.find((pr) => pr.id === picked);
9230
- projectId = project.id;
9231
- teamId = project.team;
9232
- projectName = project.name;
9489
+ linked = toLinked(project, project.expand?.team);
9233
9490
  } else {
9234
9491
  const team = await pickTeam(teams3);
9235
9492
  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;
9493
+ linked = await linkNewProject(apiKey, { name, teamId: team.id, interactive: true });
9240
9494
  }
9495
+ const { projectId, teamId, projectName } = linked;
9241
9496
  writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
9242
- p44.log.success(`Linked to ${projectName}.`);
9497
+ p45.log.success(`Linked to ${projectName} (${linked.dashboardUrl}).`);
9243
9498
  }
9244
9499
  async function pickExistingProject(projects) {
9245
- const choice = await p44.select({
9500
+ const choice = await p45.select({
9246
9501
  message: "Select a project",
9247
9502
  options: [
9248
9503
  ...projects.map((pr) => ({
@@ -9252,39 +9507,24 @@ async function pickExistingProject(projects) {
9252
9507
  { value: CREATE_NEW, label: "Create a new project" }
9253
9508
  ]
9254
9509
  });
9255
- if (p44.isCancel(choice)) {
9256
- p44.cancel("Operation cancelled.");
9257
- process30.exit(0);
9510
+ if (p45.isCancel(choice)) {
9511
+ p45.cancel("Operation cancelled.");
9512
+ process32.exit(0);
9258
9513
  }
9259
9514
  return choice;
9260
9515
  }
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
9516
  async function promptProjectName(workspaceRootDir) {
9277
9517
  const defaultValue = defaultProjectName2(workspaceRootDir);
9278
- const value = await p44.text({
9518
+ const value = await p45.text({
9279
9519
  message: "Project name",
9280
9520
  defaultValue,
9281
9521
  initialValue: defaultValue,
9282
9522
  placeholder: defaultValue,
9283
9523
  validate: (v10) => !v10?.trim() ? "Required" : void 0
9284
9524
  });
9285
- if (p44.isCancel(value)) {
9286
- p44.cancel("Operation cancelled.");
9287
- process30.exit(0);
9525
+ if (p45.isCancel(value)) {
9526
+ p45.cancel("Operation cancelled.");
9527
+ process32.exit(0);
9288
9528
  }
9289
9529
  return value.trim();
9290
9530
  }
@@ -9303,7 +9543,7 @@ import { Command as Command83 } from "commander";
9303
9543
 
9304
9544
  // src/commands/env/list.ts
9305
9545
  import { Command as Command79 } from "commander";
9306
- import * as p45 from "@clack/prompts";
9546
+ import * as p46 from "@clack/prompts";
9307
9547
  import pc19 from "picocolors";
9308
9548
  var envList = addTargetOptions(
9309
9549
  new Command79("list").description("list environment variable names").configureHelp(helpConfig),
@@ -9328,10 +9568,10 @@ var envList = addTargetOptions(
9328
9568
  );
9329
9569
  function report(keys, where) {
9330
9570
  if (keys.length === 0) {
9331
- p45.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9571
+ p46.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9332
9572
  return;
9333
9573
  }
9334
- p45.log.info(
9574
+ p46.log.info(
9335
9575
  `Environment ${pc19.dim(`(${where})`)}
9336
9576
 
9337
9577
  ` + keys.sort().map((key) => ` ${key}`).join("\n")
@@ -9339,9 +9579,9 @@ function report(keys, where) {
9339
9579
  }
9340
9580
 
9341
9581
  // src/commands/env/set.ts
9342
- import process31 from "node:process";
9582
+ import process33 from "node:process";
9343
9583
  import { Command as Command80 } from "commander";
9344
- import * as p46 from "@clack/prompts";
9584
+ import * as p47 from "@clack/prompts";
9345
9585
  import pc20 from "picocolors";
9346
9586
  var envSet = addTargetOptions(
9347
9587
  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 +9594,14 @@ var envSet = addTargetOptions(
9354
9594
  local: async (ctx) => {
9355
9595
  const resolved = await resolveValue(key, value);
9356
9596
  setLocalEnv(ctx.envFile, key, resolved);
9357
- p46.log.success(`${key} updated ${pc20.dim("(local)")}`);
9597
+ p47.log.success(`${key} updated ${pc20.dim("(local)")}`);
9358
9598
  await applyLocalEnvChange(ctx, [key]);
9359
9599
  },
9360
9600
  remote: async (ctx) => {
9361
9601
  const resolved = await resolveValue(key, value);
9362
9602
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9363
9603
  await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
9364
- p46.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9604
+ p47.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9365
9605
  await applyEnvRestart(ctx, [key]);
9366
9606
  }
9367
9607
  },
@@ -9375,20 +9615,20 @@ async function resolveValue(key, value) {
9375
9615
  return value ?? await promptValue(key);
9376
9616
  }
9377
9617
  async function promptValue(key) {
9378
- const value = await p46.password({
9618
+ const value = await p47.password({
9379
9619
  message: `Value for ${pc20.cyan(key)}`,
9380
9620
  validate: (input) => !input?.length ? "Required" : void 0
9381
9621
  });
9382
- if (p46.isCancel(value)) {
9383
- p46.cancel("Operation cancelled.");
9384
- process31.exit(0);
9622
+ if (p47.isCancel(value)) {
9623
+ p47.cancel("Operation cancelled.");
9624
+ process33.exit(0);
9385
9625
  }
9386
9626
  return value;
9387
9627
  }
9388
9628
 
9389
9629
  // src/commands/env/unset.ts
9390
9630
  import { Command as Command81 } from "commander";
9391
- import * as p47 from "@clack/prompts";
9631
+ import * as p48 from "@clack/prompts";
9392
9632
  import pc21 from "picocolors";
9393
9633
  var envUnset = addTargetOptions(
9394
9634
  new Command81("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
@@ -9400,22 +9640,22 @@ var envUnset = addTargetOptions(
9400
9640
  {
9401
9641
  local: async (ctx) => {
9402
9642
  if (!(key in readLocalEnv(ctx.envFile))) {
9403
- p47.log.info(`${key} is not set \u2014 nothing to remove.`);
9643
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9404
9644
  return;
9405
9645
  }
9406
9646
  unsetLocalEnv(ctx.envFile, key);
9407
- p47.log.success(`${key} removed ${pc21.dim("(local)")}`);
9647
+ p48.log.success(`${key} removed ${pc21.dim("(local)")}`);
9408
9648
  await applyLocalEnvChange(ctx, [key]);
9409
9649
  },
9410
9650
  remote: async (ctx) => {
9411
9651
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9412
9652
  if (!(key in env2)) {
9413
- p47.log.info(`${key} is not set \u2014 nothing to remove.`);
9653
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9414
9654
  return;
9415
9655
  }
9416
9656
  delete env2[key];
9417
9657
  await writeRemoteEnv(ctx.session, ctx.instance, env2);
9418
- p47.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9658
+ p48.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9419
9659
  await applyEnvRestart(ctx, [key]);
9420
9660
  }
9421
9661
  },
@@ -9428,9 +9668,9 @@ var envUnset = addTargetOptions(
9428
9668
  // src/commands/env/import.ts
9429
9669
  import fs38 from "node:fs";
9430
9670
  import path40 from "node:path";
9431
- import process32 from "node:process";
9671
+ import process34 from "node:process";
9432
9672
  import { Command as Command82 } from "commander";
9433
- import * as p48 from "@clack/prompts";
9673
+ import * as p49 from "@clack/prompts";
9434
9674
  import pc22 from "picocolors";
9435
9675
  var envImport = addTargetOptions(
9436
9676
  new Command82("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
@@ -9448,22 +9688,22 @@ var envImport = addTargetOptions(
9448
9688
  const incoming = read(source, file);
9449
9689
  const keys = Object.keys(incoming);
9450
9690
  if (keys.length === 0) return;
9451
- p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9691
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9452
9692
  editLocalEnv(
9453
9693
  ctx.envFile,
9454
9694
  (content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
9455
9695
  );
9456
- p48.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9696
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9457
9697
  await applyLocalEnvChange(ctx, keys);
9458
9698
  },
9459
9699
  remote: async (ctx) => {
9460
9700
  const incoming = read(resolve(file), file);
9461
9701
  const keys = Object.keys(incoming);
9462
9702
  if (keys.length === 0) return;
9463
- p48.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9703
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9464
9704
  const existing = await readRemoteEnv(ctx.session, ctx.instance);
9465
9705
  await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
9466
- p48.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9706
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9467
9707
  await applyEnvRestart(ctx, keys);
9468
9708
  }
9469
9709
  },
@@ -9473,12 +9713,12 @@ var envImport = addTargetOptions(
9473
9713
  )
9474
9714
  );
9475
9715
  function resolve(file) {
9476
- return path40.resolve(process32.cwd(), file);
9716
+ return path40.resolve(process34.cwd(), file);
9477
9717
  }
9478
9718
  function read(resolved, shown) {
9479
9719
  if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
9480
9720
  const incoming = readLocalEnvFile(resolved);
9481
- if (Object.keys(incoming).length === 0) p48.log.info(`${shown} has no variables to import.`);
9721
+ if (Object.keys(incoming).length === 0) p49.log.info(`${shown} has no variables to import.`);
9482
9722
  return incoming;
9483
9723
  }
9484
9724
 
@@ -9487,7 +9727,7 @@ var env = new Command83("env").description("manage environment variables, locall
9487
9727
 
9488
9728
  // src/commands/status.ts
9489
9729
  import { Command as Command84 } from "commander";
9490
- import * as p49 from "@clack/prompts";
9730
+ import * as p50 from "@clack/prompts";
9491
9731
  import pc23 from "picocolors";
9492
9732
  var status = addTargetOptions(
9493
9733
  new Command84("status").description("show what is deployed").configureHelp(helpConfig),
@@ -9521,11 +9761,11 @@ function report2(states, json) {
9521
9761
  return;
9522
9762
  }
9523
9763
  if (states.length === 0) {
9524
- p49.log.info("Nothing is deployed here yet.");
9764
+ p50.log.info("Nothing is deployed here yet.");
9525
9765
  return;
9526
9766
  }
9527
9767
  for (const state of states) {
9528
- p49.log.info(describe2(state));
9768
+ p50.log.info(describe2(state));
9529
9769
  }
9530
9770
  }
9531
9771
  function describe2(state) {
@@ -9550,7 +9790,7 @@ function describe2(state) {
9550
9790
 
9551
9791
  // src/commands/rollback.ts
9552
9792
  import { Command as Command85 } from "commander";
9553
- import * as p50 from "@clack/prompts";
9793
+ import * as p51 from "@clack/prompts";
9554
9794
  import pc24 from "picocolors";
9555
9795
  var rollback = addLockWaitOption(
9556
9796
  addTargetOptions(
@@ -9564,7 +9804,7 @@ var rollback = addLockWaitOption(
9564
9804
  raw,
9565
9805
  {
9566
9806
  remote: async (ctx) => {
9567
- p50.log.step(
9807
+ p51.log.step(
9568
9808
  `Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
9569
9809
  );
9570
9810
  const result = await runServerScript(
@@ -9579,7 +9819,7 @@ var rollback = addLockWaitOption(
9579
9819
  stream: true
9580
9820
  }
9581
9821
  );
9582
- p50.log.success(
9822
+ p51.log.success(
9583
9823
  `Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
9584
9824
  );
9585
9825
  }
@@ -9632,9 +9872,9 @@ var logs = addTargetOptions(
9632
9872
  import { Command as Command88 } from "commander";
9633
9873
 
9634
9874
  // src/commands/admin/create.ts
9635
- import process33 from "node:process";
9875
+ import process35 from "node:process";
9636
9876
  import { Command as Command87 } from "commander";
9637
- import * as p51 from "@clack/prompts";
9877
+ import * as p52 from "@clack/prompts";
9638
9878
  import pc25 from "picocolors";
9639
9879
  var MIN_PASSWORD = 10;
9640
9880
  var adminCreate = addTargetOptions(
@@ -9666,7 +9906,7 @@ var adminCreate = addTargetOptions(
9666
9906
  const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
9667
9907
  if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
9668
9908
  }
9669
- p51.log.info(
9909
+ p52.log.info(
9670
9910
  signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
9671
9911
  );
9672
9912
  },
@@ -9680,7 +9920,7 @@ var adminCreate = addTargetOptions(
9680
9920
  (pb) => upsertSuperuser(pb, address, password11)
9681
9921
  );
9682
9922
  const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
9683
- p51.log.info(
9923
+ p52.log.info(
9684
9924
  base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
9685
9925
  );
9686
9926
  }
@@ -9693,20 +9933,20 @@ var adminCreate = addTargetOptions(
9693
9933
  async function upsertSuperuser(pb, email3, password11) {
9694
9934
  const existing = await findSuperuser(pb, email3);
9695
9935
  if (existing) {
9696
- const confirmed = await p51.confirm({
9936
+ const confirmed = await p52.confirm({
9697
9937
  message: `${email3} already has an account, update its password?`,
9698
9938
  initialValue: false
9699
9939
  });
9700
- if (p51.isCancel(confirmed) || !confirmed) {
9701
- p51.cancel("Operation cancelled.");
9702
- process33.exit(0);
9940
+ if (p52.isCancel(confirmed) || !confirmed) {
9941
+ p52.cancel("Operation cancelled.");
9942
+ process35.exit(0);
9703
9943
  }
9704
9944
  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`);
9945
+ p52.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9706
9946
  return;
9707
9947
  }
9708
9948
  await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
9709
- p51.log.success(`${pc25.cyan(email3)} can now sign in`);
9949
+ p52.log.success(`${pc25.cyan(email3)} can now sign in`);
9710
9950
  }
9711
9951
  async function findSuperuser(pb, email3) {
9712
9952
  try {
@@ -9717,32 +9957,32 @@ async function findSuperuser(pb, email3) {
9717
9957
  }
9718
9958
  }
9719
9959
  async function promptEmail() {
9720
- const value = await p51.text({
9960
+ const value = await p52.text({
9721
9961
  message: "Email to sign in with",
9722
9962
  validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
9723
9963
  });
9724
- if (p51.isCancel(value)) {
9725
- p51.cancel("Operation cancelled.");
9726
- process33.exit(0);
9964
+ if (p52.isCancel(value)) {
9965
+ p52.cancel("Operation cancelled.");
9966
+ process35.exit(0);
9727
9967
  }
9728
9968
  return value.trim();
9729
9969
  }
9730
9970
  async function promptPassword2() {
9731
- const value = await p51.password({
9971
+ const value = await p52.password({
9732
9972
  message: "Password",
9733
9973
  validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
9734
9974
  });
9735
- if (p51.isCancel(value)) {
9736
- p51.cancel("Operation cancelled.");
9737
- process33.exit(0);
9975
+ if (p52.isCancel(value)) {
9976
+ p52.cancel("Operation cancelled.");
9977
+ process35.exit(0);
9738
9978
  }
9739
- const again = await p51.password({
9979
+ const again = await p52.password({
9740
9980
  message: "Password again",
9741
9981
  validate: (input) => input === value ? void 0 : "The two do not match"
9742
9982
  });
9743
- if (p51.isCancel(again)) {
9744
- p51.cancel("Operation cancelled.");
9745
- process33.exit(0);
9983
+ if (p52.isCancel(again)) {
9984
+ p52.cancel("Operation cancelled.");
9985
+ process35.exit(0);
9746
9986
  }
9747
9987
  return value;
9748
9988
  }
@@ -9757,7 +9997,7 @@ import { Command as Command94 } from "commander";
9757
9997
  import fs39 from "node:fs";
9758
9998
  import path41 from "node:path";
9759
9999
  import { Command as Command89 } from "commander";
9760
- import * as p52 from "@clack/prompts";
10000
+ import * as p53 from "@clack/prompts";
9761
10001
  import pc26 from "picocolors";
9762
10002
 
9763
10003
  // src/lib/backups.ts
@@ -9861,7 +10101,7 @@ Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_
9861
10101
  }
9862
10102
  const storage = await readStorageSettings(ctx.pb);
9863
10103
  if (storage.s3Enabled) {
9864
- p52.log.warn(
10104
+ p53.log.warn(
9865
10105
  `Uploads are stored in S3, so this archive holds the database only.
9866
10106
 
9867
10107
  PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
@@ -9869,7 +10109,7 @@ Your bucket's own versioning is what protects the uploaded files.`
9869
10109
  );
9870
10110
  }
9871
10111
  if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
9872
- const spinner7 = p52.spinner();
10112
+ const spinner7 = p53.spinner();
9873
10113
  spinner7.start(`Backing up ${ctx.targetName}`);
9874
10114
  try {
9875
10115
  await createBackup(ctx.pb, key);
@@ -9916,7 +10156,7 @@ async function download(ctx, key, outputDir) {
9916
10156
  fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9917
10157
  return path41.relative(ctx.workspaceRootDir, destination);
9918
10158
  }
9919
- const spinner7 = p52.spinner();
10159
+ const spinner7 = p53.spinner();
9920
10160
  spinner7.start(`Downloading ${key}`);
9921
10161
  try {
9922
10162
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9930,7 +10170,7 @@ async function download(ctx, key, outputDir) {
9930
10170
 
9931
10171
  // src/commands/backup/list.ts
9932
10172
  import { Command as Command90 } from "commander";
9933
- import * as p53 from "@clack/prompts";
10173
+ import * as p54 from "@clack/prompts";
9934
10174
  import pc27 from "picocolors";
9935
10175
  var backupList = addTargetOptions(
9936
10176
  new Command90("list").description("list the backups on a target").configureHelp(helpConfig),
@@ -9940,7 +10180,7 @@ var backupList = addTargetOptions(
9940
10180
  () => withBackupTarget(raw, "backup list", async (ctx) => {
9941
10181
  const backups = await listBackups(ctx.pb);
9942
10182
  if (backups.length === 0) {
9943
- p53.log.info(
10183
+ p54.log.info(
9944
10184
  `${pc27.cyan(ctx.targetName)} has no backups yet.
9945
10185
 
9946
10186
  Take one with ${pc27.cyan("vela backup create")}.`
@@ -9948,7 +10188,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9948
10188
  return;
9949
10189
  }
9950
10190
  const width = Math.max(...backups.map((b) => b.key.length));
9951
- p53.log.message(
10191
+ p54.log.message(
9952
10192
  backups.map(
9953
10193
  (b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
9954
10194
  ).join("\n")
@@ -9962,7 +10202,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9962
10202
  import fs40 from "node:fs";
9963
10203
  import path42 from "node:path";
9964
10204
  import { Command as Command91 } from "commander";
9965
- import * as p54 from "@clack/prompts";
10205
+ import * as p55 from "@clack/prompts";
9966
10206
  import pc28 from "picocolors";
9967
10207
  var backupDownload = addTargetOptions(
9968
10208
  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 +10233,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9993
10233
  if (!ctx.session) {
9994
10234
  fs40.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9995
10235
  } else {
9996
- const spinner7 = p54.spinner();
10236
+ const spinner7 = p55.spinner();
9997
10237
  spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
9998
10238
  try {
9999
10239
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -10012,9 +10252,9 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
10012
10252
  );
10013
10253
 
10014
10254
  // src/commands/backup/delete.ts
10015
- import process34 from "node:process";
10255
+ import process36 from "node:process";
10016
10256
  import { Command as Command92 } from "commander";
10017
- import * as p55 from "@clack/prompts";
10257
+ import * as p56 from "@clack/prompts";
10018
10258
  import pc29 from "picocolors";
10019
10259
  var backupDelete = addTargetOptions(
10020
10260
  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 +10272,13 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
10032
10272
  );
10033
10273
  }
10034
10274
  if (!options.yes) {
10035
- const confirmed = await p55.confirm({
10275
+ const confirmed = await p56.confirm({
10036
10276
  message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
10037
10277
  initialValue: false
10038
10278
  });
10039
- if (p55.isCancel(confirmed) || !confirmed) {
10040
- p55.cancel("Operation cancelled.");
10041
- process34.exit(0);
10279
+ if (p56.isCancel(confirmed) || !confirmed) {
10280
+ p56.cancel("Operation cancelled.");
10281
+ process36.exit(0);
10042
10282
  }
10043
10283
  }
10044
10284
  await ctx.pb.backups.delete(key);
@@ -10049,7 +10289,7 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
10049
10289
 
10050
10290
  // src/commands/backup/schedule.ts
10051
10291
  import { Command as Command93 } from "commander";
10052
- import * as p56 from "@clack/prompts";
10292
+ import * as p57 from "@clack/prompts";
10053
10293
  import pc30 from "picocolors";
10054
10294
  var DEFAULT_KEEP = 7;
10055
10295
  var backupSchedule = addTargetOptions(
@@ -10066,7 +10306,7 @@ var backupSchedule = addTargetOptions(
10066
10306
  }
10067
10307
  if (!cron) {
10068
10308
  const current = await readSchedule(ctx.pb);
10069
- p56.log.info(
10309
+ p57.log.info(
10070
10310
  current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
10071
10311
 
10072
10312
  Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
@@ -10102,9 +10342,9 @@ var backup = new Command94("backup").description("back up the database and uploa
10102
10342
  // src/commands/restore.ts
10103
10343
  import fs41 from "node:fs";
10104
10344
  import path43 from "node:path";
10105
- import process35 from "node:process";
10345
+ import process37 from "node:process";
10106
10346
  import { Command as Command95 } from "commander";
10107
- import * as p57 from "@clack/prompts";
10347
+ import * as p58 from "@clack/prompts";
10108
10348
  import pc31 from "picocolors";
10109
10349
  var restore = addLockWaitOption(
10110
10350
  addTargetOptions(
@@ -10145,18 +10385,18 @@ var restore = addLockWaitOption(
10145
10385
  ],
10146
10386
  stream: true
10147
10387
  });
10148
- p57.log.success(
10388
+ p58.log.success(
10149
10389
  `Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
10150
10390
  local ? path43.basename(local) : key
10151
10391
  )}.`
10152
10392
  );
10153
10393
  if (result?.storageCarriedOver) {
10154
- p57.log.info(
10394
+ p58.log.info(
10155
10395
  "The archive held no uploads, so the files already on the server were kept."
10156
10396
  );
10157
10397
  }
10158
10398
  if (result?.previousDataDir) {
10159
- p57.log.info(
10399
+ p58.log.info(
10160
10400
  `The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
10161
10401
 
10162
10402
  It is the only way back. Remove it once you are satisfied with the restore.`
@@ -10197,7 +10437,7 @@ Run ${pc31.cyan("vela backup list")} to see what it does have.`
10197
10437
  Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
10198
10438
  );
10199
10439
  }
10200
- const chosen = await p57.select({
10440
+ const chosen = await p58.select({
10201
10441
  message: `Which backup should ${ctx.targetName} be restored from?`,
10202
10442
  options: backups.map((b) => ({
10203
10443
  value: b.key,
@@ -10205,16 +10445,16 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
10205
10445
  hint: `${formatBytes(b.size)}, ${b.modified}`
10206
10446
  }))
10207
10447
  });
10208
- if (p57.isCancel(chosen)) {
10209
- p57.cancel("Operation cancelled.");
10210
- process35.exit(0);
10448
+ if (p58.isCancel(chosen)) {
10449
+ p58.cancel("Operation cancelled.");
10450
+ process37.exit(0);
10211
10451
  }
10212
10452
  return chosen;
10213
10453
  }
10214
10454
  async function stage(ctx, file) {
10215
10455
  const dir = remotePaths.restoreStage(ctx.instance);
10216
10456
  const remote = `${dir}/${path43.basename(file)}`;
10217
- const spinner7 = p57.spinner();
10457
+ const spinner7 = p58.spinner();
10218
10458
  spinner7.start(`Uploading ${path43.basename(file)}`);
10219
10459
  try {
10220
10460
  await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
@@ -10229,29 +10469,29 @@ async function stage(ctx, file) {
10229
10469
  async function confirm13(appName, targetName, envTag, from) {
10230
10470
  const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path43.basename(from))}`;
10231
10471
  if (isProd(envTag)) {
10232
- const answer = await p57.text({
10472
+ const answer = await p58.text({
10233
10473
  message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
10234
10474
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
10235
10475
  });
10236
- if (p57.isCancel(answer)) {
10237
- p57.cancel("Operation cancelled.");
10238
- process35.exit(0);
10476
+ if (p58.isCancel(answer)) {
10477
+ p58.cancel("Operation cancelled.");
10478
+ process37.exit(0);
10239
10479
  }
10240
10480
  return;
10241
10481
  }
10242
- const ok = await p57.confirm({
10482
+ const ok = await p58.confirm({
10243
10483
  message: `Replace the database and uploads of ${what}?`,
10244
10484
  initialValue: false
10245
10485
  });
10246
- if (p57.isCancel(ok) || !ok) {
10247
- p57.cancel("Operation cancelled.");
10248
- process35.exit(0);
10486
+ if (p58.isCancel(ok) || !ok) {
10487
+ p58.cancel("Operation cancelled.");
10488
+ process37.exit(0);
10249
10489
  }
10250
10490
  }
10251
10491
 
10252
10492
  // src/commands/targets.ts
10253
10493
  import { Command as Command96 } from "commander";
10254
- import * as p58 from "@clack/prompts";
10494
+ import * as p59 from "@clack/prompts";
10255
10495
  import pc32 from "picocolors";
10256
10496
  import * as v9 from "valibot";
10257
10497
  var OptionsSchema4 = v9.object({
@@ -10326,11 +10566,11 @@ function report3(rows, offline) {
10326
10566
  const lines = rows.map(
10327
10567
  (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
10568
  );
10329
- p58.log.info(`${pc32.dim(header)}
10569
+ p59.log.info(`${pc32.dim(header)}
10330
10570
  ${lines.join("\n")}`);
10331
10571
  const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
10332
10572
  if (!offline && unreachable.length > 0) {
10333
- p58.log.warn(
10573
+ p59.log.warn(
10334
10574
  `Could not reach ${unreachable.map((row) => row.server).join(", ")}.
10335
10575
  Release and domain are shown from what this project recorded.`
10336
10576
  );
@@ -10339,7 +10579,7 @@ Release and domain are shown from what this project recorded.`
10339
10579
 
10340
10580
  // src/commands/test.ts
10341
10581
  import path44 from "node:path";
10342
- import process36 from "node:process";
10582
+ import process38 from "node:process";
10343
10583
  import { Command as Command97 } from "commander";
10344
10584
  import PocketBase6 from "pocketbase";
10345
10585
  import pc33 from "picocolors";
@@ -10348,7 +10588,7 @@ import { detect as detect8 } from "package-manager-detector";
10348
10588
  import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
10349
10589
  import fs42 from "node:fs";
10350
10590
  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();
10591
+ const cwd = process38.cwd();
10352
10592
  const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
10353
10593
  const password11 = "password";
10354
10594
  const testDataDir = path44.join(cwd, "test-data");
@@ -10363,11 +10603,11 @@ var testServer = new Command97("test:server").description("run server tests").al
10363
10603
  email: email3,
10364
10604
  password: password11
10365
10605
  });
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";
10606
+ process38.env.POCKETBASE_URL = url;
10607
+ process38.env.POCKETBASE_SUPERUSER_EMAIL = email3;
10608
+ process38.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
10609
+ process38.env.VELA_DATA_DIR = testDataDir;
10610
+ process38.env.TEST = "true";
10371
10611
  console.log(`${pc33.greenBright("\u2713")} Created test database`);
10372
10612
  let vite;
10373
10613
  let cleanedUp = false;
@@ -10386,12 +10626,12 @@ var testServer = new Command97("test:server").description("run server tests").al
10386
10626
  const fail = async (message) => {
10387
10627
  console.error(`${pc33.redBright("\u2717")} ${message}`);
10388
10628
  await cleanup();
10389
- process36.exit(1);
10629
+ process38.exit(1);
10390
10630
  };
10391
- process36.on("exit", cleanupSync);
10392
- process36.on("SIGINT", () => {
10631
+ process38.on("exit", cleanupSync);
10632
+ process38.on("SIGINT", () => {
10393
10633
  cleanupSync();
10394
- process36.exit(130);
10634
+ process38.exit(130);
10395
10635
  });
10396
10636
  const pb = new PocketBase6(url);
10397
10637
  try {
@@ -10419,7 +10659,7 @@ var testServer = new Command97("test:server").description("run server tests").al
10419
10659
  });
10420
10660
  const vitePort = await findFreePort();
10421
10661
  await vite.listen(vitePort);
10422
- process36.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10662
+ process38.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10423
10663
  console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
10424
10664
  console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
10425
10665
  const extraArgs = (cmd.parent?.args ?? []).slice(1);
@@ -10438,12 +10678,12 @@ var testServer = new Command97("test:server").description("run server tests").al
10438
10678
  const resolvedArgs = resolved.args.slice();
10439
10679
  if (pm === "npm") resolvedArgs.unshift("--yes");
10440
10680
  const result = await x5(resolved.command, resolvedArgs, {
10441
- nodeOptions: { cwd, stdio: "inherit", env: { ...process36.env, CI: "1" } }
10681
+ nodeOptions: { cwd, stdio: "inherit", env: { ...process38.env, CI: "1" } }
10442
10682
  });
10443
- process36.exitCode = result.exitCode ?? 1;
10683
+ process38.exitCode = result.exitCode ?? 1;
10444
10684
  } catch (e) {
10445
10685
  console.error(`${pc33.redBright("\u2717")} ${e.message}`);
10446
- process36.exitCode = 1;
10686
+ process38.exitCode = 1;
10447
10687
  } finally {
10448
10688
  await cleanup();
10449
10689
  }
@@ -10562,13 +10802,13 @@ function printTable(routes2) {
10562
10802
  }
10563
10803
 
10564
10804
  // src/commands/i18n.ts
10565
- import process37 from "node:process";
10805
+ import process39 from "node:process";
10566
10806
  import { Command as Command99 } from "commander";
10567
10807
  import { x as x6 } from "tinyexec";
10568
10808
  import { detect as detect9 } from "package-manager-detector";
10569
10809
  import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
10570
10810
  async function runWuchale(extraArgs) {
10571
- const cwd = process37.cwd();
10811
+ const cwd = process39.cwd();
10572
10812
  const pm = (await detect9({ cwd }))?.name ?? "npm";
10573
10813
  const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
10574
10814
  const args = resolved.args.slice();
@@ -10599,13 +10839,13 @@ import { Command as Command103 } from "commander";
10599
10839
  // src/commands/cms/editor/add.ts
10600
10840
  import { randomBytes } from "node:crypto";
10601
10841
  import { Command as Command100 } from "commander";
10602
- import * as p59 from "@clack/prompts";
10842
+ import * as p60 from "@clack/prompts";
10603
10843
  import pc35 from "picocolors";
10604
10844
 
10605
10845
  // src/lib/cms-backend.ts
10606
10846
  import { createRequire as createRequire3 } from "node:module";
10607
10847
  import path46 from "node:path";
10608
- import process38 from "node:process";
10848
+ import process40 from "node:process";
10609
10849
  import { pathToFileURL as pathToFileURL3 } from "node:url";
10610
10850
  import pc34 from "picocolors";
10611
10851
  var DEFAULT_PROJECT = "default";
@@ -10622,7 +10862,7 @@ Run ${pc34.cyan("vela enable cms")} first.`
10622
10862
  }
10623
10863
  return await import(pathToFileURL3(entry).href);
10624
10864
  }
10625
- async function withCmsBackend(fn, cwd = process38.cwd()) {
10865
+ async function withCmsBackend(fn, cwd = process40.cwd()) {
10626
10866
  const root = findWorkspaceRoot(cwd);
10627
10867
  if (!root) {
10628
10868
  throw new Error("Could not find workspace root (no package.json found)");
@@ -10652,8 +10892,8 @@ var editorAdd = new Command100("add").description("create an editor who can sign
10652
10892
  if (generated) {
10653
10893
  lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
10654
10894
  }
10655
- p59.log.success(lines.join("\n"));
10656
- p59.log.info(
10895
+ p60.log.success(lines.join("\n"));
10896
+ p60.log.info(
10657
10897
  `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
10898
  );
10659
10899
  }, "Failed to add the editor.")
@@ -10661,12 +10901,12 @@ var editorAdd = new Command100("add").description("create an editor who can sign
10661
10901
 
10662
10902
  // src/commands/cms/editor/password.ts
10663
10903
  import { Command as Command101 } from "commander";
10664
- import * as p60 from "@clack/prompts";
10904
+ import * as p61 from "@clack/prompts";
10665
10905
  import pc36 from "picocolors";
10666
10906
  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
10907
  (email3, password11) => runCommand(async () => {
10668
10908
  await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
10669
- p60.log.success(
10909
+ p61.log.success(
10670
10910
  `Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
10671
10911
  );
10672
10912
  }, "Failed to set the password.")
@@ -10674,7 +10914,7 @@ var editorPassword = new Command101("password").description("set an editor's pas
10674
10914
 
10675
10915
  // src/commands/cms/editor/list.ts
10676
10916
  import { Command as Command102 } from "commander";
10677
- import * as p61 from "@clack/prompts";
10917
+ import * as p62 from "@clack/prompts";
10678
10918
  import pc37 from "picocolors";
10679
10919
  var editorList = new Command102("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10680
10920
  () => runCommand(async () => {
@@ -10685,11 +10925,11 @@ var editorList = new Command102("list").description("list editors and the projec
10685
10925
  }))
10686
10926
  );
10687
10927
  if (rows.length === 0) {
10688
- p61.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10928
+ p62.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10689
10929
  return;
10690
10930
  }
10691
10931
  const width = Math.max(...rows.map((row) => row.email.length));
10692
- p61.log.info(
10932
+ p62.log.info(
10693
10933
  `Editors
10694
10934
 
10695
10935
  ` + rows.map(
@@ -10746,7 +10986,7 @@ var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
10746
10986
  var program = new Command105().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10747
10987
  program.hook("preAction", (_thisCommand, actionCommand) => {
10748
10988
  if (isStub(actionCommand)) return;
10749
- const envRoot = findWorkspaceRoot() ?? process39.cwd();
10989
+ const envRoot = findWorkspaceRoot() ?? process41.cwd();
10750
10990
  dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
10751
10991
  const path47 = getCommandPath(actionCommand);
10752
10992
  if (NO_BACKEND_COMMMANDS.has(path47)) return;
@@ -10754,20 +10994,20 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
10754
10994
  if (NO_BACKEND_COMMMANDS.has(top)) return;
10755
10995
  if (!hasBackend()) {
10756
10996
  if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
10757
- p62.log.error(
10997
+ p63.log.error(
10758
10998
  `${pc38.cyan(`vela ${path47}`)} needs a backend, and this project does not have one.
10759
10999
 
10760
11000
  Static projects have no database to talk to.
10761
11001
 
10762
11002
  To add a backend to this project, run ${pc38.cyan("vela bless")}.`
10763
11003
  );
10764
- p62.log.message();
10765
- p62.cancel("Operation failed.");
10766
- process39.exit(1);
11004
+ p63.log.message();
11005
+ p63.cancel("Operation failed.");
11006
+ process41.exit(1);
10767
11007
  }
10768
11008
  if (SELF_CREDENTIALED_COMMANDS.has(path47)) return;
10769
- if (!process39.env.POCKETBASE_SUPERUSER_EMAIL || !process39.env.POCKETBASE_SUPERUSER_PASSWORD) {
10770
- p62.log.error(
11009
+ if (!process41.env.POCKETBASE_SUPERUSER_EMAIL || !process41.env.POCKETBASE_SUPERUSER_PASSWORD) {
11010
+ p63.log.error(
10771
11011
  `PocketBase superuser credentials are required.
10772
11012
 
10773
11013
  Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
@@ -10775,9 +11015,9 @@ Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPER
10775
11015
  To set up a new project, run ${pc38.cyan("vela create")}.
10776
11016
  To set up an existing project, run ${pc38.cyan("vela bless")}.`
10777
11017
  );
10778
- p62.log.message();
10779
- p62.cancel("Operation failed.");
10780
- process39.exit(1);
11018
+ p63.log.message();
11019
+ p63.cancel("Operation failed.");
11020
+ process41.exit(1);
10781
11021
  }
10782
11022
  });
10783
11023
  function getCommandPath(cmd) {
@@ -10831,5 +11071,5 @@ for (const command of [
10831
11071
  }
10832
11072
 
10833
11073
  // src/bin.ts
10834
- program.parse(normalizeArgv(process40.argv.slice(2)), { from: "user" });
11074
+ program.parse(normalizeArgv(process42.argv.slice(2)), { from: "user" });
10835
11075
  //# sourceMappingURL=bin.js.map