@pagefront/lint-commerce 0.9.0 → 0.11.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 +57 -13
- package/dist/catalogue.js +5 -3
- package/dist/generated/release-manifest.d.ts +22 -0
- package/dist/generated/release-manifest.js +27 -0
- package/dist/generated/schema-ids.d.ts +1 -0
- package/dist/generated/schema-ids.js +7 -0
- package/dist/generated/schema-properties.d.ts +1 -0
- package/dist/{schema-properties.js → generated/schema-properties.js} +2 -10
- package/dist/generated/schemas.d.ts +1 -0
- package/dist/generated/schemas.js +4883 -0
- package/dist/index.d.ts +10 -4
- package/dist/index.js +9 -3
- package/dist/organization-catalogue.js +6 -3
- package/dist/releases.d.ts +22 -0
- package/dist/releases.js +27 -0
- package/dist/rules/org-e-002.d.ts +7 -0
- package/dist/rules/org-e-002.js +13 -0
- package/dist/rules/org-e-003.d.ts +7 -0
- package/dist/rules/org-e-003.js +13 -0
- package/dist/rules/pdp-e-002.d.ts +3 -9
- package/dist/rules/pdp-e-002.js +6 -26
- package/dist/rules/pdp-e-016.d.ts +7 -0
- package/dist/rules/pdp-e-016.js +13 -0
- package/dist/rules/pdp-i-001.js +3 -2
- package/dist/rules/release-schema.d.ts +16 -0
- package/dist/rules/release-schema.js +77 -0
- package/dist/schema-registry.d.ts +29 -0
- package/dist/schema-registry.js +35 -0
- package/dist/schema-validators.d.ts +7 -6
- package/dist/schema-validators.js +15 -3
- package/dist/sheet-type.d.ts +17 -0
- package/dist/sheet-type.js +25 -0
- package/dist/validate-and-lint.d.ts +24 -17
- package/dist/validate-and-lint.js +47 -28
- package/dist/validate-organization.d.ts +5 -5
- package/dist/validate-organization.js +8 -15
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +3 -3
- package/dist/organization-schema.d.ts +0 -9
- package/dist/organization-schema.js +0 -441
- package/dist/product-schema.d.ts +0 -9
- package/dist/product-schema.js +0 -2014
- package/dist/schema-properties.d.ts +0 -10
package/dist/index.d.ts
CHANGED
|
@@ -7,8 +7,12 @@
|
|
|
7
7
|
* `validateOrganizationSheet` (Layer 1 for the Commerce Organization
|
|
8
8
|
* Sheet; no organization catalogue exists yet), the commerce
|
|
9
9
|
* catalogue object, and the types those signatures mention.
|
|
10
|
-
*
|
|
11
|
-
* rule modules are internal.
|
|
10
|
+
* The bundled schemas (`generated/`), the compiled validators and the
|
|
11
|
+
* individual rule modules are internal. The release manifest
|
|
12
|
+
* (`RELEASE_MANIFEST`, `sheetSpecVersionFor`, `schemaUrlFor`) and the
|
|
13
|
+
* list of bundled schema ids (`BUNDLED_SCHEMA_IDS`) are exported so
|
|
14
|
+
* callers can resolve a release to its sheet-spec versions and tell
|
|
15
|
+
* which `$schema` values this package validates.
|
|
12
16
|
*/
|
|
13
17
|
export { lintSheet } from "./lint-sheet.js";
|
|
14
18
|
export { validateAndLint } from "./validate-and-lint.js";
|
|
@@ -17,6 +21,8 @@ export { validateOrganizationSheet } from "./validate-organization.js";
|
|
|
17
21
|
export type { ValidateOrganizationResult } from "./validate-organization.js";
|
|
18
22
|
export { commerceCatalogue } from "./catalogue.js";
|
|
19
23
|
export { organizationCatalogue } from "./organization-catalogue.js";
|
|
20
|
-
export { detectSheetType } from "./sheet-type.js";
|
|
21
|
-
export type { SheetType } from "./sheet-type.js";
|
|
24
|
+
export { detectSheetType, detectSheetLine } from "./sheet-type.js";
|
|
25
|
+
export type { SheetType, SheetLine } from "./sheet-type.js";
|
|
26
|
+
export { RELEASE_MANIFEST, KNOWN_RELEASES, CURRENT_RELEASE, sheetSpecVersionFor, schemaUrlFor, } from "./releases.js";
|
|
27
|
+
export { SCHEMA_IDS as BUNDLED_SCHEMA_IDS } from "./generated/schema-ids.js";
|
|
22
28
|
export type { Report, Finding, Summary, Severity, LintOptions, Sheet, } from "@pagefront/lint-core";
|
package/dist/index.js
CHANGED
|
@@ -7,12 +7,18 @@
|
|
|
7
7
|
* `validateOrganizationSheet` (Layer 1 for the Commerce Organization
|
|
8
8
|
* Sheet; no organization catalogue exists yet), the commerce
|
|
9
9
|
* catalogue object, and the types those signatures mention.
|
|
10
|
-
*
|
|
11
|
-
* rule modules are internal.
|
|
10
|
+
* The bundled schemas (`generated/`), the compiled validators and the
|
|
11
|
+
* individual rule modules are internal. The release manifest
|
|
12
|
+
* (`RELEASE_MANIFEST`, `sheetSpecVersionFor`, `schemaUrlFor`) and the
|
|
13
|
+
* list of bundled schema ids (`BUNDLED_SCHEMA_IDS`) are exported so
|
|
14
|
+
* callers can resolve a release to its sheet-spec versions and tell
|
|
15
|
+
* which `$schema` values this package validates.
|
|
12
16
|
*/
|
|
13
17
|
export { lintSheet } from "./lint-sheet.js";
|
|
14
18
|
export { validateAndLint } from "./validate-and-lint.js";
|
|
15
19
|
export { validateOrganizationSheet } from "./validate-organization.js";
|
|
16
20
|
export { commerceCatalogue } from "./catalogue.js";
|
|
17
21
|
export { organizationCatalogue } from "./organization-catalogue.js";
|
|
18
|
-
export { detectSheetType } from "./sheet-type.js";
|
|
22
|
+
export { detectSheetType, detectSheetLine } from "./sheet-type.js";
|
|
23
|
+
export { RELEASE_MANIFEST, KNOWN_RELEASES, CURRENT_RELEASE, sheetSpecVersionFor, schemaUrlFor, } from "./releases.js";
|
|
24
|
+
export { SCHEMA_IDS as BUNDLED_SCHEMA_IDS } from "./generated/schema-ids.js";
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { KNOWN_RELEASES } from "./releases.js";
|
|
1
2
|
import { orgE001 } from "./rules/org-e-001.js";
|
|
3
|
+
import { orgE002 } from "./rules/org-e-002.js";
|
|
4
|
+
import { orgE003 } from "./rules/org-e-003.js";
|
|
2
5
|
import { orgW001 } from "./rules/org-w-001.js";
|
|
3
6
|
import { orgW002 } from "./rules/org-w-002.js";
|
|
4
7
|
import { orgW003 } from "./rules/org-w-003.js";
|
|
@@ -16,7 +19,7 @@ import { orgW006 } from "./rules/org-w-006.js";
|
|
|
16
19
|
*/
|
|
17
20
|
export const organizationCatalogue = {
|
|
18
21
|
vertical: "commerce",
|
|
19
|
-
|
|
20
|
-
catalogueVersion: "0.
|
|
21
|
-
rules: [orgE001, orgW001, orgW002, orgW003, orgW004, orgW005, orgW006],
|
|
22
|
+
releases: KNOWN_RELEASES,
|
|
23
|
+
catalogueVersion: "0.15.0",
|
|
24
|
+
rules: [orgE001, orgE002, orgE003, orgW001, orgW002, orgW003, orgW004, orgW005, orgW006],
|
|
22
25
|
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { RELEASE_MANIFEST } from "./generated/release-manifest.js";
|
|
2
|
+
import type { SheetType } from "./sheet-type.js";
|
|
3
|
+
/**
|
|
4
|
+
* The commerce release manifest (commerce/spec/releases.json): each
|
|
5
|
+
* release and the member versions it bundles. Bundled at build time by
|
|
6
|
+
* scripts/bundle-schemas.mjs, so the package always carries the
|
|
7
|
+
* manifest it was built from.
|
|
8
|
+
*/
|
|
9
|
+
export { RELEASE_MANIFEST };
|
|
10
|
+
/** Every release the manifest lists, in manifest order. */
|
|
11
|
+
export declare const KNOWN_RELEASES: readonly string[];
|
|
12
|
+
/** The latest release the manifest lists. */
|
|
13
|
+
export declare const CURRENT_RELEASE: string;
|
|
14
|
+
/**
|
|
15
|
+
* The sheet-spec version a release bundles for a sheet type, or
|
|
16
|
+
* undefined when the manifest does not list the release.
|
|
17
|
+
*/
|
|
18
|
+
export declare function sheetSpecVersionFor(release: string, sheetType: SheetType): string | undefined;
|
|
19
|
+
/** The published URL of a sheet spec's JSON Schema, which is also its `$id`. */
|
|
20
|
+
export declare function schemaUrlFor(sheetType: SheetType, version: string): string;
|
|
21
|
+
/** The legacy draft line's schema URL for a sheet type. */
|
|
22
|
+
export declare function legacySchemaUrl(sheetType: SheetType): string;
|
package/dist/releases.js
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { RELEASE_MANIFEST } from "./generated/release-manifest.js";
|
|
2
|
+
/**
|
|
3
|
+
* The commerce release manifest (commerce/spec/releases.json): each
|
|
4
|
+
* release and the member versions it bundles. Bundled at build time by
|
|
5
|
+
* scripts/bundle-schemas.mjs, so the package always carries the
|
|
6
|
+
* manifest it was built from.
|
|
7
|
+
*/
|
|
8
|
+
export { RELEASE_MANIFEST };
|
|
9
|
+
/** Every release the manifest lists, in manifest order. */
|
|
10
|
+
export const KNOWN_RELEASES = RELEASE_MANIFEST.releases.map((r) => r.release);
|
|
11
|
+
/** The latest release the manifest lists. */
|
|
12
|
+
export const CURRENT_RELEASE = KNOWN_RELEASES[KNOWN_RELEASES.length - 1];
|
|
13
|
+
/**
|
|
14
|
+
* The sheet-spec version a release bundles for a sheet type, or
|
|
15
|
+
* undefined when the manifest does not list the release.
|
|
16
|
+
*/
|
|
17
|
+
export function sheetSpecVersionFor(release, sheetType) {
|
|
18
|
+
return RELEASE_MANIFEST.releases.find((r) => r.release === release)?.sheets[sheetType];
|
|
19
|
+
}
|
|
20
|
+
/** The published URL of a sheet spec's JSON Schema, which is also its `$id`. */
|
|
21
|
+
export function schemaUrlFor(sheetType, version) {
|
|
22
|
+
return RELEASE_MANIFEST.schema_url_template.replace("{sheet}", sheetType).replace("{version}", version);
|
|
23
|
+
}
|
|
24
|
+
/** The legacy draft line's schema URL for a sheet type. */
|
|
25
|
+
export function legacySchemaUrl(sheetType) {
|
|
26
|
+
return RELEASE_MANIFEST.legacy.schemas[sheetType];
|
|
27
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Rule } from "@pagefront/lint-core";
|
|
2
|
+
/**
|
|
3
|
+
* ORG-E-002 — Sheet carries both format_version and release.
|
|
4
|
+
* The organization-sheet counterpart of PDP-E-016. Transcribed from
|
|
5
|
+
* commerce/spec/rules.md (normative).
|
|
6
|
+
*/
|
|
7
|
+
export declare const orgE002: Rule;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BOTH_VERSION_FIELDS, bothVersionFields } from "./release-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* ORG-E-002 — Sheet carries both format_version and release.
|
|
4
|
+
* The organization-sheet counterpart of PDP-E-016. Transcribed from
|
|
5
|
+
* commerce/spec/rules.md (normative).
|
|
6
|
+
*/
|
|
7
|
+
export const orgE002 = {
|
|
8
|
+
id: "ORG-E-002",
|
|
9
|
+
...BOTH_VERSION_FIELDS,
|
|
10
|
+
check: bothVersionFields,
|
|
11
|
+
introduced: "release 0.3.0",
|
|
12
|
+
specReference: "organization.md#the-envelope",
|
|
13
|
+
};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { RELEASE_SCHEMA_MISMATCH, releaseSchemaMismatch } from "./release-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* ORG-E-003 — Release / schema mismatch.
|
|
4
|
+
* The organization-sheet counterpart of PDP-E-002. Transcribed from
|
|
5
|
+
* commerce/spec/rules.md (normative).
|
|
6
|
+
*/
|
|
7
|
+
export const orgE003 = {
|
|
8
|
+
id: "ORG-E-003",
|
|
9
|
+
...RELEASE_SCHEMA_MISMATCH,
|
|
10
|
+
check: releaseSchemaMismatch("organization"),
|
|
11
|
+
introduced: "release 0.3.0",
|
|
12
|
+
specReference: "organization.md#the-envelope",
|
|
13
|
+
};
|
|
@@ -1,13 +1,7 @@
|
|
|
1
1
|
import type { Rule } from "@pagefront/lint-core";
|
|
2
2
|
/**
|
|
3
|
-
* PDP-E-002 —
|
|
4
|
-
* Transcribed from commerce/spec/rules.md
|
|
5
|
-
*
|
|
6
|
-
* `$schema` is read via the rule context, per the target line. The
|
|
7
|
-
* version segment is the trailing `v<version>.json` of the `$schema`
|
|
8
|
-
* URL. Two quiet cases, both documented readings: `$schema` absent
|
|
9
|
-
* (optional at Layer 1 — nothing to compare), and a `$schema` with no
|
|
10
|
-
* parseable version segment (it declares no version, so no mismatch
|
|
11
|
-
* can be asserted; the message requires `{schema_version}`).
|
|
3
|
+
* PDP-E-002 — Release / schema mismatch (until release 0.3.0: "Format
|
|
4
|
+
* version / schema mismatch"). Transcribed from commerce/spec/rules.md
|
|
5
|
+
* (normative); the check is shared with ORG-E-003 (release-schema.ts).
|
|
12
6
|
*/
|
|
13
7
|
export declare const pdpE002: Rule;
|
package/dist/rules/pdp-e-002.js
CHANGED
|
@@ -1,33 +1,13 @@
|
|
|
1
|
+
import { RELEASE_SCHEMA_MISMATCH, releaseSchemaMismatch } from "./release-schema.js";
|
|
1
2
|
/**
|
|
2
|
-
* PDP-E-002 —
|
|
3
|
-
* Transcribed from commerce/spec/rules.md
|
|
4
|
-
*
|
|
5
|
-
* `$schema` is read via the rule context, per the target line. The
|
|
6
|
-
* version segment is the trailing `v<version>.json` of the `$schema`
|
|
7
|
-
* URL. Two quiet cases, both documented readings: `$schema` absent
|
|
8
|
-
* (optional at Layer 1 — nothing to compare), and a `$schema` with no
|
|
9
|
-
* parseable version segment (it declares no version, so no mismatch
|
|
10
|
-
* can be asserted; the message requires `{schema_version}`).
|
|
3
|
+
* PDP-E-002 — Release / schema mismatch (until release 0.3.0: "Format
|
|
4
|
+
* version / schema mismatch"). Transcribed from commerce/spec/rules.md
|
|
5
|
+
* (normative); the check is shared with ORG-E-003 (release-schema.ts).
|
|
11
6
|
*/
|
|
12
7
|
export const pdpE002 = {
|
|
13
8
|
id: "PDP-E-002",
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
target: "$.format_version",
|
|
17
|
-
check: (match, ctx) => {
|
|
18
|
-
const formatVersion = String(match.value);
|
|
19
|
-
const schema = ctx.sheet.$schema;
|
|
20
|
-
if (typeof schema !== "string")
|
|
21
|
-
return null;
|
|
22
|
-
const segment = /v(\d+(?:\.\d+)*)\.json$/.exec(schema);
|
|
23
|
-
if (segment === null)
|
|
24
|
-
return null;
|
|
25
|
-
return segment[1] === formatVersion
|
|
26
|
-
? null
|
|
27
|
-
: { values: { format_version: formatVersion, schema_version: segment[1] } };
|
|
28
|
-
},
|
|
29
|
-
messageTemplate: "`format_version` is `{format_version}` but `$schema` URL declares version `{schema_version}`.",
|
|
30
|
-
remediation: "Align both fields to the same version. Whichever version was intended, update the other field to match.",
|
|
9
|
+
...RELEASE_SCHEMA_MISMATCH,
|
|
10
|
+
check: releaseSchemaMismatch("product"),
|
|
31
11
|
introduced: "v0.6",
|
|
32
12
|
specReference: "product.md#the-envelope",
|
|
33
13
|
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { Rule } from "@pagefront/lint-core";
|
|
2
|
+
/**
|
|
3
|
+
* PDP-E-016 — Sheet carries both format_version and release.
|
|
4
|
+
* Transcribed from commerce/spec/rules.md (normative); the check is
|
|
5
|
+
* shared with ORG-E-002 (release-schema.ts).
|
|
6
|
+
*/
|
|
7
|
+
export declare const pdpE016: Rule;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BOTH_VERSION_FIELDS, bothVersionFields } from "./release-schema.js";
|
|
2
|
+
/**
|
|
3
|
+
* PDP-E-016 — Sheet carries both format_version and release.
|
|
4
|
+
* Transcribed from commerce/spec/rules.md (normative); the check is
|
|
5
|
+
* shared with ORG-E-002 (release-schema.ts).
|
|
6
|
+
*/
|
|
7
|
+
export const pdpE016 = {
|
|
8
|
+
id: "PDP-E-016",
|
|
9
|
+
...BOTH_VERSION_FIELDS,
|
|
10
|
+
check: bothVersionFields,
|
|
11
|
+
introduced: "release 0.3.0",
|
|
12
|
+
specReference: "product.md#the-envelope",
|
|
13
|
+
};
|
package/dist/rules/pdp-i-001.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { DATA_BLOCK_PROPERTIES } from "../schema-properties.js";
|
|
1
|
+
import { DATA_BLOCK_PROPERTIES } from "../generated/schema-properties.js";
|
|
2
2
|
/**
|
|
3
3
|
* PDP-I-001 — Property outside Pagefront's modeled set.
|
|
4
4
|
* Transcribed from commerce/spec/rules.md (normative).
|
|
5
5
|
*
|
|
6
6
|
* The modeled set is the JSON Schema's dataBlock property inventory
|
|
7
|
-
*
|
|
7
|
+
* of the latest released Product Sheet schema (generated at build
|
|
8
|
+
* time, see scripts/bundle-schemas.mjs). The
|
|
8
9
|
* target `$.data.*` selects top-level data properties by design; any
|
|
9
10
|
* property outside the inventory fires, including unmodeled
|
|
10
11
|
* `pagefront:`-prefixed ones.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { CheckFn, Rule } from "@pagefront/lint-core";
|
|
2
|
+
import type { SheetType } from "../sheet-type.js";
|
|
3
|
+
/**
|
|
4
|
+
* Release / schema mismatch. On the release line the `$schema` version
|
|
5
|
+
* segment must be the sheet-spec version the release manifest maps the
|
|
6
|
+
* declared `release` and the sheet type to; a release the manifest does
|
|
7
|
+
* not list has no mapping and the rule is silent. On the legacy line
|
|
8
|
+
* the segment must equal `format_version`, as before. Quiet when
|
|
9
|
+
* `$schema` is absent or names no version, and when the sheet carries
|
|
10
|
+
* both fields (the both-fields rule reports that).
|
|
11
|
+
*/
|
|
12
|
+
export declare function releaseSchemaMismatch(sheetType: SheetType): CheckFn;
|
|
13
|
+
export declare const RELEASE_SCHEMA_MISMATCH: Pick<Rule, "title" | "severity" | "target" | "messageTemplate" | "remediation">;
|
|
14
|
+
/** A sheet carrying both `format_version` and `release`. */
|
|
15
|
+
export declare const bothVersionFields: CheckFn;
|
|
16
|
+
export declare const BOTH_VERSION_FIELDS: Pick<Rule, "title" | "severity" | "target" | "messageTemplate" | "remediation">;
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { sheetSpecVersionFor } from "../releases.js";
|
|
2
|
+
/**
|
|
3
|
+
* Shared checks for the envelope's version fields, used by the product
|
|
4
|
+
* and organization catalogues (PDP-E-002 / ORG-E-003, PDP-E-016 /
|
|
5
|
+
* ORG-E-002). Transcribed from commerce/spec/rules.md (normative).
|
|
6
|
+
*/
|
|
7
|
+
/** The trailing `v<version>.json` of a `$schema` URL. */
|
|
8
|
+
const SCHEMA_VERSION = /v(\d+(?:\.\d+)*)\.json$/;
|
|
9
|
+
const SHEET_LABEL = {
|
|
10
|
+
product: "Product Sheet",
|
|
11
|
+
organization: "Organization Sheet",
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Release / schema mismatch. On the release line the `$schema` version
|
|
15
|
+
* segment must be the sheet-spec version the release manifest maps the
|
|
16
|
+
* declared `release` and the sheet type to; a release the manifest does
|
|
17
|
+
* not list has no mapping and the rule is silent. On the legacy line
|
|
18
|
+
* the segment must equal `format_version`, as before. Quiet when
|
|
19
|
+
* `$schema` is absent or names no version, and when the sheet carries
|
|
20
|
+
* both fields (the both-fields rule reports that).
|
|
21
|
+
*/
|
|
22
|
+
export function releaseSchemaMismatch(sheetType) {
|
|
23
|
+
return (_match, ctx) => {
|
|
24
|
+
const { release, format_version: formatVersion, $schema: schema } = ctx.sheet;
|
|
25
|
+
if (typeof schema !== "string")
|
|
26
|
+
return null;
|
|
27
|
+
const schemaVersion = SCHEMA_VERSION.exec(schema)?.[1];
|
|
28
|
+
if (schemaVersion === undefined)
|
|
29
|
+
return null;
|
|
30
|
+
if (release !== undefined && formatVersion !== undefined)
|
|
31
|
+
return null;
|
|
32
|
+
if (typeof release === "string") {
|
|
33
|
+
const expected = sheetSpecVersionFor(release, sheetType);
|
|
34
|
+
if (expected === undefined || expected === schemaVersion)
|
|
35
|
+
return null;
|
|
36
|
+
return {
|
|
37
|
+
path: "$['release']",
|
|
38
|
+
values: {
|
|
39
|
+
declared: `\`release\` \`${release}\` bundles ${SHEET_LABEL[sheetType]} spec \`${expected}\``,
|
|
40
|
+
release,
|
|
41
|
+
expected,
|
|
42
|
+
schema_version: schemaVersion,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
if (formatVersion !== undefined) {
|
|
47
|
+
const declared = String(formatVersion);
|
|
48
|
+
if (declared === schemaVersion)
|
|
49
|
+
return null;
|
|
50
|
+
return {
|
|
51
|
+
path: "$['format_version']",
|
|
52
|
+
values: {
|
|
53
|
+
declared: `\`format_version\` is \`${declared}\``,
|
|
54
|
+
format_version: declared,
|
|
55
|
+
schema_version: schemaVersion,
|
|
56
|
+
},
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return null;
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
export const RELEASE_SCHEMA_MISMATCH = {
|
|
63
|
+
title: "Release / schema mismatch",
|
|
64
|
+
severity: "error",
|
|
65
|
+
target: "$",
|
|
66
|
+
messageTemplate: "{declared} but `$schema` URL declares version `{schema_version}`.",
|
|
67
|
+
remediation: "Point `$schema` at the sheet-spec version the declared release bundles (see releases.md), or declare the release that bundles the schema the sheet was written against. On a legacy sheet, align `format_version` and the `$schema` version.",
|
|
68
|
+
};
|
|
69
|
+
/** A sheet carrying both `format_version` and `release`. */
|
|
70
|
+
export const bothVersionFields = (_match, ctx) => ctx.sheet.release !== undefined && ctx.sheet.format_version !== undefined ? {} : null;
|
|
71
|
+
export const BOTH_VERSION_FIELDS = {
|
|
72
|
+
title: "Sheet carries both format_version and release",
|
|
73
|
+
severity: "error",
|
|
74
|
+
target: "$",
|
|
75
|
+
messageTemplate: "Sheet carries both `format_version` and `release`; a sheet declares one.",
|
|
76
|
+
remediation: "Keep `release` and remove `format_version`. A sheet on the legacy draft line keeps `format_version` alone and its legacy `$schema`.",
|
|
77
|
+
};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { Sheet } from "@pagefront/lint-core";
|
|
2
|
+
import type { SheetType } from "./sheet-type.js";
|
|
3
|
+
/**
|
|
4
|
+
* Which frozen schema a sheet is validated against. The package bundles
|
|
5
|
+
* every schema ever published (commerce/schemas/), keyed by `$id`, and a
|
|
6
|
+
* sheet is validated against the one its `$schema` names, on either
|
|
7
|
+
* line. Nothing is substituted: a `$schema` that names no bundled schema
|
|
8
|
+
* is reported as such, and the sheet is not validated against a
|
|
9
|
+
* neighbouring version.
|
|
10
|
+
*/
|
|
11
|
+
export type SchemaResolution = {
|
|
12
|
+
kind: "schema";
|
|
13
|
+
id: string;
|
|
14
|
+
}
|
|
15
|
+
/** `$schema` is a string that names no schema this package bundles. */
|
|
16
|
+
| {
|
|
17
|
+
kind: "unknown";
|
|
18
|
+
declared: string;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* Resolve the schema for a document. A declared `$schema` is taken at
|
|
22
|
+
* its word. Without one, the schema is the one the sheet's own
|
|
23
|
+
* statements lead to: the legacy schema for a sheet on the legacy line,
|
|
24
|
+
* and for a sheet on the release line the sheet-spec version its
|
|
25
|
+
* `release` bundles (the current release's when the release is not in
|
|
26
|
+
* the manifest). `sheetType` forces the type for callers that validate
|
|
27
|
+
* one type only.
|
|
28
|
+
*/
|
|
29
|
+
export declare function resolveSchema(sheet: Sheet, sheetType?: SheetType): SchemaResolution;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { SCHEMA_IDS } from "./generated/schema-ids.js";
|
|
2
|
+
import { CURRENT_RELEASE, legacySchemaUrl, schemaUrlFor, sheetSpecVersionFor, } from "./releases.js";
|
|
3
|
+
import { detectSheetLine, detectSheetType } from "./sheet-type.js";
|
|
4
|
+
/**
|
|
5
|
+
* The identifiers the legacy schemas carried before 2026-09-08
|
|
6
|
+
* (`…/pagefront/commerce/schemas/<type>/v0.9.json`); sheets declaring
|
|
7
|
+
* them validate against the legacy schema they became.
|
|
8
|
+
*/
|
|
9
|
+
const FORMER_LEGACY_ID = /^https:\/\/themachineweb\.org\/pagefront\/commerce\/schemas\/(product|organization)\/v0\.9\.json$/;
|
|
10
|
+
/**
|
|
11
|
+
* Resolve the schema for a document. A declared `$schema` is taken at
|
|
12
|
+
* its word. Without one, the schema is the one the sheet's own
|
|
13
|
+
* statements lead to: the legacy schema for a sheet on the legacy line,
|
|
14
|
+
* and for a sheet on the release line the sheet-spec version its
|
|
15
|
+
* `release` bundles (the current release's when the release is not in
|
|
16
|
+
* the manifest). `sheetType` forces the type for callers that validate
|
|
17
|
+
* one type only.
|
|
18
|
+
*/
|
|
19
|
+
export function resolveSchema(sheet, sheetType) {
|
|
20
|
+
const declared = sheet.$schema;
|
|
21
|
+
if (typeof declared === "string") {
|
|
22
|
+
if (SCHEMA_IDS.includes(declared))
|
|
23
|
+
return { kind: "schema", id: declared };
|
|
24
|
+
const former = FORMER_LEGACY_ID.exec(declared);
|
|
25
|
+
if (former !== null)
|
|
26
|
+
return { kind: "schema", id: legacySchemaUrl(former[1]) };
|
|
27
|
+
return { kind: "unknown", declared };
|
|
28
|
+
}
|
|
29
|
+
const type = sheetType ?? detectSheetType(sheet);
|
|
30
|
+
if (detectSheetLine(sheet) === "legacy")
|
|
31
|
+
return { kind: "schema", id: legacySchemaUrl(type) };
|
|
32
|
+
const release = typeof sheet.release === "string" ? sheet.release : CURRENT_RELEASE;
|
|
33
|
+
const version = sheetSpecVersionFor(release, type) ?? sheetSpecVersionFor(CURRENT_RELEASE, type);
|
|
34
|
+
return { kind: "schema", id: schemaUrlFor(type, version) };
|
|
35
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The Layer 1 validators, compiled ahead of time from
|
|
3
|
-
* schemas by scripts/compile-validators.mjs into
|
|
4
|
-
* (the
|
|
5
|
-
* type; the script copies it beside the
|
|
2
|
+
* The Layer 1 validators, compiled ahead of time from every bundled
|
|
3
|
+
* schema (commerce/schemas/) by scripts/compile-validators.mjs into
|
|
4
|
+
* dist/schema-validators.js (the last step of `npm run build`). This
|
|
5
|
+
* declaration is the module's type; the script copies it beside the
|
|
6
|
+
* generated file.
|
|
6
7
|
*/
|
|
7
8
|
import type { ValidateFunction } from "ajv";
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
export const
|
|
10
|
+
/** One validator per bundled schema, keyed by the schema's `$id`. */
|
|
11
|
+
export const VALIDATORS: Readonly<Record<string, ValidateFunction>>;
|