Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ app.run(); // Open http://localhost:3030/api/docs
| `enabled` | `true` | Convenience flag—skip calling `registerRoutes` if you want to hide docs. |
| `path` | `'/api/docs'` | Mount path for Swagger UI; value is used as-is. |
| `swaggerJsonPath` | `undefined` | Path relative to mount path where OpenAPI schema is served as JSON. When set, Swagger UI loads the schema from this endpoint instead of embedding it directly. |
| `authPolicy` | `AuthPolicy.disabled` | Controls authentication for the Swagger UI page itself. |

Usage example:

Expand Down
2 changes: 2 additions & 0 deletions src/openapi-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ export function createOpenApiRegistry(config: OpenApiRegistryConfig) {
schemas: {},
securitySchemes: {},
},
authPolicy: config.authPolicy || AuthPolicy.disabled,
Comment thread
sjorobekov marked this conversation as resolved.
Outdated
};

if (config.contact) {
Expand Down Expand Up @@ -403,6 +404,7 @@ export function createOpenApiRegistry(config: OpenApiRegistryConfig) {
return {
...routes,
[`MOUNT ${mountPath}`]: {
authPolicy: config.authPolicy || AuthPolicy.disabled,
Comment thread
sjorobekov marked this conversation as resolved.
Outdated
handler: ({router}: Parameters<AppMountHandler>[0]) => {
const schema = getOpenApiSchema();

Expand Down
35 changes: 34 additions & 1 deletion src/tests/openapi-registry.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import {createOpenApiRegistry} from '../openapi-registry';
import {apiKeyAuth, bearerAuth} from '../security-schemas';
import {AppRoutes, AuthPolicy, RouteContract, withContract} from '@gravity-ui/expresskit';
import {
AppMountDescription,
AppRoutes,
AuthPolicy,
RouteContract,
withContract,
} from '@gravity-ui/expresskit';
import {NodeKit} from '@gravity-ui/nodekit';
import {z} from 'zod';

Expand Down Expand Up @@ -669,6 +675,33 @@ describe('openapi-registry', () => {

const registeredRoutes = registerRoutes(routes, nodekit);
expect(registeredRoutes).toHaveProperty('MOUNT /api/docs');
const mountRoute = registeredRoutes['MOUNT /api/docs'] as AppMountDescription;
expect(mountRoute).toBeDefined();
expect(mountRoute.authPolicy).toBe(AuthPolicy.disabled);
});

it('should apply configured authPolicy to MOUNT route', () => {
const {registerRoutes} = createOpenApiRegistry({
title: 'Test API',
authPolicy: AuthPolicy.required,
});

const routes = {
'GET /test': {
handler: withContract({
request: {},
response: {content: {200: z.object({})}},
})(async (_req, res) => {
res.sendTyped(200, {});
}),
},
};

const registeredRoutes = registerRoutes(routes, nodekit);
const mountRoute = registeredRoutes['MOUNT /api/docs'] as AppMountDescription;

expect(mountRoute).toBeDefined();
expect(mountRoute.authPolicy).toBe(AuthPolicy.required);
});

it('should handle routes with tags and description', () => {
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {SwaggerUiOptions} from 'swagger-ui-express';
import type {AppRouteDescription} from '@gravity-ui/expresskit';
import type {AppRouteDescription, AuthPolicy} from '@gravity-ui/expresskit';

// OpenAPI Security Scheme Object types
export interface SecuritySchemeObject {
Expand Down Expand Up @@ -64,6 +64,7 @@ export interface OpenApiRegistryConfig {
}[];
swaggerUi?: SwaggerUiOptions;
swaggerJsonPath?: string;
authPolicy?: AuthPolicy;
transformOperation?: (
operation: OpenApiOperation,
context: {
Expand Down
Loading