@tokenoftrust/cli 3.0.1 → 3.0.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tokenoftrust/cli",
3
- "version": "3.0.1",
3
+ "version": "3.0.3",
4
4
  "description": "Token of Trust developer CLI — clone a tenant store, run it locally with save→reload, and submit it for preview. Installs the `tot` command.",
5
5
  "license": "Apache-2.0",
6
6
  "author": "Token of Trust",
@@ -18,6 +18,10 @@ export const STRUCTURED_DATA_NODE_TOKENS: readonly string[];
18
18
  export const STRUCTURED_DATA_NAMED_TYPES: readonly string[];
19
19
  export const STRUCTURED_DATA_NAME_SOURCES: readonly string[];
20
20
  export function seoDeclarationProblems(seo: unknown): string[];
21
+ export const DEFAULT_CURRENCY: "USD";
22
+ export const CURRENCY_CODES: readonly string[];
23
+ export function resolveStoreCurrency(declared: unknown): string;
24
+ export function currencyDeclarationProblems(currency: unknown): string[];
21
25
  export const COMPLIANCE_NOTICES: Record<string, string>;
22
26
  export const MANDATED_NOTICE_KEYS: string[];
23
27
  export function nearestKey(key: string, known: readonly string[]): string | null;
@@ -19,7 +19,7 @@
19
19
 
20
20
  export const TOT_CONFIG_KEYS = [
21
21
  "$schema", "tenant", "scope", "mappings", "hostPlatform", "sample", "seed",
22
- "displayName", "siteType", "compliance", "capabilities", "features", "embeds", "seo",
22
+ "displayName", "siteType", "compliance", "capabilities", "features", "embeds", "seo", "currency",
23
23
  ];
24
24
  // Keys other tooling has written that the platform does NOT read, with the key it does.
25
25
  const RENAMED_CONFIG_KEYS = { appDomain: "scope", tenantId: "tenant" };
@@ -28,10 +28,48 @@ export const COMPLIANCE_KEYS = [
28
28
  "adultSignature", "prop65", "purchaseLimit", "stateEligibility", "exciseTax",
29
29
  ];
30
30
  export const FEATURE_KEYS = [
31
- "catalog", "productSearch", "savedItems", "quickView", "newsletter", "commerceSitemap", "productJsonLd", "ageGate",
31
+ "catalog", "productSearch", "savedItems", "quickView", "productBadges", "newsletter", "commerceSitemap", "productJsonLd", "ageGate",
32
32
  ];
33
33
  export const SITE_TYPES = ["commerce", "marketing"];
34
34
 
35
+ /** The currency a store sells in when `.tot/config.json` declares none. */
36
+ export const DEFAULT_CURRENCY = "USD";
37
+
38
+ /** ISO 4217 codes a store may declare as its `currency`. */
39
+ export const CURRENCY_CODES = Object.freeze(
40
+ ("AED AFN ALL AMD ANG AOA ARS AUD AWG AZN BAM BBD BDT BGN BHD BIF BMD BND BOB BRL BSD BTN BWP BYN BZD CAD CDF CHF CLP CNY COP " +
41
+ "CRC CUP CVE CZK DJF DKK DOP DZD EGP ERN ETB EUR FJD FKP GBP GEL GHS GIP GMD GNF GTQ GYD HKD HNL HTG HUF IDR ILS INR IQD IRR " +
42
+ "ISK JMD JOD JPY KES KGS KHR KMF KPW KRW KWD KYD KZT LAK LBP LKR LRD LSL LYD MAD MDL MGA MKD MMK MNT MOP MRU MUR MVR MWK MXN " +
43
+ "MYR MZN NAD NGN NIO NOK NPR NZD OMR PAB PEN PGK PHP PKR PLN PYG QAR RON RSD RUB RWF SAR SBD SCR SDG SEK SGD SHP SLE SOS SRD " +
44
+ "SSP STN SVC SYP SZL THB TJS TMT TND TOP TRY TTD TWD TZS UAH UGX USD UYU UZS VES VND VUV WST XAF XCD XCG XOF XPF YER ZAR ZMW ZWG").split(" "),
45
+ );
46
+
47
+ /**
48
+ * The ONE place a store's currency is resolved. A declared ISO 4217 code wins; anything
49
+ * else (absent, wrong shape, lowercase, unknown code) is USD. Every surface that prices,
50
+ * signs or formats an amount takes the currency from here, never from a literal. Only the
51
+ * store owner's `.tot/config.json` can change it: a shopper's request never reaches this.
52
+ *
53
+ * @param {unknown} declared
54
+ * @returns {string}
55
+ */
56
+ export function resolveStoreCurrency(declared) {
57
+ return typeof declared === "string" && CURRENCY_CODES.includes(declared) ? declared : DEFAULT_CURRENCY;
58
+ }
59
+
60
+ /**
61
+ * What is wrong with a declared `currency`, one sentence; `[]` when it is valid.
62
+ *
63
+ * @param {unknown} currency
64
+ * @returns {string[]}
65
+ */
66
+ export function currencyDeclarationProblems(currency) {
67
+ return typeof currency === "string" && CURRENCY_CODES.includes(currency)
68
+ ? []
69
+ : [`\`currency\` is ${JSON.stringify(currency)} — must be an uppercase ISO 4217 code such as "USD" or "CAD"`];
70
+ }
71
+
72
+
35
73
  /** Every `seo` key (mirrors packages/public-runtime/src/declared-tenant-config.mjs). */
36
74
  export const SEO_KEYS = Object.freeze(["trailingSlash", "verbatimSeoTitles", "structuredData"]);
37
75
 
@@ -608,6 +646,11 @@ export function validateDeclaredConfig(config, file = ".tot/config.json") {
608
646
  && !(Array.isArray(config.embeds) && config.embeds.every((/** @type {unknown} */ s) => typeof s === "string"))) {
609
647
  out.push(mk(ERROR, "config-embeds", file, '`embeds` must be an array of embed slugs, e.g. ["youtube"]'));
610
648
  }
649
+ if (config.currency !== undefined) {
650
+ for (const problem of currencyDeclarationProblems(config.currency)) {
651
+ out.push(mk(ERROR, "config-currency", file, `${problem} — the store sells in ${DEFAULT_CURRENCY} until it is fixed`));
652
+ }
653
+ }
611
654
  if (config.seo !== undefined) {
612
655
  for (const problem of seoDeclarationProblems(config.seo)) {
613
656
  out.push(mk(ERROR, "config-seo", `${file} seo`, `${problem} — the whole \`seo\` declaration is ignored until it is fixed`));