UNPKG

6.69 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.MetadataManager = void 0;
4const typescript_1 = require("typescript");
5class MetadataManager {
6 constructor(content) {
7 this.content = content;
8 }
9 insert(metadata, symbol, staticOptions) {
10 const source = (0, typescript_1.createSourceFile)('filename.ts', this.content, typescript_1.ScriptTarget.ES2017);
11 const moduleDecoratorNode = this.findFirstDecoratorMetadata(source, 'Module');
12 if (!moduleDecoratorNode) {
13 return;
14 }
15 const matchingProperties = moduleDecoratorNode.properties
16 .filter((prop) => prop.kind === typescript_1.SyntaxKind.PropertyAssignment)
17 .filter((prop) => {
18 const name = prop.name;
19 switch (name.kind) {
20 case typescript_1.SyntaxKind.Identifier:
21 return name.getText(source) === metadata;
22 case typescript_1.SyntaxKind.StringLiteral:
23 return name.text === metadata;
24 default:
25 return false;
26 }
27 });
28 symbol = this.mergeSymbolAndExpr(symbol, staticOptions);
29 const addBlankLinesIfDynamic = () => {
30 symbol = staticOptions ? this.addBlankLines(symbol) : symbol;
31 };
32 if (matchingProperties.length === 0) {
33 const expr = moduleDecoratorNode;
34 if (expr.properties.length === 0) {
35 addBlankLinesIfDynamic();
36 return this.insertMetadataToEmptyModuleDecorator(expr, metadata, symbol);
37 }
38 else {
39 addBlankLinesIfDynamic();
40 return this.insertNewMetadataToDecorator(expr, source, metadata, symbol);
41 }
42 }
43 else {
44 return this.insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions);
45 }
46 }
47 findFirstDecoratorMetadata(source, identifier) {
48 for (const node of this.getSourceNodes(source)) {
49 const isDecoratorFactoryNode = node.kind === typescript_1.SyntaxKind.Decorator &&
50 node.expression.kind === typescript_1.SyntaxKind.CallExpression;
51 if (!isDecoratorFactoryNode)
52 continue;
53 const expr = node.expression;
54 const isExpectedExpression = expr.arguments[0]?.kind === typescript_1.SyntaxKind.ObjectLiteralExpression;
55 if (!isExpectedExpression)
56 continue;
57 if (expr.expression.kind === typescript_1.SyntaxKind.Identifier) {
58 const escapedText = expr.expression.escapedText;
59 const isTargetIdentifier = escapedText
60 ? escapedText.toLowerCase() === identifier.toLowerCase()
61 : true;
62 if (isTargetIdentifier) {
63 return expr.arguments[0];
64 }
65 }
66 }
67 }
68 getSourceNodes(sourceFile) {
69 const nodes = [sourceFile];
70 const result = [];
71 while (nodes.length > 0) {
72 const node = nodes.shift();
73 if (node) {
74 result.push(node);
75 if (node.getChildCount(sourceFile) >= 0) {
76 nodes.unshift(...node.getChildren(sourceFile));
77 }
78 }
79 }
80 return result;
81 }
82 insertMetadataToEmptyModuleDecorator(expr, metadata, symbol) {
83 const position = expr.getEnd() - 1;
84 const toInsert = ` ${metadata}: [${symbol}]`;
85 return this.content.split('').reduce((content, char, index) => {
86 if (index === position) {
87 return `${content}\n${toInsert}\n${char}`;
88 }
89 else {
90 return `${content}${char}`;
91 }
92 }, '');
93 }
94 insertNewMetadataToDecorator(expr, source, metadata, symbol) {
95 const node = expr.properties[expr.properties.length - 1];
96 const position = node.getEnd();
97 const text = node.getFullText(source);
98 const matches = text.match(/^\r?\n\s*/);
99 let toInsert;
100 if (matches) {
101 toInsert = `,${matches[0]}${metadata}: [${symbol}]`;
102 }
103 else {
104 toInsert = `, ${metadata}: [${symbol}]`;
105 }
106 return this.content.split('').reduce((content, char, index) => {
107 if (index === position) {
108 return `${content}${toInsert}${char}`;
109 }
110 else {
111 return `${content}${char}`;
112 }
113 }, '');
114 }
115 insertSymbolToMetadata(source, matchingProperties, symbol, staticOptions) {
116 const assignment = matchingProperties[0];
117 let node;
118 const arrLiteral = assignment.initializer;
119 if (!arrLiteral.elements) {
120 return this.content;
121 }
122 if (arrLiteral.elements.length === 0) {
123 node = arrLiteral;
124 }
125 else {
126 node = arrLiteral.elements;
127 }
128 if (Array.isArray(node)) {
129 const nodeArray = node;
130 const symbolsArray = nodeArray.map((childNode) => childNode.getText(source));
131 if (symbolsArray.includes(symbol)) {
132 return this.content;
133 }
134 node = node[node.length - 1];
135 }
136 let toInsert;
137 let position = node.getEnd();
138 if (node.kind === typescript_1.SyntaxKind.ArrayLiteralExpression) {
139 position--;
140 toInsert = staticOptions ? this.addBlankLines(symbol) : `${symbol}`;
141 }
142 else {
143 const text = node.getFullText(source);
144 const itemSeparator = (text.match(/^\r?\n(\r?)\s+/) ||
145 text.match(/^\r?\n/) ||
146 ' ')[0];
147 toInsert = `,${itemSeparator}${symbol}`;
148 }
149 return this.content.split('').reduce((content, char, index) => {
150 if (index === position) {
151 return `${content}${toInsert}${char}`;
152 }
153 else {
154 return `${content}${char}`;
155 }
156 }, '');
157 }
158 mergeSymbolAndExpr(symbol, staticOptions) {
159 if (!staticOptions) {
160 return symbol;
161 }
162 const spacing = 6;
163 let options = JSON.stringify(staticOptions.value, null, spacing);
164 options = options.replace(/\"([^(\")"]+)\":/g, '$1:');
165 options = options.replace(/\"/g, `'`);
166 options = options.slice(0, options.length - 1) + ' }';
167 symbol += `.${staticOptions.name}(${options})`;
168 return symbol;
169 }
170 addBlankLines(expr) {
171 return `\n ${expr}\n `;
172 }
173}
174exports.MetadataManager = MetadataManager;