UNPKG

@weverson_na/prisma-generator-nestjs-dto

Version:

Advanced Prisma Generator with Smart Merge v2: Creates DTO and Entity classes with AST-based preservation, intelligent import management, and modular architecture for NestJS

144 lines (143 loc) 4.94 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SmartMergeContent = void 0; const merge_content_1 = require("./merge-content"); class SmartMergeContent { constructor() { this.originalMerge = new merge_content_1.MergeContent(); this.SCHEMA_MARKER = '// @generated from prisma schema'; } merge(existingText, generatedText) { if (!existingText.trim()) { return generatedText; } try { const userFields = this.extractUserFields(existingText); let result = this.originalMerge.merge(existingText, generatedText); if (userFields.length > 0) { result = this.addUserFieldsBack(result, userFields); } return result; } catch (error) { console.warn('Smart merge failed, falling back to original merge'); return this.originalMerge.merge(existingText, generatedText); } } extractUserFields(text) { const userFields = []; const lines = text.split('\n'); let i = 0; while (i < lines.length) { const line = lines[i]; if (this.hasSchemaMarkerNearby(lines, i)) { i++; continue; } if (this.isFieldBlockStart(lines, i)) { const fieldBlock = this.extractFieldBlock(lines, i); if (fieldBlock) { userFields.push(fieldBlock.field); i = fieldBlock.endIndex; } else { i++; } } else { i++; } } return userFields; } isFieldBlockStart(lines, index) { const line = lines[index].trim(); return (line.startsWith('@') || line.startsWith('//') || line.startsWith('/*') || this.isPropertyLine(line)) && !line.includes('class ') && !line.includes('export ') && !line.includes('import '); } isPropertyLine(line) { const trimmed = line.trim(); return /^\s*\w+[\?\!]?\s*:\s*/.test(trimmed) && trimmed.includes(';'); } extractFieldBlock(lines, startIndex) { let fieldCode = ''; let fieldName = ''; let i = startIndex; while (i < lines.length) { const line = lines[i]; const trimmed = line.trim(); if (trimmed.startsWith('@') || trimmed.startsWith('//') || trimmed.startsWith('/*')) { fieldCode += (fieldCode ? '\n' : '') + line; i++; } else if (this.isPropertyLine(trimmed)) { fieldCode += (fieldCode ? '\n' : '') + line; fieldName = this.extractFieldName(line) || ''; i++; break; } else if (trimmed === '') { fieldCode += (fieldCode ? '\n' : '') + line; i++; } else { break; } } if (fieldName) { return { field: { name: fieldName, code: fieldCode.trim() }, endIndex: i }; } return null; } hasSchemaMarkerNearby(lines, index) { for (let i = Math.max(0, index - 5); i < index; i++) { if (lines[i].includes(this.SCHEMA_MARKER)) { return true; } } return false; } countBraces(line) { return (line.match(/\{/g) || []).length - (line.match(/\}/g) || []).length; } extractFieldName(line) { const match = line.match(/(\w+)[\?\!]?\s*:/); return match ? match[1] : null; } addUserFieldsBack(text, userFields) { let result = text; for (const field of userFields) { if (!this.fieldExistsInText(result, field.name)) { result = this.insertFieldBeforeLastBrace(result, field.code); } } return result; } fieldExistsInText(text, fieldName) { const regex = new RegExp(`\\b${fieldName}[\\?\\!]?\\s*:`, 'g'); return regex.test(text); } insertFieldBeforeLastBrace(text, fieldCode) { const lines = text.split('\n'); for (let i = lines.length - 1; i >= 0; i--) { if (lines[i].trim() === '}') { const fieldLines = fieldCode.split('\n'); const indentedFieldLines = fieldLines.map(line => { if (line.trim()) { return ' ' + line.replace(/^\s+/, ''); } return line; }); lines.splice(i, 0, '', ' // User-defined field', ...indentedFieldLines); break; } } return lines.join('\n'); } } exports.SmartMergeContent = SmartMergeContent;