@pagefront/lint-commerce 0.10.0 → 0.12.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.
Files changed (106) hide show
  1. package/README.md +49 -16
  2. package/dist/catalogue.js +4 -2
  3. package/dist/generated/release-manifest.d.ts +30 -0
  4. package/dist/generated/release-manifest.js +36 -0
  5. package/dist/generated/schema-ids.d.ts +1 -0
  6. package/dist/generated/schema-ids.js +9 -0
  7. package/dist/generated/schema-properties.d.ts +1 -0
  8. package/dist/{schema-properties.js → generated/schema-properties.js} +2 -10
  9. package/dist/generated/schemas.d.ts +1 -0
  10. package/dist/generated/schemas.js +7326 -0
  11. package/dist/index.d.ts +8 -5
  12. package/dist/index.js +8 -5
  13. package/dist/organization-catalogue.js +3 -2
  14. package/dist/releases.d.ts +12 -26
  15. package/dist/releases.js +16 -30
  16. package/dist/rules/org-e-001.js +2 -0
  17. package/dist/rules/org-e-002.js +2 -0
  18. package/dist/rules/org-e-003.js +2 -0
  19. package/dist/rules/org-e-004.d.ts +11 -0
  20. package/dist/rules/org-e-004.js +18 -0
  21. package/dist/rules/org-w-001.js +2 -0
  22. package/dist/rules/org-w-002.js +2 -0
  23. package/dist/rules/org-w-003.js +2 -0
  24. package/dist/rules/org-w-004.js +2 -0
  25. package/dist/rules/org-w-005.js +2 -0
  26. package/dist/rules/org-w-006.js +2 -0
  27. package/dist/rules/pdp-e-001.js +2 -0
  28. package/dist/rules/pdp-e-002.js +2 -0
  29. package/dist/rules/pdp-e-003.js +2 -0
  30. package/dist/rules/pdp-e-004.js +2 -0
  31. package/dist/rules/pdp-e-005.js +2 -0
  32. package/dist/rules/pdp-e-006.js +2 -0
  33. package/dist/rules/pdp-e-007.js +2 -0
  34. package/dist/rules/pdp-e-008.js +2 -0
  35. package/dist/rules/pdp-e-009.js +2 -0
  36. package/dist/rules/pdp-e-010.js +2 -0
  37. package/dist/rules/pdp-e-011.js +2 -0
  38. package/dist/rules/pdp-e-012.js +2 -0
  39. package/dist/rules/pdp-e-013.js +2 -0
  40. package/dist/rules/pdp-e-014.js +2 -0
  41. package/dist/rules/pdp-e-015.js +2 -0
  42. package/dist/rules/pdp-e-016.js +2 -0
  43. package/dist/rules/pdp-e-017.d.ts +2 -0
  44. package/dist/rules/pdp-e-017.js +80 -0
  45. package/dist/rules/pdp-e-018.d.ts +11 -0
  46. package/dist/rules/pdp-e-018.js +18 -0
  47. package/dist/rules/pdp-i-001.js +5 -2
  48. package/dist/rules/pdp-w-001.js +2 -0
  49. package/dist/rules/pdp-w-002.js +2 -0
  50. package/dist/rules/pdp-w-003.js +2 -0
  51. package/dist/rules/pdp-w-004.js +2 -0
  52. package/dist/rules/pdp-w-005.js +2 -0
  53. package/dist/rules/pdp-w-006.js +2 -0
  54. package/dist/rules/pdp-w-007.js +2 -0
  55. package/dist/rules/pdp-w-008.js +2 -0
  56. package/dist/rules/pdp-w-009.js +2 -0
  57. package/dist/rules/pdp-w-010.js +2 -0
  58. package/dist/rules/pdp-w-011.js +2 -0
  59. package/dist/rules/pdp-w-012.js +2 -0
  60. package/dist/rules/pdp-w-013.js +2 -0
  61. package/dist/rules/pdp-w-014.js +2 -0
  62. package/dist/rules/pdp-w-015.js +2 -0
  63. package/dist/rules/pdp-w-016.js +2 -0
  64. package/dist/rules/pdp-w-017.js +2 -0
  65. package/dist/rules/pdp-w-018.js +2 -0
  66. package/dist/rules/pdp-w-019.js +2 -0
  67. package/dist/rules/pdp-w-020.js +2 -0
  68. package/dist/rules/pdp-w-021.js +2 -0
  69. package/dist/rules/pdp-w-022.js +2 -0
  70. package/dist/rules/pdp-w-023.js +2 -0
  71. package/dist/rules/pdp-w-024.js +2 -0
  72. package/dist/rules/pdp-w-025.js +2 -0
  73. package/dist/rules/pdp-w-026.js +2 -0
  74. package/dist/rules/pdp-w-027.js +2 -0
  75. package/dist/rules/pdp-w-028.js +2 -0
  76. package/dist/rules/pdp-w-029.js +2 -0
  77. package/dist/rules/pdp-w-030.js +2 -0
  78. package/dist/rules/pdp-w-031.js +2 -0
  79. package/dist/rules/pdp-w-032.js +2 -0
  80. package/dist/rules/pdp-w-033.js +2 -0
  81. package/dist/rules/pdp-w-034.js +2 -0
  82. package/dist/rules/pdp-w-035.js +2 -0
  83. package/dist/rules/pdp-w-036.js +2 -0
  84. package/dist/rules/pdp-w-037.js +2 -0
  85. package/dist/rules/pdp-w-038.js +2 -0
  86. package/dist/rules/pdp-w-039.js +2 -0
  87. package/dist/rules/release-schema.d.ts +18 -7
  88. package/dist/rules/release-schema.js +55 -15
  89. package/dist/schema-registry.d.ts +42 -0
  90. package/dist/schema-registry.js +52 -0
  91. package/dist/schema-validators.d.ts +7 -8
  92. package/dist/schema-validators.js +18 -4
  93. package/dist/validate-and-lint.d.ts +28 -21
  94. package/dist/validate-and-lint.js +60 -36
  95. package/dist/validate-organization.d.ts +5 -5
  96. package/dist/validate-organization.js +8 -18
  97. package/dist/version.d.ts +1 -1
  98. package/dist/version.js +1 -1
  99. package/package.json +3 -3
  100. package/dist/legacy-schemas.d.ts +0 -9
  101. package/dist/legacy-schemas.js +0 -2446
  102. package/dist/organization-schema.d.ts +0 -10
  103. package/dist/organization-schema.js +0 -443
  104. package/dist/product-schema.d.ts +0 -9
  105. package/dist/product-schema.js +0 -2015
  106. package/dist/schema-properties.d.ts +0 -10
