Skip to content

Instantly share code, notes, and snippets.

@azarus azarus/gulptask.js
Last active Jan 29, 2020

Embed
What would you like to do?
Gulp Task to transform Typescript path imports into relative paths using the tsconfig
// Gulp Task
gulp.task("compile:source", function(done) {
gutil.log(gutil.colors.yellow("[Typescript]"), gutil.colors.magenta('Transpiling Source'));
var tsProject = ts.createProject('tsconfig.json', {
typescript: require('typescript'),
});
gulp.src("source/**/*")
.pipe(tsProject())
.pipe(tsimport(tsProject.config.compilerOptions))
.on('error', function(error, callback)
{
gutil.log(gutil.colors.red("[Typescript] Server Error:"), error.stack);
this.emit("end");
})
.pipe(gulp.dest("build/"))
.on("end", done);
});
var through = require('through2');
var replacePath = require("./replace-path.js");
module.exports = function(importOptions)
{
return function(file)
{
return through(function (buffer, enc, cb)
{
var code = buffer.toString("utf8");
code = replacePath(code, file, importOptions.baseUrl, importOptions.paths);
buffer = new Buffer(code);
this.push(buffer);
cb();
});
}
};
var fs = require("fs");
var path = require("path");
module.exports = function(code, filePath, rootPath, targetPaths)
{
var tscpaths = Object.keys(targetPaths);
var lines = code.split("\n");
return lines.map((line) =>
{
var matches = [];
var require_matches = line.match(/require\(('|")(.*)('|")\)/g);
// var import_matches = line.match(/import ('|")(.*)('|")/g);
Array.prototype.push.apply(matches, require_matches);
if(!matches)
{
return line;
}
// Go through each require statement
for(var match of matches)
{
// Find each paths
for(var tscpath of tscpaths)
{
// Find required module & check if its path matching what is described in the paths config.
var requiredModules = match.match(new RegExp(tscpath, "g"));
if(requiredModules && requiredModules.length > 0)
{
for(var requiredModule of requiredModules)
{
// Skip if it resolves to the node_modules folder
var modulePath = path.resolve('./node_modules/' + tscpath);
if (fs.existsSync(modulePath))
{
continue;
}
// Get relative path and replace
var sourcePath = path.dirname(filePath);
var targetPath = path.dirname(path.resolve(rootPath + "/" + targetPaths[tscpath]));
var relativePath = path.relative(sourcePath, targetPath)
line = line.replace(new RegExp(tscpath, "g"), "./" + relativePath + "/");
}
}
}
}
return line;
}).join("\n");
};
var through = require('through2');
var replacePath = require("./replace-path.js");
module.exports = function(importOptions)
{
return through.obj(function (file, enc, cb)
{
var code = file.contents.toString('utf8');
code = replacePath(code, file.history.toString(), importOptions.baseUrl, importOptions.paths);
file.contents = new Buffer(code);
this.push(file);
cb();
});
};
var tsify = require('tsify');
var importify = require("./typescript/importify.js");
var tsconfig = require("../tsconfig.json");
function CompileSources(entryFile)
{
var bundler = watchify( browserify({
entries: entryFile,
debug: false,
// defining transforms here will avoid crashing your stream
})
.plugin(tsify, tsconfig.compilerOptions))
.transform(importify(tsconfig.compilerOptions))
// .. etc
}
@azarus

This comment has been minimized.

Copy link
Owner Author

azarus commented Jun 4, 2017

So what the above code does is transforms all the path and baseurl options specified in the tsconfig.json file!

So lets say you have something like this specified in your tsconfig.json

{
  "compilerOptions": {
    "baseUrl": "./source/",
	"paths": {
            "@Test/*": [
                "./Test/*"
            ]
    },
  }
}

then you can use
import Test from "@Test/whatever";

it will be translated to an absolute url such as:

./whatever
or

./../whatever

depending on the location of the file.

The following code work for Browserify+watchify+tsify and Gulp-Typescript

Have fun getting rid of the relative path nightmare!!!

@prograhammer

This comment has been minimized.

Copy link

prograhammer commented Nov 25, 2017

Is this in an npm package anywhere? That's so weird that typescript doesn't do this!??

@kirakishin

This comment has been minimized.

Copy link

kirakishin commented Nov 28, 2017

@prograhammer i think the exact same thing !

@spentak

This comment has been minimized.

Copy link

spentak commented Nov 29, 2017

Yo this is cool but it doesn't parse directories within directories. Some bad regex I think

@salchichongallo

This comment has been minimized.

Copy link

salchichongallo commented Dec 17, 2017

Hi! I just built a package based on this. It's called path-alias-resolver

@yadue

This comment has been minimized.

Copy link

yadue commented Dec 21, 2017

@salchichongallo how to use your plug-in?

@jazzfog

This comment has been minimized.

Copy link

jazzfog commented Feb 6, 2018

Awesome!
One small bug on Windows though: Windows-style back-slash that comes from path.relative in relativePath breaks require().
Need to replace it to regular slash (/):

in replace-path.js
after
var relativePath = path.relative(sourcePath, targetPath)
add
relativePath = relativePath.replace(/\\/g, '/');

@Alex66955

This comment has been minimized.

Copy link

Alex66955 commented Apr 24, 2018

I have two issues with your script:

  • If the tsconfig.json provides an outDir attribute not even ".":
    • the relative path replacement didn't work correctly. It generates the relative path from outDir to sourceDir which should not happened.
    • the import replacement should be independent from the outDir attribute
    • my current workaround is to remove the outDir attribute in tsconfig and using the gulp.dest.
  • On my linux machine (ubuntu 16.04) the import replacement makes some mistakes:
    • There is a syntax error causes by a double "/"
      • tsconfig: .."@backend-TP*": ["./platform/TP/*"]..
      • src: import { CategoryTraceListener } from '@backend-TP/shared/diagnostics';
      • generated: const diagnostics_1 = require("./platform/TP//shared/diagnostics");
    • My current workaround in replace-path.js line = line.replace(new RegExp(tscpath+"/", "g"), "./" + relativePath + "/");
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.