docusaurus-plugin-generate-schema-docs 1.1.1 → 1.3.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 (81) hide show
  1. package/README.md +60 -2
  2. package/__tests__/ExampleDataLayer.test.js +92 -0
  3. package/__tests__/__fixtures__/static/schemas/add-to-cart-event.json +44 -0
  4. package/__tests__/__fixtures__/static/schemas/choice-event.json +72 -0
  5. package/__tests__/__fixtures__/static/schemas/components/dataLayer.json +56 -0
  6. package/__tests__/__fixtures__/static/schemas/components/product.json +125 -0
  7. package/__tests__/__fixtures__/static/schemas/nested/child-event.json +10 -0
  8. package/__tests__/__fixtures__/static/schemas/nested/grandchild-a.json +9 -0
  9. package/__tests__/__fixtures__/static/schemas/nested/grandchild-b.json +9 -0
  10. package/__tests__/__fixtures__/static/schemas/nested/parent-event.json +7 -0
  11. package/__tests__/__fixtures__/static/schemas/root-any-of-event.json +34 -0
  12. package/__tests__/__fixtures__/static/schemas/root-choice-event.json +36 -0
  13. package/__tests__/__fixtures__/validateSchemas/circular-schema.json +8 -0
  14. package/__tests__/__fixtures__/validateSchemas/components/referenced.json +10 -0
  15. package/__tests__/__fixtures__/validateSchemas/invalid-example-schema.json +8 -0
  16. package/__tests__/__fixtures__/validateSchemas/main-schema-with-missing-ref.json +8 -0
  17. package/__tests__/__fixtures__/validateSchemas/main-schema-with-ref.json +8 -0
  18. package/__tests__/__fixtures__/validateSchemas/no-example-schema.json +12 -0
  19. package/__tests__/__fixtures__/validateSchemas/schema-A.json +7 -0
  20. package/__tests__/__fixtures__/validateSchemas/schema-B.json +7 -0
  21. package/__tests__/__fixtures__/validateSchemas/valid-schema.json +8 -0
  22. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/add-to-cart-event.json +44 -0
  23. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/components/dataLayer.json +56 -0
  24. package/__tests__/__fixtures_versioned__/static/schemas/1.1.1/components/product.json +125 -0
  25. package/__tests__/__fixtures_versioned__/static/schemas/next/add-to-cart-event.json +44 -0
  26. package/__tests__/__fixtures_versioned__/static/schemas/next/components/dataLayer.json +56 -0
  27. package/__tests__/__fixtures_versioned__/static/schemas/next/components/product.json +125 -0
  28. package/__tests__/__fixtures_versioned__/versions.json +1 -0
  29. package/__tests__/__snapshots__/ExampleDataLayer.test.js.snap +117 -0
  30. package/__tests__/__snapshots__/generateEventDocs.nested.test.js.snap +92 -0
  31. package/__tests__/__snapshots__/generateEventDocs.test.js.snap +151 -0
  32. package/__tests__/__snapshots__/generateEventDocs.versioned.test.js.snap +53 -0
  33. package/__tests__/components/FoldableRows.test.js +330 -0
  34. package/__tests__/components/PropertiesTable.test.js +41 -0
  35. package/__tests__/components/PropertyRow.test.js +487 -0
  36. package/__tests__/components/SchemaJsonViewer.test.js +36 -0
  37. package/__tests__/components/SchemaRows.test.js +110 -0
  38. package/__tests__/components/SchemaViewer.test.js +44 -0
  39. package/__tests__/components/TableHeader.test.js +20 -0
  40. package/__tests__/generateEventDocs.nested.test.js +80 -0
  41. package/__tests__/generateEventDocs.test.js +90 -0
  42. package/__tests__/generateEventDocs.versioned.test.js +69 -0
  43. package/__tests__/helpers/buildExampleFromSchema.test.js +188 -0
  44. package/__tests__/helpers/file-system.test.js +44 -0
  45. package/__tests__/helpers/getConstraints.test.js +58 -0
  46. package/__tests__/helpers/loadSchema.test.js +20 -0
  47. package/__tests__/helpers/path-helpers.test.js +34 -0
  48. package/__tests__/helpers/processSchema.test.js +56 -0
  49. package/__tests__/helpers/schema-processing.test.js +82 -0
  50. package/__tests__/helpers/schemaToExamples.test.js +56 -0
  51. package/__tests__/helpers/schemaToTableData.filtering.test.js +65 -0
  52. package/__tests__/helpers/schemaToTableData.hierarchicalLines.test.js +539 -0
  53. package/__tests__/helpers/schemaToTableData.test.js +222 -0
  54. package/__tests__/helpers/update-schema-ids.test.js +107 -0
  55. package/__tests__/update-schema-ids.test.js +39 -0
  56. package/__tests__/validateSchemas.test.js +137 -0
  57. package/components/ExampleDataLayer.js +60 -27
  58. package/components/FoldableRows.js +164 -0
  59. package/components/PropertiesTable.js +12 -14
  60. package/components/PropertyRow.js +183 -0
  61. package/components/SchemaJsonViewer.js +8 -7
  62. package/components/SchemaRows.css +250 -0
  63. package/components/SchemaRows.js +24 -69
  64. package/components/SchemaViewer.js +21 -13
  65. package/components/TableHeader.js +15 -0
  66. package/generateEventDocs.js +141 -60
  67. package/helpers/buildExampleFromSchema.js +59 -73
  68. package/helpers/choice-index-template.js +22 -0
  69. package/helpers/file-system.js +32 -0
  70. package/helpers/getConstraints.js +52 -0
  71. package/helpers/loadSchema.js +11 -0
  72. package/helpers/path-helpers.js +22 -0
  73. package/helpers/processSchema.js +32 -0
  74. package/helpers/schema-doc-template.js +36 -0
  75. package/helpers/schema-processing.js +75 -0
  76. package/helpers/schemaToExamples.js +99 -0
  77. package/helpers/schemaToTableData.js +311 -0
  78. package/helpers/update-schema-ids.js +47 -0
  79. package/index.js +146 -47
  80. package/package.json +6 -3
  81. package/validateSchemas.js +56 -70
