vela 0.18.1 → 0.19.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
@@ -20,7 +20,7 @@ import dotenv2 from "dotenv";
20
20
  // package.json
21
21
  var package_default = {
22
22
  name: "vela",
23
- version: "0.18.1",
23
+ version: "0.19.0",
24
24
  type: "module",
25
25
  description: "A CLI for creating and updating SvelteKit projects",
26
26
  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.7.1",
60
+ "@velastack/patterns": "^0.8.0",
61
61
  "@velastack/pocketbase-codegen": "^0.1.0",
62
62
  "@velastack/schema": "^0.3.0",
63
63
  "@velastack/schema-ui": "^0.3.1",
@@ -419,9 +419,9 @@ function minOfComparatorSet(set) {
419
419
  if (upperOnly) return { major: 0, minor: 0, patch: 0, prerelease: [] };
420
420
  return floor;
421
421
  }
422
- function parseVersionPart(text18) {
423
- if (text18 === "" || text18 === "*" || text18 === "x" || text18 === "X") return null;
424
- const match = text18.match(VERSION_PART);
422
+ function parseVersionPart(text19) {
423
+ if (text19 === "" || text19 === "*" || text19 === "x" || text19 === "X") return null;
424
+ const match = text19.match(VERSION_PART);
425
425
  if (!match) return null;
426
426
  const nums = [match[1], match[2], match[3]];
427
427
  const firstWild = nums.findIndex((n) => n === void 0 || /^[xX*]$/.test(n));
@@ -914,10 +914,10 @@ function writeCachedIndex(cached2) {
914
914
  fs6.mkdirSync(cacheRoot(), { recursive: true });
915
915
  fs6.writeFileSync(indexCachePath(), JSON.stringify(cached2, null, 2));
916
916
  }
917
- function parseTemplateIndex(text18, url) {
917
+ function parseTemplateIndex(text19, url) {
918
918
  let parsed;
919
919
  try {
920
- parsed = JSON.parse(text18);
920
+ parsed = JSON.parse(text19);
921
921
  } catch (e) {
922
922
  throw new Error(`Template index at ${url} is not valid JSON: ${e.message}`);
923
923
  }
@@ -1867,8 +1867,8 @@ async function readSite(root) {
1867
1867
  if (!property || !Node6.isPropertyAssignment(property)) continue;
1868
1868
  const value = property.getInitializer();
1869
1869
  if (Node6.isStringLiteral(value) || Node6.isNoSubstitutionTemplateLiteral(value)) {
1870
- const text18 = value.getLiteralValue().trim();
1871
- if (text18) info[key] = text18;
1870
+ const text19 = value.getLiteralValue().trim();
1871
+ if (text19) info[key] = text19;
1872
1872
  }
1873
1873
  }
1874
1874
  return info;
@@ -2207,11 +2207,11 @@ function mergeOriginConfig(root, options = {}) {
2207
2207
  if (target) setOriginComment(target);
2208
2208
  }
2209
2209
  if (orphaned.length > 0) {
2210
- let text18 = vite.sourceFile.getFullText();
2210
+ let text19 = vite.sourceFile.getFullText();
2211
2211
  for (const comment of orphaned) {
2212
- text18 = text18.replace(new RegExp(String.raw`\n[\t ]*${escapeRegExp2(comment)}[\t ]*(?=\n)`), "");
2212
+ text19 = text19.replace(new RegExp(String.raw`\n[\t ]*${escapeRegExp2(comment)}[\t ]*(?=\n)`), "");
2213
2213
  }
2214
- vite.sourceFile.replaceWithText(text18);
2214
+ vite.sourceFile.replaceWithText(text19);
2215
2215
  }
2216
2216
  vite.sourceFile.saveSync();
2217
2217
  const moved = hasPathsOrigin ? "removed prerender.origin, which SvelteKit 3 no longer accepts; kept the existing paths.origin" : "moved prerender.origin to paths.origin";
@@ -2243,8 +2243,8 @@ var ORIGIN_COMMENT = [
2243
2243
  "baked in at build time. It is left unset for a deploy that serves more",
2244
2244
  "than one host, where each request's own origin is used instead."
2245
2245
  ];
2246
- function escapeRegExp2(text18) {
2247
- return text18.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2246
+ function escapeRegExp2(text19) {
2247
+ return text19.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
2248
2248
  }
2249
2249
  function mentionsPrerender(node) {
2250
2250
  return node.getLeadingCommentRanges().some((c) => /prerender/i.test(c.getText()));
@@ -2541,7 +2541,7 @@ function detectJsonIndent(source) {
2541
2541
  var PRINT_WIDTH = 100;
2542
2542
  function stringifyJson(value, indent, level = 0, prefix = 0) {
2543
2543
  const pad2 = (n) => indent.repeat(n);
2544
- const width = (text18) => text18.replaceAll(" ", " ").length;
2544
+ const width = (text19) => text19.replaceAll(" ", " ").length;
2545
2545
  if (Array.isArray(value)) {
2546
2546
  if (value.length === 0) return "[]";
2547
2547
  const scalars = value.every((v14) => v14 === null || typeof v14 !== "object");
@@ -4397,10 +4397,10 @@ var npmViewLookup = (name, range, cwd) => new Promise((resolve2, reject) => {
4397
4397
  (error, stdout, stderr) => {
4398
4398
  if (error && /\bE404\b/.test(`${stderr}${error.message}`)) return resolve2(null);
4399
4399
  if (error) return reject(error);
4400
- const text18 = stdout.trim();
4401
- if (!text18) return resolve2(null);
4400
+ const text19 = stdout.trim();
4401
+ if (!text19) return resolve2(null);
4402
4402
  try {
4403
- resolve2(newest(JSON.parse(text18)));
4403
+ resolve2(newest(JSON.parse(text19)));
4404
4404
  } catch (e) {
4405
4405
  reject(e);
4406
4406
  }
@@ -4857,14 +4857,14 @@ function skipString(source, start) {
4857
4857
  }
4858
4858
  return -1;
4859
4859
  }
4860
- function splitTopLevel(text18) {
4860
+ function splitTopLevel(text19) {
4861
4861
  const parts = [];
4862
4862
  let depth = 0;
4863
4863
  let partStart = 0;
4864
- for (let i = 0; i < text18.length; i++) {
4865
- const c = text18[i];
4864
+ for (let i = 0; i < text19.length; i++) {
4865
+ const c = text19[i];
4866
4866
  if (c === '"' || c === "'" || c === "`") {
4867
- const end = skipString(text18, i);
4867
+ const end = skipString(text19, i);
4868
4868
  if (end === -1) break;
4869
4869
  i = end;
4870
4870
  continue;
@@ -4872,12 +4872,12 @@ function splitTopLevel(text18) {
4872
4872
  if (c === "(" || c === "{" || c === "[") depth++;
4873
4873
  else if (c === ")" || c === "}" || c === "]") depth--;
4874
4874
  else if (c === "," && depth === 0) {
4875
- parts.push({ start: partStart, end: i, text: text18.slice(partStart, i) });
4875
+ parts.push({ start: partStart, end: i, text: text19.slice(partStart, i) });
4876
4876
  partStart = i + 1;
4877
4877
  }
4878
4878
  }
4879
- if (text18.slice(partStart).trim()) {
4880
- parts.push({ start: partStart, end: text18.length, text: text18.slice(partStart) });
4879
+ if (text19.slice(partStart).trim()) {
4880
+ parts.push({ start: partStart, end: text19.length, text: text19.slice(partStart) });
4881
4881
  }
4882
4882
  return parts;
4883
4883
  }
@@ -4994,8 +4994,8 @@ function rewriteGotoOptions(inner) {
4994
4994
  if (!joined.startsWith(lead)) joined = lead + joined.trimStart();
4995
4995
  return { inner: joined + tail, summary: summary.join("; ") };
4996
4996
  }
4997
- function escapeRegExp3(text18) {
4998
- return text18.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4997
+ function escapeRegExp3(text19) {
4998
+ return text19.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
4999
4999
  }
5000
5000
  function rewriteInvalidateAll(source) {
5001
5001
  const outcome = { edits: [], changes: [], tasks: [] };
@@ -5080,9 +5080,9 @@ function addTaskComments(source, file, tasks) {
5080
5080
  const lineStart2 = code2.lastIndexOf("\n", index - 1) + 1;
5081
5081
  const lineEnd = code2.indexOf("\n", index);
5082
5082
  const excerpt = code2.slice(lineStart2, lineEnd === -1 ? void 0 : lineEnd).trim().replace(/--/g, "- -").slice(0, 80);
5083
- const text18 = `${MIGRATION_TASK_MARKER} \`${excerpt}\`: ${message}`;
5084
- if (code2.includes(text18)) continue;
5085
- code2 = `<!-- ${text18} -->
5083
+ const text19 = `${MIGRATION_TASK_MARKER} \`${excerpt}\`: ${message}`;
5084
+ if (code2.includes(text19)) continue;
5085
+ code2 = `<!-- ${text19} -->
5086
5086
  ${code2}`;
5087
5087
  added.push(`line ${line}: ${message}`);
5088
5088
  continue;
@@ -5476,8 +5476,8 @@ function svArgs(root, tasks, exclude) {
5476
5476
  }
5477
5477
  var ANSI = /\u001b\[[0-9;?]*[A-Za-z]/g;
5478
5478
  function parseSvFailure(output) {
5479
- const text18 = output.replace(ANSI, "");
5480
- const match = text18.match(/Task '([^']+)' failed: ([^\n]*)/);
5479
+ const text19 = output.replace(ANSI, "");
5480
+ const match = text19.match(/Task '([^']+)' failed: ([^\n]*)/);
5481
5481
  if (!match) return null;
5482
5482
  const message = match[2].trim();
5483
5483
  const file = message.match(/Unable to process '([^']+)'/)?.[1];
@@ -5567,9 +5567,9 @@ function originFixup(root, capture, sv) {
5567
5567
  ${outcome.snippet}`);
5568
5568
  }
5569
5569
  const lost = Boolean(carry && !outcome.applied && outcome.snippet);
5570
- for (const text18 of capture?.spreads ?? []) {
5571
- if (carry && !lost && carry.text.endsWith(text18)) continue;
5572
- sv.dropped.push({ file: capture.file, text: text18 });
5570
+ for (const text19 of capture?.spreads ?? []) {
5571
+ if (carry && !lost && carry.text.endsWith(text19)) continue;
5572
+ sv.dropped.push({ file: capture.file, text: text19 });
5573
5573
  }
5574
5574
  return f;
5575
5575
  }
@@ -5869,10 +5869,10 @@ function belowFloor(project, key, entry) {
5869
5869
  return Boolean(floor && locked && compareVersions(locked, floor) < 0);
5870
5870
  }
5871
5871
  function readJson(file) {
5872
- const text18 = fs29.readFileSync(file, "utf8");
5872
+ const text19 = fs29.readFileSync(file, "utf8");
5873
5873
  return {
5874
- data: JSON.parse(text18),
5875
- indent: text18.match(/^[{[]\s*\n([\t ]+)/)?.[1] ?? " "
5874
+ data: JSON.parse(text19),
5875
+ indent: text19.match(/^[{[]\s*\n([\t ]+)/)?.[1] ?? " "
5876
5876
  };
5877
5877
  }
5878
5878
  function writeJson(file, data, indent) {
@@ -5979,13 +5979,13 @@ function previousFollowUps(root, pattern) {
5979
5979
  const end = content.indexOf("\n## ", start + FOLLOW_UPS_HEADING.length);
5980
5980
  return content.slice(start, end === -1 ? void 0 : end).split("\n").filter((line) => line.startsWith("- [") && pattern.test(line)).map((line) => line.replace(/^- \[[ x]\] /, ""));
5981
5981
  }
5982
- function code(text18) {
5983
- const fence = text18.includes("`") ? "``" : "`";
5984
- const pad2 = text18.startsWith("`") || text18.endsWith("`") ? " " : "";
5985
- return `${fence}${pad2}${text18}${pad2}${fence}`;
5982
+ function code(text19) {
5983
+ const fence = text19.includes("`") ? "``" : "`";
5984
+ const pad2 = text19.startsWith("`") || text19.endsWith("`") ? " " : "";
5985
+ return `${fence}${pad2}${text19}${pad2}${fence}`;
5986
5986
  }
5987
- function escape(text18) {
5988
- return text18.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5987
+ function escape(text19) {
5988
+ return text19.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
5989
5989
  }
5990
5990
  function writeFollowUps(root, items, generic) {
5991
5991
  const file = path28.join(root, MIGRATION_TASKS_FILE);
@@ -6127,8 +6127,8 @@ function findRepeaterImport(dir) {
6127
6127
  for (const entry of entries) {
6128
6128
  if (!entry.isFile() || !SOURCE_FILE.test(entry.name)) continue;
6129
6129
  const file = path29.join(entry.parentPath, entry.name);
6130
- const text18 = fs30.readFileSync(file, "utf8");
6131
- if (text18.includes("CmsRepeater") && REPEATER_IMPORT.test(text18)) {
6130
+ const text19 = fs30.readFileSync(file, "utf8");
6131
+ if (text19.includes("CmsRepeater") && REPEATER_IMPORT.test(text19)) {
6132
6132
  return path29.relative(dir, file);
6133
6133
  }
6134
6134
  }
@@ -7724,14 +7724,20 @@ async function ensureOrderForm(root, deps = { readApiKey, createForms: createPro
7724
7724
  // src/commands/enable/payments.ts
7725
7725
  var payments = new Command20("payments").description("enable payments (Stripe, Shopify or WhatsApp)").option("--provider <provider>", "payment provider: stripe, shopify or whatsapp").option(
7726
7726
  "--currency <code>",
7727
- "WhatsApp: the business's currency, an ISO 4217 code such as MXN (kept in src/lib/site.ts)"
7727
+ "the currency the business prices in, an ISO 4217 code such as MXN (kept in src/lib/site.ts; WhatsApp needs it)"
7728
+ ).option(
7729
+ "--country <code>",
7730
+ "the country the business is in, ISO 3166-1 such as MX; prices format for it"
7731
+ ).option(
7732
+ "--currencies <codes>",
7733
+ "other currencies to show prices in, as estimates, comma-separated (USD,EUR); blank for none"
7728
7734
  ).allowExcessArguments(true).configureHelp(helpConfig).action(
7729
7735
  (opts, cmd) => runCommand(async () => {
7730
7736
  const provider = await resolveProvider("enable-payments", opts.provider);
7731
7737
  await assertPatternRequires("enable-payments", provider.id);
7732
7738
  if (provider.id === "stripe") assertBackendReady("vela enable payments");
7733
7739
  if (provider.id === "stripe") noteWebhookSecret();
7734
- const currency = provider.id === "whatsapp" ? await askCurrency(opts.currency) : void 0;
7740
+ const business = await askBusiness(opts, provider.id === "whatsapp");
7735
7741
  const orderForm = provider.id === "whatsapp" ? await prepareOrderForm() : [];
7736
7742
  const providerEnv = await collectProviderEnv(provider);
7737
7743
  const demoId = provider.id === "whatsapp" ? "" : await askDemoId(provider);
@@ -7741,12 +7747,15 @@ var payments = new Command20("payments").description("enable payments (Stripe, S
7741
7747
  await runPattern(
7742
7748
  "enable-payments",
7743
7749
  cmd.args,
7744
- { provider: provider.id, providerEnv, demoId, currency },
7750
+ { provider: provider.id, providerEnv, demoId, ...business },
7745
7751
  {
7746
7752
  summary: `Enabled ${provider.label} payments.`,
7747
7753
  nextSteps: [
7748
7754
  ...blank.map((key) => `Set ${key} in .env.`),
7749
7755
  ...orderForm,
7756
+ ...business.currencies ? [
7757
+ "Visitors can pick a currency in the navbar; the others are estimates at the day's rate from velastack.dev. Edit `currencies` in src/lib/site.ts to change the list."
7758
+ ] : [],
7750
7759
  ...NEXT_STEPS2[provider.id],
7751
7760
  "Set the same variables on each deploy target with `vela env set`."
7752
7761
  ],
@@ -7778,24 +7787,65 @@ var NEXT_STEPS2 = {
7778
7787
  function isCurrency(code2) {
7779
7788
  return Intl.supportedValuesOf("currency").includes(code2.trim().toUpperCase());
7780
7789
  }
7781
- async function askCurrency(flag) {
7782
- if (flag) return flag.trim().toUpperCase();
7790
+ function isCountry(code2) {
7791
+ const upper = code2.trim().toUpperCase();
7792
+ return /^[A-Z]{2}$/.test(upper) && new Intl.DisplayNames(["en"], { type: "region" }).of(upper) !== upper;
7793
+ }
7794
+ function declaredBusiness() {
7783
7795
  const root = findWorkspaceRoot();
7784
7796
  const site = root ? path35.join(root, "src", "lib", "site.ts") : null;
7785
- if (site && fs35.existsSync(site) && /^\s*currency\s*:/m.test(fs35.readFileSync(site, "utf8"))) {
7786
- return void 0;
7797
+ if (!site || !fs35.existsSync(site)) return {};
7798
+ const source = fs35.readFileSync(site, "utf8");
7799
+ return {
7800
+ currency: /^\s*currency\s*:\s*['"]([A-Za-z]{3})['"]/m.exec(source)?.[1],
7801
+ country: /^\s*country\s*:\s*['"]([A-Za-z]{2})['"]/m.exec(source)?.[1],
7802
+ currencies: /^\s*currencies\s*:\s*\[([^\]]*)\]/m.exec(source)?.[1]
7803
+ };
7804
+ }
7805
+ async function askBusiness(flags, currencyRequired) {
7806
+ const declared = declaredBusiness();
7807
+ const business = {
7808
+ currency: flags.currency?.trim().toUpperCase(),
7809
+ country: flags.country?.trim().toUpperCase(),
7810
+ currencies: flags.currencies
7811
+ };
7812
+ const ask = isInteractive();
7813
+ if (!business.currency && !declared.currency) {
7814
+ if (!ask) return business;
7815
+ business.currency = await text7({
7816
+ message: "The currency the business prices in (ISO 4217)",
7817
+ placeholder: "MXN, EUR, USD...",
7818
+ validate: (value) => value && isCurrency(value) ? void 0 : currencyRequired || value ? "An ISO 4217 code, such as MXN or EUR" : void 0
7819
+ });
7787
7820
  }
7788
- if (!isInteractive()) return void 0;
7789
- const value = await p21.text({
7790
- message: "The business's currency, which every price is in (ISO 4217)",
7791
- placeholder: "MXN, EUR, USD...",
7792
- validate: (value2) => value2 && isCurrency(value2) ? void 0 : "An ISO 4217 code, such as MXN or EUR"
7793
- });
7821
+ const home = (business.currency ?? declared.currency ?? "").toUpperCase();
7822
+ if (!business.country && !declared.country && ask) {
7823
+ business.country = await text7({
7824
+ message: "The country the business is in (ISO 3166-1, two letters), so prices format for it",
7825
+ placeholder: "MX, ES, US...",
7826
+ validate: (value) => !value || isCountry(value) ? void 0 : "A two-letter country code, such as MX"
7827
+ });
7828
+ }
7829
+ if (business.currencies === void 0 && declared.currencies === void 0 && ask && home) {
7830
+ business.currencies = await text7({
7831
+ message: `Other currencies to show prices in, as estimates (comma-separated, blank for ${home} only)`,
7832
+ placeholder: "USD, EUR",
7833
+ validate: (value) => value && value.split(/[,\s]+/).some((code2) => code2 && !isCurrency(code2)) ? "ISO 4217 codes, comma-separated" : void 0
7834
+ });
7835
+ }
7836
+ return {
7837
+ currency: business.currency?.toUpperCase() || void 0,
7838
+ country: business.country?.toUpperCase() || void 0,
7839
+ currencies: business.currencies ?? void 0
7840
+ };
7841
+ }
7842
+ async function text7(options) {
7843
+ const value = await p21.text(options);
7794
7844
  if (p21.isCancel(value)) {
7795
7845
  p21.cancel("Operation cancelled.");
7796
7846
  process19.exit(0);
7797
7847
  }
7798
- return value.trim().toUpperCase();
7848
+ return (value ?? "").trim() || void 0;
7799
7849
  }
7800
7850
  async function prepareOrderForm() {
7801
7851
  if (process19.env.PUBLIC_WHATSAPP_ORDER_FORM) return [];
@@ -9489,8 +9539,8 @@ function describeTarget(target) {
9489
9539
  return target.name;
9490
9540
  }
9491
9541
  }
9492
- function bold(text18) {
9493
- return `\`${text18}\``;
9542
+ function bold(text19) {
9543
+ return `\`${text19}\``;
9494
9544
  }
9495
9545
 
9496
9546
  // src/lib/server-command.ts
@@ -14467,8 +14517,8 @@ function matrixCell(key, columns, index, states) {
14467
14517
  return pc23.dim("\u2014");
14468
14518
  }
14469
14519
  var ANSI3 = /\u001b\[[0-9;]*m/g;
14470
- function plain(text18) {
14471
- return text18.replace(ANSI3, "");
14520
+ function plain(text19) {
14521
+ return text19.replace(ANSI3, "");
14472
14522
  }
14473
14523
 
14474
14524
  // src/commands/env/set.ts