Skip to content

Commit

Permalink
feat(nest): add v10 migrations for tsconfig & CacheModule
Browse files Browse the repository at this point in the history
  • Loading branch information
barbados-clemens committed Jun 23, 2023
1 parent 16b9b20 commit e7d3115
Show file tree
Hide file tree
Showing 4 changed files with 384 additions and 1 deletion.
6 changes: 6 additions & 0 deletions packages/nest/migrations.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@
"version": "16.0.0-beta.1",
"description": "Replace @nrwl/nest with @nx/nest",
"implementation": "./src/migrations/update-16-0-0-add-nx-packages/update-16-0-0-add-nx-packages"
},
"update-16-4-0-support-nestjs-10": {
"cli": "nx",
"version": "16.4.0-beta.16",
"description": "Update TsConfig target to es2021 and CacheModule if being used. Read more at https://docs.nestjs.com/migration-guide",
"implementation": "./src/migrations/update-16-4-0-cache-manager/nestjs-10-updates"
}
},
"packageJsonUpdates": {
Expand Down
3 changes: 2 additions & 1 deletion packages/nest/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"@nx/devkit": "file:../devkit",
"@nx/js": "file:../js",
"@nx/linter": "file:../linter",
"@nx/node": "file:../node"
"@nx/node": "file:../node",
"@phenomnomnominal/tsquery": "~5.0.1"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import {
Tree,
addDependenciesToPackageJson,
createProjectGraphAsync,
formatFiles,
getProjects,
joinPathFragments,
updateJson,
visitNotIgnoredFiles,
} from '@nx/devkit';
import { tsquery } from '@phenomnomnominal/tsquery';
import {
ImportDeclaration,
VariableStatement,
ScriptTarget,
isVariableStatement,
} from 'typescript';

const JS_TS_FILE_MATCHER = /\.[jt]sx?$/;

const importMatch =
':matches(ImportDeclaration, VariableStatement):has(Identifier[name="CacheModule"], Identifier[name="CacheModule"]):has(StringLiteral[value="@nestjs/common"])';

export async function updateNestJs10(tree: Tree) {
const nestProjects = await getNestProejcts();
if (nestProjects.length === 0) {
return;
}

let installCacheModuleDeps = false;
const projects = getProjects(tree);

for (const projectName of nestProjects) {
const projectConfig = projects.get(projectName);
const tsConfig =
projectConfig.targets?.build?.options?.tsConfig ??
joinPathFragments(
projectConfig.root,
projectConfig.projectType === 'application'
? 'tsconfig.app.json'
: 'tsconfig.lib.json'
);

if (tree.exists(tsConfig)) {
updateTsConfigTarget(tree, tsConfig);
}

visitNotIgnoredFiles(tree, projectConfig.root, (filePath) => {
if (!JS_TS_FILE_MATCHER.test(filePath)) {
return;
}

installCacheModuleDeps =
updateCacheManagerImport(tree, filePath) || installCacheModuleDeps;
});
}

await formatFiles(tree);

return installCacheModuleDeps
? addDependenciesToPackageJson(
tree,
{
'@nestjs/cache-manager': '^2.0.0',
'cache-manager': '^5.2.3',
},
{}
)
: () => {};
}

async function getNestProejcts(): Promise<string[]> {
const projectGraph = await createProjectGraphAsync();

return Object.entries(projectGraph.dependencies)
.filter(([node, dep]) =>
dep.some(
({ target }) =>
!projectGraph.externalNodes?.[node] && target === 'npm:@nestjs/common'
)
)
.map(([projectName]) => projectName);
}

// change import { CacheModule } from '@nestjs/common';
// to import { CacheModule } from '@nestjs/cache-manager';
export function updateCacheManagerImport(
tree: Tree,
filePath: string
): boolean {
const content = tree.read(filePath, 'utf-8');

const updated = tsquery.replace(
content,
importMatch,

(node: ImportDeclaration | VariableStatement) => {
const text = node.getText();
return `${text.replace('CacheModule', '')}\n${
isVariableStatement(node)
? "const { CacheModule } = require('@nestjs/cache-manager')"
: "import { CacheModule } from '@nestjs/cache-manager';"
}`;
}
);

if (updated !== content) {
tree.write(filePath, updated);
return true;
}
}

export function updateTsConfigTarget(tree: Tree, tsConfigPath: string) {
updateJson(tree, tsConfigPath, (json) => {
if (!json.compilerOptions.target) {
return;
}

const normalizedTargetName = json.compilerOptions.target.toUpperCase();
// es6 isn't apart of the ScriptTarget enum but is a valid tsconfig target in json file
const existingTarget =
normalizedTargetName === 'ES6'
? ScriptTarget.ES2015
: (ScriptTarget[normalizedTargetName] as unknown as ScriptTarget);

if (existingTarget < ScriptTarget.ES2021) {
json.compilerOptions.target = 'es2021';
}

return json;
});
}

export default updateNestJs10;
Loading

0 comments on commit e7d3115

Please sign in to comment.