Skip to content

Commit

Permalink
Add support for union types in raml docs for api types (#2070)
Browse files Browse the repository at this point in the history
* feat: support unions and multiply types for api-types

* refactor: pre-processing of types and resources

* refactor: apply suggested changes

* chore: add changeset
  • Loading branch information
timonrey authored Sep 10, 2024
1 parent 61f888b commit 5f7ed85
Show file tree
Hide file tree
Showing 15 changed files with 122 additions and 44 deletions.
6 changes: 6 additions & 0 deletions .changeset/fluffy-parents-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@commercetools-docs/gatsby-transformer-raml': patch
'@commercetools-docs/gatsby-theme-api-docs': patch
---

Display union references for api-types correctly.
12 changes: 12 additions & 0 deletions api-specs/test/types/arrays.raml
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,15 @@ types:
type: scalars.IntegerTestType[]
uniqueItems: false
example: !include ../examples/array-test-type.json
UnionReferenceTestType:
description: A test type with a reference with multiple type options.
type: object
properties:
reference:
type: ArrayTestType | WideLayoutArrayTestType
description: |
Reference description.
key?:
type: string
description: |
Key type description.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ const isRegex = (string) =>
string.charAt(0) === '/' && string.charAt(string.length - 1) === '/';

const isTypeUnion = (strType) => {
return typeof strType === 'string' && strType === 'Union';
return strType === 'Union';
};

const getParameterType = ({ name, unionParams }, type, apiKey) => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import React from 'react';
import PropTypes from 'prop-types';
import styled from '@emotion/styled';
import { designSystem, Markdown } from '@commercetools-docs/ui-kit';
import SpacingsStack from '@commercetools-uikit/spacings-stack';
import SpacingsInline from '@commercetools-uikit/spacings-inline';
import { BetaTag } from '@commercetools-docs/gatsby-theme-docs';
import { typography } from '../../../../design-system';
import RegexProperty from '../../properties/regex-properties';
import RegexProperty from '../regex-properties';
import useTypesToRender from '../../../../hooks/use-type-to-render';
import Required from '../../../required';

Expand All @@ -26,6 +27,42 @@ const BetaWrapper = styled.span`
padding-top: 0.2rem;
`;

function UnionPropertiesRow(props) {
const typesToRender = useTypesToRender({
property: props.types,
apiKey: props.apiKey,
isParameter: true,
});

return (
<>
Can be{' '}
{typesToRender.map(({ type }, idx, { length }) =>
length > idx + 1 ? (
<span key={idx}>{type}, </span>
) : (
<span key={idx}>or {type}</span>
)
)}
</>
);
}

UnionPropertiesRow.propTypes = {
apiKey: PropTypes.string.isRequired,
types: PropTypes.arrayOf({
name: PropTypes.string.isRequired,
type: PropTypes.string.isRequired,
required: PropTypes.bool,
description: PropTypes.string,
additionalDescription: PropTypes.string,
items: PropTypes.shape({
type: PropTypes.string,
}),
}).isRequired,
};
UnionPropertiesRow.displayName = 'UnionParametersRow';

const NameType = (props) => {
const typesToRender = useTypesToRender({
property: props.property,
Expand All @@ -36,6 +73,20 @@ const NameType = (props) => {
const isRegex = (string) =>
string.charAt(0) === '/' && string.charAt(string.length - 1) === '/';

const isTypeUnion = (strType) => {
return strType === 'Union';
};

const getPropertiesType = ({ name, unionParams }, type, apiKey) => {
if (isRegex(name) && !typeToRender.displayPrefix) {
return `Any ${typeof type} parameter matching this regular expression`;
}
if (isTypeUnion(type)) {
return <UnionPropertiesRow types={unionParams} apiKey={apiKey} />;
}
return type;
};

return (
<SpacingsStack scale="xs">
<PropertyName>
Expand All @@ -57,11 +108,7 @@ const NameType = (props) => {
<PropertyType>
{typeToRender.displayPrefix && typeToRender.displayPrefix}

{isRegex(props.property.name) && !typeToRender.displayPrefix
? `Any ${typeof typeToRender.type} property matching this regular expression`
: typeof typeToRender.type === 'string'
? typeToRender.type
: typeToRender.type}
{getPropertiesType(props.property, typeToRender.type, props.apiKey)}
{'\u200B' /* zero-width space for the search crawler */}
</PropertyType>
</SpacingsStack>
Expand All @@ -76,6 +123,10 @@ NameType.propTypes = {
items: PropTypes.shape({
type: PropTypes.string.isRequired,
}),
unionParams: PropTypes.shape({
type: PropTypes.string.isRequired,
builtinType: PropTypes.string.isRequired,
}),
required: PropTypes.bool.isRequired,
beta: PropTypes.bool,
}).isRequired,
Expand Down
4 changes: 4 additions & 0 deletions packages/gatsby-theme-api-docs/src/hooks/use-api-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export const useApiTypes = () => {
items {
type
}
unionParams {
builtinType
type
}
maxItems
maxLength
maximum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ import { useTypeLocations } from './use-type-locations';
import generateTypesToRender from '../utils/generate-type-to-render';

/**
* It accept either a single property or an array of properties.
* The funtion returns an array of types to render
* It accepts either a single property or an array of properties.
* The function returns an array of types to render
*/
function useTypesToRender({ property, apiKey, isParameter } = {}) {
const typeLocations = useTypeLocations();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const extractAdditionalInfo = (properties) => {
'originalType',
'required',
'type',
'unionParams',
];

mainInfo.forEach((field) => {
Expand Down
7 changes: 3 additions & 4 deletions packages/gatsby-transformer-raml/src/create-api-node.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import doRecursion from "./utils/api/do-recursion.mjs";
import parametersToArray from "./utils/parameters-to-array.mjs";

import doRecursion from './utils/api/do-recursion.mjs';
import propertiesToArray from './utils/properties-to-array.mjs';

function createApiNode({
apiKey,
Expand Down Expand Up @@ -34,7 +33,7 @@ function postProcessApi({ apiKey, api }) {

postProcessedApi.apiKey = apiKey;

postProcessedApi.baseUriParameters = parametersToArray(
postProcessedApi.baseUriParameters = propertiesToArray(
postProcessedApi.baseUriParameters
);

Expand Down
12 changes: 5 additions & 7 deletions packages/gatsby-transformer-raml/src/create-resource-node.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import doRecursion from "./utils/resource/do-recursion.mjs";
import parametersToArray from "./utils/parameters-to-array.mjs";
import processMethods from "./utils/resource/process-methods.mjs";


import doRecursion from './utils/resource/do-recursion.mjs';
import propertiesToArray from './utils/properties-to-array.mjs';
import processMethods from './utils/resource/process-methods.mjs';

function createResourceNode({
apiKey,
Expand Down Expand Up @@ -50,11 +48,11 @@ function postProcessResource({

postProcessedResource.apiKey = apiKey;

postProcessedResource.uriParameters = parametersToArray(
postProcessedResource.uriParameters = propertiesToArray(
postProcessedResource.uriParameters
);

postProcessedResource.baseUriParameters = parametersToArray(
postProcessedResource.baseUriParameters = propertiesToArray(
postProcessedResource.baseUriParameters
);

Expand Down
9 changes: 2 additions & 7 deletions packages/gatsby-transformer-raml/src/create-type-node.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import resolveConflictingFieldTypes from './utils/type/resolve-conflicting-field
import generateType from './utils/type/generate-type.mjs';
import generateBuiltinType from './utils/type/generate-built-in-type.mjs';
import { examplesToArray } from './utils/resource/examples-to-array.mjs';
import propertiesToArray from './utils/properties-to-array.mjs';

function createTypeNode({
apiKey,
Expand Down Expand Up @@ -74,7 +75,7 @@ function processProperties({
let propertiesArray;

if (properties) {
propertiesArray = propertiesToArrays(properties);
propertiesArray = propertiesToArray(properties);
propertiesArray = propertiesArray.filter(
(property) => !property.deprecated && !property.markDeprecated
);
Expand All @@ -100,12 +101,6 @@ function processProperties({
return undefined;
}

function propertiesToArrays(properties) {
return Object.entries(properties).map(([key, value]) => {
return { ...value, name: key };
});
}

function enumValuesToArray(enumValue) {
if (enumValue) {
return Object.entries(enumValue).map(([key, value]) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,17 @@ const defineRamlType = ({ schema, createTypes }) => {
pattern: 'String',
required: 'Boolean!',
type: 'String!',
unionParams: '[RamlTypePropertyUnionParameter!]',
uniqueItems: 'Boolean',
},
}),
schema.buildObjectType({
name: 'RamlTypePropertyUnionParameter',
fields: {
type: 'String!',
builtinType: 'String!',
},
}),
];
createTypes(typeDefs);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ function getTypes(typeUnion) {
return results;
}

function parametersToArray(parameters) {
if (parameters) {
return Object.entries(parameters).map(([key, parameter]) => {
function propertiesToArray(properties) {
if (properties) {
return Object.entries(properties).map(([key, parameter]) => {
const paramType = generateType(parameter);
const isUnionType = paramType === 'Union';
return {
Expand All @@ -27,4 +27,4 @@ function parametersToArray(parameters) {
return undefined;
}

export default parametersToArray;
export default propertiesToArray;
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import parametersToArray from './parameters-to-array.mjs';
import propertiesToArray from './properties-to-array.mjs';

describe('parameters-to-array.js', () => {
describe('properties-to-array.js', () => {
it('should transform objects of query parameters to array', () => {
const parametersBefore = {
const propertiesBefore = {
where: {
required: false,
type: 'string',
Expand All @@ -16,7 +16,7 @@ describe('parameters-to-array.js', () => {
},
};

const parametersAfter = [
const propertiesAfter = [
{
name: 'where',
required: false,
Expand All @@ -33,11 +33,11 @@ describe('parameters-to-array.js', () => {
},
];

expect(parametersToArray(parametersBefore)).toEqual(parametersAfter);
expect(propertiesToArray(propertiesBefore)).toEqual(propertiesAfter);
});

it('should transform number to float', () => {
const parametersBefore = {
const propertiesBefore = {
limit: {
required: false,
type: 'integer',
Expand All @@ -51,7 +51,7 @@ describe('parameters-to-array.js', () => {
},
};

const parametersAfter = [
const propertiesAfter = [
{
name: 'limit',
required: false,
Expand All @@ -68,19 +68,19 @@ describe('parameters-to-array.js', () => {
},
];

expect(parametersToArray(parametersBefore)).toEqual(parametersAfter);
expect(propertiesToArray(propertiesBefore)).toEqual(propertiesAfter);
});

it('should properly convert union types transform number to float', () => {
const parametersBefore = {
const propertiesBefore = {
unionParameter: {
required: false,
type: 'integer | string | number',
builtinType: 'Union',
},
};

const parametersAfter = [
const propertiesAfter = [
{
name: 'unionParameter',
required: false,
Expand All @@ -94,6 +94,6 @@ describe('parameters-to-array.js', () => {
},
];

expect(parametersToArray(parametersBefore)).toEqual(parametersAfter);
expect(propertiesToArray(propertiesBefore)).toEqual(propertiesAfter);
});
});
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import parametersToArray from '../parameters-to-array.mjs';
import propertiesToArray from '../properties-to-array.mjs';
import responsesToArray from './responses-to-array.mjs';
import headersToArray from './headers-to-array.mjs';
import codeExamplesToArray from './code-examples-to-array.mjs';
Expand All @@ -16,7 +16,7 @@ function processMethods({

methods.forEach((method) => {
if (returnedMethods[method]) {
returnedMethods[method].queryParameters = parametersToArray(
returnedMethods[method].queryParameters = propertiesToArray(
returnedMethods[method].queryParameters
);

Expand Down
4 changes: 4 additions & 0 deletions websites/api-docs-smoke-test/src/content/types/general.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ import { ApiType } from "/shortcodes"

<ApiType apiKey="test" type="ArrayTestType" />

# UnionReferenceTestType

<ApiType apiKey="test" type="UnionReferenceTestType" />

# DateTestType

<ApiType apiKey="test" type="DateTestType" />
Expand Down

0 comments on commit 5f7ed85

Please sign in to comment.