Skip to content
This repository has been archived by the owner on Nov 11, 2023. It is now read-only.

Commit

Permalink
Expose more customProps & add some metadata
Browse files Browse the repository at this point in the history
So far `customProps` was just for the `base` let's extends this API to permit more usecases.

In the same direction, `customProps[key]` can now be a function that will receive some metadata (just the `responseType` for now)
  • Loading branch information
fabien0102 committed Mar 31, 2021
1 parent b184ed1 commit 9ca16aa
Show file tree
Hide file tree
Showing 3 changed files with 165 additions and 53 deletions.
5 changes: 4 additions & 1 deletion src/bin/restful-react-import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import slash from "slash";

import importOpenApi from "../scripts/import-open-api";
import { OperationObject } from "openapi3-ts";
import { UseGetProps } from "../useGet";

const log = console.log; // tslint:disable-line:no-console

Expand All @@ -27,7 +28,9 @@ export interface Options {
export type AdvancedOptions = Options & {
customImport?: string;
customProps?: {
base?: string;
[props in keyof Omit<UseGetProps<any, any, any, any>, "lazy" | "debounce" | "path">]:
| string
| ((meta: { responseType: string }) => string);
};

pathParametersEncodingMode?: "uriComponent" | "rfc3986";
Expand Down
28 changes: 15 additions & 13 deletions src/scripts/import-open-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -394,14 +394,13 @@ export const generateRestfulComponent = (
? getRef(lastParamInTheRouteDefinition.schema.$ref)
: "string";

const responseType = needAResponseComponent ? componentName + "Response" : responseTypes;
const genericsTypes =
verb === "get"
? `${needAResponseComponent ? componentName + "Response" : responseTypes}, ${errorTypes}, ${
queryParamsType ? componentName + "QueryParams" : "void"
}, ${paramsInPath.length ? componentName + "PathParams" : "void"}`
: `${needAResponseComponent ? componentName + "Response" : responseTypes}, ${errorTypes}, ${
queryParamsType ? componentName + "QueryParams" : "void"
}, ${
? `${responseType}, ${errorTypes}, ${queryParamsType ? componentName + "QueryParams" : "void"}, ${
paramsInPath.length ? componentName + "PathParams" : "void"
}`
: `${responseType}, ${errorTypes}, ${queryParamsType ? componentName + "QueryParams" : "void"}, ${
verb === "delete" && lastParamInTheRoute
? lastParamInTheRouteType
: needARequestBodyComponent
Expand All @@ -411,20 +410,23 @@ export const generateRestfulComponent = (

const genericsTypesForHooksProps =
verb === "get"
? `${needAResponseComponent ? componentName + "Response" : responseTypes}, ${errorTypes}, ${
queryParamsType ? componentName + "QueryParams" : "void"
}, ${paramsInPath.length ? componentName + "PathParams" : "void"}`
: `${needAResponseComponent ? componentName + "Response" : responseTypes}, ${errorTypes}, ${
queryParamsType ? componentName + "QueryParams" : "void"
}, ${
? `${responseType}, ${errorTypes}, ${queryParamsType ? componentName + "QueryParams" : "void"}, ${
paramsInPath.length ? componentName + "PathParams" : "void"
}`
: `${responseType}, ${errorTypes}, ${queryParamsType ? componentName + "QueryParams" : "void"}, ${
verb === "delete" && lastParamInTheRoute
? lastParamInTheRouteType
: needARequestBodyComponent
? componentName + "RequestBody"
: requestBodyTypes
}, ${paramsInPath.length ? componentName + "PathParams" : "void"}`;

const customPropsEntries = Object.entries(customProps);
const customPropsEntries = Object.entries(customProps).map(([key, prop]) => {
if (typeof prop === "function") {
return [key, prop({ responseType })];
}
return [key, prop];
});

const description = formatDescription(
operation.summary && operation.description
Expand Down
185 changes: 146 additions & 39 deletions src/scripts/tests/import-open-api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -893,7 +893,7 @@ describe("scripts/import-open-api", () => {
});
});

describe("generateGetComponent", () => {
describe("generateRestfulComponent", () => {
it("should generate a fully typed component", () => {
const operation: OperationObject = {
summary: "List all fields for the use case schema",
Expand Down Expand Up @@ -2151,51 +2151,158 @@ describe("scripts/import-open-api", () => {
"
`);
});
});
it("should deal with no 2xx response case", () => {
const operation: OperationObject = {
summary: "List all fields for the use case schema",
operationId: "listFields",
responses: {
"302": {
description: "Just redirect",

it("should inject some customProps", () => {
const operation: OperationObject = {
summary: "List all fields for the use case schema",
operationId: "listFields",
tags: ["schema"],
responses: {
"200": {
description: "An array of schema fields",
content: { "application/json": { schema: { $ref: "#/components/schemas/FieldListResponse" } } },
},
default: {
description: "unexpected error",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/APIError" },
example: { errors: ["msg1", "msg2"] },
},
},
},
},
default: {
description: "unexpected error",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/APIError" },
example: { errors: ["msg1", "msg2"] },
};

expect(
generateRestfulComponent(operation, "get", "/fields", [], [], [], {
resolve: "{res => res}",
}),
).toMatchInlineSnapshot(`
"
export type ListFieldsProps = Omit<GetProps<FieldListResponse, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const ListFields = (props: ListFieldsProps) => (
<Get<FieldListResponse, APIError, void, void>
path={\`/fields\`}
resolve={res => res}
{...props}
/>
);
export type UseListFieldsProps = Omit<UseGetProps<FieldListResponse, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const useListFields = (props: UseListFieldsProps) => useGet<FieldListResponse, APIError, void, void>(\`/fields\`, { resolve:res => res, ...props });
"
`);
});

it("should inject some customProps (with function)", () => {
const operation: OperationObject = {
summary: "List all fields for the use case schema",
operationId: "listFields",
tags: ["schema"],
responses: {
"200": {
description: "An array of schema fields",
content: { "application/json": { schema: { $ref: "#/components/schemas/FieldListResponse" } } },
},
default: {
description: "unexpected error",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/APIError" },
example: { errors: ["msg1", "msg2"] },
},
},
},
},
},
};

expect(generateRestfulComponent(operation, "get", "/fields", [])).toMatchInlineSnapshot(`
"
export type ListFieldsProps = Omit<GetProps<void, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const ListFields = (props: ListFieldsProps) => (
<Get<void, APIError, void, void>
path={\`/fields\`}
{...props}
/>
);
};

expect(
generateRestfulComponent(operation, "get", "/fields", [], [], [], {
resolve: ({ responseType }) => `{ data => data as ${responseType}}`,
}),
).toMatchInlineSnapshot(`
"
export type ListFieldsProps = Omit<GetProps<FieldListResponse, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const ListFields = (props: ListFieldsProps) => (
<Get<FieldListResponse, APIError, void, void>
path={\`/fields\`}
resolve={ data => data as FieldListResponse}
{...props}
/>
);
export type UseListFieldsProps = Omit<UseGetProps<void, APIError, void, void>, \\"path\\">;
export type UseListFieldsProps = Omit<UseGetProps<FieldListResponse, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const useListFields = (props: UseListFieldsProps) => useGet<void, APIError, void, void>(\`/fields\`, props);
/**
* List all fields for the use case schema
*/
export const useListFields = (props: UseListFieldsProps) => useGet<FieldListResponse, APIError, void, void>(\`/fields\`, { resolve: data => data as FieldListResponse, ...props });
"
`);
"
`);
});

it("should deal with no 2xx response case", () => {
const operation: OperationObject = {
summary: "List all fields for the use case schema",
operationId: "listFields",
responses: {
"302": {
description: "Just redirect",
},
default: {
description: "unexpected error",
content: {
"application/json": {
schema: { $ref: "#/components/schemas/APIError" },
example: { errors: ["msg1", "msg2"] },
},
},
},
},
};

expect(generateRestfulComponent(operation, "get", "/fields", [])).toMatchInlineSnapshot(`
"
export type ListFieldsProps = Omit<GetProps<void, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const ListFields = (props: ListFieldsProps) => (
<Get<void, APIError, void, void>
path={\`/fields\`}
{...props}
/>
);
export type UseListFieldsProps = Omit<UseGetProps<void, APIError, void, void>, \\"path\\">;
/**
* List all fields for the use case schema
*/
export const useListFields = (props: UseListFieldsProps) => useGet<void, APIError, void, void>(\`/fields\`, props);
"
`);
});
});

describe("reactPropsValueToObjectValue", () => {
Expand Down

0 comments on commit 9ca16aa

Please # to comment.