@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
JavaScript
;
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;