Skip to content

Commit

Permalink
fix: Create one endpoint per path, not per method (#123)
Browse files Browse the repository at this point in the history
* Create one endpoint per path, not per method

* ci: Generate code

* Remove console log

* Format

* Fix getSemanticMethod

* Fix semantic method priority order

* ci: Generate code

* ci: Generate code

---------

Co-authored-by: Seam Bot <devops@getseam.com>
  • Loading branch information
andrii-balitskyi and seambot authored Oct 16, 2024
1 parent aa98630 commit fc79f4b
Show file tree
Hide file tree
Showing 5 changed files with 861 additions and 3,153 deletions.
65 changes: 41 additions & 24 deletions src/lib/blueprint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,8 @@ const createRoute = async (
throw new Error(`Could not resolve name for route at ${path}`)
}

const endpoint = await createEndpoint(path, pathItem, context)

return {
path: routePath,
name,
Expand All @@ -398,7 +400,7 @@ const createRoute = async (
isDraft: false,
}
: null,
endpoints: await createEndpoints(path, pathItem, context),
endpoints: endpoint != null ? [endpoint] : [],
subroutes: [],
isUndocumented: false,
isDeprecated: false,
Expand Down Expand Up @@ -446,34 +448,41 @@ const addNamespaceStatusToRoute = (
}
}

const createEndpoints = async (
const createEndpoint = async (
path: string,
pathItem: OpenapiPathItem,
context: Context,
): Promise<Endpoint[]> => {
): Promise<Endpoint | null> => {
const validMethods: Method[] = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH']
const validOperations = Object.entries(pathItem).filter(
([method, operation]) =>
validMethods.includes(method.toUpperCase() as Method) &&
typeof operation === 'object' &&
operation !== null,
)
const supportedMethods = validOperations.map(
([method]) => method.toUpperCase() as Method,
)

return await Promise.all(
Object.entries(pathItem)
.filter(
([method, operation]) =>
validMethods.includes(method.toUpperCase() as Method) &&
typeof operation === 'object' &&
operation !== null,
)
.map(async ([method, operation]) => {
const uppercaseMethod = method.toUpperCase() as Method
return await createEndpoint(
[uppercaseMethod],
operation as OpenapiOperation,
path,
context,
)
}),
const validOperation = validOperations[0]
if (validOperation == null) {
// eslint-disable-next-line no-console
console.warn(`No valid operations found for ${path}`)

return null
}

const [_, operation] = validOperation

return await createEndpointFromOperation(
supportedMethods,
operation as OpenapiOperation,
path,
context,
)
}

const createEndpoint = async (
const createEndpointFromOperation = async (
methods: Method[],
operation: OpenapiOperation,
path: string,
Expand Down Expand Up @@ -505,6 +514,7 @@ const createEndpoint = async (
const draftMessage = parsedOperation['x-draft']

const request = createRequest(methods, operation, path)
const response = createResponse(operation, path)

const endpoint: Omit<Endpoint, 'codeSamples'> = {
title,
Expand All @@ -517,7 +527,7 @@ const createEndpoint = async (
undocumentedMessage,
isDraft,
draftMessage,
response: createResponse(operation, path),
response,
request,
}

Expand Down Expand Up @@ -908,8 +918,15 @@ export const getSemanticMethod = (methods: Method[]): Method => {
return methods[0]!
}

const priorityOrder: Method[] = ['PUT', 'PATCH', 'POST', 'GET', 'DELETE']
return methods.find((m) => priorityOrder.includes(m)) ?? 'POST'
const priorityOrder: Method[] = ['PUT', 'PATCH', 'GET', 'DELETE', 'POST']

for (const method of priorityOrder) {
if (methods.includes(method)) {
return method
}
}

return 'POST'
}

export const getPreferredMethod = (
Expand Down
Loading

0 comments on commit fc79f4b

Please sign in to comment.