diff --git a/README.md b/README.md index a2c21815..3b6072c6 100644 --- a/README.md +++ b/README.md @@ -40,6 +40,35 @@ With `node` installed, run by doing the following: node build --options= --output= ``` +#### Versioned Options in the CLI + +If wanting to add versioning support in your build, you must create a JSON file with the following data structure (replace example values with any mock values): + +``` +{ + "active": { + "apiVersion": "2.0", + "resourceVersion": "2023-02-14" + }, + "rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2", + "resourceVersions": ["2022-09-09", "2022-10-18", "2023-02-14"] +} +``` + +After doing so, run the build much the same as above but with the following option added: +Note: the path to the version data option JSON file should be referenced in relation to the `redoc/cli` directory + +``` +--options.versionData= +``` + +Such as: +Note: this is referencing a JSON file in the root directory + +``` +node build --options.versionData=../version-data.json +``` + ### Releasing The Redoc React component and the Redoc CLI have 2 separate release processes. Because the Redoc CLI pulls its version of Redoc from GitHub, build artifacts are included in the version tag being installed. diff --git a/cli/__test__/build/configRedoc/index.test.ts b/cli/__test__/build/configRedoc/index.test.ts index 854b4cf2..dda8ad03 100644 --- a/cli/__test__/build/configRedoc/index.test.ts +++ b/cli/__test__/build/configRedoc/index.test.ts @@ -27,4 +27,29 @@ describe('build', () => { expect(result).toContain('Found .redocly.yaml and using features.openapi options'); expect(result).toContain('bundled successfully'); }); + + it('should ingest version data from json file', () => { + const pathToTestData = '__test__/data/version-data.json'; + const r = spawnSync( + 'ts-node', + [ + '../../../index.ts', + 'build', + ' ../../../../demo/openapi.yaml', + '--output=redoc-test.html', + `--options.versionData=${pathToTestData}`, + ], + { + cwd: __dirname, + shell: true, + }, + ); + + const out = r.stdout.toString('utf-8'); + const err = r.stderr.toString('utf-8'); + const result = `${out}\n${err}`; + + expect(result).toContain(`Found ${pathToTestData} and using version data.`); + expect(result).toContain('bundled successfully'); + }); }); diff --git a/cli/__test__/data/version-data.json b/cli/__test__/data/version-data.json new file mode 100644 index 00000000..76273100 --- /dev/null +++ b/cli/__test__/data/version-data.json @@ -0,0 +1,8 @@ +{ + "active": { + "apiVersion": "2.0", + "resourceVersion": "2023-02-14" + }, + "rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2", + "resourceVersions": ["2022-09-09", "2022-10-18", "2028-02-14"] +} diff --git a/cli/index.ts b/cli/index.ts index bbfcbcf8..513c386f 100644 --- a/cli/index.ts +++ b/cli/index.ts @@ -439,6 +439,22 @@ function handleError(error: Error) { function getObjectOrJSON(options) { switch (typeof options) { case 'object': + if (options?.versionData) { + const { versionData: versionPath } = options; + const versionFilePath = resolve(__dirname, versionPath); + try { + if (existsSync(versionFilePath) && lstatSync(versionFilePath).isFile()) { + const versionData = JSON.parse(readFileSync(versionFilePath, 'utf-8')); + options.versionData = versionData; + console.log(`Found ${versionPath} and using version data.`); + } + } catch (e) { + console.log( + `Encountered error:\n\n${versionPath}\n\nis not a file with a valid JSON object.`, + ); + handleError(e); + } + } return options; case 'string': try { diff --git a/e2e/integration/menu.e2e.ts b/e2e/integration/menu.e2e.ts index b5873db7..ced1198c 100644 --- a/e2e/integration/menu.e2e.ts +++ b/e2e/integration/menu.e2e.ts @@ -4,7 +4,7 @@ describe('Menu', () => { }); it('should have valid items count', () => { - cy.get('.menu-content').find('li').should('have.length', 35); + cy.get('.menu-content').find('li').not('[role="option"]').should('have.length', 35); }); it('should have a back button', () => { diff --git a/src/components/Redoc/Redoc.tsx b/src/components/Redoc/Redoc.tsx index cc70ec88..914ff530 100644 --- a/src/components/Redoc/Redoc.tsx +++ b/src/components/Redoc/Redoc.tsx @@ -21,6 +21,7 @@ import { import { SearchBox } from '../SearchBox/SearchBox'; import { StoreProvider } from '../StoreBuilder'; +import { VersionSelector } from '../VersionSelector'; export interface RedocProps { store: AppStore; @@ -69,6 +70,9 @@ export class Redoc extends React.Component { /> )) || null} + {options.versionData && typeof options.versionData == 'object' && ( + + )} diff --git a/src/components/VersionSelector/VersionSelector.tsx b/src/components/VersionSelector/VersionSelector.tsx index 73e429f9..9580e927 100644 --- a/src/components/VersionSelector/VersionSelector.tsx +++ b/src/components/VersionSelector/VersionSelector.tsx @@ -9,6 +9,7 @@ import { StyledMenuList, StyledDisplay, StyledDropdown, + StyledSelected, } from './styled.elements'; import { Option } from './Option'; import { VersionSelectorProps } from './types'; @@ -42,9 +43,7 @@ const VersionSelectorComponent = ({ {description && {description}} setOpen(!open)}> -
-
{resourceVersions[selectedIdx]}
-
+ {resourceVersions[selectedIdx]}
diff --git a/src/components/VersionSelector/styled.elements.ts b/src/components/VersionSelector/styled.elements.ts index bfb4f71d..25b16105 100644 --- a/src/components/VersionSelector/styled.elements.ts +++ b/src/components/VersionSelector/styled.elements.ts @@ -10,7 +10,7 @@ const transitionDuration = { slower: 300, } as const; -export const ArrowIcon = styled(ArrowSvg)` +export const ArrowIcon = styled(ArrowSvg)<{ open: boolean }>` position: absolute; pointer-events: none; z-index: 1; @@ -101,12 +101,17 @@ export const StyledMenuList = styled.ul` `; export const StyledDisplay = styled.div` + width: 100%; display: grid; grid-template-columns: 1fr 16px; gap: 6px; padding: 0 4px 0 12px; `; +export const StyledSelected = styled.div` + display: flex; +`; + export const disabledOptionStyle = css` cursor: not-allowed; color: ${palette.gray.base}; diff --git a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap index b845aad4..bbc5db2a 100644 --- a/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/DiscriminatorDropdown.test.tsx.snap @@ -354,6 +354,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog/properties/packSize", @@ -687,6 +688,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog/properties/type", @@ -1007,6 +1009,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog", @@ -1389,6 +1392,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Cat/properties/type", @@ -1734,6 +1738,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Cat/properties/packSize", @@ -2050,6 +2055,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Cat", @@ -2391,6 +2397,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Pet", @@ -2762,6 +2769,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog/properties/packSize", @@ -3095,6 +3103,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog/properties/type", @@ -3415,6 +3424,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView }, "unstable_ignoreMimeParameters": false, "untrustedSpec": false, + "versionData": undefined, }, "pattern": undefined, "pointer": "#/components/schemas/Dog", diff --git a/src/components/__tests__/__snapshots__/VersionSelector.test.tsx.snap b/src/components/__tests__/__snapshots__/VersionSelector.test.tsx.snap index ab7d9f66..bf923da1 100644 --- a/src/components/__tests__/__snapshots__/VersionSelector.test.tsx.snap +++ b/src/components/__tests__/__snapshots__/VersionSelector.test.tsx.snap @@ -17,12 +17,12 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = ` class="sc-hKFxyN hYrDYQ" >
-
-
- 2023-01-01 -
+
+ 2023-01-01
@@ -54,44 +54,44 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = ` >
  • 2021-09-09
  • 2022-10-18
  • 2023-01-01 diff --git a/src/services/RedocNormalizedOptions.ts b/src/services/RedocNormalizedOptions.ts index 0ae2ff7e..ce263fe1 100644 --- a/src/services/RedocNormalizedOptions.ts +++ b/src/services/RedocNormalizedOptions.ts @@ -61,6 +61,16 @@ export interface RedocRawOptions { backNavigationPath?: string; ignoreIncompatibleTypes?: boolean | string; siteTitle?: string; + versionData?: string; +} + +export interface VersionData { + active: { + apiVersion: string; + resourceVersion: string; + }; + rootUrl: string; + resourceVersions: string[]; } export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean { @@ -269,6 +279,7 @@ export class RedocNormalizedOptions { backNavigationPath?: string; ignoreIncompatibleTypes: boolean; siteTitle?: string; + versionData?: string | VersionData; constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) { raw = { ...defaults, ...raw }; @@ -351,5 +362,6 @@ export class RedocNormalizedOptions { this.backNavigationPath = raw.backNavigationPath; this.ignoreIncompatibleTypes = argValueToBoolean(raw.ignoreIncompatibleTypes); this.siteTitle = raw.siteTitle; + this.versionData = raw.versionData; } } diff --git a/version-data.json b/version-data.json new file mode 100644 index 00000000..c298d012 --- /dev/null +++ b/version-data.json @@ -0,0 +1,8 @@ +{ + "active": { + "apiVersion": "2.0", + "resourceVersion": "2023-02-14" + }, + "rootUrl": "https://mongodb.com/docs/atlas/reference/api-resources-spec/v2", + "resourceVersions": ["2022-09-09", "2022-10-18", "2023-02-14"] +}