Skip to content
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
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ app.run(); // Open http://localhost:3030/api/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. |
| `securitySchemes` | `undefined` | OpenAPI Security Schemes |

Usage example:

Expand All @@ -95,6 +96,13 @@ const {registerRoutes} = createOpenApiRegistry({
explorer: true,
customCss: '.topbar { display: none; }',
},
securitySchemes: {
myApiKey: {
type: 'apiKey',
in: 'header',
name: 'X-API-Key',
},
},
});
```

Expand Down
6 changes: 4 additions & 2 deletions src/openapi-registry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import {NodeKit} from '@gravity-ui/nodekit';
* @returns An object with methods to register routes, security schemes, and generate the OpenAPI schema
*/
export function createOpenApiRegistry(config: OpenApiRegistryConfig) {
const initialSecuritySchemes = {...(config.securitySchemes || {})};

const openApiSchema: OpenApiSchemaObject = {
openapi: '3.0.3',
info: {
Expand All @@ -43,7 +45,7 @@ export function createOpenApiRegistry(config: OpenApiRegistryConfig) {
paths: {},
components: {
schemas: {},
securitySchemes: {},
securitySchemes: {...initialSecuritySchemes},
},
};

Expand Down Expand Up @@ -272,7 +274,7 @@ export function createOpenApiRegistry(config: OpenApiRegistryConfig) {
openApiSchema.paths = {};
if (openApiSchema.components) {
openApiSchema.components.schemas = {};
openApiSchema.components.securitySchemes = {};
openApiSchema.components.securitySchemes = {...initialSecuritySchemes};
}
}

Expand Down
55 changes: 51 additions & 4 deletions src/tests/openapi-registry.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@ describe('openapi-registry', () => {
{url: 'https://staging.example.com', description: 'Staging'},
],
path: '/docs',
securitySchemes: {
customApiKey: {
type: 'apiKey' as const,
in: 'header' as const,
name: 'X-Custom-Key',
},
},
};

const {getOpenApiSchema} = createOpenApiRegistry(config);
Expand All @@ -58,6 +65,13 @@ describe('openapi-registry', () => {
expect(schema.info.contact).toEqual(config.contact);
expect(schema.info.license).toEqual(config.license);
expect(schema.servers).toEqual(config.servers);
expect(schema.components?.securitySchemes).toEqual({
customApiKey: {
type: 'apiKey',
in: 'header',
name: 'X-Custom-Key',
},
});
});

it('should create registry with swaggerUi options', () => {
Expand Down Expand Up @@ -787,9 +801,23 @@ describe('openapi-registry', () => {
});

describe('reset', () => {
it('should reset paths and components', () => {
const {registerRoutes, getOpenApiSchema, reset} = createOpenApiRegistry({
title: 'Test API',
it('should reset paths and components to initial state', () => {
const {registerRoutes, getOpenApiSchema, reset, registerSecurityScheme} =
createOpenApiRegistry({
title: 'Test API',
securitySchemes: {
initialKey: {
type: 'apiKey',
in: 'header',
name: 'X-Initial-Key',
},
},
});

registerSecurityScheme('runtimeKey', {
type: 'apiKey',
in: 'header',
name: 'X-Runtime-Key',
});

const handler = withContract({
Expand All @@ -809,12 +837,31 @@ describe('openapi-registry', () => {

expect(schema.paths['/test']).toBeDefined();

expect(schema.components?.securitySchemes).toEqual({
initialKey: {
type: 'apiKey',
in: 'header',
name: 'X-Initial-Key',
},
runtimeKey: {
type: 'apiKey',
in: 'header',
name: 'X-Runtime-Key',
},
});

reset();
schema = getOpenApiSchema();

expect(schema.paths).toEqual({});
expect(schema.components?.schemas).toEqual({});
expect(schema.components?.securitySchemes).toEqual({});
expect(schema.components?.securitySchemes).toEqual({
initialKey: {
type: 'apiKey',
in: 'header',
name: 'X-Initial-Key',
},
});
});
});

Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ export interface OpenApiRegistryConfig {
swaggerUi?: SwaggerUiOptions;
swaggerJsonPath?: string;
authPolicy?: AuthPolicy;
securitySchemes?: Record<string, SecuritySchemeObject>;
transformOperation?: (
operation: OpenApiOperation,
context: {
Expand Down
Loading