@pagefront/lint-commerce 0.12.0 → 0.12.1

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/README.md CHANGED
@@ -26,7 +26,7 @@ lint with their own catalogue, dispatched by sheet type.
26
26
 
27
27
  ## Catalogue
28
28
 
29
- Catalogue 0.16.0, supporting commerce releases 0.4.0 (Product Sheet spec
29
+ Catalogue 0.16.1, supporting commerce releases 0.4.0 (Product Sheet spec
30
30
  0.10.0, Organization Sheet spec 0.4.0) and 0.3.0, and the legacy draft line
31
31
  (format 0.9): 58 product rules (`PDP-E-001` to `PDP-E-018`, `PDP-W-001` to
32
32
  `PDP-W-039`, `PDP-I-001`) and 10 organization rules (`ORG-E-001` to
@@ -175,6 +175,14 @@ Added in 0.12.0 (catalogue 0.16.0), with commerce release 0.4.0. Requires
175
175
  - `PDP-E-018` and `ORG-E-004` — the sheet declares a `release` the release
176
176
  manifest does not list. At Layer 1 this is a single error at `/release`.
177
177
 
178
+ Changed in 0.12.1 (catalogue 0.16.1):
179
+
180
+ - `PDP-E-017` adds a type hint. When a reference matches no option but a
181
+ declared option has the same text under another JSON type, the message
182
+ names both types, and the finding's `values` carry `reference_type`,
183
+ `declared_option` and `declared_type`. Comparison is unchanged and the
184
+ finding stays an error.
185
+
178
186
  ## API
179
187
 
180
188
  The public surface — everything importable from the package root, and
package/dist/catalogue.js CHANGED
@@ -67,6 +67,6 @@ import { pdpI001 } from "./rules/pdp-i-001.js";
67
67
  export const commerceCatalogue = {
68
68
  vertical: "commerce",
69
69
  releases: KNOWN_RELEASES,
70
- catalogueVersion: "0.16.0",
70
+ catalogueVersion: "0.16.1",
71
71
  rules: [pdpE001, pdpE002, pdpE003, pdpE004, pdpE005, pdpE006, pdpE007, pdpE008, pdpE009, pdpE010, pdpE011, pdpE012, pdpE013, pdpE014, pdpE015, pdpE016, pdpE017, pdpE018, pdpW001, pdpW002, pdpW003, pdpW004, pdpW005, pdpW006, pdpW007, pdpW008, pdpW009, pdpW010, pdpW011, pdpW012, pdpW013, pdpW014, pdpW015, pdpW016, pdpW017, pdpW018, pdpW019, pdpW020, pdpW021, pdpW022, pdpW023, pdpW024, pdpW025, pdpW026, pdpW027, pdpW028, pdpW029, pdpW030, pdpW031, pdpW032, pdpW033, pdpW034, pdpW035, pdpW036, pdpW037, pdpW038, pdpW039, pdpI001],
72
72
  };
@@ -21,6 +21,6 @@ import { orgW006 } from "./rules/org-w-006.js";
21
21
  export const organizationCatalogue = {
22
22
  vertical: "commerce",
23
23
  releases: KNOWN_RELEASES,
24
- catalogueVersion: "0.16.0",
24
+ catalogueVersion: "0.16.1",
25
25
  rules: [orgE001, orgE002, orgE003, orgE004, orgW001, orgW002, orgW003, orgW004, orgW005, orgW006],
26
26
  };
@@ -1,4 +1,13 @@
1
1
  import { asObject, own, pricedConfiguratorId, pricingBlock, seg } from "./configurator-pricing.js";
2
+ function isScalar(value) {
3
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
4
+ }
5
+ /** The declared option that equals `value` after string conversion, if any. */
6
+ function sameTextOption(value, declared) {
7
+ if (!isScalar(value))
8
+ return undefined;
9
+ return declared.find((v) => isScalar(v) && String(v) === String(value));
10
+ }
2
11
  function declaredDimensions(configurator) {
3
12
  const out = new Map();
4
13
  const dimensions = configurator["dimensions"];
@@ -22,15 +31,34 @@ function unresolved(pairs, path, dimensions) {
22
31
  for (const [dimension, value] of Object.entries(asObject(pairs) ?? {})) {
23
32
  const option = JSON.stringify(value);
24
33
  const declared = dimensions.get(dimension);
25
- let problem = null;
34
+ const at = `${path}${seg(dimension)}`;
26
35
  if (declared === undefined) {
27
- problem = `the configurator declares no dimension \`${dimension}\``;
36
+ const problem = `the configurator declares no dimension \`${dimension}\``;
37
+ hits.push({ path: at, values: { dimension, option, problem } });
28
38
  }
29
39
  else if (declared.values !== null && !declared.values.some((v) => v === value)) {
30
- problem = `\`${dimension}\` lists no option \`${option}\``;
31
- }
32
- if (problem !== null) {
33
- hits.push({ path: `${path}${seg(dimension)}`, values: { dimension, option, problem } });
40
+ const near = sameTextOption(value, declared.values);
41
+ if (near === undefined) {
42
+ const problem = `\`${dimension}\` lists no option \`${option}\``;
43
+ hits.push({ path: at, values: { dimension, option, problem } });
44
+ }
45
+ else {
46
+ const declaredOption = JSON.stringify(near);
47
+ const referenceType = typeof value;
48
+ const declaredType = typeof near;
49
+ const problem = `it references \`${option}\` (${referenceType}); dimension \`${dimension}\` declares \`${declaredOption}\` (${declaredType})`;
50
+ hits.push({
51
+ path: at,
52
+ values: {
53
+ dimension,
54
+ option,
55
+ problem,
56
+ reference_type: referenceType,
57
+ declared_option: declaredOption,
58
+ declared_type: declaredType,
59
+ },
60
+ });
61
+ }
34
62
  }
35
63
  }
36
64
  return hits;
package/dist/version.d.ts CHANGED
@@ -5,4 +5,4 @@
5
5
  * (test/linter-version.test.mjs) fails when they diverge. Regenerate
6
6
  * on version bump.
7
7
  */
8
- export declare const PACKAGE_VERSION = "0.12.0";
8
+ export declare const PACKAGE_VERSION = "0.12.1";
package/dist/version.js CHANGED
@@ -5,4 +5,4 @@
5
5
  * (test/linter-version.test.mjs) fails when they diverge. Regenerate
6
6
  * on version bump.
7
7
  */
8
- export const PACKAGE_VERSION = "0.12.0";
8
+ export const PACKAGE_VERSION = "0.12.1";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagefront/lint-commerce",
3
- "version": "0.12.0",
3
+ "version": "0.12.1",
4
4
  "description": "Pagefront commerce linter: the commerce rule catalogue and CLI, on the @pagefront/lint-core engine.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {