vela 0.11.5 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.js CHANGED
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // src/bin.ts
4
- import process39 from "node:process";
4
+ import process42 from "node:process";
5
5
 
6
6
  // src/lib/argv.ts
7
7
  function normalizeArgv(argv) {
@@ -11,9 +11,9 @@ function normalizeArgv(argv) {
11
11
  }
12
12
 
13
13
  // src/program.ts
14
- import process38 from "node:process";
15
- import * as p61 from "@clack/prompts";
16
- import { Command as Command104 } from "commander";
14
+ import process41 from "node:process";
15
+ import * as p63 from "@clack/prompts";
16
+ import { Command as Command105 } from "commander";
17
17
  import nodePath from "node:path";
18
18
  import dotenv2 from "dotenv";
19
19
  import pc38 from "picocolors";
@@ -21,7 +21,7 @@ import pc38 from "picocolors";
21
21
  // package.json
22
22
  var package_default = {
23
23
  name: "vela",
24
- version: "0.11.5",
24
+ version: "0.12.0",
25
25
  type: "module",
26
26
  description: "A CLI for creating and updating SvelteKit projects",
27
27
  license: "MIT",
@@ -57,7 +57,7 @@ var package_default = {
57
57
  dependencies: {
58
58
  "@clack/prompts": "^1.7.0",
59
59
  "@faker-js/faker": "^10.6.0",
60
- "@velastack/patterns": "^0.2.4",
60
+ "@velastack/patterns": "^0.2.5",
61
61
  "@velastack/pocketbase-codegen": "^0.1.0",
62
62
  "annotate-json-schema": "^0.1.0",
63
63
  commander: "^13.1.0",
@@ -66,7 +66,7 @@ var package_default = {
66
66
  dotenv: "^17.4.2",
67
67
  "fetch-cookie": "^3.2.0",
68
68
  "json-schema-faker": "^0.6.3",
69
- "magic-string": "^0.30.21",
69
+ "magic-string": "^1.2.3",
70
70
  "package-manager-detector": "^1.8.0",
71
71
  picocolors: "^1.1.1",
72
72
  pocketbase: "^0.28.0",
@@ -321,10 +321,15 @@ function readPackageJson(path47) {
321
321
  var PACKAGE_NAME_PLACEHOLDER = /~TODO~/g;
322
322
  var APP_NAME_PLACEHOLDER = /~APP_NAME~/g;
323
323
  var CLI_VERSION_PLACEHOLDER = /~VELA_VERSION~/g;
324
+ var SITE_URL_PLACEHOLDER = /~SITE_URL~/g;
325
+ var CMS_ENDPOINT_PLACEHOLDER = /~CMS_ENDPOINT~/g;
326
+ var LOCAL_SITE_URL = "http://localhost:5173";
324
327
  function fillTemplatePlaceholders(raw, values) {
325
328
  const packageName = toValidPackageName(values.appName);
326
329
  const appName = escapeSingleQuoted(values.appName);
327
- return raw.replace(PACKAGE_NAME_PLACEHOLDER, () => packageName).replace(APP_NAME_PLACEHOLDER, () => appName).replace(CLI_VERSION_PLACEHOLDER, () => values.cliVersion);
330
+ const siteUrl = escapeSingleQuoted(values.siteUrl ?? LOCAL_SITE_URL);
331
+ const cmsEndpoint = escapeSingleQuoted(values.cmsEndpoint ?? "");
332
+ return raw.replace(PACKAGE_NAME_PLACEHOLDER, () => packageName).replace(APP_NAME_PLACEHOLDER, () => appName).replace(CLI_VERSION_PLACEHOLDER, () => values.cliVersion).replace(SITE_URL_PLACEHOLDER, () => siteUrl).replace(CMS_ENDPOINT_PLACEHOLDER, () => cmsEndpoint);
328
333
  }
329
334
  function escapeSingleQuoted(value) {
330
335
  return value.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
@@ -562,6 +567,10 @@ var entrySchema = v2.object({
562
567
  price: v2.optional(v2.number()),
563
568
  previewUrl: v2.optional(v2.string()),
564
569
  nextSteps: v2.optional(v2.array(v2.string())),
570
+ /** Reads its copy from a hosted CMS through `site.cmsEndpoint`. */
571
+ cms: v2.optional(v2.boolean()),
572
+ /** A prebuilt static build is published for velastack.dev's instant deploys. */
573
+ instantDeploy: v2.optional(v2.boolean()),
565
574
  /** Tarball location, relative to the index URL. */
566
575
  file: v2.string(),
567
576
  sha256: v2.pipe(v2.string(), v2.regex(/^[0-9a-f]{64}$/)),
@@ -593,10 +602,10 @@ function writeCachedIndex(cached2) {
593
602
  fs5.mkdirSync(cacheRoot(), { recursive: true });
594
603
  fs5.writeFileSync(indexCachePath(), JSON.stringify(cached2, null, 2));
595
604
  }
596
- function parseTemplateIndex(text18, url) {
605
+ function parseTemplateIndex(text19, url) {
597
606
  let parsed;
598
607
  try {
599
- parsed = JSON.parse(text18);
608
+ parsed = JSON.parse(text19);
600
609
  } catch (e) {
601
610
  throw new Error(`Template index at ${url} is not valid JSON: ${e.message}`);
602
611
  }
@@ -753,6 +762,7 @@ async function listAllTemplates(options = {}) {
753
762
  tags: entry.tags,
754
763
  price: entry.price,
755
764
  nextSteps: entry.nextSteps,
765
+ cms: entry.cms,
756
766
  entry,
757
767
  indexUrl
758
768
  });
@@ -833,6 +843,7 @@ function readManifest(root, name) {
833
843
  tags: optionalStringArray(manifest.tags),
834
844
  price: typeof manifest.price === "number" ? manifest.price : void 0,
835
845
  nextSteps: optionalStringArray(manifest.nextSteps),
846
+ cms: typeof manifest.cms === "boolean" ? manifest.cms : void 0,
836
847
  dir: path5.join(root, name)
837
848
  };
838
849
  }
@@ -968,7 +979,7 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
968
979
  };
969
980
  proc.once("exit", onExit);
970
981
  let attempts = 0;
971
- const check = async () => {
982
+ const check2 = async () => {
972
983
  if (settled) return;
973
984
  attempts++;
974
985
  try {
@@ -989,9 +1000,9 @@ function waitForReadyOrExit(proc, url, maxAttempts = 40) {
989
1000
  reject(new Error(`Timed out waiting for health at ${url}`));
990
1001
  return;
991
1002
  }
992
- setTimeout(check, 250);
1003
+ setTimeout(check2, 250);
993
1004
  };
994
- check();
1005
+ check2();
995
1006
  });
996
1007
  }
997
1008
  async function startPocketbaseServe(opts) {
@@ -1912,37 +1923,493 @@ function printNextSteps(projectPath, packageManager2) {
1912
1923
  }
1913
1924
 
1914
1925
  // src/commands/create.ts
1926
+ import fs17 from "node:fs";
1927
+ import path15 from "node:path";
1928
+ import process11 from "node:process";
1929
+ import * as v4 from "valibot";
1930
+ import { Command as Command4 } from "commander";
1931
+ import * as p8 from "@clack/prompts";
1932
+ import { detect as detect3, resolveCommand as resolveCommand3 } from "package-manager-detector";
1933
+
1934
+ // src/lib/providers.ts
1935
+ import process8 from "node:process";
1936
+ import * as p5 from "@clack/prompts";
1937
+ import { bySlug } from "@velastack/patterns";
1938
+ function capabilityName(slug2) {
1939
+ return slug2.replace(/^enable-/, "");
1940
+ }
1941
+ function choices(providers) {
1942
+ return `--provider <${providers.map((provider) => provider.id).join("|")}>`;
1943
+ }
1944
+ function unknownProviderMessage(name, raw, providers) {
1945
+ return [
1946
+ `Unknown provider "${raw}" for ${name}.`,
1947
+ "",
1948
+ "Available providers:",
1949
+ ...providers.map((provider) => ` ${provider.id}`)
1950
+ ].join("\n");
1951
+ }
1952
+ function decideProvider(request) {
1953
+ const { patternName, providers, flagValue, interactive } = request;
1954
+ if (flagValue !== void 0) {
1955
+ const provider = providers.find((candidate) => candidate.id === flagValue);
1956
+ if (!provider) {
1957
+ return { kind: "error", message: unknownProviderMessage(patternName, flagValue, providers) };
1958
+ }
1959
+ return { kind: "use", provider };
1960
+ }
1961
+ if (interactive) return { kind: "prompt" };
1962
+ return {
1963
+ kind: "error",
1964
+ message: `Choose ${article(patternName)} ${patternName} provider: pass ${choices(providers)}. There is no terminal to ask on.`
1965
+ };
1966
+ }
1967
+ function article(word) {
1968
+ return /^[aeiou]/i.test(word) ? "an" : "a";
1969
+ }
1970
+ function isInteractive() {
1971
+ return Boolean(process8.stdout.isTTY) && !process8.env.CI;
1972
+ }
1973
+ function providerFlagInArgv(argv) {
1974
+ return argv.some((arg) => arg === "--provider" || arg.startsWith("--provider="));
1975
+ }
1976
+ function checkProviderInput(pattern, argv, input) {
1977
+ const providers = pattern.providers ?? [];
1978
+ if (providers.length > 0) {
1979
+ if (typeof input.provider !== "string" || input.provider.length === 0) {
1980
+ throw new Error(`${pattern.title} needs a provider. Pass ${choices(providers)}.`);
1981
+ }
1982
+ return;
1983
+ }
1984
+ if (providerFlagInArgv(argv)) {
1985
+ throw new Error(`${pattern.title} does not support --provider.`);
1986
+ }
1987
+ }
1988
+ async function resolveProvider(slug2, flagValue) {
1989
+ const pattern = bySlug[slug2];
1990
+ const providers = pattern.providers ?? [];
1991
+ if (providers.length === 0) {
1992
+ throw new Error(`${pattern.title} does not support --provider.`);
1993
+ }
1994
+ const patternName = capabilityName(slug2);
1995
+ const decision = decideProvider({
1996
+ patternName,
1997
+ providers,
1998
+ flagValue,
1999
+ interactive: isInteractive()
2000
+ });
2001
+ if (decision.kind === "error") throw new Error(decision.message);
2002
+ if (decision.kind === "use") return decision.provider;
2003
+ const selected = await p5.select({
2004
+ message: `Select ${patternName} provider`,
2005
+ options: providers.map((provider) => ({ value: provider.id, label: provider.label }))
2006
+ });
2007
+ if (p5.isCancel(selected)) {
2008
+ p5.cancel("Operation cancelled.");
2009
+ process8.exit(0);
2010
+ }
2011
+ return providers.find((provider) => provider.id === selected);
2012
+ }
2013
+ async function collectProviderEnv(provider) {
2014
+ const values = {};
2015
+ const interactive = isInteractive();
2016
+ for (const variable of provider.env ?? []) {
2017
+ const existing = process8.env[variable.key];
2018
+ if (existing) {
2019
+ values[variable.key] = existing;
2020
+ continue;
2021
+ }
2022
+ if (!interactive) {
2023
+ values[variable.key] = variable.default ?? "";
2024
+ continue;
2025
+ }
2026
+ const value = await p5.text({
2027
+ message: variable.label,
2028
+ placeholder: variable.placeholder,
2029
+ initialValue: variable.default
2030
+ });
2031
+ if (p5.isCancel(value)) {
2032
+ p5.cancel("Operation cancelled.");
2033
+ process8.exit(0);
2034
+ }
2035
+ values[variable.key] = (value ?? "").trim();
2036
+ }
2037
+ return values;
2038
+ }
2039
+ function missingEnvKeys(provider, values) {
2040
+ return (provider.env ?? []).filter((variable) => !(values[variable.key] ?? "").trim() && !variable.default).map((variable) => variable.key);
2041
+ }
2042
+
2043
+ // src/lib/link-on-create.ts
2044
+ var FREE_CMS_HINT = "Get a free CMS at https://velastack.dev";
2045
+ var PROJECT_ID_RE = /^[a-z0-9]{15}$/;
2046
+ var CMS_URL_RE = /^https?:\/\/\S+$/;
2047
+ var NOT_LOGGED_IN = "Not logged in. Run `vela login` to login, or set VELA_API_KEY.";
2048
+ var NO_CMS_WARNING = `No CMS configured: \`cmsEndpoint\` in src/lib/site.ts is empty, so the site shows its fallback copy. Pass \`--link new\`, \`--link <project-id>\` or \`--cms <url>\` to set it, or fill it in later. ${FREE_CMS_HINT}.`;
2049
+ function decideLink(request) {
2050
+ const { link: link2, needsCms, loggedIn, interactive } = request;
2051
+ if (link2 === "none") return { kind: "none" };
2052
+ if (link2 === "new") {
2053
+ return loggedIn ? { kind: "create" } : { kind: "error", message: NOT_LOGGED_IN };
2054
+ }
2055
+ if (link2 !== void 0) {
2056
+ return loggedIn ? { kind: "existing", projectId: link2 } : { kind: "error", message: NOT_LOGGED_IN };
2057
+ }
2058
+ if (!interactive) return { kind: "none", warn: needsCms ? NO_CMS_WARNING : void 0 };
2059
+ if (loggedIn) return { kind: "create" };
2060
+ return needsCms ? { kind: "prompt-cms" } : { kind: "none" };
2061
+ }
2062
+ function cmsEndpointFor(projectId) {
2063
+ return `${API_URL}/v1/projects/${projectId}/cms`;
2064
+ }
2065
+ function normalizeCmsUrl(url) {
2066
+ return url.trim().replace(/\/+$/, "");
2067
+ }
2068
+ function linkNextSteps(outcome) {
2069
+ const steps = [];
2070
+ const { linked, cmsEndpoint, cmsSource, templateCms, loggedIn, interactive } = outcome;
2071
+ if (templateCms && linked && cmsSource === "linked") {
2072
+ steps.push(
2073
+ `Add an editor at ${linked.dashboardUrl}/cms/editors, then open any page with \`?edit\` and sign in from the admin bar.`
2074
+ );
2075
+ } else if (cmsEndpoint) {
2076
+ steps.push("Open any page with `?edit` and sign in from the admin bar.");
2077
+ } else if (templateCms) {
2078
+ steps.push(
2079
+ `When you have a CMS, set \`cmsEndpoint\` in \`src/lib/site.ts\`. ${FREE_CMS_HINT}.`
2080
+ );
2081
+ }
2082
+ if (linked && !(templateCms && cmsSource === "linked")) {
2083
+ steps.push(
2084
+ `Run \`vela deploy\` when you're ready; the project is linked to ${linked.dashboardUrl}.`
2085
+ );
2086
+ } else if (!linked && interactive && !loggedIn && !templateCms) {
2087
+ steps.push("Run `vela login` then `vela link` to get a free velastack.app hostname on deploy.");
2088
+ }
2089
+ return steps;
2090
+ }
2091
+
2092
+ // src/lib/link-project.ts
2093
+ import process9 from "node:process";
2094
+ import * as p6 from "@clack/prompts";
2095
+
2096
+ // src/lib/velastack-api.ts
2097
+ async function apiFetch(apiKey, pathAndQuery, init) {
2098
+ const headers = new Headers(init?.headers);
2099
+ headers.set("Authorization", `Bearer ${apiKey}`);
2100
+ if (init?.body && !headers.has("Content-Type")) {
2101
+ headers.set("Content-Type", "application/json");
2102
+ }
2103
+ const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
2104
+ if (res.status === 401) {
2105
+ throw new Error("API key invalid \u2014 run `vela login`");
2106
+ }
2107
+ if (res.status === 403) {
2108
+ const body = await res.text().catch(() => "");
2109
+ throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
2110
+ }
2111
+ if (!res.ok) {
2112
+ const body = await res.text().catch(() => "");
2113
+ throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
2114
+ }
2115
+ return await res.json();
2116
+ }
2117
+ async function getCurrentUser(apiKey) {
2118
+ const data = await apiFetch(
2119
+ apiKey,
2120
+ "/api/collections/users/records?perPage=1"
2121
+ );
2122
+ const user = data.items[0];
2123
+ if (!user) throw new Error("No user found. Run `vela login` to login.");
2124
+ return user;
2125
+ }
2126
+ async function listTeams(apiKey) {
2127
+ const data = await apiFetch(
2128
+ apiKey,
2129
+ "/api/collections/teams/records?perPage=200"
2130
+ );
2131
+ return data.items;
2132
+ }
2133
+ async function listProjects(apiKey) {
2134
+ const data = await apiFetch(
2135
+ apiKey,
2136
+ "/api/collections/projects/records?perPage=200&expand=team"
2137
+ );
2138
+ return data.items;
2139
+ }
2140
+ async function createProject(apiKey, args) {
2141
+ return apiFetch(apiKey, "/api/collections/projects/records", {
2142
+ method: "POST",
2143
+ body: JSON.stringify({
2144
+ name: args.name,
2145
+ team: args.teamId,
2146
+ user: args.userId,
2147
+ ...args.template ? { template: args.template } : {}
2148
+ })
2149
+ });
2150
+ }
2151
+ async function registerServer(apiKey, input) {
2152
+ return apiFetch(apiKey, "/v1/servers", {
2153
+ method: "POST",
2154
+ body: JSON.stringify(input)
2155
+ });
2156
+ }
2157
+ async function startDeployment(apiKey, projectId, input) {
2158
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
2159
+ method: "POST",
2160
+ body: JSON.stringify(input)
2161
+ });
2162
+ }
2163
+ async function finishDeployment(apiKey, projectId, deploymentId, input) {
2164
+ return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
2165
+ method: "PATCH",
2166
+ body: JSON.stringify(input)
2167
+ });
2168
+ }
2169
+ async function destroyEnvironment(apiKey, projectId, envTag) {
2170
+ return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
2171
+ method: "DELETE"
2172
+ });
2173
+ }
2174
+
2175
+ // src/lib/link-project.ts
2176
+ function dashboardUrl(teamSlug, projectSlug) {
2177
+ return teamSlug && projectSlug ? `${API_URL}/${teamSlug}/${projectSlug}` : API_URL;
2178
+ }
2179
+ async function pickTeam(teams3) {
2180
+ if (teams3.length === 1) return teams3[0];
2181
+ const choice = await p6.select({
2182
+ message: "Select a team",
2183
+ options: teams3.map((team) => ({
2184
+ value: team.id,
2185
+ label: team.is_personal ? `${team.name} (personal)` : team.name
2186
+ }))
2187
+ });
2188
+ if (p6.isCancel(choice)) {
2189
+ p6.cancel("Operation cancelled.");
2190
+ process9.exit(0);
2191
+ }
2192
+ return teams3.find((team) => team.id === choice);
2193
+ }
2194
+ async function resolveTeam(teams3, options) {
2195
+ if (options.teamId) {
2196
+ const team = teams3.find((candidate) => candidate.id === options.teamId);
2197
+ if (!team) {
2198
+ throw new Error(
2199
+ `You are not a member of team ${options.teamId}. Omit --team to use your personal team.`
2200
+ );
2201
+ }
2202
+ return team;
2203
+ }
2204
+ if (teams3.length === 0) throw new Error("No team found on velastack.dev for this account.");
2205
+ const personal = teams3.find((team) => team.is_personal);
2206
+ if (personal) return personal;
2207
+ if (options.interactive) return pickTeam(teams3);
2208
+ throw new Error("Several teams and no personal one: pass --team <id>.");
2209
+ }
2210
+ async function linkNewProject(apiKey, args) {
2211
+ const [user, teams3] = await Promise.all([getCurrentUser(apiKey), listTeams(apiKey)]);
2212
+ const team = await resolveTeam(teams3, { teamId: args.teamId, interactive: args.interactive });
2213
+ const project = await createProject(apiKey, {
2214
+ name: args.name,
2215
+ teamId: team.id,
2216
+ userId: user.id,
2217
+ template: args.template
2218
+ });
2219
+ return toLinked(project, team);
2220
+ }
2221
+ async function linkExistingProject(apiKey, projectId) {
2222
+ const projects = await listProjects(apiKey);
2223
+ const project = projects.find((candidate) => candidate.id === projectId);
2224
+ if (!project) {
2225
+ throw new Error(`No project ${projectId} on velastack.dev for this account.`);
2226
+ }
2227
+ return toLinked(project, project.expand?.team);
2228
+ }
2229
+ function toLinked(project, team) {
2230
+ return {
2231
+ projectId: project.id,
2232
+ teamId: project.team,
2233
+ projectName: project.name,
2234
+ dashboardUrl: dashboardUrl(team?.slug, project.slug)
2235
+ };
2236
+ }
2237
+
2238
+ // src/lib/project-config.ts
1915
2239
  import fs16 from "node:fs";
1916
2240
  import path14 from "node:path";
1917
- import process8 from "node:process";
1918
- import * as v4 from "valibot";
2241
+ function projectConfigPath(workspaceRootDir) {
2242
+ return path14.join(workspaceRootDir, ".vela", "project.json");
2243
+ }
2244
+ function readProjectConfig(workspaceRootDir) {
2245
+ const file = projectConfigPath(workspaceRootDir);
2246
+ if (!fs16.existsSync(file)) return null;
2247
+ try {
2248
+ const parsed = JSON.parse(fs16.readFileSync(file, "utf8"));
2249
+ if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
2250
+ return null;
2251
+ }
2252
+ return {
2253
+ projectId: parsed.projectId,
2254
+ teamId: parsed.teamId,
2255
+ projectName: parsed.projectName
2256
+ };
2257
+ } catch {
2258
+ return null;
2259
+ }
2260
+ }
2261
+ function writeProjectConfig(workspaceRootDir, config) {
2262
+ const file = projectConfigPath(workspaceRootDir);
2263
+ fs16.mkdirSync(path14.dirname(file), { recursive: true });
2264
+ let existing = {};
2265
+ if (fs16.existsSync(file)) {
2266
+ try {
2267
+ existing = JSON.parse(fs16.readFileSync(file, "utf8"));
2268
+ } catch {
2269
+ }
2270
+ }
2271
+ fs16.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2272
+ }
2273
+
2274
+ // src/commands/login.ts
2275
+ import os3 from "node:os";
2276
+ import process10 from "node:process";
1919
2277
  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";
2278
+ import * as p7 from "@clack/prompts";
2279
+ import makeFetchCookie from "fetch-cookie";
2280
+ var login = new Command3("login").description("login to velastack.dev").configureHelp(helpConfig).action(
2281
+ () => runCommand(async () => {
2282
+ await loginInteractively();
2283
+ p7.log.success("Logged in to velastack.dev");
2284
+ }, "Failed to login.")
2285
+ );
2286
+ async function loginInteractively() {
2287
+ const { email: email3, password: password11 } = await p7.group(
2288
+ {
2289
+ email: () => p7.text({ message: "Email" }),
2290
+ password: () => p7.password({ message: "Password" })
2291
+ },
2292
+ {
2293
+ onCancel: () => {
2294
+ p7.cancel("Operation cancelled.");
2295
+ process10.exit(0);
2296
+ }
2297
+ }
2298
+ );
2299
+ const fetchCookie = makeFetchCookie(fetch);
2300
+ const loginRes = await fetchCookie(`${API_URL}/login`, {
2301
+ method: "POST",
2302
+ headers: {
2303
+ "Content-Type": "application/x-www-form-urlencoded",
2304
+ Origin: API_URL
2305
+ },
2306
+ body: new URLSearchParams({ type: "password", email: email3, password: password11 }).toString()
2307
+ });
2308
+ if (!loginRes.headers.get("Set-Cookie")) {
2309
+ throw new Error(
2310
+ "Run `vela signup` to create an account or reset at https://velastack.dev/reset"
2311
+ );
2312
+ }
2313
+ const apiKey = await issueApiKey(fetchCookie);
2314
+ writeConfig({ apiKey });
2315
+ return apiKey;
2316
+ }
2317
+ async function issueApiKey(fetchCookie) {
2318
+ const label4 = `CLI - ${os3.hostname()}`;
2319
+ await fetchCookie(`${API_URL}/api-keys/new`, {
2320
+ method: "POST",
2321
+ headers: {
2322
+ "Content-Type": "application/x-www-form-urlencoded",
2323
+ Origin: API_URL
2324
+ },
2325
+ body: new URLSearchParams({ label: label4 }).toString()
2326
+ });
2327
+ const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
2328
+ const apiKey = extractApiKey(cookie);
2329
+ if (!apiKey) {
2330
+ throw new Error("Failed to create API key. Try again or contact support.");
2331
+ }
2332
+ const [id] = apiKey.split(".");
2333
+ const res = await fetchCookie(`${API_URL}/api/collections/api_keys/records`, {
2334
+ headers: { Authorization: `Bearer ${apiKey}` }
2335
+ });
2336
+ const data = await res.json();
2337
+ for (const item of data.items) {
2338
+ if (item.label === label4 && item.id !== id) {
2339
+ await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
2340
+ method: "DELETE",
2341
+ headers: { Authorization: `Bearer ${apiKey}` }
2342
+ });
2343
+ }
2344
+ }
2345
+ return apiKey;
2346
+ }
2347
+ function extractApiKey(cookie) {
2348
+ const flashCookie = cookie.split(";").find((c) => c.trim().startsWith("flash="));
2349
+ if (!flashCookie) return null;
2350
+ const decoded = decodeURIComponent(flashCookie.split("=")[1]);
2351
+ return JSON.parse(decoded).apiKey;
2352
+ }
2353
+
2354
+ // src/commands/create.ts
1922
2355
  function optionsSchema2(listing) {
1923
2356
  const names = listing.templates.map((template) => template.name);
1924
- let choices = `must be one of: ${templateChoicesMessage(listing.templates)}`;
2357
+ let choices2 = `must be one of: ${templateChoicesMessage(listing.templates)}`;
1925
2358
  if (listing.registryError) {
1926
- choices += ` (could not reach the template registry: ${listing.registryError})`;
2359
+ choices2 += ` (could not reach the template registry: ${listing.registryError})`;
1927
2360
  }
1928
2361
  return v4.strictObject({
1929
2362
  install: v4.union([v4.boolean(), v4.picklist(AGENT_NAMES)], "must be a package manager"),
1930
- template: v4.optional(v4.picklist(names, choices)),
2363
+ template: v4.optional(v4.picklist(names, choices2)),
1931
2364
  name: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
1932
2365
  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")))
2366
+ password: v4.optional(v4.pipe(v4.string(), v4.minLength(8, "must be at least 8 characters long"))),
2367
+ link: v4.optional(
2368
+ v4.pipe(
2369
+ v4.string(),
2370
+ v4.check(
2371
+ (value) => value === "new" || value === "none" || PROJECT_ID_RE.test(value),
2372
+ "must be `new`, `none` or a velastack.dev project id"
2373
+ )
2374
+ )
2375
+ ),
2376
+ team: v4.optional(v4.pipe(v4.string(), v4.trim(), v4.minLength(1, "must not be empty"))),
2377
+ cms: v4.optional(
2378
+ v4.pipe(v4.string(), v4.trim(), v4.regex(CMS_URL_RE, "must be an absolute CMS URL"))
2379
+ )
1934
2380
  });
1935
2381
  }
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) => {
2382
+ function checkFlagsForTemplate(template, options) {
2383
+ if (!template.backend && (options.email || options.password)) {
2384
+ throw new Error(
2385
+ `--email and --password don't apply to the ${template.name} template \u2014 it has no backend.`
2386
+ );
2387
+ }
2388
+ if (options.cms !== void 0 && !template.cms) {
2389
+ throw new Error(
2390
+ `--cms doesn't apply to the ${template.name} template \u2014 it reads no copy from a CMS.`
2391
+ );
2392
+ }
2393
+ if (options.team !== void 0 && options.link !== "new") {
2394
+ throw new Error("--team only applies together with --link new.");
2395
+ }
2396
+ }
2397
+ var create = new Command4("create").description("scaffold a new velastack project").argument("[path]", "where the project will be created").option("--template <type>", "template to scaffold (built-in or from the registry)", "minimal").option("--no-install", "skip installing dependencies").option("--name <name>", "app name (used for emails, etc)").option("--email <email>", "email of the admin user").option("--password <password>", "password of the admin user").option(
2398
+ "--link <new|none|project-id>",
2399
+ "link to a velastack.dev project: create one, skip, or use an existing project id (default: create when logged in at a terminal)"
2400
+ ).option("--team <id>", "velastack.dev team for `--link new` (default: your personal team)").option(
2401
+ "--cms <url>",
2402
+ "read from a CMS at this URL instead of the linked project's (CMS-ready templates only)"
2403
+ ).addOption(installOption).configureHelp(helpConfig).action((projectPath, rawOpts) => {
1937
2404
  return runCommand(async () => {
1938
2405
  const listing = await listAllTemplates();
1939
2406
  const options = parseOptions(optionsSchema2(listing), rawOpts);
1940
- const { directory, packageManager: packageManager2, name, template } = await createProject(
2407
+ const { directory, packageManager: packageManager2, name, template, link: link2 } = await createProject2(
1941
2408
  projectPath,
1942
2409
  options,
1943
2410
  listing
1944
2411
  );
1945
- const relative = path14.relative(process8.cwd(), directory);
2412
+ const relative = path15.relative(process11.cwd(), directory);
1946
2413
  const pm = packageManager2 ?? (await detect3({ cwd: directory }))?.name ?? getUserAgent() ?? "npm";
1947
2414
  const nextSteps = [];
1948
2415
  if (relative !== "") {
@@ -1973,6 +2440,7 @@ var create = new Command3("create").description("scaffold a new velastack projec
1973
2440
  );
1974
2441
  nextSteps.push("Run `vela ui add <component>` to add UI components.");
1975
2442
  }
2443
+ nextSteps.push(...linkNextSteps(link2));
1976
2444
  nextSteps.push("Stuck? Visit https://docs.velastack.dev");
1977
2445
  reportResult({
1978
2446
  summary: `Created ${name} at ${directory}.`,
@@ -1980,42 +2448,38 @@ var create = new Command3("create").description("scaffold a new velastack projec
1980
2448
  });
1981
2449
  }, "Failed to create project.");
1982
2450
  });
1983
- async function createProject(cwdArg, options, listing) {
2451
+ async function createProject2(cwdArg, options, listing) {
1984
2452
  const onCancel2 = () => {
1985
- p5.cancel("Operation cancelled.");
1986
- process8.exit(0);
2453
+ p8.cancel("Operation cancelled.");
2454
+ process11.exit(0);
1987
2455
  };
1988
2456
  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
- }
2457
+ checkFlagsForTemplate(template, options);
1994
2458
  let directory;
1995
2459
  if (cwdArg) {
1996
- directory = path14.resolve(cwdArg);
2460
+ directory = path15.resolve(cwdArg);
1997
2461
  } else {
1998
- const answer = await p5.text({
2462
+ const answer = await p8.text({
1999
2463
  message: "Where would you like your project to be created?",
2000
2464
  placeholder: " (hit Enter to use current directory)",
2001
2465
  defaultValue: "./"
2002
2466
  });
2003
- if (p5.isCancel(answer)) onCancel2();
2004
- directory = path14.resolve(answer);
2467
+ if (p8.isCancel(answer)) onCancel2();
2468
+ directory = path15.resolve(answer);
2005
2469
  }
2006
- if (fs16.existsSync(directory) && fs16.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
2007
- const force = await p5.confirm({
2470
+ if (fs17.existsSync(directory) && fs17.readdirSync(directory).filter((f) => !f.startsWith(".git")).length > 0) {
2471
+ const force = await p8.confirm({
2008
2472
  message: "Directory not empty. Continue?",
2009
2473
  initialValue: false
2010
2474
  });
2011
- if (p5.isCancel(force) || !force) onCancel2();
2475
+ if (p8.isCancel(force) || !force) onCancel2();
2012
2476
  }
2013
- const dirName = path14.basename(directory);
2014
- const { name } = await p5.group(
2477
+ const dirName = path15.basename(directory);
2478
+ const { name } = await p8.group(
2015
2479
  {
2016
2480
  name: () => {
2017
2481
  if (options.name) return Promise.resolve(options.name);
2018
- return p5.text({
2482
+ return p8.text({
2019
2483
  message: "App name (used for emails, etc)",
2020
2484
  initialValue: dirName || "SvelteKit",
2021
2485
  validate: (value) => value?.trim() ? void 0 : "App name is required"
@@ -2025,19 +2489,28 @@ async function createProject(cwdArg, options, listing) {
2025
2489
  { onCancel: onCancel2 }
2026
2490
  );
2027
2491
  const credentials = template.backend ? await promptCredentials(options, onCancel2) : void 0;
2492
+ const link2 = await linkOnCreate(name, template, options, onCancel2);
2028
2493
  const projectPath = directory;
2029
- if (template.source === "remote") p5.log.step(`Downloading template ${template.name}...`);
2494
+ if (template.source === "remote") p8.log.step(`Downloading template ${template.name}...`);
2030
2495
  const resolved = await resolveTemplate(template);
2031
2496
  try {
2032
2497
  copyTemplate(resolved, projectPath);
2033
- applyTemplateFiles(projectPath, { appName: name, cliVersion: package_default.version });
2498
+ applyTemplateFiles(projectPath, {
2499
+ appName: name,
2500
+ cliVersion: package_default.version,
2501
+ cmsEndpoint: link2.cmsEndpoint
2502
+ });
2034
2503
  } finally {
2035
2504
  resolved.cleanup();
2036
2505
  }
2037
- if (!fs16.existsSync(path14.join(projectPath, "package.json"))) {
2506
+ if (!fs17.existsSync(path15.join(projectPath, "package.json"))) {
2038
2507
  throw new Error(`Template ${template.name} is missing package.template.json`);
2039
2508
  }
2040
- p5.log.success("Project created");
2509
+ if (link2.linked) {
2510
+ const { projectId, teamId, projectName } = link2.linked;
2511
+ writeProjectConfig(projectPath, { projectId, teamId, projectName });
2512
+ }
2513
+ p8.log.success("Project created");
2041
2514
  let packageManager2;
2042
2515
  if (options.install !== false) {
2043
2516
  const pm = typeof options.install === "string" ? options.install : await packageManagerPrompt(projectPath);
@@ -2050,7 +2523,7 @@ async function createProject(cwdArg, options, listing) {
2050
2523
  }
2051
2524
  if (credentials) {
2052
2525
  const { email: email3, password: password11 } = credentials;
2053
- p5.log.step("Initializing PocketBase...");
2526
+ p8.log.step("Initializing PocketBase...");
2054
2527
  await createSuperuser(projectPath, email3, password11);
2055
2528
  await withPocketbase(
2056
2529
  projectPath,
@@ -2069,16 +2542,99 @@ async function createProject(cwdArg, options, listing) {
2069
2542
  },
2070
2543
  ["PocketBase superuser credentials \u2014 used by `vela` commands"]
2071
2544
  );
2072
- p5.log.success("PocketBase initialized");
2545
+ p8.log.success("PocketBase initialized");
2073
2546
  }
2074
- return { directory: projectPath, packageManager: packageManager2, name, template };
2547
+ return { directory: projectPath, packageManager: packageManager2, name, template, link: link2 };
2548
+ }
2549
+ async function linkOnCreate(name, template, options, onCancel2) {
2550
+ const templateCms = template.cms === true;
2551
+ const interactive = isInteractive();
2552
+ const loggedIn = readApiKey() !== null;
2553
+ const outcome = {
2554
+ cmsEndpoint: options.cms ? normalizeCmsUrl(options.cms) : "",
2555
+ cmsSource: options.cms ? "flag" : "none",
2556
+ templateCms,
2557
+ loggedIn,
2558
+ interactive
2559
+ };
2560
+ let decision = decideLink({
2561
+ link: options.link,
2562
+ needsCms: templateCms && !options.cms,
2563
+ loggedIn,
2564
+ interactive
2565
+ });
2566
+ if (decision.kind === "prompt-cms") {
2567
+ const choice = await promptCms(onCancel2);
2568
+ if (choice.kind === "url") {
2569
+ outcome.cmsEndpoint = choice.url;
2570
+ outcome.cmsSource = "prompt";
2571
+ decision = { kind: "none" };
2572
+ } else {
2573
+ decision = { kind: choice.kind === "login" ? "login-then-create" : "none" };
2574
+ }
2575
+ }
2576
+ if (decision.kind === "error") throw new Error(decision.message);
2577
+ let apiKey;
2578
+ if (decision.kind === "login-then-create") {
2579
+ apiKey = await loginInteractively();
2580
+ outcome.loggedIn = true;
2581
+ decision = { kind: "create" };
2582
+ }
2583
+ let linked;
2584
+ if (decision.kind === "create") {
2585
+ p8.log.step(
2586
+ options.link === "new" ? "Linking to a new velastack.dev project..." : "Linking to a new velastack.dev project (pass `--link none` to skip)..."
2587
+ );
2588
+ linked = await linkNewProject(apiKey ?? requireApiKey(), {
2589
+ name,
2590
+ template: template.name,
2591
+ teamId: options.team,
2592
+ interactive
2593
+ });
2594
+ } else if (decision.kind === "existing") {
2595
+ p8.log.step("Linking to velastack.dev...");
2596
+ linked = await linkExistingProject(requireApiKey(), decision.projectId);
2597
+ } else if (decision.kind === "none" && decision.warn) {
2598
+ p8.log.warn(decision.warn);
2599
+ }
2600
+ if (linked) {
2601
+ outcome.linked = linked;
2602
+ p8.log.success(`Linked to ${linked.projectName} (${linked.dashboardUrl})`);
2603
+ if (templateCms && !outcome.cmsEndpoint) {
2604
+ outcome.cmsEndpoint = cmsEndpointFor(linked.projectId);
2605
+ outcome.cmsSource = "linked";
2606
+ p8.log.success(`CMS: ${outcome.cmsEndpoint}`);
2607
+ }
2608
+ }
2609
+ return outcome;
2610
+ }
2611
+ async function promptCms(onCancel2) {
2612
+ p8.note(`This template reads its copy from a hosted CMS.
2613
+ ${FREE_CMS_HINT}.`, "CMS");
2614
+ const choice = await p8.select({
2615
+ message: "Where should the site read its content from?",
2616
+ options: [
2617
+ { value: "login", label: "Log in to velastack.dev and create one", hint: "free" },
2618
+ { value: "url", label: "Use an existing CMS URL" },
2619
+ { value: "skip", label: "Skip for now", hint: "the site shows its fallback copy" }
2620
+ ]
2621
+ });
2622
+ if (p8.isCancel(choice)) onCancel2();
2623
+ if (choice !== "url") return { kind: choice };
2624
+ const url = await p8.text({
2625
+ message: "CMS URL",
2626
+ placeholder: "https://velastack.dev/v1/projects/<project>/cms",
2627
+ validate: (value) => CMS_URL_RE.test(value?.trim() ?? "") ? void 0 : "Enter an absolute http(s) URL"
2628
+ });
2629
+ if (p8.isCancel(url)) onCancel2();
2630
+ return { kind: "url", url: normalizeCmsUrl(url) };
2075
2631
  }
2076
2632
  function promptCredentials(options, onCancel2) {
2077
- return p5.group(
2633
+ return p8.group(
2078
2634
  {
2079
2635
  email: () => {
2080
2636
  if (options.email) return Promise.resolve(options.email);
2081
- return p5.text({
2637
+ return p8.text({
2082
2638
  message: "Enter an email for the admin user",
2083
2639
  initialValue: "admin@example.com",
2084
2640
  validate: (value) => !value ? "Email is required" : !value.includes("@") ? "Invalid email" : void 0
@@ -2086,7 +2642,7 @@ function promptCredentials(options, onCancel2) {
2086
2642
  },
2087
2643
  password: () => {
2088
2644
  if (options.password) return Promise.resolve(options.password);
2089
- return p5.password({
2645
+ return p8.password({
2090
2646
  message: "Enter a password for the admin user (at least 8 characters)",
2091
2647
  validate: (value) => !value ? "Password is required" : value.length < 8 ? "Password must be at least 8 characters long" : void 0
2092
2648
  });
@@ -2097,27 +2653,28 @@ function promptCredentials(options, onCancel2) {
2097
2653
  }
2098
2654
 
2099
2655
  // src/commands/generate.ts
2100
- import { Command as Command9 } from "commander";
2656
+ import { Command as Command10 } from "commander";
2101
2657
 
2102
2658
  // src/commands/generate/form.ts
2103
- import { Command as Command4 } from "commander";
2104
- import * as p11 from "@clack/prompts";
2659
+ import { Command as Command5 } from "commander";
2660
+ import * as p14 from "@clack/prompts";
2105
2661
 
2106
2662
  // src/lib/pattern-runner.ts
2107
- import path15 from "node:path";
2108
- import * as p6 from "@clack/prompts";
2109
- import { bySlug } from "@velastack/patterns";
2663
+ import path16 from "node:path";
2664
+ import * as p9 from "@clack/prompts";
2665
+ import { bySlug as bySlug2 } from "@velastack/patterns";
2110
2666
  function toRelative(root, filePath) {
2111
- return path15.isAbsolute(filePath) ? path15.relative(root, filePath) : filePath;
2667
+ return path16.isAbsolute(filePath) ? path16.relative(root, filePath) : filePath;
2112
2668
  }
2113
2669
  var isSuccess = (f) => (f.status ?? "success") === "success";
2114
2670
  async function runPattern(slug2, argv, input, report4) {
2115
- const pattern = bySlug[slug2];
2671
+ const pattern = bySlug2[slug2];
2116
2672
  if (!pattern) {
2117
2673
  throw new Error(`Unknown pattern: ${slug2}`);
2118
2674
  }
2675
+ checkProviderInput(pattern, argv, input);
2119
2676
  const { workspaceRootDir, features } = await getWorkspace();
2120
- const log45 = p6.taskLog({ title: report4.task.title });
2677
+ const log45 = p9.taskLog({ title: report4.task.title });
2121
2678
  let result;
2122
2679
  try {
2123
2680
  result = await pattern.generate({
@@ -2156,7 +2713,7 @@ async function runPattern(slug2, argv, input, report4) {
2156
2713
  const deleted = result.deletes.filter(isSuccess);
2157
2714
  const totalChanges = created.length + modified.length + deleted.length + result.components.length + result.packages.length + result.collections.length;
2158
2715
  if (totalChanges === 0 && failures.length === 0) {
2159
- p6.log.info(`${pattern.title ?? slug2} produced no changes.`);
2716
+ p9.log.info(`${pattern.title ?? slug2} produced no changes.`);
2160
2717
  return;
2161
2718
  }
2162
2719
  reportResult({
@@ -2177,45 +2734,9 @@ async function runPattern(slug2, argv, input, report4) {
2177
2734
  // src/lib/ai-flow.ts
2178
2735
  import fs18 from "node:fs";
2179
2736
  import path17 from "node:path";
2180
- import * as p10 from "@clack/prompts";
2737
+ import * as p13 from "@clack/prompts";
2181
2738
  import pc4 from "picocolors";
2182
2739
 
2183
- // src/lib/project-config.ts
2184
- import fs17 from "node:fs";
2185
- import path16 from "node:path";
2186
- function projectConfigPath(workspaceRootDir) {
2187
- return path16.join(workspaceRootDir, ".vela", "project.json");
2188
- }
2189
- function readProjectConfig(workspaceRootDir) {
2190
- const file = projectConfigPath(workspaceRootDir);
2191
- if (!fs17.existsSync(file)) return null;
2192
- try {
2193
- const parsed = JSON.parse(fs17.readFileSync(file, "utf8"));
2194
- if (typeof parsed.projectId !== "string" || typeof parsed.teamId !== "string" || typeof parsed.projectName !== "string") {
2195
- return null;
2196
- }
2197
- return {
2198
- projectId: parsed.projectId,
2199
- teamId: parsed.teamId,
2200
- projectName: parsed.projectName
2201
- };
2202
- } catch {
2203
- return null;
2204
- }
2205
- }
2206
- function writeProjectConfig(workspaceRootDir, config) {
2207
- const file = projectConfigPath(workspaceRootDir);
2208
- fs17.mkdirSync(path16.dirname(file), { recursive: true });
2209
- let existing = {};
2210
- if (fs17.existsSync(file)) {
2211
- try {
2212
- existing = JSON.parse(fs17.readFileSync(file, "utf8"));
2213
- } catch {
2214
- }
2215
- }
2216
- fs17.writeFileSync(file, JSON.stringify({ ...existing, ...config }, null, 2) + "\n");
2217
- }
2218
-
2219
2740
  // src/lib/ai-client.ts
2220
2741
  async function aiPost(workspaceRootDir, endpoint, body) {
2221
2742
  const apiKey = requireApiKey();
@@ -2250,14 +2771,14 @@ var aiSchema = (workspaceRootDir, body) => aiPost(workspaceRootDir, "schema", bo
2250
2771
  var aiForm = (workspaceRootDir, body) => aiPost(workspaceRootDir, "form", body);
2251
2772
 
2252
2773
  // src/lib/ai-loop.ts
2253
- import * as p7 from "@clack/prompts";
2774
+ import * as p10 from "@clack/prompts";
2254
2775
  async function aiLoop(opts) {
2255
2776
  let prompt = opts.initialPrompt;
2256
2777
  let history = [];
2257
2778
  let attempt = 0;
2258
2779
  while (true) {
2259
2780
  attempt++;
2260
- const spinner7 = p7.spinner();
2781
+ const spinner7 = p10.spinner();
2261
2782
  spinner7.start(`${opts.stageLabel} (${attempt > 1 ? "iteration " + attempt : "first pass"})\u2026`);
2262
2783
  let result;
2263
2784
  let turn;
@@ -2271,12 +2792,12 @@ async function aiLoop(opts) {
2271
2792
  throw e;
2272
2793
  }
2273
2794
  opts.renderPreview(result);
2274
- const next = await p7.text({
2795
+ const next = await p10.text({
2275
2796
  message: "Refine the result, or press Enter to apply.",
2276
2797
  placeholder: opts.refinePlaceholder,
2277
2798
  defaultValue: ""
2278
2799
  });
2279
- if (p7.isCancel(next)) return null;
2800
+ if (p10.isCancel(next)) return null;
2280
2801
  const trimmed = (typeof next === "string" ? next : "").trim();
2281
2802
  if (trimmed === "") return result;
2282
2803
  history = turn;
@@ -2285,7 +2806,7 @@ async function aiLoop(opts) {
2285
2806
  }
2286
2807
 
2287
2808
  // src/lib/ai-existing-models.ts
2288
- import * as p8 from "@clack/prompts";
2809
+ import * as p11 from "@clack/prompts";
2289
2810
  async function loadExistingModels(workspaceRootDir) {
2290
2811
  let result = [];
2291
2812
  try {
@@ -2310,7 +2831,7 @@ async function loadExistingModels(workspaceRootDir) {
2310
2831
  });
2311
2832
  } catch (e) {
2312
2833
  const msg = e instanceof Error ? e.message : String(e);
2313
- p8.log.warn(
2834
+ p11.log.warn(
2314
2835
  `Could not load existing schema from PocketBase (${msg}). The AI agent will design without that context.`
2315
2836
  );
2316
2837
  return [];
@@ -2319,7 +2840,7 @@ async function loadExistingModels(workspaceRootDir) {
2319
2840
  }
2320
2841
 
2321
2842
  // src/lib/ai-to-argv.ts
2322
- import * as p9 from "@clack/prompts";
2843
+ import * as p12 from "@clack/prompts";
2323
2844
  var PRIMITIVE_TYPES = /* @__PURE__ */ new Set(["text", "number", "bool", "email", "date", "url", "file"]);
2324
2845
  function singularize(name) {
2325
2846
  if (name.endsWith("ies") && name.length > 3) return `${name.slice(0, -3)}y`;
@@ -2342,7 +2863,7 @@ function collectionSpecToArgv(spec) {
2342
2863
  for (const field of spec.fields) {
2343
2864
  const type = typeArg(field);
2344
2865
  if (type === null) {
2345
- p9.log.warn(
2866
+ p12.log.warn(
2346
2867
  `Skipping field "${field.name}" (type "${field.type}" cannot be represented as a pattern argument)`
2347
2868
  );
2348
2869
  continue;
@@ -2445,10 +2966,10 @@ function renderModel(spec) {
2445
2966
  const tail = extra.length > 0 ? " " + pc4.dim(extra.join(" ")) : "";
2446
2967
  lines.push(` ${f.name.padEnd(nameWidth)} ${f.type.padEnd(typeWidth)} ${required}${tail}`);
2447
2968
  }
2448
- p10.log.message(lines.join("\n"));
2969
+ p13.log.message(lines.join("\n"));
2449
2970
  }
2450
2971
  function renderLayout(layout) {
2451
- p10.log.message(renderGrid(layout));
2972
+ p13.log.message(renderGrid(layout));
2452
2973
  }
2453
2974
  async function runSchemaStage(opts) {
2454
2975
  const { workspaceRootDir } = await getWorkspace();
@@ -2495,7 +3016,7 @@ function writeLayoutSidecar(workspaceRootDir, modelName, layout) {
2495
3016
  }
2496
3017
 
2497
3018
  // src/commands/generate/form.ts
2498
- var form = new Command4("form").description("generate a form from a model").argument("[model]", 'model name (e.g. "contact")').argument("[fields...]", 'field definitions (e.g. "name:text", "email:email")').option("--remote", "generate a form backed by a remote PocketBase collection").option(
3019
+ var form = new Command5("form").description("generate a form from a model").argument("[model]", 'model name (e.g. "contact")').argument("[fields...]", 'field definitions (e.g. "name:text", "email:email")').option("--remote", "generate a form backed by a remote PocketBase collection").option(
2499
3020
  "--route <route>",
2500
3021
  'place the form at a custom route (e.g. "(app)/[team_id]/projects/new"). Defaults to the model name under (app)/(public).'
2501
3022
  ).option(
@@ -2512,12 +3033,12 @@ var form = new Command4("form").description("generate a form from a model").argu
2512
3033
  }
2513
3034
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "form" });
2514
3035
  if (!stage2) {
2515
- p11.cancel("Aborted before any files were written.");
3036
+ p14.cancel("Aborted before any files were written.");
2516
3037
  return;
2517
3038
  }
2518
3039
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2519
3040
  if (!layout) {
2520
- p11.cancel("Aborted before any files were written.");
3041
+ p14.cancel("Aborted before any files were written.");
2521
3042
  return;
2522
3043
  }
2523
3044
  argv = specToArgv(stage2.model);
@@ -2558,9 +3079,9 @@ var form = new Command4("form").description("generate a form from a model").argu
2558
3079
  );
2559
3080
 
2560
3081
  // src/commands/generate/schema.ts
2561
- import { Command as Command5 } from "commander";
2562
- import * as p12 from "@clack/prompts";
2563
- var schema = new Command5("schema").description("generate a schema from a model").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--ai <description>", "design the schema with AI from a natural-language description").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3082
+ import { Command as Command6 } from "commander";
3083
+ import * as p15 from "@clack/prompts";
3084
+ var schema = new Command6("schema").description("generate a schema from a model").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--ai <description>", "design the schema with AI from a natural-language description").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2564
3085
  (model, fields, options) => runCommand(async () => {
2565
3086
  let argv;
2566
3087
  let modelName;
@@ -2570,7 +3091,7 @@ var schema = new Command5("schema").description("generate a schema from a model"
2570
3091
  }
2571
3092
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "schema" });
2572
3093
  if (!stage2) {
2573
- p12.cancel("Aborted before any files were written.");
3094
+ p15.cancel("Aborted before any files were written.");
2574
3095
  return;
2575
3096
  }
2576
3097
  argv = specToArgv(stage2.model);
@@ -2603,8 +3124,8 @@ var schema = new Command5("schema").description("generate a schema from a model"
2603
3124
  );
2604
3125
 
2605
3126
  // src/commands/generate/resource.ts
2606
- import { Command as Command6 } from "commander";
2607
- var resource = new Command6("resource").description("generate a resource (model + CRUD pages)").argument("<model>", "model name").argument("[fields...]", "field definitions").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3127
+ import { Command as Command7 } from "commander";
3128
+ var resource = new Command7("resource").description("generate a resource (model + CRUD pages)").argument("<model>", "model name").argument("[fields...]", "field definitions").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2608
3129
  (model, fields) => runCommand(
2609
3130
  () => runPattern(
2610
3131
  "generate-resource",
@@ -2629,9 +3150,9 @@ var resource = new Command6("resource").description("generate a resource (model
2629
3150
  );
2630
3151
 
2631
3152
  // src/commands/generate/scaffold.ts
2632
- import { Command as Command7 } from "commander";
2633
- import * as p13 from "@clack/prompts";
2634
- var scaffold = new Command7("scaffold").description("generate a full CRUD scaffold (model, forms, list, detail)").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--remote", "generate a scaffold backed by a remote PocketBase collection").option(
3153
+ import { Command as Command8 } from "commander";
3154
+ import * as p16 from "@clack/prompts";
3155
+ var scaffold = new Command8("scaffold").description("generate a full CRUD scaffold (model, forms, list, detail)").argument("[model]", "model name").argument("[fields...]", "field definitions").option("--remote", "generate a scaffold backed by a remote PocketBase collection").option(
2635
3156
  "--route <route>",
2636
3157
  'place the scaffold at a custom route (e.g. "(app)/[team_id]/projects"). Defaults to the pluralized model name under (app)/(public).'
2637
3158
  ).option(
@@ -2648,12 +3169,12 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2648
3169
  }
2649
3170
  const stage2 = await runSchemaStage({ prompt: options.ai, useCase: "scaffold" });
2650
3171
  if (!stage2) {
2651
- p13.cancel("Aborted before any files were written.");
3172
+ p16.cancel("Aborted before any files were written.");
2652
3173
  return;
2653
3174
  }
2654
3175
  const layout = await runLayoutStage(stage2.workspaceRootDir, stage2.model);
2655
3176
  if (!layout) {
2656
- p13.cancel("Aborted before any files were written.");
3177
+ p16.cancel("Aborted before any files were written.");
2657
3178
  return;
2658
3179
  }
2659
3180
  argv = specToArgv(stage2.model);
@@ -2695,8 +3216,8 @@ var scaffold = new Command7("scaffold").description("generate a full CRUD scaffo
2695
3216
  );
2696
3217
 
2697
3218
  // src/commands/generate/migration.ts
2698
- import { Command as Command8 } from "commander";
2699
- var migration = new Command8("migration").description("generate a migration for an existing collection").argument("<collection>", "collection name").argument("<op>", "operation (add, remove, rename, references)").argument("[args...]", 'operation arguments (e.g. "birthday:date")').allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3219
+ import { Command as Command9 } from "commander";
3220
+ var migration = new Command9("migration").description("generate a migration for an existing collection").argument("<collection>", "collection name").argument("<op>", "operation (add, remove, rename, references)").argument("[args...]", 'operation arguments (e.g. "birthday:date")').allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2700
3221
  (collection, op, args) => runCommand(
2701
3222
  () => runPattern(
2702
3223
  "generate-migration",
@@ -2720,14 +3241,45 @@ var migration = new Command8("migration").description("generate a migration for
2720
3241
  );
2721
3242
 
2722
3243
  // src/commands/generate.ts
2723
- var generate = new Command9("generate").description("generate scaffolding for database models and forms").configureHelp(helpConfig).addCommand(form).addCommand(schema).addCommand(resource).addCommand(scaffold).addCommand(migration);
3244
+ var generate = new Command10("generate").description("generate scaffolding for database models and forms").configureHelp(helpConfig).addCommand(form).addCommand(schema).addCommand(resource).addCommand(scaffold).addCommand(migration);
2724
3245
 
2725
3246
  // src/commands/enable.ts
2726
- import { Command as Command24 } from "commander";
3247
+ import { Command as Command26 } from "commander";
3248
+
3249
+ // src/commands/enable/analytics.ts
3250
+ import { Command as Command11 } from "commander";
3251
+ var analytics = new Command11("analytics").description("enable web analytics (Plausible, Google Analytics or PostHog)").option("--provider <provider>", "analytics provider: plausible, google or posthog").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3252
+ (opts, cmd) => runCommand(async () => {
3253
+ const provider = await resolveProvider("enable-analytics", opts.provider);
3254
+ const providerEnv = await collectProviderEnv(provider);
3255
+ const blank = missingEnvKeys(provider, providerEnv);
3256
+ await runPattern(
3257
+ "enable-analytics",
3258
+ cmd.args,
3259
+ { provider: provider.id, providerEnv },
3260
+ {
3261
+ summary: `Enabled analytics with ${provider.label}.`,
3262
+ nextSteps: [
3263
+ ...blank.map(
3264
+ (key) => `Set ${key} in .env; the analytics component renders nothing until it is set.`
3265
+ ),
3266
+ `Run \`vela dev\` and look for a page view in ${provider.label}.`,
3267
+ "Set the same PUBLIC_* variables on each deploy target with `vela env set`.",
3268
+ "The component lives in src/lib/components/analytics/analytics.svelte; edit it freely."
3269
+ ],
3270
+ task: {
3271
+ title: "Enabling analytics",
3272
+ success: `Enabled analytics with ${provider.label}`,
3273
+ error: "Failed to enable analytics"
3274
+ }
3275
+ }
3276
+ );
3277
+ }, "Failed to enable analytics.")
3278
+ );
2727
3279
 
2728
3280
  // src/commands/enable/auth.ts
2729
- import { Command as Command10 } from "commander";
2730
- var auth = new Command10("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3281
+ import { Command as Command12 } from "commander";
3282
+ var auth = new Command12("auth").description("enable authentication (email/password + OAuth scaffold)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2731
3283
  (_opts, cmd) => runCommand(
2732
3284
  () => runPattern(
2733
3285
  "enable-auth",
@@ -2752,8 +3304,8 @@ var auth = new Command10("auth").description("enable authentication (email/passw
2752
3304
  );
2753
3305
 
2754
3306
  // src/commands/enable/api.ts
2755
- import { Command as Command11 } from "commander";
2756
- var api = new Command11("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3307
+ import { Command as Command13 } from "commander";
3308
+ var api = new Command13("api").description("enable the PocketBase REST API").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2757
3309
  (_opts, cmd) => runCommand(
2758
3310
  () => runPattern(
2759
3311
  "enable-api",
@@ -2778,8 +3330,8 @@ var api = new Command11("api").description("enable the PocketBase REST API").all
2778
3330
  );
2779
3331
 
2780
3332
  // src/commands/enable/api-keys.ts
2781
- import { Command as Command12 } from "commander";
2782
- var apiKeys = new Command12("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3333
+ import { Command as Command14 } from "commander";
3334
+ var apiKeys = new Command14("api-keys").description("enable API key management").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2783
3335
  (_opts, cmd) => runCommand(
2784
3336
  () => runPattern(
2785
3337
  "enable-api-keys",
@@ -2804,8 +3356,8 @@ var apiKeys = new Command12("api-keys").description("enable API key management")
2804
3356
  );
2805
3357
 
2806
3358
  // src/commands/enable/backend.ts
2807
- import { Command as Command13 } from "commander";
2808
- var backend = new Command13("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3359
+ import { Command as Command15 } from "commander";
3360
+ var backend = new Command15("backend").description("enable the PocketBase backend").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2809
3361
  (_opts, cmd) => runCommand(
2810
3362
  () => runPattern(
2811
3363
  "enable-backend",
@@ -2830,8 +3382,8 @@ var backend = new Command13("backend").description("enable the PocketBase backen
2830
3382
  );
2831
3383
 
2832
3384
  // src/commands/enable/i18n.ts
2833
- import { Command as Command14 } from "commander";
2834
- var i18n = new Command14("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3385
+ import { Command as Command16 } from "commander";
3386
+ var i18n = new Command16("i18n").description("enable internationalization").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2835
3387
  (_opts, cmd) => runCommand(
2836
3388
  () => runPattern(
2837
3389
  "enable-i18n",
@@ -2856,8 +3408,8 @@ var i18n = new Command14("i18n").description("enable internationalization").allo
2856
3408
  );
2857
3409
 
2858
3410
  // src/commands/enable/teams.ts
2859
- import { Command as Command15 } from "commander";
2860
- var teams = new Command15("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3411
+ import { Command as Command17 } from "commander";
3412
+ var teams = new Command17("teams").description("enable team / multi-tenant support").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2861
3413
  (_opts, cmd) => runCommand(
2862
3414
  () => runPattern(
2863
3415
  "enable-teams",
@@ -2882,13 +3434,13 @@ var teams = new Command15("teams").description("enable team / multi-tenant suppo
2882
3434
  );
2883
3435
 
2884
3436
  // src/commands/enable/payments.ts
2885
- import process9 from "node:process";
2886
- import { Command as Command16 } from "commander";
2887
- import * as p14 from "@clack/prompts";
3437
+ import process12 from "node:process";
3438
+ import { Command as Command18 } from "commander";
3439
+ import * as p17 from "@clack/prompts";
2888
3440
  var PROVIDERS = [{ value: "stripe", label: "Stripe" }];
2889
- var payments = new Command16("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3441
+ var payments = new Command18("payments").description("enable payments").option("--provider <provider>", "payment provider", "stripe").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2890
3442
  (opts, cmd) => runCommand(async () => {
2891
- const provider = await resolveProvider(opts.provider, cmd.getOptionValueSource("provider"));
3443
+ const provider = await resolveProvider2(opts.provider, cmd.getOptionValueSource("provider"));
2892
3444
  const input = {
2893
3445
  provider,
2894
3446
  stripeSecretKey: await ensureKey("STRIPE_SECRET_KEY", "Stripe secret key (sk_...)"),
@@ -2914,28 +3466,28 @@ var payments = new Command16("payments").description("enable payments").option("
2914
3466
  });
2915
3467
  }, "Failed to enable payments.")
2916
3468
  );
2917
- async function resolveProvider(value, source) {
3469
+ async function resolveProvider2(value, source) {
2918
3470
  if (source && source !== "default") {
2919
3471
  if (!PROVIDERS.some((o) => o.value === value)) {
2920
3472
  throw new Error(`Unknown payment provider: ${value}`);
2921
3473
  }
2922
3474
  return value;
2923
3475
  }
2924
- const selected = await p14.select({
3476
+ const selected = await p17.select({
2925
3477
  message: "Which payment provider?",
2926
3478
  options: PROVIDERS,
2927
3479
  initialValue: "stripe"
2928
3480
  });
2929
- if (p14.isCancel(selected)) {
2930
- p14.cancel("Operation cancelled.");
2931
- process9.exit(0);
3481
+ if (p17.isCancel(selected)) {
3482
+ p17.cancel("Operation cancelled.");
3483
+ process12.exit(0);
2932
3484
  }
2933
3485
  return selected;
2934
3486
  }
2935
3487
  async function ensureWebhookSecret() {
2936
- const existing = process9.env.STRIPE_WEBHOOK_SECRET;
3488
+ const existing = process12.env.STRIPE_WEBHOOK_SECRET;
2937
3489
  if (existing) return existing;
2938
- p14.note(
3490
+ p17.note(
2939
3491
  [
2940
3492
  "Download the Stripe CLI (https://stripe.com/docs/stripe-cli), then run:",
2941
3493
  " stripe listen --forward-to localhost:5173/webhooks/stripe",
@@ -2947,7 +3499,7 @@ async function ensureWebhookSecret() {
2947
3499
  return promptPassword("Stripe webhook signing secret (whsec_...)");
2948
3500
  }
2949
3501
  async function ensurePriceId() {
2950
- p14.note(
3502
+ p17.note(
2951
3503
  [
2952
3504
  "Stripe checkout requires a product and price_id.",
2953
3505
  "If you have a demo product price_id, enter it below, or leave blank to create a demo one for you."
@@ -2955,36 +3507,36 @@ async function ensurePriceId() {
2955
3507
  "Stripe demo product",
2956
3508
  { format: (line) => line }
2957
3509
  );
2958
- const value = await p14.text({
3510
+ const value = await p17.text({
2959
3511
  message: "Stripe price_id (price_...)",
2960
3512
  placeholder: "leave blank to create a demo product"
2961
3513
  });
2962
- if (p14.isCancel(value)) {
2963
- p14.cancel("Operation cancelled.");
2964
- process9.exit(0);
3514
+ if (p17.isCancel(value)) {
3515
+ p17.cancel("Operation cancelled.");
3516
+ process12.exit(0);
2965
3517
  }
2966
3518
  return (value ?? "").trim();
2967
3519
  }
2968
3520
  async function ensureKey(envVar, message) {
2969
- const existing = process9.env[envVar];
3521
+ const existing = process12.env[envVar];
2970
3522
  if (existing) return existing;
2971
3523
  return promptPassword(message);
2972
3524
  }
2973
3525
  async function promptPassword(message) {
2974
- const value = await p14.password({
3526
+ const value = await p17.password({
2975
3527
  message,
2976
3528
  validate: (v10) => v10 && v10.length ? void 0 : "Required"
2977
3529
  });
2978
- if (p14.isCancel(value)) {
2979
- p14.cancel("Operation cancelled.");
2980
- process9.exit(0);
3530
+ if (p17.isCancel(value)) {
3531
+ p17.cancel("Operation cancelled.");
3532
+ process12.exit(0);
2981
3533
  }
2982
3534
  return value;
2983
3535
  }
2984
3536
 
2985
3537
  // src/commands/enable/subscriptions.ts
2986
- import { Command as Command17 } from "commander";
2987
- var subscriptions = new Command17("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3538
+ import { Command as Command19 } from "commander";
3539
+ var subscriptions = new Command19("subscriptions").description("enable Stripe subscriptions (requires auth and payments)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
2988
3540
  (_opts, cmd) => runCommand(
2989
3541
  () => runPattern(
2990
3542
  "enable-subscriptions",
@@ -3009,8 +3561,8 @@ var subscriptions = new Command17("subscriptions").description("enable Stripe su
3009
3561
  );
3010
3562
 
3011
3563
  // src/commands/enable/notifications.ts
3012
- import { Command as Command18 } from "commander";
3013
- var notifications = new Command18("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3564
+ import { Command as Command20 } from "commander";
3565
+ var notifications = new Command20("notifications").description("enable in-app notifications with a bell dropdown (requires auth)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
3014
3566
  (_opts, cmd) => runCommand(
3015
3567
  () => runPattern(
3016
3568
  "enable-notifications",
@@ -3035,15 +3587,15 @@ var notifications = new Command18("notifications").description("enable in-app no
3035
3587
  );
3036
3588
 
3037
3589
  // src/commands/enable/s3.ts
3038
- import process13 from "node:process";
3039
- import { Command as Command19 } from "commander";
3040
- import * as p17 from "@clack/prompts";
3590
+ import process16 from "node:process";
3591
+ import { Command as Command21 } from "commander";
3592
+ import * as p20 from "@clack/prompts";
3041
3593
  import pc8 from "picocolors";
3042
3594
 
3043
3595
  // src/lib/server-command.ts
3044
- import process12 from "node:process";
3596
+ import process15 from "node:process";
3045
3597
  import * as v6 from "valibot";
3046
- import * as p15 from "@clack/prompts";
3598
+ import * as p18 from "@clack/prompts";
3047
3599
  import pc5 from "picocolors";
3048
3600
 
3049
3601
  // src/lib/deploy-config.ts
@@ -3217,10 +3769,10 @@ import { resolveCommand as resolveCommand4 } from "package-manager-detector/comm
3217
3769
 
3218
3770
  // src/lib/ssh.ts
3219
3771
  import fs20 from "node:fs";
3220
- import os3 from "node:os";
3772
+ import os4 from "node:os";
3221
3773
  import path19 from "node:path";
3222
3774
  import crypto3 from "node:crypto";
3223
- import process10 from "node:process";
3775
+ import process13 from "node:process";
3224
3776
  import { spawn as spawn2 } from "node:child_process";
3225
3777
  var RemoteCommandError = class extends Error {
3226
3778
  exitCode;
@@ -3261,7 +3813,7 @@ var SshSession = class {
3261
3813
  }
3262
3814
  async open() {
3263
3815
  if (this.controlPath) return;
3264
- const dir = path19.join(os3.tmpdir(), "vela-ssh");
3816
+ const dir = path19.join(os4.tmpdir(), "vela-ssh");
3265
3817
  fs20.mkdirSync(dir, { recursive: true, mode: 448 });
3266
3818
  const socket = path19.join(dir, `${crypto3.randomBytes(6).toString("hex")}.sock`);
3267
3819
  this.controlPath = socket;
@@ -3498,17 +4050,17 @@ function spawnCapture(command, args, opts = {}) {
3498
4050
  const child = spawn2(command, args, {
3499
4051
  stdio,
3500
4052
  cwd: opts.cwd,
3501
- env: opts.env ? { ...process10.env, ...opts.env } : void 0
4053
+ env: opts.env ? { ...process13.env, ...opts.env } : void 0
3502
4054
  });
3503
4055
  let stdout = "";
3504
4056
  let stderr = "";
3505
4057
  child.stdout?.on("data", (chunk) => {
3506
4058
  stdout += chunk;
3507
- if (opts.streamStdout) process10.stdout.write(chunk);
4059
+ if (opts.streamStdout) process13.stdout.write(chunk);
3508
4060
  });
3509
4061
  child.stderr?.on("data", (chunk) => {
3510
4062
  stderr += chunk;
3511
- if (opts.stream) process10.stderr.write(chunk);
4063
+ if (opts.stream) process13.stderr.write(chunk);
3512
4064
  });
3513
4065
  child.on("error", reject);
3514
4066
  child.on("close", (code) => resolve2({ stdout, stderr, exitCode: code ?? 1 }));
@@ -3615,7 +4167,7 @@ function sshOptionsFrom(options) {
3615
4167
  import crypto4 from "node:crypto";
3616
4168
  import fs22 from "node:fs";
3617
4169
  import path21 from "node:path";
3618
- import process11 from "node:process";
4170
+ import process14 from "node:process";
3619
4171
  var VELA_ROOT = "/var/lib/vela";
3620
4172
  var VELA_ETC = "/etc/vela";
3621
4173
  var VELA_USER = "vela";
@@ -3652,7 +4204,7 @@ async function syncServerScripts(session) {
3652
4204
  const dir = `${SCRIPT_VERSIONS_DIR}/${digest}`;
3653
4205
  const present = await session.script(`[ -d "$1" ] && echo yes || echo no`, { args: [dir] });
3654
4206
  if (present.stdout.trim() !== "yes") {
3655
- const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process11.pid}.${Date.now()}`;
4207
+ const incoming = `${SCRIPT_VERSIONS_DIR}/.incoming.${digest}.${process14.pid}.${Date.now()}`;
3656
4208
  await session.script(`mkdir -p "$1" && chmod 0755 "$(dirname "$1")" "$1"`, {
3657
4209
  args: [incoming]
3658
4210
  });
@@ -3911,8 +4463,8 @@ function describeTarget(target) {
3911
4463
  return target.name;
3912
4464
  }
3913
4465
  }
3914
- function bold(text18) {
3915
- return `\`${text18}\``;
4466
+ function bold(text19) {
4467
+ return `\`${text19}\``;
3916
4468
  }
3917
4469
 
3918
4470
  // src/lib/server-command.ts
@@ -4016,7 +4568,7 @@ async function ensureBinding(workspaceRootDir, target, request = {}) {
4016
4568
  writeBinding(workspaceRootDir, key, binding);
4017
4569
  }
4018
4570
  if (moving) {
4019
- p15.log.warn(
4571
+ p18.log.warn(
4020
4572
  `${pc5.cyan(bindingName(target))} now points at ${pc5.cyan(server)}.
4021
4573
 
4022
4574
  Whatever is running on ${existing.server} is left there, and this project can no
@@ -4027,7 +4579,7 @@ longer reach it. Remove it there first if that was not intended.`
4027
4579
  }
4028
4580
  async function confirmMove(target, from, to) {
4029
4581
  const name = bindingName(target);
4030
- if (!process12.stdout.isTTY || process12.env.CI) {
4582
+ if (!process15.stdout.isTTY || process15.env.CI) {
4031
4583
  throw new Error(
4032
4584
  `${pc5.cyan(`--server ${to}`)} does not match the server recorded for ${pc5.cyan(name)}, ${pc5.cyan(from)}.
4033
4585
 
@@ -4035,13 +4587,13 @@ Drop ${pc5.cyan("--server")} to use the recorded one, or move the binding on pur
4035
4587
  this command once from a terminal (or editing .vela/project.json).`
4036
4588
  );
4037
4589
  }
4038
- const ok = await p15.confirm({
4590
+ const ok = await p18.confirm({
4039
4591
  message: `${name} ${target.kind === "preview" ? "run" : "runs"} on ${from}. Point ${name} at ${to} instead?`,
4040
4592
  initialValue: false
4041
4593
  });
4042
- if (p15.isCancel(ok) || !ok) {
4043
- p15.cancel("Operation cancelled.");
4044
- process12.exit(0);
4594
+ if (p18.isCancel(ok) || !ok) {
4595
+ p18.cancel("Operation cancelled.");
4596
+ process15.exit(0);
4045
4597
  }
4046
4598
  }
4047
4599
  function bindingName(target) {
@@ -4049,7 +4601,7 @@ function bindingName(target) {
4049
4601
  }
4050
4602
  async function promptServer(target) {
4051
4603
  const name = bindingName(target);
4052
- if (!process12.stdout.isTTY || process12.env.CI) {
4604
+ if (!process15.stdout.isTTY || process15.env.CI) {
4053
4605
  throw new Error(
4054
4606
  `${name} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet, and there is no terminal to ask on.
4055
4607
 
@@ -4057,29 +4609,29 @@ Pass ${pc5.cyan("--server user@host")}, or run the command once from your own ma
4057
4609
  and commit ${pc5.cyan(".vela/project.json")}.`
4058
4610
  );
4059
4611
  }
4060
- p15.log.info(
4612
+ p18.log.info(
4061
4613
  `${pc5.cyan(name)} ${target.kind === "preview" ? "are" : "is"} not bound to a server yet.`
4062
4614
  );
4063
- const value = await p15.text({
4615
+ const value = await p18.text({
4064
4616
  message: `Which server should ${name} run on?`,
4065
4617
  placeholder: "root@203.0.113.10",
4066
4618
  validate: (input) => input?.trim() ? void 0 : "An ssh_config alias, or user@host"
4067
4619
  });
4068
- if (p15.isCancel(value)) {
4069
- p15.cancel("Operation cancelled.");
4070
- process12.exit(0);
4620
+ if (p18.isCancel(value)) {
4621
+ p18.cancel("Operation cancelled.");
4622
+ process15.exit(0);
4071
4623
  }
4072
4624
  return value.trim();
4073
4625
  }
4074
4626
  async function promptDomain(target) {
4075
- if (!process12.stdout.isTTY || process12.env.CI) return void 0;
4076
- const value = await p15.text({
4627
+ if (!process15.stdout.isTTY || process15.env.CI) return void 0;
4628
+ const value = await p18.text({
4077
4629
  message: `Which hostname should ${target.name} be served on?`,
4078
4630
  placeholder: "example.com \u2014 leave blank to decide later"
4079
4631
  });
4080
- if (p15.isCancel(value)) {
4081
- p15.cancel("Operation cancelled.");
4082
- process12.exit(0);
4632
+ if (p18.isCancel(value)) {
4633
+ p18.cancel("Operation cancelled.");
4634
+ process15.exit(0);
4083
4635
  }
4084
4636
  return value.trim() || void 0;
4085
4637
  }
@@ -4087,10 +4639,10 @@ async function applyRestart(ctx) {
4087
4639
  const outcome = await restartInstance(ctx.session, ctx.instance);
4088
4640
  if (!outcome.deployed) return;
4089
4641
  if (outcome.restarted) {
4090
- p15.log.success("App restarted");
4642
+ p18.log.success("App restarted");
4091
4643
  return;
4092
4644
  }
4093
- p15.log.error(
4645
+ p18.log.error(
4094
4646
  `App restart failed.
4095
4647
 
4096
4648
  The new value is stored and will be used the next time the app starts.
@@ -4099,7 +4651,7 @@ ${pc5.dim(outcome.error ?? "")}`
4099
4651
  }
4100
4652
  async function applyEnvRestart(ctx, changed) {
4101
4653
  if (touchesSuperuser(changed)) {
4102
- p15.log.warn(
4654
+ p18.log.warn(
4103
4655
  `PocketBase superuser credentials changed.
4104
4656
 
4105
4657
  The database still holds the old ones, so the app has not been restarted.
@@ -4136,7 +4688,7 @@ import pc7 from "picocolors";
4136
4688
 
4137
4689
  // src/lib/local-env.ts
4138
4690
  import fs24 from "node:fs";
4139
- import * as p16 from "@clack/prompts";
4691
+ import * as p19 from "@clack/prompts";
4140
4692
  import pc6 from "picocolors";
4141
4693
  function readLocalEnv(envFile) {
4142
4694
  if (!fs24.existsSync(envFile)) return {};
@@ -4162,16 +4714,16 @@ async function applyLocalEnvChange(ctx, changed) {
4162
4714
  process.env.POCKETBASE_SUPERUSER_EMAIL = email3;
4163
4715
  process.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
4164
4716
  await ensureSuperuser(ctx.workspaceRootDir);
4165
- p16.log.success("Local superuser updated to match");
4717
+ p19.log.success("Local superuser updated to match");
4166
4718
  } else {
4167
- p16.log.warn(
4719
+ p19.log.warn(
4168
4720
  `The local database still has the old superuser.
4169
4721
  Set both ${pc6.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc6.cyan("POCKETBASE_SUPERUSER_PASSWORD")} to reconcile it.`
4170
4722
  );
4171
4723
  }
4172
4724
  }
4173
4725
  if (getPocketbaseMetadata(ctx.workspaceRootDir)) {
4174
- p16.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4726
+ p19.log.info(`Restart ${pc6.cyan("vela dev")} to pick this up.`);
4175
4727
  }
4176
4728
  }
4177
4729
 
@@ -4335,7 +4887,7 @@ function hasFile(dir) {
4335
4887
 
4336
4888
  // src/commands/enable/s3.ts
4337
4889
  var s3 = addTargetOptions(
4338
- new Command19("s3").description("enable S3 file storage").option("--backups", "configure where backups are kept, not where uploads go").option("--endpoint <url>", "S3 endpoint URL").option("--bucket <name>", "S3 bucket name").option("--region <region>", "S3 region").option("--access-key <key>", "S3 access key").option("--secret <secret>", "S3 secret key \u2014 prefer VELA_S3_SECRET").option("--force-path-style", "address the bucket in the path (MinIO, Ceph)").option("--no-force-path-style", "address the bucket as a subdomain (AWS, R2)").option("--force", "enable it even though uploads already exist on disk").configureHelp(helpConfig),
4890
+ new Command21("s3").description("enable S3 file storage").option("--backups", "configure where backups are kept, not where uploads go").option("--endpoint <url>", "S3 endpoint URL").option("--bucket <name>", "S3 bucket name").option("--region <region>", "S3 region").option("--access-key <key>", "S3 access key").option("--secret <secret>", "S3 secret key \u2014 prefer VELA_S3_SECRET").option("--force-path-style", "address the bucket in the path (MinIO, Ceph)").option("--no-force-path-style", "address the bucket as a subdomain (AWS, R2)").option("--force", "enable it even though uploads already exist on disk").configureHelp(helpConfig),
4339
4891
  "local"
4340
4892
  ).action(
4341
4893
  (raw) => runCommand(() => {
@@ -4353,7 +4905,7 @@ var s3 = addTargetOptions(
4353
4905
  failure = error instanceof Error ? error.message : String(error);
4354
4906
  }
4355
4907
  if (failure) {
4356
- p17.log.warn(
4908
+ p20.log.warn(
4357
4909
  `The connection test failed \u2014 the settings are saved but may be wrong.
4358
4910
 
4359
4911
  ${pc8.dim(failure)}
@@ -4397,64 +4949,64 @@ Do that first, then re-run with ${pc8.cyan("--force")}.`
4397
4949
  );
4398
4950
  }
4399
4951
  async function promptConfig(options, existing) {
4400
- const endpoint = options.endpoint ?? await text7("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4401
- const bucket = options.bucket ?? await text7("S3 bucket name", existing.bucket);
4402
- const region = options.region ?? await text7("S3 region", existing.region || "us-east-1");
4403
- const accessKey = options.accessKey ?? await text7("S3 access key", existing.accessKey);
4404
- const secret = options.secret ?? process13.env.VELA_S3_SECRET ?? await password5("S3 secret key");
4952
+ const endpoint = options.endpoint ?? await text9("S3 endpoint URL", existing.endpoint || "https://s3.amazonaws.com");
4953
+ const bucket = options.bucket ?? await text9("S3 bucket name", existing.bucket);
4954
+ const region = options.region ?? await text9("S3 region", existing.region || "us-east-1");
4955
+ const accessKey = options.accessKey ?? await text9("S3 access key", existing.accessKey);
4956
+ const secret = options.secret ?? process16.env.VELA_S3_SECRET ?? await password6("S3 secret key");
4405
4957
  const forcePathStyle = options.forcePathStyle ?? await confirm4(
4406
4958
  "Address the bucket in the path? (MinIO, Ceph and most self-hosted gateways need this)",
4407
4959
  defaultForcePathStyle(endpoint)
4408
4960
  );
4409
4961
  return { endpoint, bucket, region, accessKey, secret, forcePathStyle };
4410
4962
  }
4411
- async function text7(message, initialValue = "") {
4412
- const value = await p17.text({
4963
+ async function text9(message, initialValue = "") {
4964
+ const value = await p20.text({
4413
4965
  message,
4414
4966
  initialValue,
4415
4967
  validate: (input) => input?.trim() ? void 0 : `${message} is required`
4416
4968
  });
4417
- if (p17.isCancel(value)) {
4418
- p17.cancel("Operation cancelled.");
4419
- process13.exit(0);
4969
+ if (p20.isCancel(value)) {
4970
+ p20.cancel("Operation cancelled.");
4971
+ process16.exit(0);
4420
4972
  }
4421
4973
  return value.trim();
4422
4974
  }
4423
- async function password5(message) {
4424
- const value = await p17.password({
4975
+ async function password6(message) {
4976
+ const value = await p20.password({
4425
4977
  message,
4426
4978
  validate: (input) => input ? void 0 : `${message} is required`
4427
4979
  });
4428
- if (p17.isCancel(value)) {
4429
- p17.cancel("Operation cancelled.");
4430
- process13.exit(0);
4980
+ if (p20.isCancel(value)) {
4981
+ p20.cancel("Operation cancelled.");
4982
+ process16.exit(0);
4431
4983
  }
4432
4984
  return value;
4433
4985
  }
4434
4986
  async function confirm4(message, initialValue) {
4435
- const value = await p17.confirm({ message, initialValue });
4436
- if (p17.isCancel(value)) {
4437
- p17.cancel("Operation cancelled.");
4438
- process13.exit(0);
4987
+ const value = await p20.confirm({ message, initialValue });
4988
+ if (p20.isCancel(value)) {
4989
+ p20.cancel("Operation cancelled.");
4990
+ process16.exit(0);
4439
4991
  }
4440
4992
  return value;
4441
4993
  }
4442
4994
 
4443
4995
  // src/commands/enable/smtp.ts
4444
- import process14 from "node:process";
4445
- import { Command as Command20 } from "commander";
4446
- import * as p18 from "@clack/prompts";
4447
- var smtp = new Command20("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4996
+ import process17 from "node:process";
4997
+ import { Command as Command22 } from "commander";
4998
+ import * as p21 from "@clack/prompts";
4999
+ var smtp = new Command22("smtp").description("configure SMTP for transactional email").configureHelp(helpConfig).action(
4448
5000
  () => runCommand(async () => {
4449
5001
  const { workspaceRootDir } = await getWorkspace();
4450
- const config = await p18.group(
5002
+ const config = await p21.group(
4451
5003
  {
4452
- host: () => p18.text({
5004
+ host: () => p21.text({
4453
5005
  message: "SMTP host",
4454
5006
  placeholder: "smtp.example.com",
4455
5007
  validate: (v10) => v10 ? void 0 : "Host is required"
4456
5008
  }),
4457
- port: () => p18.text({
5009
+ port: () => p21.text({
4458
5010
  message: "SMTP port",
4459
5011
  initialValue: "587",
4460
5012
  validate: (v10) => {
@@ -4464,13 +5016,13 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
4464
5016
  return void 0;
4465
5017
  }
4466
5018
  }),
4467
- username: () => p18.text({ message: "SMTP username" }),
4468
- password: () => p18.password({ message: "SMTP password" })
5019
+ username: () => p21.text({ message: "SMTP username" }),
5020
+ password: () => p21.password({ message: "SMTP password" })
4469
5021
  },
4470
5022
  {
4471
5023
  onCancel: () => {
4472
- p18.cancel("Operation cancelled.");
4473
- process14.exit(0);
5024
+ p21.cancel("Operation cancelled.");
5025
+ process17.exit(0);
4474
5026
  }
4475
5027
  }
4476
5028
  );
@@ -4497,24 +5049,24 @@ var smtp = new Command20("smtp").description("configure SMTP for transactional e
4497
5049
  );
4498
5050
 
4499
5051
  // src/commands/enable/cms.ts
4500
- import process15 from "node:process";
4501
- import { Command as Command21 } from "commander";
4502
- import * as p19 from "@clack/prompts";
5052
+ import process18 from "node:process";
5053
+ import { Command as Command23 } from "commander";
5054
+ import * as p22 from "@clack/prompts";
4503
5055
  import pc9 from "picocolors";
4504
- var cms = new Command21("cms").description("enable an inline-editing CMS with an admin bar").option(
5056
+ var cms = new Command23("cms").description("enable an inline-editing CMS with an admin bar").option(
4505
5057
  "--endpoint <url>",
4506
5058
  "read from a hosted CMS at this URL instead of installing the backend in this app"
4507
5059
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4508
5060
  (opts, cmd) => runCommand(async () => {
4509
5061
  if (!opts.endpoint && !hasBackend()) {
4510
- p19.log.error(
5062
+ p22.log.error(
4511
5063
  `${pc9.cyan("vela enable cms")} needs a server to host the CMS backend, and this project is static.
4512
5064
 
4513
5065
  Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${pc9.cyan("vela enable cms --endpoint <url>")}.`
4514
5066
  );
4515
- p19.log.message();
4516
- p19.cancel("Operation failed.");
4517
- process15.exitCode = 1;
5067
+ p22.log.message();
5068
+ p22.cancel("Operation failed.");
5069
+ process18.exitCode = 1;
4518
5070
  return;
4519
5071
  }
4520
5072
  await runPattern("enable-cms", cmd.args, opts.endpoint ? { endpoint: opts.endpoint } : {}, {
@@ -4534,8 +5086,8 @@ Run ${pc9.cyan("vela bless")} to add a backend, or point at a hosted CMS with ${
4534
5086
  );
4535
5087
 
4536
5088
  // src/commands/enable/blog.ts
4537
- import { Command as Command22 } from "commander";
4538
- var blog = new Command22("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5089
+ import { Command as Command24 } from "commander";
5090
+ var blog = new Command24("blog").description("enable an mdsvex blog with posts, tags, and RSS").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4539
5091
  (_opts, cmd) => runCommand(
4540
5092
  () => runPattern(
4541
5093
  "enable-blog",
@@ -4560,8 +5112,8 @@ var blog = new Command22("blog").description("enable an mdsvex blog with posts,
4560
5112
  );
4561
5113
 
4562
5114
  // src/commands/enable/content-negotiation.ts
4563
- import { Command as Command23 } from "commander";
4564
- var contentNegotiation = new Command23("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5115
+ import { Command as Command25 } from "commander";
5116
+ var contentNegotiation = new Command25("content-negotiation").description("enable content negotiation (sveltekit-negotiate)").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4565
5117
  (_opts, cmd) => runCommand(
4566
5118
  () => runPattern(
4567
5119
  "enable-content-negotiation",
@@ -4585,33 +5137,33 @@ var contentNegotiation = new Command23("content-negotiation").description("enabl
4585
5137
  );
4586
5138
 
4587
5139
  // src/commands/enable.ts
4588
- var enable = new Command24("enable").description("enable features").configureHelp(helpConfig).addCommand(auth).addCommand(api).addCommand(apiKeys).addCommand(backend).addCommand(contentNegotiation).addCommand(i18n).addCommand(teams).addCommand(payments).addCommand(subscriptions).addCommand(notifications).addCommand(s3).addCommand(smtp).addCommand(cms).addCommand(blog);
5140
+ var enable = new Command26("enable").description("enable features").configureHelp(helpConfig).addCommand(analytics).addCommand(auth).addCommand(api).addCommand(apiKeys).addCommand(backend).addCommand(contentNegotiation).addCommand(i18n).addCommand(teams).addCommand(payments).addCommand(subscriptions).addCommand(notifications).addCommand(s3).addCommand(smtp).addCommand(cms).addCommand(blog);
4589
5141
 
4590
5142
  // src/commands/disable.ts
4591
- import { Command as Command35 } from "commander";
5143
+ import { Command as Command37 } from "commander";
4592
5144
 
4593
5145
  // src/commands/disable/auth.ts
4594
- import { Command as Command25 } from "commander";
5146
+ import { Command as Command27 } from "commander";
4595
5147
 
4596
5148
  // src/commands/disable/_shared.ts
4597
- import process16 from "node:process";
4598
- import * as p20 from "@clack/prompts";
5149
+ import process19 from "node:process";
5150
+ import * as p23 from "@clack/prompts";
4599
5151
  async function runDisable(opts, flags, cmdArgs) {
4600
5152
  if (!flags.yes) {
4601
- const ok = await p20.confirm({
5153
+ const ok = await p23.confirm({
4602
5154
  message: opts.confirmMessage,
4603
5155
  initialValue: false
4604
5156
  });
4605
- if (p20.isCancel(ok) || !ok) {
4606
- p20.cancel("Operation cancelled.");
4607
- process16.exit(0);
5157
+ if (p23.isCancel(ok) || !ok) {
5158
+ p23.cancel("Operation cancelled.");
5159
+ process19.exit(0);
4608
5160
  }
4609
5161
  }
4610
5162
  await runPattern(opts.slug, cmdArgs, { destructive: true }, opts.report);
4611
5163
  }
4612
5164
 
4613
5165
  // src/commands/disable/auth.ts
4614
- var auth2 = new Command25("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5166
+ var auth2 = new Command27("auth").description("disable authentication").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4615
5167
  (opts, cmd) => runCommand(
4616
5168
  () => runDisable(
4617
5169
  {
@@ -4637,8 +5189,8 @@ var auth2 = new Command25("auth").description("disable authentication").option("
4637
5189
  );
4638
5190
 
4639
5191
  // src/commands/disable/api.ts
4640
- import { Command as Command26 } from "commander";
4641
- var api2 = new Command26("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5192
+ import { Command as Command28 } from "commander";
5193
+ var api2 = new Command28("api").description("disable the REST API").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4642
5194
  (opts, cmd) => runCommand(
4643
5195
  () => runDisable(
4644
5196
  {
@@ -4661,8 +5213,8 @@ var api2 = new Command26("api").description("disable the REST API").option("-y,
4661
5213
  );
4662
5214
 
4663
5215
  // src/commands/disable/api-keys.ts
4664
- import { Command as Command27 } from "commander";
4665
- var apiKeys2 = new Command27("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5216
+ import { Command as Command29 } from "commander";
5217
+ var apiKeys2 = new Command29("api-keys").description("disable API key management").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4666
5218
  (opts, cmd) => runCommand(
4667
5219
  () => runDisable(
4668
5220
  {
@@ -4685,8 +5237,8 @@ var apiKeys2 = new Command27("api-keys").description("disable API key management
4685
5237
  );
4686
5238
 
4687
5239
  // src/commands/disable/backend.ts
4688
- import { Command as Command28 } from "commander";
4689
- var backend2 = new Command28("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5240
+ import { Command as Command30 } from "commander";
5241
+ var backend2 = new Command30("backend").description("disable the PocketBase backend").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4690
5242
  (opts, cmd) => runCommand(
4691
5243
  () => runDisable(
4692
5244
  {
@@ -4709,8 +5261,8 @@ var backend2 = new Command28("backend").description("disable the PocketBase back
4709
5261
  );
4710
5262
 
4711
5263
  // src/commands/disable/content-negotiation.ts
4712
- import { Command as Command29 } from "commander";
4713
- var contentNegotiation2 = new Command29("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5264
+ import { Command as Command31 } from "commander";
5265
+ var contentNegotiation2 = new Command31("content-negotiation").description("disable content negotiation").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4714
5266
  (opts, cmd) => runCommand(
4715
5267
  () => runDisable(
4716
5268
  {
@@ -4733,8 +5285,8 @@ var contentNegotiation2 = new Command29("content-negotiation").description("disa
4733
5285
  );
4734
5286
 
4735
5287
  // src/commands/disable/i18n.ts
4736
- import { Command as Command30 } from "commander";
4737
- var i18n2 = new Command30("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5288
+ import { Command as Command32 } from "commander";
5289
+ var i18n2 = new Command32("i18n").description("disable internationalization").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4738
5290
  (opts, cmd) => runCommand(
4739
5291
  () => runDisable(
4740
5292
  {
@@ -4760,8 +5312,8 @@ var i18n2 = new Command30("i18n").description("disable internationalization").op
4760
5312
  );
4761
5313
 
4762
5314
  // src/commands/disable/teams.ts
4763
- import { Command as Command31 } from "commander";
4764
- var teams2 = new Command31("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5315
+ import { Command as Command33 } from "commander";
5316
+ var teams2 = new Command33("teams").description("disable teams").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4765
5317
  (opts, cmd) => runCommand(
4766
5318
  () => runDisable(
4767
5319
  {
@@ -4787,8 +5339,8 @@ var teams2 = new Command31("teams").description("disable teams").option("-y, --y
4787
5339
  );
4788
5340
 
4789
5341
  // src/commands/disable/payments.ts
4790
- import { Command as Command32 } from "commander";
4791
- var payments2 = new Command32("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5342
+ import { Command as Command34 } from "commander";
5343
+ var payments2 = new Command34("payments").description("disable payments").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4792
5344
  (opts, cmd) => runCommand(
4793
5345
  () => runDisable(
4794
5346
  {
@@ -4815,11 +5367,11 @@ var payments2 = new Command32("payments").description("disable payments").option
4815
5367
  );
4816
5368
 
4817
5369
  // src/commands/disable/s3.ts
4818
- import { Command as Command33 } from "commander";
4819
- import * as p21 from "@clack/prompts";
5370
+ import { Command as Command35 } from "commander";
5371
+ import * as p24 from "@clack/prompts";
4820
5372
  import pc10 from "picocolors";
4821
5373
  var s32 = addTargetOptions(
4822
- new Command33("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
5374
+ new Command35("s3").description("disable S3 file storage").option("--backups", "keep backups on the server again, rather than uploads").configureHelp(helpConfig),
4823
5375
  "local"
4824
5376
  ).action(
4825
5377
  (raw) => runCommand(() => {
@@ -4828,7 +5380,7 @@ var s32 = addTargetOptions(
4828
5380
  return withBackupTarget(raw, "disable s3", async (ctx) => {
4829
5381
  const existing = await readS3(ctx.pb, filesystem);
4830
5382
  if (!existing.enabled) {
4831
- p21.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
5383
+ p24.log.info(`S3 ${label2(filesystem)} is already off for ${ctx.targetName}.`);
4832
5384
  return;
4833
5385
  }
4834
5386
  await disableS3(ctx.pb, filesystem);
@@ -4848,8 +5400,8 @@ function label2(filesystem) {
4848
5400
  }
4849
5401
 
4850
5402
  // src/commands/disable/smtp.ts
4851
- import { Command as Command34 } from "commander";
4852
- var smtp2 = new Command34("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
5403
+ import { Command as Command36 } from "commander";
5404
+ var smtp2 = new Command36("smtp").description("disable SMTP configuration").configureHelp(helpConfig).action(
4853
5405
  () => runCommand(async () => {
4854
5406
  const { workspaceRootDir } = await getWorkspace();
4855
5407
  await withPocketbase(workspaceRootDir, async (pb) => {
@@ -4866,30 +5418,30 @@ var smtp2 = new Command34("smtp").description("disable SMTP configuration").conf
4866
5418
  );
4867
5419
 
4868
5420
  // src/commands/disable.ts
4869
- var disable = new Command35("disable").description("disable features").configureHelp(helpConfig).addCommand(auth2).addCommand(api2).addCommand(apiKeys2).addCommand(backend2).addCommand(contentNegotiation2).addCommand(i18n2).addCommand(teams2).addCommand(payments2).addCommand(s32).addCommand(smtp2);
5421
+ var disable = new Command37("disable").description("disable features").configureHelp(helpConfig).addCommand(auth2).addCommand(api2).addCommand(apiKeys2).addCommand(backend2).addCommand(contentNegotiation2).addCommand(i18n2).addCommand(teams2).addCommand(payments2).addCommand(s32).addCommand(smtp2);
4870
5422
 
4871
5423
  // src/commands/destroy.ts
4872
- import { Command as Command41 } from "commander";
5424
+ import { Command as Command43 } from "commander";
4873
5425
 
4874
5426
  // src/commands/destroy/form.ts
4875
- import { Command as Command36 } from "commander";
5427
+ import { Command as Command38 } from "commander";
4876
5428
 
4877
5429
  // src/commands/destroy/_shared.ts
4878
- import process17 from "node:process";
4879
- import * as p22 from "@clack/prompts";
5430
+ import process20 from "node:process";
5431
+ import * as p25 from "@clack/prompts";
4880
5432
  async function runDestroy(slug2, model, confirmMessage, report4, flags) {
4881
5433
  if (!flags.yes) {
4882
- const ok = await p22.confirm({ message: confirmMessage, initialValue: false });
4883
- if (p22.isCancel(ok) || !ok) {
4884
- p22.cancel("Operation cancelled.");
4885
- process17.exit(0);
5434
+ const ok = await p25.confirm({ message: confirmMessage, initialValue: false });
5435
+ if (p25.isCancel(ok) || !ok) {
5436
+ p25.cancel("Operation cancelled.");
5437
+ process20.exit(0);
4886
5438
  }
4887
5439
  }
4888
5440
  await runPattern(slug2, [model], { destructive: true, route: flags.route }, report4);
4889
5441
  }
4890
5442
 
4891
5443
  // src/commands/destroy/form.ts
4892
- var form2 = new Command36("form").description("destroy a form generated by `vela generate form`").argument("<model>", "model name used when the form was generated (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").option(
5444
+ var form2 = new Command38("form").description("destroy a form generated by `vela generate form`").argument("<model>", "model name used when the form was generated (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").option(
4893
5445
  "--route <route>",
4894
5446
  "custom route the form was generated at (must match the --route used at generation)"
4895
5447
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -4913,8 +5465,8 @@ var form2 = new Command36("form").description("destroy a form generated by `vela
4913
5465
  );
4914
5466
 
4915
5467
  // src/commands/destroy/schema.ts
4916
- import { Command as Command37 } from "commander";
4917
- var schema2 = new Command37("schema").description("destroy a zod schema generated by `vela generate schema`").argument("<model>", "schema model name (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5468
+ import { Command as Command39 } from "commander";
5469
+ var schema2 = new Command39("schema").description("destroy a zod schema generated by `vela generate schema`").argument("<model>", "schema model name (e.g., contact, login)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4918
5470
  (model, opts) => runCommand(
4919
5471
  () => runDestroy(
4920
5472
  "destroy-schema",
@@ -4935,8 +5487,8 @@ var schema2 = new Command37("schema").description("destroy a zod schema generate
4935
5487
  );
4936
5488
 
4937
5489
  // src/commands/destroy/resource.ts
4938
- import { Command as Command38 } from "commander";
4939
- var resource2 = new Command38("resource").description("destroy a resource generated by `vela generate resource`").argument("<model>", "model path used when the resource was generated (e.g., contacts, articles)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
5490
+ import { Command as Command40 } from "commander";
5491
+ var resource2 = new Command40("resource").description("destroy a resource generated by `vela generate resource`").argument("<model>", "model path used when the resource was generated (e.g., contacts, articles)").option("-y, --yes", "skip confirmation prompt").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
4940
5492
  (model, opts) => runCommand(
4941
5493
  () => runDestroy(
4942
5494
  "destroy-resource",
@@ -4957,8 +5509,8 @@ var resource2 = new Command38("resource").description("destroy a resource genera
4957
5509
  );
4958
5510
 
4959
5511
  // src/commands/destroy/scaffold.ts
4960
- import { Command as Command39 } from "commander";
4961
- var scaffold2 = new Command39("scaffold").description("destroy a scaffold generated by `vela generate scaffold`").argument("<model>", "model name used when the scaffold was generated (e.g., contact, todo)").option("-y, --yes", "skip confirmation prompt").option(
5512
+ import { Command as Command41 } from "commander";
5513
+ var scaffold2 = new Command41("scaffold").description("destroy a scaffold generated by `vela generate scaffold`").argument("<model>", "model name used when the scaffold was generated (e.g., contact, todo)").option("-y, --yes", "skip confirmation prompt").option(
4962
5514
  "--route <route>",
4963
5515
  "custom route the scaffold was generated at (must match the --route used at generation)"
4964
5516
  ).allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(
@@ -4985,9 +5537,9 @@ var scaffold2 = new Command39("scaffold").description("destroy a scaffold genera
4985
5537
  );
4986
5538
 
4987
5539
  // src/commands/destroy/deployment.ts
4988
- import process18 from "node:process";
4989
- import { Command as Command40 } from "commander";
4990
- import * as p25 from "@clack/prompts";
5540
+ import process21 from "node:process";
5541
+ import { Command as Command42 } from "commander";
5542
+ import * as p28 from "@clack/prompts";
4991
5543
  import pc13 from "picocolors";
4992
5544
 
4993
5545
  // src/lib/destroy-guard.ts
@@ -5035,88 +5587,12 @@ function describe({ appName, envTag, purge }) {
5035
5587
  }
5036
5588
 
5037
5589
  // src/lib/deploy-report.ts
5038
- import * as p24 from "@clack/prompts";
5590
+ import * as p27 from "@clack/prompts";
5039
5591
  import pc12 from "picocolors";
5040
5592
 
5041
5593
  // src/lib/server-identity.ts
5042
- import * as p23 from "@clack/prompts";
5594
+ import * as p26 from "@clack/prompts";
5043
5595
  import pc11 from "picocolors";
5044
-
5045
- // src/lib/velastack-api.ts
5046
- async function apiFetch(apiKey, pathAndQuery, init) {
5047
- const headers = new Headers(init?.headers);
5048
- headers.set("Authorization", `Bearer ${apiKey}`);
5049
- if (init?.body && !headers.has("Content-Type")) {
5050
- headers.set("Content-Type", "application/json");
5051
- }
5052
- const res = await fetch(`${API_URL}${pathAndQuery}`, { ...init, headers });
5053
- if (res.status === 401) {
5054
- throw new Error("API key invalid \u2014 run `vela login`");
5055
- }
5056
- if (res.status === 403) {
5057
- const body = await res.text().catch(() => "");
5058
- throw new Error(`velastack.dev refused this key (${body || "forbidden"}) \u2014 run \`vela login\``);
5059
- }
5060
- if (!res.ok) {
5061
- const body = await res.text().catch(() => "");
5062
- throw new Error(`Velastack API error (${res.status}): ${body || res.statusText}`);
5063
- }
5064
- return await res.json();
5065
- }
5066
- async function getCurrentUser(apiKey) {
5067
- const data = await apiFetch(
5068
- apiKey,
5069
- "/api/collections/users/records?perPage=1"
5070
- );
5071
- const user = data.items[0];
5072
- if (!user) throw new Error("No user found. Run `vela login` to login.");
5073
- return user;
5074
- }
5075
- async function listTeams(apiKey) {
5076
- const data = await apiFetch(
5077
- apiKey,
5078
- "/api/collections/teams/records?perPage=200"
5079
- );
5080
- return data.items;
5081
- }
5082
- async function listProjects(apiKey) {
5083
- const data = await apiFetch(
5084
- apiKey,
5085
- "/api/collections/projects/records?perPage=200&expand=team"
5086
- );
5087
- return data.items;
5088
- }
5089
- async function createProject2(apiKey, args) {
5090
- return apiFetch(apiKey, "/api/collections/projects/records", {
5091
- method: "POST",
5092
- body: JSON.stringify({ name: args.name, team: args.teamId, user: args.userId })
5093
- });
5094
- }
5095
- async function registerServer(apiKey, input) {
5096
- return apiFetch(apiKey, "/v1/servers", {
5097
- method: "POST",
5098
- body: JSON.stringify(input)
5099
- });
5100
- }
5101
- async function startDeployment(apiKey, projectId, input) {
5102
- return apiFetch(apiKey, `/v1/projects/${projectId}/deployments`, {
5103
- method: "POST",
5104
- body: JSON.stringify(input)
5105
- });
5106
- }
5107
- async function finishDeployment(apiKey, projectId, deploymentId, input) {
5108
- return apiFetch(apiKey, `/v1/projects/${projectId}/deployments/${deploymentId}`, {
5109
- method: "PATCH",
5110
- body: JSON.stringify(input)
5111
- });
5112
- }
5113
- async function destroyEnvironment(apiKey, projectId, envTag) {
5114
- return apiFetch(apiKey, `/v1/projects/${projectId}/environments/${encodeURIComponent(envTag)}`, {
5115
- method: "DELETE"
5116
- });
5117
- }
5118
-
5119
- // src/lib/server-identity.ts
5120
5596
  var IPV4 = /^\d{1,3}(?:\.\d{1,3}){3}$/;
5121
5597
  async function ensureServerIdentity(session, apiKey) {
5122
5598
  const existing = await readServerIdentity(session);
@@ -5129,7 +5605,7 @@ async function ensureServerIdentity(session, apiKey) {
5129
5605
  if (!existing || existing.serverId !== registered.serverId || existing.originHost !== registered.originHost || existing.token !== registered.token) {
5130
5606
  await writeServerIdentity(session, registered);
5131
5607
  if (existing) {
5132
- p23.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5608
+ p26.log.info(`${pc11.cyan(session.target)} was re-registered with velastack.dev.`);
5133
5609
  }
5134
5610
  }
5135
5611
  await runServerScript(session, "origin.sh");
@@ -5169,7 +5645,7 @@ function createDeployReporter(workspaceRootDir) {
5169
5645
  const link2 = readProjectConfig(workspaceRootDir);
5170
5646
  const apiKey = link2 ? readApiKey() : null;
5171
5647
  if (link2 && !apiKey) {
5172
- p24.log.warn(
5648
+ p27.log.warn(
5173
5649
  `This project is linked to ${pc12.cyan(link2.projectName)} on velastack.dev, but there is no
5174
5650
  API key here, so this deploy will not be recorded. Run ${pc12.cyan("vela login")}, or set
5175
5651
  ${pc12.cyan("VELA_API_KEY")}.`
@@ -5219,7 +5695,7 @@ async function reportEnvironmentDestroyed(workspaceRootDir, envTag) {
5219
5695
  }
5220
5696
  }
5221
5697
  function warn(what, err) {
5222
- p24.log.warn(
5698
+ p27.log.warn(
5223
5699
  `velastack.dev could not ${what}.
5224
5700
  ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5225
5701
  );
@@ -5228,7 +5704,7 @@ ${pc12.dim(err instanceof Error ? err.message : String(err))}`
5228
5704
  // src/commands/destroy/deployment.ts
5229
5705
  var deployment = addLockWaitOption(
5230
5706
  addTargetOptions(
5231
- new Command40("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5707
+ new Command42("deployment").description("remove a deployed environment from its server").configureHelp(helpConfig),
5232
5708
  "production"
5233
5709
  )
5234
5710
  ).option("--purge", "also delete the database and uploaded files").option("-y, --yes", "skip the confirmation prompt").option(
@@ -5247,7 +5723,7 @@ var deployment = addLockWaitOption(
5247
5723
  purge: options.purge === true,
5248
5724
  yes: options.yes === true,
5249
5725
  confirm: options.confirm,
5250
- interactive: Boolean(process18.stdin.isTTY && process18.stdout.isTTY)
5726
+ interactive: Boolean(process21.stdin.isTTY && process21.stdout.isTTY)
5251
5727
  });
5252
5728
  if (decision.kind === "refuse") throw new Error(decision.message);
5253
5729
  if (decision.kind === "prompt") {
@@ -5262,13 +5738,13 @@ var deployment = addLockWaitOption(
5262
5738
  stream: true
5263
5739
  });
5264
5740
  if (result?.existed === false) {
5265
- p25.log.info(
5741
+ p28.log.info(
5266
5742
  `Nothing named ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} on ${ctx.server}; nothing to remove.`
5267
5743
  );
5268
5744
  return;
5269
5745
  }
5270
5746
  await reportEnvironmentDestroyed(ctx.workspaceRootDir, ctx.envTag);
5271
- p25.log.success(
5747
+ p28.log.success(
5272
5748
  `Removed ${pc13.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${ctx.server}.` + (result?.purged ? result.trash ? `
5273
5749
 
5274
5750
  A snapshot of its data is at ${pc13.cyan(result.trash)} on the server for two weeks.` : "" : `
@@ -5286,35 +5762,35 @@ The database and uploads are still in the instance's shared directory. Pass ${pc
5286
5762
  );
5287
5763
  async function confirm8(appName, targetName, byName) {
5288
5764
  if (byName) {
5289
- const answer = await p25.text({
5765
+ const answer = await p28.text({
5290
5766
  message: `This removes ${pc13.cyan(`${appName} (${targetName})`)}. Type the app name to confirm`,
5291
5767
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
5292
5768
  });
5293
- if (p25.isCancel(answer)) {
5294
- p25.cancel("Operation cancelled.");
5295
- process18.exit(0);
5769
+ if (p28.isCancel(answer)) {
5770
+ p28.cancel("Operation cancelled.");
5771
+ process21.exit(0);
5296
5772
  }
5297
5773
  return;
5298
5774
  }
5299
- const ok = await p25.confirm({
5775
+ const ok = await p28.confirm({
5300
5776
  message: `Remove ${appName} (${targetName})?`,
5301
5777
  initialValue: false
5302
5778
  });
5303
- if (p25.isCancel(ok) || !ok) {
5304
- p25.cancel("Operation cancelled.");
5305
- process18.exit(0);
5779
+ if (p28.isCancel(ok) || !ok) {
5780
+ p28.cancel("Operation cancelled.");
5781
+ process21.exit(0);
5306
5782
  }
5307
5783
  }
5308
5784
 
5309
5785
  // src/commands/destroy.ts
5310
- var destroy = new Command41("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5786
+ var destroy = new Command43("destroy").description("destroy scaffolding, or a deployment").configureHelp(helpConfig).addCommand(form2).addCommand(schema2).addCommand(resource2).addCommand(scaffold2).addCommand(deployment);
5311
5787
 
5312
5788
  // src/commands/ui.ts
5313
- import { Command as Command47 } from "commander";
5789
+ import { Command as Command49 } from "commander";
5314
5790
 
5315
5791
  // src/commands/ui/add.ts
5316
- import { Command as Command42 } from "commander";
5317
- import * as p26 from "@clack/prompts";
5792
+ import { Command as Command44 } from "commander";
5793
+ import * as p29 from "@clack/prompts";
5318
5794
  import { installComponents } from "@velastack/patterns";
5319
5795
 
5320
5796
  // src/lib/ui-add.ts
@@ -5363,10 +5839,10 @@ function uiAddReport(requested, outcome) {
5363
5839
  }
5364
5840
 
5365
5841
  // src/commands/ui/add.ts
5366
- var add = new Command42("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
5842
+ var add = new Command44("add").description("add ui components (shadcn-svelte items and vela components such as data-table)").argument("<components...>", "the components to add").option("--overwrite", "replace components that already exist", false).configureHelp(helpConfig).action(
5367
5843
  (components, options) => runCommand(async () => {
5368
5844
  const { workspaceRootDir } = await getWorkspace();
5369
- const log45 = p26.taskLog({ title: "Adding UI components..." });
5845
+ const log45 = p29.taskLog({ title: "Adding UI components..." });
5370
5846
  let outcome;
5371
5847
  try {
5372
5848
  outcome = await installComponents({
@@ -5385,13 +5861,13 @@ var add = new Command42("add").description("add ui components (shadcn-svelte ite
5385
5861
  );
5386
5862
 
5387
5863
  // src/commands/ui/base.ts
5388
- import { Command as Command43 } from "commander";
5389
- import * as p27 from "@clack/prompts";
5864
+ import { Command as Command45 } from "commander";
5865
+ import * as p30 from "@clack/prompts";
5390
5866
  import { applyBaseColor } from "@velastack/patterns";
5391
- var base = new Command43("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5867
+ var base = new Command45("base").description("change the base (gray) palette").argument("<color>", `base color to use (${BASE_COLORS.join(", ")})`).configureHelp(helpConfig).action(
5392
5868
  (color) => runCommand(async () => {
5393
5869
  const { workspaceRootDir } = await getWorkspace();
5394
- const log45 = p27.taskLog({ title: `Applying the ${color} palette...` });
5870
+ const log45 = p30.taskLog({ title: `Applying the ${color} palette...` });
5395
5871
  let outcome;
5396
5872
  try {
5397
5873
  outcome = await applyBaseColor({ root: workspaceRootDir, color });
@@ -5413,8 +5889,8 @@ var base = new Command43("base").description("change the base (gray) palette").a
5413
5889
  );
5414
5890
 
5415
5891
  // src/commands/ui/list.ts
5416
- import { Command as Command44 } from "commander";
5417
- import * as p28 from "@clack/prompts";
5892
+ import { Command as Command46 } from "commander";
5893
+ import * as p31 from "@clack/prompts";
5418
5894
  import { listComponents } from "@velastack/patterns";
5419
5895
 
5420
5896
  // src/lib/ui-list.ts
@@ -5445,7 +5921,7 @@ function uiListReport(result) {
5445
5921
  }
5446
5922
 
5447
5923
  // src/commands/ui/list.ts
5448
- var list = new Command44("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
5924
+ var list = new Command46("list").description("list installed ui components, vela components and the style registry").option("--json", "print the result as JSON", false).configureHelp(helpConfig).action(
5449
5925
  (options) => runCommand(async () => {
5450
5926
  const { workspaceRootDir } = await getWorkspace();
5451
5927
  if (options.json) {
@@ -5453,7 +5929,7 @@ var list = new Command44("list").description("list installed ui components, vela
5453
5929
  console.log(JSON.stringify(result2, null, 2));
5454
5930
  return;
5455
5931
  }
5456
- const spinner7 = p28.spinner();
5932
+ const spinner7 = p31.spinner();
5457
5933
  spinner7.start("Reading the registry...");
5458
5934
  let result;
5459
5935
  try {
@@ -5465,15 +5941,15 @@ var list = new Command44("list").description("list installed ui components, vela
5465
5941
  spinner7.stop(`Read the ${result.style} registry`);
5466
5942
  reportResult(uiListReport(result));
5467
5943
  if (result.registryUnavailable) {
5468
- p28.log.warn(`${result.registryUnavailable}
5944
+ p31.log.warn(`${result.registryUnavailable}
5469
5945
  Registry components are not listed.`);
5470
5946
  }
5471
5947
  }, "Failed to list UI components.")
5472
5948
  );
5473
5949
 
5474
5950
  // src/commands/ui/style.ts
5475
- import { Command as Command45 } from "commander";
5476
- import * as p29 from "@clack/prompts";
5951
+ import { Command as Command47 } from "commander";
5952
+ import * as p32 from "@clack/prompts";
5477
5953
  import { switchStyle } from "@velastack/patterns";
5478
5954
 
5479
5955
  // src/lib/ui-style.ts
@@ -5499,10 +5975,10 @@ function uiStyleReport(result) {
5499
5975
  }
5500
5976
 
5501
5977
  // src/commands/ui/style.ts
5502
- var style = new Command45("style").description("switch the shadcn-svelte style, re-adding its components").argument("<style>", `style to switch to (${STYLES.join(", ")})`).option("-y, --yes", "skip the confirmation prompt").option("--no-font", "keep the current font instead of applying the style's").configureHelp(helpConfig).action(
5978
+ var style = new Command47("style").description("switch the shadcn-svelte style, re-adding its components").argument("<style>", `style to switch to (${STYLES.join(", ")})`).option("-y, --yes", "skip the confirmation prompt").option("--no-font", "keep the current font instead of applying the style's").configureHelp(helpConfig).action(
5503
5979
  (name, options) => runCommand(async () => {
5504
5980
  const { workspaceRootDir } = await getWorkspace();
5505
- const spinner7 = p29.spinner();
5981
+ const spinner7 = p32.spinner();
5506
5982
  spinner7.start(`Reading the ${name} registry...`);
5507
5983
  let log45;
5508
5984
  let outcome;
@@ -5515,20 +5991,20 @@ var style = new Command45("style").description("switch the shadcn-svelte style,
5515
5991
  confirm: async (components) => {
5516
5992
  spinner7.stop(`Read the ${name} registry`);
5517
5993
  if (components.length > 0) {
5518
- p29.log.info(
5994
+ p32.log.info(
5519
5995
  `Re-adds ${components.length} component(s) from the ${name} registry; local edits to their files are lost:
5520
5996
  ${components.map((c) => `- ${c}`).join("\n")}`
5521
5997
  );
5522
5998
  } else {
5523
- p29.log.info(
5999
+ p32.log.info(
5524
6000
  `No installed component comes from the registry; only the config changes.`
5525
6001
  );
5526
6002
  }
5527
6003
  if (!options.yes) {
5528
- const ok = await p29.confirm({ message: `Switch to ${name}?`, initialValue: false });
5529
- if (p29.isCancel(ok) || !ok) return false;
6004
+ const ok = await p32.confirm({ message: `Switch to ${name}?`, initialValue: false });
6005
+ if (p32.isCancel(ok) || !ok) return false;
5530
6006
  }
5531
- log45 = p29.taskLog({ title: `Switching to the ${name} style...` });
6007
+ log45 = p32.taskLog({ title: `Switching to the ${name} style...` });
5532
6008
  return true;
5533
6009
  }
5534
6010
  });
@@ -5539,11 +6015,11 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5539
6015
  }
5540
6016
  spinner7.stop(`Read the ${name} registry`);
5541
6017
  if (outcome.status === "unchanged") {
5542
- p29.log.info(`Already using the ${name} style.`);
6018
+ p32.log.info(`Already using the ${name} style.`);
5543
6019
  return;
5544
6020
  }
5545
6021
  if (outcome.status === "cancelled") {
5546
- p29.cancel("Operation cancelled.");
6022
+ p32.cancel("Operation cancelled.");
5547
6023
  return;
5548
6024
  }
5549
6025
  log45?.success("Style switched");
@@ -5552,13 +6028,13 @@ ${components.map((c) => `- ${c}`).join("\n")}`
5552
6028
  );
5553
6029
 
5554
6030
  // src/commands/ui/theme.ts
5555
- import { Command as Command46 } from "commander";
5556
- import * as p30 from "@clack/prompts";
6031
+ import { Command as Command48 } from "commander";
6032
+ import * as p33 from "@clack/prompts";
5557
6033
  import { applyTheme } from "@velastack/patterns";
5558
- var theme = new Command46("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
6034
+ var theme = new Command48("theme").description("change the accent color, keeping the base palette").argument("<accent>", `accent to use (${THEMES.join(", ")})`).configureHelp(helpConfig).action(
5559
6035
  (accent) => runCommand(async () => {
5560
6036
  const { workspaceRootDir } = await getWorkspace();
5561
- const log45 = p30.taskLog({ title: `Applying the ${accent} accent...` });
6037
+ const log45 = p33.taskLog({ title: `Applying the ${accent} accent...` });
5562
6038
  let outcome;
5563
6039
  try {
5564
6040
  outcome = await applyTheme({ root: workspaceRootDir, theme: accent });
@@ -5580,22 +6056,22 @@ var theme = new Command46("theme").description("change the accent color, keeping
5580
6056
  );
5581
6057
 
5582
6058
  // src/commands/ui.ts
5583
- var ui = new Command47("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
6059
+ var ui = new Command49("ui").description("generate ui components").configureHelp(helpConfig).addCommand(add).addCommand(list).addCommand(style).addCommand(base).addCommand(theme);
5584
6060
 
5585
6061
  // src/commands/legal.ts
5586
- import { Command as Command50 } from "commander";
6062
+ import { Command as Command52 } from "commander";
5587
6063
 
5588
6064
  // src/commands/legal/terms.ts
5589
6065
  import fs26 from "node:fs";
5590
6066
  import path23 from "node:path";
5591
- import { Command as Command48 } from "commander";
5592
- import * as p32 from "@clack/prompts";
6067
+ import { Command as Command50 } from "commander";
6068
+ import * as p35 from "@clack/prompts";
5593
6069
 
5594
6070
  // src/commands/legal/shared.ts
5595
- import process19 from "node:process";
5596
- import * as p31 from "@clack/prompts";
6071
+ import process22 from "node:process";
6072
+ import * as p34 from "@clack/prompts";
5597
6073
  var sharedFields = {
5598
- websiteUrl: () => p31.text({
6074
+ websiteUrl: () => p34.text({
5599
6075
  message: "What is your website URL?",
5600
6076
  placeholder: "http://www.mysite.com",
5601
6077
  validate: (value) => {
@@ -5604,7 +6080,7 @@ var sharedFields = {
5604
6080
  }
5605
6081
  }
5606
6082
  }),
5607
- websiteName: () => p31.text({
6083
+ websiteName: () => p34.text({
5608
6084
  message: "What is your website name?",
5609
6085
  placeholder: "My Site",
5610
6086
  validate: (value) => {
@@ -5613,7 +6089,7 @@ var sharedFields = {
5613
6089
  }
5614
6090
  }
5615
6091
  }),
5616
- entityType: () => p31.select({
6092
+ entityType: () => p34.select({
5617
6093
  message: "Entity type",
5618
6094
  options: [
5619
6095
  {
@@ -5624,7 +6100,7 @@ var sharedFields = {
5624
6100
  { value: "individual", label: "I'm an Individual" }
5625
6101
  ]
5626
6102
  }),
5627
- businessName: ({ results }) => results?.entityType === "business" ? p31.text({
6103
+ businessName: ({ results }) => results?.entityType === "business" ? p34.text({
5628
6104
  message: "What is the name of the business?",
5629
6105
  placeholder: "My Company LLC",
5630
6106
  validate: (value) => {
@@ -5633,7 +6109,7 @@ var sharedFields = {
5633
6109
  }
5634
6110
  }
5635
6111
  }) : void 0,
5636
- businessAddress: ({ results }) => results?.entityType === "business" ? p31.text({
6112
+ businessAddress: ({ results }) => results?.entityType === "business" ? p34.text({
5637
6113
  message: "What is the address of the business?",
5638
6114
  placeholder: "1 Cupertino, CA 95014",
5639
6115
  validate: (value) => {
@@ -5642,7 +6118,7 @@ var sharedFields = {
5642
6118
  }
5643
6119
  }
5644
6120
  }) : void 0,
5645
- country: () => p31.text({
6121
+ country: () => p34.text({
5646
6122
  message: "Enter the country",
5647
6123
  validate: (value) => {
5648
6124
  if (!value) {
@@ -5650,7 +6126,7 @@ var sharedFields = {
5650
6126
  }
5651
6127
  }
5652
6128
  }),
5653
- state: () => p31.text({
6129
+ state: () => p34.text({
5654
6130
  message: "Enter the state",
5655
6131
  validate: (value) => {
5656
6132
  if (!value) {
@@ -5660,11 +6136,11 @@ var sharedFields = {
5660
6136
  })
5661
6137
  };
5662
6138
  var onCancel = () => {
5663
- p31.cancel("Operation cancelled.");
5664
- process19.exit(0);
6139
+ p34.cancel("Operation cancelled.");
6140
+ process22.exit(0);
5665
6141
  };
5666
6142
  async function contactMethods(type) {
5667
- const selection = await p31.multiselect({
6143
+ const selection = await p34.multiselect({
5668
6144
  message: `How can users contact you for any questions regarding your ${type === "privacy" ? "Privacy Policy" : "Terms & Conditions"}? Check all that apply`,
5669
6145
  options: [
5670
6146
  { value: "email", label: "By email" },
@@ -5673,11 +6149,11 @@ async function contactMethods(type) {
5673
6149
  { value: "mail", label: "By sending post mail" }
5674
6150
  ]
5675
6151
  });
5676
- if (p31.isCancel(selection)) onCancel();
6152
+ if (p34.isCancel(selection)) onCancel();
5677
6153
  const contact = selection;
5678
6154
  const details = {};
5679
6155
  if (contact.includes("email")) {
5680
- const email3 = await p31.text({
6156
+ const email3 = await p34.text({
5681
6157
  message: "What's the email?",
5682
6158
  placeholder: "office@mycompany.com",
5683
6159
  validate: (value) => {
@@ -5686,11 +6162,11 @@ async function contactMethods(type) {
5686
6162
  }
5687
6163
  }
5688
6164
  });
5689
- if (p31.isCancel(email3)) onCancel();
6165
+ if (p34.isCancel(email3)) onCancel();
5690
6166
  details.email = email3;
5691
6167
  }
5692
6168
  if (contact.includes("page")) {
5693
- const page = await p31.text({
6169
+ const page = await p34.text({
5694
6170
  message: "What's the link?",
5695
6171
  placeholder: "http://www.mycompany.com/contact",
5696
6172
  validate: (value) => {
@@ -5699,11 +6175,11 @@ async function contactMethods(type) {
5699
6175
  }
5700
6176
  }
5701
6177
  });
5702
- if (p31.isCancel(page)) onCancel();
6178
+ if (p34.isCancel(page)) onCancel();
5703
6179
  details.page = page;
5704
6180
  }
5705
6181
  if (contact.includes("phone")) {
5706
- const phone = await p31.text({
6182
+ const phone = await p34.text({
5707
6183
  message: "What's the phone number?",
5708
6184
  placeholder: "408.996.1010",
5709
6185
  validate: (value) => {
@@ -5712,11 +6188,11 @@ async function contactMethods(type) {
5712
6188
  }
5713
6189
  }
5714
6190
  });
5715
- if (p31.isCancel(phone)) onCancel();
6191
+ if (p34.isCancel(phone)) onCancel();
5716
6192
  details.phone = phone;
5717
6193
  }
5718
6194
  if (contact.includes("mail")) {
5719
- const address = await p31.text({
6195
+ const address = await p34.text({
5720
6196
  message: "What's the address?",
5721
6197
  placeholder: "767 Fifth Avenue New York, NY 10153, United States",
5722
6198
  validate: (value) => {
@@ -5725,7 +6201,7 @@ async function contactMethods(type) {
5725
6201
  }
5726
6202
  }
5727
6203
  });
5728
- if (p31.isCancel(address)) onCancel();
6204
+ if (p34.isCancel(address)) onCancel();
5729
6205
  details.address = address;
5730
6206
  }
5731
6207
  return { methods: contact, details };
@@ -6121,7 +6597,7 @@ var generateTermsHtml = (answers) => {
6121
6597
  };
6122
6598
  async function termsAction() {
6123
6599
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6124
- const core = await p32.group(
6600
+ const core = await p35.group(
6125
6601
  {
6126
6602
  websiteUrl: sharedFields.websiteUrl,
6127
6603
  websiteName: sharedFields.websiteName,
@@ -6133,25 +6609,25 @@ async function termsAction() {
6133
6609
  },
6134
6610
  { onCancel }
6135
6611
  );
6136
- const accounts = await p32.select({
6612
+ const accounts = await p35.select({
6137
6613
  message: "Can users create accounts?",
6138
6614
  options: [
6139
6615
  { value: "yes", label: "Yes, users can create accounts" },
6140
6616
  { value: "no", label: "No" }
6141
6617
  ]
6142
6618
  });
6143
- if (p32.isCancel(accounts)) onCancel();
6144
- const userContent = await p32.select({
6619
+ if (p35.isCancel(accounts)) onCancel();
6620
+ const userContent = await p35.select({
6145
6621
  message: "Can users create and/or upload content (ie. text, images)?",
6146
6622
  options: [
6147
6623
  { value: "yes", label: "Yes, users can create and/or upload content" },
6148
6624
  { value: "no", label: "No" }
6149
6625
  ]
6150
6626
  });
6151
- if (p32.isCancel(userContent)) onCancel();
6627
+ if (p35.isCancel(userContent)) onCancel();
6152
6628
  let infringementEmail;
6153
6629
  if (userContent === "yes") {
6154
- const email3 = await p32.text({
6630
+ const email3 = await p35.text({
6155
6631
  message: "What's the email address where you will receive infringements notices?",
6156
6632
  placeholder: "dmca@website.com",
6157
6633
  validate: (value) => {
@@ -6160,10 +6636,10 @@ async function termsAction() {
6160
6636
  }
6161
6637
  }
6162
6638
  });
6163
- if (p32.isCancel(email3)) onCancel();
6639
+ if (p35.isCancel(email3)) onCancel();
6164
6640
  infringementEmail = email3;
6165
6641
  }
6166
- const canBuyGoods = await p32.select({
6642
+ const canBuyGoods = await p35.select({
6167
6643
  message: "Can users buy goods (products, items)?",
6168
6644
  options: [
6169
6645
  {
@@ -6173,28 +6649,28 @@ async function termsAction() {
6173
6649
  { value: "no", label: "No" }
6174
6650
  ]
6175
6651
  });
6176
- if (p32.isCancel(canBuyGoods)) onCancel();
6177
- const subscriptions2 = await p32.select({
6652
+ if (p35.isCancel(canBuyGoods)) onCancel();
6653
+ const subscriptions2 = await p35.select({
6178
6654
  message: "Do you offer subscription plans?",
6179
6655
  options: [
6180
6656
  { value: "yes", label: "Yes, we offer subscription plans" },
6181
6657
  { value: "no", label: "No" }
6182
6658
  ]
6183
6659
  });
6184
- if (p32.isCancel(subscriptions2)) onCancel();
6660
+ if (p35.isCancel(subscriptions2)) onCancel();
6185
6661
  let freeTrial;
6186
6662
  if (subscriptions2 === "yes") {
6187
- const ft = await p32.select({
6663
+ const ft = await p35.select({
6188
6664
  message: "Do you offer a free trial?",
6189
6665
  options: [
6190
6666
  { value: "yes", label: "Yes" },
6191
6667
  { value: "no", label: "No" }
6192
6668
  ]
6193
6669
  });
6194
- if (p32.isCancel(ft)) onCancel();
6670
+ if (p35.isCancel(ft)) onCancel();
6195
6671
  freeTrial = ft;
6196
6672
  }
6197
- const exclusiveContent = await p32.select({
6673
+ const exclusiveContent = await p35.select({
6198
6674
  message: "Do you want to make it clear that your own content & trademarks are your exclusive property?",
6199
6675
  options: [
6200
6676
  {
@@ -6204,24 +6680,24 @@ async function termsAction() {
6204
6680
  { value: "no", label: "No" }
6205
6681
  ]
6206
6682
  });
6207
- if (p32.isCancel(exclusiveContent)) onCancel();
6208
- const feedbackReuse = await p32.select({
6683
+ if (p35.isCancel(exclusiveContent)) onCancel();
6684
+ const feedbackReuse = await p35.select({
6209
6685
  message: "If users provide you feedback & suggestions, do you want to use this feedback without compensation or credits given?",
6210
6686
  options: [
6211
6687
  { value: "yes", label: "Yes, we may implement any feedback or suggestions we receive" },
6212
6688
  { value: "no", label: "No" }
6213
6689
  ]
6214
6690
  });
6215
- if (p32.isCancel(feedbackReuse)) onCancel();
6216
- const promotions = await p32.select({
6691
+ if (p35.isCancel(feedbackReuse)) onCancel();
6692
+ const promotions = await p35.select({
6217
6693
  message: "Do you plan to offer promotions, contests, sweepstakes?",
6218
6694
  options: [
6219
6695
  { value: "yes", label: "Yes, we may offer promotions, contests, sweepstakes" },
6220
6696
  { value: "no", label: "No" }
6221
6697
  ]
6222
6698
  });
6223
- if (p32.isCancel(promotions)) onCancel();
6224
- const mobileAppRaw = await p32.multiselect({
6699
+ if (p35.isCancel(promotions)) onCancel();
6700
+ const mobileAppRaw = await p35.multiselect({
6225
6701
  message: "Is the Service distributed through any mobile app stores? Check all that apply",
6226
6702
  options: [
6227
6703
  { value: "apple", label: "Apple App Store" },
@@ -6229,7 +6705,7 @@ async function termsAction() {
6229
6705
  ],
6230
6706
  required: false
6231
6707
  });
6232
- if (p32.isCancel(mobileAppRaw)) onCancel();
6708
+ if (p35.isCancel(mobileAppRaw)) onCancel();
6233
6709
  const mobileApp = mobileAppRaw ?? [];
6234
6710
  const contact = await contactMethods("terms");
6235
6711
  const html = generateTermsHtml({
@@ -6272,13 +6748,13 @@ async function termsAction() {
6272
6748
  ]
6273
6749
  });
6274
6750
  }
6275
- var terms = new Command48("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6751
+ var terms = new Command50("terms").description("generate placeholder terms and conditions").configureHelp(helpConfig).action(() => runCommand(termsAction, "Failed to generate terms and conditions."));
6276
6752
 
6277
6753
  // src/commands/legal/privacy.ts
6278
6754
  import fs27 from "node:fs";
6279
6755
  import path24 from "node:path";
6280
- import { Command as Command49 } from "commander";
6281
- import * as p33 from "@clack/prompts";
6756
+ import { Command as Command51 } from "commander";
6757
+ import * as p36 from "@clack/prompts";
6282
6758
  var mapLabels = {
6283
6759
  personalInfo: {
6284
6760
  email: "Email address",
@@ -6696,12 +7172,12 @@ var generatePrivacyHtml = (answers) => {
6696
7172
  return `<section data-role="content">${sections.join("")}</section>`;
6697
7173
  };
6698
7174
  async function promptWithCustom(message, options, customMessage) {
6699
- const selection = await p33.multiselect({ message, options });
6700
- if (p33.isCancel(selection)) onCancel();
7175
+ const selection = await p36.multiselect({ message, options });
7176
+ if (p36.isCancel(selection)) onCancel();
6701
7177
  const values = selection;
6702
7178
  if (values.includes("custom")) {
6703
- const custom = await p33.text({ message: customMessage });
6704
- if (p33.isCancel(custom)) onCancel();
7179
+ const custom = await p36.text({ message: customMessage });
7180
+ if (p36.isCancel(custom)) onCancel();
6705
7181
  const idx = values.indexOf("custom");
6706
7182
  if (idx !== -1) values.splice(idx, 1);
6707
7183
  if (custom) values.push(String(custom));
@@ -6710,7 +7186,7 @@ async function promptWithCustom(message, options, customMessage) {
6710
7186
  }
6711
7187
  async function privacyAction() {
6712
7188
  const { workspaceRootDir, publicRoutesDir } = await getWorkspace();
6713
- const core = await p33.group(
7189
+ const core = await p36.group(
6714
7190
  {
6715
7191
  websiteUrl: sharedFields.websiteUrl,
6716
7192
  websiteName: sharedFields.websiteName,
@@ -6722,7 +7198,7 @@ async function privacyAction() {
6722
7198
  },
6723
7199
  { onCancel }
6724
7200
  );
6725
- const personalInfo = await p33.multiselect({
7201
+ const personalInfo = await p36.multiselect({
6726
7202
  message: "What kind of personal information do you collect from users? Check all that apply",
6727
7203
  options: [
6728
7204
  { value: "email", label: "Email address" },
@@ -6737,16 +7213,16 @@ async function privacyAction() {
6737
7213
  ],
6738
7214
  required: false
6739
7215
  });
6740
- if (p33.isCancel(personalInfo)) onCancel();
7216
+ if (p36.isCancel(personalInfo)) onCancel();
6741
7217
  const contact = await contactMethods("privacy");
6742
- const tracking = await p33.select({
7218
+ const tracking = await p36.select({
6743
7219
  message: "Do you use tracking and/or analytics tools, such as Google Analytics?",
6744
7220
  options: [
6745
7221
  { value: "yes", label: "Yes, we use Google Analytics or other related tools" },
6746
7222
  { value: "no", label: "No" }
6747
7223
  ]
6748
7224
  });
6749
- if (p33.isCancel(tracking)) onCancel();
7225
+ if (p36.isCancel(tracking)) onCancel();
6750
7226
  let trackingTools;
6751
7227
  if (tracking === "yes") {
6752
7228
  trackingTools = await promptWithCustom(
@@ -6765,7 +7241,7 @@ async function privacyAction() {
6765
7241
  "Enter your custom tracking/analytics tool name"
6766
7242
  );
6767
7243
  }
6768
- const sendEmails = await p33.select({
7244
+ const sendEmails = await p36.select({
6769
7245
  message: "Do you send emails to users?",
6770
7246
  options: [
6771
7247
  {
@@ -6775,7 +7251,7 @@ async function privacyAction() {
6775
7251
  { value: "no", label: "No" }
6776
7252
  ]
6777
7253
  });
6778
- if (p33.isCancel(sendEmails)) onCancel();
7254
+ if (p36.isCancel(sendEmails)) onCancel();
6779
7255
  let emailPlatforms;
6780
7256
  if (sendEmails === "yes") {
6781
7257
  emailPlatforms = await promptWithCustom(
@@ -6790,14 +7266,14 @@ async function privacyAction() {
6790
7266
  "Enter your custom email platform"
6791
7267
  );
6792
7268
  }
6793
- const showAds = await p33.select({
7269
+ const showAds = await p36.select({
6794
7270
  message: "Do you show ads?",
6795
7271
  options: [
6796
7272
  { value: "yes", label: "Yes, we show ads" },
6797
7273
  { value: "no", label: "No" }
6798
7274
  ]
6799
7275
  });
6800
- if (p33.isCancel(showAds)) onCancel();
7276
+ if (p36.isCancel(showAds)) onCancel();
6801
7277
  let adsPlatforms;
6802
7278
  if (showAds === "yes") {
6803
7279
  adsPlatforms = await promptWithCustom(
@@ -6820,7 +7296,7 @@ async function privacyAction() {
6820
7296
  "Enter your custom ads platform"
6821
7297
  );
6822
7298
  }
6823
- const canPay = await p33.select({
7299
+ const canPay = await p36.select({
6824
7300
  message: "Can users pay for products or services?",
6825
7301
  options: [
6826
7302
  { value: "yes", label: "Yes, users can pay for our products/services" },
@@ -6830,7 +7306,7 @@ async function privacyAction() {
6830
7306
  }
6831
7307
  ]
6832
7308
  });
6833
- if (p33.isCancel(canPay)) onCancel();
7309
+ if (p36.isCancel(canPay)) onCancel();
6834
7310
  let paymentProcessors;
6835
7311
  if (canPay === "yes") {
6836
7312
  paymentProcessors = await promptWithCustom(
@@ -6861,14 +7337,14 @@ async function privacyAction() {
6861
7337
  "Enter your custom payment processor/method"
6862
7338
  );
6863
7339
  }
6864
- const remarketing = await p33.select({
7340
+ const remarketing = await p36.select({
6865
7341
  message: "Do you use remarketing services for marketing & advertising purposes?",
6866
7342
  options: [
6867
7343
  { value: "yes", label: "Yes, we use remarketing services to advertise our business" },
6868
7344
  { value: "no", label: "No" }
6869
7345
  ]
6870
7346
  });
6871
- if (p33.isCancel(remarketing)) onCancel();
7347
+ if (p36.isCancel(remarketing)) onCancel();
6872
7348
  let remarketingPlatforms;
6873
7349
  if (remarketing === "yes") {
6874
7350
  remarketingPlatforms = await promptWithCustom(
@@ -6887,7 +7363,7 @@ async function privacyAction() {
6887
7363
  "Enter your custom remarketing platform"
6888
7364
  );
6889
7365
  }
6890
- const providersRaw = await p33.multiselect({
7366
+ const providersRaw = await p36.multiselect({
6891
7367
  message: "Select if you use any of the following providers",
6892
7368
  options: [
6893
7369
  { value: "recaptcha", label: "Invisible reCAPTCHA" },
@@ -6898,16 +7374,16 @@ async function privacyAction() {
6898
7374
  ],
6899
7375
  required: false
6900
7376
  });
6901
- if (p33.isCancel(providersRaw)) onCancel();
7377
+ if (p36.isCancel(providersRaw)) onCancel();
6902
7378
  const providers = providersRaw;
6903
7379
  if (providers.includes("custom")) {
6904
- const custom = await p33.text({ message: "Enter your custom provider" });
6905
- if (p33.isCancel(custom)) onCancel();
7380
+ const custom = await p36.text({ message: "Enter your custom provider" });
7381
+ if (p36.isCancel(custom)) onCancel();
6906
7382
  const idx = providers.indexOf("custom");
6907
7383
  if (idx !== -1) providers.splice(idx, 1);
6908
7384
  if (custom) providers.push(String(custom));
6909
7385
  }
6910
- const usStates = await p33.select({
7386
+ const usStates = await p36.select({
6911
7387
  message: "Include U.S. state privacy rights (CCPA/CPRA, VCDPA, CPA, CTDPA, UCPA, TX, OR, etc.)?",
6912
7388
  options: [
6913
7389
  {
@@ -6918,55 +7394,55 @@ async function privacyAction() {
6918
7394
  ],
6919
7395
  initialValue: "yes"
6920
7396
  });
6921
- if (p33.isCancel(usStates)) onCancel();
6922
- const gdpr = await p33.select({
7397
+ if (p36.isCancel(usStates)) onCancel();
7398
+ const gdpr = await p36.select({
6923
7399
  message: "Do you want your Privacy Policy to include GDPR / UK GDPR wording?",
6924
7400
  options: [
6925
7401
  { value: "yes", label: "Yes. Include GDPR rights for EEA, UK, and Swiss residents" },
6926
7402
  { value: "no", label: "No" }
6927
7403
  ]
6928
7404
  });
6929
- if (p33.isCancel(gdpr)) onCancel();
7405
+ if (p36.isCancel(gdpr)) onCancel();
6930
7406
  let facebookFanPage = "no";
6931
7407
  const facebookDetails = { name: "", url: "" };
6932
7408
  if (gdpr === "yes") {
6933
- const fan = await p33.select({
7409
+ const fan = await p36.select({
6934
7410
  message: "Do you have a Facebook Fan Page?",
6935
7411
  options: [
6936
7412
  { value: "yes", label: "Yes, we have a Facebook Fan Page" },
6937
7413
  { value: "no", label: "No" }
6938
7414
  ]
6939
7415
  });
6940
- if (p33.isCancel(fan)) onCancel();
7416
+ if (p36.isCancel(fan)) onCancel();
6941
7417
  facebookFanPage = fan;
6942
7418
  if (facebookFanPage === "yes") {
6943
- const name = await p33.text({
7419
+ const name = await p36.text({
6944
7420
  message: "What is the name of the Facebook Fan Page?",
6945
7421
  placeholder: "My Facebook Page"
6946
7422
  });
6947
- if (p33.isCancel(name)) onCancel();
7423
+ if (p36.isCancel(name)) onCancel();
6948
7424
  facebookDetails.name = name;
6949
- const url = await p33.text({
7425
+ const url = await p36.text({
6950
7426
  message: "What is the URL of the Facebook Fan Page?",
6951
7427
  placeholder: "https://facebook.com/my-facebook-page"
6952
7428
  });
6953
- if (p33.isCancel(url)) onCancel();
7429
+ if (p36.isCancel(url)) onCancel();
6954
7430
  facebookDetails.url = url;
6955
7431
  }
6956
7432
  }
6957
- const kids = await p33.select({
7433
+ const kids = await p36.select({
6958
7434
  message: "Do you collect information from kids under the age of 13?",
6959
7435
  options: [
6960
7436
  { value: "yes", label: "Yes. We collect information from children under the age of 13" },
6961
7437
  { value: "no", label: "No" }
6962
7438
  ]
6963
7439
  });
6964
- if (p33.isCancel(kids)) onCancel();
6965
- const retention = await p33.text({
7440
+ if (p36.isCancel(kids)) onCancel();
7441
+ const retention = await p36.text({
6966
7442
  message: "How long do you retain personal information? (leave blank for default wording)",
6967
7443
  placeholder: "e.g. 12 months after account closure"
6968
7444
  });
6969
- if (p33.isCancel(retention)) onCancel();
7445
+ if (p36.isCancel(retention)) onCancel();
6970
7446
  const html = generatePrivacyHtml({
6971
7447
  core,
6972
7448
  personalInfo: personalInfo ?? [],
@@ -7021,16 +7497,16 @@ async function privacyAction() {
7021
7497
  ]
7022
7498
  });
7023
7499
  }
7024
- var privacy = new Command49("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7500
+ var privacy = new Command51("privacy").description("generate placeholder privacy policy").configureHelp(helpConfig).action(() => runCommand(privacyAction, "Failed to generate privacy policy."));
7025
7501
 
7026
7502
  // src/commands/legal.ts
7027
- var legal = new Command50("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7503
+ var legal = new Command52("legal").description("generate placeholder legal documents").configureHelp(helpConfig).addCommand(terms).addCommand(privacy);
7028
7504
 
7029
7505
  // src/commands/fixtures.ts
7030
- import { Command as Command56 } from "commander";
7506
+ import { Command as Command58 } from "commander";
7031
7507
 
7032
7508
  // src/commands/fixtures/load.ts
7033
- import { Command as Command51 } from "commander";
7509
+ import { Command as Command53 } from "commander";
7034
7510
 
7035
7511
  // src/lib/data.ts
7036
7512
  import fs28 from "node:fs";
@@ -7220,7 +7696,7 @@ async function hasLoadedFixtures(pb) {
7220
7696
  }
7221
7697
 
7222
7698
  // src/commands/fixtures/load.ts
7223
- var load = new Command51("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7699
+ var load = new Command53("load").description("load fixtures into the database").configureHelp(helpConfig).action(
7224
7700
  () => runCommand(async () => {
7225
7701
  const { workspaceRootDir } = await getWorkspace();
7226
7702
  let loaded = [];
@@ -7246,8 +7722,8 @@ var load = new Command51("load").description("load fixtures into the database").
7246
7722
  );
7247
7723
 
7248
7724
  // src/commands/fixtures/clear.ts
7249
- import { Command as Command52 } from "commander";
7250
- var clear = new Command52("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7725
+ import { Command as Command54 } from "commander";
7726
+ var clear = new Command54("clear").description("clear loaded fixtures").configureHelp(helpConfig).action(
7251
7727
  () => runCommand(async () => {
7252
7728
  const { workspaceRootDir } = await getWorkspace();
7253
7729
  let cleared = [];
@@ -7276,8 +7752,8 @@ var clear = new Command52("clear").description("clear loaded fixtures").configur
7276
7752
  );
7277
7753
 
7278
7754
  // src/commands/fixtures/reset.ts
7279
- import { Command as Command53 } from "commander";
7280
- var reset = new Command53("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7755
+ import { Command as Command55 } from "commander";
7756
+ var reset = new Command55("reset").description("clear and reload fixtures").configureHelp(helpConfig).action(
7281
7757
  () => runCommand(async () => {
7282
7758
  const { workspaceRootDir } = await getWorkspace();
7283
7759
  let cleared = [];
@@ -7309,8 +7785,8 @@ var reset = new Command53("reset").description("clear and reload fixtures").conf
7309
7785
  // src/commands/fixtures/generate.ts
7310
7786
  import fs29 from "node:fs";
7311
7787
  import path26 from "node:path";
7312
- import { Command as Command54, InvalidArgumentError } from "commander";
7313
- import * as p34 from "@clack/prompts";
7788
+ import { Command as Command56, InvalidArgumentError } from "commander";
7789
+ import * as p37 from "@clack/prompts";
7314
7790
  import { annotate } from "annotate-json-schema";
7315
7791
  import { createGenerator } from "json-schema-faker";
7316
7792
  import { faker } from "@faker-js/faker";
@@ -7420,7 +7896,7 @@ async function generateFixtureFiles(pb, workspaceRootDir, opts) {
7420
7896
  }
7421
7897
  return { writtenFiles, warnings };
7422
7898
  }
7423
- var generate2 = new Command54("generate").description("generate fixture data").option("-c, --count <count>", "number of records per collection", parseCount, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed).option("-f, --force", "overwrite existing fixture files and clear loaded fixtures").configureHelp(helpConfig).action(
7899
+ var generate2 = new Command56("generate").description("generate fixture data").option("-c, --count <count>", "number of records per collection", parseCount, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed).option("-f, --force", "overwrite existing fixture files and clear loaded fixtures").configureHelp(helpConfig).action(
7424
7900
  (opts) => runCommand(async () => {
7425
7901
  const { workspaceRootDir } = await getWorkspace();
7426
7902
  const existing = getFixtureFiles(workspaceRootDir);
@@ -7449,7 +7925,7 @@ var generate2 = new Command54("generate").description("generate fixture data").o
7449
7925
  seed: opts.seed
7450
7926
  });
7451
7927
  });
7452
- for (const warning of result.warnings) p34.log.warn(warning);
7928
+ for (const warning of result.warnings) p37.log.warn(warning);
7453
7929
  if (result.writtenFiles.length === 0) {
7454
7930
  reportResult({
7455
7931
  summary: "No eligible collections found to generate fixtures for.",
@@ -7473,8 +7949,8 @@ var generate2 = new Command54("generate").description("generate fixture data").o
7473
7949
  );
7474
7950
 
7475
7951
  // src/commands/fixtures/regen.ts
7476
- import { Command as Command55, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7477
- import * as p35 from "@clack/prompts";
7952
+ import { Command as Command57, InvalidArgumentError as InvalidArgumentError2 } from "commander";
7953
+ import * as p38 from "@clack/prompts";
7478
7954
  function parseCount2(value) {
7479
7955
  const n = parseInt(value, 10);
7480
7956
  if (!Number.isFinite(n) || n <= 0 || n > 999) {
@@ -7489,7 +7965,7 @@ function parseSeed2(value) {
7489
7965
  }
7490
7966
  return n;
7491
7967
  }
7492
- var regen = new Command55("regen").description("clear the database, regenerate fixture files, and reload them").option("-c, --count <count>", "number of records per collection", parseCount2, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed2).configureHelp(helpConfig).action(
7968
+ var regen = new Command57("regen").description("clear the database, regenerate fixture files, and reload them").option("-c, --count <count>", "number of records per collection", parseCount2, 10).option("-s, --seed <seed>", "seed for deterministic output", parseSeed2).configureHelp(helpConfig).action(
7493
7969
  (opts) => runCommand(async () => {
7494
7970
  const { workspaceRootDir } = await getWorkspace();
7495
7971
  let cleared = [];
@@ -7503,7 +7979,7 @@ var regen = new Command55("regen").description("clear the database, regenerate f
7503
7979
  });
7504
7980
  loaded = await loadFixtures(pb, workspaceRootDir);
7505
7981
  });
7506
- for (const warning of result.warnings) p35.log.warn(warning);
7982
+ for (const warning of result.warnings) p38.log.warn(warning);
7507
7983
  reportResult({
7508
7984
  summary: `Regenerated fixtures (${loaded.length} collection(s) reloaded).`,
7509
7985
  filesCreated: result.writtenFiles,
@@ -7518,14 +7994,14 @@ var regen = new Command55("regen").description("clear the database, regenerate f
7518
7994
  );
7519
7995
 
7520
7996
  // src/commands/fixtures.ts
7521
- var fixtures = new Command56("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7997
+ var fixtures = new Command58("fixtures").description("manage fixture data").configureHelp(helpConfig).addCommand(generate2).addCommand(load).addCommand(clear).addCommand(reset).addCommand(regen);
7522
7998
 
7523
7999
  // src/commands/seeds.ts
7524
- import { Command as Command60 } from "commander";
8000
+ import { Command as Command62 } from "commander";
7525
8001
 
7526
8002
  // src/commands/seeds/load.ts
7527
- import { Command as Command57 } from "commander";
7528
- var load2 = new Command57("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
8003
+ import { Command as Command59 } from "commander";
8004
+ var load2 = new Command59("load").description("load seeds into the database").option("-f, --force", "load even if target collections already have records").configureHelp(helpConfig).action(
7529
8005
  (opts) => runCommand(async () => {
7530
8006
  const { workspaceRootDir } = await getWorkspace();
7531
8007
  const seedFiles = getSeedFiles(workspaceRootDir);
@@ -7564,7 +8040,7 @@ var load2 = new Command57("load").description("load seeds into the database").op
7564
8040
  // src/commands/seeds/save.ts
7565
8041
  import fs30 from "node:fs";
7566
8042
  import path27 from "node:path";
7567
- import { Command as Command58 } from "commander";
8043
+ import { Command as Command60 } from "commander";
7568
8044
  var padZeros2 = (num, length) => num.toString().padStart(length, "0");
7569
8045
  function filterSystemFields(record, systemFieldNames) {
7570
8046
  const out = {};
@@ -7575,7 +8051,7 @@ function filterSystemFields(record, systemFieldNames) {
7575
8051
  }
7576
8052
  return out;
7577
8053
  }
7578
- var save = new Command58("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
8054
+ var save = new Command60("save").description("save the current data as seeds").option("-f, --force", "overwrite existing seed files").configureHelp(helpConfig).action(
7579
8055
  (opts) => runCommand(async () => {
7580
8056
  const { workspaceRootDir } = await getWorkspace();
7581
8057
  const seedsPath = dataDir(workspaceRootDir, "seeds");
@@ -7647,123 +8123,50 @@ var save = new Command58("save").description("save the current data as seeds").o
7647
8123
  );
7648
8124
 
7649
8125
  // src/commands/seeds/clear.ts
7650
- import { Command as Command59 } from "commander";
7651
- var clear2 = new Command59("clear").description("clear seeded records").configureHelp(helpConfig).action(
8126
+ import { Command as Command61 } from "commander";
8127
+ var clear2 = new Command61("clear").description("clear seeded records").configureHelp(helpConfig).action(
7652
8128
  () => runCommand(async () => {
7653
8129
  const { workspaceRootDir } = await getWorkspace();
7654
8130
  const seedFiles = getSeedFiles(workspaceRootDir);
7655
8131
  if (seedFiles.length === 0) {
7656
- reportResult({
7657
- summary: "No seed files found in data/seeds.",
7658
- nextSteps: ["Run `vela seeds save` to create seed files from the current database."]
7659
- });
7660
- return;
7661
- }
7662
- let cleared = [];
7663
- await withPocketbase(workspaceRootDir, async (pb) => {
7664
- cleared = await clearSeeds(pb, workspaceRootDir, seedFiles);
7665
- });
7666
- if (cleared.length === 0) {
7667
- reportResult({
7668
- summary: "No seeded records found to clear.",
7669
- nextSteps: ["Run `vela seeds load` to load seed records into the database."]
7670
- });
7671
- return;
7672
- }
7673
- reportResult({
7674
- summary: `Cleared ${cleared.length} seed file(s) worth of records.`,
7675
- recordsCleared: cleared,
7676
- nextSteps: ["Run `vela seeds load` to reload seeds from the files in data/seeds."]
7677
- });
7678
- }, "Failed to clear seeds.")
7679
- );
7680
-
7681
- // src/commands/seeds.ts
7682
- var seeds = new Command60("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7683
-
7684
- // src/commands/signup.ts
7685
- import { Command as Command62 } from "commander";
7686
- import * as p37 from "@clack/prompts";
7687
- import makeFetchCookie2 from "fetch-cookie";
7688
-
7689
- // src/commands/login.ts
7690
- import os4 from "node:os";
7691
- import { Command as Command61 } from "commander";
7692
- import * as p36 from "@clack/prompts";
7693
- import makeFetchCookie from "fetch-cookie";
7694
- var login = new Command61("login").description("login to velastack.dev").configureHelp(helpConfig).action(
7695
- () => runCommand(async () => {
7696
- const { email: email3, password: password11 } = await p36.group({
7697
- email: () => p36.text({ message: "Email" }),
7698
- password: () => p36.password({ message: "Password" })
7699
- });
7700
- const fetchCookie = makeFetchCookie(fetch);
7701
- const loginRes = await fetchCookie(`${API_URL}/login`, {
7702
- method: "POST",
7703
- headers: {
7704
- "Content-Type": "application/x-www-form-urlencoded",
7705
- Origin: API_URL
7706
- },
7707
- body: new URLSearchParams({
7708
- type: "password",
7709
- email: email3,
7710
- password: password11
7711
- }).toString()
7712
- });
7713
- if (!loginRes.headers.get("Set-Cookie")) {
7714
- throw new Error(
7715
- "Run `vela signup` to create an account or reset at https://velastack.dev/reset"
7716
- );
8132
+ reportResult({
8133
+ summary: "No seed files found in data/seeds.",
8134
+ nextSteps: ["Run `vela seeds save` to create seed files from the current database."]
8135
+ });
8136
+ return;
7717
8137
  }
7718
- const apiKey = await issueApiKey(fetchCookie);
7719
- writeConfig({ apiKey });
7720
- p36.log.success("Logged in to velastack.dev");
7721
- }, "Failed to login.")
7722
- );
7723
- async function issueApiKey(fetchCookie) {
7724
- const label4 = `CLI - ${os4.hostname()}`;
7725
- await fetchCookie(`${API_URL}/api-keys/new`, {
7726
- method: "POST",
7727
- headers: {
7728
- "Content-Type": "application/x-www-form-urlencoded",
7729
- Origin: API_URL
7730
- },
7731
- body: new URLSearchParams({ label: label4 }).toString()
7732
- });
7733
- const cookie = await fetchCookie.cookieJar.getCookieString(API_URL);
7734
- const apiKey = extractApiKey(cookie);
7735
- if (!apiKey) {
7736
- throw new Error("Failed to create API key. Try again or contact support.");
7737
- }
7738
- const [id] = apiKey.split(".");
7739
- const res = await fetchCookie(`${API_URL}/api/collections/api_keys/records`, {
7740
- headers: { Authorization: `Bearer ${apiKey}` }
7741
- });
7742
- const data = await res.json();
7743
- for (const item of data.items) {
7744
- if (item.label === label4 && item.id !== id) {
7745
- await fetchCookie(`${API_URL}/api/collections/api_keys/records/${item.id}`, {
7746
- method: "DELETE",
7747
- headers: { Authorization: `Bearer ${apiKey}` }
8138
+ let cleared = [];
8139
+ await withPocketbase(workspaceRootDir, async (pb) => {
8140
+ cleared = await clearSeeds(pb, workspaceRootDir, seedFiles);
8141
+ });
8142
+ if (cleared.length === 0) {
8143
+ reportResult({
8144
+ summary: "No seeded records found to clear.",
8145
+ nextSteps: ["Run `vela seeds load` to load seed records into the database."]
7748
8146
  });
8147
+ return;
7749
8148
  }
7750
- }
7751
- return apiKey;
7752
- }
7753
- function extractApiKey(cookie) {
7754
- const flashCookie = cookie.split(";").find((c) => c.trim().startsWith("flash="));
7755
- if (!flashCookie) return null;
7756
- const decoded = decodeURIComponent(flashCookie.split("=")[1]);
7757
- return JSON.parse(decoded).apiKey;
7758
- }
8149
+ reportResult({
8150
+ summary: `Cleared ${cleared.length} seed file(s) worth of records.`,
8151
+ recordsCleared: cleared,
8152
+ nextSteps: ["Run `vela seeds load` to reload seeds from the files in data/seeds."]
8153
+ });
8154
+ }, "Failed to clear seeds.")
8155
+ );
8156
+
8157
+ // src/commands/seeds.ts
8158
+ var seeds = new Command62("seeds").description("manage seed data").configureHelp(helpConfig).addCommand(load2).addCommand(save).addCommand(clear2);
7759
8159
 
7760
8160
  // src/commands/signup.ts
7761
- var signup = new Command62("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
8161
+ import { Command as Command63 } from "commander";
8162
+ import * as p39 from "@clack/prompts";
8163
+ import makeFetchCookie2 from "fetch-cookie";
8164
+ var signup = new Command63("signup").description("signup to velastack.dev").configureHelp(helpConfig).action(
7762
8165
  () => runCommand(async () => {
7763
- const { email: email3, password: password11, passwordConfirm } = await p37.group({
7764
- email: () => p37.text({ message: "Email" }),
7765
- password: () => p37.password({ message: "Password" }),
7766
- passwordConfirm: () => p37.password({ message: "Confirm password" })
8166
+ const { email: email3, password: password11, passwordConfirm } = await p39.group({
8167
+ email: () => p39.text({ message: "Email" }),
8168
+ password: () => p39.password({ message: "Password" }),
8169
+ passwordConfirm: () => p39.password({ message: "Confirm password" })
7767
8170
  });
7768
8171
  if (password11 !== passwordConfirm) {
7769
8172
  throw new Error("Passwords do not match.");
@@ -7787,33 +8190,33 @@ var signup = new Command62("signup").description("signup to velastack.dev").conf
7787
8190
  }
7788
8191
  const apiKey = await issueApiKey(fetchCookie);
7789
8192
  writeConfig({ apiKey });
7790
- p37.log.success("Signed up to velastack.dev");
7791
- p37.log.info("Check your email for a confirmation link.");
8193
+ p39.log.success("Signed up to velastack.dev");
8194
+ p39.log.info("Check your email for a confirmation link.");
7792
8195
  }, "Failed to signup.")
7793
8196
  );
7794
8197
 
7795
8198
  // src/commands/logout.ts
7796
- import { Command as Command63 } from "commander";
7797
- import * as p38 from "@clack/prompts";
7798
- var logout = new Command63("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
8199
+ import { Command as Command64 } from "commander";
8200
+ import * as p40 from "@clack/prompts";
8201
+ var logout = new Command64("logout").alias("signout").description("logout from velastack.dev").configureHelp(helpConfig).action(
7799
8202
  () => runCommand(() => {
7800
8203
  if (!readConfig()) {
7801
- p38.log.info("Not logged in");
8204
+ p40.log.info("Not logged in");
7802
8205
  return;
7803
8206
  }
7804
8207
  clearConfig();
7805
- p38.log.success("Logged out of velastack.dev");
8208
+ p40.log.success("Logged out of velastack.dev");
7806
8209
  })
7807
8210
  );
7808
8211
 
7809
8212
  // src/commands/whoami.ts
7810
- import { Command as Command64 } from "commander";
7811
- import * as p39 from "@clack/prompts";
7812
- var whoami = new Command64("whoami").description("show the current user").configureHelp(helpConfig).action(
8213
+ import { Command as Command65 } from "commander";
8214
+ import * as p41 from "@clack/prompts";
8215
+ var whoami = new Command65("whoami").description("show the current user").configureHelp(helpConfig).action(
7813
8216
  () => runCommand(async () => {
7814
8217
  const apiKey = readConfig()?.apiKey;
7815
8218
  if (!apiKey) {
7816
- p39.log.info("Not logged in. Run `vela login` to login.");
8219
+ p41.log.info("Not logged in. Run `vela login` to login.");
7817
8220
  return;
7818
8221
  }
7819
8222
  const res = await fetch(`${API_URL}/api/collections/users/records`, {
@@ -7821,22 +8224,22 @@ var whoami = new Command64("whoami").description("show the current user").config
7821
8224
  });
7822
8225
  const data = await res.json();
7823
8226
  if (!data.items.length) throw new Error("No user found. Run `vela login` to login.");
7824
- p39.log.success(`Logged in as ${data.items[0].email}`);
8227
+ p41.log.success(`Logged in as ${data.items[0].email}`);
7825
8228
  })
7826
8229
  );
7827
8230
 
7828
8231
  // src/commands/migrate.ts
7829
- import { Command as Command70 } from "commander";
8232
+ import { Command as Command71 } from "commander";
7830
8233
 
7831
8234
  // src/commands/migrate/up.ts
7832
- import { Command as Command65 } from "commander";
8235
+ import { Command as Command66 } from "commander";
7833
8236
 
7834
8237
  // src/lib/migrate.ts
7835
8238
  import path28 from "node:path";
7836
- import process20 from "node:process";
8239
+ import process23 from "node:process";
7837
8240
  import { x as x2 } from "tinyexec";
7838
8241
  async function runPocketbaseMigrate(args) {
7839
- const cwd = process20.cwd();
8242
+ const cwd = process23.cwd();
7840
8243
  const { getBinaryPath } = await import("pocketbase-server");
7841
8244
  const binaryPath = getBinaryPath();
7842
8245
  await x2(
@@ -7868,10 +8271,10 @@ async function runMigrateUp() {
7868
8271
  ]
7869
8272
  });
7870
8273
  }
7871
- var up = new Command65("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
8274
+ var up = new Command66("up").description("apply all pending migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations."));
7872
8275
 
7873
8276
  // src/commands/migrate/down.ts
7874
- import { Command as Command66, InvalidArgumentError as InvalidArgumentError3 } from "commander";
8277
+ import { Command as Command67, InvalidArgumentError as InvalidArgumentError3 } from "commander";
7875
8278
  function parseSteps(value) {
7876
8279
  const n = parseInt(value, 10);
7877
8280
  if (!Number.isFinite(n) || n <= 0) {
@@ -7879,7 +8282,7 @@ function parseSteps(value) {
7879
8282
  }
7880
8283
  return n;
7881
8284
  }
7882
- var down = new Command66("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
8285
+ var down = new Command67("down").alias("rollback").description("revert the last N applied migrations").argument("[number]", "how many migrations to revert", parseSteps, 1).configureHelp(helpConfig).action(
7883
8286
  (n) => runCommand(async () => {
7884
8287
  await runPocketbaseMigrate(["down", String(n)]);
7885
8288
  reportResult({
@@ -7895,11 +8298,11 @@ var down = new Command66("down").alias("rollback").description("revert the last
7895
8298
  // src/commands/migrate/create.ts
7896
8299
  import fs31 from "node:fs";
7897
8300
  import path29 from "node:path";
7898
- import process21 from "node:process";
7899
- import { Command as Command67 } from "commander";
7900
- var create2 = new Command67("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
8301
+ import process24 from "node:process";
8302
+ import { Command as Command68 } from "commander";
8303
+ var create2 = new Command68("create").alias("new").description("create a new blank migration").argument("<name>", "migration name (snake_case)").configureHelp(helpConfig).action(
7901
8304
  (name) => runCommand(async () => {
7902
- const cwd = process21.cwd();
8305
+ const cwd = process24.cwd();
7903
8306
  const before = listMigrationFiles(cwd);
7904
8307
  await runPocketbaseMigrate(["create", name]);
7905
8308
  const after = listMigrationFiles(cwd);
@@ -7923,11 +8326,11 @@ function listMigrationFiles(cwd) {
7923
8326
  // src/commands/migrate/collections.ts
7924
8327
  import fs32 from "node:fs";
7925
8328
  import path30 from "node:path";
7926
- import process22 from "node:process";
7927
- import { Command as Command68 } from "commander";
7928
- var collections = new Command68("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
8329
+ import process25 from "node:process";
8330
+ import { Command as Command69 } from "commander";
8331
+ var collections = new Command69("collections").alias("snapshot").description("snapshot local collections into a new migration").configureHelp(helpConfig).action(
7929
8332
  () => runCommand(async () => {
7930
- const cwd = process22.cwd();
8333
+ const cwd = process25.cwd();
7931
8334
  const before = listMigrationFiles2(cwd);
7932
8335
  await runPocketbaseMigrate(["collections"]);
7933
8336
  const after = listMigrationFiles2(cwd);
@@ -7956,8 +8359,8 @@ function listMigrationFiles2(cwd) {
7956
8359
  }
7957
8360
 
7958
8361
  // src/commands/migrate/history-sync.ts
7959
- import { Command as Command69 } from "commander";
7960
- var historySync = new Command69("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
8362
+ import { Command as Command70 } from "commander";
8363
+ var historySync = new Command70("history-sync").description("drop _migrations rows whose files no longer exist").configureHelp(helpConfig).action(
7961
8364
  () => runCommand(async () => {
7962
8365
  await runPocketbaseMigrate(["history-sync"]);
7963
8366
  reportResult({
@@ -7968,20 +8371,20 @@ var historySync = new Command69("history-sync").description("drop _migrations ro
7968
8371
  );
7969
8372
 
7970
8373
  // src/commands/migrate.ts
7971
- var migrate = new Command70("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
8374
+ var migrate = new Command71("migrate").description("manage database migrations").configureHelp(helpConfig).action(() => runCommand(runMigrateUp, "Failed to run migrations.")).addCommand(up).addCommand(down).addCommand(create2).addCommand(collections).addCommand(historySync);
7972
8375
 
7973
8376
  // src/commands/dev.ts
7974
8377
  import fs33 from "node:fs";
7975
8378
  import path32 from "node:path";
7976
- import process24 from "node:process";
8379
+ import process27 from "node:process";
7977
8380
  import { performance } from "node:perf_hooks";
7978
- import { Command as Command71, InvalidArgumentError as InvalidArgumentError4 } from "commander";
8381
+ import { Command as Command72, InvalidArgumentError as InvalidArgumentError4 } from "commander";
7979
8382
  import pc15 from "picocolors";
7980
8383
  import PocketBase4 from "pocketbase";
7981
8384
 
7982
8385
  // src/lib/vite.ts
7983
8386
  import path31 from "node:path";
7984
- import process23 from "node:process";
8387
+ import process26 from "node:process";
7985
8388
  import { createRequire as createRequire2 } from "node:module";
7986
8389
  import { pathToFileURL as pathToFileURL2 } from "node:url";
7987
8390
  import pc14 from "picocolors";
@@ -8005,13 +8408,13 @@ function resolveProjectVite(cwd) {
8005
8408
  return null;
8006
8409
  }
8007
8410
  }
8008
- async function loadVite(cwd = process23.cwd()) {
8411
+ async function loadVite(cwd = process26.cwd()) {
8009
8412
  const entry = resolveProjectVite(cwd);
8010
8413
  const vite = entry ? await import(pathToFileURL2(entry).href) : await import("vite");
8011
8414
  const error = viteVersionError(vite.version);
8012
8415
  if (error) {
8013
8416
  console.error(`${pc14.redBright("\u2717")} ${error}`);
8014
- process23.exit(1);
8417
+ process26.exit(1);
8015
8418
  }
8016
8419
  return vite;
8017
8420
  }
@@ -8024,16 +8427,16 @@ function parsePort(value) {
8024
8427
  }
8025
8428
  return port;
8026
8429
  }
8027
- var dev = new Command71("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
8028
- const cwd = process24.cwd();
8029
- process24.env.VELA_DATA_DIR ??= localDataDir(cwd);
8430
+ var dev = new Command72("dev").description("start the development server").option("--open [path]", "open the app in a browser once the server is ready").option("--host [host]", "expose the server on the network").option("--port <port>", "port to listen on", parsePort).option("--strictPort", "exit if the port is already in use instead of taking the next one").option("--cors", "enable CORS").option("--force", "re-bundle dependencies, ignoring the optimizer cache").configureHelp(helpConfig).action(async (options) => {
8431
+ const cwd = process27.cwd();
8432
+ process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
8030
8433
  const startTime = performance.now();
8031
8434
  const { createServer, version } = await loadVite(cwd);
8032
8435
  const viteMetadataDir = path32.join(cwd, "node_modules", ".vite");
8033
8436
  const viteMetadataFile = path32.join(viteMetadataDir, "_pocketbase_metadata.json");
8034
8437
  let pbProc;
8035
8438
  const backend3 = hasBackend(cwd);
8036
- const needsStart = backend3 && !process24.env.POCKETBASE_URL;
8439
+ const needsStart = backend3 && !process27.env.POCKETBASE_URL;
8037
8440
  const cleanup = () => {
8038
8441
  if (pbProc?.pid) pbProc.kill();
8039
8442
  if (fs33.existsSync(viteMetadataFile)) fs33.rmSync(viteMetadataFile);
@@ -8048,15 +8451,15 @@ var dev = new Command71("dev").description("start the development server").optio
8048
8451
  stdio: "pipe"
8049
8452
  });
8050
8453
  pbProc = started.proc;
8051
- process24.env.POCKETBASE_URL = started.url;
8052
- pbProc.stdout?.pipe(process24.stdout);
8053
- pbProc.stderr?.pipe(process24.stderr);
8454
+ process27.env.POCKETBASE_URL = started.url;
8455
+ pbProc.stdout?.pipe(process27.stdout);
8456
+ pbProc.stderr?.pipe(process27.stderr);
8054
8457
  pbProc.on("error", (err) => console.error("PocketBase error:", err));
8055
8458
  pbProc.on("exit", (code) => console.log(`PocketBase exited with code ${code}`));
8056
- process24.on("exit", cleanup);
8057
- process24.on("SIGINT", () => {
8459
+ process27.on("exit", cleanup);
8460
+ process27.on("SIGINT", () => {
8058
8461
  cleanup();
8059
- process24.exit(0);
8462
+ process27.exit(0);
8060
8463
  });
8061
8464
  }
8062
8465
  const serverOptions = {};
@@ -8078,21 +8481,21 @@ var dev = new Command71("dev").description("start the development server").optio
8078
8481
  await fs33.promises.writeFile(
8079
8482
  viteMetadataFile,
8080
8483
  JSON.stringify({
8081
- pocketbaseUrl: process24.env.POCKETBASE_URL,
8484
+ pocketbaseUrl: process27.env.POCKETBASE_URL,
8082
8485
  vitePort,
8083
8486
  viteHost
8084
8487
  })
8085
8488
  );
8086
- const pb = new PocketBase4(process24.env.POCKETBASE_URL);
8489
+ const pb = new PocketBase4(process27.env.POCKETBASE_URL);
8087
8490
  await pb.collection("_superusers").authWithPassword(
8088
- process24.env.POCKETBASE_SUPERUSER_EMAIL,
8089
- process24.env.POCKETBASE_SUPERUSER_PASSWORD
8491
+ process27.env.POCKETBASE_SUPERUSER_EMAIL,
8492
+ process27.env.POCKETBASE_SUPERUSER_PASSWORD
8090
8493
  );
8091
8494
  await pb.settings.update({ meta: { appURL: `http://${viteHost}:${vitePort}` } });
8092
8495
  await startWatchingTypes(cwd, pb);
8093
8496
  });
8094
8497
  await server.listen();
8095
- const hasExistingLogs = process24.stdout.bytesWritten > 0 || process24.stderr.bytesWritten > 0;
8498
+ const hasExistingLogs = process27.stdout.bytesWritten > 0 || process27.stderr.bytesWritten > 0;
8096
8499
  const startupDurationString = pc15.dim(
8097
8500
  `ready in ${pc15.reset(pc15.bold(Math.ceil(performance.now() - startTime)))} ms`
8098
8501
  );
@@ -8132,9 +8535,9 @@ async function startWatchingTypes(cwd, pb) {
8132
8535
  // src/commands/build.ts
8133
8536
  import fs34 from "node:fs";
8134
8537
  import path33 from "node:path";
8135
- import process26 from "node:process";
8136
- import { Command as Command72 } from "commander";
8137
- import * as p40 from "@clack/prompts";
8538
+ import process29 from "node:process";
8539
+ import { Command as Command73 } from "commander";
8540
+ import * as p42 from "@clack/prompts";
8138
8541
  import pc16 from "picocolors";
8139
8542
  import { x as x3 } from "tinyexec";
8140
8543
  import { detect as detect5 } from "package-manager-detector";
@@ -8147,10 +8550,10 @@ function applyBuildEnv(cwd, env2 = process.env) {
8147
8550
  }
8148
8551
 
8149
8552
  // src/lib/origin.ts
8150
- import process25 from "node:process";
8553
+ import process28 from "node:process";
8151
8554
  function resolveOrigin(workspaceRootDir, envTag, config = {}) {
8152
8555
  return normalizeOrigin(
8153
- process25.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8556
+ process28.env.VELA_ORIGIN ?? readBinding(workspaceRootDir, envTag)?.domain ?? config.deploy?.domain
8154
8557
  );
8155
8558
  }
8156
8559
  function normalizeOrigin(value) {
@@ -8170,13 +8573,13 @@ function splitHosts(value) {
8170
8573
 
8171
8574
  // src/commands/build.ts
8172
8575
  var PRERENDERED_DIR = path33.join(".svelte-kit", "output", "prerendered");
8173
- var build = new Command72("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
8174
- const cwd = process26.cwd();
8576
+ var build = new Command73("build").description("build the app").configureHelp(helpConfig).option("-t, --target <target>", "which copy of the app to build for", PRODUCTION_TARGET).action(async (options) => {
8577
+ const cwd = process29.cwd();
8175
8578
  applyBuildEnv(cwd);
8176
8579
  const origin = await originForBuild(cwd, options.target);
8177
- if (origin) process26.env.VELA_ORIGIN = origin;
8580
+ if (origin) process29.env.VELA_ORIGIN = origin;
8178
8581
  let pbProc;
8179
- const needsStart = hasBackend(cwd) && !process26.env.POCKETBASE_URL;
8582
+ const needsStart = hasBackend(cwd) && !process29.env.POCKETBASE_URL;
8180
8583
  const cleanup = () => {
8181
8584
  if (pbProc?.pid) pbProc.kill();
8182
8585
  };
@@ -8190,11 +8593,11 @@ var build = new Command72("build").description("build the app").configureHelp(he
8190
8593
  dev: true
8191
8594
  });
8192
8595
  pbProc = started.proc;
8193
- process26.env.POCKETBASE_URL = started.url;
8194
- process26.on("exit", cleanup);
8195
- process26.on("SIGINT", () => {
8596
+ process29.env.POCKETBASE_URL = started.url;
8597
+ process29.on("exit", cleanup);
8598
+ process29.on("SIGINT", () => {
8196
8599
  cleanup();
8197
- process26.exit(0);
8600
+ process29.exit(0);
8198
8601
  });
8199
8602
  }
8200
8603
  try {
@@ -8227,7 +8630,7 @@ async function originForBuild(cwd, target) {
8227
8630
  function warnIfPrerendered(cwd) {
8228
8631
  const dir = path33.join(cwd, PRERENDERED_DIR);
8229
8632
  if (!fs34.existsSync(dir) || fs34.readdirSync(dir).length === 0) return;
8230
- p40.log.warn(
8633
+ p42.log.warn(
8231
8634
  `Prerendered pages were built with no domain configured, so their canonical
8232
8635
  links point at SvelteKit's placeholder host rather than at this site.
8233
8636
 
@@ -8237,16 +8640,16 @@ Set one with ${pc16.cyan("vela deploy --domain example.com")}, or pass ${pc16.cy
8237
8640
 
8238
8641
  // src/commands/preview.ts
8239
8642
  import path34 from "node:path";
8240
- import process27 from "node:process";
8241
- import { Command as Command73 } from "commander";
8643
+ import process30 from "node:process";
8644
+ import { Command as Command74 } from "commander";
8242
8645
  import { x as x4 } from "tinyexec";
8243
8646
  import { detect as detect6 } from "package-manager-detector";
8244
8647
  import { resolveCommand as resolveCommand6 } from "package-manager-detector/commands";
8245
- var preview = new Command73("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
8246
- const cwd = process27.cwd();
8247
- process27.env.VELA_DATA_DIR ??= localDataDir(cwd);
8648
+ var preview = new Command74("preview").description("preview the built app").configureHelp(helpConfig).action(async () => {
8649
+ const cwd = process30.cwd();
8650
+ process30.env.VELA_DATA_DIR ??= localDataDir(cwd);
8248
8651
  let pbProc;
8249
- const needsStart = hasBackend(cwd) && !process27.env.POCKETBASE_URL;
8652
+ const needsStart = hasBackend(cwd) && !process30.env.POCKETBASE_URL;
8250
8653
  const cleanup = () => {
8251
8654
  if (pbProc?.pid) pbProc.kill();
8252
8655
  };
@@ -8259,11 +8662,11 @@ var preview = new Command73("preview").description("preview the built app").conf
8259
8662
  dev: true
8260
8663
  });
8261
8664
  pbProc = started.proc;
8262
- process27.env.POCKETBASE_URL = started.url;
8263
- process27.on("exit", cleanup);
8264
- process27.on("SIGINT", () => {
8665
+ process30.env.POCKETBASE_URL = started.url;
8666
+ process30.on("exit", cleanup);
8667
+ process30.on("SIGINT", () => {
8265
8668
  cleanup();
8266
- process27.exit(0);
8669
+ process30.exit(0);
8267
8670
  });
8268
8671
  }
8269
8672
  try {
@@ -8282,8 +8685,8 @@ var preview = new Command73("preview").description("preview the built app").conf
8282
8685
 
8283
8686
  // src/commands/sync.ts
8284
8687
  import path35 from "node:path";
8285
- import { Command as Command74 } from "commander";
8286
- var sync = new Command74("sync").description("sync types from the database").configureHelp(helpConfig).action(
8688
+ import { Command as Command75 } from "commander";
8689
+ var sync = new Command75("sync").description("sync types from the database").configureHelp(helpConfig).action(
8287
8690
  () => runCommand(async () => {
8288
8691
  const { workspaceRootDir } = await getWorkspace();
8289
8692
  const typesDir = path35.join(workspaceRootDir, ".svelte-kit", "types");
@@ -8296,8 +8699,8 @@ var sync = new Command74("sync").description("sync types from the database").con
8296
8699
  );
8297
8700
 
8298
8701
  // src/commands/provision.ts
8299
- import { Command as Command75 } from "commander";
8300
- import * as p41 from "@clack/prompts";
8702
+ import { Command as Command76 } from "commander";
8703
+ import * as p43 from "@clack/prompts";
8301
8704
  import pc17 from "picocolors";
8302
8705
  import * as v7 from "valibot";
8303
8706
  var OptionsSchema2 = v7.object({
@@ -8306,24 +8709,24 @@ var OptionsSchema2 = v7.object({
8306
8709
  nodeMajor: v7.optional(v7.string())
8307
8710
  });
8308
8711
  var provision = addSshOptions(
8309
- new Command75("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
8712
+ new Command76("provision").description("prepare a server to host vela apps").argument("<target>", "SSH target \u2014 an alias from ~/.ssh/config, or user@host").configureHelp(helpConfig)
8310
8713
  ).option("--pb-version <version>", "PocketBase version to install").option("--node-major <version>", "Node.js major version to install", "22").action(
8311
8714
  (target, raw) => runCommand(async () => {
8312
8715
  const options = parseOptions(OptionsSchema2, raw);
8313
8716
  const pbVersion = options.pbVersion ?? pocketbaseVersion();
8314
- p41.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8315
- p41.log.info(`Target ${pc17.cyan(target)}`);
8717
+ p43.intro(pc17.bgCyan(pc17.black(" vela provision ")));
8718
+ p43.log.info(`Target ${pc17.cyan(target)}`);
8316
8719
  await withSsh(target, sshOptionsFrom(options), async (session) => {
8317
8720
  await session.detectElevation();
8318
8721
  const existing = await readServerInfo(session);
8319
8722
  if (existing) {
8320
- p41.log.info(
8723
+ p43.log.info(
8321
8724
  `Already provisioned by vela ${existing.cliVersion} on ${existing.provisionedAt}. Bringing it up to date.`
8322
8725
  );
8323
8726
  }
8324
- p41.log.step("Uploading server scripts");
8727
+ p43.log.step("Uploading server scripts");
8325
8728
  await syncServerScripts(session);
8326
- p41.log.step("Running provision");
8729
+ p43.log.step("Running provision");
8327
8730
  const result = await runServerScript(session, "provision.sh", {
8328
8731
  args: [
8329
8732
  "--pb-version",
@@ -8335,7 +8738,7 @@ var provision = addSshOptions(
8335
8738
  ],
8336
8739
  stream: true
8337
8740
  });
8338
- p41.log.success(
8741
+ p43.log.success(
8339
8742
  `${target} is ready.
8340
8743
 
8341
8744
  Node ${result?.node ?? "installed"}
@@ -8343,29 +8746,29 @@ var provision = addSshOptions(
8343
8746
  PocketBase ${result?.pocketbase ?? pbVersion}`
8344
8747
  );
8345
8748
  });
8346
- p41.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8749
+ p43.outro(`Deploy with ${pc17.cyan(`vela deploy --server ${target}`)}`);
8347
8750
  }, "Failed to provision.")
8348
8751
  );
8349
8752
 
8350
8753
  // src/commands/deploy.ts
8351
8754
  import path38 from "node:path";
8352
8755
  import fs37 from "node:fs";
8353
- import { Command as Command76, Option as Option2 } from "commander";
8354
- import * as p42 from "@clack/prompts";
8756
+ import { Command as Command77, Option as Option2 } from "commander";
8757
+ import * as p44 from "@clack/prompts";
8355
8758
  import pc18 from "picocolors";
8356
8759
  import * as v8 from "valibot";
8357
8760
 
8358
8761
  // src/lib/pocketbase-settings.ts
8359
8762
  import fs35 from "node:fs";
8360
8763
  import path36 from "node:path";
8361
- import process28 from "node:process";
8764
+ import process31 from "node:process";
8362
8765
  import PocketBase5 from "pocketbase";
8363
8766
  var COPIED_KEYS = ["appName", "senderName", "senderAddress"];
8364
8767
  async function readLocalMeta(cwd) {
8365
8768
  const dataDir2 = path36.join(cwd, DATA_DIR);
8366
8769
  if (!fs35.existsSync(dataDir2)) return null;
8367
- const email3 = process28.env.POCKETBASE_SUPERUSER_EMAIL;
8368
- const password11 = process28.env.POCKETBASE_SUPERUSER_PASSWORD;
8770
+ const email3 = process31.env.POCKETBASE_SUPERUSER_EMAIL;
8771
+ const password11 = process31.env.POCKETBASE_SUPERUSER_PASSWORD;
8369
8772
  if (!email3 || !password11) return null;
8370
8773
  let proc;
8371
8774
  try {
@@ -8694,7 +9097,7 @@ var OptionsSchema3 = v8.object({
8694
9097
  });
8695
9098
  var deploy = addLockWaitOption(
8696
9099
  addTargetOptions(
8697
- new Command76("deploy").description("deploy the app").configureHelp(helpConfig),
9100
+ new Command77("deploy").description("deploy the app").configureHelp(helpConfig),
8698
9101
  "production"
8699
9102
  )
8700
9103
  ).option("--project <name>", "override the project name").option("--domain <hosts>", "hostname(s) to serve on, comma separated").option("--health-path <path>", "path the health check requests").option("--keep <count>", "how many old releases to keep on the server").option("--pb-version <version>", "PocketBase version to run").option("--no-build", "deploy the existing build output without rebuilding").addOption(
@@ -8710,7 +9113,7 @@ var deploy = addLockWaitOption(
8710
9113
  (raw) => runCommand(async () => {
8711
9114
  const options = parseOptions(OptionsSchema3, raw);
8712
9115
  const backend3 = hasBackend();
8713
- p42.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
9116
+ p44.intro(pc18.bgCyan(pc18.black(" vela deploy ")));
8714
9117
  if (options.build !== false) {
8715
9118
  const { workspaceRootDir } = await getWorkspace();
8716
9119
  await prepareAdapter(workspaceRootDir);
@@ -8720,7 +9123,7 @@ var deploy = addLockWaitOption(
8720
9123
  {
8721
9124
  remote: async (ctx) => {
8722
9125
  const { session, instance, workspaceRootDir, config } = ctx;
8723
- p42.log.info(
9126
+ p44.log.info(
8724
9127
  `${pc18.cyan(ctx.appName)} ${pc18.dim("\u2192")} ${pc18.cyan(ctx.targetName)} ${pc18.dim(`(${ctx.server})`)}`
8725
9128
  );
8726
9129
  const [existing] = await readInstanceStates(session, instance);
@@ -8730,7 +9133,7 @@ var deploy = addLockWaitOption(
8730
9133
  const askedForRemoteDb = options.remoteDb ?? config.deploy?.buildAgainstRemote;
8731
9134
  const remoteDb = askedForRemoteDb ?? instanceHasBackend(existing);
8732
9135
  if (existing && instanceHasBackend(existing) !== backend3) {
8733
- p42.log.info(
9136
+ p44.log.info(
8734
9137
  backend3 ? `${pc18.cyan(ctx.targetName)} was deployed without a backend before. This deploy adds PocketBase.` : `${pc18.cyan(ctx.targetName)} was deployed with a backend before. This deploy removes PocketBase; its database stays on the server.`
8735
9138
  );
8736
9139
  }
@@ -8773,7 +9176,7 @@ with DNS of your own pointing at ${ctx.server}.`
8773
9176
  tunnel = await openDatabaseTunnel(session, instance, existing);
8774
9177
  } catch (err) {
8775
9178
  if (askedForRemoteDb) throw err;
8776
- p42.log.warn(
9179
+ p44.log.warn(
8777
9180
  `Could not build against the ${pc18.cyan(ctx.targetName)} database, using a local one instead.
8778
9181
  ${pc18.dim(String(err))}`
8779
9182
  );
@@ -8781,13 +9184,13 @@ ${pc18.dim(String(err))}`
8781
9184
  }
8782
9185
  if (tunnel) {
8783
9186
  buildEnv = { ...buildEnv, ...tunnel.env };
8784
- p42.log.info(
9187
+ p44.log.info(
8785
9188
  `Building against the ${pc18.cyan(ctx.targetName)} database on ${ctx.server} ${pc18.dim(`(port ${tunnel.pbPort})`)}`
8786
9189
  );
8787
9190
  } else if (backend3) {
8788
9191
  await ensureSuperuser(workspaceRootDir);
8789
9192
  }
8790
- p42.log.step("Building");
9193
+ p44.log.step("Building");
8791
9194
  try {
8792
9195
  await runBuild(workspaceRootDir, config.deploy?.buildCommand, buildEnv);
8793
9196
  } finally {
@@ -8795,9 +9198,9 @@ ${pc18.dim(String(err))}`
8795
9198
  }
8796
9199
  }
8797
9200
  const entries = collectArtifact(workspaceRootDir, config.deploy ?? {});
8798
- p42.log.step(`Uploading release ${pc18.dim(release)}`);
9201
+ p44.log.step(`Uploading release ${pc18.dim(release)}`);
8799
9202
  await uploadRelease(session, instance, release, entries);
8800
- p42.log.step("Activating");
9203
+ p44.log.step("Activating");
8801
9204
  result = await runServerScript(session, "apply.sh", {
8802
9205
  args: [
8803
9206
  instance,
@@ -8848,7 +9251,7 @@ ${pc18.dim(String(err))}`
8848
9251
  url: primaryHost ? url : void 0
8849
9252
  });
8850
9253
  const redirects = started?.environment.redirects ?? [];
8851
- p42.log.success(
9254
+ p44.log.success(
8852
9255
  `Deployed ${pc18.cyan(ctx.appName)} ${pc18.dim(release)}
8853
9256
 
8854
9257
  URL ${url}
@@ -8856,7 +9259,7 @@ ${pc18.dim(String(err))}`
8856
9259
  ` : "") + ` Port ${result?.webPort ?? "?"}${backend3 ? ` (PocketBase ${result?.pbPort ?? "?"})` : ""}`
8857
9260
  );
8858
9261
  if (managed && managed !== existing?.managed) {
8859
- p42.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
9262
+ p44.log.info(`${pc18.cyan(managed)} goes live within a minute.`);
8860
9263
  }
8861
9264
  if (result?.superuserCreated) {
8862
9265
  await copyLocalBranding(
@@ -8865,7 +9268,7 @@ ${pc18.dim(String(err))}`
8865
9268
  workspaceRootDir,
8866
9269
  primaryHost ? result?.url ?? "" : ""
8867
9270
  );
8868
- p42.log.info(
9271
+ p44.log.info(
8869
9272
  `Created the PocketBase superuser this app authenticates as.
8870
9273
 
8871
9274
  Its credentials are stored in the environment on the server. To use
@@ -8876,7 +9279,7 @@ and deploy again.`
8876
9279
  await reportAppURLDrift(session, instance, primaryHost);
8877
9280
  }
8878
9281
  if (!primaryHost) {
8879
- p42.log.warn(
9282
+ p44.log.warn(
8880
9283
  `No domain configured, so nothing is proxied to this app yet.
8881
9284
  Redeploy with ${pc18.cyan("--domain example.com")} once DNS points at ${ctx.server}` + (reporter.enabled ? "" : `,
8882
9285
  or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
@@ -8886,7 +9289,7 @@ or ${pc18.cyan("vela link")} it to get a free velastack.app hostname.`) + `.`
8886
9289
  },
8887
9290
  { project: options.project, askDomain: true, label: "deploy" }
8888
9291
  );
8889
- p42.outro(`${pc18.cyan("vela status")} to see what is running`);
9292
+ p44.outro(`${pc18.cyan("vela status")} to see what is running`);
8890
9293
  }, "Failed to deploy.")
8891
9294
  );
8892
9295
  async function prepareAdapter(workspaceRootDir) {
@@ -8905,8 +9308,8 @@ ${pc18.cyan(err.snippet)}` : err.message);
8905
9308
  outcome.packageJsonChanged ? "package.json" : void 0
8906
9309
  ].filter((f) => Boolean(f));
8907
9310
  const why = outcome.previous === "auto" ? `${ADAPTER_AUTO} builds nothing for a server of your own` : outcome.previous === "none" ? "No adapter was configured" : `${ADAPTER_NODE} was configured but not in package.json`;
8908
- p42.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
8909
- p42.log.info(
9311
+ p44.log.step(`Switching the adapter to ${pc18.cyan(ADAPTER_NODE)}`);
9312
+ p44.log.info(
8910
9313
  `${why}, and vela deploy runs the app as a Node server.
8911
9314
 
8912
9315
  Changed ${changed.join(", ")}` + (outcome.removedDeps.length ? `
@@ -8919,14 +9322,14 @@ ${pc18.cyan(err.snippet)}` : err.message);
8919
9322
  rethrow(err);
8920
9323
  }
8921
9324
  }
8922
- p42.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
9325
+ p44.log.warn(`Commit ${changed.join(", ")} so every deploy builds the same way.`);
8923
9326
  }
8924
9327
  async function reportAppURLDrift(session, instance, domain) {
8925
9328
  const expected = normalizeOrigin(domain);
8926
9329
  if (!expected) return;
8927
9330
  const current = await readRemoteAppURL(session, instance);
8928
9331
  if (!current || normalizeOrigin(current) === expected) return;
8929
- p42.log.warn(
9332
+ p44.log.warn(
8930
9333
  `This app's PocketBase ${pc18.cyan("appURL")} is ${pc18.dim(current)}, but it is served on ${pc18.dim(expected)}.
8931
9334
 
8932
9335
  Emails and anything else PocketBase links to will use the former. Update it in
@@ -8941,15 +9344,15 @@ async function copyLocalBranding(session, instance, workspaceRootDir, appURL) {
8941
9344
  if (copied.length === 0) return;
8942
9345
  const outcome = await restartInstance(session, instance);
8943
9346
  if (outcome.deployed && !outcome.restarted) {
8944
- p42.log.warn(
9347
+ p44.log.warn(
8945
9348
  `Copied ${copied.join(", ")}, but the app did not restart to pick them up.
8946
9349
  ${pc18.dim(outcome.error ?? "")}`
8947
9350
  );
8948
9351
  return;
8949
9352
  }
8950
- p42.log.success(`Copied ${copied.join(", ")} from this project's database`);
9353
+ p44.log.success(`Copied ${copied.join(", ")} from this project's database`);
8951
9354
  } catch (err) {
8952
- p42.log.warn(
9355
+ p44.log.warn(
8953
9356
  `Could not copy this project's PocketBase settings across.
8954
9357
  Set them in the admin panel instead. ${pc18.dim(String(err))}`
8955
9358
  );
@@ -9042,7 +9445,7 @@ async function reportEmptyEnvironment(session, instance, workspaceRootDir) {
9042
9445
  const remote = await readRemoteEnv(session, instance);
9043
9446
  if (Object.keys(remote).length > 0) return;
9044
9447
  if (!fs37.existsSync(path38.join(workspaceRootDir, ".env"))) return;
9045
- p42.log.warn(
9448
+ p44.log.warn(
9046
9449
  `This app has no production environment variables yet.
9047
9450
 
9048
9451
  Local ${pc18.cyan(".env")} values are not uploaded by a deploy. Set them with
@@ -9053,53 +9456,43 @@ async function serverTimeOrLocal(session) {
9053
9456
  try {
9054
9457
  return await serverTime(session);
9055
9458
  } catch {
9056
- p42.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9459
+ p44.log.warn("Could not read the clock on the server; stamping this release from this machine.");
9057
9460
  return /* @__PURE__ */ new Date();
9058
9461
  }
9059
9462
  }
9060
9463
 
9061
9464
  // src/commands/link.ts
9062
9465
  import path39 from "node:path";
9063
- import process29 from "node:process";
9064
- import { Command as Command77 } from "commander";
9065
- import * as p43 from "@clack/prompts";
9466
+ import process32 from "node:process";
9467
+ import { Command as Command78 } from "commander";
9468
+ import * as p45 from "@clack/prompts";
9066
9469
  var CREATE_NEW = "__new__";
9067
- var link = new Command77("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
9470
+ var link = new Command78("link").description("link this project to a velastack.dev project").configureHelp(helpConfig).action(() => runCommand(linkProject, "Failed to link the project."));
9068
9471
  async function linkProject() {
9069
9472
  const { workspaceRootDir } = await getWorkspace();
9070
9473
  const existing = readProjectConfig(workspaceRootDir);
9071
9474
  if (existing) {
9072
- p43.log.success(`Linked to ${existing.projectName}.`);
9475
+ p45.log.success(`Linked to ${existing.projectName}.`);
9073
9476
  return;
9074
9477
  }
9075
9478
  const apiKey = requireApiKey();
9076
- const [user, teams3, projects] = await Promise.all([
9077
- getCurrentUser(apiKey),
9078
- listTeams(apiKey),
9079
- listProjects(apiKey)
9080
- ]);
9081
- let projectId;
9082
- let teamId;
9083
- let projectName;
9479
+ const [teams3, projects] = await Promise.all([listTeams(apiKey), listProjects(apiKey)]);
9084
9480
  const picked = projects.length > 0 ? await pickExistingProject(projects) : CREATE_NEW;
9481
+ let linked;
9085
9482
  if (picked !== CREATE_NEW) {
9086
9483
  const project = projects.find((pr) => pr.id === picked);
9087
- projectId = project.id;
9088
- teamId = project.team;
9089
- projectName = project.name;
9484
+ linked = toLinked(project, project.expand?.team);
9090
9485
  } else {
9091
9486
  const team = await pickTeam(teams3);
9092
9487
  const name = await promptProjectName(workspaceRootDir);
9093
- const created = await createProject2(apiKey, { name, teamId: team.id, userId: user.id });
9094
- projectId = created.id;
9095
- teamId = team.id;
9096
- projectName = created.name;
9488
+ linked = await linkNewProject(apiKey, { name, teamId: team.id, interactive: true });
9097
9489
  }
9490
+ const { projectId, teamId, projectName } = linked;
9098
9491
  writeProjectConfig(workspaceRootDir, { projectId, teamId, projectName });
9099
- p43.log.success(`Linked to ${projectName}.`);
9492
+ p45.log.success(`Linked to ${projectName} (${linked.dashboardUrl}).`);
9100
9493
  }
9101
9494
  async function pickExistingProject(projects) {
9102
- const choice = await p43.select({
9495
+ const choice = await p45.select({
9103
9496
  message: "Select a project",
9104
9497
  options: [
9105
9498
  ...projects.map((pr) => ({
@@ -9109,39 +9502,24 @@ async function pickExistingProject(projects) {
9109
9502
  { value: CREATE_NEW, label: "Create a new project" }
9110
9503
  ]
9111
9504
  });
9112
- if (p43.isCancel(choice)) {
9113
- p43.cancel("Operation cancelled.");
9114
- process29.exit(0);
9505
+ if (p45.isCancel(choice)) {
9506
+ p45.cancel("Operation cancelled.");
9507
+ process32.exit(0);
9115
9508
  }
9116
9509
  return choice;
9117
9510
  }
9118
- async function pickTeam(teams3) {
9119
- if (teams3.length === 1) return teams3[0];
9120
- const choice = await p43.select({
9121
- message: "Select a team",
9122
- options: teams3.map((team) => ({
9123
- value: team.id,
9124
- label: team.is_personal ? `${team.name} (personal)` : team.name
9125
- }))
9126
- });
9127
- if (p43.isCancel(choice)) {
9128
- p43.cancel("Operation cancelled.");
9129
- process29.exit(0);
9130
- }
9131
- return teams3.find((team) => team.id === choice);
9132
- }
9133
9511
  async function promptProjectName(workspaceRootDir) {
9134
9512
  const defaultValue = defaultProjectName2(workspaceRootDir);
9135
- const value = await p43.text({
9513
+ const value = await p45.text({
9136
9514
  message: "Project name",
9137
9515
  defaultValue,
9138
9516
  initialValue: defaultValue,
9139
9517
  placeholder: defaultValue,
9140
9518
  validate: (v10) => !v10?.trim() ? "Required" : void 0
9141
9519
  });
9142
- if (p43.isCancel(value)) {
9143
- p43.cancel("Operation cancelled.");
9144
- process29.exit(0);
9520
+ if (p45.isCancel(value)) {
9521
+ p45.cancel("Operation cancelled.");
9522
+ process32.exit(0);
9145
9523
  }
9146
9524
  return value.trim();
9147
9525
  }
@@ -9156,14 +9534,14 @@ function defaultProjectName2(workspaceRootDir) {
9156
9534
  }
9157
9535
 
9158
9536
  // src/commands/env.ts
9159
- import { Command as Command82 } from "commander";
9537
+ import { Command as Command83 } from "commander";
9160
9538
 
9161
9539
  // src/commands/env/list.ts
9162
- import { Command as Command78 } from "commander";
9163
- import * as p44 from "@clack/prompts";
9540
+ import { Command as Command79 } from "commander";
9541
+ import * as p46 from "@clack/prompts";
9164
9542
  import pc19 from "picocolors";
9165
9543
  var envList = addTargetOptions(
9166
- new Command78("list").description("list environment variable names").configureHelp(helpConfig),
9544
+ new Command79("list").description("list environment variable names").configureHelp(helpConfig),
9167
9545
  "local"
9168
9546
  ).action(
9169
9547
  (raw) => runCommand(
@@ -9185,10 +9563,10 @@ var envList = addTargetOptions(
9185
9563
  );
9186
9564
  function report(keys, where) {
9187
9565
  if (keys.length === 0) {
9188
- p44.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9566
+ p46.log.info(`No environment variables configured ${pc19.dim(`(${where})`)}.`);
9189
9567
  return;
9190
9568
  }
9191
- p44.log.info(
9569
+ p46.log.info(
9192
9570
  `Environment ${pc19.dim(`(${where})`)}
9193
9571
 
9194
9572
  ` + keys.sort().map((key) => ` ${key}`).join("\n")
@@ -9196,12 +9574,12 @@ function report(keys, where) {
9196
9574
  }
9197
9575
 
9198
9576
  // src/commands/env/set.ts
9199
- import process30 from "node:process";
9200
- import { Command as Command79 } from "commander";
9201
- import * as p45 from "@clack/prompts";
9577
+ import process33 from "node:process";
9578
+ import { Command as Command80 } from "commander";
9579
+ import * as p47 from "@clack/prompts";
9202
9580
  import pc20 from "picocolors";
9203
9581
  var envSet = addTargetOptions(
9204
- new Command79("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
9582
+ new Command80("set").description("set an environment variable").argument("<key>", "variable name").argument("[value]", "value \u2014 prompted for, without echo, when omitted").configureHelp(helpConfig),
9205
9583
  "local"
9206
9584
  ).action(
9207
9585
  (key, value, raw) => runCommand(
@@ -9211,14 +9589,14 @@ var envSet = addTargetOptions(
9211
9589
  local: async (ctx) => {
9212
9590
  const resolved = await resolveValue(key, value);
9213
9591
  setLocalEnv(ctx.envFile, key, resolved);
9214
- p45.log.success(`${key} updated ${pc20.dim("(local)")}`);
9592
+ p47.log.success(`${key} updated ${pc20.dim("(local)")}`);
9215
9593
  await applyLocalEnvChange(ctx, [key]);
9216
9594
  },
9217
9595
  remote: async (ctx) => {
9218
9596
  const resolved = await resolveValue(key, value);
9219
9597
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9220
9598
  await writeRemoteEnv(ctx.session, ctx.instance, { ...env2, [key]: resolved });
9221
- p45.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9599
+ p47.log.success(`${key} updated ${pc20.dim(`(${ctx.targetName})`)}`);
9222
9600
  await applyEnvRestart(ctx, [key]);
9223
9601
  }
9224
9602
  },
@@ -9232,23 +9610,23 @@ async function resolveValue(key, value) {
9232
9610
  return value ?? await promptValue(key);
9233
9611
  }
9234
9612
  async function promptValue(key) {
9235
- const value = await p45.password({
9613
+ const value = await p47.password({
9236
9614
  message: `Value for ${pc20.cyan(key)}`,
9237
9615
  validate: (input) => !input?.length ? "Required" : void 0
9238
9616
  });
9239
- if (p45.isCancel(value)) {
9240
- p45.cancel("Operation cancelled.");
9241
- process30.exit(0);
9617
+ if (p47.isCancel(value)) {
9618
+ p47.cancel("Operation cancelled.");
9619
+ process33.exit(0);
9242
9620
  }
9243
9621
  return value;
9244
9622
  }
9245
9623
 
9246
9624
  // src/commands/env/unset.ts
9247
- import { Command as Command80 } from "commander";
9248
- import * as p46 from "@clack/prompts";
9625
+ import { Command as Command81 } from "commander";
9626
+ import * as p48 from "@clack/prompts";
9249
9627
  import pc21 from "picocolors";
9250
9628
  var envUnset = addTargetOptions(
9251
- new Command80("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
9629
+ new Command81("unset").description("remove an environment variable").argument("<key>", "variable name").configureHelp(helpConfig),
9252
9630
  "local"
9253
9631
  ).action(
9254
9632
  (key, raw) => runCommand(
@@ -9257,22 +9635,22 @@ var envUnset = addTargetOptions(
9257
9635
  {
9258
9636
  local: async (ctx) => {
9259
9637
  if (!(key in readLocalEnv(ctx.envFile))) {
9260
- p46.log.info(`${key} is not set \u2014 nothing to remove.`);
9638
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9261
9639
  return;
9262
9640
  }
9263
9641
  unsetLocalEnv(ctx.envFile, key);
9264
- p46.log.success(`${key} removed ${pc21.dim("(local)")}`);
9642
+ p48.log.success(`${key} removed ${pc21.dim("(local)")}`);
9265
9643
  await applyLocalEnvChange(ctx, [key]);
9266
9644
  },
9267
9645
  remote: async (ctx) => {
9268
9646
  const env2 = await readRemoteEnv(ctx.session, ctx.instance);
9269
9647
  if (!(key in env2)) {
9270
- p46.log.info(`${key} is not set \u2014 nothing to remove.`);
9648
+ p48.log.info(`${key} is not set \u2014 nothing to remove.`);
9271
9649
  return;
9272
9650
  }
9273
9651
  delete env2[key];
9274
9652
  await writeRemoteEnv(ctx.session, ctx.instance, env2);
9275
- p46.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9653
+ p48.log.success(`${key} removed ${pc21.dim(`(${ctx.targetName})`)}`);
9276
9654
  await applyEnvRestart(ctx, [key]);
9277
9655
  }
9278
9656
  },
@@ -9285,12 +9663,12 @@ var envUnset = addTargetOptions(
9285
9663
  // src/commands/env/import.ts
9286
9664
  import fs38 from "node:fs";
9287
9665
  import path40 from "node:path";
9288
- import process31 from "node:process";
9289
- import { Command as Command81 } from "commander";
9290
- import * as p47 from "@clack/prompts";
9666
+ import process34 from "node:process";
9667
+ import { Command as Command82 } from "commander";
9668
+ import * as p49 from "@clack/prompts";
9291
9669
  import pc22 from "picocolors";
9292
9670
  var envImport = addTargetOptions(
9293
- new Command81("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
9671
+ new Command82("import").description("merge a dotenv file into the environment").argument("<file>", "dotenv file to read").configureHelp(helpConfig),
9294
9672
  "local"
9295
9673
  ).action(
9296
9674
  (file, raw) => runCommand(
@@ -9305,22 +9683,22 @@ var envImport = addTargetOptions(
9305
9683
  const incoming = read(source, file);
9306
9684
  const keys = Object.keys(incoming);
9307
9685
  if (keys.length === 0) return;
9308
- p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9686
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9309
9687
  editLocalEnv(
9310
9688
  ctx.envFile,
9311
9689
  (content) => keys.reduce((acc, key) => upsertEnvVar(acc, key, incoming[key]), content)
9312
9690
  );
9313
- p47.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9691
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim("(local)")}`);
9314
9692
  await applyLocalEnvChange(ctx, keys);
9315
9693
  },
9316
9694
  remote: async (ctx) => {
9317
9695
  const incoming = read(resolve(file), file);
9318
9696
  const keys = Object.keys(incoming);
9319
9697
  if (keys.length === 0) return;
9320
- p47.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9698
+ p49.log.step(`Importing ${keys.length} variable(s) from ${pc22.cyan(file)}`);
9321
9699
  const existing = await readRemoteEnv(ctx.session, ctx.instance);
9322
9700
  await writeRemoteEnv(ctx.session, ctx.instance, { ...existing, ...incoming });
9323
- p47.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9701
+ p49.log.success(`${keys.length} variable(s) updated ${pc22.dim(`(${ctx.targetName})`)}`);
9324
9702
  await applyEnvRestart(ctx, keys);
9325
9703
  }
9326
9704
  },
@@ -9330,24 +9708,24 @@ var envImport = addTargetOptions(
9330
9708
  )
9331
9709
  );
9332
9710
  function resolve(file) {
9333
- return path40.resolve(process31.cwd(), file);
9711
+ return path40.resolve(process34.cwd(), file);
9334
9712
  }
9335
9713
  function read(resolved, shown) {
9336
9714
  if (!fs38.existsSync(resolved)) throw new Error(`${shown} does not exist.`);
9337
9715
  const incoming = readLocalEnvFile(resolved);
9338
- if (Object.keys(incoming).length === 0) p47.log.info(`${shown} has no variables to import.`);
9716
+ if (Object.keys(incoming).length === 0) p49.log.info(`${shown} has no variables to import.`);
9339
9717
  return incoming;
9340
9718
  }
9341
9719
 
9342
9720
  // src/commands/env.ts
9343
- var env = new Command82("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
9721
+ var env = new Command83("env").description("manage environment variables, locally or on a target").configureHelp(helpConfig).addCommand(envList).addCommand(envSet).addCommand(envUnset).addCommand(envImport);
9344
9722
 
9345
9723
  // src/commands/status.ts
9346
- import { Command as Command83 } from "commander";
9347
- import * as p48 from "@clack/prompts";
9724
+ import { Command as Command84 } from "commander";
9725
+ import * as p50 from "@clack/prompts";
9348
9726
  import pc23 from "picocolors";
9349
9727
  var status = addTargetOptions(
9350
- new Command83("status").description("show what is deployed").configureHelp(helpConfig),
9728
+ new Command84("status").description("show what is deployed").configureHelp(helpConfig),
9351
9729
  "production"
9352
9730
  ).option("--all", "show every app on the server, not just this project").option("--json", "print raw JSON").action(
9353
9731
  (raw) => runCommand(async () => {
@@ -9378,11 +9756,11 @@ function report2(states, json) {
9378
9756
  return;
9379
9757
  }
9380
9758
  if (states.length === 0) {
9381
- p48.log.info("Nothing is deployed here yet.");
9759
+ p50.log.info("Nothing is deployed here yet.");
9382
9760
  return;
9383
9761
  }
9384
9762
  for (const state of states) {
9385
- p48.log.info(describe2(state));
9763
+ p50.log.info(describe2(state));
9386
9764
  }
9387
9765
  }
9388
9766
  function describe2(state) {
@@ -9406,12 +9784,12 @@ function describe2(state) {
9406
9784
  }
9407
9785
 
9408
9786
  // src/commands/rollback.ts
9409
- import { Command as Command84 } from "commander";
9410
- import * as p49 from "@clack/prompts";
9787
+ import { Command as Command85 } from "commander";
9788
+ import * as p51 from "@clack/prompts";
9411
9789
  import pc24 from "picocolors";
9412
9790
  var rollback = addLockWaitOption(
9413
9791
  addTargetOptions(
9414
- new Command84("rollback").description("put the previous release back").configureHelp(helpConfig),
9792
+ new Command85("rollback").description("put the previous release back").configureHelp(helpConfig),
9415
9793
  "production"
9416
9794
  )
9417
9795
  ).option("--to <release>", "roll back to a specific release instead of the previous one").action(
@@ -9421,7 +9799,7 @@ var rollback = addLockWaitOption(
9421
9799
  raw,
9422
9800
  {
9423
9801
  remote: async (ctx) => {
9424
- p49.log.step(
9802
+ p51.log.step(
9425
9803
  `Rolling back ${pc24.cyan(ctx.appName)} ${pc24.dim(`(${ctx.targetName})`)} on ${ctx.server}`
9426
9804
  );
9427
9805
  const result = await runServerScript(
@@ -9436,7 +9814,7 @@ var rollback = addLockWaitOption(
9436
9814
  stream: true
9437
9815
  }
9438
9816
  );
9439
- p49.log.success(
9817
+ p51.log.success(
9440
9818
  `Rolled back to ${pc24.cyan(result?.release ?? "the previous release")}` + (result?.from ? ` ${pc24.dim(`(was ${result.from})`)}` : "")
9441
9819
  );
9442
9820
  }
@@ -9450,9 +9828,9 @@ var rollback = addLockWaitOption(
9450
9828
  );
9451
9829
 
9452
9830
  // src/commands/logs.ts
9453
- import { Command as Command85 } from "commander";
9831
+ import { Command as Command86 } from "commander";
9454
9832
  var logs = addTargetOptions(
9455
- new Command85("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
9833
+ new Command86("logs").description("tail the logs of a deployed app").configureHelp(helpConfig),
9456
9834
  "production"
9457
9835
  ).option("-f, --follow", "keep streaming new output").option("-n, --lines <count>", "how many lines of history to show", "100").option("--pocketbase", "show the PocketBase service instead of the app").action(
9458
9836
  (raw) => runCommand(async () => {
@@ -9486,16 +9864,16 @@ var logs = addTargetOptions(
9486
9864
  );
9487
9865
 
9488
9866
  // src/commands/admin.ts
9489
- import { Command as Command87 } from "commander";
9867
+ import { Command as Command88 } from "commander";
9490
9868
 
9491
9869
  // src/commands/admin/create.ts
9492
- import process32 from "node:process";
9493
- import { Command as Command86 } from "commander";
9494
- import * as p50 from "@clack/prompts";
9870
+ import process35 from "node:process";
9871
+ import { Command as Command87 } from "commander";
9872
+ import * as p52 from "@clack/prompts";
9495
9873
  import pc25 from "picocolors";
9496
9874
  var MIN_PASSWORD = 10;
9497
9875
  var adminCreate = addTargetOptions(
9498
- new Command86("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
9876
+ new Command87("create").description("create a login for the admin panel").argument("[email]", "email to sign in with \u2014 prompted for when omitted").configureHelp(helpConfig),
9499
9877
  "local"
9500
9878
  ).action(
9501
9879
  (email3, raw) => runCommand(
@@ -9523,7 +9901,7 @@ var adminCreate = addTargetOptions(
9523
9901
  const metadata = getPocketbaseMetadata(ctx.workspaceRootDir);
9524
9902
  if (metadata) signIn = `http://${metadata.viteHost}:${metadata.vitePort}`;
9525
9903
  }
9526
- p50.log.info(
9904
+ p52.log.info(
9527
9905
  signIn ? `Sign in at ${pc25.cyan(`${signIn}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once ${pc25.cyan("vela dev")} is running.`
9528
9906
  );
9529
9907
  },
@@ -9537,7 +9915,7 @@ var adminCreate = addTargetOptions(
9537
9915
  (pb) => upsertSuperuser(pb, address, password11)
9538
9916
  );
9539
9917
  const base2 = state?.domain ? `https://${state.domain.split(",")[0].trim()}` : "";
9540
- p50.log.info(
9918
+ p52.log.info(
9541
9919
  base2 ? `Sign in at ${pc25.cyan(`${base2}/admin`)}` : `Sign in at ${pc25.cyan("/admin")} once a domain is configured for this target.`
9542
9920
  );
9543
9921
  }
@@ -9550,20 +9928,20 @@ var adminCreate = addTargetOptions(
9550
9928
  async function upsertSuperuser(pb, email3, password11) {
9551
9929
  const existing = await findSuperuser(pb, email3);
9552
9930
  if (existing) {
9553
- const confirmed = await p50.confirm({
9931
+ const confirmed = await p52.confirm({
9554
9932
  message: `${email3} already has an account, update its password?`,
9555
9933
  initialValue: false
9556
9934
  });
9557
- if (p50.isCancel(confirmed) || !confirmed) {
9558
- p50.cancel("Operation cancelled.");
9559
- process32.exit(0);
9935
+ if (p52.isCancel(confirmed) || !confirmed) {
9936
+ p52.cancel("Operation cancelled.");
9937
+ process35.exit(0);
9560
9938
  }
9561
9939
  await pb.collection("_superusers").update(existing, { password: password11, passwordConfirm: password11 });
9562
- p50.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9940
+ p52.log.success(`Password updated for ${pc25.cyan(email3)}, you can sign in now`);
9563
9941
  return;
9564
9942
  }
9565
9943
  await pb.collection("_superusers").create({ email: email3, password: password11, passwordConfirm: password11 });
9566
- p50.log.success(`${pc25.cyan(email3)} can now sign in`);
9944
+ p52.log.success(`${pc25.cyan(email3)} can now sign in`);
9567
9945
  }
9568
9946
  async function findSuperuser(pb, email3) {
9569
9947
  try {
@@ -9574,47 +9952,47 @@ async function findSuperuser(pb, email3) {
9574
9952
  }
9575
9953
  }
9576
9954
  async function promptEmail() {
9577
- const value = await p50.text({
9955
+ const value = await p52.text({
9578
9956
  message: "Email to sign in with",
9579
9957
  validate: (input) => input?.includes("@") ? void 0 : "An email address is required"
9580
9958
  });
9581
- if (p50.isCancel(value)) {
9582
- p50.cancel("Operation cancelled.");
9583
- process32.exit(0);
9959
+ if (p52.isCancel(value)) {
9960
+ p52.cancel("Operation cancelled.");
9961
+ process35.exit(0);
9584
9962
  }
9585
9963
  return value.trim();
9586
9964
  }
9587
9965
  async function promptPassword2() {
9588
- const value = await p50.password({
9966
+ const value = await p52.password({
9589
9967
  message: "Password",
9590
9968
  validate: (input) => (input?.length ?? 0) >= MIN_PASSWORD ? void 0 : `At least ${MIN_PASSWORD} characters is required`
9591
9969
  });
9592
- if (p50.isCancel(value)) {
9593
- p50.cancel("Operation cancelled.");
9594
- process32.exit(0);
9970
+ if (p52.isCancel(value)) {
9971
+ p52.cancel("Operation cancelled.");
9972
+ process35.exit(0);
9595
9973
  }
9596
- const again = await p50.password({
9974
+ const again = await p52.password({
9597
9975
  message: "Password again",
9598
9976
  validate: (input) => input === value ? void 0 : "The two do not match"
9599
9977
  });
9600
- if (p50.isCancel(again)) {
9601
- p50.cancel("Operation cancelled.");
9602
- process32.exit(0);
9978
+ if (p52.isCancel(again)) {
9979
+ p52.cancel("Operation cancelled.");
9980
+ process35.exit(0);
9603
9981
  }
9604
9982
  return value;
9605
9983
  }
9606
9984
 
9607
9985
  // src/commands/admin.ts
9608
- var admin = new Command87("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
9986
+ var admin = new Command88("admin").description("manage admin panel logins").configureHelp(helpConfig).addCommand(adminCreate);
9609
9987
 
9610
9988
  // src/commands/backup.ts
9611
- import { Command as Command93 } from "commander";
9989
+ import { Command as Command94 } from "commander";
9612
9990
 
9613
9991
  // src/commands/backup/create.ts
9614
9992
  import fs39 from "node:fs";
9615
9993
  import path41 from "node:path";
9616
- import { Command as Command88 } from "commander";
9617
- import * as p51 from "@clack/prompts";
9994
+ import { Command as Command89 } from "commander";
9995
+ import * as p53 from "@clack/prompts";
9618
9996
  import pc26 from "picocolors";
9619
9997
 
9620
9998
  // src/lib/backups.ts
@@ -9702,7 +10080,7 @@ async function writeSchedule(pb, cron, maxKeep) {
9702
10080
  // src/commands/backup/create.ts
9703
10081
  var DEFAULT_BACKUP_DIR = "backups";
9704
10082
  var backupCreate = addTargetOptions(
9705
- new Command88("create").description("take a backup of the database and uploads").argument("[name]", "name for the archive \u2014 generated when omitted").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).option("--no-download", "leave the archive on the server").configureHelp(helpConfig),
10083
+ new Command89("create").description("take a backup of the database and uploads").argument("[name]", "name for the archive \u2014 generated when omitted").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).option("--no-download", "leave the archive on the server").configureHelp(helpConfig),
9706
10084
  "production"
9707
10085
  ).action(
9708
10086
  (name, raw) => runCommand(() => {
@@ -9718,7 +10096,7 @@ Backup names are lowercase letters, digits, ${pc26.cyan("-")} and ${pc26.cyan("_
9718
10096
  }
9719
10097
  const storage = await readStorageSettings(ctx.pb);
9720
10098
  if (storage.s3Enabled) {
9721
- p51.log.warn(
10099
+ p53.log.warn(
9722
10100
  `Uploads are stored in S3, so this archive holds the database only.
9723
10101
 
9724
10102
  PocketBase leaves ${pc26.cyan("storage/")} out of a backup whenever S3 is on.
@@ -9726,7 +10104,7 @@ Your bucket's own versioning is what protects the uploaded files.`
9726
10104
  );
9727
10105
  }
9728
10106
  if (ctx.session) await checkpointAppDatabases(ctx.session, ctx.instance);
9729
- const spinner7 = p51.spinner();
10107
+ const spinner7 = p53.spinner();
9730
10108
  spinner7.start(`Backing up ${ctx.targetName}`);
9731
10109
  try {
9732
10110
  await createBackup(ctx.pb, key);
@@ -9773,7 +10151,7 @@ async function download(ctx, key, outputDir) {
9773
10151
  fs39.copyFileSync(path41.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9774
10152
  return path41.relative(ctx.workspaceRootDir, destination);
9775
10153
  }
9776
- const spinner7 = p51.spinner();
10154
+ const spinner7 = p53.spinner();
9777
10155
  spinner7.start(`Downloading ${key}`);
9778
10156
  try {
9779
10157
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9786,18 +10164,18 @@ async function download(ctx, key, outputDir) {
9786
10164
  }
9787
10165
 
9788
10166
  // src/commands/backup/list.ts
9789
- import { Command as Command89 } from "commander";
9790
- import * as p52 from "@clack/prompts";
10167
+ import { Command as Command90 } from "commander";
10168
+ import * as p54 from "@clack/prompts";
9791
10169
  import pc27 from "picocolors";
9792
10170
  var backupList = addTargetOptions(
9793
- new Command89("list").description("list the backups on a target").configureHelp(helpConfig),
10171
+ new Command90("list").description("list the backups on a target").configureHelp(helpConfig),
9794
10172
  "production"
9795
10173
  ).action(
9796
10174
  (raw) => runCommand(
9797
10175
  () => withBackupTarget(raw, "backup list", async (ctx) => {
9798
10176
  const backups = await listBackups(ctx.pb);
9799
10177
  if (backups.length === 0) {
9800
- p52.log.info(
10178
+ p54.log.info(
9801
10179
  `${pc27.cyan(ctx.targetName)} has no backups yet.
9802
10180
 
9803
10181
  Take one with ${pc27.cyan("vela backup create")}.`
@@ -9805,7 +10183,7 @@ Take one with ${pc27.cyan("vela backup create")}.`
9805
10183
  return;
9806
10184
  }
9807
10185
  const width = Math.max(...backups.map((b) => b.key.length));
9808
- p52.log.message(
10186
+ p54.log.message(
9809
10187
  backups.map(
9810
10188
  (b) => `${b.key.padEnd(width)} ${pc27.dim(formatBytes(b.size).padStart(8))} ${pc27.dim(b.modified)}`
9811
10189
  ).join("\n")
@@ -9818,11 +10196,11 @@ Take one with ${pc27.cyan("vela backup create")}.`
9818
10196
  // src/commands/backup/download.ts
9819
10197
  import fs40 from "node:fs";
9820
10198
  import path42 from "node:path";
9821
- import { Command as Command90 } from "commander";
9822
- import * as p53 from "@clack/prompts";
10199
+ import { Command as Command91 } from "commander";
10200
+ import * as p55 from "@clack/prompts";
9823
10201
  import pc28 from "picocolors";
9824
10202
  var backupDownload = addTargetOptions(
9825
- new Command90("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
10203
+ new Command91("download").description("save a backup off the server").argument("<key>", "archive to download, as shown by `vela backup list`").option("-o, --output <dir>", "where to save the archive", DEFAULT_BACKUP_DIR).configureHelp(helpConfig),
9826
10204
  "production"
9827
10205
  ).action(
9828
10206
  (key, raw) => runCommand(() => {
@@ -9850,7 +10228,7 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9850
10228
  if (!ctx.session) {
9851
10229
  fs40.copyFileSync(path42.join(ctx.workspaceRootDir, "data", "backups", key), destination);
9852
10230
  } else {
9853
- const spinner7 = p53.spinner();
10231
+ const spinner7 = p55.spinner();
9854
10232
  spinner7.start(`Downloading ${key} (${formatBytes(found.size)})`);
9855
10233
  try {
9856
10234
  await ctx.session.download(remotePaths.backup(ctx.instance, key), destination);
@@ -9869,12 +10247,12 @@ Fetch it from the bucket directly \u2014 vela does not hold its credentials.`
9869
10247
  );
9870
10248
 
9871
10249
  // src/commands/backup/delete.ts
9872
- import process33 from "node:process";
9873
- import { Command as Command91 } from "commander";
9874
- import * as p54 from "@clack/prompts";
10250
+ import process36 from "node:process";
10251
+ import { Command as Command92 } from "commander";
10252
+ import * as p56 from "@clack/prompts";
9875
10253
  import pc29 from "picocolors";
9876
10254
  var backupDelete = addTargetOptions(
9877
- new Command91("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
10255
+ new Command92("delete").description("remove a backup from a target").argument("<key>", "archive to delete, as shown by `vela backup list`").option("-y, --yes", "skip the confirmation").configureHelp(helpConfig),
9878
10256
  "production"
9879
10257
  ).action(
9880
10258
  (key, raw) => runCommand(() => {
@@ -9889,13 +10267,13 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
9889
10267
  );
9890
10268
  }
9891
10269
  if (!options.yes) {
9892
- const confirmed = await p54.confirm({
10270
+ const confirmed = await p56.confirm({
9893
10271
  message: `Delete ${key} (${formatBytes(found.size)}) from ${ctx.targetName}?`,
9894
10272
  initialValue: false
9895
10273
  });
9896
- if (p54.isCancel(confirmed) || !confirmed) {
9897
- p54.cancel("Operation cancelled.");
9898
- process33.exit(0);
10274
+ if (p56.isCancel(confirmed) || !confirmed) {
10275
+ p56.cancel("Operation cancelled.");
10276
+ process36.exit(0);
9899
10277
  }
9900
10278
  }
9901
10279
  await ctx.pb.backups.delete(key);
@@ -9905,12 +10283,12 @@ Run ${pc29.cyan("vela backup list")} to see what it does have.`
9905
10283
  );
9906
10284
 
9907
10285
  // src/commands/backup/schedule.ts
9908
- import { Command as Command92 } from "commander";
9909
- import * as p55 from "@clack/prompts";
10286
+ import { Command as Command93 } from "commander";
10287
+ import * as p57 from "@clack/prompts";
9910
10288
  import pc30 from "picocolors";
9911
10289
  var DEFAULT_KEEP = 7;
9912
10290
  var backupSchedule = addTargetOptions(
9913
- new Command92("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
10291
+ new Command93("schedule").description("back up automatically on a schedule").argument("[cron]", "when to run, as a cron expression \u2014 shows the current one when omitted").option("--keep <n>", "how many scheduled archives to keep", String(DEFAULT_KEEP)).option("--off", "stop backing up automatically").configureHelp(helpConfig),
9914
10292
  "production"
9915
10293
  ).action(
9916
10294
  (cron, raw) => runCommand(() => {
@@ -9923,7 +10301,7 @@ var backupSchedule = addTargetOptions(
9923
10301
  }
9924
10302
  if (!cron) {
9925
10303
  const current = await readSchedule(ctx.pb);
9926
- p55.log.info(
10304
+ p57.log.info(
9927
10305
  current.cron ? `${ctx.targetName} backs up on ${pc30.cyan(current.cron)}, keeping ${current.maxKeep}.` : `${ctx.targetName} has no backup schedule.
9928
10306
 
9929
10307
  Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
@@ -9954,18 +10332,18 @@ Set one with ${pc30.cyan('vela backup schedule "0 3 * * *"')}.`
9954
10332
  );
9955
10333
 
9956
10334
  // src/commands/backup.ts
9957
- var backup = new Command93("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
10335
+ var backup = new Command94("backup").description("back up the database and uploads, locally or on a target").configureHelp(helpConfig).addCommand(backupCreate).addCommand(backupList).addCommand(backupDownload).addCommand(backupDelete).addCommand(backupSchedule);
9958
10336
 
9959
10337
  // src/commands/restore.ts
9960
10338
  import fs41 from "node:fs";
9961
10339
  import path43 from "node:path";
9962
- import process34 from "node:process";
9963
- import { Command as Command94 } from "commander";
9964
- import * as p56 from "@clack/prompts";
10340
+ import process37 from "node:process";
10341
+ import { Command as Command95 } from "commander";
10342
+ import * as p58 from "@clack/prompts";
9965
10343
  import pc31 from "picocolors";
9966
10344
  var restore = addLockWaitOption(
9967
10345
  addTargetOptions(
9968
- new Command94("restore").description("replace a deployment\u2019s database and uploads from a backup").argument("[source]", "a backup key on the target, or a path to a local archive").configureHelp(helpConfig),
10346
+ new Command95("restore").description("replace a deployment\u2019s database and uploads from a backup").argument("[source]", "a backup key on the target, or a path to a local archive").configureHelp(helpConfig),
9969
10347
  "production"
9970
10348
  )
9971
10349
  ).option("-y, --yes", "skip the confirmation prompt").option("--no-migrate", "do not run migrations against the restored database").option("--keep-previous <n>", "how many replaced databases to keep", "1").action(
@@ -10002,18 +10380,18 @@ var restore = addLockWaitOption(
10002
10380
  ],
10003
10381
  stream: true
10004
10382
  });
10005
- p56.log.success(
10383
+ p58.log.success(
10006
10384
  `Restored ${pc31.cyan(`${ctx.appName} (${ctx.targetName})`)} from ${pc31.cyan(
10007
10385
  local ? path43.basename(local) : key
10008
10386
  )}.`
10009
10387
  );
10010
10388
  if (result?.storageCarriedOver) {
10011
- p56.log.info(
10389
+ p58.log.info(
10012
10390
  "The archive held no uploads, so the files already on the server were kept."
10013
10391
  );
10014
10392
  }
10015
10393
  if (result?.previousDataDir) {
10016
- p56.log.info(
10394
+ p58.log.info(
10017
10395
  `The database this replaced is at ${pc31.cyan(result.previousDataDir)}.
10018
10396
 
10019
10397
  It is the only way back. Remove it once you are satisfied with the restore.`
@@ -10054,7 +10432,7 @@ Run ${pc31.cyan("vela backup list")} to see what it does have.`
10054
10432
  Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive on this machine.`
10055
10433
  );
10056
10434
  }
10057
- const chosen = await p56.select({
10435
+ const chosen = await p58.select({
10058
10436
  message: `Which backup should ${ctx.targetName} be restored from?`,
10059
10437
  options: backups.map((b) => ({
10060
10438
  value: b.key,
@@ -10062,16 +10440,16 @@ Take one with ${pc31.cyan("vela backup create")}, or pass the path to an archive
10062
10440
  hint: `${formatBytes(b.size)}, ${b.modified}`
10063
10441
  }))
10064
10442
  });
10065
- if (p56.isCancel(chosen)) {
10066
- p56.cancel("Operation cancelled.");
10067
- process34.exit(0);
10443
+ if (p58.isCancel(chosen)) {
10444
+ p58.cancel("Operation cancelled.");
10445
+ process37.exit(0);
10068
10446
  }
10069
10447
  return chosen;
10070
10448
  }
10071
10449
  async function stage(ctx, file) {
10072
10450
  const dir = remotePaths.restoreStage(ctx.instance);
10073
10451
  const remote = `${dir}/${path43.basename(file)}`;
10074
- const spinner7 = p56.spinner();
10452
+ const spinner7 = p58.spinner();
10075
10453
  spinner7.start(`Uploading ${path43.basename(file)}`);
10076
10454
  try {
10077
10455
  await ctx.session.script(`mkdir -p "$1"`, { args: [dir] });
@@ -10086,29 +10464,29 @@ async function stage(ctx, file) {
10086
10464
  async function confirm13(appName, targetName, envTag, from) {
10087
10465
  const what = `${pc31.cyan(`${appName} (${targetName})`)} from ${pc31.cyan(path43.basename(from))}`;
10088
10466
  if (isProd(envTag)) {
10089
- const answer = await p56.text({
10467
+ const answer = await p58.text({
10090
10468
  message: `This replaces the database and uploads of ${what}. Type the app name to confirm`,
10091
10469
  validate: (value) => value === appName ? void 0 : `Type ${appName} to confirm`
10092
10470
  });
10093
- if (p56.isCancel(answer)) {
10094
- p56.cancel("Operation cancelled.");
10095
- process34.exit(0);
10471
+ if (p58.isCancel(answer)) {
10472
+ p58.cancel("Operation cancelled.");
10473
+ process37.exit(0);
10096
10474
  }
10097
10475
  return;
10098
10476
  }
10099
- const ok = await p56.confirm({
10477
+ const ok = await p58.confirm({
10100
10478
  message: `Replace the database and uploads of ${what}?`,
10101
10479
  initialValue: false
10102
10480
  });
10103
- if (p56.isCancel(ok) || !ok) {
10104
- p56.cancel("Operation cancelled.");
10105
- process34.exit(0);
10481
+ if (p58.isCancel(ok) || !ok) {
10482
+ p58.cancel("Operation cancelled.");
10483
+ process37.exit(0);
10106
10484
  }
10107
10485
  }
10108
10486
 
10109
10487
  // src/commands/targets.ts
10110
- import { Command as Command95 } from "commander";
10111
- import * as p57 from "@clack/prompts";
10488
+ import { Command as Command96 } from "commander";
10489
+ import * as p59 from "@clack/prompts";
10112
10490
  import pc32 from "picocolors";
10113
10491
  import * as v9 from "valibot";
10114
10492
  var OptionsSchema4 = v9.object({
@@ -10117,7 +10495,7 @@ var OptionsSchema4 = v9.object({
10117
10495
  offline: v9.optional(v9.boolean())
10118
10496
  });
10119
10497
  var targets = addSshOptions(
10120
- new Command95("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
10498
+ new Command96("targets").description("list the targets this project can deploy to").configureHelp(helpConfig)
10121
10499
  ).option("--json", "print raw JSON").option("--offline", "skip connecting to servers").action(
10122
10500
  (raw) => runCommand(async () => {
10123
10501
  const options = parseOptions(OptionsSchema4, raw);
@@ -10183,11 +10561,11 @@ function report3(rows, offline) {
10183
10561
  const lines = rows.map(
10184
10562
  (row) => `${row.kind === "local" ? pc32.dim(row.target.padEnd(target)) : pc32.cyan(row.target.padEnd(target))} ${row.server.padEnd(server)} ${row.domain.padEnd(domain)} ${row.release}`
10185
10563
  );
10186
- p57.log.info(`${pc32.dim(header)}
10564
+ p59.log.info(`${pc32.dim(header)}
10187
10565
  ${lines.join("\n")}`);
10188
10566
  const unreachable = rows.filter((row) => row.kind === "remote" && !row.reachable);
10189
10567
  if (!offline && unreachable.length > 0) {
10190
- p57.log.warn(
10568
+ p59.log.warn(
10191
10569
  `Could not reach ${unreachable.map((row) => row.server).join(", ")}.
10192
10570
  Release and domain are shown from what this project recorded.`
10193
10571
  );
@@ -10196,16 +10574,16 @@ Release and domain are shown from what this project recorded.`
10196
10574
 
10197
10575
  // src/commands/test.ts
10198
10576
  import path44 from "node:path";
10199
- import process35 from "node:process";
10200
- import { Command as Command96 } from "commander";
10577
+ import process38 from "node:process";
10578
+ import { Command as Command97 } from "commander";
10201
10579
  import PocketBase6 from "pocketbase";
10202
10580
  import pc33 from "picocolors";
10203
10581
  import { x as x5 } from "tinyexec";
10204
10582
  import { detect as detect8 } from "package-manager-detector";
10205
10583
  import { resolveCommand as resolveCommand7 } from "package-manager-detector/commands";
10206
10584
  import fs42 from "node:fs";
10207
- var testServer = new Command96("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
10208
- const cwd = process35.cwd();
10585
+ var testServer = new Command97("test:server").description("run server tests").allowUnknownOption(true).allowExcessArguments(true).configureHelp(helpConfig).action(async (_opts, cmd) => {
10586
+ const cwd = process38.cwd();
10209
10587
  const email3 = `test-${Math.random().toString(36).slice(2)}@example.com`;
10210
10588
  const password11 = "password";
10211
10589
  const testDataDir = path44.join(cwd, "test-data");
@@ -10220,11 +10598,11 @@ var testServer = new Command96("test:server").description("run server tests").al
10220
10598
  email: email3,
10221
10599
  password: password11
10222
10600
  });
10223
- process35.env.POCKETBASE_URL = url;
10224
- process35.env.POCKETBASE_SUPERUSER_EMAIL = email3;
10225
- process35.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
10226
- process35.env.VELA_DATA_DIR = testDataDir;
10227
- process35.env.TEST = "true";
10601
+ process38.env.POCKETBASE_URL = url;
10602
+ process38.env.POCKETBASE_SUPERUSER_EMAIL = email3;
10603
+ process38.env.POCKETBASE_SUPERUSER_PASSWORD = password11;
10604
+ process38.env.VELA_DATA_DIR = testDataDir;
10605
+ process38.env.TEST = "true";
10228
10606
  console.log(`${pc33.greenBright("\u2713")} Created test database`);
10229
10607
  let vite;
10230
10608
  let cleanedUp = false;
@@ -10243,12 +10621,12 @@ var testServer = new Command96("test:server").description("run server tests").al
10243
10621
  const fail = async (message) => {
10244
10622
  console.error(`${pc33.redBright("\u2717")} ${message}`);
10245
10623
  await cleanup();
10246
- process35.exit(1);
10624
+ process38.exit(1);
10247
10625
  };
10248
- process35.on("exit", cleanupSync);
10249
- process35.on("SIGINT", () => {
10626
+ process38.on("exit", cleanupSync);
10627
+ process38.on("SIGINT", () => {
10250
10628
  cleanupSync();
10251
- process35.exit(130);
10629
+ process38.exit(130);
10252
10630
  });
10253
10631
  const pb = new PocketBase6(url);
10254
10632
  try {
@@ -10276,7 +10654,7 @@ var testServer = new Command96("test:server").description("run server tests").al
10276
10654
  });
10277
10655
  const vitePort = await findFreePort();
10278
10656
  await vite.listen(vitePort);
10279
- process35.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10657
+ process38.env.VITE_TEST_URL = `http://localhost:${vitePort}`;
10280
10658
  console.log(`${pc33.greenBright("\u2713")} Started Vite: http://localhost:${vitePort}`);
10281
10659
  console.log(`${pc33.greenBright("\u2713")} Started PocketBase: ${url}`);
10282
10660
  const extraArgs = (cmd.parent?.args ?? []).slice(1);
@@ -10295,12 +10673,12 @@ var testServer = new Command96("test:server").description("run server tests").al
10295
10673
  const resolvedArgs = resolved.args.slice();
10296
10674
  if (pm === "npm") resolvedArgs.unshift("--yes");
10297
10675
  const result = await x5(resolved.command, resolvedArgs, {
10298
- nodeOptions: { cwd, stdio: "inherit", env: { ...process35.env, CI: "1" } }
10676
+ nodeOptions: { cwd, stdio: "inherit", env: { ...process38.env, CI: "1" } }
10299
10677
  });
10300
- process35.exitCode = result.exitCode ?? 1;
10678
+ process38.exitCode = result.exitCode ?? 1;
10301
10679
  } catch (e) {
10302
10680
  console.error(`${pc33.redBright("\u2717")} ${e.message}`);
10303
- process35.exitCode = 1;
10681
+ process38.exitCode = 1;
10304
10682
  } finally {
10305
10683
  await cleanup();
10306
10684
  }
@@ -10333,7 +10711,7 @@ function stubPagesPlugin() {
10333
10711
  // src/commands/routes.ts
10334
10712
  import fs43 from "node:fs";
10335
10713
  import path45 from "node:path";
10336
- import { Command as Command97 } from "commander";
10714
+ import { Command as Command98 } from "commander";
10337
10715
  var HTTP_METHODS = /* @__PURE__ */ new Set([
10338
10716
  "GET",
10339
10717
  "POST",
@@ -10344,7 +10722,7 @@ var HTTP_METHODS = /* @__PURE__ */ new Set([
10344
10722
  "HEAD",
10345
10723
  "fallback"
10346
10724
  ]);
10347
- var routes = new Command97("routes").description("list routes").configureHelp(helpConfig).action(async () => {
10725
+ var routes = new Command98("routes").description("list routes").configureHelp(helpConfig).action(async () => {
10348
10726
  const { workspaceRootDir, routesDir } = await getWorkspace();
10349
10727
  const routesRoot = path45.join(workspaceRootDir, routesDir);
10350
10728
  const found = walk(routesRoot, routesRoot).filter((r) => r.methods.length > 0);
@@ -10419,13 +10797,13 @@ function printTable(routes2) {
10419
10797
  }
10420
10798
 
10421
10799
  // src/commands/i18n.ts
10422
- import process36 from "node:process";
10423
- import { Command as Command98 } from "commander";
10800
+ import process39 from "node:process";
10801
+ import { Command as Command99 } from "commander";
10424
10802
  import { x as x6 } from "tinyexec";
10425
10803
  import { detect as detect9 } from "package-manager-detector";
10426
10804
  import { resolveCommand as resolveCommand8 } from "package-manager-detector/commands";
10427
10805
  async function runWuchale(extraArgs) {
10428
- const cwd = process36.cwd();
10806
+ const cwd = process39.cwd();
10429
10807
  const pm = (await detect9({ cwd }))?.name ?? "npm";
10430
10808
  const resolved = resolveCommand8(pm, "execute", ["wuchale", ...extraArgs]);
10431
10809
  const args = resolved.args.slice();
@@ -10435,11 +10813,11 @@ async function runWuchale(extraArgs) {
10435
10813
  throwOnError: true
10436
10814
  });
10437
10815
  }
10438
- var extract2 = new Command98("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
10439
- var watch = new Command98("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
10440
- var status2 = new Command98("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
10441
- var clean = new Command98("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
10442
- var i18n3 = new Command98("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract2, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
10816
+ var extract2 = new Command99("extract").description("extract translatable strings").configureHelp(helpConfig).action(() => runWuchale([]));
10817
+ var watch = new Command99("watch").description("watch and extract translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--watch"]));
10818
+ var status2 = new Command99("status").description("show i18n status").configureHelp(helpConfig).action(() => runWuchale(["status"]));
10819
+ var clean = new Command99("clean").description("clean unused translatable strings").configureHelp(helpConfig).action(() => runWuchale(["--clean"]));
10820
+ var i18n3 = new Command99("i18n").description("i18n utilities").configureHelp(helpConfig).addCommand(extract2, { isDefault: true }).addCommand(watch).addCommand(status2).addCommand(clean);
10443
10821
 
10444
10822
  // src/commands/oauth.ts
10445
10823
  var oauth = stubCommand("oauth", "configure OAuth providers");
@@ -10448,21 +10826,21 @@ var oauth = stubCommand("oauth", "configure OAuth providers");
10448
10826
  var schemas = stubCommand("schemas", "manage database schemas");
10449
10827
 
10450
10828
  // src/commands/cms.ts
10451
- import { Command as Command103 } from "commander";
10829
+ import { Command as Command104 } from "commander";
10452
10830
 
10453
10831
  // src/commands/cms/editor.ts
10454
- import { Command as Command102 } from "commander";
10832
+ import { Command as Command103 } from "commander";
10455
10833
 
10456
10834
  // src/commands/cms/editor/add.ts
10457
10835
  import { randomBytes } from "node:crypto";
10458
- import { Command as Command99 } from "commander";
10459
- import * as p58 from "@clack/prompts";
10836
+ import { Command as Command100 } from "commander";
10837
+ import * as p60 from "@clack/prompts";
10460
10838
  import pc35 from "picocolors";
10461
10839
 
10462
10840
  // src/lib/cms-backend.ts
10463
10841
  import { createRequire as createRequire3 } from "node:module";
10464
10842
  import path46 from "node:path";
10465
- import process37 from "node:process";
10843
+ import process40 from "node:process";
10466
10844
  import { pathToFileURL as pathToFileURL3 } from "node:url";
10467
10845
  import pc34 from "picocolors";
10468
10846
  var DEFAULT_PROJECT = "default";
@@ -10479,7 +10857,7 @@ Run ${pc34.cyan("vela enable cms")} first.`
10479
10857
  }
10480
10858
  return await import(pathToFileURL3(entry).href);
10481
10859
  }
10482
- async function withCmsBackend(fn, cwd = process37.cwd()) {
10860
+ async function withCmsBackend(fn, cwd = process40.cwd()) {
10483
10861
  const root = findWorkspaceRoot(cwd);
10484
10862
  if (!root) {
10485
10863
  throw new Error("Could not find workspace root (no package.json found)");
@@ -10498,7 +10876,7 @@ async function withCmsBackend(fn, cwd = process37.cwd()) {
10498
10876
  }
10499
10877
 
10500
10878
  // src/commands/cms/editor/add.ts
10501
- var editorAdd = new Command99("add").description("create an editor who can sign in to the admin bar").argument("<email>", "email the editor signs in with").option("--password <password>", "password to set \u2014 generated and shown once when omitted").option("--project <id>", "project the editor may edit", DEFAULT_PROJECT).configureHelp(helpConfig).action(
10879
+ var editorAdd = new Command100("add").description("create an editor who can sign in to the admin bar").argument("<email>", "email the editor signs in with").option("--password <password>", "password to set \u2014 generated and shown once when omitted").option("--project <id>", "project the editor may edit", DEFAULT_PROJECT).configureHelp(helpConfig).action(
10502
10880
  (email3, options) => runCommand(async () => {
10503
10881
  const generated = options.password === void 0;
10504
10882
  const password11 = options.password ?? randomBytes(12).toString("base64url");
@@ -10509,31 +10887,31 @@ var editorAdd = new Command99("add").description("create an editor who can sign
10509
10887
  if (generated) {
10510
10888
  lines.push("", `Password: ${pc35.bold(password11)}`, "", "It is shown once; copy it now.");
10511
10889
  }
10512
- p58.log.success(lines.join("\n"));
10513
- p58.log.info(
10890
+ p60.log.success(lines.join("\n"));
10891
+ p60.log.info(
10514
10892
  `Run ${pc35.cyan("vela dev")}, open any page with ${pc35.cyan("?edit")} on the URL (or press ${pc35.cyan("Ctrl+E")}), and sign in.`
10515
10893
  );
10516
10894
  }, "Failed to add the editor.")
10517
10895
  );
10518
10896
 
10519
10897
  // src/commands/cms/editor/password.ts
10520
- import { Command as Command100 } from "commander";
10521
- import * as p59 from "@clack/prompts";
10898
+ import { Command as Command101 } from "commander";
10899
+ import * as p61 from "@clack/prompts";
10522
10900
  import pc36 from "picocolors";
10523
- var editorPassword = new Command100("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
10901
+ var editorPassword = new Command101("password").description("set an editor's password").argument("<email>", "email of the editor").argument("<password>", "new password").configureHelp(helpConfig).action(
10524
10902
  (email3, password11) => runCommand(async () => {
10525
10903
  await withCmsBackend((cms3) => cms3.editors.setPassword(email3, password11));
10526
- p59.log.success(
10904
+ p61.log.success(
10527
10905
  `Updated the password for ${pc36.cyan(email3)}. Existing sessions were signed out.`
10528
10906
  );
10529
10907
  }, "Failed to set the password.")
10530
10908
  );
10531
10909
 
10532
10910
  // src/commands/cms/editor/list.ts
10533
- import { Command as Command101 } from "commander";
10534
- import * as p60 from "@clack/prompts";
10911
+ import { Command as Command102 } from "commander";
10912
+ import * as p62 from "@clack/prompts";
10535
10913
  import pc37 from "picocolors";
10536
- var editorList = new Command101("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10914
+ var editorList = new Command102("list").description("list editors and the projects they may edit").configureHelp(helpConfig).action(
10537
10915
  () => runCommand(async () => {
10538
10916
  const rows = await withCmsBackend(
10539
10917
  async (cms3) => cms3.editors.list().map((editor2) => ({
@@ -10542,11 +10920,11 @@ var editorList = new Command101("list").description("list editors and the projec
10542
10920
  }))
10543
10921
  );
10544
10922
  if (rows.length === 0) {
10545
- p60.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10923
+ p62.log.info(`No editors yet. Add one with ${pc37.cyan("vela cms editor add <email>")}.`);
10546
10924
  return;
10547
10925
  }
10548
10926
  const width = Math.max(...rows.map((row) => row.email.length));
10549
- p60.log.info(
10927
+ p62.log.info(
10550
10928
  `Editors
10551
10929
 
10552
10930
  ` + rows.map(
@@ -10557,10 +10935,10 @@ var editorList = new Command101("list").description("list editors and the projec
10557
10935
  );
10558
10936
 
10559
10937
  // src/commands/cms/editor.ts
10560
- var editor = new Command102("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
10938
+ var editor = new Command103("editor").description("manage who can sign in to the admin bar").configureHelp(helpConfig).addCommand(editorAdd).addCommand(editorPassword).addCommand(editorList);
10561
10939
 
10562
10940
  // src/commands/cms.ts
10563
- var cms2 = new Command103("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
10941
+ var cms2 = new Command104("cms").description("manage the CMS").configureHelp(helpConfig).addCommand(editor);
10564
10942
 
10565
10943
  // src/program.ts
10566
10944
  var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
@@ -10578,6 +10956,8 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
10578
10956
  "generate form",
10579
10957
  // The CMS keeps its own SQLite database and editors; PocketBase is never involved.
10580
10958
  "enable cms",
10959
+ // Analytics only touches the root layout and .env; it must work on static sites.
10960
+ "enable analytics",
10581
10961
  "cms",
10582
10962
  // Server commands talk to a VPS over SSH, never to the local database.
10583
10963
  "provision",
@@ -10598,10 +10978,10 @@ var NO_BACKEND_COMMMANDS = /* @__PURE__ */ new Set([
10598
10978
  ]);
10599
10979
  var BACKEND_OPTIONAL_COMMANDS = /* @__PURE__ */ new Set(["dev", "build", "preview", "deploy"]);
10600
10980
  var SELF_CREDENTIALED_COMMANDS = /* @__PURE__ */ new Set(["test:server"]);
10601
- var program = new Command104().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10981
+ var program = new Command105().name(package_default.name).description(package_default.description).version(package_default.version, "-v, --version").configureHelp(helpConfig);
10602
10982
  program.hook("preAction", (_thisCommand, actionCommand) => {
10603
10983
  if (isStub(actionCommand)) return;
10604
- const envRoot = findWorkspaceRoot() ?? process38.cwd();
10984
+ const envRoot = findWorkspaceRoot() ?? process41.cwd();
10605
10985
  dotenv2.config({ path: nodePath.join(envRoot, ".env"), quiet: true });
10606
10986
  const path47 = getCommandPath(actionCommand);
10607
10987
  if (NO_BACKEND_COMMMANDS.has(path47)) return;
@@ -10609,20 +10989,20 @@ program.hook("preAction", (_thisCommand, actionCommand) => {
10609
10989
  if (NO_BACKEND_COMMMANDS.has(top)) return;
10610
10990
  if (!hasBackend()) {
10611
10991
  if (BACKEND_OPTIONAL_COMMANDS.has(top)) return;
10612
- p61.log.error(
10992
+ p63.log.error(
10613
10993
  `${pc38.cyan(`vela ${path47}`)} needs a backend, and this project does not have one.
10614
10994
 
10615
10995
  Static projects have no database to talk to.
10616
10996
 
10617
10997
  To add a backend to this project, run ${pc38.cyan("vela bless")}.`
10618
10998
  );
10619
- p61.log.message();
10620
- p61.cancel("Operation failed.");
10621
- process38.exit(1);
10999
+ p63.log.message();
11000
+ p63.cancel("Operation failed.");
11001
+ process41.exit(1);
10622
11002
  }
10623
11003
  if (SELF_CREDENTIALED_COMMANDS.has(path47)) return;
10624
- if (!process38.env.POCKETBASE_SUPERUSER_EMAIL || !process38.env.POCKETBASE_SUPERUSER_PASSWORD) {
10625
- p61.log.error(
11004
+ if (!process41.env.POCKETBASE_SUPERUSER_EMAIL || !process41.env.POCKETBASE_SUPERUSER_PASSWORD) {
11005
+ p63.log.error(
10626
11006
  `PocketBase superuser credentials are required.
10627
11007
 
10628
11008
  Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPERUSER_PASSWORD")} in your .env file.
@@ -10630,9 +11010,9 @@ Set ${pc38.cyan("POCKETBASE_SUPERUSER_EMAIL")} and ${pc38.cyan("POCKETBASE_SUPER
10630
11010
  To set up a new project, run ${pc38.cyan("vela create")}.
10631
11011
  To set up an existing project, run ${pc38.cyan("vela bless")}.`
10632
11012
  );
10633
- p61.log.message();
10634
- p61.cancel("Operation failed.");
10635
- process38.exit(1);
11013
+ p63.log.message();
11014
+ p63.cancel("Operation failed.");
11015
+ process41.exit(1);
10636
11016
  }
10637
11017
  });
10638
11018
  function getCommandPath(cmd) {
@@ -10686,5 +11066,5 @@ for (const command of [
10686
11066
  }
10687
11067
 
10688
11068
  // src/bin.ts
10689
- program.parse(normalizeArgv(process39.argv.slice(2)), { from: "user" });
11069
+ program.parse(normalizeArgv(process42.argv.slice(2)), { from: "user" });
10690
11070
  //# sourceMappingURL=bin.js.map