UNPKG

@adonisjs/require-ts

Version:
196 lines (195 loc) 6.88 kB
"use strict"; /* * @adonisjs/require-ts * * (c) Harminder Virk <virk@adonisjs.comharminder@cav.ai> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Compiler = void 0; const utils_1 = require("@poppinss/utils"); const source_map_support_1 = __importDefault(require("source-map-support")); const utils_2 = require("../utils"); const Cache_1 = require("../Cache"); const DiagnosticsReporter_1 = require("../DiagnosticsReporter"); /** * Exposes the API compile source files using the tsc compiler. No * type checking takes place. */ class Compiler { constructor(appRoot, cacheRoot, ts, options, usesCache = true) { this.appRoot = appRoot; this.cacheRoot = cacheRoot; this.ts = ts; this.options = options; this.usesCache = usesCache; /** * In-memory compiled files cache for source maps to work. */ this.memCache = new Map(); /** * Disk cache */ this.cache = this.usesCache ? new Cache_1.Cache(this.appRoot, this.cacheRoot) : new Cache_1.FakeCache(); /** * Dignostic reporter to print program errors */ this.diagnosticsReporter = new DiagnosticsReporter_1.DiagnosticsReporter(this.appRoot, this.ts, false); this.transformers = {}; this.patchCompilerOptions(); this.setupSourceMaps(); this.resolveTransformers(); } /** * Patch compiler options to make source map work properly */ patchCompilerOptions() { /** * Force inline source maps. We need this to avoid manual * lookups */ this.options.compilerOptions.inlineSourceMap = true; /** * Inline sources */ this.options.compilerOptions.inlineSources = true; /** * Remove "outDir" property, so that the source maps paths are generated * relative from the cwd and not the outDir. * * ts-node manually patches the source maps to use absolute paths. We cannot * do same, since we cache files on the disk and changing the folder name * of project root will corrupt the absolute path names inside the * source maps. */ delete this.options.compilerOptions.outDir; /** * Inline source maps and source map cannot be used together */ delete this.options.compilerOptions.sourceMap; } /** * Resolves transformer relative from the app root */ resolverTransformer(transformer) { try { const value = (0, utils_1.esmRequire)(require.resolve(transformer, { paths: [this.appRoot] })); if (typeof value !== 'function') { throw new Error('Transformer module must export a function'); } return value(this.ts, this.appRoot); } catch (error) { if (error.code === 'ENOENT') { throw new Error(`Unable to resolve transformer "${transformer}" specified in tsconfig.json file`); } throw error; } } /** * Resolve transformers */ resolveTransformers() { if (!this.options.transformers) { return; } if (this.options.transformers.before) { this.transformers.before = this.options.transformers.before.map((transformer) => { return this.resolverTransformer(transformer.transform); }); } if (this.options.transformers.after) { this.transformers.after = this.options.transformers.after.map((transformer) => { return this.resolverTransformer(transformer.transform); }); } if (this.options.transformers.afterDeclarations) { this.transformers.afterDeclarations = this.options.transformers.afterDeclarations.map((transformer) => { return this.resolverTransformer(transformer.transform); }); } } /** * Setup source maps support to read from in-memory cache */ setupSourceMaps() { source_map_support_1.default.install({ environment: 'node', retrieveFile: (pathOrUrl) => { (0, utils_2.debug)('reading source for "%s"', pathOrUrl); return this.memCache.get(pathOrUrl) || ''; }, }); } /** * Compiles the file using the typescript compiler */ compileFile(filePath, contents, virtualFile) { (0, utils_2.debug)('compiling file using typescript "%s"', filePath); let { outputText, diagnostics } = this.ts.transpileModule(contents, { fileName: filePath, compilerOptions: virtualFile ? { ...this.options.compilerOptions, rootDir: undefined, } : this.options.compilerOptions, reportDiagnostics: !virtualFile, transformers: this.transformers, }); /** * Report diagnostics if any */ if (diagnostics) { this.diagnosticsReporter.report(diagnostics); } /** * Write to in-memory cache for sourcemaps to work */ this.memCache.set(filePath, outputText); return outputText; } /** * Compile typescript source code using the tsc compiler. */ compile(filePath, contents, virtualFile = false) { /** * Do not cache virtual files */ if (virtualFile) { (0, utils_2.debug)('compiling virtual file "%s" (no cache)', filePath); return this.compileFile(filePath, contents, true); } (0, utils_2.debug)('compiling file "%s"', filePath); const cachePath = this.cache.makeCachePath(filePath, contents, '.js'); /** * Return the file from cache when it exists */ const compiledContent = this.cache.get(cachePath); if (compiledContent) { /** * Write to in-memory cache for sourcemaps to work */ this.memCache.set(filePath, compiledContent); return compiledContent; } /** * Compile file using the compiler */ const outputText = this.compileFile(filePath, contents, false); /** * Write to cache on disk */ this.cache.set(cachePath, outputText); /** * Return compiled text */ return outputText; } } exports.Compiler = Compiler;