ttypescript
Version:
Over TypeScript tool to use custom transformers in the tsconfig.json
191 lines (190 loc) • 7.72 kB
JavaScript
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.PluginCreator = void 0;
var resolve = require("resolve");
var util_1 = require("util");
var patchCreateProgram_1 = require("./patchCreateProgram");
function createTransformerFromPattern(_a) {
var typescript = _a.typescript, factory = _a.factory, config = _a.config, program = _a.program, ls = _a.ls;
var transform = config.transform, after = config.after, afterDeclarations = config.afterDeclarations, name = config.name, type = config.type, cleanConfig = __rest(config, ["transform", "after", "afterDeclarations", "name", "type"]);
if (!transform)
throw new Error('Not a valid config entry: "transform" key not found');
var ret;
switch (config.type) {
case 'ls':
if (!ls)
throw new Error("Plugin ".concat(transform, " need a LanguageService"));
ret = factory(ls, cleanConfig);
break;
case 'config':
ret = factory(cleanConfig);
break;
case 'compilerOptions':
ret = factory(program.getCompilerOptions(), cleanConfig);
break;
case 'checker':
ret = factory(program.getTypeChecker(), cleanConfig);
break;
case undefined:
case 'program':
ret = factory(program, cleanConfig, {
ts: typescript,
addDiagnostic: (0, patchCreateProgram_1.addDiagnosticFactory)(program),
});
break;
case 'raw':
ret = function (ctx) { return factory(ctx, program, cleanConfig); };
break;
default:
return never(config.type);
}
if (typeof ret === 'function') {
if (after)
return { after: ret };
else if (afterDeclarations) {
return { afterDeclarations: ret };
}
else
return { before: ret };
}
return ret;
}
function never(n) {
throw new Error('Unexpected type: ' + n);
}
var tsNodeIncluded = false;
// to fix recursion bug, see usage below
var requireStack = [];
/**
* @example
*
* new PluginCreator([
* {transform: '@zerollup/ts-transform-paths', someOption: '123'},
* {transform: '@zerollup/ts-transform-paths', type: 'ls', someOption: '123'},
* {transform: '@zerollup/ts-transform-paths', type: 'ls', after: true, someOption: '123'}
* ]).createTransformers({ program })
*/
var PluginCreator = /** @class */ (function () {
function PluginCreator(typescript, configs, resolveBaseDir) {
if (resolveBaseDir === void 0) { resolveBaseDir = process.cwd(); }
this.typescript = typescript;
this.configs = configs;
this.resolveBaseDir = resolveBaseDir;
this.validateConfigs(configs);
}
PluginCreator.prototype.mergeTransformers = function (into, source) {
var _a, _b, _c;
var slice = function (input) { return (Array.isArray(input) ? input.slice() : [input]); };
if (source.before) {
(_a = into.before).push.apply(_a, slice(source.before));
}
if (source.after) {
(_b = into.after).push.apply(_b, slice(source.after));
}
if (source.afterDeclarations) {
(_c = into.afterDeclarations).push.apply(_c, slice(source.afterDeclarations));
}
return this;
};
PluginCreator.prototype.createTransformers = function (params, customTransformers) {
var chain = {
before: [],
after: [],
afterDeclarations: [],
};
var ls;
var program;
if ('ls' in params) {
ls = params.ls;
program = ls.getProgram();
}
else {
program = params.program;
}
for (var _i = 0, _a = this.configs; _i < _a.length; _i++) {
var config = _a[_i];
if (!config.transform) {
continue;
}
var factory = this.resolveFactory(config.transform, config.import);
// if recursion
if (factory === undefined)
continue;
var transformer = createTransformerFromPattern({
typescript: this.typescript,
factory: factory,
config: config,
program: program,
ls: ls,
});
this.mergeTransformers(chain, transformer);
}
// if we're given some custom transformers, they must be chained at the end
if (customTransformers) {
this.mergeTransformers(chain, customTransformers);
}
return chain;
};
PluginCreator.prototype.resolveFactory = function (transform, importKey) {
if (importKey === void 0) { importKey = 'default'; }
if (!tsNodeIncluded &&
transform.match(/\.tsx?$/) &&
(module.parent.parent === null ||
module.parent.parent.parent === null ||
module.parent.parent.parent.id.split(/[\/\\]/).indexOf('ts-node') === -1)) {
require('ts-node').register({
transpileOnly: true,
skipProject: true,
compilerOptions: {
target: 'ES2018',
jsx: 'react',
esModuleInterop: true,
module: 'commonjs',
},
});
tsNodeIncluded = true;
}
var modulePath = resolve.sync(transform, { basedir: this.resolveBaseDir });
// in ts-node occurs error cause recursion:
// ts-node file.ts -> createTransformers -> require transformer.ts
// -> createTransformers -> require transformer.ts -> ...
// this happens cause ts-node uses to compile transformers the same config included this transformer
// so this stack checks that if we already required this file we are in the reqursion
if (requireStack.indexOf(modulePath) > -1)
return;
requireStack.push(modulePath);
var commonjsModule = require(modulePath);
requireStack.pop();
var factoryModule = typeof commonjsModule === 'function' ? { default: commonjsModule } : commonjsModule;
var factory = factoryModule[importKey];
if (!factory) {
throw new Error("tsconfig.json > plugins: \"".concat(transform, "\" does not have an export \"").concat(importKey, "\": ") +
(0, util_1.inspect)(factoryModule));
}
if (typeof factory !== 'function') {
throw new Error("tsconfig.json > plugins: \"".concat(transform, "\" export \"").concat(importKey, "\" is not a plugin: \"").concat((0, util_1.inspect)(factory), "\""));
}
return factory;
};
PluginCreator.prototype.validateConfigs = function (configs) {
for (var _i = 0, configs_1 = configs; _i < configs_1.length; _i++) {
var config = configs_1[_i];
if (!config.name && !config.transform) {
throw new Error('tsconfig.json plugins error: transform must be present');
}
}
};
return PluginCreator;
}());
exports.PluginCreator = PluginCreator;
;