|
1 |
| -import { ClassDeclaration, IndentationText, Project, PropertyDeclaration, QuoteKind, Scope, SourceFile, Symbol, SyntaxKind } from "ts-morph"; |
| 1 | +import { ClassDeclaration, IndentationText, Project, PropertyDeclaration, QuoteKind, SourceFile, Symbol, SyntaxKind } from "ts-morph"; |
2 | 2 | import * as path from "path";
|
3 | 3 | import * as fs from "fs";
|
4 | 4 | // import { exec } from "child_process";
|
@@ -152,159 +152,64 @@ export class ConstructsUpdater extends MetadataUpdater {
|
152 | 152 | const classes = this.getCdkResourceClasses(sourceFile.getFilePath());
|
153 | 153 | for (const resource of classes) {
|
154 | 154 | this.addImportAndMetadataStatement(resource.sourceFile, resource.filePath, resource.node);
|
155 |
| - this.makeConstructsPropInjectable(resource.sourceFile, resource.filePath, resource.node); |
156 | 155 | }
|
157 | 156 | });
|
158 | 157 | }
|
159 | 158 |
|
160 |
| - /** |
161 |
| - * This makes a Construct Property Injectable by doing 3 things: |
162 |
| - * - add PROPERTY_INJECTION_ID property |
163 |
| - * - import propertyInjectable from core/lib/prop-injectable |
164 |
| - * - add class decorator @propertyInjectable |
165 |
| - * |
166 |
| - * If the Construct already has PROPERTY_INJECTION_ID, then skip it. |
167 |
| - */ |
168 |
| - private makeConstructsPropInjectable(sourceFile: SourceFile, filePath: string, node: ClassDeclaration) { |
169 |
| - console.log(`path: ${filePath}, class: ${node.getName()}`); |
170 |
| - |
171 |
| - if (this.isAlreadyInjectable(node)) { |
172 |
| - return; // do nothing |
173 |
| - } |
174 |
| - |
175 |
| - // Add PROPERTY_INJECTION_ID |
176 |
| - node.addProperty({ |
177 |
| - scope: Scope.Public, |
178 |
| - isStatic: true, |
179 |
| - isReadonly: true, |
180 |
| - name: 'PROPERTY_INJECTION_ID', |
181 |
| - type: "string", |
182 |
| - initializer: this.filePathToInjectionId(filePath, node.getName()), |
183 |
| - }); |
184 |
| - console.log(' Added PROPERTY_INJECTION_ID') |
185 |
| - |
186 |
| - // Add Decorator |
187 |
| - node.addDecorator({ |
188 |
| - name: "propertyInjectable", |
189 |
| - }); |
190 |
| - console.log(' Added @propertyInjectable') |
191 |
| - |
192 |
| - // import propertyInjectable |
193 |
| - this.importCoreLibFile(sourceFile, filePath, 'prop-injectable', 'propertyInjectable'); |
194 |
| - |
195 |
| - // Write the updated file back to disk |
196 |
| - sourceFile.saveSync(); |
197 |
| - } |
198 |
| - |
199 |
| - /** |
200 |
| - * If the Construct already has PROPERTY_INJECTION_ID, then it is injectable already. |
201 |
| - */ |
202 |
| - private isAlreadyInjectable(classDeclaration: ClassDeclaration): boolean { |
203 |
| - const properties: PropertyDeclaration[] = classDeclaration.getProperties(); |
204 |
| - for (const prop of properties) { |
205 |
| - if (prop.getName() === 'PROPERTY_INJECTION_ID') { |
206 |
| - console.log(`Skipping ${classDeclaration.getName()}. It is already injectable`); |
207 |
| - return true; |
208 |
| - } |
209 |
| - } |
210 |
| - return false; |
211 |
| - } |
212 | 159 |
|
213 | 160 | /**
|
214 |
| - * This converts the filePath |
215 |
| - * '<HOME_DIR>/<CDK_HOME>/aws-cdk/packages/aws-cdk-lib/aws-apigateway/lib/api-key.ts' |
216 |
| - * and className 'ApiKey' |
217 |
| - * to 'aws-cdk-lib.aws-apigateway.ApiKey'. |
218 |
| - * |
219 |
| - * '<HOME_DIR>/<CDK_HOME>/aws-cdk/packages/@aws-cdk/aws-amplify-alpha/lib/app.ts' |
220 |
| - * and className 'App' |
221 |
| - * to '@aws-cdk.aws-amplify-alpha.App |
| 161 | + * Add the import statement for MetadataType to the file. |
222 | 162 | */
|
223 |
| - private filePathToInjectionId(filePath: string, className: string | undefined): string { |
224 |
| - if (!className) { |
225 |
| - throw new Error('Could not build PROPERTY_INJECTION_ID if className is undefined'); |
226 |
| - } |
227 |
| - |
228 |
| - const start = '/packages/'; |
229 |
| - const startIndex = filePath.indexOf(start); |
230 |
| - const subPath = filePath.substring(startIndex + start.length); |
231 |
| - const parts: string[] = subPath.split('\/'); |
232 |
| - if (parts.length < 3) { |
233 |
| - throw new Error(`Could not build PROPERTY_INJECTION_ID for ${filePath} ${className}`); |
| 163 | + private addImportAndMetadataStatement(sourceFile: any, filePath: string, node: any) { |
| 164 | + const ret = this.addLineInConstructor(sourceFile, node); |
| 165 | + if (!ret) { |
| 166 | + return; |
234 | 167 | }
|
235 | 168 |
|
236 |
| - // we only care about /packages/aws-cdk-lib/ and /packages/@aws-cdk/, |
237 |
| - // but in case there are L2 constructs in other sub dir, it will handle it too. |
238 |
| - return `'${parts[0]}.${parts[1]}.${className}'`; |
239 |
| - } |
240 |
| - |
241 |
| - /** |
242 |
| - * This returns the relative path of the import file in core/lib. |
243 |
| - * For example, importFile is prop-injectable or metadata-resource |
244 |
| - */ |
245 |
| - private getRelativePathForPropInjectionImport(filePath: string, importFile: string): string { |
246 | 169 | const absoluteFilePath = path.resolve(filePath);
|
247 |
| - const absoluteTargetPath = path.resolve(__dirname, `../../../../packages/aws-cdk-lib/core/lib/${importFile}.ts`); |
| 170 | + const absoluteTargetPath = path.resolve(__dirname, '../../../../packages/aws-cdk-lib/core/lib/metadata-resource.ts'); |
| 171 | + |
248 | 172 | let relativePath = path.relative(path.dirname(absoluteFilePath), absoluteTargetPath).replace(/\\/g, "/").replace(/.ts/, "");
|
249 | 173 | if (absoluteFilePath.includes('@aws-cdk')) {
|
250 |
| - relativePath = `aws-cdk-lib/core/lib/${importFile}` |
| 174 | + relativePath = 'aws-cdk-lib/core/lib/metadata-resource' |
251 | 175 | }
|
252 |
| - return relativePath; |
253 |
| - } |
254 | 176 |
|
255 |
| - /** |
256 |
| - * This adds import of a class in aws-cdk-lib/core/lib to the file. |
257 |
| - */ |
258 |
| - private importCoreLibFile( |
259 |
| - sourceFile: SourceFile, |
260 |
| - filePath: string, |
261 |
| - importfileName: string, |
262 |
| - importClassName: string |
263 |
| - ) { |
264 |
| - const relativePath = this.getRelativePathForPropInjectionImport(filePath, importfileName); |
265 |
| - |
266 |
| - // Check if an import from the import file already exists |
| 177 | + // Check if an import from 'metadata-resource' already exists |
267 | 178 | const existingImport = sourceFile.getImportDeclarations().find((stmt: any) => {
|
268 |
| - return stmt.getModuleSpecifier().getText().includes(importfileName); |
| 179 | + return stmt.getModuleSpecifier().getText().includes('/metadata-resource'); |
269 | 180 | });
|
270 |
| - if (existingImport) { |
271 |
| - return; |
272 |
| - } |
273 |
| - |
274 |
| - // Find the correct insertion point (after the last import before the new one) |
275 |
| - const importDeclarations = sourceFile.getImportDeclarations(); |
276 |
| - let insertIndex = importDeclarations.length; // Default to appending |
277 |
| - |
278 |
| - for (let i = importDeclarations.length - 1; i >= 0; i--) { |
279 |
| - const existingImport = importDeclarations[i].getModuleSpecifier().getLiteralText(); |
280 | 181 |
|
281 |
| - // Insert the new import before the first one that is lexicographically greater |
282 |
| - if (existingImport.localeCompare(relativePath) > 0) { |
283 |
| - insertIndex = i; |
284 |
| - } else { |
285 |
| - break; |
| 182 | + if (existingImport) { |
| 183 | + // Check if 'MethodMetadata' is already imported |
| 184 | + const namedImports = existingImport.getNamedImports().map((imp: any) => imp.getName()); |
| 185 | + if (!namedImports.includes("addConstructMetadata")) { |
| 186 | + existingImport.addNamedImport({ name: "addConstructMetadata" }); |
| 187 | + console.log(`Merged import for addConstructMetadata in file: ${filePath}`); |
286 | 188 | }
|
287 |
| - } |
288 |
| - |
289 |
| - // Insert the new import at the correct index |
290 |
| - sourceFile.insertImportDeclaration(insertIndex, { |
291 |
| - moduleSpecifier: relativePath, |
292 |
| - namedImports: [{ name: importClassName }], |
293 |
| - }); |
294 |
| - console.log(` Added import for ${importClassName} in file: ${filePath} with relative path: ${relativePath}`); |
295 |
| - } |
| 189 | + } else { |
| 190 | + // Find the correct insertion point (after the last import before the new one) |
| 191 | + const importDeclarations = sourceFile.getImportDeclarations(); |
| 192 | + let insertIndex = importDeclarations.length; // Default to appending |
| 193 | + |
| 194 | + for (let i = importDeclarations.length - 1; i >= 0; i--) { |
| 195 | + const existingImport = importDeclarations[i].getModuleSpecifier().getLiteralText(); |
296 | 196 |
|
297 |
| - /** |
298 |
| - * Add the import statement for MetadataType to the file. |
299 |
| - */ |
300 |
| - private addImportAndMetadataStatement(sourceFile: any, filePath: string, node: any) { |
301 |
| - const ret = this.addLineInConstructor(sourceFile, node); |
302 |
| - if (!ret) { |
303 |
| - return; |
| 197 | + // Insert the new import before the first one that is lexicographically greater |
| 198 | + if (existingImport.localeCompare(relativePath) > 0) { |
| 199 | + insertIndex = i; |
| 200 | + } else { |
| 201 | + break; |
| 202 | + } |
| 203 | + } |
| 204 | + |
| 205 | + // Insert the new import at the correct index |
| 206 | + sourceFile.insertImportDeclaration(insertIndex, { |
| 207 | + moduleSpecifier: relativePath, |
| 208 | + namedImports: [{ name: "addConstructMetadata" }], |
| 209 | + }); |
| 210 | + console.log(`Added import for addConstructMetadata in file: ${filePath} with relative path: ${relativePath}`); |
304 | 211 | }
|
305 | 212 |
|
306 |
| - this.importCoreLibFile(sourceFile, filePath, 'metadata-resource', 'addConstructMetadata'); |
307 |
| - |
308 | 213 | // Write the updated file back to disk
|
309 | 214 | sourceFile.saveSync();
|
310 | 215 | }
|
|
0 commit comments