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,58 @@
1
+ import { getConstraints } from '../../helpers/getConstraints';
2
+
3
+ describe('getConstraints', () => {
4
+ it('should return "required" if isReq is true', () => {
5
+ const constraints = getConstraints({}, true);
6
+ expect(constraints).toContain('required');
7
+ });
8
+
9
+ it('should handle simple key-value constraints', () => {
10
+ const prop = {
11
+ minLength: 1,
12
+ maxLength: 10,
13
+ minimum: 0,
14
+ maximum: 100,
15
+ minItems: 1,
16
+ maxItems: 5,
17
+ };
18
+ const constraints = getConstraints(prop, false);
19
+ expect(constraints).toEqual([
20
+ 'minLength: 1',
21
+ 'maxLength: 10',
22
+ 'minimum: 0',
23
+ 'maximum: 100',
24
+ 'minItems: 1',
25
+ 'maxItems: 5',
26
+ ]);
27
+ });
28
+
29
+ it('should handle pattern constraint', () => {
30
+ const prop = { pattern: '^[a-z]+$' };
31
+ const constraints = getConstraints(prop, false);
32
+ expect(constraints).toContain('pattern: /^[a-z]+$/');
33
+ });
34
+
35
+ it('should handle uniqueItems constraint', () => {
36
+ const prop = { uniqueItems: true };
37
+ const constraints = getConstraints(prop, false);
38
+ expect(constraints).toContain('uniqueItems: true');
39
+ });
40
+
41
+ it('should handle additionalProperties constraint', () => {
42
+ const prop = { additionalProperties: false };
43
+ const constraints = getConstraints(prop, false);
44
+ expect(constraints).toContain('additionalProperties: false');
45
+ });
46
+
47
+ it('should handle enum constraint', () => {
48
+ const prop = { enum: ['a', 'b', 'c'] };
49
+ const constraints = getConstraints(prop, false);
50
+ expect(constraints).toContain('enum: [a, b, c]');
51
+ });
52
+
53
+ it('should handle const constraint', () => {
54
+ const prop = { const: 'a' };
55
+ const constraints = getConstraints(prop, false);
56
+ expect(constraints).toContain('const: "a"');
57
+ });
58
+ });
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import loadSchema from '../../helpers/loadSchema';
7
+
8
+ describe('loadSchema', () => {
9
+ it('should load and parse a JSON file', () => {
10
+ const filePath = path.join(__dirname, '..', '__fixtures__', 'validateSchemas', 'circular-schema.json');
11
+ const schema = loadSchema(filePath);
12
+ expect(schema.title).toBe('Circular Schema');
13
+ });
14
+ });
@@ -0,0 +1,36 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import processSchema from '../../helpers/processSchema';
7
+
8
+ describe('processSchema', () => {
9
+ it('should bundle refs and return a merged schema', async () => {
10
+ const filePath = path.join(__dirname, '..', '__fixtures__', 'validateSchemas', 'main-schema-with-ref.json');
11
+ const mergedSchema = await processSchema(filePath);
12
+
13
+ expect(mergedSchema.title).toBe('Main Schema with Ref');
14
+ expect(mergedSchema.properties.component.$ref).toBeUndefined();
15
+ expect(mergedSchema.properties.component.type).toBe('object');
16
+ expect(mergedSchema.properties.component.properties.prop.type).toBe('string');
17
+ });
18
+
19
+ it('should handle circular references correctly', async () => {
20
+ const filePath = path.join(__dirname, '..', '__fixtures__', 'validateSchemas', 'circular-schema.json');
21
+ const mergedSchema = await processSchema(filePath);
22
+
23
+ expect(mergedSchema.title).toBe('Circular Schema');
24
+ expect(mergedSchema.properties.parent.$ref).toBe('#');
25
+ });
26
+
27
+ it('should handle multi-file circular references and produce a self-contained schema', async () => {
28
+ const filePath = path.join(__dirname, '..', '__fixtures__', 'validateSchemas', 'schema-A.json');
29
+ const mergedSchema = await processSchema(filePath);
30
+
31
+ expect(mergedSchema.title).toBe('Schema A');
32
+ expect(mergedSchema.properties.b.$ref).toBeUndefined();
33
+ expect(mergedSchema.properties.b.title).toBe('Schema B');
34
+ expect(mergedSchema.properties.b.properties.a.$ref).toBe('#');
35
+ });
36
+ });
@@ -0,0 +1,100 @@
1
+ /**
2
+ * @jest-environment node
3
+ */
4
+
5
+ import path from 'path';
6
+ import fs from 'fs';
7
+ import os from 'os';
8
+ import validateSchemas from '../validateSchemas';
9
+
10
+ describe('validateSchemas', () => {
11
+ let tmpDir;
12
+ let consoleErrorSpy;
13
+ let consoleLogSpy;
14
+
15
+ beforeEach(() => {
16
+ tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'schema-test-'));
17
+ consoleErrorSpy = jest.spyOn(console, 'error').mockImplementation(() => { });
18
+ consoleLogSpy = jest.spyOn(console, 'log').mockImplementation(() => { });
19
+ });
20
+
21
+ afterEach(() => {
22
+ fs.rmSync(tmpDir, { recursive: true, force: true });
23
+ jest.restoreAllMocks();
24
+ });
25
+
26
+ const writeSchema = (dir, fileName, content) => {
27
+ const filePath = path.join(dir, fileName);
28
+ fs.mkdirSync(path.dirname(filePath), { recursive: true });
29
+ fs.writeFileSync(filePath, JSON.stringify(content, null, 2));
30
+ };
31
+
32
+ const loadFixture = (fixtureName) => {
33
+ const fixturePath = path.resolve(__dirname, '__fixtures__', 'validateSchemas', fixtureName);
34
+ const schemaContent = fs.readFileSync(fixturePath, 'utf8');
35
+ return JSON.parse(schemaContent);
36
+ };
37
+
38
+ it('should return true when all schemas are valid', async () => {
39
+ const validSchema = loadFixture('valid-schema.json');
40
+ writeSchema(tmpDir, 'valid-schema.json', validSchema);
41
+
42
+ const result = await validateSchemas(tmpDir);
43
+ expect(result).toBe(true);
44
+ expect(consoleLogSpy).toHaveBeenCalledWith('✅ Schema valid-schema.json produced a valid example.');
45
+ });
46
+
47
+ it('should return false if an example fails validation', async () => {
48
+ const invalidExampleSchema = loadFixture('invalid-example-schema.json');
49
+ writeSchema(tmpDir, 'invalid-example-schema.json', invalidExampleSchema);
50
+
51
+ const result = await validateSchemas(tmpDir);
52
+ expect(result).toBe(false);
53
+ expect(consoleErrorSpy).toHaveBeenCalledWith('❌ Schema invalid-example-schema.json example data failed validation:');
54
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.arrayContaining([
55
+ expect.objectContaining({
56
+ instancePath: '/age',
57
+ keyword: 'type',
58
+ message: 'must be number'
59
+ })
60
+ ]));
61
+ });
62
+
63
+ it('should fail validation for missing required property', async () => {
64
+ const noValidExampleSchema = loadFixture('no-example-schema.json');
65
+ writeSchema(tmpDir, 'no-valid-example-schema.json', noValidExampleSchema);
66
+
67
+ const result = await validateSchemas(tmpDir);
68
+ expect(result).toBe(false);
69
+ expect(consoleErrorSpy).toHaveBeenCalledWith('❌ Schema no-valid-example-schema.json example data failed validation:');
70
+ expect(consoleErrorSpy).toHaveBeenCalledWith(expect.arrayContaining([
71
+ expect.objectContaining({
72
+ keyword: 'required',
73
+ params: { missingProperty: 'some_prop' },
74
+ })
75
+ ]));
76
+ });
77
+
78
+ it('should handle schemas with $refs correctly', async () => {
79
+ const componentSchema = loadFixture(path.join('components', 'referenced.json'));
80
+ const mainSchema = loadFixture('main-schema-with-ref.json');
81
+
82
+ writeSchema(path.join(tmpDir, 'components'), 'referenced.json', componentSchema);
83
+ writeSchema(tmpDir, 'main-schema-with-ref.json', mainSchema);
84
+
85
+ const result = await validateSchemas(tmpDir);
86
+ expect(result).toBe(true);
87
+ expect(consoleLogSpy).toHaveBeenCalledWith('✅ Schema main-schema-with-ref.json produced a valid example.');
88
+ });
89
+
90
+ it('should reject if a referenced schema is missing', async () => {
91
+ const mainSchema = loadFixture('main-schema-with-missing-ref.json');
92
+ writeSchema(tmpDir, 'main-schema-with-missing-ref.json', mainSchema);
93
+
94
+ const expectedErrorPath = path.join(tmpDir, 'non-existent-component.json');
95
+ await expect(validateSchemas(tmpDir)).rejects.toThrow(expect.objectContaining({
96
+ message: expect.stringContaining(`Error opening file ${expectedErrorPath}`)
97
+ }));
98
+ });
99
+
100
+ });
@@ -4,7 +4,7 @@ import buildExampleFromSchema from '../helpers/buildExampleFromSchema';
4
4
 
