hey-api-builders
Version:
A custom plugin for @hey-api/openapi-ts that generates mock data builders with a lightweight custom runtime, Zod integration, or static mock generation.
130 lines (115 loc) • 3.49 kB
text/typescript
import type { Schema, MockStrategy } from '../types';
import type { ExtendedSchema } from '../types';
import { toPascal } from './string-utils';
/**
* Code generation utilities
*/
/**
* Generates with* methods for builder classes
* @param schema - JSON Schema
* @param typeName - TypeScript type name
* @returns Generated method code
*/
export function generateWithMethods(schema: Schema, typeName: string): string {
const schemaWithProps = schema as ExtendedSchema;
if (schemaWithProps.type !== 'object' || !schemaWithProps.properties) {
return '';
}
return Object.keys(schemaWithProps.properties)
.map(
(p) =>
` with${toPascal(p)}(value: types.${typeName}["${p}"]): this { this.overrides["${p}"] = value; return this; }`
)
.join('\n');
}
/**
* Generates import statements
* @param options - Import options
* @returns Import statements
*/
export function generateImports(options: {
mockStrategy: MockStrategy;
generateZod: boolean;
}): string {
const { mockStrategy, generateZod } = options;
let imports = '';
const needsZodImport = generateZod || mockStrategy === 'zod';
if (mockStrategy === 'static') {
return 'import type * as types from "./types.gen"\n\n';
}
if (mockStrategy === 'zod') {
imports += 'import { generateMockFromZodSchema } from "hey-api-builders"\n';
} else {
imports += 'import { generateMock } from "hey-api-builders"\n';
imports += 'import type { BuilderSchema } from "hey-api-builders"\n';
}
if (needsZodImport) {
imports += 'import { z } from "zod"\n';
}
imports += 'import type * as types from "./types.gen"\n\n';
return imports;
}
/**
* Generates BuilderOptions type definition
* @returns Type definition code
*/
export function generateBuilderOptionsType(): string {
return `type BuilderOptions = {
useDefault?: boolean;
useExamples?: boolean;
alwaysIncludeOptionals?: boolean;
optionalsProbability?: number | false;
omitNulls?: boolean;
}\n\n`;
}
/**
* Generates schema constants for JSF
* @param metas - Schema metadata
* @returns Schema constant code
*/
export function generateSchemaConstants(
metas: Array<{ constName: string; schema: Schema }>
): string {
const schemaEntries: string[] = [];
for (const m of metas) {
schemaEntries.push(` ${m.constName}: ${JSON.stringify(m.schema)}`);
}
return (
'const schemas = {\n' +
schemaEntries.join(',\n') +
'\n} satisfies Record<string, BuilderSchema>\n\n'
);
}
/**
* Generates a class property declaration
* @param name - Property name
* @param type - Property type
* @param value - Initial value
* @returns Property declaration
*/
export function generateProperty(name: string, type: string, value: string): string {
return ` private ${name}: ${type} = ${value}\n`;
}
/**
* Generates a builder method
* @param name - Method name
* @param returnType - Return type
* @param body - Method body
* @returns Method declaration
*/
export function generateMethod(name: string, returnType: string, body: string): string {
return ` ${name}(): ${returnType} {\n${body} }\n`;
}
/**
* Indents code by a specified number of spaces
* @param code - Code to indent
* @param spaces - Number of spaces
* @returns Indented code
*/
export function indent(code: string, spaces: number): string {
const indentation = ' '.repeat(spaces);
return code
.split('\n')
.map((line) => (line.trim() ? indentation + line : line))
.join('\n');
}