docs-utils: fix auth detection + added query params (#8997)
This commit is contained in:
1 parent
13e4f4aeb5
commit
090cb36543
1 file changed
+93
-31
@@ -42,6 +42,12 @@ export type OasArea = "admin" | "store"
|
|||||||
|
|
||||||
type ParameterType = "query" | "path"
|
type ParameterType = "query" | "path"
|
||||||
|
|
||||||
|
type AuthRequests = {
|
||||||
|
exact?: string
|
||||||
|
startsWith?: string
|
||||||
|
requiresAuthentication: boolean
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* OAS generator for API routes. It extends the {@link FunctionKindGenerator}
|
* OAS generator for API routes. It extends the {@link FunctionKindGenerator}
|
||||||
* since API routes are functions.
|
* since API routes are functions.
|
||||||
@@ -55,7 +61,21 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
"RequestWithContext",
|
"RequestWithContext",
|
||||||
"AuthenticatedMedusaRequest",
|
"AuthenticatedMedusaRequest",
|
||||||
]
|
]
|
||||||
|
// as it's not always possible to detect authenticated request
|
||||||
|
// use this to override the default detection logic.
|
||||||
|
readonly AUTH_REQUESTS: AuthRequests[] = [
|
||||||
|
{
|
||||||
|
exact: "store/orders",
|
||||||
|
requiresAuthentication: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
startsWith: "store/customers/me",
|
||||||
|
requiresAuthentication: true,
|
||||||
|
},
|
||||||
|
]
|
||||||
readonly RESPONSE_TYPE_NAMES = ["MedusaResponse"]
|
readonly RESPONSE_TYPE_NAMES = ["MedusaResponse"]
|
||||||
|
readonly FIELD_QUERY_PARAMS = ["fields", "expand"]
|
||||||
|
readonly PAGINATION_QUERY_PARAMS = ["limit", "offset", "order"]
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This map collects tags of all the generated OAS, then, once the generation process finishes,
|
* This map collects tags of all the generated OAS, then, once the generation process finishes,
|
||||||
@@ -452,6 +472,10 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
type: "query",
|
type: "query",
|
||||||
})
|
})
|
||||||
|
|
||||||
|
if (!oas.parameters.length) {
|
||||||
|
oas.parameters = undefined
|
||||||
|
}
|
||||||
|
|
||||||
// update request schema
|
// update request schema
|
||||||
const existingRequestBodySchema = (
|
const existingRequestBodySchema = (
|
||||||
oas.requestBody as OpenAPIV3.RequestBodyObject
|
oas.requestBody as OpenAPIV3.RequestBodyObject
|
||||||
@@ -461,7 +485,10 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
newSchema: requestSchema,
|
newSchema: requestSchema,
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!updatedRequestSchema) {
|
if (
|
||||||
|
!updatedRequestSchema ||
|
||||||
|
Object.keys(updatedRequestSchema).length === 0
|
||||||
|
) {
|
||||||
// if there's no request schema, remove it from the OAS
|
// if there's no request schema, remove it from the OAS
|
||||||
delete oas.requestBody
|
delete oas.requestBody
|
||||||
} else {
|
} else {
|
||||||
@@ -531,19 +558,26 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
delete oas.responses![oldResponseStatus]
|
delete oas.responses![oldResponseStatus]
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the response schema
|
if (updatedResponseSchema && Object.keys(updatedResponseSchema).length) {
|
||||||
oas.responses![newStatus] = {
|
// update the response schema
|
||||||
description: "OK",
|
oas.responses![newStatus] = {
|
||||||
content: {
|
description: "OK",
|
||||||
"application/json": {
|
content: {
|
||||||
schema: updatedResponseSchema
|
"application/json": {
|
||||||
? this.oasSchemaHelper.namedSchemaToReference(
|
schema: updatedResponseSchema
|
||||||
updatedResponseSchema
|
? this.oasSchemaHelper.namedSchemaToReference(
|
||||||
) ||
|
updatedResponseSchema
|
||||||
this.oasSchemaHelper.schemaChildrenToRefs(updatedResponseSchema)
|
) ||
|
||||||
: updatedResponseSchema,
|
this.oasSchemaHelper.schemaChildrenToRefs(
|
||||||
|
updatedResponseSchema
|
||||||
|
)
|
||||||
|
: updatedResponseSchema,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
}
|
||||||
|
} else if (oldResponseStatus) {
|
||||||
|
// delete the old response schema
|
||||||
|
delete oas.responses![oldResponseStatus]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -733,11 +767,21 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
.statements.some((statement) =>
|
.statements.some((statement) =>
|
||||||
statement.getText().includes("AUTHENTICATE = false")
|
statement.getText().includes("AUTHENTICATE = false")
|
||||||
)
|
)
|
||||||
|
const hasAuthenticationOverride =
|
||||||
|
this.AUTH_REQUESTS.find((authRequest) => {
|
||||||
|
return (
|
||||||
|
authRequest.exact === oasPath ||
|
||||||
|
(authRequest.startsWith && oasPath.startsWith(authRequest.startsWith))
|
||||||
|
)
|
||||||
|
})?.requiresAuthentication === true
|
||||||
const isAdminAuthenticated =
|
const isAdminAuthenticated =
|
||||||
!isAuthenticationDisabled && oasPath.startsWith("admin")
|
(!isAuthenticationDisabled || hasAuthenticationOverride) &&
|
||||||
const isStoreAuthenticated =
|
oasPath.startsWith("admin")
|
||||||
!isAuthenticationDisabled && oasPath.startsWith("store/customers/me")
|
const isStoreAuthenticated = hasAuthenticationOverride
|
||||||
const isAuthenticated = isAdminAuthenticated || isStoreAuthenticated
|
? oasPath.startsWith("store")
|
||||||
|
: !isAuthenticationDisabled && oasPath.startsWith("store")
|
||||||
|
const isAuthenticated =
|
||||||
|
isAdminAuthenticated || isStoreAuthenticated || hasAuthenticationOverride
|
||||||
|
|
||||||
return {
|
return {
|
||||||
isAdminAuthenticated,
|
isAdminAuthenticated,
|
||||||
@@ -958,13 +1002,26 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
// TODO for now I'll use the type for validatedQuery until
|
// TODO for now I'll use the type for validatedQuery until
|
||||||
// we have an actual approach to infer query types
|
// we have an actual approach to infer query types
|
||||||
const querySymbol = requestType.getProperty("validatedQuery")
|
const querySymbol = requestType.getProperty("validatedQuery")
|
||||||
if (querySymbol && this.shouldAddQueryParams(node)) {
|
if (querySymbol) {
|
||||||
|
const { shouldAddFields, shouldAddPagination } =
|
||||||
|
this.shouldAddQueryParams(node)
|
||||||
const queryType = this.checker.getTypeOfSymbol(querySymbol)
|
const queryType = this.checker.getTypeOfSymbol(querySymbol)
|
||||||
const queryTypeName = this.checker.typeToString(queryType)
|
const queryTypeName = this.checker.typeToString(queryType)
|
||||||
queryType.getProperties().forEach((property) => {
|
queryType.getProperties().forEach((property) => {
|
||||||
|
const propertyName = property.getName()
|
||||||
|
// if this is a field / pagination query parameter and
|
||||||
|
// they're not used in the route, don't add them.
|
||||||
|
if (
|
||||||
|
(this.FIELD_QUERY_PARAMS.includes(propertyName) &&
|
||||||
|
!shouldAddFields) ||
|
||||||
|
(this.PAGINATION_QUERY_PARAMS.includes(propertyName) &&
|
||||||
|
!shouldAddPagination)
|
||||||
|
) {
|
||||||
|
return
|
||||||
|
}
|
||||||
const propertyType = this.checker.getTypeOfSymbol(property)
|
const propertyType = this.checker.getTypeOfSymbol(property)
|
||||||
const descriptionOptions: SchemaDescriptionOptions = {
|
const descriptionOptions: SchemaDescriptionOptions = {
|
||||||
typeStr: property.getName(),
|
typeStr: propertyName,
|
||||||
parentName: tagName,
|
parentName: tagName,
|
||||||
rawParentName: queryTypeName,
|
rawParentName: queryTypeName,
|
||||||
node: property.valueDeclaration,
|
node: property.valueDeclaration,
|
||||||
@@ -973,13 +1030,13 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
}
|
}
|
||||||
parameters.push(
|
parameters.push(
|
||||||
this.getParameterObject({
|
this.getParameterObject({
|
||||||
name: property.getName(),
|
name: propertyName,
|
||||||
type: "query",
|
type: "query",
|
||||||
description: this.getSchemaDescription(descriptionOptions),
|
description: this.getSchemaDescription(descriptionOptions),
|
||||||
required: this.isRequired(property),
|
required: this.isRequired(property),
|
||||||
schema: this.typeToSchema({
|
schema: this.typeToSchema({
|
||||||
itemType: propertyType,
|
itemType: propertyType,
|
||||||
title: property.getName(),
|
title: propertyName,
|
||||||
descriptionOptions,
|
descriptionOptions,
|
||||||
context: "request",
|
context: "request",
|
||||||
}),
|
}),
|
||||||
@@ -2062,15 +2119,16 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
shouldAddQueryParams(node: FunctionNode): boolean {
|
shouldAddQueryParams(node: FunctionNode): {
|
||||||
const queryParamsUsageIndicators = [
|
shouldAddFields: boolean
|
||||||
`req.filterableFields`,
|
shouldAddPagination: boolean
|
||||||
`req.remoteQueryConfig`,
|
} {
|
||||||
]
|
|
||||||
const fnText = node.getText()
|
const fnText = node.getText()
|
||||||
return queryParamsUsageIndicators.some((indicator) =>
|
|
||||||
fnText.includes(indicator)
|
return {
|
||||||
)
|
shouldAddFields: fnText.includes(`req.remoteQueryConfig.fields`),
|
||||||
|
shouldAddPagination: fnText.includes(`req.remoteQueryConfig.pagination`),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hasResponseType(node: FunctionNode, oas: OpenApiOperation): boolean {
|
hasResponseType(node: FunctionNode, oas: OpenApiOperation): boolean {
|
||||||
@@ -2081,14 +2139,18 @@ class OasKindGenerator extends FunctionKindGenerator {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseContent = (oas.responses![oldResponseStatus] as OpenAPIV3.ResponseObject).content
|
const responseContent = (
|
||||||
|
oas.responses![oldResponseStatus] as OpenAPIV3.ResponseObject
|
||||||
|
).content
|
||||||
if (!responseContent) {
|
if (!responseContent) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const fnText = node.getText()
|
const fnText = node.getText()
|
||||||
|
|
||||||
return Object.keys(responseContent).some((responseType) => fnText.includes(responseType))
|
return Object.keys(responseContent).some((responseType) =>
|
||||||
|
fnText.includes(responseType)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private removeStringRegExpTypeOverlaps(types: ts.Type[]): ts.Type[] {
|
private removeStringRegExpTypeOverlaps(types: ts.Type[]): ts.Type[] {
|
||||||
|
|||||||
Reference in new issue
Block a user