Files
smartserve/ts/openapi/openapi.coerce.ts

111 lines
2.7 KiB
TypeScript

/**
* Type coercion utilities for query parameters
* Converts string values from query params to proper types based on JSON Schema
*/
import type { TJsonSchema, IOpenApiParamMeta } from '../decorators/decorators.types.js';
/**
* Coerce a single value based on JSON Schema type
*/
export function coerceValue(value: string | undefined, schema: TJsonSchema): unknown {
if (value === undefined || value === '') {
// Return default if available
if (schema.default !== undefined) {
return schema.default;
}
return undefined;
}
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
switch (type) {
case 'integer': {
const num = parseInt(value, 10);
return isNaN(num) ? value : num;
}
case 'number': {
const num = parseFloat(value);
return isNaN(num) ? value : num;
}
case 'boolean': {
if (value === 'true' || value === '1') return true;
if (value === 'false' || value === '0' || value === '') return false;
return value;
}
case 'array': {
// Handle comma-separated values
const items = value.split(',').map(item => item.trim());
if (schema.items) {
return items.map(item => coerceValue(item, schema.items as TJsonSchema));
}
return items;
}
case 'null': {
if (value === 'null' || value === '') return null;
return value;
}
case 'object': {
// Attempt to parse JSON
try {
return JSON.parse(value);
} catch {
return value;
}
}
case 'string':
default:
return value;
}
}
/**
* Coerce all query parameters based on their schemas
*/
export function coerceQueryParams(
query: Record<string, string>,
schemas: Map<string, IOpenApiParamMeta>
): Record<string, unknown> {
const result: Record<string, unknown> = { ...query };
for (const [name, meta] of schemas) {
if (meta.schema) {
const rawValue = query[name];
const coercedValue = coerceValue(rawValue, meta.schema);
if (coercedValue !== undefined) {
result[name] = coercedValue;
} else if (meta.schema.default !== undefined) {
// Apply default when value is missing
result[name] = meta.schema.default;
}
}
}
return result;
}
/**
* Coerce path parameters based on their schemas
*/
export function coercePathParams(
params: Record<string, string>,
schemas: Map<string, IOpenApiParamMeta>
): Record<string, unknown> {
const result: Record<string, unknown> = { ...params };
for (const [name, meta] of schemas) {
if (meta.schema && params[name] !== undefined) {
result[name] = coerceValue(params[name], meta.schema);
}
}
return result;
}