@pagefront/lint-commerce 0.6.0 → 0.8.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/README.md +42 -2
- package/dist/catalogue.js +15 -2
- package/dist/organization-catalogue.js +1 -1
- package/dist/product-schema.js +143 -19
- package/dist/rules/configurator-pricing.d.ts +114 -0
- package/dist/rules/configurator-pricing.js +349 -0
- package/dist/rules/pdp-e-001.js +12 -3
- package/dist/rules/pdp-e-005.d.ts +12 -0
- package/dist/rules/pdp-e-005.js +40 -0
- package/dist/rules/pdp-e-006.d.ts +11 -0
- package/dist/rules/pdp-e-006.js +36 -0
- package/dist/rules/pdp-e-007.d.ts +12 -0
- package/dist/rules/pdp-e-007.js +53 -0
- package/dist/rules/pdp-e-008.d.ts +10 -0
- package/dist/rules/pdp-e-008.js +41 -0
- package/dist/rules/pdp-e-009.d.ts +12 -0
- package/dist/rules/pdp-e-009.js +62 -0
- package/dist/rules/pdp-e-010.d.ts +10 -0
- package/dist/rules/pdp-e-010.js +37 -0
- package/dist/rules/pdp-e-011.d.ts +11 -0
- package/dist/rules/pdp-e-011.js +53 -0
- package/dist/rules/pdp-e-012.d.ts +2 -0
- package/dist/rules/pdp-e-012.js +32 -0
- package/dist/rules/pdp-w-031.d.ts +12 -0
- package/dist/rules/pdp-w-031.js +35 -0
- package/dist/rules/pdp-w-032.d.ts +10 -0
- package/dist/rules/pdp-w-032.js +42 -0
- package/dist/rules/pdp-w-033.d.ts +10 -0
- package/dist/rules/pdp-w-033.js +30 -0
- package/dist/rules/pdp-w-034.d.ts +10 -0
- package/dist/rules/pdp-w-034.js +28 -0
- package/dist/rules/pdp-w-035.d.ts +11 -0
- package/dist/rules/pdp-w-035.js +41 -0
- package/dist/rules/sheet-url-host.d.ts +11 -0
- package/dist/rules/sheet-url-host.js +22 -0
- package/dist/schema-validators.js +8 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,8 +26,8 @@ lint with their own catalogue, dispatched by sheet type.
|
|
|
26
26
|
|
|
27
27
|
## Catalogue
|
|
28
28
|
|
|
29
|
-
Catalogue 0.
|
|
30
|
-
`PDP-E-
|
|
29
|
+
Catalogue 0.11.0, targeting format 0.9: 48 product rules (`PDP-E-001` to
|
|
30
|
+
`PDP-E-012`, `PDP-W-001` to `PDP-W-035`, `PDP-I-001`) and 7 organization
|
|
31
31
|
rules (`ORG-E-001`, `ORG-W-001` to `ORG-W-006`), each defined in
|
|
32
32
|
[`rules.md`](https://github.com/themachineweb/pagefront/blob/main/commerce/spec/rules.md)
|
|
33
33
|
with its target, check, message and remediation. Every report carries the
|
|
@@ -53,6 +53,46 @@ section:
|
|
|
53
53
|
- `PDP-W-030` — a `warranty` on an Offer, or a `pagefront:manufacturerWarranty`
|
|
54
54
|
on the Product, carries neither `durationOfWarranty` nor `description`
|
|
55
55
|
|
|
56
|
+
Added in 0.7.0 (catalogue 0.10.0), from the organization spec's
|
|
57
|
+
["Linking contract"](https://themachineweb.org/pagefront/spec/commerce/organization#linking-contract-identity-only)
|
|
58
|
+
section:
|
|
59
|
+
|
|
60
|
+
- `PDP-E-005` — `pagefront:sheetUrl` on an Offer's `seller` is on a host
|
|
61
|
+
other than the product sheet's
|
|
62
|
+
- `PDP-E-006` — `pagefront:sheetUrl` on `brand` is on a host other than
|
|
63
|
+
that of the brand's `@id`
|
|
64
|
+
- `PDP-W-031` — an Offer's `seller` has an `@id` but no
|
|
65
|
+
`pagefront:sheetUrl`, and the Offer states no return or shipping terms
|
|
66
|
+
of its own
|
|
67
|
+
|
|
68
|
+
Added in 0.8.0 (catalogue 0.11.0), from the product spec's
|
|
69
|
+
["Configurator pricing and price bands"](https://themachineweb.org/pagefront/spec/commerce/product#configurator-pricing-and-price-bands)
|
|
70
|
+
section. Configurator pricing moved from `pagefront:configurator` into the
|
|
71
|
+
offer's `pagefront:configuratorPricing`; a sheet carrying prices inside the
|
|
72
|
+
configurator now fails Layer 1.
|
|
73
|
+
|
|
74
|
+
- `PDP-E-001` now also covers the pricing block's `configurator`
|
|
75
|
+
reference, which must equal the `@id` of the Sheet's
|
|
76
|
+
`pagefront:configurator`
|
|
77
|
+
- `PDP-E-007` — `baseConfiguration` omits a priced dimension, or names a
|
|
78
|
+
dimension or option the configurator does not declare
|
|
79
|
+
- `PDP-E-008` — the modifier of a base option is not zero
|
|
80
|
+
- `PDP-E-009` — a modifier names an unknown dimension or option, or a
|
|
81
|
+
dimension declared `affectsPrice: false`
|
|
82
|
+
- `PDP-E-010` — an Offer's `price` differs from its pricing block's
|
|
83
|
+
`basePrice`
|
|
84
|
+
- `PDP-E-011` — an AggregateOffer's `lowPrice` or `highPrice` differs
|
|
85
|
+
from the band computed from a complete pricing block
|
|
86
|
+
- `PDP-E-012` — more than one offer prices the same configurator
|
|
87
|
+
- `PDP-W-032` — a priced option has no modifier and `pricing` is not
|
|
88
|
+
`partial`
|
|
89
|
+
- `PDP-W-033` — a configurator has priced dimensions and no offer prices it
|
|
90
|
+
- `PDP-W-034` — an offer states a price beside a configurator and no
|
|
91
|
+
offer carries a pricing block
|
|
92
|
+
- `PDP-W-035` — `basePrice` looks like a component price (heuristic)
|
|
93
|
+
|
|
94
|
+
Amounts are summed and compared as exact decimals.
|
|
95
|
+
|
|
56
96
|
## API
|
|
57
97
|
|
|
58
98
|
The public surface — everything importable from the package root, and
|
package/dist/catalogue.js
CHANGED
|
@@ -2,6 +2,14 @@ import { pdpE001 } from "./rules/pdp-e-001.js";
|
|
|
2
2
|
import { pdpE002 } from "./rules/pdp-e-002.js";
|
|
3
3
|
import { pdpE003 } from "./rules/pdp-e-003.js";
|
|
4
4
|
import { pdpE004 } from "./rules/pdp-e-004.js";
|
|
5
|
+
import { pdpE005 } from "./rules/pdp-e-005.js";
|
|
6
|
+
import { pdpE006 } from "./rules/pdp-e-006.js";
|
|
7
|
+
import { pdpE007 } from "./rules/pdp-e-007.js";
|
|
8
|
+
import { pdpE008 } from "./rules/pdp-e-008.js";
|
|
9
|
+
import { pdpE009 } from "./rules/pdp-e-009.js";
|
|
10
|
+
import { pdpE010 } from "./rules/pdp-e-010.js";
|
|
11
|
+
import { pdpE011 } from "./rules/pdp-e-011.js";
|
|
12
|
+
import { pdpE012 } from "./rules/pdp-e-012.js";
|
|
5
13
|
import { pdpW001 } from "./rules/pdp-w-001.js";
|
|
6
14
|
import { pdpW002 } from "./rules/pdp-w-002.js";
|
|
7
15
|
import { pdpW003 } from "./rules/pdp-w-003.js";
|
|
@@ -32,6 +40,11 @@ import { pdpW027 } from "./rules/pdp-w-027.js";
|
|
|
32
40
|
import { pdpW028 } from "./rules/pdp-w-028.js";
|
|
33
41
|
import { pdpW029 } from "./rules/pdp-w-029.js";
|
|
34
42
|
import { pdpW030 } from "./rules/pdp-w-030.js";
|
|
43
|
+
import { pdpW031 } from "./rules/pdp-w-031.js";
|
|
44
|
+
import { pdpW032 } from "./rules/pdp-w-032.js";
|
|
45
|
+
import { pdpW033 } from "./rules/pdp-w-033.js";
|
|
46
|
+
import { pdpW034 } from "./rules/pdp-w-034.js";
|
|
47
|
+
import { pdpW035 } from "./rules/pdp-w-035.js";
|
|
35
48
|
import { pdpI001 } from "./rules/pdp-i-001.js";
|
|
36
49
|
/**
|
|
37
50
|
* The commerce product-sheet rule catalogue — the executable form of
|
|
@@ -43,6 +56,6 @@ import { pdpI001 } from "./rules/pdp-i-001.js";
|
|
|
43
56
|
export const commerceCatalogue = {
|
|
44
57
|
vertical: "commerce",
|
|
45
58
|
formatVersion: "0.9",
|
|
46
|
-
catalogueVersion: "0.
|
|
47
|
-
rules: [pdpE001, pdpE002, pdpE003, pdpE004, 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, pdpI001],
|
|
59
|
+
catalogueVersion: "0.11.0",
|
|
60
|
+
rules: [pdpE001, pdpE002, pdpE003, pdpE004, pdpE005, pdpE006, pdpE007, pdpE008, pdpE009, pdpE010, pdpE011, pdpE012, 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, pdpI001],
|
|
48
61
|
};
|
|
@@ -17,6 +17,6 @@ import { orgW006 } from "./rules/org-w-006.js";
|
|
|
17
17
|
export const organizationCatalogue = {
|
|
18
18
|
vertical: "commerce",
|
|
19
19
|
formatVersion: "0.9",
|
|
20
|
-
catalogueVersion: "0.
|
|
20
|
+
catalogueVersion: "0.11.0",
|
|
21
21
|
rules: [orgE001, orgW001, orgW002, orgW003, orgW004, orgW005, orgW006],
|
|
22
22
|
};
|
package/dist/product-schema.js
CHANGED
|
@@ -10,7 +10,7 @@ export const PRODUCT_SCHEMA = {
|
|
|
10
10
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
11
11
|
"$id": "https://themachineweb.org/pagefront/spec/commerce/product/v0.9.json",
|
|
12
12
|
"title": "Pagefront Product Sheet v0.9",
|
|
13
|
-
"description": "Formal schema for the Pagefront product sheet. v0.9
|
|
13
|
+
"description": "Formal schema for the Pagefront product sheet. Revision of 2026-10-01 (breaking, within v0.9): configurator pricing moves from pagefront:configurator to the offer. The configurator loses basePrice, basePriceCurrency and priceFormula, its options lose priceModifier and currency, and it gains an optional @id and an exclusions[] array; configurator dimensions gain affectsPrice; Offer and AggregateOffer accept pagefront:configuratorPricing, which names the configurator it prices and carries baseConfiguration, basePrice, modifiers, optional adjustments[] and a pricing completeness flag. v0.9 sheets that carried prices inside the configurator no longer validate. v0.9 was otherwise an additive release on top of v0.8: the legalEntity entry's organization now also validates in reference-stub form (@type + @id, no name) so entries can reference a Commerce Organization Sheet; the inline form and all other constraints are unchanged, and v0.8 sheets remain valid once their format_version is updated. v0.8 is an additive release on top of v0.7: it adds a pagefront:featureGroup[] array for grouped, ordered technical specifications (groups of Schema.org PropertyValue entries, with an optional pagefront:presentationValue display variant per entry), a pagefront:productHighlights[] array of ordered publisher-authored selling-point strings, and a pagefront:legalEntity[] array for role-typed legal entities behind a product (closed role enum: brand_owner, licensee, authorized_representative, importer, manufacturer — EU GPSR responsible persons and similar). gtin and gtin13 now accept a string or an array of strings (regional packaging, re-releases); category now accepts the display string, a Schema.org CategoryCode object, or a mixed array of both. The pagefront:Document role enum gains repairability_index, recall_notice, and declaration_of_conformity; the pagefront:RelatedProduct relationship enum gains service. v0.8 also adds two GPSR-driven safety fields: a pagefront:safetyWarning[] array for typed, language-scoped safety warnings (text required; optional pictogram URL and open-vocabulary hazardCategory) and a pagefront:safetyNotice[] array for structured recall/safety notices (closed noticeType enum: recall, warning; closed remedy enum: repair, replacement, refund). v0.7 sheets remain valid under v0.8 once their format_version is updated. Validates the envelope and pagefront-namespaced extensions strictly; Schema.org-typed blocks permit additional unspecified properties.",
|
|
14
14
|
"type": "object",
|
|
15
15
|
"required": [
|
|
16
16
|
"format_version",
|
|
@@ -135,7 +135,13 @@ export const PRODUCT_SCHEMA = {
|
|
|
135
135
|
}
|
|
136
136
|
},
|
|
137
137
|
"brand": {
|
|
138
|
-
"type": "object"
|
|
138
|
+
"type": "object",
|
|
139
|
+
"properties": {
|
|
140
|
+
"pagefront:sheetUrl": {
|
|
141
|
+
"type": "string",
|
|
142
|
+
"format": "uri"
|
|
143
|
+
}
|
|
144
|
+
}
|
|
139
145
|
},
|
|
140
146
|
"description": {
|
|
141
147
|
"type": "string"
|
|
@@ -1053,6 +1059,10 @@ export const PRODUCT_SCHEMA = {
|
|
|
1053
1059
|
"email": {
|
|
1054
1060
|
"type": "string",
|
|
1055
1061
|
"format": "email"
|
|
1062
|
+
},
|
|
1063
|
+
"pagefront:sheetUrl": {
|
|
1064
|
+
"type": "string",
|
|
1065
|
+
"format": "uri"
|
|
1056
1066
|
}
|
|
1057
1067
|
},
|
|
1058
1068
|
"additionalProperties": true
|
|
@@ -1199,7 +1209,13 @@ export const PRODUCT_SCHEMA = {
|
|
|
1199
1209
|
"pattern": "^https?://schema\\.org/(NewCondition|UsedCondition|RefurbishedCondition|DamagedCondition)$"
|
|
1200
1210
|
},
|
|
1201
1211
|
"seller": {
|
|
1202
|
-
"type": "object"
|
|
1212
|
+
"type": "object",
|
|
1213
|
+
"properties": {
|
|
1214
|
+
"pagefront:sheetUrl": {
|
|
1215
|
+
"type": "string",
|
|
1216
|
+
"format": "uri"
|
|
1217
|
+
}
|
|
1218
|
+
}
|
|
1203
1219
|
},
|
|
1204
1220
|
"shippingDetails": {
|
|
1205
1221
|
"oneOf": [
|
|
@@ -1238,6 +1254,9 @@ export const PRODUCT_SCHEMA = {
|
|
|
1238
1254
|
},
|
|
1239
1255
|
"pagefront:priceOnRequest": {
|
|
1240
1256
|
"$ref": "#/$defs/priceOnRequest"
|
|
1257
|
+
},
|
|
1258
|
+
"pagefront:configuratorPricing": {
|
|
1259
|
+
"$ref": "#/$defs/configuratorPricing"
|
|
1241
1260
|
}
|
|
1242
1261
|
},
|
|
1243
1262
|
"anyOf": [
|
|
@@ -1258,6 +1277,12 @@ export const PRODUCT_SCHEMA = {
|
|
|
1258
1277
|
]
|
|
1259
1278
|
}
|
|
1260
1279
|
],
|
|
1280
|
+
"dependentRequired": {
|
|
1281
|
+
"pagefront:configuratorPricing": [
|
|
1282
|
+
"price",
|
|
1283
|
+
"priceCurrency"
|
|
1284
|
+
]
|
|
1285
|
+
},
|
|
1261
1286
|
"additionalProperties": true
|
|
1262
1287
|
},
|
|
1263
1288
|
"aggregateOffer": {
|
|
@@ -1308,6 +1333,9 @@ export const PRODUCT_SCHEMA = {
|
|
|
1308
1333
|
},
|
|
1309
1334
|
"seller": {
|
|
1310
1335
|
"type": "object"
|
|
1336
|
+
},
|
|
1337
|
+
"pagefront:configuratorPricing": {
|
|
1338
|
+
"$ref": "#/$defs/configuratorPricing"
|
|
1311
1339
|
}
|
|
1312
1340
|
},
|
|
1313
1341
|
"additionalProperties": true
|
|
@@ -1641,15 +1669,9 @@ export const PRODUCT_SCHEMA = {
|
|
|
1641
1669
|
"@type": {
|
|
1642
1670
|
"const": "pagefront:Configurator"
|
|
1643
1671
|
},
|
|
1644
|
-
"
|
|
1645
|
-
"type": "string"
|
|
1646
|
-
},
|
|
1647
|
-
"basePriceCurrency": {
|
|
1672
|
+
"@id": {
|
|
1648
1673
|
"type": "string",
|
|
1649
|
-
"
|
|
1650
|
-
},
|
|
1651
|
-
"priceFormula": {
|
|
1652
|
-
"type": "string"
|
|
1674
|
+
"minLength": 1
|
|
1653
1675
|
},
|
|
1654
1676
|
"dimensions": {
|
|
1655
1677
|
"type": "array",
|
|
@@ -1657,6 +1679,14 @@ export const PRODUCT_SCHEMA = {
|
|
|
1657
1679
|
"$ref": "#/$defs/configuratorDimension"
|
|
1658
1680
|
},
|
|
1659
1681
|
"minItems": 1
|
|
1682
|
+
},
|
|
1683
|
+
"exclusions": {
|
|
1684
|
+
"type": "array",
|
|
1685
|
+
"items": {
|
|
1686
|
+
"$ref": "#/$defs/configurationSelection",
|
|
1687
|
+
"type": "object",
|
|
1688
|
+
"minProperties": 1
|
|
1689
|
+
}
|
|
1660
1690
|
}
|
|
1661
1691
|
},
|
|
1662
1692
|
"additionalProperties": false
|
|
@@ -1691,20 +1721,19 @@ export const PRODUCT_SCHEMA = {
|
|
|
1691
1721
|
}
|
|
1692
1722
|
]
|
|
1693
1723
|
},
|
|
1694
|
-
"priceModifier": {
|
|
1695
|
-
"type": "string"
|
|
1696
|
-
},
|
|
1697
|
-
"currency": {
|
|
1698
|
-
"type": "string",
|
|
1699
|
-
"pattern": "^[A-Z]{3}$"
|
|
1700
|
-
},
|
|
1701
1724
|
"description": {
|
|
1702
1725
|
"type": "string"
|
|
1703
|
-
}
|
|
1726
|
+
},
|
|
1727
|
+
"priceModifier": false,
|
|
1728
|
+
"currency": false
|
|
1704
1729
|
},
|
|
1705
1730
|
"additionalProperties": true
|
|
1706
1731
|
}
|
|
1707
1732
|
},
|
|
1733
|
+
"affectsPrice": {
|
|
1734
|
+
"type": "boolean",
|
|
1735
|
+
"default": true
|
|
1736
|
+
},
|
|
1708
1737
|
"system": {
|
|
1709
1738
|
"type": "string"
|
|
1710
1739
|
},
|
|
@@ -1714,6 +1743,101 @@ export const PRODUCT_SCHEMA = {
|
|
|
1714
1743
|
},
|
|
1715
1744
|
"additionalProperties": false
|
|
1716
1745
|
},
|
|
1746
|
+
"configurationSelection": {
|
|
1747
|
+
"type": "object",
|
|
1748
|
+
"additionalProperties": {
|
|
1749
|
+
"anyOf": [
|
|
1750
|
+
{
|
|
1751
|
+
"type": "string"
|
|
1752
|
+
},
|
|
1753
|
+
{
|
|
1754
|
+
"type": "number"
|
|
1755
|
+
},
|
|
1756
|
+
{
|
|
1757
|
+
"type": "boolean"
|
|
1758
|
+
}
|
|
1759
|
+
]
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
"configuratorPricing": {
|
|
1763
|
+
"type": "object",
|
|
1764
|
+
"required": [
|
|
1765
|
+
"@type",
|
|
1766
|
+
"configurator",
|
|
1767
|
+
"baseConfiguration",
|
|
1768
|
+
"basePrice",
|
|
1769
|
+
"modifiers"
|
|
1770
|
+
],
|
|
1771
|
+
"properties": {
|
|
1772
|
+
"@type": {
|
|
1773
|
+
"const": "pagefront:ConfiguratorPricing"
|
|
1774
|
+
},
|
|
1775
|
+
"configurator": {
|
|
1776
|
+
"type": "object",
|
|
1777
|
+
"required": [
|
|
1778
|
+
"@id"
|
|
1779
|
+
],
|
|
1780
|
+
"properties": {
|
|
1781
|
+
"@type": {
|
|
1782
|
+
"const": "pagefront:Configurator"
|
|
1783
|
+
},
|
|
1784
|
+
"@id": {
|
|
1785
|
+
"type": "string",
|
|
1786
|
+
"minLength": 1
|
|
1787
|
+
}
|
|
1788
|
+
},
|
|
1789
|
+
"additionalProperties": false
|
|
1790
|
+
},
|
|
1791
|
+
"baseConfiguration": {
|
|
1792
|
+
"$ref": "#/$defs/configurationSelection"
|
|
1793
|
+
},
|
|
1794
|
+
"basePrice": {
|
|
1795
|
+
"type": "string",
|
|
1796
|
+
"pattern": "^[0-9]+(\\.[0-9]+)?$"
|
|
1797
|
+
},
|
|
1798
|
+
"modifiers": {
|
|
1799
|
+
"type": "object",
|
|
1800
|
+
"additionalProperties": {
|
|
1801
|
+
"type": "object",
|
|
1802
|
+
"additionalProperties": {
|
|
1803
|
+
"type": "string",
|
|
1804
|
+
"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
|
|
1805
|
+
}
|
|
1806
|
+
}
|
|
1807
|
+
},
|
|
1808
|
+
"adjustments": {
|
|
1809
|
+
"type": "array",
|
|
1810
|
+
"items": {
|
|
1811
|
+
"type": "object",
|
|
1812
|
+
"required": [
|
|
1813
|
+
"when",
|
|
1814
|
+
"priceModifier"
|
|
1815
|
+
],
|
|
1816
|
+
"properties": {
|
|
1817
|
+
"when": {
|
|
1818
|
+
"$ref": "#/$defs/configurationSelection",
|
|
1819
|
+
"type": "object",
|
|
1820
|
+
"minProperties": 1
|
|
1821
|
+
},
|
|
1822
|
+
"priceModifier": {
|
|
1823
|
+
"type": "string",
|
|
1824
|
+
"pattern": "^-?[0-9]+(\\.[0-9]+)?$"
|
|
1825
|
+
}
|
|
1826
|
+
},
|
|
1827
|
+
"additionalProperties": false
|
|
1828
|
+
}
|
|
1829
|
+
},
|
|
1830
|
+
"pricing": {
|
|
1831
|
+
"type": "string",
|
|
1832
|
+
"enum": [
|
|
1833
|
+
"complete",
|
|
1834
|
+
"partial"
|
|
1835
|
+
],
|
|
1836
|
+
"default": "complete"
|
|
1837
|
+
}
|
|
1838
|
+
},
|
|
1839
|
+
"additionalProperties": false
|
|
1840
|
+
},
|
|
1717
1841
|
"madeToOrderTerms": {
|
|
1718
1842
|
"type": "object",
|
|
1719
1843
|
"required": [
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Sheet } from "@pagefront/lint-core";
|
|
2
|
+
/**
|
|
3
|
+
* Shared helpers for the configurator-pricing rules (PDP-E-001's
|
|
4
|
+
* `configurator` arm, PDP-E-007 to PDP-E-012, PDP-W-032 to PDP-W-035).
|
|
5
|
+
* They implement the catalogue's Definitions: *pricing block*, *priced
|
|
6
|
+
* dimension*, *option key*, *computed total* and *computed band*.
|
|
7
|
+
*/
|
|
8
|
+
type Obj = Record<string, unknown>;
|
|
9
|
+
export declare function asObject(value: unknown): Obj | null;
|
|
10
|
+
/** Own-property lookup: option keys are publisher strings (`constructor`, …). */
|
|
11
|
+
export declare function own(obj: Obj | null, key: string): unknown;
|
|
12
|
+
/**
|
|
13
|
+
* A name selector in the engine's path style (RFC 9535 normalized
|
|
14
|
+
* paths). Option keys are publisher strings, so the quote, the
|
|
15
|
+
* backslash and control characters are escaped as the RFC prescribes.
|
|
16
|
+
*/
|
|
17
|
+
export declare function seg(key: string): string;
|
|
18
|
+
export interface Decimal {
|
|
19
|
+
units: bigint;
|
|
20
|
+
/** Number of decimal places `units` is scaled by. */
|
|
21
|
+
scale: number;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A decimal reading of an amount: a plain decimal string, or a JSON
|
|
25
|
+
* number whose shortest serialization is a plain decimal. Anything else
|
|
26
|
+
* is not comparable and yields undefined.
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseDecimal(value: unknown): Decimal | undefined;
|
|
29
|
+
export declare function addDecimal(a: Decimal, b: Decimal): Decimal;
|
|
30
|
+
/** Negative, zero or positive as `a` is below, equal to or above `b`. */
|
|
31
|
+
export declare function compareDecimal(a: Decimal, b: Decimal): number;
|
|
32
|
+
export declare function isZero(d: Decimal): boolean;
|
|
33
|
+
/** Renders with the decimal's own number of places (`859.00` at scale 2). */
|
|
34
|
+
export declare function formatDecimal(d: Decimal): string;
|
|
35
|
+
/** The string form an option value is matched by (Definitions: *option key*). */
|
|
36
|
+
export declare function optionKey(value: unknown): string | undefined;
|
|
37
|
+
export interface Dimension {
|
|
38
|
+
name: string;
|
|
39
|
+
/** `affectsPrice` is not `false`. */
|
|
40
|
+
priced: boolean;
|
|
41
|
+
/** Option keys in document order; null when the dimension enumerates none. */
|
|
42
|
+
optionKeys: string[] | null;
|
|
43
|
+
}
|
|
44
|
+
export interface Configurator {
|
|
45
|
+
id: string | undefined;
|
|
46
|
+
dimensions: Dimension[];
|
|
47
|
+
byName: Map<string, Dimension>;
|
|
48
|
+
/** Each exclusion as dimension name → option key. */
|
|
49
|
+
exclusions: Map<string, string>[];
|
|
50
|
+
}
|
|
51
|
+
/** The Sheet's `pagefront:configurator`, or null when absent or shapeless. */
|
|
52
|
+
export declare function readConfigurator(sheet: Sheet): Configurator | null;
|
|
53
|
+
export declare function hasPricedDimension(configurator: Configurator): boolean;
|
|
54
|
+
/** The pricing block of an `offers` entry, or null. */
|
|
55
|
+
export declare function pricingBlock(offer: unknown): Obj | null;
|
|
56
|
+
/** The `configurator.@id` a pricing block names, when it is a string. */
|
|
57
|
+
export declare function pricedConfiguratorId(block: Obj): string | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* The configurator a pricing block prices: the Sheet's configurator when
|
|
60
|
+
* the block's reference equals its `@id` by exact string match. Null is
|
|
61
|
+
* the unresolved reference PDP-E-001 reports; the pricing rules are
|
|
62
|
+
* silent on it.
|
|
63
|
+
*/
|
|
64
|
+
export declare function resolveConfigurator(block: Obj, sheet: Sheet): Configurator | null;
|
|
65
|
+
export declare function offerEntries(sheet: Sheet): unknown[];
|
|
66
|
+
/**
|
|
67
|
+
* True when an `offers` entry states a price, in the sense PDP-W-033 and
|
|
68
|
+
* PDP-W-034 share: an `AggregateOffer`, or an `Offer` with `price` or a
|
|
69
|
+
* non-empty `priceSpecification`. Price-on-request offers state none.
|
|
70
|
+
*/
|
|
71
|
+
export declare function entryStatesPrice(entry: unknown): boolean;
|
|
72
|
+
export declare function isComplete(block: Obj): boolean;
|
|
73
|
+
export type BaseConfigurationProblem = {
|
|
74
|
+
kind: "omitted";
|
|
75
|
+
dimension: string;
|
|
76
|
+
} | {
|
|
77
|
+
kind: "unknown-dimension";
|
|
78
|
+
dimension: string;
|
|
79
|
+
} | {
|
|
80
|
+
kind: "unknown-option";
|
|
81
|
+
dimension: string;
|
|
82
|
+
value: string;
|
|
83
|
+
};
|
|
84
|
+
/** PDP-E-007's findings: omitted dimensions first, then pairs in document order. */
|
|
85
|
+
export declare function baseConfigurationProblems(configurator: Configurator, block: Obj): BaseConfigurationProblem[];
|
|
86
|
+
export type MissingModifierProblem = {
|
|
87
|
+
kind: "no-options";
|
|
88
|
+
dimension: string;
|
|
89
|
+
} | {
|
|
90
|
+
kind: "missing";
|
|
91
|
+
dimension: string;
|
|
92
|
+
option: string;
|
|
93
|
+
};
|
|
94
|
+
/** PDP-W-032's findings, whatever the block's `pricing` value. */
|
|
95
|
+
export declare function missingModifierProblems(configurator: Configurator, block: Obj): MissingModifierProblem[];
|
|
96
|
+
export interface Band {
|
|
97
|
+
min: Decimal;
|
|
98
|
+
max: Decimal;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The minimum and maximum computed total over all non-excluded
|
|
102
|
+
* configurations, or null when it cannot be computed (an amount is not
|
|
103
|
+
* a decimal, a modifier is missing, or every configuration is
|
|
104
|
+
* excluded). The caller has established that the block resolves to
|
|
105
|
+
* `configurator`.
|
|
106
|
+
*
|
|
107
|
+
* Only the dimensions named in an exclusion or an adjustment are
|
|
108
|
+
* enumerated together. Every other priced dimension contributes its
|
|
109
|
+
* smallest modifier to the minimum and its largest to the maximum,
|
|
110
|
+
* independently of the rest, which yields the same band as the full
|
|
111
|
+
* enumeration.
|
|
112
|
+
*/
|
|
113
|
+
export declare function computeBand(configurator: Configurator, block: Obj): Band | null;
|
|
114
|
+
export {};
|