docusaurus-plugin-generate-schema-docs 1.1.1 → 1.2.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 (44) hide show
  1. package/README.md +22 -0
  2. package/__tests__/ExampleDataLayer.test.js +169 -0
  3. package/__tests__/__fixtures__/static/schemas/add-to-cart-event.json +55 -0
  4. package/__tests__/__fixtures__/static/schemas/components/dataLayer.json +58 -0
  5. package/__tests__/__fixtures__/static/schemas/components/product.json +211 -0
  6. package/__tests__/__fixtures__/validateSchemas/circular-schema.json +8 -0
  7. package/__tests__/__fixtures__/validateSchemas/components/referenced.json +8 -0
  8. package/__tests__/__fixtures__/validateSchemas/invalid-example-schema.json +8 -0
  9. package/__tests__/__fixtures__/validateSchemas/main-schema-with-missing-ref.json +8 -0
  10. package/__tests__/__fixtures__/validateSchemas/main-schema-with-ref.json +8 -0
  11. package/__tests__/__fixtures__/validateSchemas/no-example-schema.json +12 -0
  12. package/__tests__/__fixtures__/validateSchemas/schema-A.json +7 -0
  13. package/__tests__/__fixtures__/validateSchemas/schema-B.json +7 -0
  14. package/__tests__/__fixtures__/validateSchemas/valid-schema.json +8 -0
  15. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +53 -0
  16. package/__tests__/components/PropertiesTable.test.js +24 -0
  17. package/__tests__/components/PropertyRow.test.js +67 -0
  18. package/__tests__/components/SchemaJsonViewer.test.js +32 -0
  19. package/__tests__/components/SchemaRows.test.js +80 -0
  20. package/__tests__/components/SchemaViewer.test.js +27 -0
  21. package/__tests__/components/TableHeader.test.js +20 -0
  22. package/__tests__/generateEventDocs.test.js +84 -0
  23. package/__tests__/helpers/buildExampleFromSchema.test.js +188 -0
  24. package/__tests__/helpers/getConstraints.test.js +58 -0
  25. package/__tests__/helpers/loadSchema.test.js +14 -0
  26. package/__tests__/helpers/processSchema.test.js +36 -0
  27. package/__tests__/validateSchemas.test.js +100 -0
  28. package/components/ExampleDataLayer.js +7 -5
  29. package/components/PropertiesTable.js +5 -10
  30. package/components/PropertyRow.js +74 -0
  31. package/components/SchemaJsonViewer.js +3 -2
  32. package/components/SchemaRows.css +28 -0
  33. package/components/SchemaRows.js +19 -47
  34. package/components/SchemaViewer.js +4 -2
  35. package/components/TableHeader.js +15 -0
  36. package/generateEventDocs.js +37 -36
  37. package/helpers/buildExampleFromSchema.js +3 -3
  38. package/helpers/getConstraints.js +53 -0
  39. package/helpers/loadSchema.js +11 -0
  40. package/helpers/mdx-template.js +36 -0
  41. package/helpers/processSchema.js +32 -0
  42. package/index.js +21 -11
  43. package/package.json +6 -3
  44. package/validateSchemas.js +6 -3
