@tokenoftrust/cli 3.0.3 → 3.0.4
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 +1 -1
- package/src/declared-config.d.mts +3 -0
- package/src/declared-config.mjs +50 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tokenoftrust/cli",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.4",
|
|
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",
|
|
@@ -22,6 +22,9 @@ export const DEFAULT_CURRENCY: "USD";
|
|
|
22
22
|
export const CURRENCY_CODES: readonly string[];
|
|
23
23
|
export function resolveStoreCurrency(declared: unknown): string;
|
|
24
24
|
export function currencyDeclarationProblems(currency: unknown): string[];
|
|
25
|
+
export const SHIPPING_KEYS: readonly string[];
|
|
26
|
+
export const MAX_SHIPPING_AMOUNT: number;
|
|
27
|
+
export function shippingDeclarationProblems(shipping: unknown): string[];
|
|
25
28
|
export const COMPLIANCE_NOTICES: Record<string, string>;
|
|
26
29
|
export const MANDATED_NOTICE_KEYS: string[];
|
|
27
30
|
export function nearestKey(key: string, known: readonly string[]): string | null;
|
package/src/declared-config.mjs
CHANGED
|
@@ -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", "currency",
|
|
22
|
+
"displayName", "siteType", "compliance", "capabilities", "features", "embeds", "seo", "currency", "shipping",
|
|
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" };
|
|
@@ -196,6 +196,46 @@ export function seoDeclarationProblems(seo) {
|
|
|
196
196
|
return problems;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/** Every `shipping` key (mirrors packages/public-runtime/src/declared-tenant-config.mjs). */
|
|
200
|
+
export const SHIPPING_KEYS = Object.freeze(["flatRate", "freeAtOrAbove"]);
|
|
201
|
+
|
|
202
|
+
/** Largest shipping amount a declaration may state, in the cart's currency. */
|
|
203
|
+
export const MAX_SHIPPING_AMOUNT = 100000;
|
|
204
|
+
|
|
205
|
+
/** @param {unknown} value */
|
|
206
|
+
const isShippingAmount = (value) =>
|
|
207
|
+
typeof value === "number" && Number.isFinite(value) && value >= 0 && value <= MAX_SHIPPING_AMOUNT
|
|
208
|
+
&& Math.abs(value * 100 - Math.round(value * 100)) < 1e-6;
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* What is wrong with a declared `shipping` value, one sentence per problem; `[]` when it is
|
|
212
|
+
* valid. A policy with any problem is refused whole, so checkout never charges half of one.
|
|
213
|
+
*
|
|
214
|
+
* @param {unknown} shipping
|
|
215
|
+
* @returns {string[]}
|
|
216
|
+
*/
|
|
217
|
+
export function shippingDeclarationProblems(shipping) {
|
|
218
|
+
if (!isPlainObject(shipping)) return ["`shipping` must be an object"];
|
|
219
|
+
const problems = [];
|
|
220
|
+
const source = /** @type {Record<string, unknown>} */ (shipping);
|
|
221
|
+
for (const key of Object.keys(source)) {
|
|
222
|
+
if (!SHIPPING_KEYS.includes(key)) problems.push(`\`shipping.${key}\` is not a shipping key (${SHIPPING_KEYS.join(", ")})`);
|
|
223
|
+
}
|
|
224
|
+
if (!isShippingAmount(source.flatRate)) {
|
|
225
|
+
problems.push(`\`shipping.flatRate\` must be an amount from 0 to ${MAX_SHIPPING_AMOUNT} with at most two decimal places`);
|
|
226
|
+
}
|
|
227
|
+
if (source.freeAtOrAbove !== undefined && !(isShippingAmount(source.freeAtOrAbove) && /** @type {number} */ (source.freeAtOrAbove) > 0)) {
|
|
228
|
+
problems.push(`\`shipping.freeAtOrAbove\` must be an amount above 0 and at most ${MAX_SHIPPING_AMOUNT} with at most two decimal places`);
|
|
229
|
+
}
|
|
230
|
+
return problems;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
/** The owner-facing sentence for an invalid `shipping` declaration. */
|
|
234
|
+
function shippingProblemMessage(problems) {
|
|
235
|
+
return `\`shipping\` is not a valid shipping policy (${problems.join("; ")}). ` +
|
|
236
|
+
"Checkout charges no shipping until it is fixed.";
|
|
237
|
+
}
|
|
238
|
+
|
|
199
239
|
|
|
200
240
|
/** What each compliance key puts on the page — the thing that is missing when it is. */
|
|
201
241
|
export const COMPLIANCE_NOTICES = {
|
|
@@ -568,6 +608,8 @@ export function declarationFindings(current, previous) {
|
|
|
568
608
|
if (warning.enabled && warning.problems.length > 0) {
|
|
569
609
|
out.push(`CONFIG: ${nicotineWarningProblemMessage(warning.problems)}`);
|
|
570
610
|
}
|
|
611
|
+
const shipping = current.shipping === undefined ? [] : shippingDeclarationProblems(current.shipping);
|
|
612
|
+
if (shipping.length > 0) out.push(`CONFIG: ${shippingProblemMessage(shipping)}`);
|
|
571
613
|
}
|
|
572
614
|
for (const { key, notice } of droppedMandatedNotices(previous, current)) {
|
|
573
615
|
out.push(
|
|
@@ -656,6 +698,13 @@ export function validateDeclaredConfig(config, file = ".tot/config.json") {
|
|
|
656
698
|
out.push(mk(ERROR, "config-seo", `${file} seo`, `${problem} — the whole \`seo\` declaration is ignored until it is fixed`));
|
|
657
699
|
}
|
|
658
700
|
}
|
|
701
|
+
if (config.shipping !== undefined) {
|
|
702
|
+
const problems = shippingDeclarationProblems(config.shipping);
|
|
703
|
+
if (problems.length > 0) {
|
|
704
|
+
out.push(mk(ERROR, "config-shipping", `${file} shipping`, shippingProblemMessage(problems),
|
|
705
|
+
'declare e.g. `"shipping": { "flatRate": 5.99, "freeAtOrAbove": 100 }`, or remove `shipping` to charge none'));
|
|
706
|
+
}
|
|
707
|
+
}
|
|
659
708
|
return out;
|
|
660
709
|
}
|
|
661
710
|
|