UNPKG

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.

175 lines (156 loc) 5.85 kB
import type { GeneratedSchemaMeta, MockStrategy } from '../types'; import type { Schema } from '../types'; import { generateZodSchema } from './zod-schema-generator'; import { generateStaticMockCode } from './static-mock-generator'; import { generateWithMethods } from '../core/code-generator'; /** * Builder class generation */ export interface BuilderGeneratorOptions { mockStrategy: MockStrategy; } /** * Generates a builder class for an enum schema */ export function generateEnumBuilder( meta: GeneratedSchemaMeta, options: BuilderGeneratorOptions ): string { const { typeName, schema } = meta; const { mockStrategy } = options; let code = `export class ${typeName}Builder {\n`; code += ` private options: BuilderOptions = {}\n`; code += ` setOptions(o: BuilderOptions): this { this.options = o || {}; return this }\n\n`; if (mockStrategy === 'static') { code += generateStaticEnumBuild(typeName, schema); } else if (mockStrategy === 'zod') { code += generateZodEnumBuild(typeName, schema); } else { code += generateCustomEnumBuild(typeName, meta.constName); } code += `}\n\n`; return code; } /** * Generates a builder class for an object schema */ export function generateObjectBuilder( meta: GeneratedSchemaMeta, options: BuilderGeneratorOptions ): string { const { typeName, schema, constName } = meta; const { mockStrategy } = options; let code = `export class ${typeName}Builder {\n`; code += ` private overrides: Partial<types.${typeName}> = {}\n`; code += ` private options: BuilderOptions = {}\n`; code += ` setOptions(o: BuilderOptions): this { this.options = o || {}; return this }\n`; const withMethods = generateWithMethods(schema, typeName); if (withMethods) { code += withMethods + '\n'; } code += '\n'; if (mockStrategy === 'static') { code += generateStaticObjectBuild(typeName, schema); } else if (mockStrategy === 'zod') { code += generateZodObjectBuild(typeName, schema); } else { code += generateCustomObjectBuild(typeName, constName); } code += `}\n\n`; return code; } /** * Static mock build method for enums */ function generateStaticEnumBuild(typeName: string, schema: Schema): string { const staticMock = generateStaticMockCode(schema, typeName); return ` build(): types.${typeName} {\n return ${staticMock} as types.${typeName};\n }\n`; } /** * Zod mock build method for enums */ function generateZodEnumBuild(typeName: string, schema: Schema): string { const zodSchemaString = generateZodSchema(schema); return ( ` build(): types.${typeName} {\n` + ` const zodSchemaString = \`${zodSchemaString}\`;\n` + ` return generateMockFromZodSchema(zodSchemaString, {}, {\n` + ` useDefault: this.options.useDefault,\n` + ` useExamples: this.options.useExamples,\n` + ` alwaysIncludeOptionals: this.options.alwaysIncludeOptionals,\n` + ` optionalsProbability: this.options.optionalsProbability,\n` + ` omitNulls: this.options.omitNulls\n` + ` }) as types.${typeName};\n` + ` }\n` ); } /** * Custom runtime build method for enums */ function generateCustomEnumBuild(typeName: string, constName: string): string { return ( ` build(): types.${typeName} {\n` + ` return generateMock<types.${typeName}>(schemas.${constName}, {\n` + ` useDefault: this.options.useDefault,\n` + ` useExamples: this.options.useExamples,\n` + ` alwaysIncludeOptionals: this.options.alwaysIncludeOptionals,\n` + ` optionalsProbability: this.options.optionalsProbability,\n` + ` omitNulls: this.options.omitNulls\n` + ` })\n` + ` }\n` ); } /** * Static mock build method for objects */ function generateStaticObjectBuild(typeName: string, schema: Schema): string { const staticMock = generateStaticMockCode(schema, typeName); return ( ` build(): types.${typeName} {\n` + ` const baseMock = ${staticMock};\n` + ` return { ...baseMock, ...this.overrides } as types.${typeName};\n` + ` }\n` ); } /** * Zod mock build method for objects */ function generateZodObjectBuild(typeName: string, schema: Schema): string { const zodSchemaString = generateZodSchema(schema); return ( ` build(): types.${typeName} {\n` + ` const zodSchemaString = \`${zodSchemaString}\`;\n` + ` return generateMockFromZodSchema(zodSchemaString, this.overrides, {\n` + ` useDefault: this.options.useDefault,\n` + ` useExamples: this.options.useExamples,\n` + ` alwaysIncludeOptionals: this.options.alwaysIncludeOptionals,\n` + ` optionalsProbability: this.options.optionalsProbability,\n` + ` omitNulls: this.options.omitNulls\n` + ` }) as types.${typeName};\n` + ` }\n` ); } /** * Custom runtime build method for objects */ function generateCustomObjectBuild(typeName: string, constName: string): string { return ( ` build(): types.${typeName} {\n` + ` const mock = generateMock<types.${typeName}>(schemas.${constName}, {\n` + ` useDefault: this.options.useDefault,\n` + ` useExamples: this.options.useExamples,\n` + ` alwaysIncludeOptionals: this.options.alwaysIncludeOptionals,\n` + ` optionalsProbability: this.options.optionalsProbability,\n` + ` omitNulls: this.options.omitNulls\n` + ` })\n` + ` for (const k in this.overrides) {\n` + ` if (Object.prototype.hasOwnProperty.call(this.overrides, k)) {\n` + ` const typedMock = mock as Record<string, unknown>;\n` + ` const typedOverrides = this.overrides as Record<string, unknown>;\n` + ` typedMock[k] = typedOverrides[k];\n` + ` }\n` + ` }\n` + ` return mock\n` + ` }\n` ); }