package/index.js CHANGED
@@ -1,50 +1,149 @@
1
+ import { getPathsForVersion } from './helpers/path-helpers.js';
2
+ import updateSchemaIds from './helpers/update-schema-ids.js';
3
+ import fs from 'fs';
1
4
  import validateSchemas from './validateSchemas.js';
2
5
  import generateEventDocs from './generateEventDocs.js';
3
6
  import path from 'path';
4
- import { fileURLToPath } from 'url';
5
-
6
- const __filename = fileURLToPath(import.meta.url);
7
- const __dirname = path.dirname(__filename);
8
-
9
- export default function (context, options) {
10
- return {
11
- name: 'docusaurus-plugin-generate-schema-docs',
12
-
13
- getThemePath() {
14
- return path.resolve(__dirname, './components');
15
- },
16
-
17
- extendCli(cli) {
18
- cli
19
- .command('validate-schemas')
20
- .description('Validate JSON Schemas with the examples inside the schemas')
21
- .action(async () => {
22
- console.log('Validating GTM Schemas...');
23
- // You might get the path from 'options' or assume a default
24
- const schemaPath = options?.path || path.join(context.siteDir, 'schemas');
25
-
26
- const success = await validateSchemas(schemaPath);
27
-
28
- if (!success)
29
- {
30
- console.error('Validation failed.');
31
- process.exit(1); // Important for CI to fail!
32
- }
33
- console.log(' All schemas and examples are valid!');
34
- });
35
-
36
- cli
37
- .command('generate schema-docs')
38
- .description('Generate schema documentation from JSON schemas')
39
- .action(async () => {
40
- // You can pass options here if generateEventDocs needs the path too
41
- // e.g., await generateEventDocs(options.path || './static/schemas');
42
- await generateEventDocs();
43
- });
44
- },
45
-
46
- async loadContent() {
47
- await generateEventDocs();
48
- },
49
- };
50
- }
7
+
8
+ export default async function (context) {
9
+ const { siteDir } = context;
10
+ const { organizationName, projectName, url } = context.siteConfig;
11
+ const options = { organizationName, projectName, siteDir, url };
12
+ const versionsJsonPath = path.join(siteDir, 'versions.json');
13
+ const isVersioned = fs.existsSync(versionsJsonPath);
14
+
15
+ const extendCli = (cli) => {
16
+ cli
17
+ .command('validate-schemas [version]')
18
+ .description('Validate JSON Schemas with the examples inside the schemas')
19
+ .action(async (version) => {
20
+ console.log('Validating GTM Schemas...');
21
+ const schemaVersion = version || 'next';
22
+ const { schemaDir } = getPathsForVersion(
23
+ schemaVersion,
24
+ context.siteDir,
25
+ );
26
+ const success = await validateSchemas(schemaDir);
27
+ if (!success) {
28
+ console.error('Validation failed.');
29
+ process.exit(1);
30
+ }
31
+ console.log('✅ All schemas and examples are valid!');
32
+ });
33
+
34
+ cli
35
+ .command('generate-schema-docs')
36
+ .description('Generate schema documentation from JSON schemas')
37
+ .action(async () => {
38
+ if (isVersioned) {
39
+ const versions = JSON.parse(
40
+ fs.readFileSync(versionsJsonPath, 'utf8'),
41
+ );
42
+ for (const version of versions) {
43
+ await generateEventDocs({ ...options, version });
44
+ }
45
+ await generateEventDocs({ ...options, version: 'current' });
46
+ } else {
47
+ await generateEventDocs(options);
48
+ }
49
+ });
50
+
51
+ cli
52
+ .command('update-schema-ids [version]')
53
+ .description('Update the $id of the versioned schemas')
54
+ .action((version) => {
55
+ updateSchemaIds(siteDir, url, version);
56
+ });
57
+
58
+ cli
59
+ .command('version-with-schemas <version>')
60
+ .description(
61
+ 'Create a new docs version and copy schemas from next to versioned folder',
62
+ )
63
+ .action(async (version) => {
64
+ const { execSync } = await import('child_process');
65
+
66
+ console.log(`📦 Creating docs version ${version}...`);
67
+ try {
68
+ // Run the standard docusaurus docs:version command
69
+ execSync(`npx docusaurus docs:version ${version}`, {
70
+ cwd: siteDir,
71
+ stdio: 'inherit',
72
+ });
73
+ } catch (error) {
74
+ console.error('❌ Failed to create docs version');
75
+ process.exit(1);
76
+ }
77
+
78
+ console.log(`📂 Copying schemas from next to ${version}...`);
79
+ const nextSchemasDir = path.join(siteDir, 'static/schemas/next');
80
+ const versionedSchemasDir = path.join(
81
+ siteDir,
82
+ 'static/schemas',
83
+ version,
84
+ );
85
+
86
+ if (!fs.existsSync(nextSchemasDir)) {
87
+ console.error(
88
+ `❌ Source schemas directory not found: ${nextSchemasDir}`,
89
+ );
90
+ process.exit(1);
91
+ }
92
+
93
+ // Copy the schemas
94
+ try {
95
+ fs.cpSync(nextSchemasDir, versionedSchemasDir, { recursive: true });
96
+ console.log(`✅ Schemas copied to ${versionedSchemasDir}`);
97
+ } catch (error) {
98
+ console.error(`❌ Failed to copy schemas: ${error.message}`);
99
+ process.exit(1);
100
+ }
101
+
102
+ // Update schema IDs for the new version
103
+ console.log(`🔄 Updating schema $ids for version ${version}...`);
104
+ updateSchemaIds(siteDir, url, version);
105
+
106
+ // Generate documentation for the new version
107
+ console.log(`📝 Generating documentation for version ${version}...`);
108
+ await generateEventDocs({ ...options, version });
109
+
110
+ console.log(`\n✅ Version ${version} created successfully!`);
111
+ console.log(`\nNext steps:`);
112
+ console.log(` 1. Review the changes in static/schemas/${version}/`);
113
+ console.log(
114
+ ` 2. Review the changes in versioned_docs/version-${version}/`,
115
+ );
116
+ console.log(` 3. Commit the changes to version control`);
117
+ });
118
+ };
119
+
120
+ const schemasPath = isVersioned
121
+ ? path.join(siteDir, 'static/schemas/next')
122
+ : path.join(siteDir, 'static/schemas');
123
+
124
+ return {
125
+ name: 'docusaurus-plugin-generate-schema-docs',
126
+
127
+ getPathsToWatch() {
128
+ return [schemasPath];
129
+ },
130
+
131
+ async loadContent() {
132
+ if (isVersioned) {
133
+ const versions = JSON.parse(fs.readFileSync(versionsJsonPath, 'utf8'));
134
+ for (const version of versions) {
135
+ await generateEventDocs({ ...options, version });
136
+ }
137
+ await generateEventDocs({ ...options, version: 'current' });
138
+ } else {
139
+ await generateEventDocs(options);
140
+ }
141
+ },
142
+
143
+ getThemePath() {
144
+ return './components';
145
+ },
146
+
147
+ extendCli,
148
+ };
149
+ }
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.3.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,85 +2,71 @@ 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 $RefParser from "@apidevtools/json-schema-ref-parser";
6
- import mergeJsonSchema from "json-schema-merge-allof";
5
+ import addFormats from 'ajv-formats';
6
+ import processSchema from './helpers/processSchema';
7
7
 
