mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-07 19:22:14 +09:00
179 lines
5.8 KiB
TypeScript
179 lines
5.8 KiB
TypeScript
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
import {
|
|
APIErrorCodeSchema,
|
|
Base64ImageTypeSchema,
|
|
DiscriminatorTypeSchema,
|
|
EmailTypeSchema,
|
|
Int32TypeSchema,
|
|
Int64StringTypeSchema,
|
|
Int64TypeSchema,
|
|
LocaleSchema,
|
|
NonNegativeSafeIntegerTypeSchema,
|
|
PasswordTypeSchema,
|
|
PhoneNumberTypeSchema,
|
|
SnowflakeTypeSchema,
|
|
UnsignedInt64TypeSchema,
|
|
UsernameTypeSchema,
|
|
ValidationErrorItemSchema,
|
|
} from '@fluxer/openapi/src/converters/BuiltInSchemas';
|
|
import type {OpenAPISchema, OpenAPISecurityScheme} from '@fluxer/openapi/src/OpenAPITypes';
|
|
import {ERROR_SCHEMA} from '@fluxer/openapi/src/registry/ResponseRegistry';
|
|
|
|
const ORDERED_TAG_NAMES = [
|
|
'Auth',
|
|
'Users',
|
|
'Guilds',
|
|
'Channels',
|
|
'Invites',
|
|
'Packs',
|
|
'Webhooks',
|
|
'OAuth2',
|
|
'Gateway',
|
|
'Search',
|
|
'Read States',
|
|
'KLIPY',
|
|
'Saved Media',
|
|
'Themes',
|
|
'Downloads',
|
|
'Reports',
|
|
'Instance',
|
|
'Admin',
|
|
'Billing',
|
|
'Premium',
|
|
'Gifts',
|
|
'RPC',
|
|
] as const;
|
|
interface TagDefinition {
|
|
readonly name: (typeof ORDERED_TAG_NAMES)[number];
|
|
readonly description: string;
|
|
}
|
|
const TAG_DEFINITIONS: ReadonlyArray<TagDefinition> = [
|
|
{name: 'Auth', description: 'Authentication and session management'},
|
|
{name: 'Users', description: 'User accounts and profiles'},
|
|
{name: 'Guilds', description: 'Guild management'},
|
|
{name: 'Channels', description: 'Channel management and messaging'},
|
|
{name: 'Invites', description: 'Guild invitations'},
|
|
{name: 'Packs', description: 'Sticker and emoji packs'},
|
|
{name: 'Webhooks', description: 'Webhook management'},
|
|
{name: 'OAuth2', description: 'OAuth2 applications and authorization'},
|
|
{name: 'Gateway', description: 'WebSocket gateway information'},
|
|
{name: 'Search', description: 'Search functionality'},
|
|
{name: 'Read States', description: 'Message read state tracking'},
|
|
{name: 'KLIPY', description: 'GIF search via KLIPY'},
|
|
{name: 'Saved Media', description: 'User saved media management'},
|
|
{name: 'Themes', description: 'User interface themes'},
|
|
{name: 'Downloads', description: 'App downloads'},
|
|
{name: 'Reports', description: 'Content reporting'},
|
|
{name: 'Instance', description: 'Instance configuration and info'},
|
|
{name: 'Admin', description: 'Administrative operations for instance management'},
|
|
{name: 'Billing', description: 'Subscription and payment management via Stripe'},
|
|
{name: 'Premium', description: 'Premium subscription features and benefits'},
|
|
{name: 'Gifts', description: 'Gift codes and redemption'},
|
|
{name: 'RPC', description: 'Remote procedure call endpoints for internal operations'},
|
|
] as const;
|
|
const TAG_DESCRIPTIONS = TAG_DEFINITIONS.reduce<Record<(typeof ORDERED_TAG_NAMES)[number], string>>(
|
|
(acc, definition) => {
|
|
acc[definition.name] = definition.description;
|
|
return acc;
|
|
},
|
|
{} as Record<(typeof ORDERED_TAG_NAMES)[number], string>,
|
|
);
|
|
const SECURITY_SCHEMES: Record<string, OpenAPISecurityScheme> = {
|
|
botToken: {
|
|
type: 'apiKey',
|
|
in: 'header',
|
|
name: 'Authorization',
|
|
description:
|
|
'Bot token: `Authorization: Bot <token>`. This is the primary authentication method for bot applications.',
|
|
},
|
|
oauth2Token: {
|
|
type: 'oauth2',
|
|
description: 'OAuth2 access token: `Authorization: Bearer <token>`.',
|
|
flows: {
|
|
authorizationCode: {
|
|
authorizationUrl: '/oauth2/authorize',
|
|
tokenUrl: '/oauth2/token',
|
|
scopes: {
|
|
identify: 'Read basic user identity information.',
|
|
email: 'Read the user email address.',
|
|
guilds: 'Read guild membership information for the current user.',
|
|
connections: 'Read linked third-party account connections for the current user.',
|
|
bot: 'Add a bot user to a guild.',
|
|
},
|
|
},
|
|
},
|
|
},
|
|
bearerToken: {
|
|
type: 'http',
|
|
scheme: 'bearer',
|
|
description:
|
|
'Bearer-form token: `Authorization: Bearer <token>`. Use `oauth2Token` when a route requires OAuth2 scopes.',
|
|
},
|
|
sessionToken: {
|
|
type: 'apiKey',
|
|
in: 'header',
|
|
name: 'Authorization',
|
|
description:
|
|
'User session token from login: `Authorization: <token>` (no prefix). Prefer a bot account over user tokens where possible.',
|
|
},
|
|
adminApiKey: {
|
|
type: 'apiKey',
|
|
in: 'header',
|
|
name: 'Authorization',
|
|
description: 'Admin API key: `Authorization: Admin <token>`. Only valid for `/admin/*` endpoints.',
|
|
},
|
|
};
|
|
const BUILT_IN_SCHEMAS: ReadonlyArray<readonly [string, OpenAPISchema]> = [
|
|
['Error', ERROR_SCHEMA],
|
|
['APIErrorCode', APIErrorCodeSchema],
|
|
['SnowflakeType', SnowflakeTypeSchema],
|
|
['Int32Type', Int32TypeSchema],
|
|
['NonNegativeSafeIntegerType', NonNegativeSafeIntegerTypeSchema],
|
|
['Int64Type', Int64TypeSchema],
|
|
['Int64StringType', Int64StringTypeSchema],
|
|
['UnsignedInt64Type', UnsignedInt64TypeSchema],
|
|
['UsernameType', UsernameTypeSchema],
|
|
['DiscriminatorType', DiscriminatorTypeSchema],
|
|
['EmailType', EmailTypeSchema],
|
|
['PasswordType', PasswordTypeSchema],
|
|
['PhoneNumberType', PhoneNumberTypeSchema],
|
|
['Base64ImageType', Base64ImageTypeSchema],
|
|
['Locale', LocaleSchema],
|
|
['ValidationErrorItem', ValidationErrorItemSchema],
|
|
];
|
|
interface IOpenAPIGeneratorCatalog {
|
|
readonly excluded: {
|
|
readonly prefixes: ReadonlyArray<string>;
|
|
readonly paths: ReadonlySet<string>;
|
|
};
|
|
readonly tags: {
|
|
readonly order: ReadonlyArray<string>;
|
|
readonly descriptions: Record<string, string>;
|
|
};
|
|
readonly securitySchemes: Record<string, OpenAPISecurityScheme>;
|
|
readonly builtInSchemas: ReadonlyArray<readonly [string, OpenAPISchema]>;
|
|
}
|
|
export const OpenAPIGeneratorCatalog: IOpenAPIGeneratorCatalog = {
|
|
excluded: {
|
|
prefixes: ['/test/'],
|
|
paths: new Set<string>(['/_rpc', '/oauth2/authorize']),
|
|
},
|
|
tags: {
|
|
order: ORDERED_TAG_NAMES,
|
|
descriptions: TAG_DESCRIPTIONS,
|
|
},
|
|
securitySchemes: SECURITY_SCHEMES,
|
|
builtInSchemas: BUILT_IN_SCHEMAS,
|
|
};
|
|
export function isExcludedRoutePath(routePath: string): boolean {
|
|
if (OpenAPIGeneratorCatalog.excluded.paths.has(routePath)) {
|
|
return true;
|
|
}
|
|
for (const prefix of OpenAPIGeneratorCatalog.excluded.prefixes) {
|
|
if (routePath.startsWith(prefix) || routePath === prefix.slice(0, -1)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|