@@ -5,9 +5,7 @@
5
5
  * boundary: callers see `SchemaError`, never Ajv's own error type.
6
6
  */
7
7
  import type { LintOptions, Report } from "@pagefront/lint-core";
8
- import type { SheetLine, SheetType } from "./sheet-type.js";
9
- /** The Layer 1 validator for a sheet type on a line. */
10
- export declare function validatorFor(sheetType: SheetType, line: SheetLine): import("ajv").ValidateFunction<unknown>;
8
+ import type { SheetType } from "./sheet-type.js";
11
9
  /**
12
10
  * One Layer 1 (JSON Schema) validation failure, in a shape this
13
11
  * package owns. `instancePath` is a JSON Pointer to the offending
@@ -27,25 +25,34 @@ export type ValidateAndLintResult = {
27
25
  report: Report;
28
26
  };
29
27
  /**
30
- * Validate a parsed-but-unvalidated document against the bundled
31
- * product JSON Schema (Layer 1), and — only if it passes — lint it
32
- * against the commerce rule catalogue (Layer 2). The engine assumes a
33
- * schema-valid Sheet, so a failing document never reaches the
34
- * catalogue; Layer 1 success is also what makes the internal cast to
35
- * `Sheet` sound (the schema requires the envelope fields).
28
+ * Layer 1 for one document: validate it against the frozen schema the
29
+ * release it declares resolves to (see schema-registry.ts); a legacy
30
+ * sheet is validated against the schema its `$schema` names. Returns
31
+ * the errors, empty when the document is valid. A `release` the
32
+ * manifest does not list is a Layer 1 failure of its own, reported at
33
+ * `/release` with the keyword `release`; a legacy `$schema` naming no
34
+ * bundled schema is reported at `/$schema`. In neither case is the
35
+ * document validated against some other version.
36
+ */
37
+ export declare function schemaErrorsFor(input: unknown, sheetType?: SheetType): SchemaError[];
38
+ /**
39
+ * Validate a parsed-but-unvalidated document against a bundled JSON
40
+ * Schema (Layer 1), and — only if it passes — lint it against the
41
+ * commerce rule catalogue (Layer 2). The engine assumes a schema-valid
42
+ * Sheet, so a failing document never reaches the catalogue; Layer 1
43
+ * success is also what makes the internal cast to `Sheet` sound (the
44
+ * schema requires the envelope fields).
36
45
  *
37
- * Two lines are validated (see sheet-type.ts): a sheet carrying
38
- * `release` validates against the current sheet-spec schema for its
39
- * type, and a legacy sheet carrying `format_version` validates against
40
- * the frozen legacy schema (format 0.9). A legacy sheet declaring some
41
- * other `format_version` failing Layer 1 is the intended behavior:
42
- * there is no separate "unsupported version" outcome.
46
+ * The package bundles every schema ever published, on both lines: the
47
+ * sheet-spec versions of each release, and the legacy draft line's
48
+ * format 0.9 schemas. A sheet is judged by the release it declares: the
49
+ * schema is the one that release bundles for the sheet's type, and a
50
+ * `$schema` that names another one is a Layer 2 finding (PDP-E-002,
51
+ * ORG-E-003). A release the manifest does not list fails Layer 1 with a
52
+ * single error saying so.
43
53
  *
44
- * Dispatches by page type (see sheet-type.ts): product sheets validate
45
- * against the product schema and lint with the product catalogue;
46
- * Commerce Organization Sheets validate against the organization
47
- * schema and lint with the organization catalogue. Detection reads the
48
- * envelope `$schema` first, falling back to data-block shape, so a
49
- * document of either type routes to its own schema's errors.
54
+ * Layer 2 dispatches by page type (see sheet-type.ts): product sheets
55
+ * lint with the product catalogue, Commerce Organization Sheets with
56
+ * the organization catalogue.
50
57
  */
