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.

221 lines 7.71 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MockGenerator = void 0; exports.generateMock = generateMock; /** * Custom mock data generator for JSON schemas * This is a lightweight alternative to json-schema-faker */ class MockGenerator { constructor(options = {}) { this.seenRefs = new Set(); this.options = { useDefault: options.useDefault ?? false, useExamples: options.useExamples ?? false, alwaysIncludeOptionals: options.alwaysIncludeOptionals ?? false, optionalsProbability: options.optionalsProbability ?? 1, omitNulls: options.omitNulls ?? false, requiredOnly: options.requiredOnly ?? false, }; } /** * Generate mock data from schema */ generate(schema) { this.seenRefs.clear(); return this.generateValue(schema); } generateValue(schema) { if (schema.$ref) { if (this.seenRefs.has(schema.$ref)) { return null; } this.seenRefs.add(schema.$ref); } if (this.options.useDefault && schema.default !== undefined) { return schema.default; } if (this.options.useExamples && schema.examples && schema.examples.length > 0) { return schema.examples[0]; } if (schema.const !== undefined) { return schema.const; } if (schema.enum && schema.enum.length > 0) { return schema.enum[0]; } if (schema.nullable && this.shouldIncludeNull()) { return null; } if (schema.allOf && schema.allOf.length > 0) { return this.generateAllOf(schema.allOf); } if (schema.anyOf && schema.anyOf.length > 0) { return this.generateValue(schema.anyOf[0]); } if (schema.oneOf && schema.oneOf.length > 0) { return this.generateValue(schema.oneOf[0]); } if (Array.isArray(schema.type)) { const nonNullTypes = schema.type.filter((t) => t !== 'null'); const type = nonNullTypes.length > 0 ? nonNullTypes[0] : 'null'; return this.generateByType({ ...schema, type }); } return this.generateByType(schema); } generateByType(schema) { const type = schema.type || 'object'; switch (type) { case 'null': return null; case 'boolean': return false; case 'integer': case 'number': return this.generateNumber(schema); case 'string': return this.generateString(schema); case 'array': return this.generateArray(schema); case 'object': return this.generateObject(schema); default: return null; } } generateNumber(schema) { const min = schema.minimum ?? (schema.exclusiveMinimum ? typeof schema.exclusiveMinimum === 'number' ? schema.exclusiveMinimum + 1 : 1 : 0); const max = schema.maximum ?? (schema.exclusiveMaximum ? typeof schema.exclusiveMaximum === 'number' ? schema.exclusiveMaximum - 1 : 99 : 100); let value = min; if (schema.multipleOf) { value = Math.ceil(min / schema.multipleOf) * schema.multipleOf; if (value > max) { value = schema.multipleOf; } } return schema.type === 'integer' ? Math.floor(value) : value; } generateString(schema) { const minLength = schema.minLength ?? 0; const maxLength = schema.maxLength ?? 10; if (schema.format) { return this.generateStringByFormat(schema.format, minLength, maxLength); } if (schema.pattern) { return this.generateStringForPattern(schema.pattern, minLength, maxLength); } const length = Math.max(minLength, Math.min(maxLength, 10)); return 'a'.repeat(length); } generateStringByFormat(format, minLength, maxLength) { switch (format) { case 'email': return 'test@example.com'; case 'uri': case 'url': return 'https://example.com'; case 'uuid': return '00000000-0000-0000-0000-000000000000'; case 'date': return '2024-01-01'; case 'date-time': return '2024-01-01T00:00:00Z'; case 'time': return '00:00:00'; case 'ipv4': return '127.0.0.1'; case 'ipv6': return '::1'; case 'hostname': return 'localhost'; case 'phone': return '+1234567890'; default: { const length = Math.max(minLength, Math.min(maxLength, 10)); return 'string'.substring(0, Math.max(length, 1)); } } } generateStringForPattern(pattern, minLength, maxLength) { const length = Math.max(minLength, Math.min(maxLength, 10)); return 'x'.repeat(length); } generateArray(schema) { const minItems = schema.minItems ?? 0; const maxItems = schema.maxItems ?? 3; const length = Math.max(minItems, Math.min(maxItems, 1)); if (!schema.items) { return Array(length).fill(null); } if (Array.isArray(schema.items)) { return schema.items.map((itemSchema) => this.generateValue(itemSchema)); } return Array.from({ length }, () => this.generateValue(schema.items)); } generateObject(schema) { const obj = {}; if (!schema.properties) { return obj; } const required = new Set(schema.required || []); for (const [propName, propSchema] of Object.entries(schema.properties)) { const isRequired = required.has(propName); if (this.options.requiredOnly && !isRequired) { continue; } if (!isRequired && !this.shouldIncludeOptional()) { continue; } const value = this.generateValue(propSchema); if (this.options.omitNulls && value === null) { continue; } obj[propName] = value; } return obj; } generateAllOf(schemas) { const merged = {}; for (const schema of schemas) { const value = this.generateValue(schema); if (typeof value === 'object' && value !== null && !Array.isArray(value)) { Object.assign(merged, value); } } return merged; } shouldIncludeOptional() { if (this.options.alwaysIncludeOptionals) { return true; } if (this.options.optionalsProbability === false) { return false; } return Math.random() < this.options.optionalsProbability; } shouldIncludeNull() { return !this.options.omitNulls && Math.random() < 0.1; } } exports.MockGenerator = MockGenerator; /** * Generates mock data using custom mock generator * @param schema - JSON Schema * @param options - Generation options * @returns Generated mock data */ function generateMock(schema, options) { const generator = new MockGenerator(options); return generator.generate(schema); } //# sourceMappingURL=mock-runtime.js.map