Using Typescript's baseUrl compiler option with node

862 views Asked by At

Can node's module loader support TS's baseUrl compiler option?

TS 2 introduced the baseUrl compiler option, to effectively enable project relative require() and import requests.

However, this requires the module loader to support the same thing, as TS doesn't actually rewrite the request during transpilation. For tools like webpack, this is fairly straightforward.

Unfortunately, when using TS to develop node applications (.i.e backend services, command line tools, electron desktop apps) there didn't seem to be a way to change node's module loader behavior.

Is there a way?

1

There are 1 answers

0
user2672083 On BEST ANSWER

Yes!

Appreciating TS's position, here's a simple solution to the 90% use case for those of us using node, but wanting the convenience of using baseUrl relative require() calls without any fuss.

This solution hooks node's require() call, and resolves requests using the dirname of "main" to mimic baseUrl. It therefore assumes the baseUrl compiler option was also set to the same directory where the source "main.ts" was located.

To use, paste this tiny chunk of code at the top of your "main.ts".

import * as path from 'path'
import * as fs from 'fs'
(function() {
  const CH_PERIOD = 46
  const baseUrl = path.dirname(process['mainModule'].filename)
  const existsCache = {d:0}; delete existsCache.d
  const moduleProto = Object.getPrototypeOf(module)
  const origRequire = moduleProto.require
  moduleProto.require = function(request) {
    let existsPath = existsCache[request]
    if(existsPath === undefined) {
      existsPath = ''
      if(!path.isAbsolute(request) && request.charCodeAt(0) !== CH_PERIOD) {
        const ext = path.extname(request)
        const basedRequest = path.join(baseUrl, ext ? request : request + '.js')
        if(fs.existsSync(basedRequest)) existsPath = basedRequest
        else {
          const basedIndexRequest = path.join(baseUrl, request, 'index.js')
          existsPath = fs.existsSync(basedIndexRequest) ? basedIndexRequest : ''
        }
      }
      existsCache[request] = existsPath
    }
    return origRequire.call(this, existsPath || request)
  }
})()