UNPKG

auto-typegen

Version:

Automatically generate TypeScript interfaces from JSON data, API responses, or database schemas. Perfect for Mongoose, Sequelize, and raw data. Simplify your workflow and ensure type safety with just one function call!

90 lines (89 loc) 3.46 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.TypeGenerator = void 0; class TypeGenerator { constructor() { this.generatedInterfaces = {}; this.usedInterfaceNames = new Set(); // Track used names } generate(data, interfaceName = 'AutoGenerated') { this.generatedInterfaces = {}; this.usedInterfaceNames.clear(); this.processData(data, interfaceName); return this.formatInterfaces(interfaceName); } processData(data, interfaceName) { var _a; if (data instanceof Date) return 'Date'; if (((_a = data === null || data === void 0 ? void 0 : data.constructor) === null || _a === void 0 ? void 0 : _a.name) === 'ObjectId') return 'string'; if (Array.isArray(data)) { return this.processArray(data, interfaceName); } if (typeof data === 'object' && data !== null) { return this.processObject(data, interfaceName); } return typeof data; } processArray(arr, parentName) { if (arr.length === 0) return 'any[]'; const elementType = this.processData(arr[0], parentName); return `${elementType}[]`; } processObject(obj, interfaceName) { // Generate a unique signature for nested objects const signature = this.getObjectSignature(obj, interfaceName); if (this.generatedInterfaces[signature]) { return this.generatedInterfaces[signature]; } let uniqueName = interfaceName; let counter = 1; // Ensure unique interface names while (this.usedInterfaceNames.has(uniqueName)) { uniqueName = `${interfaceName}_${counter++}`; } this.usedInterfaceNames.add(uniqueName); const interfaceBody = Object.entries(obj) .map(([key, value]) => { const type = this.processData(value, `${uniqueName}${this.capitalize(key)}`); return `${key}: ${type};`; }) .join('\n '); const interfaceCode = `interface ${uniqueName} {\n ${interfaceBody}\n}`; this.generatedInterfaces[signature] = uniqueName; this.generatedInterfaces[uniqueName] = interfaceCode; return uniqueName; } // Generate a recursive signature for nested objects getObjectSignature(obj, parentName) { return Object.entries(obj) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => { let type; if (Array.isArray(value)) { type = `array:${this.processData(value[0] || {}, `${parentName}${this.capitalize(key)}`)}`; } else if (typeof value === 'object' && value !== null) { type = `object:${this.getObjectSignature(value, `${parentName}${this.capitalize(key)}`)}`; } else { type = typeof value; } return `${key}:${type}`; }) .join(','); } capitalize(str) { return str.charAt(0).toUpperCase() + str.slice(1); } formatInterfaces(rootName) { // Include ALL generated interfaces return (Object.values(this.generatedInterfaces) .filter((v) => v.includes('interface')) .reverse() .join('\n\n') + `\n\nexport { ${rootName} };`); } } exports.TypeGenerator = TypeGenerator;