Im executing a ts file with:
npx ts-node ./tinker.ts
The file reads and parses the AST of another file sample.ts
containing a single line:
console.log(123)
Next it should execute that code, but manipulate it before doing so - for example I want to change 123 to 1337.
So, the final result of running npx ts-node ./tinker.ts
should be that 1337 is printed in my terminal. Please see my draft below. The code comments is the part that I could not understand how to do.
console.log(123);
import * as fs from "fs";
const ts = require("typescript");
const path = "./sample.ts";
const code = fs.readFileSync(path, "utf-8"); // "console.log(123)"
const node = ts.createSourceFile("TEMP.ts", code, ts.ScriptTarget.Latest);
let logStatement = node.statements.at(0);
logStatement.expression.arguments.at(0).text = "1337";
// execute the manipulated code!
// expect to see 1337 logged!
To reiterate, running npx ts-node ./tinker.ts
should log 1337. How can I achieve this?
The idea of the solution is to perform the following actions:
package.json
file{
"name": "question-73432934",
"version": "1.0.0",
"description": "",
"main": "index.js",
"type": "module",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "BSD",
"dependencies": {
"ts-morph": "15.1.0",
"typescript": "4.7.4"
},
"devDependencies": {
"ts-node": "10.9.1"
}
}
After updating the file content, please, execute the command:
$ npm clean-install
tsconfig.json
file{
"compilerOptions": {
"target": "es2017",
"module": "esnext",
"moduleResolution": "node",
"esModuleInterop": true
},
"ts-node": {
"esm": true
}
}
sample.ts
fileconsole.log(123);
tinker.ts
fileimport * as fs from "fs";
import { Project, SyntaxKind, CallExpression } from "ts-morph";
async function createModifiedFile(inputFilePath: string, outputFilePath: string) {
const code = await fs.promises.readFile(inputFilePath, "utf8");
const project = new Project();
const sourceFile = project.createSourceFile(
outputFilePath,
code,
{ overwrite: true }
);
const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression);
const callExpression = callExpressions[0] as CallExpression;
callExpression.removeArgument(0);
callExpression.addArgument("1337");
await sourceFile.save();
};
async function importModuleDynamically(filePath: string) {
await import(filePath);
};
await createModifiedFile("sample.ts", "temp.ts");
await importModuleDynamically("./temp.ts");
$ npx ts-node tinker.ts
Program output:
1337
The created TypeScript module:
$ cat temp.ts
console.log(1337);
import