@@ -0,0 +1,53 @@
1
+ // A list of JSON Schema keywords that have simple key-value constraints.
2
+ const constraintHandlers = {
3
+ // Simple key-value constraints
4
+ minLength: (val) => `minLength: ${val}`,
5
+ maxLength: (val) => `maxLength: ${val}`,
6
+ minimum: (val) => `minimum: ${val}`,
7
+ maximum: (val) => `maximum: ${val}`,
8
+ exclusiveMinimum: (val) => `exclusiveMinimum: ${val}`,
9
+ exclusiveMaximum: (val) => `exclusiveMaximum: ${val}`,
10
+ minItems: (val) => `minItems: ${val}`,
11
+ maxItems: (val) => `maxItems: ${val}`,
12
+ minProperties: (val) => `minProperties: ${val}`,
13
+ maxProperties: (val) => `maxProperties: ${val}`,
14
+ multipleOf: (val) => `multipleOf: ${val}`,
15
+ format: (val) => `format: ${val}`,
16
+ minContains: (val) => `minContains: ${val}`,
17
+ maxContains: (val) => `maxContains: ${val}`,
18
+
19
+ // Special-cased constraints
20
+ pattern: (val) => `pattern: /${val}/`,
21
+ uniqueItems: (val) => (val ? 'uniqueItems: true' : null),
22
+ additionalProperties: (val) => (val === false ? 'additionalProperties: false' : null),
23
+ propertyNames: (val) => `propertyNames: ${JSON.stringify(val)}`,
24
+ dependentRequired: (val) => {
25
+ const deps = Object.entries(val).map(([key, depVal]) => `${key} -> [${depVal.join(', ')}]`).join('; ');
26
+ return `dependentRequired: ${deps}`;
27
+ },
28
+ contains: (val) => `contains: ${JSON.stringify(val)}`,
29
+ enum: (val) => `enum: [${val.join(', ')}]`,
30
+ const: (val) => `const: ${JSON.stringify(val)}`,
31
+ };
32
+
33
+ export const getConstraints = (prop, isReq) => {
34
+ const constraints = [];
35
+ if (isReq)
36
+ {
37
+ constraints.push('required');
38
+ }
39
+
40
+ for (const keyword in constraintHandlers)
41
+ {
42
+ if (prop[keyword] !== undefined)
43
+ {
44
+ const handler = constraintHandlers[keyword];
45
+ const result = handler(prop[keyword]);
46
+ if (result)
47
+ {
48
+ constraints.push(result);
49
+ }
50
+ }
51
+ }
52
+ return constraints;
53
+ };
@@ -0,0 +1,11 @@
1
+ import fs from 'fs';
2
+
3
+ /**
4
+ * Loads a JSON schema file and returns its content as a JSON object.
5
+ * @param {string} filePath Path to the JSON schema file.
6
+ * @returns {object} The parsed JSON schema.
7
+ */
8
+ export default function loadSchema(filePath) {
9
+ const rawContent = fs.readFileSync(filePath, 'utf-8');
10
+ return JSON.parse(rawContent);
11
+ }
@@ -0,0 +1,36 @@
1
+ export default function MdxTemplate(data) {
2
+ const {
3
+ schema,
4
+ mergedSchema,
5
+ baseEditUrl,
6
+ file,
7
+ topPartialImport,
8
+ bottomPartialImport,
9
+ topPartialComponent,
10
+ bottomPartialComponent
11
+ } = data;
12
+
13
+ return `---
14
+ title: ${schema.title}
15
+ description: ${JSON.stringify(schema.description)}
16
+ sidebar_label: ${schema.title}
17
+ custom_edit_url: ${baseEditUrl}/demo/static/schemas/${file}
18
+ ---
19
+
20
+ import SchemaViewer from '@theme/SchemaViewer';
21
+ import SchemaJsonViewer from '@theme/SchemaJsonViewer';
22
+ ${topPartialImport}
23
+ ${bottomPartialImport}
24
+
25
+ # ${schema.title}
26
+
27
+ ${schema.description}
28
+
29
+ ${topPartialComponent}
30
+
31
+ <SchemaViewer schema={${JSON.stringify(mergedSchema)}} />
32
+ <SchemaJsonViewer schema={${JSON.stringify(schema)}} />
33
+
34
+ ${bottomPartialComponent}
35
+ `;
36
+ }
@@ -0,0 +1,32 @@
1
+ import $RefParser from "@apidevtools/json-schema-ref-parser";
2
+ import mergeJsonSchema from "json-schema-merge-allof";
3
+
4
+ /**
5
+ * Processes a JSON schema file by bundling external references,
6
+ * dereferencing internal references, and merging allOf properties.
7
+ *
8
+ * @param {string} filePath Path to the JSON schema file.
9
+ * @returns {Promise<object>} The processed (merged) schema.
10
+ */
11
+ export default async function processSchema(filePath) {
12
+ // 1. Bundle all external references into a single, self-contained schema
13
+ const bundledSchema = await $RefParser.bundle(filePath, {
14
+ mutateInputSchema: false,
15
+ });
16
+
17
+ // 2. Dereference the bundled schema to resolve internal refs for allOf merging
18
+ const dereferencedSchema = await $RefParser.dereference(bundledSchema, {
19
+ dereference: {
20
+ circular: 'ignore', // Keep recursive parts as $refs
21
+ }
22
+ });
23
+
24
+ // Then merge allOf properties
25
+ const mergedSchema = mergeJsonSchema(dereferencedSchema, {
26
+ resolvers: {
27
+ defaultResolver: mergeJsonSchema.options.resolvers.title
28
+ }
29
+ });
30
+
31
+ return mergedSchema;
32
+ }
package/index.js CHANGED
@@ -1,17 +1,31 @@
1
1
  import validateSchemas from './validateSchemas.js';
2
2
  import generateEventDocs from './generateEventDocs.js';