51
58
  export declare function validateAndLint(input: unknown, options?: LintOptions): ValidateAndLintResult;
@@ -1,49 +1,73 @@
1
1
  import { lintSheet } from "./lint-sheet.js";
2
- import { detectSheetLine, detectSheetType } from "./sheet-type.js";
3
- import { validateProduct, validateOrganization, validateLegacyProduct, validateLegacyOrganization, } from "./schema-validators.js";
4
- /** The Layer 1 validator for a sheet type on a line. */
5
- export function validatorFor(sheetType, line) {
6
- if (line === "legacy") {
7
- return sheetType === "organization" ? validateLegacyOrganization : validateLegacyProduct;
8
- }
9
- return sheetType === "organization" ? validateOrganization : validateProduct;
10
- }
2
+ import { resolveSchema } from "./schema-registry.js";
3
+ import { VALIDATORS } from "./schema-validators.js";
11
4
  // The validators are compiled ahead of time (see schema-validators.d.ts):
12
5
  // nothing here generates code at load time, so the pipeline runs where
13
6
  // eval is unavailable, and consumers calling it in a loop pay no
14
7
  // compilation cost.
15
8
  /**
16
- * Validate a parsed-but-unvalidated document against the bundled
17
- * product JSON Schema (Layer 1), and — only if it passes — lint it
18
- * against the commerce rule catalogue (Layer 2). The engine assumes a
19
- * schema-valid Sheet, so a failing document never reaches the
20
- * catalogue; Layer 1 success is also what makes the internal cast to
21
- * `Sheet` sound (the schema requires the envelope fields).
9
+ * Layer 1 for one document: validate it against the frozen schema the
10
+ * release it declares resolves to (see schema-registry.ts); a legacy
11
+ * sheet is validated against the schema its `$schema` names. Returns
12
+ * the errors, empty when the document is valid. A `release` the
13
+ * manifest does not list is a Layer 1 failure of its own, reported at
14
+ * `/release` with the keyword `release`; a legacy `$schema` naming no
15
+ * bundled schema is reported at `/$schema`. In neither case is the
16
+ * document validated against some other version.
17
+ */
18
+ export function schemaErrorsFor(input, sheetType) {
19
+ const envelope = (typeof input === "object" && input !== null ? input : {});
20
+ const resolution = resolveSchema(envelope, sheetType);
21
+ if (resolution.kind === "unknown-release") {
22
+ return [
23
+ {
24
+ instancePath: "/release",
25
+ message: `names no release this linter knows: ${resolution.declared}`,
26
+ keyword: "release",
27
+ },
28
+ ];
29
+ }
30
+ if (resolution.kind === "unknown-schema") {
31
+ return [
32
+ {
33
+ instancePath: "/$schema",
34
+ message: `names no schema this linter bundles: ${resolution.declared}`,
35
+ keyword: "$schema",
36
+ },
37
+ ];
38
+ }
39
+ const validate = VALIDATORS[resolution.id];
40
+ if (validate(input))
41
+ return [];
42
+ return (validate.errors ?? []).map((error) => ({
43
+ instancePath: error.instancePath,
44
+ message: error.message ?? "invalid",
45
+ keyword: error.keyword,
46
+ }));
47
+ }
48
+ /**
49
+ * Validate a parsed-but-unvalidated document against a bundled JSON
50
+ * Schema (Layer 1), and — only if it passes — lint it against the
51
+ * commerce rule catalogue (Layer 2). The engine assumes a schema-valid
52
+ * Sheet, so a failing document never reaches the catalogue; Layer 1
53
+ * success is also what makes the internal cast to `Sheet` sound (the
54
+ * schema requires the envelope fields).
22
55
  *
23
- * Two lines are validated (see sheet-type.ts): a sheet carrying
24
- * `release` validates against the current sheet-spec schema for its
25
- * type, and a legacy sheet carrying `format_version` validates against
26
- * the frozen legacy schema (format 0.9). A legacy sheet declaring some
27
- * other `format_version` failing Layer 1 is the intended behavior:
28
- * there is no separate "unsupported version" outcome.
56
+ * The package bundles every schema ever published, on both lines: the
57
+ * sheet-spec versions of each release, and the legacy draft line's
58
+ * format 0.9 schemas. A sheet is judged by the release it declares: the
59
+ * schema is the one that release bundles for the sheet's type, and a
60
+ * `$schema` that names another one is a Layer 2 finding (PDP-E-002,
61
+ * ORG-E-003). A release the manifest does not list fails Layer 1 with a
62
+ * single error saying so.
29
63
  *
30
- * Dispatches by page type (see sheet-type.ts): product sheets validate
31
- * against the product schema and lint with the product catalogue;
32
- * Commerce Organization Sheets validate against the organization
33
- * schema and lint with the organization catalogue. Detection reads the
34
- * envelope `$schema` first, falling back to data-block shape, so a
35
- * document of either type routes to its own schema's errors.
64
+ * Layer 2 dispatches by page type (see sheet-type.ts): product sheets
65
+ * lint with the product catalogue, Commerce Organization Sheets with
66
+ * the organization catalogue.
36
67
  */
