diff --git a/src/bin/restful-react-import.ts b/src/bin/restful-react-import.ts index 5514828d..46dffa1e 100644 --- a/src/bin/restful-react-import.ts +++ b/src/bin/restful-react-import.ts @@ -3,6 +3,7 @@ import program from "commander"; import { existsSync, readFileSync, unlinkSync, writeFileSync } from "fs"; import inquirer from "inquirer"; import difference from "lodash/difference"; +import pick from "lodash/pick"; import { join, parse } from "path"; import request from "request"; import { homedir } from "os"; @@ -20,6 +21,7 @@ export interface Options { github?: string; transformer?: string; validation?: boolean; + skipReact?: boolean; } export type AdvancedOptions = Options & { @@ -52,6 +54,7 @@ program.option("-u, --url [value]", "url to spec (yaml or json openapi specs)"); program.option("-g, --github [value]", "github path (format: `owner:repo:branch:path`)"); program.option("-t, --transformer [value]", "transformer function path"); program.option("--validation", "add the validation step (provided by ibm-openapi-validator)"); +program.option("--skip-react", "skip the generation of react components/hooks"); program.option("--config [value]", "override flags by a config file"); program.parse(process.argv); @@ -67,6 +70,16 @@ const successWithoutOutputMessage = chalk.yellow("Success! No output path specif const importSpecs = async (options: AdvancedOptions) => { const transformer = options.transformer ? require(join(process.cwd(), options.transformer)) : undefined; + const optionsKeys: Array = [ + "validation", + "customImport", + "customProps", + "customGenerator", + "pathParametersEncodingMode", + "skipReact", + ]; + const importOptions = pick(options, optionsKeys); + if (!options.file && !options.url && !options.github) { throw new Error("You need to provide an input specification with `--file`, '--url', or `--github`"); } @@ -80,11 +93,7 @@ const importSpecs = async (options: AdvancedOptions) => { data, format, transformer, - validation: options.validation, - customImport: options.customImport, - customProps: options.customProps, - customGenerator: options.customGenerator, - pathParametersEncodingMode: options.pathParametersEncodingMode, + ...importOptions, }); } else if (options.url) { const { url } = options; @@ -116,11 +125,7 @@ const importSpecs = async (options: AdvancedOptions) => { data: body, format, transformer, - validation: options.validation, - customImport: options.customImport, - customProps: options.customProps, - customGenerator: options.customGenerator, - pathParametersEncodingMode: options.pathParametersEncodingMode, + ...importOptions, }), ); }); @@ -204,11 +209,7 @@ const importSpecs = async (options: AdvancedOptions) => { data: body.data.repository.object.text, format, transformer, - validation: options.validation, - customImport: options.customImport, - customProps: options.customProps, - customGenerator: options.customGenerator, - pathParametersEncodingMode: options.pathParametersEncodingMode, + ...importOptions, }), ); }); diff --git a/src/scripts/import-open-api.ts b/src/scripts/import-open-api.ts index a90999df..5ae0e774 100644 --- a/src/scripts/import-open-api.ts +++ b/src/scripts/import-open-api.ts @@ -288,6 +288,7 @@ export const generateRestfulComponent = ( parameters: Array = [], schemasComponents?: ComponentsObject, customProps: AdvancedOptions["customProps"] = {}, + skipReact = false, customGenerator?: AdvancedOptions["customGenerator"], ) => { if (!operation.operationId) { @@ -461,24 +462,28 @@ export interface ${componentName}RequestBody ${requestBodyTypes} ` : "" } -export type ${componentName}Props = Omit<${Component}Props<${genericsTypes}>, "path"${ - verb === "get" ? "" : ` | "verb"` - }>${paramsInPath.length ? ` & ${componentName}PathParams` : ""}; +`; + + if (!skipReact) { + // Component version + output += `export type ${componentName}Props = Omit<${Component}Props<${genericsTypes}>, "path"${ + verb === "get" ? "" : ` | "verb"` + }>${paramsInPath.length ? ` & ${componentName}PathParams` : ""}; ${description}export const ${componentName} = (${ - paramsInPath.length ? `{${paramsInPath.join(", ")}, ...props}` : "props" - }: ${componentName}Props) => ( + paramsInPath.length ? `{${paramsInPath.join(", ")}, ...props}` : "props" + }: ${componentName}Props) => ( <${Component}<${genericsTypes}>${ - verb === "get" - ? "" - : ` + verb === "get" + ? "" + : ` verb="${verb.toUpperCase()}"` - } + } path={encode\`${route}\`}${ - customPropsEntries.length - ? "\n " + customPropsEntries.map(([key, value]) => `${key}=${value}`).join("\n ") - : "" - } + customPropsEntries.length + ? "\n " + customPropsEntries.map(([key, value]) => `${key}=${value}`).join("\n ") + : "" + } ${verb === "delete" ? "pathInlineBodyEncode={encodingFn}" : ""} {...props} /> @@ -486,34 +491,35 @@ ${description}export const ${componentName} = (${ `; - // Hooks version - output += `export type Use${componentName}Props = Omit, "path"${ - verb === "get" ? "" : ` | "verb"` - }>${paramsInPath.length ? ` & ${componentName}PathParams` : ""}; + // Hooks version + output += `export type Use${componentName}Props = Omit, "path"${ + verb === "get" ? "" : ` | "verb"` + }>${paramsInPath.length ? ` & ${componentName}PathParams` : ""}; ${description}export const use${componentName} = (${ - paramsInPath.length ? `{${paramsInPath.join(", ")}, ...props}` : "props" - }: Use${componentName}Props) => use${Component}<${genericsTypes}>(${ - verb === "get" ? "" : `"${verb.toUpperCase()}", ` - }${ - paramsInPath.length - ? `(paramsInPath: ${componentName}PathParams) => encode\`${route.replace(/\$\{/g, "${paramsInPath.")}\`` - : `encode\`${route}\`` - }, ${ - customPropsEntries.length || paramsInPath.length || verb === "delete" - ? `{ ${ - customPropsEntries.length - ? `${customPropsEntries - .map(([key, value]) => `${key}:${reactPropsValueToObjectValue(value || "")}`) - .join(", ")},` - : "" - }${verb === "delete" ? "pathInlineBodyEncode: encodingFn, " : " "}${ - paramsInPath.length ? `pathParams: { ${paramsInPath.join(", ")} },` : "" - } ...props }` - : "props" - }); + paramsInPath.length ? `{${paramsInPath.join(", ")}, ...props}` : "props" + }: Use${componentName}Props) => use${Component}<${genericsTypes}>(${ + verb === "get" ? "" : `"${verb.toUpperCase()}", ` + }${ + paramsInPath.length + ? `(paramsInPath: ${componentName}PathParams) => encode\`${route.replace(/\$\{/g, "${paramsInPath.")}\`` + : `encode\`${route}\`` + }, ${ + customPropsEntries.length || paramsInPath.length || verb === "delete" + ? `{ ${ + customPropsEntries.length + ? `${customPropsEntries + .map(([key, value]) => `${key}:${reactPropsValueToObjectValue(value || "")}`) + .join(", ")},` + : "" + }${verb === "delete" ? "pathInlineBodyEncode: encodingFn, " : " "}${ + paramsInPath.length ? `pathParams: { ${paramsInPath.join(", ")} },` : "" + } ...props }` + : "props" + }); `; + } // Custom version if (customGenerator) { @@ -529,7 +535,7 @@ ${description}export const use${componentName} = (${ }); } - if (headerParams.map(({ name }) => name.toLocaleLowerCase()).includes("prefer")) { + if (!skipReact && headerParams.map(({ name }) => name.toLocaleLowerCase()).includes("prefer")) { output += `export type Poll${componentName}Props = Omit, "path">${ paramsInPath.length ? ` & {${paramsTypes}}` : "" }; @@ -765,12 +771,14 @@ const getEncodingFunction = (mode: "uriComponent" | "rfc3986") => { * @param options.format format of the spec * @param options.transformer custom function to transform your spec * @param options.validation validate the spec with ibm-openapi-validator tool + * @param options.skipReact skip the generation of react components/hooks */ const importOpenApi = async ({ data, format, transformer, validation, + skipReact, customImport, customProps, customGenerator, @@ -780,6 +788,7 @@ const importOpenApi = async ({ format: "yaml" | "json"; transformer?: (specs: OpenAPIObject) => OpenAPIObject; validation?: boolean; + skipReact?: boolean; customImport?: AdvancedOptions["customImport"]; customProps?: AdvancedOptions["customProps"]; customGenerator?: AdvancedOptions["customGenerator"]; @@ -813,6 +822,7 @@ const importOpenApi = async ({ verbs.parameters, specs.components, customProps, + skipReact, customGenerator, ); } @@ -833,11 +843,15 @@ const importOpenApi = async ({ if (havePoll) { imports.push("Poll", "PollProps"); } + const restfulReactImports = skipReact + ? "" + : `import React from "react"; +import { ${imports.join(", ")} } from "restful-react";`; + output = `/* Generated by restful-react */ -import React from "react"; -import { ${imports.join(", ")} } from "restful-react";${customImport ? `\n${customImport}\n` : ""} +${restfulReactImports}${customImport ? `\n${customImport}\n` : ""} export type Omit = Pick>;