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

chore(core): add dev feature tag for openapi.json #6025

Merged
merged 1 commit into from
Jun 21, 2024
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
4 changes: 2 additions & 2 deletions packages/core/src/routes/swagger/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
buildTag,
findSupplementFiles,
normalizePath,
removeCloudOnlyOperations,
removeUnnecessaryOperations,
validateSupplement,
validateSwaggerDocument,
} from './utils/general.js';
Expand Down Expand Up @@ -196,7 +196,7 @@ export default function swaggerRoutes<T extends AnonymousRouter, R extends Route
const supplementPaths = await findSupplementFiles(routesDirectory);
const supplementDocuments = await Promise.all(
supplementPaths.map(async (path) =>
removeCloudOnlyOperations(
removeUnnecessaryOperations(
// eslint-disable-next-line no-restricted-syntax -- trust the type here as we'll validate it later
JSON.parse(await fs.readFile(path, 'utf8')) as DeepPartial<OpenAPIV3.Document>
)
Expand Down
27 changes: 20 additions & 7 deletions packages/core/src/routes/swagger/utils/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@

/** The tag name used in the supplement document to indicate that the operation is cloud only. */
const cloudOnlyTag = 'Cloud only';
/** The tag name is used in the supplement document to indicate that the corresponding API operation is a dev feature. */
const devFeatureTag = 'Dev feature';

/**
* Get the root component name from the given absolute path.
Expand Down Expand Up @@ -114,10 +116,12 @@
if (
isKeyInObject(operation, 'tags') &&
Array.isArray(operation.tags) &&
(operation.tags.length > 1 || operation.tags[0] !== cloudOnlyTag)
!operation.tags.every(
(tag) => typeof tag === 'string' && [cloudOnlyTag, devFeatureTag].includes(tag)
)

Check warning on line 121 in packages/core/src/routes/swagger/utils/general.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/swagger/utils/general.ts#L119-L121

Added lines #L119 - L121 were not covered by tests
) {
throw new TypeError(
`Cannot use \`tags\` in supplement document on path \`${path}\` and operation \`${method}\` except for tag \`${cloudOnlyTag}\`. Define tags in the document root instead.`
`Cannot use \`tags\` in supplement document on path \`${path}\` and operation \`${method}\` except for tag \`${cloudOnlyTag}\` and \`${devFeatureTag}\`. Define tags in the document root instead.`

Check warning on line 124 in packages/core/src/routes/swagger/utils/general.ts

View check run for this annotation

Codecov / codecov/patch

packages/core/src/routes/swagger/utils/general.ts#L124

Added line #L124 was not covered by tests
);
}
}
Expand Down Expand Up @@ -216,19 +220,28 @@
* **CAUTION**: This function mutates the input document.
*
* Remove operations (path + method) that are tagged with `Cloud only` if the application is not
* running in the cloud. This will prevent the swagger validation from failing in the OSS
* environment.
* running in the cloud and remove operations with `Dev feature` tag if Logto's `isDevFeatureEnabled` flag
* is set to be false.
*
* This will prevent the swagger validation from failing in the OSS environment.
*
*/
export const removeCloudOnlyOperations = (
// eslint-disable-next-line complexity
export const removeUnnecessaryOperations = (
document: DeepPartial<OpenAPIV3.Document>
): DeepPartial<OpenAPIV3.Document> => {
if (EnvSet.values.isCloud || !document.paths) {
const { isCloud, isDevFeaturesEnabled } = EnvSet.values;
if ((isCloud && isDevFeaturesEnabled) || !document.paths) {
return document;
}

for (const [path, pathItem] of Object.entries(document.paths)) {
for (const method of Object.values(OpenAPIV3.HttpMethods)) {
if (pathItem?.[method]?.tags?.includes(cloudOnlyTag)) {
if (
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
(!isCloud && pathItem?.[method]?.tags?.includes(cloudOnlyTag)) ||
(!isDevFeaturesEnabled && pathItem?.[method]?.tags?.includes(devFeatureTag))
) {
// eslint-disable-next-line @silverhand/fp/no-delete, @typescript-eslint/no-dynamic-delete -- intended
delete pathItem[method];
}
Expand Down
Loading