@nestjs/schematics
Version:
Nest - modern, fast, powerful node.js web framework (@schematics)
175 lines (174 loc) • 6.69 kB
JavaScript
Object.defineProperty(exports, "__esModule", { value: true });
exports.MetadataManager = void 0;
const typescript_1 = require("typescript");
class MetadataManager {
constructor(content) {
this.content = content;
}
insert(metadata, symbol, staticOptions) {
const source = (0, typescript_1.createSourceFile)('filename.ts', this.content, typescript_1.ScriptTarget.ES2017);
const moduleDecoratorNode = this.findFirstDecoratorMetadata(source, 'Module');
if (!moduleDecoratorNode) {
return;
}
const matchingProperties = moduleDecoratorNode.properties
.filter((prop) => prop.kind === typescript_1.SyntaxKind.PropertyAssignment)
.filter((prop) => {
const name = prop.name;
switch (name.kind) {
case typescript_1.SyntaxKind.Identifier:
return name.getText(source) === metadata;
case typescript_1.SyntaxKind.StringLiteral:
return name.text === metadata;
default:
return false;
}
});
symbol = this.mergeSymbolAndExpr(symbol, staticOptions);
const addBlankLinesIfDynamic = () => {
symbol = staticOptions ? this.addBlankLines(symbol) : symbol;
};
if (matchingProperties.length === 0) {
const expr = moduleDecoratorNode;
if (expr.properties.length === 0) {
addBlankLinesIfDynamic();
return this.insertMetadataToEmptyModuleDecorator(expr, metadata, symbol);
}
else {
addBlankLinesIfDynamic();
return this.insertNewMetadataToDecorator(expr, source, metadata, symbol);
}
}
else {
return this.insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions);
}
}
findFirstDecoratorMetadata(source, identifier) {
for (const node of this.getSourceNodes(source)) {
const isDecoratorFactoryNode = node.kind === typescript_1.SyntaxKind.Decorator &&
node.expression.kind === typescript_1.SyntaxKind.CallExpression;
if (!isDecoratorFactoryNode)
continue;
const expr = node.expression;
const isExpectedExpression = expr.arguments[0]?.kind === typescript_1.SyntaxKind.ObjectLiteralExpression;
if (!isExpectedExpression)
continue;
if (expr.expression.kind === typescript_1.SyntaxKind.Identifier) {
const escapedText = expr.expression.escapedText;
const isTargetIdentifier = escapedText
? escapedText.toLowerCase() === identifier.toLowerCase()
: true;
if (isTargetIdentifier) {
return expr.arguments[0];
}
}
}
}
getSourceNodes(sourceFile) {
const nodes = [sourceFile];
const result = [];
while (nodes.length > 0) {
const node = nodes.shift();
if (node) {
result.push(node);
if (node.getChildCount(sourceFile) >= 0) {
nodes.unshift(...node.getChildren(sourceFile));
}
}
}
return result;
}
insertMetadataToEmptyModuleDecorator(expr, metadata, symbol) {
const position = expr.getEnd() - 1;
const toInsert = ` ${metadata}: [${symbol}]`;
return this.content.split('').reduce((content, char, index) => {
if (index === position) {
return `${content}\n${toInsert}\n${char}`;
}
else {
return `${content}${char}`;
}
}, '');
}
insertNewMetadataToDecorator(expr, source, metadata, symbol) {
const node = expr.properties[expr.properties.length - 1];
const position = node.getEnd();
const text = node.getFullText(source);
const matches = text.match(/^\r?\n\s*/);
let toInsert;
if (matches) {
toInsert = `,${matches[0]}${metadata}: [${symbol}]`;
}
else {
toInsert = `, ${metadata}: [${symbol}]`;
}
return this.content.split('').reduce((content, char, index) => {
if (index === position) {
return `${content}${toInsert}${char}`;
}
else {
return `${content}${char}`;
}
}, '');
}
insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions) {
const assignment = matchingProperties[0];
let node;
const arrLiteral = assignment.initializer;
if (!arrLiteral.elements) {
return this.content;
}
if (arrLiteral.elements.length === 0) {
node = arrLiteral;
}
else {
node = arrLiteral.elements;
}
if (Array.isArray(node)) {
const nodeArray = node;
const symbolsArray = nodeArray.map((childNode) => childNode.getText(source));
if (symbolsArray.includes(symbol)) {
return this.content;
}
node = node[node.length - 1];
}
let toInsert;
let position = node.getEnd();
if (node.kind === typescript_1.SyntaxKind.ArrayLiteralExpression) {
position--;
toInsert = staticOptions ? this.addBlankLines(symbol) : `${symbol}`;
}
else {
const text = node.getFullText(source);
const itemSeparator = (text.match(/^\r?\n(\r?)\s+/) ||
text.match(/^\r?\n/) ||
' ')[0];
toInsert = `,${itemSeparator}${symbol}`;
}
return this.content.split('').reduce((content, char, index) => {
if (index === position) {
return `${content}${toInsert}${char}`;
}
else {
return `${content}${char}`;
}
}, '');
}
mergeSymbolAndExpr(symbol, staticOptions) {
if (!staticOptions) {
return symbol;
}
const spacing = 6;
let options = JSON.stringify(staticOptions.value, null, spacing);
options = options.replace(/\"([^(\")"]+)\":/g, '$1:');
options = options.replace(/\"/g, `'`);
options = options.slice(0, options.length - 1) + ' }';
symbol += `.${staticOptions.name}(${options})`;
return symbol;
}
addBlankLines(expr) {
return `\n ${expr}\n `;
}
}
exports.MetadataManager = MetadataManager;
;