Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(type-safe-api): fix generated react hooks compilation issues #605

Merged
merged 1 commit into from
Oct 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ SPDX-License-Identifier: Apache-2.0 */
import * as fs from "fs";
import * as path from "path";
import kebabCase from "lodash/kebabCase";
import camelCase from "lodash/camelCase";
import { parse } from "ts-command-line-args";

// Used to split OpenAPI generated files into multiple files in order to work around
Expand Down Expand Up @@ -32,6 +33,8 @@ const applyReplacementFunction = (functionConfig: FunctionConfig): string => {
switch (functionConfig.function) {
case "kebabCase":
return kebabCase(functionConfig.args[0]);
case "camelCase":
return camelCase(functionConfig.args[0]);
default:
throw new Error(`Unsupported TSAPI_FN function ${functionConfig.function}`);
}
Expand Down Expand Up @@ -127,6 +130,9 @@ void (async () => {

// Delete the original file
fs.rmSync(filePath);
} else {
// Apply the replacement functions directly
fs.writeFileSync(filePath, applyReplacementFunctions(contents));
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export const use{{operationIdCamelCase}} = <TError = ResponseError>(
if (!api) {
throw NO_API_ERROR;
}
return useInfiniteQuery(["{{nickname}}"{{#allParams.0}}, params{{/allParams.0}}], ({ pageParam }) => api.{{nickname}}({ {{#allParams.0}}...params, {{/allParams.0}}{{vendorExtensions.x-paginated.inputToken}}: pageParam }), {
return useInfiniteQuery(["{{nickname}}"{{#allParams.0}}, params{{/allParams.0}}], ({ pageParam }) => api.{{nickname}}({ {{#allParams.0}}...params, {{/allParams.0}}###TSAPI_FN###{"function": "camelCase", "args": ["{{vendorExtensions.x-paginated.inputToken}}"]}###/TSAPI_FN###: pageParam }), {
getNextPageParam: (response) => response.{{vendorExtensions.x-paginated.outputToken}},
context: {{classname}}DefaultContext,
...options as any,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,42 @@ SPDX-License-Identifier: Apache-2.0 */
import SwaggerParser from "@apidevtools/swagger-parser";
import { writeFile } from "projen/lib/util";
import { parse } from "ts-command-line-args";
import * as path from 'path';
import * as _ from "lodash";
import fs from "fs";
import type { OpenAPIV3 } from "openapi-types";

// Smithy HTTP trait is used to map Smithy operations to their location in the spec
const SMITHY_HTTP_TRAIT_ID = "smithy.api#http";

// The OpenAPI vendor extension used for paginated operations
const PAGINATED_VENDOR_EXTENSION = "x-paginated";

// Traits that will "rename" members in the generated OpenAPI spec
const SMITHY_RENAME_TRAITS = [
"smithy.api#httpQuery",
"smithy.api#httpHeader",
];

// Maps traits to specific vendor extensions which we also support specifying in OpenAPI
const TRAIT_TO_SUPPORTED_OPENAPI_VENDOR_EXTENSION: { [key: string]: string } = {
"smithy.api#paginated": "x-paginated",
"smithy.api#paginated": PAGINATED_VENDOR_EXTENSION,
};

interface SmithyMember {
readonly target: string;
readonly traits?: { [key: string]: any };
}

interface SmithyOperationInput {
readonly type: string;
readonly members?: { [key: string]: SmithyMember }
}

interface SmithyOperationDetails {
readonly id: string;
readonly method: string;
readonly path: string;
readonly traits: { [key: string]: any };
readonly input?: SmithyOperationInput;
}

interface InvalidRequestParameter {
Expand Down Expand Up @@ -80,6 +98,7 @@ void (async () => {
method: shape.traits[SMITHY_HTTP_TRAIT_ID].method?.toLowerCase(),
path: shape.traits[SMITHY_HTTP_TRAIT_ID].uri,
traits: shape.traits,
input: smithyModel.shapes[shape.input?.target],
}));

// Apply all operation-level traits as vendor extensions to the relevant operation in the spec
Expand All @@ -96,7 +115,20 @@ void (async () => {
if (traitId.endsWith("#handler")) {
vendorExtension = "x-handler";
}
spec.paths[operation.path][operation.method][vendorExtension] = value;

let extensionValue = value;

// The smithy paginated trait is written in terms of inputs which may have different names in openapi
// so we must map them here
if (vendorExtension === PAGINATED_VENDOR_EXTENSION) {
extensionValue = Object.fromEntries(Object.entries(value as {[key: string]: string}).map(([traitProperty, memberName]) => {
const member = operation.input?.members?.[memberName];
const renamedMemberName = SMITHY_RENAME_TRAITS.map(trait => member?.traits?.[trait]).find(x => x) ?? memberName;
return [traitProperty, renamedMemberName];
}));
}

spec.paths[operation.path][operation.method][vendorExtension] = extensionValue;
});
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export class TypescriptReactQueryHooksLibrary extends TypeScriptProject {
}

// Add dependencies on react-query and react
this.addDeps("@tanstack/react-query");
this.addDeps("@tanstack/react-query@^4"); // Pin at 4 for now - requires generated code updates to upgrade to 5
this.addDevDeps("react", "@types/react");
this.addPeerDeps("react");

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading