Skip to content

Commit

Permalink
fix(elements-core): translate resolved schema objects (stoplightio#2305)
Browse files Browse the repository at this point in the history
  • Loading branch information
P0lip authored Jan 5, 2023
1 parent be805ec commit 46b6187
Show file tree
Hide file tree
Showing 10 changed files with 130 additions and 15 deletions.
3 changes: 2 additions & 1 deletion packages/elements-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stoplight/elements-core",
"version": "7.7.7",
"version": "7.7.8",
"sideEffects": [
"web-components.min.js",
"src/web-components/**",
Expand Down Expand Up @@ -57,6 +57,7 @@
]
},
"dependencies": {
"@stoplight/http-spec": "^5.1.4",
"@stoplight/json": "^3.18.1",
"@stoplight/json-schema-ref-parser": "^9.0.5",
"@stoplight/json-schema-sampler": "0.2.3",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { Box, Flex, NodeAnnotation, Select, VStack } from '@stoplight/mosaic';
import { IHttpOperationRequestBody } from '@stoplight/types';
import * as React from 'react';

import { useInlineRefResolver } from '../../../context/InlineRefResolver';
import { useSchemaInlineRefResolver } from '../../../context/InlineRefResolver';
import { useOptionsCtx } from '../../../context/Options';
import { isJSONSchema } from '../../../utils/guards';
import { getOriginalObject } from '../../../utils/ref-resolving/resolvedObject';
Expand All @@ -24,7 +24,7 @@ export const isBodyEmpty = (body?: BodyProps['body']) => {
};

export const Body = ({ body, onChange }: BodyProps) => {
const refResolver = useInlineRefResolver();
const refResolver = useSchemaInlineRefResolver();
const [chosenContent, setChosenContent] = React.useState(0);
const { nodeHasChanged } = useOptionsCtx();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { JSONSchema7Object } from 'json-schema';
import { sortBy } from 'lodash';
import * as React from 'react';

import { useInlineRefResolver } from '../../../context/InlineRefResolver';
import { useSchemaInlineRefResolver } from '../../../context/InlineRefResolver';
import { useOptionsCtx } from '../../../context/Options';
import { isNodeExample } from '../../../utils/http-spec/examples';

Expand Down Expand Up @@ -35,7 +35,7 @@ const defaultStyle = {

export const Parameters: React.FunctionComponent<ParametersProps> = ({ parameters, parameterType }) => {
const { nodeHasChanged } = useOptionsCtx();
const refResolver = useInlineRefResolver();
const refResolver = useSchemaInlineRefResolver();

const schema = React.useMemo(
() => httpOperationParamsToSchema({ parameters, parameterType }),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { IHttpOperationResponse } from '@stoplight/types';
import { sortBy, uniqBy } from 'lodash';
import * as React from 'react';

import { useInlineRefResolver } from '../../../context/InlineRefResolver';
import { useSchemaInlineRefResolver } from '../../../context/InlineRefResolver';
import { useOptionsCtx } from '../../../context/Options';
import { getOriginalObject } from '../../../utils/ref-resolving/resolvedObject';
import { MarkdownViewer } from '../../MarkdownViewer';
Expand Down Expand Up @@ -76,7 +76,7 @@ Responses.displayName = 'HttpOperation.Responses';
const Response = ({ response, onMediaTypeChange }: ResponseProps) => {
const { contents = [], headers = [], description } = response;
const [chosenContent, setChosenContent] = React.useState(0);
const refResolver = useInlineRefResolver();
const refResolver = useSchemaInlineRefResolver();
const { nodeHasChanged } = useOptionsCtx();

const responseContent = contents[chosenContent];
Expand Down
4 changes: 2 additions & 2 deletions packages/elements-core/src/components/Docs/Model/Model.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cn from 'classnames';
import { JSONSchema7 } from 'json-schema';
import * as React from 'react';

import { useInlineRefResolver, useResolvedObject } from '../../../context/InlineRefResolver';
import { useResolvedObject, useSchemaInlineRefResolver } from '../../../context/InlineRefResolver';
import { useOptionsCtx } from '../../../context/Options';
import { useIsCompact } from '../../../hooks/useIsCompact';
import { exceedsSize, generateExamplesFromJsonSchema } from '../../../utils/exampleGeneration/exampleGeneration';
Expand All @@ -27,7 +27,7 @@ const ModelComponent: React.FC<ModelProps> = ({
layoutOptions,
exportProps,
}) => {
const resolveRef = useInlineRefResolver();
const resolveRef = useSchemaInlineRefResolver();
const data = useResolvedObject(unresolvedData) as JSONSchema7;
const { nodeHasChanged } = useOptionsCtx();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import React from 'react';
import URI from 'urijs';

import { NodeTypeColors, NodeTypeIconDefs } from '../../../constants';
import { useInlineRefResolver } from '../../../context/InlineRefResolver';
import { useSchemaInlineRefResolver } from '../../../context/InlineRefResolver';
import { PersistenceContextProvider } from '../../../context/Persistence';
import { useParsedValue } from '../../../hooks/useParsedValue';
import { JSONSchema } from '../../../types';
Expand All @@ -35,7 +35,7 @@ interface ISchemaAndDescriptionProps {
}

const SchemaAndDescription = ({ title: titleProp, schema }: ISchemaAndDescriptionProps) => {
const resolveRef = useInlineRefResolver();
const resolveRef = useSchemaInlineRefResolver();
const title = titleProp ?? schema.title;
return (
<Box py={2}>
Expand Down
95 changes: 94 additions & 1 deletion packages/elements-core/src/context/InlineRefResolver.spec.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
import { renderHook } from '@testing-library/react-hooks';
import * as React from 'react';

import { InlineRefResolverProvider, useDocument, useInlineRefResolver, useResolvedObject } from './InlineRefResolver';
import {
InlineRefResolverProvider,
useDocument,
useInlineRefResolver,
useResolvedObject,
useSchemaInlineRefResolver,
} from './InlineRefResolver';

describe('InlineRefResolver', () => {
describe('useDocument hook', () => {
Expand Down Expand Up @@ -51,4 +57,91 @@ describe('InlineRefResolver', () => {
expect(firstReturnedObject).toBe(secondReturnedObject);
});
});

describe('useSchemaInlineRefResolver', () => {
const wrapper: React.FC<{ document: Record<string, unknown> }> = ({ children, document }) => (
<InlineRefResolverProvider document={document}>{children}</InlineRefResolverProvider>
);

it('translates resolved schema', () => {
const document = {
openapi: '3.0.0',
paths: {
'/user': {
post: {
requestBody: {
content: {
'application/json': {
schema: {
type: 'object',
properties: {
user: {
$ref: '#/components/schemas/User',
},
},
},
},
},
},
},
},
},
components: {
schemas: {
User: {
type: 'object',
nullable: true,
properties: {
id: {
type: 'integer',
nullable: true,
},
stars: {
type: 'number',
format: 'int32',
},
},
},
},
},
};

const { result } = renderHook(() => useSchemaInlineRefResolver(), { wrapper, initialProps: { document } });

const resolved = result.current(
{
source: null,
pointer: '#/components/schemas/User',
},
[],
{
type: 'object',
properties: {
user: {
$ref: '#/components/schemas/User',
},
},
$schema: 'http://json-schema.org/draft-07/schema#',
'x-stoplight': {
id: 'd3bf5ceb7dd53',
},
},
);

expect(resolved).toEqual({
type: ['object', 'null'],
properties: {
id: {
type: ['integer', 'null'],
},
stars: {
type: 'number',
format: 'int32',
maximum: 2147483647,
minimum: -2147483648,
},
},
});
});
});
});
21 changes: 21 additions & 0 deletions packages/elements-core/src/context/InlineRefResolver.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { convertToJsonSchema } from '@stoplight/http-spec/oas';
import { isPlainObject } from '@stoplight/json';
import type { Dictionary } from '@stoplight/types';
import * as React from 'react';
import { useContext } from 'react';

Expand Down Expand Up @@ -51,3 +53,22 @@ export const useResolvedObject = (currentObject: object): object => {
[currentObject, document, resolver],
);
};

export const useSchemaInlineRefResolver = (): ReferenceResolver => {
const document = useDocument();
const resolver = useInlineRefResolver();

return React.useCallback<ReferenceResolver>(
(...args) => {
const resolved = resolver?.(...args);
if (!isPlainObject(resolved)) {
return resolved;
}

const converted = convertToJsonSchema((document ?? {}) as Dictionary<unknown>, resolved);
delete converted.$schema;
return converted;
},
[document, resolver],
);
};
2 changes: 1 addition & 1 deletion packages/elements-dev-portal/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
]
},
"dependencies": {
"@stoplight/elements-core": "~7.7.7",
"@stoplight/elements-core": "~7.7.8",
"@stoplight/markdown-viewer": "^5.5.0",
"@stoplight/mosaic": "^1.33.0",
"@stoplight/path": "^1.3.2",
Expand Down
4 changes: 2 additions & 2 deletions packages/elements/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@stoplight/elements",
"version": "7.7.7",
"version": "7.7.8",
"description": "UI components for composing beautiful developer documentation.",
"keywords": [],
"sideEffects": [
Expand Down Expand Up @@ -62,7 +62,7 @@
]
},
"dependencies": {
"@stoplight/elements-core": "~7.7.7",
"@stoplight/elements-core": "~7.7.8",
"@stoplight/http-spec": "^5.1.4",
"@stoplight/json": "^3.18.1",
"@stoplight/mosaic": "^1.33.0",
Expand Down

0 comments on commit 46b6187

Please sign in to comment.