Skip to content
Merged
178 changes: 178 additions & 0 deletions openapi3.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,161 @@ paths:
$ref: '#/components/responses/400BadRequest'
'500':
$ref: '#/components/responses/500InternalServerError'
/schema/index:
get:
operationId: getSchemasIndex
summary: Get searchable index of all schemas
description: Returns metadata for all schemas. Frontend can build client-side search index from this data.
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- schemas
properties:
schemas:
type: array
items:
type: object
required:
- id
- name
- path
- version
- category
properties:
id:
type: string
format: uri
name:
type: string
path:
type: string
version:
type: string
description:
type: string
category:
type: string
title:
type: string
'404':
$ref: '#/components/responses/404NotFound'
'500':
$ref: '#/components/responses/500InternalServerError'
/schema/full:
get:
operationId: getFullSchema
summary: Get comprehensive schema metadata
parameters:
- name: id
in: query
description: The id of the requested schema
required: true
schema:
$ref: '#/components/schemas/schemaId'
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- id
- name
- path
- version
- category
- rawContent
- dereferencedContent
- dependencies
- envVars
properties:
id:
type: string
format: uri
name:
type: string
path:
type: string
version:
type: string
category:
type: string
description:
type: string
title:
type: string
rawContent:
type: object
additionalProperties: true
description: Raw JSON Schema
dereferencedContent:
type: object
additionalProperties: true
description: Schema with all $refs resolved
typeContent:
type: string
nullable: true
description: TypeScript type definitions
dependencies:
type: object
required:
- parents
- children
properties:
parents:
type: array
items:
$ref: '#/components/schemas/schemaReference'
description: All parent schemas that reference this schema (nested tree structure)
children:
type: array
items:
$ref: '#/components/schemas/schemaReference'
description: All child schemas referenced by this schema (nested tree structure)
envVars:
type: array
items:
type: object
required:
- envVariable
- configPath
properties:
envVariable:
type: string
description: Environment variable name
configPath:
type: string
description: JSON path to the property (e.g., "db.host")
format:
type: string
description: Format hint (from x-env-format or format field)
type:
type: string
description: JSON schema type (e.g., "string", "integer")
required:
type: boolean
description: Whether this field is required
description:
type: string
description: Schema description
default:
description: Default value (any type)
refLink:
type: string
format: uri
description: External schema reference if this env var comes from a $ref
'400':
$ref: '#/components/responses/400BadRequest'
'404':
$ref: '#/components/responses/404NotFound'
'500':
$ref: '#/components/responses/500InternalServerError'
/capabilities:
get:
operationId: getCapabilities
Expand Down Expand Up @@ -397,6 +552,29 @@ components:
$ref: '#/components/schemas/schemaTree'
name:
type: string
schemaReference:
type: object
required:
- id
- name
properties:
id:
type: string
format: uri
description: Schema ID
name:
type: string
description: Schema name
children:
type: array
items:
$ref: '#/components/schemas/schemaReference'
description: Nested child schemas (recursive)
parents:
type: array
items:
$ref: '#/components/schemas/schemaReference'
description: Nested parent schemas (recursive)
config:
type: object
additionalProperties: false
Expand Down
154 changes: 154 additions & 0 deletions src/openapiTypes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,43 @@ export type paths = {
patch?: never;
trace?: never;
};
'/schema/index': {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/**
* Get searchable index of all schemas
* @description Returns metadata for all schemas. Frontend can build client-side search index from this data.
*/
get: operations['getSchemasIndex'];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
'/schema/full': {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
/** Get comprehensive schema metadata */
get: operations['getFullSchema'];
put?: never;
post?: never;
delete?: never;
options?: never;
head?: never;
patch?: never;
trace?: never;
};
'/capabilities': {
parameters: {
query?: never;
Expand Down Expand Up @@ -158,6 +195,19 @@ export type components = {
children: components['schemas']['schemaTree'];
name: string;
};
schemaReference: {
/**
* Format: uri
* @description Schema ID
*/
id: string;
/** @description Schema name */
name: string;
/** @description Nested child schemas (recursive) */
children?: components['schemas']['schemaReference'][];
/** @description Nested parent schemas (recursive) */
parents?: components['schemas']['schemaReference'][];
};
config: {
configName: components['schemas']['configName'];
schemaId: components['schemas']['schemaId'];
Expand Down Expand Up @@ -452,6 +502,110 @@ export interface operations {
500: components['responses']['500InternalServerError'];
};
};
getSchemasIndex: {
parameters: {
query?: never;
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': {
schemas: {
/** Format: uri */
id: string;
name: string;
path: string;
version: string;
description?: string;
category: string;
title?: string;
}[];
};
};
};
500: components['responses']['500InternalServerError'];
};
};
getFullSchema: {
parameters: {
query: {
/** @description The id of the requested schema */
id: components['schemas']['schemaId'];
};
header?: never;
path?: never;
cookie?: never;
};
requestBody?: never;
responses: {
/** @description OK */
200: {
headers: {
[name: string]: unknown;
};
content: {
'application/json': {
/** Format: uri */
id: string;
name: string;
path: string;
version: string;
category: string;
description?: string;
title?: string;
/** @description Raw JSON Schema */
rawContent: {
[key: string]: unknown;
};
/** @description Schema with all $refs resolved */
dereferencedContent: {
[key: string]: unknown;
};
/** @description TypeScript type definitions */
typeContent?: string | null;
dependencies: {
/** @description All parent schemas that reference this schema (nested tree structure) */
parents: components['schemas']['schemaReference'][];
/** @description All child schemas referenced by this schema (nested tree structure) */
children: components['schemas']['schemaReference'][];
};
envVars: {
/** @description Environment variable name */
envVariable: string;
/** @description JSON path to the property (e.g., "db.host") */
configPath: string;
/** @description Format hint (from x-env-format or format field) */
format?: string;
/** @description JSON schema type (e.g., "string", "integer") */
type?: string;
/** @description Whether this field is required */
required?: boolean;
/** @description Schema description */
description?: string;
/** @description Default value (any type) */
default?: unknown;
/**
* Format: uri
* @description External schema reference if this env var comes from a $ref
*/
refLink?: string;
}[];
};
};
};
400: components['responses']['400BadRequest'];
404: components['responses']['404NotFound'];
500: components['responses']['500InternalServerError'];
};
};
getCapabilities: {
parameters: {
query?: never;
Expand Down
28 changes: 28 additions & 0 deletions src/schemas/controllers/schemaController.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,32 @@ export class SchemaController {
const schemasTree = await this.manager.getSchemas();
return res.status(httpStatus.OK).json(schemasTree);
};

public getSchemasIndex: TypedRequestHandler<'/schema/index', 'get'> = async (req, res, next) => {
try {
const indexData = await this.manager.getSchemaIndex();

// Set cache headers
res.setHeader('Cache-Control', 'public, max-age=3600'); // 1 hour

return res.status(httpStatus.OK).json(indexData);
} catch (error) {
next(error);
}
};

public getFullSchema: TypedRequestHandler<'/schema/full', 'get'> = async (req, res, next) => {
try {
const metadata = await this.manager.getFullSchemaMetadata(req.query.id);

return res.status(httpStatus.OK).json(metadata);
} catch (error) {
if (error instanceof SchemaNotFoundError) {
(error as HttpError).status = httpStatus.NOT_FOUND;
} else if (error instanceof SchemaPathIsInvalidError) {
(error as HttpError).status = httpStatus.BAD_REQUEST;
}
next(error);
}
};
}
Loading
Loading