37
68
  export function validateAndLint(input, options) {
38
- const envelope = (typeof input === "object" && input !== null ? input : {});
39
- const validate = validatorFor(detectSheetType(envelope), detectSheetLine(envelope));
40
- if (!validate(input)) {
41
- const schemaErrors = (validate.errors ?? []).map((error) => ({
42
- instancePath: error.instancePath,
43
- message: error.message ?? "invalid",
44
- keyword: error.keyword,
45
- }));
69
+ const schemaErrors = schemaErrorsFor(input);
70
+ if (schemaErrors.length > 0)
46
71
  return { layer: 1, schemaErrors };
47
- }
48
72
  return { layer: 2, report: lintSheet(input, options) };
49
73
  }
@@ -18,10 +18,10 @@ export type ValidateOrganizationResult = {
18
18
  schemaErrors: SchemaError[];
19
19
  };
20
20
  /**
21
- * Validate a parsed-but-unvalidated document against the bundled
22
- * Commerce Organization Sheet JSON Schema for its line: the current
23
- * sheet-spec schema for a sheet carrying `release`, the frozen legacy
24
- * schema for one carrying `format_version`, exactly as in the product
25
- * pipeline.
21
+ * Validate a parsed-but-unvalidated document against a bundled
22
+ * Commerce Organization Sheet JSON Schema: the one its `$schema` names,
23
+ * or, when it declares none, the organization schema for its line (the
24
+ * sheet-spec version its `release` bundles, or the legacy format 0.9
25
+ * schema for a sheet carrying `format_version`).
26
26
  */
