Comparing version 1.0.10 to 1.1.0
@@ -7,71 +7,24 @@ # Changelog | ||
## [1.0.9] - 2020-04-27 | ||
## [1.1.0] (05-08-2020) | ||
### Added | ||
- Added `beforeEmit` option, which allows 'transforming' `Program` instance before `program.emit()` is called. | ||
## [1.0] (2019 - 2020) | ||
### Fixed | ||
- Updated for Node v14 | ||
_(Addresses [#7](https://github.com/nonara/ts-patch/issues/8), [shelljs/shelljs#991](https://github.com/shelljs/shelljs/issues/991))_ | ||
## [1.0.8] - 2020-04-21 | ||
### Fixed | ||
- Adjusted ts-node compilerOptions to ES2018 | ||
_(Fixes [#7](https://github.com/nonara/ts-patch/issues/7))_ | ||
## [1.0.7] - 2020-03-24 | ||
### Fixed | ||
- Exposed & fixed `addDiagnostic` helper | ||
_(Fixes [#6](https://github.com/nonara/ts-patch/issues/6))_ | ||
## [1.0.6] - 2020-03-18 | ||
### Fixed | ||
- Rolled `resolve` package into patch | ||
_(Fixes [#5](https://github.com/nonara/ts-patch/issues/5))_ | ||
## [1.0.5] - 2019-12-18 | ||
### Fixed | ||
- Converted EOL to LF (MacOS support) | ||
_(Fixes [#3](https://github.com/nonara/ts-patch/issues/3) [#4](https://github.com/nonara/ts-patch/issues/4))_ | ||
## [1.0.4] - 2019-10-31 | ||
### Fixed | ||
- Edge cases occurred in which TypeScript based transformers using CommonJS were not being interpretted properly. | ||
_(Should address [issue #1](https://github.com/nonara/ts-patch/issues/1))_ | ||
## [1.0.3] - 2019-10-31 | ||
### Added | ||
- Added changelog file | ||
### Changed | ||
- Updated rewire implementation in tests (broken with Node 13) | ||
- Locked Rollup to version 1.25.2 (Awaiting fix for [rollup-plugin-dts issue #64](https://github.com/Swatinem/rollup-plugin-dts/issues/64)) | ||
## [1.0.2] - 2019-10-15 | ||
### Changed | ||
- Refactored patch tests to use package TS version | ||
## [1.0.1] - 2019-10-15 | ||
### Fixed | ||
- Corrected a few docstring / comments for accuracy | ||
- Set license to MIT | ||
## [1.0.0] - 2019-10-14 | ||
- Initial project release | ||
[1.0.9]: https://github.com/nonara/ts-patch/compare/v1.0.8...v1.0.9 | ||
[1.0.8]: https://github.com/nonara/ts-patch/compare/v1.0.7...v1.0.8 | ||
[1.0.7]: https://github.com/nonara/ts-patch/compare/v1.0.6...v1.0.7 | ||
[1.0.6]: https://github.com/nonara/ts-patch/compare/v1.0.5...v1.0.6 | ||
[1.0.5]: https://github.com/nonara/ts-patch/compare/v1.0.4...v1.0.5 | ||
[1.0.4]: https://github.com/nonara/ts-patch/compare/v1.0.3...v1.0.4 | ||
[1.0.3]: https://github.com/nonara/ts-patch/compare/v1.0.2...v1.0.3 | ||
[1.0.2]: https://github.com/nonara/ts-patch/compare/v1.0.1...v1.0.2 | ||
[1.0.1]: https://github.com/nonara/ts-patch/compare/v1.0.0...v1.0.1 | ||
[1.0.0]: https://github.com/nonara/ts-patch/releases/tag/v1.0.0 | ||
[1.1.0]: https://github.com/nonara/ts-patch/compare/v1.0.10...v1.1.0 | ||
[1.0]: https://github.com/nonara/ts-patch/releases/tag/v1.0.0...v1.0.10 |
{ | ||
"name": "ts-patch", | ||
"version": "1.0.10", | ||
"version": "1.1.0", | ||
"description": "Patch typescript to support custom transformers in tsconfig.json", | ||
@@ -5,0 +5,0 @@ "main": "./index.js", |
@@ -9,6 +9,9 @@ [![npm version](https://badge.fury.io/js/ts-patch.svg)](https://badge.fury.io/js/ts-patch) | ||
## Description | ||
ts-patch is a tool which patches typescript to allow custom transformers (plugins) to be specified in tsconfig.json. | ||
ts-patch is a tool which directly patches a typescript installation to allow custom transformers (plugins). Plugins are specified in `tsconfig.json`, or provided programmatically in `CompilerOptions`. | ||
Its logic is based on [ttypescript](https://github.com/cevek/ttypescript). (Credit and thanks to [cevek](https://github.com/cevek) for the excellent work!) | ||
It now also supports 'transforming' the `Program` instance prior to emit. See [Transforming Program](#transforming-program) for more info! | ||
Logic based on [ttypescript](https://github.com/cevek/ttypescript). It is also fully compatible. | ||
(Credit and thanks to [cevek](https://github.com/cevek) for the excellent work!) | ||
## Features | ||
@@ -19,2 +22,3 @@ * Easy to patch or unpatch any version of typescript (2.7+) | ||
* Advanced options for patching individual files, specific locations, etc. (see `ts-patch /?`) | ||
* Can transform `Program` instance used for emit | ||
@@ -48,12 +52,14 @@ ## Installation | ||
### Plugin Options | ||
| Option | Description | | ||
| --------------------- | :----------- | | ||
| **transform** | Module name or path to transformer _(*.ts or *.js)_ | | ||
| type | Plugin entry point format _(see [Plugin Types](#plugin-types))_ | | ||
| import | Name of exported transformer function _(defaults to `default` export)_ | | ||
| after | Apply transformer after stock TS transformers. | | ||
| afterDeclarations | Apply transformer to declaration (*.d.ts) files _(TypeScript 2.9+)_. | | ||
| beforeEmit | Transform `Program` before `program.emit()` is called _(See [Transforming Program](#transforming-program))_ | | ||
| _..._ | Provide your own custom options, which will be passed to the transformer | | ||
* **transform** - path to transformer or module name | ||
* **type** (optional) - Plugin entry point format (see below for options) | ||
* **import** (optional) - Name of exported transform plugin in transformer module. | ||
* **after** (optional) - Apply transformer after all others | ||
* **afterDeclarations** (optional) - Apply transformer to d.ts files (supported in TypeScript 2.9+) | ||
* _[custom options]_ - Supply additional options to transformer | ||
_Note: Required options are bold_ | ||
_Note: `transform` can accept npm module or local file path (.ts or .js) relative to to `tsconfig.json` path_ | ||
### Plugin Types | ||
@@ -105,5 +111,6 @@ | ||
{ "transform": "./transformers/my-transformer.ts" }, | ||
{ "transform": "transformer-module", "after": true }, | ||
{ "transform": "transformer-module", "afterDeclarations": true }, | ||
{ "transform": "transformer-module", "type": "ls" } | ||
{ "transform": "transformer-module1", "after": true }, | ||
{ "transform": "transformer-module2", "afterDeclarations": true }, | ||
{ "transform": "transformer-module3", "type": "ls" }, | ||
{ "transform": "transformer-module4", "beforeEmit": true } | ||
] | ||
@@ -114,2 +121,44 @@ } | ||
## Transforming Program | ||
There are some cases where a transformer isn't enough. Some of the biggest examples are if you're trying to: | ||
- TypeCheck code after it's been transformed | ||
- Add or remove emit files during transformation | ||
In order to do this, you'd normally have to create a custom build tool which manually creates `Program` and manipulates | ||
or re-creates it as you need. | ||
The good news is, you can now integrate this into standard tsc behaviour via a `beforeEmit` plugin. | ||
### Export Signature | ||
`(program: ts.Program, host?: ts.CompilerHost, options?: PluginConfig) => ts.Program` | ||
### Notes | ||
- A Program transformer is not a TS transformer. The signature does not change, so the `type` config option is ignored! | ||
- The `before` and `after` config options also do not apply if `beforeEmit: true` is specified | ||
### Example | ||
```TypeScript | ||
/** | ||
* Add a file to Program | ||
*/ | ||
import * as ts from 'typescript'; | ||
import * as path from 'path'; | ||
export const newFile = path.resolve(__dirname, 'added-file.ts'); | ||
export default function (program: ts.Program, host?: ts.CompilerHost) { | ||
return ts.createProgram( | ||
/* rootNames */ program.getRootFileNames().concat([ newFile ]), | ||
program.getCompilerOptions(), | ||
host, | ||
/* oldProgram */ program | ||
); | ||
} | ||
``` | ||
## Transformers | ||
@@ -116,0 +165,0 @@ |
@@ -27,3 +27,11 @@ declare namespace ts { | ||
afterDeclarations?: boolean; | ||
/** | ||
* Alter *Program* instance before emit() is called. (`type`, `after`, & `afterDeclarations` settings will not apply) | ||
* Entry point must be (program: Program, host?: CompilerHost) => Program | ||
*/ | ||
beforeEmit?: boolean; | ||
} | ||
type TransformerList = Required<CustomTransformers>; | ||
type TransformerPlugin = TransformerBasePlugin | TransformerFactory<SourceFile>; | ||
type PluginFactory = LSPattern | ProgramPattern | ConfigPattern | CompilerOptionsPattern | TypeCheckerPattern | RawPattern; | ||
interface TransformerBasePlugin { | ||
@@ -34,5 +42,7 @@ before?: TransformerFactory<SourceFile>; | ||
} | ||
type TransformerList = Required<CustomTransformers>; | ||
type TransformerPlugin = TransformerBasePlugin | TransformerFactory<SourceFile>; | ||
type ProgramTransformer = (program: Program, host?: CompilerHost, config?: PluginConfig) => Program; | ||
type LSPattern = (ls: LanguageService, config: {}) => TransformerPlugin; | ||
type CompilerOptionsPattern = (compilerOpts: CompilerOptions, config: {}) => TransformerPlugin; | ||
type ConfigPattern = (config: {}) => TransformerPlugin; | ||
type TypeCheckerPattern = (checker: TypeChecker, config: {}) => TransformerPlugin; | ||
type ProgramPattern = (program: Program, config: {}, helpers?: { | ||
@@ -42,7 +52,3 @@ ts: typeof ts; | ||
}) => TransformerPlugin; | ||
type CompilerOptionsPattern = (compilerOpts: CompilerOptions, config: {}) => TransformerPlugin; | ||
type ConfigPattern = (config: {}) => TransformerPlugin; | ||
type TypeCheckerPattern = (checker: TypeChecker, config: {}) => TransformerPlugin; | ||
type RawPattern = (context: TransformationContext, program: Program, config: {}) => Transformer<SourceFile>; | ||
type PluginFactory = LSPattern | ProgramPattern | ConfigPattern | CompilerOptionsPattern | TypeCheckerPattern | RawPattern; | ||
/** | ||
@@ -66,3 +72,6 @@ * @example | ||
ls: LanguageService; | ||
}, customTransformers?: CustomTransformers): Required<CustomTransformers>; | ||
}, customTransformers?: CustomTransformers): { | ||
transformers: TransformerList; | ||
programTransformers: Map<ProgramTransformer, PluginConfig>; | ||
}; | ||
private resolveFactory; | ||
@@ -69,0 +78,0 @@ static validateConfigs(configs: PluginConfig[]): void; |
@@ -42,10 +42,36 @@ (function () { | ||
function __spreadArrays() { | ||
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length; | ||
for (var r = Array(s), k = 0, i = 0; i < il; i++) | ||
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) | ||
r[k] = a[j]; | ||
return r; | ||
function __values(o) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0; | ||
if (m) return m.call(o); | ||
return { | ||
next: function () { | ||
if (o && i >= o.length) o = void 0; | ||
return { value: o && o[i++], done: !o }; | ||
} | ||
}; | ||
} | ||
function __read(o, n) { | ||
var m = typeof Symbol === "function" && o[Symbol.iterator]; | ||
if (!m) return o; | ||
var i = m.call(o), r, ar = [], e; | ||
try { | ||
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value); | ||
} | ||
catch (error) { e = { error: error }; } | ||
finally { | ||
try { | ||
if (r && !r.done && (m = i["return"])) m.call(i); | ||
} | ||
finally { if (e) throw e.error; } | ||
} | ||
return ar; | ||
} | ||
function __spread() { | ||
for (var ar = [], i = 0; i < arguments.length; i++) | ||
ar = ar.concat(__read(arguments[i])); | ||
return ar; | ||
} | ||
/* | ||
@@ -882,7 +908,4 @@ * The logic in this file is based on TTypescript (https://github.com/cevek/ttypescript) | ||
/* | ||
* The logic in this file is based on TTypescript (https://github.com/cevek/ttypescript) | ||
* Credit & thanks go to cevek (https://github.com/cevek) for the incredible work! | ||
*/ | ||
// endregion | ||
// endregion | ||
/* ******************************************************************************************************************** | ||
@@ -914,27 +937,39 @@ * PluginCreator | ||
if (source.before) | ||
(_a = into.before).push.apply(_a, slice(source.before)); | ||
(_a = into.before).push.apply(_a, __spread(slice(source.before))); | ||
if (source.after) | ||
(_b = into.after).push.apply(_b, slice(source.after)); | ||
(_b = into.after).push.apply(_b, __spread(slice(source.after))); | ||
if (source.afterDeclarations) | ||
(_c = into.afterDeclarations).push.apply(_c, slice(source.afterDeclarations)); | ||
(_c = into.afterDeclarations).push.apply(_c, __spread(slice(source.afterDeclarations))); | ||
return this; | ||
}; | ||
PluginCreator.prototype.createTransformers = function (params, customTransformers) { | ||
var chain = { before: [], after: [], afterDeclarations: [] }; | ||
var _a = ('ls' in params) ? [params.ls, params.ls.getProgram()] : [void 0, params.program], ls = _a[0], program = _a[1]; | ||
for (var _i = 0, _b = this.configs; _i < _b.length; _i++) { | ||
var config = _b[_i]; | ||
if (!config.transform) | ||
continue; | ||
var factory = this.resolveFactory(config.transform, config.import); | ||
// In case of recursion | ||
if (factory === undefined) | ||
continue; | ||
var transformer = PluginCreator.createTransformerFromPattern({ factory: factory, config: config, program: program, ls: ls }); | ||
this.mergeTransformers(chain, transformer); | ||
var e_1, _a; | ||
var transformers = { before: [], after: [], afterDeclarations: [] }; | ||
var programTransformers = new Map(); | ||
var _b = __read(('ls' in params) ? [params.ls, params.ls.getProgram()] : [void 0, params.program], 2), ls = _b[0], program = _b[1]; | ||
try { | ||
for (var _c = __values(this.configs), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var config = _d.value; | ||
if (!config.transform) | ||
continue; | ||
var factory = this.resolveFactory(config.transform, config.import); | ||
if (factory === undefined) | ||
continue; // In case of recursion | ||
if (config.beforeEmit) | ||
programTransformers.set(factory, config); | ||
else | ||
this.mergeTransformers(transformers, PluginCreator.createTransformerFromPattern({ factory: factory, config: config, program: program, ls: ls })); | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
// Chain custom transformers at the end | ||
if (customTransformers) | ||
this.mergeTransformers(chain, customTransformers); | ||
return chain; | ||
this.mergeTransformers(transformers, customTransformers); | ||
return { transformers: transformers, programTransformers: programTransformers }; | ||
}; | ||
@@ -964,2 +999,3 @@ /* *********************************************************** | ||
return; | ||
/* Load plugin */ | ||
requireStack.push(modulePath); | ||
@@ -980,11 +1016,21 @@ var commonjsModule = require(modulePath); | ||
PluginCreator.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'); | ||
var e_2, _a; | ||
try { | ||
for (var configs_1 = __values(configs), configs_1_1 = configs_1.next(); !configs_1_1.done; configs_1_1 = configs_1.next()) { | ||
var config = configs_1_1.value; | ||
if (!config.name && !config.transform) | ||
throw new Error('tsconfig.json plugins error: transform must be present'); | ||
} | ||
} | ||
catch (e_2_1) { e_2 = { error: e_2_1 }; } | ||
finally { | ||
try { | ||
if (configs_1_1 && !configs_1_1.done && (_a = configs_1.return)) _a.call(configs_1); | ||
} | ||
finally { if (e_2) throw e_2.error; } | ||
} | ||
}; | ||
PluginCreator.createTransformerFromPattern = function (_a) { | ||
var 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"]); | ||
var transform = config.transform, after = config.after, afterDeclarations = config.afterDeclarations, name = config.name, type = config.type, beforeEmit = config.beforeEmit, cleanConfig = __rest(config, ["transform", "after", "afterDeclarations", "name", "type", "beforeEmit"]); | ||
if (!transform) | ||
@@ -1065,3 +1111,3 @@ throw new Error('Not a valid config entry: "transform" key not found'); | ||
var _a = plugins[0].customTransformers, _b = _a.before, before_1 = _b === void 0 ? [] : _b, _c = _a.after, after_1 = _c === void 0 ? [] : _c; | ||
return __spreadArrays(before_1.map(function (item) { return ({ transform: item }); }), after_1.map(function (item) { return ({ transform: item, after: true }); })); | ||
return __spread(before_1.map(function (item) { return ({ transform: item }); }), after_1.map(function (item) { return ({ transform: item, after: true }); })); | ||
} | ||
@@ -1106,9 +1152,30 @@ return plugins; | ||
/* Hook TypeScript emit method */ | ||
// noinspection UnnecessaryLocalVariableJS | ||
var originalEmit = program.emit; | ||
program.originalEmit = originalEmit; | ||
program.emit = function newEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers) { | ||
var e_1, _a; | ||
/* Merge in our transformers */ | ||
var mergedTransformers = pluginCreator.createTransformers({ program: program }, customTransformers); | ||
var _b = pluginCreator.createTransformers({ program: program }, customTransformers), programTransformers = _b.programTransformers, transformers = _b.transformers; | ||
/* Transform Program */ | ||
var targetProgram = program; | ||
try { | ||
// @ts-ignore - no iterator error | ||
for (var _c = __values(programTransformers.entries()), _d = _c.next(); !_d.done; _d = _c.next()) { | ||
var _e = __read(_d.value, 2), programTransformer = _e[0], config = _e[1]; | ||
var newProgram = programTransformer(targetProgram, host, config); | ||
if (typeof (newProgram === null || newProgram === void 0 ? void 0 : newProgram['emit']) === 'function') | ||
targetProgram = newProgram; | ||
} | ||
} | ||
catch (e_1_1) { e_1 = { error: e_1_1 }; } | ||
finally { | ||
try { | ||
if (_d && !_d.done && (_a = _c.return)) _a.call(_c); | ||
} | ||
finally { if (e_1) throw e_1.error; } | ||
} | ||
/* Invoke TS emit */ | ||
var result = originalEmit(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, mergedTransformers); | ||
result.diagnostics = __spreadArrays((result.diagnostics || []), (transformerErrors.get(program) || [])); | ||
var result = (targetProgram['originalEmit'] || targetProgram.emit)(targetSourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, transformers); | ||
result.diagnostics = __spread((result.diagnostics || []), (transformerErrors.get(program) || [])); | ||
return result; | ||
@@ -1115,0 +1182,0 @@ }; |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
161713
2481
226