0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2024-12-16 20:26:19 -05:00

refactor: undo changes on swagger API utils and hide SAML app APIs

This commit is contained in:
Darcy Ye 2024-11-26 11:54:41 +08:00
parent 0795ba9364
commit ccb47b7443
No known key found for this signature in database
GPG key ID: B46F4C07EDEFC610
5 changed files with 20 additions and 44 deletions

View file

@ -12,7 +12,7 @@
}, },
"scripts": { "scripts": {
"precommit": "lint-staged", "precommit": "lint-staged",
"copy:apidocs": "rsync -a -m --include '*/' --include '*.openapi.json' --exclude '*' src/routes/ build/routes/ && rsync -a -m --include '*/' --include '*.openapi.json' --exclude '*' src/saml-applications/ build/saml-applications/", "copy:apidocs": "rsync -a -m --include '*/' --include '*.openapi.json' --exclude '*' src/routes/ build/routes/",
"check": "tsc --noEmit", "check": "tsc --noEmit",
"build": "tsup", "build": "tsup",
"build:test": "rm -rf build/ && tsc -p tsconfig.test.json --sourcemap && pnpm run copy:apidocs", "build:test": "rm -rf build/ && tsc -p tsconfig.test.json --sourcemap && pnpm run copy:apidocs",

View file

@ -47,17 +47,11 @@ const managementApiIdentifiableEntityNames = Object.freeze([
'organization-role', 'organization-role',
'organization-scope', 'organization-scope',
'organization-invitation', 'organization-invitation',
'saml-application',
]); ]);
/** Additional tags that cannot be inferred from the path. */ /** Additional tags that cannot be inferred from the path. */
const additionalTags = Object.freeze( const additionalTags = Object.freeze(
condArray<string>( condArray<string>('Organization applications', 'Custom UI assets', 'Organization users')
'Organization applications',
'Custom UI assets',
'Organization users',
EnvSet.values.isDevFeaturesEnabled && 'SAML applications'
)
); );
export const buildManagementApiBaseDocument = ( export const buildManagementApiBaseDocument = (
@ -213,7 +207,7 @@ export const buildUserApiBaseDocument = (
}); });
export const getSupplementDocuments = async ( export const getSupplementDocuments = async (
directory = 'build', directory = 'routes',
option?: FindSupplementFilesOptions option?: FindSupplementFilesOptions
) => { ) => {
// Find supplemental documents // Find supplemental documents

View file

@ -35,7 +35,6 @@ const tagMap = new Map([
['sso-connectors', 'SSO connectors'], ['sso-connectors', 'SSO connectors'],
['sso-connector-providers', 'SSO connector providers'], ['sso-connector-providers', 'SSO connector providers'],
['.well-known', 'Well-known'], ['.well-known', 'Well-known'],
['saml-applications', 'SAML applications'],
]); ]);
/** /**
@ -68,43 +67,25 @@ export const findSupplementFiles = async (
option?: FindSupplementFilesOptions option?: FindSupplementFilesOptions
) => { ) => {
const result: string[] = []; const result: string[] = [];
const files = await fs.readdir(directory);
for (const file of files) { for (const file of await fs.readdir(directory)) {
const fullPath = path.join(directory, file); const stats = await fs.stat(path.join(directory, file));
const stats = await fs.stat(fullPath);
if (stats.isDirectory()) { if (
// Skip if the current directory is excluded // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
if (option?.excludeDirectories?.includes(file)) { option?.excludeDirectories?.includes(file) ||
(option?.includeDirectories && !option.includeDirectories.includes(file))
) {
continue; continue;
} }
// Recursively search subdirectories if (stats.isDirectory()) {
const subFiles = await findSupplementFiles(fullPath, option); result.push(...(await findSupplementFiles(path.join(directory, file))));
result.push(...subFiles);
} else if (file.endsWith('.openapi.json')) { } else if (file.endsWith('.openapi.json')) {
result.push(fullPath); result.push(path.join(directory, file));
} }
} }
// If `includeDirectories` is specified, only keep files that contain the specified subdirectories
if (option?.includeDirectories?.length && option.includeDirectories.length > 0) {
return result.filter((filePath) =>
// The fallback to empty array will never happen here, as we've already checked the length of option.`includeDirectories` before entering this branch
(option.includeDirectories ?? []).some((directory) => filePath.includes(`/${directory}/`))
);
}
// If `excludeDirectories` is specified, exclude files that contain the specified subdirectories
if (option?.excludeDirectories?.length && option.excludeDirectories.length > 0) {
return result.filter(
(filePath) =>
// The fallback to empty array will never happen here, as we've already checked the length of option.`excludeDirectories` before entering this branch
!(option.excludeDirectories ?? []).some((directory) => filePath.includes(`/${directory}/`))
);
}
return result; return result;
}; };
/* eslint-enable @silverhand/fp/no-mutating-methods, no-await-in-loop */ /* eslint-enable @silverhand/fp/no-mutating-methods, no-await-in-loop */
@ -157,9 +138,7 @@ const validateSupplementPaths = (
if ( if (
isKeyInObject(operation, 'tags') && isKeyInObject(operation, 'tags') &&
Array.isArray(operation.tags) && Array.isArray(operation.tags) &&
!operation.tags.every( !operation.tags.every((tag) => typeof tag === 'string' && reservedTags.has(tag))
(tag) => typeof tag === 'string' && [cloudOnlyTag, devFeatureTag].includes(tag)
)
) { ) {
throw new TypeError( throw new TypeError(
`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.` `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.`

View file

@ -138,6 +138,9 @@ export const buildRouterObjects = <T extends UnknownRouter>(routers: T[], option
.map((method) => method.toLowerCase()) .map((method) => method.toLowerCase())
// There is no need to show the HEAD method. // There is no need to show the HEAD method.
.filter((method): method is OpenAPIV3.HttpMethods => method !== 'head') .filter((method): method is OpenAPIV3.HttpMethods => method !== 'head')
// TODO: Remove this and bring back `/saml-applications` routes before release.
// Exclude `/saml-applications` routes for now.
.filter(() => !routerPath.startsWith('/saml-applications'))
.map((httpMethod) => { .map((httpMethod) => {
const path = normalizePath(routerPath); const path = normalizePath(routerPath);
const operation = buildOperation(httpMethod, stack, routerPath, isAuthGuarded); const operation = buildOperation(httpMethod, stack, routerPath, isAuthGuarded);

View file

@ -30,7 +30,7 @@ export default function openapiRoutes<T extends AnonymousRouter, R extends Unkno
const { pathMap, tags } = groupRoutesByPath(managementApiRoutes); const { pathMap, tags } = groupRoutesByPath(managementApiRoutes);
// Find supplemental documents // Find supplemental documents
const supplementDocuments = await getSupplementDocuments('build', { const supplementDocuments = await getSupplementDocuments('routes', {
excludeDirectories: ['experience', 'interaction', 'account', 'verification'], excludeDirectories: ['experience', 'interaction', 'account', 'verification'],
}); });
const baseDocument = buildManagementApiBaseDocument(pathMap, tags, ctx.request.origin); const baseDocument = buildManagementApiBaseDocument(pathMap, tags, ctx.request.origin);