27
27
  export declare function validateOrganizationSheet(input: unknown): ValidateOrganizationResult;
@@ -1,22 +1,12 @@
1
- import { detectSheetLine } from "./sheet-type.js";
2
- import { validatorFor } from "./validate-and-lint.js";
1
+ import { schemaErrorsFor } from "./validate-and-lint.js";
3
2
  /**
4
- * Validate a parsed-but-unvalidated document against the bundled
5
- * Commerce Organization Sheet JSON Schema for its line: the current
6
- * sheet-spec schema for a sheet carrying `release`, the frozen legacy
7
- * schema for one carrying `format_version`, exactly as in the product
8
- * pipeline.
3
+ * Validate a parsed-but-unvalidated document against a bundled
4
+ * Commerce Organization Sheet JSON Schema: the one its `$schema` names,
5
+ * or, when it declares none, the organization schema for its line (the
6
+ * sheet-spec version its `release` bundles, or the legacy format 0.9
7
+ * schema for a sheet carrying `format_version`).
9
8
  */
10
9
  export function validateOrganizationSheet(input) {
11
- const envelope = (typeof input === "object" && input !== null ? input : {});
12
- const validate = validatorFor("organization", detectSheetLine(envelope));
13
- if (!validate(input)) {
14
- const schemaErrors = (validate.errors ?? []).map((error) => ({
15
- instancePath: error.instancePath,
16
- message: error.message ?? "invalid",
17
- keyword: error.keyword,
18
- }));
19
- return { valid: false, schemaErrors };
20
- }
21
- return { valid: true };
10
+ const schemaErrors = schemaErrorsFor(input, "organization");
11
+ return schemaErrors.length > 0 ? { valid: false, schemaErrors } : { valid: true };
22
12
  }
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.10.0";
8
+ export declare const PACKAGE_VERSION = "0.12.0";
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.10.0";
8
+ export const PACKAGE_VERSION = "0.12.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagefront/lint-commerce",
3
- "version": "0.10.0",
3
+ "version": "0.12.0",
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": {
@@ -34,12 +34,12 @@
34
34
  "access": "public"
35
35
  },
36
36
  "scripts": {
37
- "build": "tsc && node scripts/compile-validators.mjs",
37
+ "build": "node scripts/bundle-schemas.mjs && tsc && node scripts/compile-validators.mjs",
38
38
  "test": "npm run build && node --test test/*.test.mjs",
39
39
  "prepublishOnly": "npm test"
40
40
  },
41
41
  "dependencies": {
42
- "@pagefront/lint-core": "^0.2.0",
42
+ "@pagefront/lint-core": "^0.3.0",
43
43
  "ajv": "^8.20.0",
44
44
  "ajv-formats": "^3.0.1"
45
45
  },
@@ -1,9 +0,0 @@
1
- /**
2
- * The legacy draft line's JSON Schemas (commerce/spec/legacy/*.v0.9.json),
3
- * bundled verbatim so sheets carrying `format_version` keep validating
4
- * against the schemas their `$schema` URLs name. The files are frozen:
5
- * the schema drift test (test/schema.test.mjs) fails if a bundled copy
6
- * and its source diverge.
7
- */
8
- export declare const LEGACY_PRODUCT_SCHEMA: Record<string, unknown>;
9
- export declare const LEGACY_ORGANIZATION_SCHEMA: Record<string, unknown>;