UNPKG

@hey-api/openapi-ts

Version:

🚀 The OpenAPI to TypeScript codegen. Generate clients, SDKs, validators, and more.

180 lines (163 loc) • 4.21 kB
interface SerializeOptions<T> extends SerializePrimitiveOptions, SerializerOptions<T> {} interface SerializePrimitiveOptions { allowReserved?: boolean; name: string; } export interface SerializerOptions<T> { /** * @default true */ explode: boolean; style: T; } export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; type MatrixStyle = 'label' | 'matrix' | 'simple'; export type ObjectStyle = 'form' | 'deepObject'; type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; interface SerializePrimitiveParam extends SerializePrimitiveOptions { value: string; } export const separatorArrayExplode = (style: ArraySeparatorStyle) => { switch (style) { case 'label': return '.'; case 'matrix': return ';'; case 'simple': return ','; default: return '&'; } }; export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { switch (style) { case 'form': return ','; case 'pipeDelimited': return '|'; case 'spaceDelimited': return '%20'; default: return ','; } }; export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { switch (style) { case 'label': return '.'; case 'matrix': return ';'; case 'simple': return ','; default: return '&'; } }; export const serializeArrayParam = ({ allowReserved, explode, name, style, value, }: SerializeOptions<ArraySeparatorStyle> & { value: unknown[]; }) => { if (!explode) { const joinedValues = ( allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) ).join(separatorArrayNoExplode(style)); switch (style) { case 'label': return `.${joinedValues}`; case 'matrix': return `;${name}=${joinedValues}`; case 'simple': return joinedValues; default: return `${name}=${joinedValues}`; } } const separator = separatorArrayExplode(style); const joinedValues = value .map((v) => { if (style === 'label' || style === 'simple') { return allowReserved ? v : encodeURIComponent(v as string); } return serializePrimitiveParam({ allowReserved, name, value: v as string, }); }) .join(separator); return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues; }; export const serializePrimitiveParam = ({ allowReserved, name, value, }: SerializePrimitiveParam) => { if (value === undefined || value === null) { return ''; } if (typeof value === 'object') { throw new Error( 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', ); } return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; }; export const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly, }: SerializeOptions<ObjectSeparatorStyle> & { value: Record<string, unknown> | Date; valueOnly?: boolean; }) => { if (value instanceof Date) { return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; } if (style !== 'deepObject' && !explode) { let values: string[] = []; Object.entries(value).forEach(([key, v]) => { values = [ ...values, key, allowReserved ? (v as string) : encodeURIComponent(v as string), ]; }); const joinedValues = values.join(','); switch (style) { case 'form': return `${name}=${joinedValues}`; case 'label': return `.${joinedValues}`; case 'matrix': return `;${name}=${joinedValues}`; default: return joinedValues; } } const separator = separatorObjectExplode(style); const joinedValues = Object.entries(value) .map(([key, v]) => serializePrimitiveParam({ allowReserved, name: style === 'deepObject' ? `${name}[${key}]` : key, value: v as string, }), ) .join(separator); return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues; };