Skip to content

fix: pathItem's parameters field support #48

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

Merged
merged 2 commits into from
Apr 27, 2021
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
13 changes: 12 additions & 1 deletion src/internal/OpenApiTools/Walker/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,15 @@ export interface State {
[operationId: string]: CodeGenerator.OpenApiOperation;
}

type UniqueParameterMap = Record<string, OpenApi.Parameter>;

const uniqParameters = (rawParameters: OpenApi.Parameter[]): OpenApi.Parameter[] => {
const parameterMap = rawParameters.reduce<UniqueParameterMap>((all, parameter) => {
return { ...all, [`${parameter.in}:${parameter.name}`]: parameter };
}, {});
return Object.values(parameterMap);
};

export const create = (rootSchema: OpenApi.Document): State => {
const paths = rootSchema.paths || {};
const state: State = {};
Expand All @@ -20,13 +29,15 @@ export const create = (rootSchema: OpenApi.Document): State => {
if (!operation.operationId) {
return;
}
const parameters = [...(pathItem.parameters || []), ...(operation.parameters || [])] as OpenApi.Parameter[];

state[operation.operationId] = {
httpMethod,
requestUri,
comment: [operation.summary, operation.description].filter(Boolean).join(EOL),
deprecated: !!operation.deprecated,
requestBody: operation.requestBody as OpenApi.RequestBody,
parameters: operation.parameters as OpenApi.Parameter[],
parameters: uniqParameters(parameters),
responses: operation.responses as CodeGenerator.OpenApiResponses,
};
});
Expand Down
2 changes: 1 addition & 1 deletion src/internal/OpenApiTools/Walker/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class Store {
private state: State.Type;
private operator: Structure.OperatorType;
private getChildByPaths: Structure.GetChildByPaths;
constructor(private factory: Factory.Type, private rootDocument: OpenApi.Document) {
constructor(private factory: Factory.Type, rootDocument: OpenApi.Document) {
this.state = State.createDefaultState(rootDocument);
const { operator, getChildByPaths } = Structure.create();
this.operator = operator;
Expand Down
14 changes: 9 additions & 5 deletions src/internal/OpenApiTools/components/Operation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ const generateComment = (operation: OpenApi.Operation): string => {
return comments.join(EOL);
};

// 使わない可能性あり
export const generateNamespace = (
entryPoint: string,
currentPoint: string,
Expand All @@ -40,6 +39,7 @@ export const generateNamespace = (
parentPath: string,
name: string,
operation: OpenApi.Operation,
pathItemParameters: OpenApi.PathItem["parameters"],
context: ToTypeNode.Context,
converterContext: ConverterContext.Types,
): void => {
Expand All @@ -55,7 +55,9 @@ export const generateNamespace = (
deprecated: operation.deprecated,
});

if (operation.parameters) {
const parameters = [...pathItemParameters || [], ...operation.parameters || []];

if (parameters.length > 0) {
const parameterName = "Parameter";
store.addStatement(`${basePath}/Parameter`, {
kind: "interface",
Expand All @@ -66,7 +68,7 @@ export const generateNamespace = (
store,
factory,
parameterName,
operation.parameters,
parameters,
context,
converterContext,
),
Expand Down Expand Up @@ -136,6 +138,7 @@ export const generateStatements = (
requestUri: string,
httpMethod: string, // PUT POST PATCH
operation: OpenApi.Operation,
pathItemParameters: OpenApi.PathItem["parameters"],
context: ToTypeNode.Context,
converterContext: ConverterContext.Types,
): ts.Statement[] => {
Expand All @@ -145,7 +148,8 @@ export const generateStatements = (
throw new Error("not setting operationId\n" + JSON.stringify(operation));
}
store.updateOperationState(httpMethod, requestUri, operationId, {});
if (operation.parameters) {
const parameters = [...pathItemParameters || [], ...operation.parameters || []];
if (parameters.length > 0) {
const parameterName = converterContext.generateParameterName(operationId);
statements.push(
Parameter.generateAliasInterface(
Expand All @@ -154,7 +158,7 @@ export const generateStatements = (
store,
factory,
parameterName,
operation.parameters,
parameters,
context,
converterContext,
),
Expand Down
41 changes: 29 additions & 12 deletions src/internal/OpenApiTools/components/Parameter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,32 +36,38 @@ export const generateTypeAlias = (
});
};

export const generatePropertySignature = (
export const generatePropertySignatureObject = (
entryPoint: string,
currentPoint: string,
store: Walker.Store,
factory: Factory.Type,
parameter: OpenApi.Parameter | OpenApi.Reference,
context: ToTypeNode.Context,
converterContext: ConverterContext.Types,
): ts.PropertySignature => {
): { name: string; typeElement: ts.PropertySignature } => {
if (Guard.isReference(parameter)) {
const reference = Reference.generate<OpenApi.Parameter>(entryPoint, currentPoint, parameter);
if (reference.type === "local") {
context.setReferenceHandler(currentPoint, reference);
const localRef = store.getParameter(reference.path);
return factory.PropertySignature.create({
name: converterContext.escapePropertySignatureName(localRef.name),
const name = converterContext.escapePropertySignatureName(localRef.name);
const typeElement = factory.PropertySignature.create({
name: name,
optional: false,
comment: localRef.description,
type: factory.TypeReferenceNode.create({
name: context.resolveReferencePath(currentPoint, reference.path).name,
}),
});
return {
name,
typeElement: typeElement,
};
}
const isPathProperty = reference.data.in === "path";
return factory.PropertySignature.create({
name: converterContext.escapePropertySignatureName(reference.data.name),
const name = converterContext.escapePropertySignatureName(reference.data.name);
const typeElement = factory.PropertySignature.create({
name: name,
optional: isPathProperty ? false : !reference.data.required,
comment: reference.data.description,
type: ToTypeNode.convert(
Expand All @@ -73,14 +79,23 @@ export const generatePropertySignature = (
converterContext,
),
});
return {
name,
typeElement: typeElement,
};
}
const isPathProperty = parameter.in === "path";
return factory.PropertySignature.create({
name: converterContext.escapePropertySignatureName(parameter.name),
const name = converterContext.escapePropertySignatureName(parameter.name);
const typeElement = factory.PropertySignature.create({
name: name,
optional: isPathProperty ? false : !parameter.required,
type: ToTypeNode.convert(entryPoint, currentPoint, factory, parameter.schema || { type: "null" }, context, converterContext),
comment: parameter.description,
});
return {
name,
typeElement: typeElement,
};
};

export const generatePropertySignatures = (
Expand All @@ -92,9 +107,11 @@ export const generatePropertySignatures = (
context: ToTypeNode.Context,
converterContext: ConverterContext.Types,
): ts.PropertySignature[] => {
return parameters.map(parameter => {
return generatePropertySignature(entryPoint, currentPoint, store, factory, parameter, context, converterContext);
});
const typeElementMap = parameters.reduce<Record<string, ts.PropertySignature>>((all, parameter) => {
const { name, typeElement } = generatePropertySignatureObject(entryPoint, currentPoint, store, factory, parameter, context, converterContext);
return { ...all, [name]: typeElement };
}, {});
return Object.values(typeElementMap);
};

export const generateInterface = (
Expand All @@ -103,7 +120,7 @@ export const generateInterface = (
store: Walker.Store,
factory: Factory.Type,
name: string,
parameters: [OpenApi.Parameter | OpenApi.Reference],
parameters: (OpenApi.Parameter | OpenApi.Reference)[],
context: ToTypeNode.Context,
converterContext: ConverterContext.Types,
): ts.InterfaceDeclaration => {
Expand Down
31 changes: 16 additions & 15 deletions src/internal/OpenApiTools/components/PathItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,28 +29,28 @@ export const generateNamespace = (
comment: Servers.addComment([topComment, pathItem.description], pathItem.servers),
});
if (pathItem.get) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "GET", pathItem.get, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "GET", pathItem.get, pathItem.parameters, context, converterContext);
}
if (pathItem.put) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "PUT", pathItem.put, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "PUT", pathItem.put, pathItem.parameters,context, converterContext);
}
if (pathItem.post) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "POST", pathItem.post, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "POST", pathItem.post, pathItem.parameters, context, converterContext);
}
if (pathItem.delete) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "DELETE", pathItem.delete, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "DELETE", pathItem.delete, pathItem.parameters, context, converterContext);
}
if (pathItem.options) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "OPTIONS", pathItem.options, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "OPTIONS", pathItem.options, pathItem.parameters, context, converterContext);
}
if (pathItem.head) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "HEAD", pathItem.head, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "HEAD", pathItem.head, pathItem.parameters, context, converterContext);
}
if (pathItem.patch) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "PATCH", pathItem.patch, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "PATCH", pathItem.patch, pathItem.parameters, context, converterContext);
}
if (pathItem.trace) {
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "TRACE", pathItem.trace, context, converterContext);
Operation.generateNamespace(entryPoint, currentPoint, store, factory, basePath, "TRACE", pathItem.trace, pathItem.parameters, context, converterContext);
}
if (pathItem.parameters) {
Parameters.generateNamespaceWithList(entryPoint, currentPoint, store, factory, pathItem.parameters, context, converterContext);
Expand All @@ -70,22 +70,22 @@ export const generateStatements = (
const statements: ts.Statement[][] = [];
if (pathItem.get) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "GET", pathItem.get, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "GET", pathItem.get, pathItem.parameters, context, converterContext),
);
}
if (pathItem.put) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "PUT", pathItem.put, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "PUT", pathItem.put, pathItem.parameters, context, converterContext),
);
}
if (pathItem.post) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "POST", pathItem.post, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "POST", pathItem.post, pathItem.parameters, context, converterContext),
);
}
if (pathItem.delete) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "DELETE", pathItem.delete, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "DELETE", pathItem.delete, pathItem.parameters, context, converterContext),
);
}
if (pathItem.options) {
Expand All @@ -98,24 +98,25 @@ export const generateStatements = (
requestUri,
"OPTIONS",
pathItem.options,
pathItem.parameters,
context,
converterContext,
),
);
}
if (pathItem.head) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "HEAD", pathItem.head, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "HEAD", pathItem.head, pathItem.parameters, context, converterContext),
);
}
if (pathItem.patch) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "PATCH", pathItem.patch, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "PATCH", pathItem.patch, pathItem.parameters, context, converterContext),
);
}
if (pathItem.trace) {
statements.push(
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "TRACE", pathItem.trace, context, converterContext),
Operation.generateStatements(entryPoint, currentPoint, store, factory, requestUri, "TRACE", pathItem.trace, pathItem.parameters, context, converterContext),
);
}
// if (pathItem.parameters) {
Expand Down
2 changes: 1 addition & 1 deletion src/typedef/OpenApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ export interface Operation {
description?: string;
externalDocs?: ExternalDocumentation;
operationId?: string;
parameters?: [Parameter | Reference];
parameters?: (Parameter | Reference)[];
requestBody?: RequestBody | Reference;
responses?: Responses;
callbacks?: Record<string, Callback | Reference>;
Expand Down
Loading