@pagefront/lint-commerce 0.1.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/LICENSE +202 -0
- package/README.md +118 -0
- package/dist/catalogue.d.ts +9 -0
- package/dist/catalogue.js +43 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +144 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +18 -0
- package/dist/lint-sheet.d.ts +13 -0
- package/dist/lint-sheet.js +25 -0
- package/dist/organization-catalogue.d.ts +11 -0
- package/dist/organization-catalogue.js +21 -0
- package/dist/organization-schema.d.ts +9 -0
- package/dist/organization-schema.js +441 -0
- package/dist/product-schema.d.ts +9 -0
- package/dist/product-schema.js +1853 -0
- package/dist/rules/org-shared.d.ts +21 -0
- package/dist/rules/org-shared.js +44 -0
- package/dist/rules/org-w-001.d.ts +12 -0
- package/dist/rules/org-w-001.js +31 -0
- package/dist/rules/org-w-002.d.ts +12 -0
- package/dist/rules/org-w-002.js +32 -0
- package/dist/rules/org-w-003.d.ts +11 -0
- package/dist/rules/org-w-003.js +30 -0
- package/dist/rules/org-w-004.d.ts +12 -0
- package/dist/rules/org-w-004.js +32 -0
- package/dist/rules/org-w-005.d.ts +2 -0
- package/dist/rules/org-w-005.js +54 -0
- package/dist/rules/org-w-006.d.ts +13 -0
- package/dist/rules/org-w-006.js +32 -0
- package/dist/rules/pdp-e-001.d.ts +2 -0
- package/dist/rules/pdp-e-001.js +42 -0
- package/dist/rules/pdp-e-002.d.ts +13 -0
- package/dist/rules/pdp-e-002.js +33 -0
- package/dist/rules/pdp-i-001.d.ts +2 -0
- package/dist/rules/pdp-i-001.js +28 -0
- package/dist/rules/pdp-w-001.d.ts +12 -0
- package/dist/rules/pdp-w-001.js +22 -0
- package/dist/rules/pdp-w-002.d.ts +13 -0
- package/dist/rules/pdp-w-002.js +23 -0
- package/dist/rules/pdp-w-003.d.ts +12 -0
- package/dist/rules/pdp-w-003.js +22 -0
- package/dist/rules/pdp-w-004.d.ts +11 -0
- package/dist/rules/pdp-w-004.js +30 -0
- package/dist/rules/pdp-w-005.d.ts +18 -0
- package/dist/rules/pdp-w-005.js +44 -0
- package/dist/rules/pdp-w-006.d.ts +10 -0
- package/dist/rules/pdp-w-006.js +31 -0
- package/dist/rules/pdp-w-007.d.ts +9 -0
- package/dist/rules/pdp-w-007.js +29 -0
- package/dist/rules/pdp-w-008.d.ts +19 -0
- package/dist/rules/pdp-w-008.js +43 -0
- package/dist/rules/pdp-w-009.d.ts +9 -0
- package/dist/rules/pdp-w-009.js +29 -0
- package/dist/rules/pdp-w-010.d.ts +24 -0
- package/dist/rules/pdp-w-010.js +85 -0
- package/dist/rules/pdp-w-011.d.ts +2 -0
- package/dist/rules/pdp-w-011.js +44 -0
- package/dist/rules/pdp-w-012.d.ts +18 -0
- package/dist/rules/pdp-w-012.js +51 -0
- package/dist/rules/pdp-w-013.d.ts +13 -0
- package/dist/rules/pdp-w-013.js +25 -0
- package/dist/rules/pdp-w-014.d.ts +26 -0
- package/dist/rules/pdp-w-014.js +69 -0
- package/dist/rules/pdp-w-015.d.ts +10 -0
- package/dist/rules/pdp-w-015.js +33 -0
- package/dist/rules/pdp-w-016.d.ts +9 -0
- package/dist/rules/pdp-w-016.js +30 -0
- package/dist/rules/pdp-w-017.d.ts +2 -0
- package/dist/rules/pdp-w-017.js +55 -0
- package/dist/rules/pdp-w-018.d.ts +2 -0
- package/dist/rules/pdp-w-018.js +32 -0
- package/dist/rules/pdp-w-019.d.ts +14 -0
- package/dist/rules/pdp-w-019.js +49 -0
- package/dist/rules/pdp-w-020.d.ts +2 -0
- package/dist/rules/pdp-w-020.js +64 -0
- package/dist/rules/pdp-w-021.d.ts +2 -0
- package/dist/rules/pdp-w-021.js +53 -0
- package/dist/rules/pdp-w-022.d.ts +11 -0
- package/dist/rules/pdp-w-022.js +25 -0
- package/dist/rules/pdp-w-023.d.ts +2 -0
- package/dist/rules/pdp-w-023.js +39 -0
- package/dist/rules/pdp-w-024.d.ts +24 -0
- package/dist/rules/pdp-w-024.js +58 -0
- package/dist/rules/pdp-w-025.d.ts +2 -0
- package/dist/rules/pdp-w-025.js +35 -0
- package/dist/rules/pdp-w-026.d.ts +10 -0
- package/dist/rules/pdp-w-026.js +31 -0
- package/dist/rules/pdp-w-027.d.ts +14 -0
- package/dist/rules/pdp-w-027.js +47 -0
- package/dist/schema-properties.d.ts +10 -0
- package/dist/schema-properties.js +67 -0
- package/dist/sheet-type.d.ts +16 -0
- package/dist/sheet-type.js +20 -0
- package/dist/validate-and-lint.d.ts +47 -0
- package/dist/validate-and-lint.js +53 -0
- package/dist/validate-organization.d.ts +27 -0
- package/dist/validate-organization.js +30 -0
- package/dist/version.d.ts +8 -0
- package/dist/version.js +8 -0
- package/package.json +50 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PDP-W-027 — Empty accepted answer.
|
|
3
|
+
* Transcribed from commerce/spec/rules.md (normative).
|
|
4
|
+
*
|
|
5
|
+
* The target selects `acceptedAnswer` objects, so presence is given by
|
|
6
|
+
* the match; the check tests `text` (absent, empty, or whitespace-only
|
|
7
|
+
* — the schema requires non-empty `text`, so only the whitespace arm
|
|
8
|
+
* is reachable on Layer-1-valid input; the others are defensive).
|
|
9
|
+
* `{name}` is the parent question's `name` (schema-required), read
|
|
10
|
+
* from the sheet via the match's path index; `(unnamed)` defensively
|
|
11
|
+
* on invalid input.
|
|
12
|
+
*/
|
|
13
|
+
export const pdpW027 = {
|
|
14
|
+
id: "PDP-W-027",
|
|
15
|
+
title: "Empty accepted answer",
|
|
16
|
+
severity: "warning",
|
|
17
|
+
target: "$.data.question[*].acceptedAnswer",
|
|
18
|
+
check: (match, ctx) => {
|
|
19
|
+
const answer = match.value;
|
|
20
|
+
if (typeof answer !== "object" || answer === null)
|
|
21
|
+
return null;
|
|
22
|
+
const text = answer["text"];
|
|
23
|
+
const empty = text === undefined ||
|
|
24
|
+
text === null ||
|
|
25
|
+
(typeof text === "string" && text.trim() === "");
|
|
26
|
+
if (!empty)
|
|
27
|
+
return null;
|
|
28
|
+
let name = "(unnamed)";
|
|
29
|
+
const index = /\['question'\]\[(\d+)\]/.exec(match.path)?.[1];
|
|
30
|
+
const data = typeof ctx.sheet.data === "object" && ctx.sheet.data !== null
|
|
31
|
+
? ctx.sheet.data
|
|
32
|
+
: {};
|
|
33
|
+
if (index !== undefined && Array.isArray(data["question"])) {
|
|
34
|
+
const question = data["question"][Number(index)];
|
|
35
|
+
if (typeof question === "object" &&
|
|
36
|
+
question !== null &&
|
|
37
|
+
typeof question["name"] === "string") {
|
|
38
|
+
name = question["name"];
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return { values: { name } };
|
|
42
|
+
},
|
|
43
|
+
messageTemplate: "Question `{name}` at `{path}` has an `acceptedAnswer` with no text.",
|
|
44
|
+
remediation: "Populate `acceptedAnswer.text` with the answer prose, or remove the `acceptedAnswer` (and consider whether an unanswered question belongs in the sheet at all).",
|
|
45
|
+
introduced: "v0.8",
|
|
46
|
+
specReference: "product.md#product-qa",
|
|
47
|
+
};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data-block property inventory for PDP-I-001, derived from the
|
|
3
|
+
* Pagefront JSON Schema (commerce/spec/product.json, format 0.9) —
|
|
4
|
+
* the normative property inventory per the catalogue's Definitions
|
|
5
|
+
* section. Generated from `$defs.dataBlock.properties`; the
|
|
6
|
+
* inventory drift test (test/inventory.test.mjs) fails when the
|
|
7
|
+
* schema and this list diverge. Regenerate on schema change, in the
|
|
8
|
+
* same catalogue-versioned change.
|
|
9
|
+
*/
|
|
10
|
+
export declare const DATA_BLOCK_PROPERTIES: readonly string[];
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The data-block property inventory for PDP-I-001, derived from the
|
|
3
|
+
* Pagefront JSON Schema (commerce/spec/product.json, format 0.9) —
|
|
4
|
+
* the normative property inventory per the catalogue's Definitions
|
|
5
|
+
* section. Generated from `$defs.dataBlock.properties`; the
|
|
6
|
+
* inventory drift test (test/inventory.test.mjs) fails when the
|
|
7
|
+
* schema and this list diverge. Regenerate on schema change, in the
|
|
8
|
+
* same catalogue-versioned change.
|
|
9
|
+
*/
|
|
10
|
+
export const DATA_BLOCK_PROPERTIES = [
|
|
11
|
+
"@context",
|
|
12
|
+
"@id",
|
|
13
|
+
"@type",
|
|
14
|
+
"additionalProperty",
|
|
15
|
+
"aggregateRating",
|
|
16
|
+
"brand",
|
|
17
|
+
"category",
|
|
18
|
+
"color",
|
|
19
|
+
"countryOfOrigin",
|
|
20
|
+
"depth",
|
|
21
|
+
"description",
|
|
22
|
+
"gtin",
|
|
23
|
+
"gtin13",
|
|
24
|
+
"hasCertification",
|
|
25
|
+
"hasPart",
|
|
26
|
+
"hasVariant",
|
|
27
|
+
"height",
|
|
28
|
+
"image",
|
|
29
|
+
"inLanguage",
|
|
30
|
+
"isPartOf",
|
|
31
|
+
"isRelatedTo",
|
|
32
|
+
"isSimilarTo",
|
|
33
|
+
"isVariantOf",
|
|
34
|
+
"manufacturer",
|
|
35
|
+
"material",
|
|
36
|
+
"mpn",
|
|
37
|
+
"name",
|
|
38
|
+
"offers",
|
|
39
|
+
"pagefront:availableLanguages",
|
|
40
|
+
"pagefront:careInstructions",
|
|
41
|
+
"pagefront:configurator",
|
|
42
|
+
"pagefront:construction",
|
|
43
|
+
"pagefront:document",
|
|
44
|
+
"pagefront:fabricComposition",
|
|
45
|
+
"pagefront:featureGroup",
|
|
46
|
+
"pagefront:gemstone",
|
|
47
|
+
"pagefront:legalEntity",
|
|
48
|
+
"pagefront:madeToOrderTerms",
|
|
49
|
+
"pagefront:manufacturingChain",
|
|
50
|
+
"pagefront:materialComposition",
|
|
51
|
+
"pagefront:productHighlights",
|
|
52
|
+
"pagefront:relatedProduct",
|
|
53
|
+
"pagefront:safetyNotice",
|
|
54
|
+
"pagefront:safetyWarning",
|
|
55
|
+
"pagefront:sizeChart",
|
|
56
|
+
"pagefront:sizeRecommendation",
|
|
57
|
+
"productGroupID",
|
|
58
|
+
"productID",
|
|
59
|
+
"question",
|
|
60
|
+
"review",
|
|
61
|
+
"sku",
|
|
62
|
+
"url",
|
|
63
|
+
"variesBy",
|
|
64
|
+
"video",
|
|
65
|
+
"weight",
|
|
66
|
+
"width",
|
|
67
|
+
];
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Sheet } from "@pagefront/lint-core";
|
|
2
|
+
/**
|
|
3
|
+
* Sheet-type detection for page-type dispatch: organization sheets are
|
|
4
|
+
* a different page type from product sheets, and each page type's
|
|
5
|
+
* rules must never run on the other's sheets.
|
|
6
|
+
*
|
|
7
|
+
* The envelope `$schema` is authoritative when it names a page type
|
|
8
|
+
* (`/schemas/organization/` or `/schemas/product/` in its path). The
|
|
9
|
+
* data-block fallback — `@type` of `Organization` / `OnlineStore` /
|
|
10
|
+
* `OnlineBusiness` with `pagefront:commerceRole` present — applies
|
|
11
|
+
* only when `$schema` is absent or names neither, so a declared schema
|
|
12
|
+
* always wins over shape heuristics. The default is `product`, the
|
|
13
|
+
* page type the catalogue predates dispatch with.
|
|
14
|
+
*/
|
|
15
|
+
export type SheetType = "product" | "organization";
|
|
16
|
+
export declare function detectSheetType(sheet: Sheet): SheetType;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const ORG_DATA_TYPES = new Set(["Organization", "OnlineStore", "OnlineBusiness"]);
|
|
2
|
+
export function detectSheetType(sheet) {
|
|
3
|
+
const schema = sheet.$schema;
|
|
4
|
+
if (typeof schema === "string") {
|
|
5
|
+
if (schema.includes("/schemas/organization/"))
|
|
6
|
+
return "organization";
|
|
7
|
+
if (schema.includes("/schemas/product/"))
|
|
8
|
+
return "product";
|
|
9
|
+
}
|
|
10
|
+
const data = sheet.data;
|
|
11
|
+
if (typeof data === "object" && data !== null && !Array.isArray(data)) {
|
|
12
|
+
const d = data;
|
|
13
|
+
if (typeof d["@type"] === "string" &&
|
|
14
|
+
ORG_DATA_TYPES.has(d["@type"]) &&
|
|
15
|
+
d["pagefront:commerceRole"] !== undefined) {
|
|
16
|
+
return "organization";
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return "product";
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Layer 1 → Layer 2 sequencing as a library function — the same
|
|
3
|
+
* pipeline the CLI runs, importable by CI scripts and production
|
|
4
|
+
* validation layers. Ajv is an implementation detail behind this
|
|
5
|
+
* boundary: callers see `SchemaError`, never Ajv's own error type.
|
|
6
|
+
*/
|
|
7
|
+
import type { LintOptions, Report } from "@pagefront/lint-core";
|
|
8
|
+
/**
|
|
9
|
+
* One Layer 1 (JSON Schema) validation failure, in a shape this
|
|
10
|
+
* package owns. `instancePath` is a JSON Pointer to the offending
|
|
11
|
+
* location (`""` for the document root); `keyword` is the schema
|
|
12
|
+
* keyword that failed (e.g. `"required"`, `"format"`).
|
|
13
|
+
*/
|
|
14
|
+
export interface SchemaError {
|
|
15
|
+
instancePath: string;
|
|
16
|
+
message: string;
|
|
17
|
+
keyword: string;
|
|
18
|
+
}
|
|
19
|
+
export type ValidateAndLintResult = {
|
|
20
|
+
layer: 1;
|
|
21
|
+
schemaErrors: SchemaError[];
|
|
22
|
+
} | {
|
|
23
|
+
layer: 2;
|
|
24
|
+
report: Report;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* Validate a parsed-but-unvalidated document against the bundled
|
|
28
|
+
* product JSON Schema (Layer 1), and — only if it passes — lint it
|
|
29
|
+
* against the commerce rule catalogue (Layer 2). The engine assumes a
|
|
30
|
+
* schema-valid Sheet, so a failing document never reaches the
|
|
31
|
+
* catalogue; Layer 1 success is also what makes the internal cast to
|
|
32
|
+
* `Sheet` sound (the schema requires the envelope fields).
|
|
33
|
+
*
|
|
34
|
+
* The bundled schemas are the current catalogue's format version. A
|
|
35
|
+
* document declaring some other `format_version` failing Layer 1 is
|
|
36
|
+
* the intended behavior, not a gap: this package lints exactly one
|
|
37
|
+
* format version, and there is no separate "unsupported version"
|
|
38
|
+
* outcome.
|
|
39
|
+
*
|
|
40
|
+
* Dispatches by page type (see sheet-type.ts): product sheets validate
|
|
41
|
+
* against the product schema and lint with the product catalogue;
|
|
42
|
+
* Commerce Organization Sheets validate against the organization
|
|
43
|
+
* schema and lint with the organization catalogue. Detection reads the
|
|
44
|
+
* envelope `$schema` first, falling back to data-block shape, so a
|
|
45
|
+
* document of either type routes to its own schema's errors.
|
|
46
|
+
*/
|
|
47
|
+
export declare function validateAndLint(input: unknown, options?: LintOptions): ValidateAndLintResult;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { lintSheet } from "./lint-sheet.js";
|
|
2
|
+
import { PRODUCT_SCHEMA } from "./product-schema.js";
|
|
3
|
+
import { ORGANIZATION_SCHEMA } from "./organization-schema.js";
|
|
4
|
+
import { detectSheetType } from "./sheet-type.js";
|
|
5
|
+
// ajv ships CJS with `module.exports === exports.default`; under
|
|
6
|
+
// NodeNext the default import binding is the CJS namespace, so the
|
|
7
|
+
// class/function is reached via `.default` (identical at runtime).
|
|
8
|
+
import Ajv2020Module from "ajv/dist/2020.js";
|
|
9
|
+
import addFormatsModule from "ajv-formats";
|
|
10
|
+
const Ajv2020 = Ajv2020Module.default;
|
|
11
|
+
const addFormats = addFormatsModule.default;
|
|
12
|
+
// Compiled once at module scope: pipeline consumers call
|
|
13
|
+
// validateAndLint in a loop, and schema compilation is the expensive
|
|
14
|
+
// step. `allowUnionTypes` because the product schema legitimately
|
|
15
|
+
// uses union `type` keywords.
|
|
16
|
+
const ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true });
|
|
17
|
+
addFormats(ajv);
|
|
18
|
+
const validateProduct = ajv.compile(PRODUCT_SCHEMA);
|
|
19
|
+
const validateOrganization = ajv.compile(ORGANIZATION_SCHEMA);
|
|
20
|
+
/**
|
|
21
|
+
* Validate a parsed-but-unvalidated document against the bundled
|
|
22
|
+
* product JSON Schema (Layer 1), and — only if it passes — lint it
|
|
23
|
+
* against the commerce rule catalogue (Layer 2). The engine assumes a
|
|
24
|
+
* schema-valid Sheet, so a failing document never reaches the
|
|
25
|
+
* catalogue; Layer 1 success is also what makes the internal cast to
|
|
26
|
+
* `Sheet` sound (the schema requires the envelope fields).
|
|
27
|
+
*
|
|
28
|
+
* The bundled schemas are the current catalogue's format version. A
|
|
29
|
+
* document declaring some other `format_version` failing Layer 1 is
|
|
30
|
+
* the intended behavior, not a gap: this package lints exactly one
|
|
31
|
+
* format version, and there is no separate "unsupported version"
|
|
32
|
+
* outcome.
|
|
33
|
+
*
|
|
34
|
+
* Dispatches by page type (see sheet-type.ts): product sheets validate
|
|
35
|
+
* against the product schema and lint with the product catalogue;
|
|
36
|
+
* Commerce Organization Sheets validate against the organization
|
|
37
|
+
* schema and lint with the organization catalogue. Detection reads the
|
|
38
|
+
* envelope `$schema` first, falling back to data-block shape, so a
|
|
39
|
+
* document of either type routes to its own schema's errors.
|
|
40
|
+
*/
|
|
41
|
+
export function validateAndLint(input, options) {
|
|
42
|
+
const sheetType = detectSheetType((typeof input === "object" && input !== null ? input : {}));
|
|
43
|
+
const validate = sheetType === "organization" ? validateOrganization : validateProduct;
|
|
44
|
+
if (!validate(input)) {
|
|
45
|
+
const schemaErrors = (validate.errors ?? []).map((error) => ({
|
|
46
|
+
instancePath: error.instancePath,
|
|
47
|
+
message: error.message ?? "invalid",
|
|
48
|
+
keyword: error.keyword,
|
|
49
|
+
}));
|
|
50
|
+
return { layer: 1, schemaErrors };
|
|
51
|
+
}
|
|
52
|
+
return { layer: 2, report: lintSheet(input, options) };
|
|
53
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer 1 validation for the Commerce Organization Sheet — the
|
|
3
|
+
* organization analogue of validateAndLint's first stage. There is
|
|
4
|
+
* deliberately no Layer 2 here: the commerce rule catalogue is
|
|
5
|
+
* product-scoped, and an organization catalogue does not exist yet
|
|
6
|
+
* (dispatching per-page-type schemas and catalogues is tracked as
|
|
7
|
+
* "Rule namespaces" in core/spec/linter.md), so a schema-valid
|
|
8
|
+
* document simply passes.
|
|
9
|
+
*
|
|
10
|
+
* As with the product pipeline, Ajv is an implementation detail:
|
|
11
|
+
* callers see `SchemaError`, never Ajv's own error type.
|
|
12
|
+
*/
|
|
13
|
+
import type { SchemaError } from "./validate-and-lint.js";
|
|
14
|
+
export type ValidateOrganizationResult = {
|
|
15
|
+
valid: true;
|
|
16
|
+
} | {
|
|
17
|
+
valid: false;
|
|
18
|
+
schemaErrors: SchemaError[];
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Validate a parsed-but-unvalidated document against the bundled
|
|
22
|
+
* Commerce Organization Sheet JSON Schema. The bundled schema is the
|
|
23
|
+
* current format version; a document declaring some other
|
|
24
|
+
* `format_version` failing Layer 1 is the intended behavior, exactly
|
|
25
|
+
* as in the product pipeline.
|
|
26
|
+
*/
|
|
27
|
+
export declare function validateOrganizationSheet(input: unknown): ValidateOrganizationResult;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ORGANIZATION_SCHEMA } from "./organization-schema.js";
|
|
2
|
+
// ajv ships CJS with `module.exports === exports.default`; under
|
|
3
|
+
// NodeNext the default import binding is the CJS namespace, so the
|
|
4
|
+
// class/function is reached via `.default` (identical at runtime).
|
|
5
|
+
import Ajv2020Module from "ajv/dist/2020.js";
|
|
6
|
+
import addFormatsModule from "ajv-formats";
|
|
7
|
+
const Ajv2020 = Ajv2020Module.default;
|
|
8
|
+
const addFormats = addFormatsModule.default;
|
|
9
|
+
// Compiled once at module scope, mirroring validate-and-lint.
|
|
10
|
+
const ajv = new Ajv2020({ allErrors: true, allowUnionTypes: true });
|
|
11
|
+
addFormats(ajv);
|
|
12
|
+
const validate = ajv.compile(ORGANIZATION_SCHEMA);
|
|
13
|
+
/**
|
|
14
|
+
* Validate a parsed-but-unvalidated document against the bundled
|
|
15
|
+
* Commerce Organization Sheet JSON Schema. The bundled schema is the
|
|
16
|
+
* current format version; a document declaring some other
|
|
17
|
+
* `format_version` failing Layer 1 is the intended behavior, exactly
|
|
18
|
+
* as in the product pipeline.
|
|
19
|
+
*/
|
|
20
|
+
export function validateOrganizationSheet(input) {
|
|
21
|
+
if (!validate(input)) {
|
|
22
|
+
const schemaErrors = (validate.errors ?? []).map((error) => ({
|
|
23
|
+
instancePath: error.instancePath,
|
|
24
|
+
message: error.message ?? "invalid",
|
|
25
|
+
keyword: error.keyword,
|
|
26
|
+
}));
|
|
27
|
+
return { valid: false, schemaErrors };
|
|
28
|
+
}
|
|
29
|
+
return { valid: true };
|
|
30
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This package's version, as a generated constant so the library
|
|
3
|
+
* entry stays free of Node built-ins (browser consumers bundle it).
|
|
4
|
+
* Must match package.json's `version` — the drift test
|
|
5
|
+
* (test/linter-version.test.mjs) fails when they diverge. Regenerate
|
|
6
|
+
* on version bump.
|
|
7
|
+
*/
|
|
8
|
+
export declare const PACKAGE_VERSION = "0.1.0";
|
package/dist/version.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This package's version, as a generated constant so the library
|
|
3
|
+
* entry stays free of Node built-ins (browser consumers bundle it).
|
|
4
|
+
* Must match package.json's `version` — the drift test
|
|
5
|
+
* (test/linter-version.test.mjs) fails when they diverge. Regenerate
|
|
6
|
+
* on version bump.
|
|
7
|
+
*/
|
|
8
|
+
export const PACKAGE_VERSION = "0.1.0";
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@pagefront/lint-commerce",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Pagefront commerce linter: the commerce rule catalogue and CLI, on the @pagefront/lint-core engine.",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/themachineweb/pagefront.git",
|
|
9
|
+
"directory": "commerce/lint"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/themachineweb/pagefront/tree/main/commerce/lint#readme",
|
|
12
|
+
"bugs": "https://github.com/themachineweb/pagefront/issues",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"pagefront",
|
|
15
|
+
"linter",
|
|
16
|
+
"commerce",
|
|
17
|
+
"product",
|
|
18
|
+
"schema.org",
|
|
19
|
+
"json-ld",
|
|
20
|
+
"structured-data"
|
|
21
|
+
],
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "dist/index.js",
|
|
24
|
+
"types": "dist/index.d.ts",
|
|
25
|
+
"bin": {
|
|
26
|
+
"pagefront-lint-commerce": "dist/cli.js"
|
|
27
|
+
},
|
|
28
|
+
"files": [
|
|
29
|
+
"dist",
|
|
30
|
+
"README.md",
|
|
31
|
+
"LICENSE"
|
|
32
|
+
],
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"scripts": {
|
|
37
|
+
"build": "tsc",
|
|
38
|
+
"test": "tsc && node --test test/*.test.mjs",
|
|
39
|
+
"prepublishOnly": "npm test"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@pagefront/lint-core": "^0.1.0",
|
|
43
|
+
"ajv": "^8.20.0",
|
|
44
|
+
"ajv-formats": "^3.0.1"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^26.2.0",
|
|
48
|
+
"typescript": "^5.0.0"
|
|
49
|
+
}
|
|
50
|
+
}
|