Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
ts-patch is a tool that allows you to patch the TypeScript compiler (tsc) to enable custom transformers and other advanced features. It is particularly useful for developers who need to extend the capabilities of TypeScript beyond what is natively supported.
Custom Transformers
This feature allows you to apply custom transformers to the TypeScript compiler. By patching the compiler, you can specify custom transformers in your tsconfig.json file, enabling advanced code transformations during the compilation process.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can use custom transformers in your tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"plugins": [
{ "transform": "./path/to/your/transformer" }
]
}
}
// Unpatch when done
unpatch();
Advanced Compiler Options
This feature allows you to enable advanced compiler options that are not natively supported by TypeScript. By patching the compiler, you can use options like experimental decorators and emit decorator metadata.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can use advanced compiler options in your tsconfig.json
// tsconfig.json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true
}
}
// Unpatch when done
unpatch();
Integration with Build Tools
This feature allows you to integrate ts-patch with various build tools like Webpack. By patching the TypeScript compiler, you can use custom transformers and advanced compiler options in your build process.
const { patch, unpatch } = require('ts-patch');
// Apply the patch
patch();
// Now you can integrate ts-patch with build tools like Webpack
// webpack.config.js
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/
}
]
},
resolve: {
extensions: ['.tsx', '.ts', '.js']
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist')
}
};
// Unpatch when done
unpatch();
ttypescript is a fork of the TypeScript compiler that allows you to use custom transformers directly in your tsconfig.json. It is similar to ts-patch in that it enables advanced TypeScript features, but it requires you to use a different compiler binary.
babel-plugin-transform-typescript-metadata is a Babel plugin that adds support for TypeScript metadata reflection. While it doesn't patch the TypeScript compiler, it provides similar functionality by enabling advanced TypeScript features through Babel.
typescript-transform-paths is a TypeScript transformer that rewrites module paths based on the paths specified in tsconfig.json. It is similar to ts-patch in that it allows for custom transformations, but it focuses specifically on module path rewriting.
Patch typescript to allow custom transformers (plugins) during build.
Plugins are specified in tsconfig.json
, or provided programmatically in CompilerOptions
.
Migrating from ttypescript is easy! See: Method 1: Live Compiler
ts-patch /?
)Program
(see: Transforming Program)<yarn|npm|pnpm> add -D ts-patch
The live compiler patches on-the-fly, each time it is run.
Via commandline: Simply use tspc
(instead of tsc
)
With tools such as ts-node, webpack, ts-jest, etc: specify the compiler as ts-patch/compiler
Persistent patch modifies the typescript installation within the node_modules path. It requires additional configuration to remain persisted, but it carries less load time and complexity compared to the live compiler.
# For advanced options, see: ts-patch /?
ts-patch install
prepare
script (keeps patch persisted after npm install)package.json
{
/* ... */
"scripts": {
"prepare": "ts-patch install -s"
}
}
tsconfig.json: Add transformers to compilerOptions
in plugins
array.
Examples
{
"compilerOptions": {
"plugins": [
// Source Transformers
{ "transform": "transformer-module" },
{ "transform": "transformer2", "extraOption": 123 },
{ "transform": "trans-with-mapping", "resolvePathAliases": true },
{ "transform": "esm-transformer", "isEsm": true },
// Program Transformer
{ "transform": "transformer-module5", "transformProgram": true }
]
}
}
Option | Type | Description |
---|---|---|
transform | string | Module name or path to transformer (*.ts or *.js) |
after | boolean | Apply transformer after stock TS transformers |
afterDeclarations | boolean | Apply transformer to declaration (*.d.ts) files |
transformProgram | boolean | Transform Program during ts.createProgram() (see: Program Transformers) |
isEsm | boolean | Transformer is ES Module (note: experimental — requires esm) |
resolvePathAliases | boolean | Resolve path aliases in transformer (requires tsconfig-paths) |
type | string | See: Source Transformer Entry Point (default: 'program') |
import | string | Name of exported transformer function (defaults to default export) |
tsConfig | string | tsconfig.json file for transformer (allows specifying compileOptions, path mapping support, etc) |
... | Provide your own custom options, which will be passed to the transformer |
Note: Required options are bold
For an overview of the typescript compiler (such as what a SourceFile
and Program
is) see: Typescript Compiler Notes.
Source Transformers will transform the AST of SourceFiles during compilation, allowing you to alter the output of the JS or declarations files.
(program: ts.Program, config: PluginConfig, extras: TransformerExtras) => ts.TransformerFactory
PluginConfig: Type Declaration
TransformerExtras: Type Declaration
ts.TransformerFactory: (context: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile
Note: Additional legacy signatures are supported, but it is not recommended to develop a new transformer using them.
Transformers can be written in JS or TS.
import type * as ts from 'typescript';
import type { TransformerExtras, PluginConfig } from 'ts-patch';
/** Changes string literal 'before' to 'after' */
export default function (program: ts.Program, pluginConfig: PluginConfig, { ts: tsInstance }: TransformerExtras) {
return (ctx: ts.TransformationContext) => {
const { factory } = ctx;
return (sourceFile: ts.SourceFile) => {
function visit(node: ts.Node): ts.Node {
if (tsInstance.isStringLiteral(node) && node.text === 'before') {
return factory.createStringLiteral('after');
}
return tsInstance.visitEachChild(node, visit, ctx);
}
return tsInstance.visitNode(sourceFile, visit);
};
};
}
Live Examples:
{ transform: "typescript-transform-paths" }
{ transform: "typescript-is/lib/transform-inline/transformer" }
{ transform: "typia/lib/transform" }
(💻playground)
{ transform: "@nestia/core/lib/transform" }
Diagnostics can be altered in a Source Transformer.
To alter diagnostics you can use the following, provided from the TransformerExtras
parameter:
property | description |
---|---|
diagnostics | Reference to Diagnostic array |
addDiagnostic() | Safely add Diagnostic to diagnostics array |
removeDiagnostic() | Safely remove Diagnostic from diagnostics array |
This alters diagnostics during emit only. If you want to alter diagnostics in your IDE as well, you'll need to create a LanguageService plugin to accompany your source transformer
Sometimes you want to do more than just transform source code. For example you may want to:
For this, we've introduced what we call a Program Transformer. The transform action takes place during ts.createProgram
, and allows
re-creating the Program
instance that typescript uses.
(program: ts.Program, host: ts.CompilerHost | undefined, options: PluginConfig, extras: ProgramTransformerExtras) => ts.Program
ProgramTransformerExtras >>> Type Declaration
To configure a Program Transformer, supply "transformProgram": true
in the config transformer entry.
Note: The before
, after
, and afterDeclarations
options do not apply to a Program Transformer and will be ignored
/**
* Add a file to Program
*/
import * as path from 'path';
import type * as ts from 'typescript';
import type { ProgramTransformerExtras, PluginConfig } from 'ts-patch';
export const newFile = path.resolve(__dirname, 'added-file.ts');
export default function (
program: ts.Program,
host: ts.CompilerHost | undefined,
options: PluginConfig,
{ ts: tsInstance }: ProgramTransformerExtras
) {
return tsInstance.createProgram(
/* rootNames */ program.getRootFileNames().concat([ newFile ]),
program.getCompilerOptions(),
host,
/* oldProgram */ program
);
}
Note: For a more complete example, see Transforming Program with additional AST transformations
Live Examples:
{ transform: "@typescript-virtual-barrel/compiler-plugin", transformProgram: true }
{ transform: "ts-overrides-plugin", transformProgram: true }
The plugin package configuration allows you to specify custom options for your TypeScript plugin.
This configuration is defined in the package.json
of your plugin under the tsp
property.
An example use case is enabling parseAllJsDoc
if you require full JSDoc parsing in tsc for your transformer in TS v5.3+. (see: 5.3 JSDoc parsing changes)
For all available options, see the PluginPackageConfig
type in plugin-types.ts
{
"name": "your-plugin-name",
"version": "1.0.0",
"tsp": {
"tscOptions": {
"parseAllJsDoc": true
}
}
}
Tool | Type | Description |
---|---|---|
TS AST Viewer | Web App | Allows you to see the Node structure and other TS properties of your source code. |
ts-expose-internals | NPM Package | Exposes internal types and methods of the TS compiler API |
#compiler-internals-and-api
on TypeScript Discord Server(env) TSP_SKIP_CACHE
Skips patch cache when patching via cli or live compiler.
(env) TSP_COMPILER_TS_PATH
Specify typescript library path to use for ts-patch/compiler
(defaults to require.resolve('typescript')
)
(env) TSP_CACHE_DIR
Override patch cache directory
(cli) ts-patch clear-cache
Cleans patch cache & lockfiles
Ron S. |
If you're interested in helping and are knowledgeable with the TS compiler codebase, feel free to reach out!
This project is licensed under the MIT License, as described in LICENSE.md
FAQs
Patch typescript to support custom transformers in tsconfig.json
The npm package ts-patch receives a total of 195,863 weekly downloads. As such, ts-patch popularity was classified as popular.
We found that ts-patch demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.