I'm compiling typescript to es5 / commonjs format. I'm using typescript's tsconfig.json paths
property to specify a fixed root for `import statements.
So for example I might have a path configuration @example: './src/'
.
After the *.ts files are compiled the the require statements will look something like:
require('@example/boo/foo');
I need to create a post processing script that considers the path of the current javascript file and the import path.
So for example if the javascript file having it's imports updated is located in dist/foo/pitythefoo.js
and it imports exports from dist/boo/boo.js
then the path @example/boo/boo
has to be replaced with ../boo/boo
.
Now if pitythefoo.js
was at the root of dist
(dist/pitythefoo.js
then the @example
string would just be replaced with ./
.
So the basic algorithm seems to be:
If the file is at the root of dist
, then replace @example
with ./
. If it's deeper, then count how deep and if it's for example two directories deep, then add the ../..
to move up to the root and then into the path where the importing module resource sits. Sound reasonable?
So in general I was was thinking something like:
globby('dist/**/*.js'). //get the paths of all the js files
then(process); //read each file as a text file and perform the string replacement
//Save the file using the original file name.
function process(path:string) {
const file = fs.readFileSync(path);
//update require statements contents of file
fs.writeFileSync(file,path);
}
Does anyone know of a utility that function that can analyzes the import path length and the path of the current resources and generate the correct relative path for the require()
statement?
It seems like it might be a fairly common pattern, so trying to avoid reinventing the wheel ...
I've implemented a script that solves this for my project. The goal was to be able to use the non relative paths, which we can do with Typescripts paths
configuration option, and have the compiled ES5 / CommonJS output use relative paths such that the package could be published to NPM. The link above has the github version and here it is the code:
const fs = require("fs");
const globby = require("globby");
require("mkdirp").sync("dist");
require("cpy")("package.json", "dist");
const options = { overwrite: true };
const rc = require("recursive-copy");
rc("target/src/", "dist", options).then(() => {
globby("./dist/**/*.js")
.then(paths => {
paths.forEach(update);
})
.catch(e => console.log(e));
globby("./dist/**/*.d.ts")
.then(paths => {
paths.forEach(update);
})
.catch(e => console.log(e));
});
function update(path) {
count = (path.match(/\//g) || []).length;
let replacement = "";
if (count == 2) {
replacement = "./";
} else if (count > 2) {
const size = count - 2;
replacement = Array(size)
.fill("../")
.join("");
} else {
throw new Error("Invalid / count in path of file");
}
let js = fs.readFileSync(path, "utf8");
js = js.replace(/@fs\//g, replacement);
fs.writeFileSync(path, js);
}