mirror of
https://github.com/Redocly/redoc.git
synced 2025-07-31 02:19:47 +03:00
DOP-3505: Redoc CLI ingests version data from json file (#15)
This commit is contained in:
parent
2d61688fcc
commit
da330e9178
29
README.md
29
README.md
|
@ -40,6 +40,35 @@ With `node` installed, run by doing the following:
|
||||||
node <path/to/redoc/cli/index.js> build <path/to/spec/file/or/url> --options=<path/to/options.json> --output=<path/to/custom/output/file/name.html>
|
node <path/to/redoc/cli/index.js> build <path/to/spec/file/or/url> --options=<path/to/options.json> --output=<path/to/custom/output/file/name.html>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### 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=<path/to/mock/data/file.json/from/cli/directory>
|
||||||
|
```
|
||||||
|
|
||||||
|
Such as:
|
||||||
|
Note: this is referencing a JSON file in the root directory
|
||||||
|
|
||||||
|
```
|
||||||
|
node <path/to/redoc/cli/index.js> build <path/to/spec/file/or/url> --options.versionData=../version-data.json
|
||||||
|
```
|
||||||
|
|
||||||
### Releasing
|
### 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.
|
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.
|
||||||
|
|
|
@ -27,4 +27,29 @@ describe('build', () => {
|
||||||
expect(result).toContain('Found .redocly.yaml and using features.openapi options');
|
expect(result).toContain('Found .redocly.yaml and using features.openapi options');
|
||||||
expect(result).toContain('bundled successfully');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
8
cli/__test__/data/version-data.json
Normal file
8
cli/__test__/data/version-data.json
Normal file
|
@ -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"]
|
||||||
|
}
|
16
cli/index.ts
16
cli/index.ts
|
@ -439,6 +439,22 @@ function handleError(error: Error) {
|
||||||
function getObjectOrJSON(options) {
|
function getObjectOrJSON(options) {
|
||||||
switch (typeof options) {
|
switch (typeof options) {
|
||||||
case 'object':
|
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;
|
return options;
|
||||||
case 'string':
|
case 'string':
|
||||||
try {
|
try {
|
||||||
|
|
|
@ -4,7 +4,7 @@ describe('Menu', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should have valid items count', () => {
|
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', () => {
|
it('should have a back button', () => {
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
|
|
||||||
import { SearchBox } from '../SearchBox/SearchBox';
|
import { SearchBox } from '../SearchBox/SearchBox';
|
||||||
import { StoreProvider } from '../StoreBuilder';
|
import { StoreProvider } from '../StoreBuilder';
|
||||||
|
import { VersionSelector } from '../VersionSelector';
|
||||||
|
|
||||||
export interface RedocProps {
|
export interface RedocProps {
|
||||||
store: AppStore;
|
store: AppStore;
|
||||||
|
@ -69,6 +70,9 @@ export class Redoc extends React.Component<RedocProps> {
|
||||||
/>
|
/>
|
||||||
)) ||
|
)) ||
|
||||||
null}
|
null}
|
||||||
|
{options.versionData && typeof options.versionData == 'object' && (
|
||||||
|
<VersionSelector {...options.versionData} />
|
||||||
|
)}
|
||||||
<SideMenu menu={menu} />
|
<SideMenu menu={menu} />
|
||||||
</StickyResponsiveSidebar>
|
</StickyResponsiveSidebar>
|
||||||
<ApiContentWrap className="api-content">
|
<ApiContentWrap className="api-content">
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {
|
||||||
StyledMenuList,
|
StyledMenuList,
|
||||||
StyledDisplay,
|
StyledDisplay,
|
||||||
StyledDropdown,
|
StyledDropdown,
|
||||||
|
StyledSelected,
|
||||||
} from './styled.elements';
|
} from './styled.elements';
|
||||||
import { Option } from './Option';
|
import { Option } from './Option';
|
||||||
import { VersionSelectorProps } from './types';
|
import { VersionSelectorProps } from './types';
|
||||||
|
@ -42,9 +43,7 @@ const VersionSelectorComponent = ({
|
||||||
{description && <StyledDescription>{description}</StyledDescription>}
|
{description && <StyledDescription>{description}</StyledDescription>}
|
||||||
<StyledButton onClick={() => setOpen(!open)}>
|
<StyledButton onClick={() => setOpen(!open)}>
|
||||||
<StyledDisplay>
|
<StyledDisplay>
|
||||||
<div>
|
<StyledSelected>{resourceVersions[selectedIdx]}</StyledSelected>
|
||||||
<div>{resourceVersions[selectedIdx]}</div>
|
|
||||||
</div>
|
|
||||||
<ArrowIcon open={open} />
|
<ArrowIcon open={open} />
|
||||||
</StyledDisplay>
|
</StyledDisplay>
|
||||||
</StyledButton>
|
</StyledButton>
|
||||||
|
|
|
@ -10,7 +10,7 @@ const transitionDuration = {
|
||||||
slower: 300,
|
slower: 300,
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
export const ArrowIcon = styled(ArrowSvg)`
|
export const ArrowIcon = styled(ArrowSvg)<{ open: boolean }>`
|
||||||
position: absolute;
|
position: absolute;
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
|
@ -101,12 +101,17 @@ export const StyledMenuList = styled.ul`
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const StyledDisplay = styled.div`
|
export const StyledDisplay = styled.div`
|
||||||
|
width: 100%;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 16px;
|
grid-template-columns: 1fr 16px;
|
||||||
gap: 6px;
|
gap: 6px;
|
||||||
padding: 0 4px 0 12px;
|
padding: 0 4px 0 12px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const StyledSelected = styled.div`
|
||||||
|
display: flex;
|
||||||
|
`;
|
||||||
|
|
||||||
export const disabledOptionStyle = css`
|
export const disabledOptionStyle = css`
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
color: ${palette.gray.base};
|
color: ${palette.gray.base};
|
||||||
|
|
|
@ -354,6 +354,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||||
|
@ -687,6 +688,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog/properties/type",
|
"pointer": "#/components/schemas/Dog/properties/type",
|
||||||
|
@ -1007,6 +1009,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog",
|
"pointer": "#/components/schemas/Dog",
|
||||||
|
@ -1389,6 +1392,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Cat/properties/type",
|
"pointer": "#/components/schemas/Cat/properties/type",
|
||||||
|
@ -1734,6 +1738,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Cat/properties/packSize",
|
"pointer": "#/components/schemas/Cat/properties/packSize",
|
||||||
|
@ -2050,6 +2055,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Cat",
|
"pointer": "#/components/schemas/Cat",
|
||||||
|
@ -2391,6 +2397,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Pet",
|
"pointer": "#/components/schemas/Pet",
|
||||||
|
@ -2762,6 +2769,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog/properties/packSize",
|
"pointer": "#/components/schemas/Dog/properties/packSize",
|
||||||
|
@ -3095,6 +3103,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog/properties/type",
|
"pointer": "#/components/schemas/Dog/properties/type",
|
||||||
|
@ -3415,6 +3424,7 @@ exports[`Components SchemaView discriminator should correctly render SchemaView
|
||||||
},
|
},
|
||||||
"unstable_ignoreMimeParameters": false,
|
"unstable_ignoreMimeParameters": false,
|
||||||
"untrustedSpec": false,
|
"untrustedSpec": false,
|
||||||
|
"versionData": undefined,
|
||||||
},
|
},
|
||||||
"pattern": undefined,
|
"pattern": undefined,
|
||||||
"pointer": "#/components/schemas/Dog",
|
"pointer": "#/components/schemas/Dog",
|
||||||
|
|
|
@ -17,12 +17,12 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
||||||
class="sc-hKFxyN hYrDYQ"
|
class="sc-hKFxyN hYrDYQ"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="sc-iCoGMd fgtoGu"
|
class="sc-iCoGMd gojxeT"
|
||||||
>
|
>
|
||||||
<div>
|
<div
|
||||||
<div>
|
class="sc-fujyAs hQJiDC"
|
||||||
2023-01-01
|
>
|
||||||
</div>
|
2023-01-01
|
||||||
</div>
|
</div>
|
||||||
<svg
|
<svg
|
||||||
fill="none"
|
fill="none"
|
||||||
|
@ -44,7 +44,7 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
aria-labelledby="View a different version of documentation."
|
aria-labelledby="View a different version of documentation."
|
||||||
class="sc-jrsJWt ofjNY"
|
class="sc-kEqXSa litKaz"
|
||||||
role="listbox"
|
role="listbox"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
>
|
>
|
||||||
|
@ -54,44 +54,44 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
||||||
>
|
>
|
||||||
<li
|
<li
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="sc-fujyAs iIVhNL"
|
class="sc-pNWdM glxGCd"
|
||||||
role="option"
|
role="option"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="sc-kEqXSa cBTyJc"
|
class="sc-iqAclL dXUzZL"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
class="sc-pNWdM irvinq"
|
class="sc-jrsJWt hDLwjI"
|
||||||
>
|
>
|
||||||
2021-09-09
|
2021-09-09
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
aria-selected="false"
|
aria-selected="false"
|
||||||
class="sc-fujyAs iIVhNL"
|
class="sc-pNWdM glxGCd"
|
||||||
role="option"
|
role="option"
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<span
|
<span
|
||||||
class="sc-kEqXSa cBTyJc"
|
class="sc-iqAclL dXUzZL"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
class="sc-pNWdM irvinq"
|
class="sc-jrsJWt hDLwjI"
|
||||||
>
|
>
|
||||||
2022-10-18
|
2022-10-18
|
||||||
</span>
|
</span>
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li
|
||||||
aria-selected="true"
|
aria-selected="true"
|
||||||
class="sc-fujyAs Ywdfd"
|
class="sc-pNWdM jlRKTH"
|
||||||
role="option"
|
role="option"
|
||||||
selected=""
|
selected=""
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
aria-label="Checkmark Icon"
|
aria-label="Checkmark Icon"
|
||||||
class="sc-iqAclL ejyrfD"
|
class="sc-crzoAE gdYtkZ"
|
||||||
height="16"
|
height="16"
|
||||||
role="img"
|
role="img"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
|
@ -105,7 +105,7 @@ exports[`VersionSelector should correctly render VersionSelector 1`] = `
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
<span
|
<span
|
||||||
class="sc-pNWdM irvinq"
|
class="sc-jrsJWt hDLwjI"
|
||||||
>
|
>
|
||||||
2023-01-01
|
2023-01-01
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -61,6 +61,16 @@ export interface RedocRawOptions {
|
||||||
backNavigationPath?: string;
|
backNavigationPath?: string;
|
||||||
ignoreIncompatibleTypes?: boolean | string;
|
ignoreIncompatibleTypes?: boolean | string;
|
||||||
siteTitle?: 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 {
|
export function argValueToBoolean(val?: string | boolean, defaultValue?: boolean): boolean {
|
||||||
|
@ -269,6 +279,7 @@ export class RedocNormalizedOptions {
|
||||||
backNavigationPath?: string;
|
backNavigationPath?: string;
|
||||||
ignoreIncompatibleTypes: boolean;
|
ignoreIncompatibleTypes: boolean;
|
||||||
siteTitle?: string;
|
siteTitle?: string;
|
||||||
|
versionData?: string | VersionData;
|
||||||
|
|
||||||
constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) {
|
constructor(raw: RedocRawOptions, defaults: RedocRawOptions = {}) {
|
||||||
raw = { ...defaults, ...raw };
|
raw = { ...defaults, ...raw };
|
||||||
|
@ -351,5 +362,6 @@ export class RedocNormalizedOptions {
|
||||||
this.backNavigationPath = raw.backNavigationPath;
|
this.backNavigationPath = raw.backNavigationPath;
|
||||||
this.ignoreIncompatibleTypes = argValueToBoolean(raw.ignoreIncompatibleTypes);
|
this.ignoreIncompatibleTypes = argValueToBoolean(raw.ignoreIncompatibleTypes);
|
||||||
this.siteTitle = raw.siteTitle;
|
this.siteTitle = raw.siteTitle;
|
||||||
|
this.versionData = raw.versionData;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
8
version-data.json
Normal file
8
version-data.json
Normal file
|
@ -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"]
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user