8
8
  const validateSchemas = async (schemaPath) => {
9
- const ajv = new Ajv2020();
10
- ajv.addKeyword('x-gtm-clear');
9
+ const ajv = new Ajv2020();
10
+ addFormats(ajv);
11
+ ajv.addKeyword('x-gtm-clear');
11
12
 
12
- const getAllFiles = (dir, allFiles = []) => {
13
- const files = fs.readdirSync(dir);
13
+ const getAllFiles = (dir, allFiles = []) => {
14
+ const files = fs.readdirSync(dir);
14
15
 
15
- files.forEach(file => {
16
- const filePath = path.join(dir, file);
17
- if (fs.statSync(filePath).isDirectory())
18
- {
19
- getAllFiles(filePath, allFiles);
20
- } else
21
- {
22
- if (file.endsWith('.json'))
23
- {
24
- allFiles.push(filePath);
25
- }
26
- }
27
- });
28
- return allFiles;
29
- };
16
+ files.forEach((file) => {
17
+ const filePath = path.join(dir, file);
18
+ if (fs.statSync(filePath).isDirectory()) {
19
+ getAllFiles(filePath, allFiles);
20
+ } else {
21
+ if (file.endsWith('.json')) {
22
+ allFiles.push(filePath);
23
+ }
24
+ }
25
+ });
26
+ return allFiles;
27
+ };
30
28
 
31
- const allSchemaFiles = getAllFiles('schemas');
32
- for (const file of allSchemaFiles)
33
- {
34
- const schemaContent = fs.readFileSync(file, 'utf-8');
35
- const schema = JSON.parse(schemaContent);
36
- ajv.addSchema(schema);
37
- }
29
+ const allSchemaFiles = getAllFiles(schemaPath);
30
+ for (const file of allSchemaFiles) {
31
+ const schemaContent = fs.readFileSync(file, 'utf-8');
32
+ const schema = JSON.parse(schemaContent);
33
+ ajv.addSchema(schema);
34
+ }
38
35
 
39
- const schemaFiles = fs.readdirSync(schemaPath).filter(file => file.endsWith('.json'));
40
- let allValid = true;
41
- for (const file of schemaFiles)
42
- {
43
- const filePath = path.join(schemaPath, file);
44
-
45
- // Dereference and merge, same as in generateEventDocs.js
46
- const clonedSchema = await $RefParser.dereference(filePath, {
47
- mutateInputSchema: false, dereference: {
48
- circular: 'ignore'
49
- }
50
- });
51
- const mergedSchema = mergeJsonSchema(clonedSchema, {
52
- resolvers: {
53
- defaultResolver: mergeJsonSchema.options.resolvers.title
54
- }
55
- });
36
+ const schemaFiles = fs
37
+ .readdirSync(schemaPath)
38
+ .filter((file) => file.endsWith('.json'));
39
+ let allValid = true;
40
+ for (const file of schemaFiles) {
41
+ const filePath = path.join(schemaPath, file);
56
42
 
57
- const example_data = buildExampleFromSchema(mergedSchema);
43
+ const mergedSchema = await processSchema(filePath);
58
44
 
59
- if (!example_data)
60
- {
61
- console.error(`❌ Schema ${file} does not produce a valid example.`);
62
- allValid = false;
63
- } else
64
- {
65
- const originalSchema = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
66
- const validate = ajv.getSchema(originalSchema.$id);
67
- if (!validate) {
68
- console.error(`❌ Could not find compiled schema for ${originalSchema.$id}`);
69
- allValid = false;
70
- continue;
71
- }
72
- if (validate(example_data))
73
- {
74
- console.log(`✅ Schema ${file} produced a valid example.`);
75
- } else
76
- {
77
- console.error(`❌ Schema ${file} example data failed validation:`);
78
- console.error(validate.errors);
79
- allValid = false;
80
- }
81
- }
45
+ const example_data = buildExampleFromSchema(mergedSchema);
46
+
47
+ if (!example_data) {
48
+ console.error(`x Schema ${file} does not produce a valid example.`);
49
+ allValid = false;
50
+ } else {
51
+ const originalSchema = JSON.parse(fs.readFileSync(filePath, 'utf-8'));
52
+ const validate = ajv.getSchema(originalSchema.$id);
53
+ if (!validate) {
54
+ console.error(
55
+ `x Could not find compiled schema for ${originalSchema.$id}`,
56
+ );
57
+ allValid = false;
58
+ continue;
59
+ }
60
+ if (validate(example_data)) {
61
+ console.log(`OK Schema ${file} produced a valid example.`);
62
+ } else {
63
+ console.error(`x Schema ${file} example data failed validation:`);
64
+ console.error(validate.errors);
65
+ allValid = false;
66
+ }
82
67
  }
83
- return allValid;
68
+ }
69
+ return allValid;
84
70
  };
85
71
 
86
72
  export default validateSchemas;