5
5
  export default function ExampleDataLayer({ schema }) {
6
6
  // 1. Identify properties that need to be reset (cleared) first
7
- const propertiesToReset = findComplexPropertiesToReset(schema || {});
7
+ const clearableProperties = findClearableProperties(schema || {});
8
8
 
9
9
  // 2. Build the main example data
10
10
  const example = buildExampleFromSchema(schema || {});
@@ -12,11 +12,14 @@ export default function ExampleDataLayer({ schema }) {
12
12
  // 3. Construct the code snippet
13
13
  let codeSnippet = '';
14
14
 
15
+ // Filter properties to reset to only those present in the example
16
+ const propertiesToClear = clearableProperties.filter(prop => prop in example);
17
+
15
18
  // If there are properties to reset, push them as null first
16
- if (propertiesToReset.length > 0)
19
+ if (propertiesToClear.length > 0)
17
20
  {
18
21
  const resetObject = {};
19
- propertiesToReset.forEach(prop => {
22
+ propertiesToClear.forEach(prop => {
20
23
  resetObject[prop] = null;
21
24
  });
22
25
  codeSnippet += `window.dataLayer.push(${JSON.stringify(resetObject, null, 2)});\n`;
@@ -28,11 +31,10 @@ export default function ExampleDataLayer({ schema }) {
28
31
  return <CodeBlock language="javascript">{codeSnippet}</CodeBlock>
29
32
  };
30
33
 
31
- const findComplexPropertiesToReset = (schema) => {
34
+ export const findClearableProperties = (schema) => {
32
35
  if (!schema || !schema.properties) return [];
33
36
 
34
37
  return Object.entries(schema.properties)
35
38
  .filter(([key, definition]) => definition["x-gtm-clear"] === true)
36
39
  .map(([key]) => key);
37
40
  }
38
-
@@ -1,19 +1,14 @@
1
+ import React from 'react';
1
2
  import SchemaRows from './SchemaRows';
3
+ import TableHeader from './TableHeader';
4
+ import { getConstraints } from '../helpers/getConstraints';
2
5
 
3
6
  export default function PropertiesTable({ schema }) {
4
7
 
5
8
  return <table>
6
- <thead>
7
- <tr>
8
- <th width="20%">Property</th>
9
- <th width="15%">Type</th>
10
- <th width="10%">Req</th>
11
- <th with="15%">Examples</th>
12
- <th>Description</th>
13
- </tr>
14
- </thead>
9
+ <TableHeader />
15
10
  <tbody>
16
- <SchemaRows properties={schema.properties} requiredList={schema.required} />
11
+ <SchemaRows properties={schema.properties} requiredList={schema.required} getConstraints={getConstraints} />
17
12
  </tbody>
18
13
  </table>
19
14
  }
@@ -0,0 +1,74 @@
1
+ import React from 'react';
2
+ import clsx from 'clsx';
3
+
4
+ // Helper to format the property type
5
+ const getPropertyType = (type) => {
6
+ return Array.isArray(type) ? type.join(' | ') : type;
7
+ };
8
+
9
+ // Helper to format examples
10
+ const formatExamples = (examples) => {
11
+ if (!examples)
12
+ {
13
+ return '';
14
+ }
15
+ return examples
16
+ .map((example) =>
17
+ typeof example === 'object' ? JSON.stringify(example) : example
18
+ )
19
+ .join(', ');
20
+ };
21
+
22
+ const PropertyRow = ({ propertyKey, prop, requiredList, getConstraints }) => {
23
+ const isReq = requiredList.includes(propertyKey);
24
+ const constraints = getConstraints(prop, isReq);
25
+
26
+ const childProperties = prop.properties || (prop.items && prop.items.properties);
27
+ const hasChildren = childProperties && Object.keys(childProperties).length > 0;
28
+
29
+ const isObject = prop.type === 'object';
30
+ const isArrayOfObjects = prop.type === 'array' && prop.items && prop.items.type === 'object';
31
+
32
+ if ((isObject || isArrayOfObjects) && !hasChildren)
33
+ {
34
+ return null;
35
+ }
36
+
37
+ const numRows = Math.max(1, constraints.length);
38
+ const [firstConstraint, ...remainingConstraints] = constraints;
39
+
40
+ return (
41
+ <React.Fragment>
42
+ <tr className={clsx(isReq && 'required-row')}>
43
+ <td rowSpan={numRows}>
44
+ <strong>{propertyKey}</strong>
45
+ {hasChildren && <span style={{ fontSize: '0.8em', marginLeft: '5px' }}>⤵</span>}
46
+ </td>
47
+ <td rowSpan={numRows}><code>{getPropertyType(prop.type)}</code></td>
48
+ <td>
49
+ {firstConstraint && (
50
+ <code className={clsx('constraint-code', firstConstraint === 'required' && 'required')}>
51
+ {firstConstraint}
52
+ </code>
53
+ )}
54
+ </td>
55
+ <td rowSpan={numRows}>
56
+ {formatExamples(prop.examples)}
57
+ </td>
58
+ <td rowSpan={numRows}>{prop.description || ''}</td>
59
+ </tr>
60
+
61
+ {remainingConstraints.map((constraint, index) => (
62
+ <tr className={clsx(isReq && 'required-row')} key={`${propertyKey}-constraint-${index}`}>
63
+ <td>
64
+ <code className={clsx('constraint-code', constraint === 'required' && 'required')}>
65
+ {constraint}
66
+ </code>
67
+ </td>
68
+ </tr>
69
+ ))}
70
+ </React.Fragment>
71
+ );
72
+ };
73
+
74
+ export default PropertyRow;
@@ -1,10 +1,11 @@
1
+ import React from 'react';
1
2
  import CodeBlock from '@theme/CodeBlock';
2
3
 
3
4
  export default function SchemaJsonViewer({ schema }) {
4
5
 
5
6
  return (
6
- <details>
7
+ <details className="schema-json-viewer">
7
8
  <summary>View Raw JSON Schema</summary>
8
9
  <CodeBlock language="json">{JSON.stringify(schema, null, 2)}</CodeBlock>
9
10
  </details>);
10
- }
11
+ }
@@ -0,0 +1,28 @@
1
+ .required-row {
2
+ background-color: rgba(255, 0, 0, 0.05);
3
+ }
4
+
5
+ .constraint-code {
6
+ white-space: pre-wrap;
7
+ margin-right: 4px;
8
+ display: inline-block;
9
+ margin-bottom: 4px;
10
+ }
11
+
12
+ .constraint-code.required {
13
+ font-weight: bold;
14
+ color: #c7254e;
15
+ /* A reddish color */
16
+ background-color: #f9f2f4;
17
+ padding: 2px 4px;
18
+ border-radius: 4px;
19
+ }
20
+
21
+ .nested-table-container {
22
+ padding-left: 20px;
23
+ border-left: 4px solid #eee;
24
+ }
25
+
26
+ .schema-json-viewer {
27
+ margin-bottom: 1em;
28
+ }
@@ -1,71 +1,43 @@
1
1
  import React from 'react';
2
+ import './SchemaRows.css';
3
+ import PropertyRow from './PropertyRow';
4
+ import TableHeader from './TableHeader';
2
5
 
3
- const SchemaRows = ({ properties, requiredList = [], level = 0 }) => {
6
+ const SchemaRows = ({ properties, requiredList = [], level = 0, getConstraints }) => {
4
7
  return (
5
8
  <>
6
9
  {Object.entries(properties).map(([key, prop]) => {
7
- const isReq = requiredList.includes(key);
8
-
9
- // 1. Calculate if it has children (Same as before)
10
- const hasChildren =
11
- (prop.type === 'object' &&
12
- prop.properties &&
13
- Object.keys(prop.properties).length > 0) ||
14
- (prop.type === 'array' &&
15
- prop.items &&
16
- prop.items.properties &&
17
- Object.keys(prop.items.properties).length > 0);
18
-
19
- const isObject = prop.type === 'object';
20
- const isArrayOfObjects = prop.type === 'array' && prop.items && prop.items.type === 'object';
21
-
22
- if ((isObject || isArrayOfObjects) && !hasChildren)
23
- {
24
- return null;
25
- }
10
+ const childProperties = prop.properties || (prop.items && prop.items.properties);
11
+ const hasChildren = childProperties && Object.keys(childProperties).length > 0;
26
12
 
27
13
  return (
28
14
  <React.Fragment key={key}>
29
- {/* Main property row */}
30
- <tr style={{ backgroundColor: isReq ? 'rgba(255,0,0,0.05)' : 'transparent' }}>
31
- <td>
32
- <strong>{key}</strong>
33
- {hasChildren && <span style={{ fontSize: '0.8em', marginLeft: '5px' }}>⤵</span>}
34
- </td>
35
- <td><code>{Array.isArray(prop.type) ? prop.type.join('|') : prop.type}</code></td>
36
- <td style={{ textAlign: 'center' }}>{isReq ? '✅' : ''}</td>
37
- <td>{prop.examples ? prop.examples.join(', ') : ''}</td>
38
- <td>{prop.description || ''}</td>
39
- </tr>
40
-
41
- {/* Nested children rendered immediately after parent */}
15
+ <PropertyRow
16
+ propertyKey={key}
17
+ prop={prop}
18
+ requiredList={requiredList}
19
+ level={level}
20
+ getConstraints={getConstraints}
21
+ />
42
22
  {hasChildren && (
43
- <tr>
44
- <td colSpan="5" style={{ paddingLeft: '20px', borderLeft: '4px solid #eee' }}>
23
+ <tr key={`${key}-nested`}>
24
+ <td colSpan="5" className="nested-table-container">
45
25
  <strong>{prop.type === 'array' ? `${key} [ ]` : `${key} { }`}</strong>
46
26
  <table style={{ width: '100%', marginTop: '5px' }}>
47
- <thead>
48
- <tr>
49
- <th width="20%">Property</th>
50
- <th width="15%">Type</th>
51
- <th width="10%">Req</th>
52
- <th width="15%">Examples</th>
53
- <th>Description</th>
54
- </tr>
55
- </thead>
27
+ <TableHeader />
56
28
  <tbody>
57
29
  <SchemaRows
58
30
  properties={prop.type === 'object' ? prop.properties : prop.items.properties}
59
31
  requiredList={prop.type === 'object' ? prop.required || [] : prop.items.required || []}
60
32
  level={level + 1}
33
+ getConstraints={getConstraints}
61
34
  />
62
35
  </tbody>
63
36
  </table>
64
37
  </td>
65
38
  </tr>
66
- )
67
- }
68
- </React.Fragment >
39
+ )}
40
+ </React.Fragment>
69
41
  );
70
42
  })}
71
43
  </>
@@ -1,3 +1,5 @@
1
+ import React from 'react';
2
+ import Heading from '@theme/Heading';
1
3
  import ExampleDataLayer from './ExampleDataLayer';
2
4
  import PropertiesTable from './PropertiesTable';
3
5
 
@@ -9,10 +11,10 @@ export default function SchemaViewer({ schema }) {
9
11
 
10
12
  return (
11
13
  <div>
12
- <h2>DataLayer Example</h2>
14
+ <Heading as="h2">DataLayer Example</Heading>
13
15
  <ExampleDataLayer schema={schema} />
14
16
 
15
- <h2>Event Properties</h2>
17
+ <Heading as="h2">Event Properties</Heading>
16
18
  <PropertiesTable schema={schema} />
17
19
  </div>
18
20
  );
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+
3
+ export default function TableHeader() {
4
+ return (
5
+ <thead>
6
+ <tr>
7
+ <th width="20%">Property</th>
8
+ <th width="15%">Type</th>
9
+ <th width="25%">Constraints</th>
10
+ <th width="15%">Examples</th>
11
+ <th>Description</th>
12
+ </tr>
13
+ </thead>
14
+ );
15
+ }
@@ -1,12 +1,16 @@
1
- import $RefParser from "@apidevtools/json-schema-ref-parser";
2
- import mergeJsonSchema from "json-schema-merge-allof";
3
1
  import fs from 'fs';
4
2
  import path from 'path';
3
+ import loadSchema from './helpers/loadSchema';
4
+ import processSchema from './helpers/processSchema';
5
+ import MdxTemplate from './helpers/mdx-template.js';
5
6
 
6
- export default async function generateEventDocs() {
7
+ export default async function generateEventDocs(options) {
8
+ const { organizationName, projectName, siteDir } = options || {};
9
+ const baseEditUrl = `https://github.com/${organizationName}/${projectName}/edit/main`;
7
10
  // CONFIGURATION
8
- const SCHEMA_DIR = 'schemas'; // Where your JSON files are
9
- const OUTPUT_DIR = 'docs/events'; // Where MDX goes
11
+ const SCHEMA_DIR = path.join(siteDir, 'static/schemas'); // Where your JSON files are
12
+ const OUTPUT_DIR = path.join(siteDir, 'docs/events'); // Where MDX goes
13
+ const PARTIALS_DIR = path.join(siteDir, 'docs/partials'); // Where your partials are
10
14
 
11
15
  // Ensure output dir exists
12
16
  if (!fs.existsSync(OUTPUT_DIR))
@@ -22,41 +26,38 @@ export default async function generateEventDocs() {
22
26
  for (const file of files)
23
27
  {
24
28
  const filePath = path.join(SCHEMA_DIR, file);
25
- const rawContent = fs.readFileSync(filePath, 'utf-8');
26
- const schema = JSON.parse(rawContent);
29
+ const schema = loadSchema(filePath);
30
+ const mergedSchema = await processSchema(filePath);
31
+ const eventName = file.replace('.json', '');
27
32
 
28
- // First, dereference all $ref properties
29
- const clonedSchema = await $RefParser.dereference(filePath, {
30
- mutateInputSchema: false, dereference: {
31
- circular: 'ignore'
32
- }
33
- });
34
-
35
- // Then merge allOf properties
36
- const mergedSchema = mergeJsonSchema(clonedSchema, {
37
- resolvers: {
38
- defaultResolver: mergeJsonSchema.options.resolvers.title
39
- }
40
- });
33
+ // Check for partials
34
+ const topPartialPath = path.join(PARTIALS_DIR, `${eventName}.mdx`);
35
+ const bottomPartialPath = path.join(PARTIALS_DIR, `${eventName}_bottom.mdx`);
41
36
 
42
- // Define the MDX Content
43
- // We embed the JSON directly into the file to avoid Webpack import issues
44
- const mdxContent = `---
45
- title: ${schema.title}
46
- description: ${schema.description}
47
- sidebar_label: ${schema.title}
48
- ---
37
+ let topPartialImport = '';
38
+ let topPartialComponent = '';
39
+ if (fs.existsSync(topPartialPath)) {
40
+ topPartialImport = `import TopPartial from '@site/docs/partials/${eventName}.mdx';`;
41
+ topPartialComponent = '<TopPartial />';
42
+ }
49
43
 
50
- import SchemaViewer from '@theme/SchemaViewer';
51
- import SchemaJsonViewer from '@theme/SchemaJsonViewer';
44
+ let bottomPartialImport = '';
45
+ let bottomPartialComponent = '';
46
+ if (fs.existsSync(bottomPartialPath)) {
47
+ bottomPartialImport = `import BottomPartial from '@site/docs/partials/${eventName}_bottom.mdx';`;
48
+ bottomPartialComponent = '<BottomPartial />';
49
+ }
52
50
 
53
- # ${schema.title}
54
-
55
- ${schema.description}
56
-
57
- <SchemaViewer schema={${JSON.stringify(mergedSchema)}} />
58
- <SchemaJsonViewer schema={${JSON.stringify(schema)}} />
59
- `;
51
+ const mdxContent = MdxTemplate({
52
+ schema,
53
+ mergedSchema,
54
+ baseEditUrl,
55
+ file,
56
+ topPartialImport,
57
+ bottomPartialImport,
58
+ topPartialComponent,
59
+ bottomPartialComponent
60
+ });
60
61
 
61
62
  // Write the .mdx file
62
63
  const outputFilename = file.replace('.json', '.mdx');
@@ -28,7 +28,7 @@ const buildExampleFromSchema = (schema) => {
28
28
  return obj;
29
29
  }
30
30
  // Object with no properties defined
31
- return {};
31
+ return undefined;
32
32
  }
33
33
 
34
34
  if (type === 'array')
@@ -43,7 +43,7 @@ const buildExampleFromSchema = (schema) => {
43
43
  }
44
44
  }
45
45
  // Empty array or array of undefined items
46
- return [];
46
+ return undefined;
47
47
  }
48
48
 
49
49
  switch (type)
@@ -80,4 +80,4 @@ const buildExampleFromSchema = (schema) => {
80
80
 
81
81
  return {};
82
82
  }
83
- export default buildExampleFromSchema;
83
+ export default buildExampleFromSchema;