@tokenoftrust/cli 2.4.13 → 2.4.15

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": "2.4.13",
3
+ "version": "2.4.15",
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",
@@ -31,10 +31,10 @@ export const FEATURE_KEYS = [
31
31
  export const SITE_TYPES = ["commerce", "marketing"];
32
32
 
33
33
  /** Every `seo` key (mirrors packages/public-runtime/src/declared-tenant-config.mjs). */
34
- export const SEO_KEYS = Object.freeze(["trailingSlash", "structuredData"]);
34
+ export const SEO_KEYS = Object.freeze(["trailingSlash", "verbatimCatalogTitles", "structuredData"]);
35
35
 
36
36
  /** Every `seo.structuredData` key. */
37
- export const STRUCTURED_DATA_KEYS = Object.freeze(["graphs", "names", "reviews"]);
37
+ export const STRUCTURED_DATA_KEYS = Object.freeze(["graphs", "names", "reviews", "onlyOn"]);
38
38
 
39
39
  /**
40
40
  * The page types a structured-data profile declares a graph for. `productGroup` is a product
@@ -86,6 +86,9 @@ export function seoDeclarationProblems(seo) {
86
86
  if (source.trailingSlash !== undefined && typeof source.trailingSlash !== "boolean") {
87
87
  problems.push("`seo.trailingSlash` must be true or false");
88
88
  }
89
+ if (source.verbatimCatalogTitles !== undefined && typeof source.verbatimCatalogTitles !== "boolean") {
90
+ problems.push("`seo.verbatimCatalogTitles` must be true or false");
91
+ }
89
92
  const sd = source.structuredData;
90
93
  if (sd === undefined) return problems;
91
94
  if (!isPlainObject(sd)) return [...problems, "`seo.structuredData` must be an object"];
@@ -135,6 +138,21 @@ export function seoDeclarationProblems(seo) {
135
138
  if (data.reviews !== undefined && typeof data.reviews !== "boolean") {
136
139
  problems.push("`seo.structuredData.reviews` must be true or false");
137
140
  }
141
+ if (data.onlyOn !== undefined) {
142
+ if (!isPlainObject(data.onlyOn)) {
143
+ problems.push("`seo.structuredData.onlyOn` must map a node type to the paths it is emitted on");
144
+ } else {
145
+ for (const [token, paths] of Object.entries(/** @type {Record<string, unknown>} */ (data.onlyOn))) {
146
+ const at = `seo.structuredData.onlyOn.${token}`;
147
+ if (!STRUCTURED_DATA_NODE_TOKENS.includes(token)) {
148
+ problems.push(`\`${at}\`: ${JSON.stringify(token)} is not a node type the renderer builds`);
149
+ } else if (!Array.isArray(paths) || paths.length === 0
150
+ || !paths.every((p) => typeof p === "string" && p.startsWith("/") && !p.startsWith("//"))) {
151
+ problems.push(`\`${at}\` must be a non-empty array of root-absolute paths such as "/faq/"`);
152
+ }
153
+ }
154
+ }
155
+ }
138
156
  return problems;
139
157
  }
140
158