diff --git a/modules/component-store/schematics-core/tsconfig.lib.json b/modules/component-store/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/component-store/schematics-core/tsconfig.lib.json +++ b/modules/component-store/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/component-store/schematics-core/utility/visitors.ts b/modules/component-store/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/component-store/schematics-core/utility/visitors.ts +++ b/modules/component-store/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/component-store/tsconfig.schematics.json b/modules/component-store/tsconfig.schematics.json index 6ce954388f..7ae7a6a734 100644 --- a/modules/component-store/tsconfig.schematics.json +++ b/modules/component-store/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/component/schematics-core/tsconfig.lib.json b/modules/component/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/component/schematics-core/tsconfig.lib.json +++ b/modules/component/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/component/schematics-core/utility/visitors.ts b/modules/component/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/component/schematics-core/utility/visitors.ts +++ b/modules/component/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/component/tsconfig.schematics.json b/modules/component/tsconfig.schematics.json index a4ddb29020..044886ed53 100644 --- a/modules/component/tsconfig.schematics.json +++ b/modules/component/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/data/schematics-core/tsconfig.lib.json b/modules/data/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/data/schematics-core/tsconfig.lib.json +++ b/modules/data/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/data/schematics-core/utility/visitors.ts b/modules/data/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/data/schematics-core/utility/visitors.ts +++ b/modules/data/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/data/tsconfig.schematics.json b/modules/data/tsconfig.schematics.json index 10cc7e381d..f779bfe34f 100644 --- a/modules/data/tsconfig.schematics.json +++ b/modules/data/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/effects/schematics-core/tsconfig.lib.json b/modules/effects/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/effects/schematics-core/tsconfig.lib.json +++ b/modules/effects/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/effects/schematics-core/utility/visitors.ts b/modules/effects/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/effects/schematics-core/utility/visitors.ts +++ b/modules/effects/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/effects/tsconfig.schematics.json b/modules/effects/tsconfig.schematics.json index 88dcd0495a..fec5cc794a 100644 --- a/modules/effects/tsconfig.schematics.json +++ b/modules/effects/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/entity/schematics-core/tsconfig.lib.json b/modules/entity/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/entity/schematics-core/tsconfig.lib.json +++ b/modules/entity/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/entity/schematics-core/utility/visitors.ts b/modules/entity/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/entity/schematics-core/utility/visitors.ts +++ b/modules/entity/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/entity/tsconfig.schematics.json b/modules/entity/tsconfig.schematics.json index 6e4991381c..34e4210ff2 100644 --- a/modules/entity/tsconfig.schematics.json +++ b/modules/entity/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/eslint-plugin/tsconfig.schematics.json b/modules/eslint-plugin/tsconfig.schematics.json index 15bad1c7c8..96abb46af4 100644 --- a/modules/eslint-plugin/tsconfig.schematics.json +++ b/modules/eslint-plugin/tsconfig.schematics.json @@ -10,7 +10,7 @@ "outDir": "../../dist/modules/eslint-plugin", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/operators/schematics-core/tsconfig.lib.json b/modules/operators/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/operators/schematics-core/tsconfig.lib.json +++ b/modules/operators/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/operators/schematics-core/utility/visitors.ts b/modules/operators/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/operators/schematics-core/utility/visitors.ts +++ b/modules/operators/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/operators/tsconfig.schematics.json b/modules/operators/tsconfig.schematics.json index 772e1f63c6..db4d6dca3b 100644 --- a/modules/operators/tsconfig.schematics.json +++ b/modules/operators/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/router-store/schematics-core/tsconfig.lib.json b/modules/router-store/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/router-store/schematics-core/tsconfig.lib.json +++ b/modules/router-store/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/router-store/schematics-core/utility/visitors.ts b/modules/router-store/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/router-store/schematics-core/utility/visitors.ts +++ b/modules/router-store/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/router-store/tsconfig.schematics.json b/modules/router-store/tsconfig.schematics.json index b8ca15b6e3..687d09b3ae 100644 --- a/modules/router-store/tsconfig.schematics.json +++ b/modules/router-store/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/schematics-core/tsconfig.lib.json b/modules/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/schematics-core/tsconfig.lib.json +++ b/modules/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/schematics-core/utility/visitors.ts b/modules/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/schematics-core/utility/visitors.ts +++ b/modules/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/schematics/schematics-core/tsconfig.lib.json b/modules/schematics/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/schematics/schematics-core/tsconfig.lib.json +++ b/modules/schematics/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/schematics/schematics-core/utility/visitors.ts b/modules/schematics/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/schematics/schematics-core/utility/visitors.ts +++ b/modules/schematics/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/schematics/tsconfig.build.json b/modules/schematics/tsconfig.build.json index 172550d658..9727e0bca0 100644 --- a/modules/schematics/tsconfig.build.json +++ b/modules/schematics/tsconfig.build.json @@ -11,7 +11,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/schematics/tsconfig.schematics.json b/modules/schematics/tsconfig.schematics.json index 3fc1f247f3..ec9260da3e 100644 --- a/modules/schematics/tsconfig.schematics.json +++ b/modules/schematics/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/signals/migrations/18_0_0-rc_3-protected-state/index.ts b/modules/signals/migrations/18_0_0-rc_3-protected-state/index.ts index 84004d620d..9fbe95b5fb 100644 --- a/modules/signals/migrations/18_0_0-rc_3-protected-state/index.ts +++ b/modules/signals/migrations/18_0_0-rc_3-protected-state/index.ts @@ -6,6 +6,7 @@ import { import { Rule, SchematicContext, Tree } from '@angular-devkit/schematics'; import * as ts from 'typescript'; import { commitChanges } from '../../schematics-core'; +import { visitImportDeclaration } from '../../schematics-core/utility/visitors'; export default function migrateWritableStateSource(): Rule { return (tree: Tree, ctx: SchematicContext) => { @@ -89,19 +90,6 @@ function visitCallExpression( }); } -function visitImportDeclaration( - node: ts.Node, - callback: (importDeclaration: ts.ImportDeclaration) => void -) { - if (ts.isImportDeclaration(node)) { - callback(node); - } - - ts.forEachChild(node, (child) => { - visitImportDeclaration(child, callback); - }); -} - function findImportedName(source: ts.SourceFile) { let importedName = ''; visitImportDeclaration(source, (importDeclaration) => { diff --git a/modules/signals/migrations/19_0_0-rc_0-props/index.spec.ts b/modules/signals/migrations/19_0_0-rc_0-props/index.spec.ts new file mode 100644 index 0000000000..7822157f59 --- /dev/null +++ b/modules/signals/migrations/19_0_0-rc_0-props/index.spec.ts @@ -0,0 +1,258 @@ +import * as path from 'path'; +import { + SchematicTestRunner, + UnitTestTree, +} from '@angular-devkit/schematics/testing'; +import { createWorkspace } from '@ngrx/schematics-core/testing'; +import { tags } from '@angular-devkit/core'; + +describe('migrate to props', () => { + const collectionPath = path.join(__dirname, '../migration.json'); + const schematicRunner = new SchematicTestRunner('schematics', collectionPath); + + let appTree: UnitTestTree; + + beforeEach(async () => { + appTree = await createWorkspace(schematicRunner, appTree); + }); + + const verifySchematic = async (input: string, output: string) => { + appTree.create('main.ts', input); + + const logEntries: string[] = []; + schematicRunner.logger.subscribe((logEntry) => + logEntries.push(logEntry.message) + ); + + const tree = await schematicRunner.runSchematic( + `19_0_0-rc_0-props`, + {}, + appTree + ); + + const actual = tree.readContent('main.ts'); + + expect(actual).toBe(output); + + return logEntries; + }; + + it('renames (Named)EntityComputed imports to (Named)EntityProps', async () => { + const input = tags.stripIndent` +import { EntityComputed, NamedEntityComputed } from '@ngrx/signals/entities'; +`; + + const output = tags.stripIndent` +import { EntityProps, NamedEntityProps } from '@ngrx/signals/entities'; +`; + + const logEntries = await verifySchematic(input, output); + expect(logEntries).toEqual([ + "[@ngrx/signals] Renamed '(Named)EntityComputed' to '(Named)EntityProps' in /main.ts", + ]); + }); + + it('replaces property `computed` in `SignalStoreFeature` to `props`', async () => { + const input = tags.stripIndent` +import { signalStoreFeature, type } from '@ngrx/signals'; +import { Signal } from '@angular/core'; + +export function withMyFeature() { + return signalStoreFeature({ computed: type<{ num: Signal }>() }); +} +`; + + const output = tags.stripIndent` +import { signalStoreFeature, type } from '@ngrx/signals'; +import { Signal } from '@angular/core'; + +export function withMyFeature() { + return signalStoreFeature({ props: type<{ num: Signal }>() }); +} +`; + + const logEntries = await verifySchematic(input, output); + expect(logEntries).toEqual([ + "[@ngrx/signals] Renamed 'computed' to 'props' in signalStoreFeature() in /main.ts", + ]); + }); + + it('replaces property `computed` in `type` with `signalStoreFeature` to `props`', async () => { + const input = tags.stripIndent` +export function withMyFeature() { + return signalStoreFeature( + type<{ computed: { num: Signal } }>() + ); +} +`; + + const output = tags.stripIndent` +export function withMyFeature() { + return signalStoreFeature( + type<{ props: { num: Signal } }>() + ); +} +`; + + await verifySchematic(input, output); + }); + + it('replaces `computed` in `SignalStoreFeature` to `props`', async () => { + const input = tags.stripIndent` +import { SignalStoreFeature } from '@ngrx/signals'; +import { Signal } from '@angular/core'; + +declare function withMyFeature(): SignalStoreFeature< + { state: {}; computed: { num1: Signal }; methods: {} }, + { state: {}; computed: { num2: Signal }; methods: {} } +>; +`; + + const output = tags.stripIndent` +import { SignalStoreFeature } from '@ngrx/signals'; +import { Signal } from '@angular/core'; + +declare function withMyFeature(): SignalStoreFeature< + { state: {}; props: { num1: Signal }; methods: {} }, + { state: {}; props: { num2: Signal }; methods: {} } +>; +`; + + const logEntries = await verifySchematic(input, output); + expect(logEntries).toEqual([ + "[@ngrx/signals] Renamed 'computed' to 'props' in SignalStoreFeature<> in /main.ts", + ]); + }); + + test('kitchen sink', async () => { + const input = tags.stripIndent` +import { EntityComputed, NamedEntityComputed } from '@ngrx/signals/entities'; +import { + EmptyFeatureResult, + SignalStoreFeature, + signalStoreFeature, + type, + withHooks, + withMethods, +} from '@ngrx/signals'; +import { rxMethod } from '@ngrx/signals/rxjs-interop'; +import { tap } from 'rxjs/operators'; +import { Signal } from '@angular/core'; + +declare function withNamedDataService< + E extends { id: number }, + Collection extends string +>(): SignalStoreFeature< + EmptyFeatureResult & { computed: NamedEntityComputed } +>; + +declare function withDataService< + E extends { id: number }, + Collection extends string +>(): SignalStoreFeature }>; + +export function withConsoleLogger() { + return signalStoreFeature( + { computed: type<{ pretty: Signal }>() }, + withMethods(() => ({ + log: rxMethod(tap((message) => console.log(message))), + })), + withHooks((store) => ({ + onInit() { + store.log(store.pretty()); + }, + })) + ); +}`; + + const output = tags.stripIndent` +import { EntityProps, NamedEntityProps } from '@ngrx/signals/entities'; +import { + EmptyFeatureResult, + SignalStoreFeature, + signalStoreFeature, + type, + withHooks, + withMethods, +} from '@ngrx/signals'; +import { rxMethod } from '@ngrx/signals/rxjs-interop'; +import { tap } from 'rxjs/operators'; +import { Signal } from '@angular/core'; + +declare function withNamedDataService< + E extends { id: number }, + Collection extends string +>(): SignalStoreFeature< + EmptyFeatureResult & { props: NamedEntityProps } +>; + +declare function withDataService< + E extends { id: number }, + Collection extends string +>(): SignalStoreFeature }>; + +export function withConsoleLogger() { + return signalStoreFeature( + { props: type<{ pretty: Signal }>() }, + withMethods(() => ({ + log: rxMethod(tap((message) => console.log(message))), + })), + withHooks((store) => ({ + onInit() { + store.log(store.pretty()); + }, + })) + ); +}`; + + const logEntries = await verifySchematic(input, output); + expect(logEntries).toEqual([ + "[@ngrx/signals] Renamed '(Named)EntityComputed' to '(Named)EntityProps' in /main.ts", + "[@ngrx/signals] Renamed 'computed' to 'props' in SignalStoreFeature<> in /main.ts", + "[@ngrx/signals] Renamed 'computed' to 'props' in signalStoreFeature() in /main.ts", + ]); + }); + + it('creates two files with minimal changes and checks both files', async () => { + const input1 = tags.stripIndent` +import { EntityComputed } from '@ngrx/signals/entities'; +`; + + const output1 = tags.stripIndent` +import { EntityProps } from '@ngrx/signals/entities'; +`; + + const input2 = tags.stripIndent` +import { NamedEntityComputed } from '@ngrx/signals/entities'; +`; + + const output2 = tags.stripIndent` +import { NamedEntityProps } from '@ngrx/signals/entities'; + `; + + appTree.create('file1.ts', input1); + appTree.create('file2.ts', input2); + + const logEntries: string[] = []; + schematicRunner.logger.subscribe((logEntry) => + logEntries.push(logEntry.message) + ); + + const tree = await schematicRunner.runSchematic( + `19_0_0-rc_0-props`, + {}, + appTree + ); + + const actual1 = tree.readContent('file1.ts'); + const actual2 = tree.readContent('file2.ts'); + + expect(actual1).toBe(output1); + expect(actual2).toBe(output2); + + expect(logEntries).toEqual([ + "[@ngrx/signals] Renamed '(Named)EntityComputed' to '(Named)EntityProps' in /file1.ts", + "[@ngrx/signals] Renamed '(Named)EntityComputed' to '(Named)EntityProps' in /file2.ts", + ]); + }); +}); diff --git a/modules/signals/migrations/19_0_0-rc_0-props/index.ts b/modules/signals/migrations/19_0_0-rc_0-props/index.ts new file mode 100644 index 0000000000..919ae85230 --- /dev/null +++ b/modules/signals/migrations/19_0_0-rc_0-props/index.ts @@ -0,0 +1,224 @@ +import { + chain, + Rule, + SchematicContext, + Tree, +} from '@angular-devkit/schematics'; +import { + Change, + commitChanges, + createReplaceChange, + visitTSSourceFiles, +} from '../../schematics-core'; +import { + visitCallExpression, + visitImportDeclaration, + visitImportSpecifier, + visitTypeLiteral, + visitTypeReference, +} from '../../schematics-core/utility/visitors'; +import * as ts from 'typescript'; + +function migratedToEntityProps(sourceFile: ts.SourceFile) { + const changes: Change[] = []; + visitImportDeclaration(sourceFile, (importDeclaration, moduleName) => { + if (moduleName !== '@ngrx/signals/entities') { + return; + } + + visitImportSpecifier(importDeclaration, (importSpecifier) => { + if (importSpecifier.name.getText() === 'EntityComputed') { + changes.push( + createReplaceChange( + sourceFile, + importSpecifier, + importSpecifier.getText(), + 'EntityProps' + ) + ); + + visitTypeReference(sourceFile, (type) => { + if (type.typeName.getText() === 'EntityComputed') { + changes.push( + createReplaceChange( + sourceFile, + type, + type.typeName.getText(), + 'EntityProps' + ) + ); + } + }); + } + + if (importSpecifier.name.getText() === 'NamedEntityComputed') { + changes.push( + createReplaceChange( + sourceFile, + importSpecifier, + importSpecifier.getText(), + 'NamedEntityProps' + ) + ); + + visitTypeReference(sourceFile, (typeReference) => { + if (typeReference.typeName.getText() === 'NamedEntityComputed') { + changes.push( + createReplaceChange( + sourceFile, + typeReference.typeName, + typeReference.typeName.getText(), + 'NamedEntityProps' + ) + ); + } + }); + } + }); + }); + + return changes; +} + +function migrateToPropsInSignalStoreFeatureType( + sourceFile: ts.SourceFile +): Change[] { + const changes: Change[] = []; + visitTypeReference(sourceFile, (typeReference) => { + if (typeReference.typeName.getText() !== 'SignalStoreFeature') { + return; + } + + visitTypeLiteral(typeReference, (typeLiteral) => { + const typeLiteralChildren = typeLiteral.members; + for (const propertySignature of typeLiteralChildren) { + if (ts.isPropertySignature(propertySignature)) { + if (propertySignature.name.getText() === 'computed') { + changes.push( + createReplaceChange( + sourceFile, + propertySignature.name, + 'computed', + 'props' + ) + ); + } + } + } + }); + }); + + return changes; +} + +function migrateToPropsInSignalStoreFeatureWithObjectLiteral( + objectLiteral: ts.ObjectLiteralExpression, + sourceFile: ts.SourceFile +): Change[] { + const computedKey = objectLiteral.properties + .filter(ts.isPropertyAssignment) + .find((property) => property.name.getText() === 'computed'); + if (computedKey) { + return [createReplaceChange(sourceFile, computedKey, 'computed', 'props')]; + } + + return []; +} + +function migrateToPropsInSignalStoreFeatureWithCallExpression( + callExpression: ts.CallExpression, + sourceFile: ts.SourceFile +): Change[] { + if (callExpression.expression.getText() === 'type') { + const typeArgument = callExpression.typeArguments?.at(0); + + if (typeArgument && ts.isTypeLiteralNode(typeArgument)) { + const computedKey = typeArgument.members + .filter(ts.isPropertySignature) + .find( + (propertySignature) => propertySignature.name.getText() === 'computed' + ); + + if (computedKey) { + return [ + createReplaceChange(sourceFile, computedKey, 'computed', 'props'), + ]; + } + } + } + + return []; +} + +function migrateToPropsInSignalStoreFeatureFunction( + sourceFile: ts.SourceFile +): Change[] { + const changes: Change[] = []; + visitCallExpression(sourceFile, (callExpression) => { + if (callExpression.expression.getText() !== 'signalStoreFeature') { + return; + } + + const objectLiteralOrCallExpression = callExpression.arguments[0]; + if (!objectLiteralOrCallExpression) { + return; + } + + if (ts.isObjectLiteralExpression(objectLiteralOrCallExpression)) { + changes.push( + ...migrateToPropsInSignalStoreFeatureWithObjectLiteral( + objectLiteralOrCallExpression, + sourceFile + ) + ); + } else if (ts.isCallExpression(objectLiteralOrCallExpression)) { + changes.push( + ...migrateToPropsInSignalStoreFeatureWithCallExpression( + objectLiteralOrCallExpression, + sourceFile + ) + ); + } + }); + + return changes; +} + +export function migrate(): Rule { + return (tree: Tree, ctx: SchematicContext) => { + visitTSSourceFiles(tree, (sourceFile) => { + const entityPropsChanges = migratedToEntityProps(sourceFile); + const propsInSignalStoreFeatureTypeChanges = + migrateToPropsInSignalStoreFeatureType(sourceFile); + const propsInSignalStoreFeatureFunctionChanges = + migrateToPropsInSignalStoreFeatureFunction(sourceFile); + const changes = [ + ...entityPropsChanges, + ...propsInSignalStoreFeatureTypeChanges, + ...propsInSignalStoreFeatureFunctionChanges, + ]; + + commitChanges(tree, sourceFile.fileName, changes); + + if (entityPropsChanges.length) { + ctx.logger.info( + `[@ngrx/signals] Renamed '(Named)EntityComputed' to '(Named)EntityProps' in ${sourceFile.fileName}` + ); + } + if (propsInSignalStoreFeatureTypeChanges.length) { + ctx.logger.info( + `[@ngrx/signals] Renamed 'computed' to 'props' in SignalStoreFeature<> in ${sourceFile.fileName}` + ); + } + if (propsInSignalStoreFeatureFunctionChanges.length) { + ctx.logger.info( + `[@ngrx/signals] Renamed 'computed' to 'props' in signalStoreFeature() in ${sourceFile.fileName}` + ); + } + }); + }; +} + +export default function (): Rule { + return chain([migrate()]); +} diff --git a/modules/signals/migrations/migration.json b/modules/signals/migrations/migration.json index 9d2168ca35..d208435769 100644 --- a/modules/signals/migrations/migration.json +++ b/modules/signals/migrations/migration.json @@ -10,6 +10,11 @@ "description": "Replace StateSignal usages with WritableStateSource", "version": "18.0.0-rc.3", "factory": "./18_0_0-rc_3-writablestatesource/index" + }, + "19_0_0-rc_0-props": { + "description": "Replace several properties with a single props object", + "version": "19.0.0-rc.0", + "factory": "./19_0_0-rc_0-props/index" } } } diff --git a/modules/signals/schematics-core/tsconfig.lib.json b/modules/signals/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/signals/schematics-core/tsconfig.lib.json +++ b/modules/signals/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/signals/schematics-core/utility/visitors.ts b/modules/signals/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/signals/schematics-core/utility/visitors.ts +++ b/modules/signals/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/signals/tsconfig.schematics.json b/modules/signals/tsconfig.schematics.json index c5bb5a37e5..66bc9d8890 100644 --- a/modules/signals/tsconfig.schematics.json +++ b/modules/signals/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/store-devtools/schematics-core/tsconfig.lib.json b/modules/store-devtools/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/store-devtools/schematics-core/tsconfig.lib.json +++ b/modules/store-devtools/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/store-devtools/schematics-core/utility/visitors.ts b/modules/store-devtools/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/store-devtools/schematics-core/utility/visitors.ts +++ b/modules/store-devtools/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/store-devtools/tsconfig.schematics.json b/modules/store-devtools/tsconfig.schematics.json index 2dfddef2e7..ebb3b29630 100644 --- a/modules/store-devtools/tsconfig.schematics.json +++ b/modules/store-devtools/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/store/schematics-core/tsconfig.lib.json b/modules/store/schematics-core/tsconfig.lib.json index c0f1097a2b..13021f14d8 100644 --- a/modules/store/schematics-core/tsconfig.lib.json +++ b/modules/store/schematics-core/tsconfig.lib.json @@ -8,7 +8,7 @@ "outDir": "../../dist/modules/schematics-score", "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["es2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/modules/store/schematics-core/utility/visitors.ts b/modules/store/schematics-core/utility/visitors.ts index fa4edd06af..b0e0229e13 100644 --- a/modules/store/schematics-core/utility/visitors.ts +++ b/modules/store/schematics-core/utility/visitors.ts @@ -198,6 +198,86 @@ export function visitDecorator( }); } +export function visitImportDeclaration( + node: ts.Node, + callback: ( + importDeclaration: ts.ImportDeclaration, + moduleName?: string + ) => void +) { + if (ts.isImportDeclaration(node)) { + const moduleSpecifier = node.moduleSpecifier.getText(); + const moduleName = moduleSpecifier.replaceAll('"', '').replaceAll("'", ''); + + callback(node, moduleName); + } + + ts.forEachChild(node, (child) => { + visitImportDeclaration(child, callback); + }); +} + +export function visitImportSpecifier( + node: ts.ImportDeclaration, + callback: (importSpecifier: ts.ImportSpecifier) => void +) { + const { importClause } = node; + if (!importClause) { + return; + } + + const importClauseChildren = importClause.getChildren(); + for (const namedImport of importClauseChildren) { + if (ts.isNamedImports(namedImport)) { + const namedImportChildren = namedImport.elements; + for (const importSpecifier of namedImportChildren) { + if (ts.isImportSpecifier(importSpecifier)) { + callback(importSpecifier); + } + } + } + } +} + +export function visitTypeReference( + node: ts.Node, + callback: (typeReference: ts.TypeReferenceNode) => void +) { + if (ts.isTypeReferenceNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeReference(child, callback); + }); +} + +export function visitTypeLiteral( + node: ts.Node, + callback: (typeLiteral: ts.TypeLiteralNode) => void +) { + if (ts.isTypeLiteralNode(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitTypeLiteral(child, callback); + }); +} + +export function visitCallExpression( + node: ts.Node, + callback: (callExpression: ts.CallExpression) => void +) { + if (ts.isCallExpression(node)) { + callback(node); + } + + ts.forEachChild(node, (child) => { + visitCallExpression(child, callback); + }); +} + function* visit(directory: DirEntry): IterableIterator { for (const path of directory.subfiles) { if (path.endsWith('.ts') && !path.endsWith('.d.ts')) { diff --git a/modules/store/tsconfig.schematics.json b/modules/store/tsconfig.schematics.json index e53393e33e..27b53d323c 100644 --- a/modules/store/tsconfig.schematics.json +++ b/modules/store/tsconfig.schematics.json @@ -12,7 +12,7 @@ }, "sourceMap": true, "inlineSources": true, - "lib": ["es2018", "dom"], + "lib": ["ES2022", "dom"], "skipLibCheck": true, "strict": true }, diff --git a/projects/ngrx.io/src/404-body.html b/projects/ngrx.io/src/404-body.html index a92c9a7912..66826f10f1 100644 --- a/projects/ngrx.io/src/404-body.html +++ b/projects/ngrx.io/src/404-body.html @@ -42,7 +42,7 @@

Resource Not Found