3
3
  import path from 'path';
4
- import { fileURLToPath } from 'url';
5
4
 
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
5
+ export default async function (context) {
6
+ const { siteDir } = context;
7
+ const { organizationName, projectName } = context.siteConfig;
8
+ const options = { organizationName, projectName, siteDir };
9
+ const schemasPath = path.join(siteDir, 'static/schemas');
10
+
11
+ // Generate docs on startup
12
+ await generateEventDocs(options);
8
13
 
9
- export default function (context, options) {
10
14
  return {
11
15
  name: 'docusaurus-plugin-generate-schema-docs',
12
16
 
17
+ getPathsToWatch() {
18
+ // Watch the schemas directory for changes
19
+ return [schemasPath];
20
+ },
21
+
22
+ async loadContent() {
23
+ // Generate event documentation when watched files change
24
+ await generateEventDocs(options);
25
+ },
26
+
13
27
  getThemePath() {
14
- return path.resolve(__dirname, './components');
28
+ return './components';
15
29
  },
16
30
 
17
31
  extendCli(cli) {
@@ -21,7 +35,7 @@ export default function (context, options) {
21
35
  .action(async () => {
22
36
  console.log('Validating GTM Schemas...');
23
37
  // You might get the path from 'options' or assume a default
24
- const schemaPath = options?.path || path.join(context.siteDir, 'schemas');
38
+ const schemaPath = options?.path || path.join(context.siteDir, 'static/schemas');
25
39
 
26
40
  const success = await validateSchemas(schemaPath);
27
41
 
@@ -42,9 +56,5 @@ export default function (context, options) {
42
56
  await generateEventDocs();
43
57
  });
44
58
  },
45
-
46
- async loadContent() {
47
- await generateEventDocs();
48
- },
49
59
  };
50
- }
60
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "docusaurus-plugin-generate-schema-docs",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "description": "Docusaurus plugin to generate documentation from JSON schemas.",
5
5
  "main": "index.js",
6
6
  "license": "MIT",
@@ -10,11 +10,14 @@
10
10
  },
11
11
  "dependencies": {
12
12
  "@apidevtools/json-schema-ref-parser": "^15.1.3",
13
- "fs-extra": "^11.2.0",
13
+ "fs-extra": "^11.3.3",
14
14
  "json-schema-merge-allof": "^0.8.1"
15
15
  },
16
16
  "publishConfig": {
17
17
  "access": "public",
18
18
  "provenance": true
19
+ },
20
+ "devDependencies": {
21
+ "jest": "^30.2.0"
19
22
  }
20
- }
23
+ }
@@ -2,11 +2,13 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import buildExampleFromSchema from './helpers/buildExampleFromSchema';
4
4
  import Ajv2020 from 'ajv/dist/2020.js';
5
+ import addFormats from 'ajv-formats';
5
6
  import $RefParser from "@apidevtools/json-schema-ref-parser";
6
7
  import mergeJsonSchema from "json-schema-merge-allof";
7
8
 
8
9
  const validateSchemas = async (schemaPath) => {
9
10
  const ajv = new Ajv2020();
11
+ addFormats(ajv);
10
12
  ajv.addKeyword('x-gtm-clear');
11
13
 
12
14
  const getAllFiles = (dir, allFiles = []) => {
@@ -28,7 +30,7 @@ const validateSchemas = async (schemaPath) => {
28
30
  return allFiles;
29
31
  };
30
32
 
31
- const allSchemaFiles = getAllFiles('schemas');
33
+ const allSchemaFiles = getAllFiles(schemaPath);
32
34
  for (const file of allSchemaFiles)
33
35
  {
34
36
  const schemaContent = fs.readFileSync(file, 'utf-8');
@@ -41,7 +43,7 @@ const validateSchemas = async (schemaPath) => {
41
43
  for (const file of schemaFiles)
42
44
  {
43
45
  const filePath = path.join(schemaPath, file);
44
-
46
+
45
47
  // Dereference and merge, same as in generateEventDocs.js
46
48
  const clonedSchema = await $RefParser.dereference(filePath, {
47
49
  mutateInputSchema: false, dereference: {
@@ -64,7 +66,8 @@ const validateSchemas = async (schemaPath) => {
64
66
  {
65
67
  const originalSchema = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
66
68
  const validate = ajv.getSchema(originalSchema.$id);
67
- if (!validate) {
69
+ if (!validate)
70
+ {
68
71
  console.error(`❌ Could not find compiled schema for ${originalSchema.$id}`);
69
72
  allValid = false;
70
73
  continue;