{"id":13847271,"url":"https://github.com/nonara/ts-patch","last_synced_at":"2025-05-14T00:04:53.629Z","repository":{"id":42826113,"uuid":"206664157","full_name":"nonara/ts-patch","owner":"nonara","description":"Augment the TypeScript compiler to support extended functionality","archived":false,"fork":false,"pushed_at":"2024-12-05T00:00:38.000Z","size":993,"stargazers_count":842,"open_issues_count":23,"forks_count":26,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-05-06T22:05:37.488Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nonara.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":["nonara"]}},"created_at":"2019-09-05T21:58:34.000Z","updated_at":"2025-05-06T06:03:35.000Z","dependencies_parsed_at":"2024-06-03T23:10:48.189Z","dependency_job_id":"9ef34df8-99b7-47d8-bb58-0e9b2840d91e","html_url":"https://github.com/nonara/ts-patch","commit_stats":null,"previous_names":[],"tags_count":44,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonara%2Fts-patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonara%2Fts-patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonara%2Fts-patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nonara%2Fts-patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nonara","download_url":"https://codeload.github.com/nonara/ts-patch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252982994,"owners_count":21835680,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-04T18:01:15.203Z","updated_at":"2025-05-14T00:04:53.569Z","avatar_url":"https://github.com/nonara.png","language":"TypeScript","readme":"[![npm version](https://badge.fury.io/js/ts-patch.svg)](https://badge.fury.io/js/ts-patch)\n[![NPM Downloads](https://img.shields.io/npm/dm/ts-patch.svg?style=flat)](https://npmjs.org/package/ts-patch)\n![Build Status](https://github.com/nonara/ts-patch/workflows/Build/badge.svg)\n\n# ts-patch\n\nPatch typescript to allow custom transformers (plugins) during build.\n\nPlugins are specified in `tsconfig.json`, or provided programmatically in `CompilerOptions`.\n\n_Migrating from ttypescript is easy! See: [Method 1: Live Compiler](#method-1-live-compiler)_\n\n## Features\n\n* Patch typescript installation via on-the-fly, in-memory patching _or_ as a persistent patch\n* Can patch individual libraries (see `ts-patch /?`)\n* Hook build process by transforming the `Program` (see: [Transforming Program](#transforming-program))\n* Add, remove, or modify diagnostics (see: [Altering Diagnostics](#altering-diagnostics))\n* Fully compatible with legacy [ttypescript](https://github.com/cevek/ttypescript) projects\n* **(new)** Experimental support for ES Module based transformers\n\n# Table of Contents\n\n\u003c!-- TOC --\u003e\n* [ts-patch](#ts-patch)\n  * [Features](#features)\n* [Table of Contents](#table-of-contents)\n* [Installation](#installation)\n* [Usage](#usage)\n  * [Method 1: Live Compiler](#method-1-live-compiler)\n  * [Method 2: Persistent Patch](#method-2-persistent-patch)\n* [Configuration](#configuration)\n  * [Plugin Options](#plugin-options)\n* [Writing Transformers](#writing-transformers)\n  * [Source Transformers](#source-transformers)\n    * [Source Transformer Entry Point](#source-transformer-entry-point)\n    * [Source Transformer Example](#source-transformer-example)\n    * [Altering Diagnostics](#altering-diagnostics)\n    * [Note](#note)\n  * [Program Transformers](#program-transformers)\n    * [Program Transformer Entry Point](#program-transformer-entry-point)\n    * [Configuring Program Transformers](#configuring-program-transformers)\n    * [Program Transformer Example](#program-transformer-example)\n  * [Plugin Package Configuration](#plugin-package-configuration)\n    * [Example](#example)\n  * [Resources](#resources)\n    * [Recommended Reading](#recommended-reading)\n    * [Recommended Tools](#recommended-tools)\n    * [Discussion](#discussion)\n* [Advanced Options](#advanced-options)\n* [Maintainers](#maintainers)\n  * [Help Wanted](#help-wanted)\n* [License](#license)\n\u003c!-- TOC --\u003e\n\n# Installation\n\n1. Install package\n```sh\n\u003cyarn|npm|pnpm\u003e add -D ts-patch\n```\n\n# Usage\n\n## Method 1: Live Compiler\n\nThe live compiler patches on-the-fly, each time it is run.\n\n**Via commandline:** Simply use `tspc` (instead of `tsc`)\n\n**With tools such as ts-node, webpack, ts-jest, etc:** specify the compiler as  `ts-patch/compiler`\n\n## Method 2: Persistent Patch\n\nPersistent patch modifies the typescript installation within the node_modules path. It requires additional configuration\nto remain persisted, but it carries less load time and complexity compared to the live compiler.\n\n1. Install the patch\n\n```shell\n# For advanced options, see: ts-patch /?\nts-patch install\n```\n\n2. Add `prepare` script (keeps patch persisted after npm install)\n\n`package.json`\n ```jsonc\n{\n  /* ... */\n  \"scripts\": {\n    \"prepare\": \"ts-patch install -s\"\n  }\n}\n ```\n\n# Configuration\n\n**tsconfig.json**: Add transformers to `compilerOptions` in `plugins` array.\n\n**Examples**\n```jsonc\n{\n    \"compilerOptions\": {\n        \"plugins\": [\n            // Source Transformers\n            { \"transform\": \"transformer-module\" },\n            { \"transform\": \"transformer2\", \"extraOption\": 123 },\n            { \"transform\": \"trans-with-mapping\", \"resolvePathAliases\": true },\n            { \"transform\": \"esm-transformer\", \"isEsm\": true },\n\n            // Program Transformer\n            { \"transform\": \"transformer-module5\", \"transformProgram\": true }\n        ]\n    }\n}\n```\n\n## Plugin Options\n\n| Option             | Type    | Description                                                                                                   |\n|--------------------|---------|:--------------------------------------------------------------------------------------------------------------|\n| **transform**      | string  | Module name or path to transformer _(*.ts or *.js)_                                                           |\n| after              | boolean | Apply transformer after stock TS transformers                                                                 |\n| afterDeclarations  | boolean | Apply transformer to declaration (*.d.ts) files                                                               |\n| transformProgram   | boolean | Transform `Program` during `ts.createProgram()` _(see: [Program Transformers](#program-transformers))_        |\n| isEsm              | boolean | Transformer is ES Module (_note: experimental_ — requires [esm](https://www.npmjs.com/package/esm))           |\n| resolvePathAliases | boolean | Resolve path aliases in transformer (requires [tsconfig-paths](https://www.npmjs.com/package/tsconfig-paths)) |\n| type               | string  | See: [Source Transformer Entry Point](#source-transformer-entry-point) (default: 'program')                   |\n| import             | string  | Name of exported transformer function _(defaults to `default` export)_                                        |\n| tsConfig           | string  | tsconfig.json file _for transformer_ (allows specifying compileOptions, path mapping support, etc)            |\n| _..._              |         | Provide your own custom options, which will be passed to the transformer                                      |\n\n_Note: Required options are bold_\n\n# Writing Transformers\n\nFor an overview of the typescript compiler (such as what a `SourceFile` and `Program` is) see: [Typescript Compiler Notes](https://github.com/microsoft/TypeScript-Compiler-Notes).\n\n## Source Transformers\n\nSource Transformers will transform the AST of SourceFiles during compilation, allowing you to alter the output of the JS or declarations files.\n\n### Source Transformer Entry Point\n\n```ts\n(program: ts.Program, config: PluginConfig, extras: TransformerExtras) =\u003e ts.TransformerFactory\n```\n\n**PluginConfig**: [Type Declaration](https://github.com/nonara/ts-patch/blob/master/projects/core/shared/plugin-types.ts)  \n**TransformerExtras**: [Type Declaration](https://github.com/nonara/ts-patch/blob/master/projects/core/shared/plugin-types.ts)  \n**ts.TransformerFactory**: `(context: ts.TransformationContext) =\u003e (sourceFile: ts.SourceFile) =\u003e ts.SourceFile`\n\n_Note: Additional [legacy signatures](https://github.com/cevek/ttypescript#pluginconfigtype) are supported, but it is not recommended to develop a new transformer using them._\n\n### Source Transformer Example\n\nTransformers can be written in JS or TS.\n\n```ts\nimport type * as ts from 'typescript';\nimport type { TransformerExtras, PluginConfig } from 'ts-patch';\n\n/** Changes string literal 'before' to 'after' */\nexport default function (program: ts.Program, pluginConfig: PluginConfig, { ts: tsInstance }: TransformerExtras) {\n  return (ctx: ts.TransformationContext) =\u003e {\n    const { factory } = ctx;\n    \n    return (sourceFile: ts.SourceFile) =\u003e {\n      function visit(node: ts.Node): ts.Node {\n        if (tsInstance.isStringLiteral(node) \u0026\u0026 node.text === 'before') {\n          return factory.createStringLiteral('after');\n        }\n        return tsInstance.visitEachChild(node, visit, ctx);\n      }\n      return tsInstance.visitNode(sourceFile, visit);\n    };\n  };\n}\n\n```\n\n**Live Examples**:\n\n[`{ transform: \"typescript-transform-paths\" }`](https://github.com/LeDDGroup/typescript-transform-paths)\n\n[`{ transform: \"typescript-is/lib/transform-inline/transformer\" }`](https://github.com/woutervh-/typescript-is)\n\n[`{ transform: \"typia/lib/transform\" }`](https://github.com/samchon/typia) ([💻playground](https://typia.io/playground))\n\n[`{ transform: \"@nestia/core/lib/transform\" }`](https://github.com/samchon/nestia)\n\n### Altering Diagnostics\n\nDiagnostics can be altered in a Source Transformer.\n\nTo alter diagnostics you can use the following, provided from the `TransformerExtras` parameter:\n\n| property           | description                                         |\n|--------------------|-----------------------------------------------------|\n| diagnostics        | Reference to `Diagnostic` array                     |   \n| addDiagnostic()    | Safely add `Diagnostic` to `diagnostics` array      |\n| removeDiagnostic() | Safely remove `Diagnostic` from `diagnostics` array | \n\n### Note\n\n_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_\n\n## Program Transformers\n\nSometimes you want to do more than just transform source code. For example you may want to:\n\n- TypeCheck code after it's been transformed\n- Generate code and add it to the program\n- Add or remove emit files during transformation\n\nFor this, we've introduced what we call a Program Transformer. The transform action takes place during `ts.createProgram`, and allows\nre-creating the `Program` instance that typescript uses.\n\n### Program Transformer Entry Point\n\n```ts\n(program: ts.Program, host: ts.CompilerHost | undefined, options: PluginConfig, extras: ProgramTransformerExtras) =\u003e ts.Program\n```\n\n**ProgramTransformerExtras** \u003e\u003e\u003e [Type Declaration](https://github.com/nonara/ts-patch/blob/master/projects/core/shared/plugin-types.ts)\n\n### Configuring Program Transformers\n\nTo configure a Program Transformer, supply `\"transformProgram\": true` in the config transformer entry.\n\n_Note: The `before`, `after`, and `afterDeclarations` options do not apply to a Program Transformer and will be ignored_\n\n[See Config Example](#configuration)\n\n### Program Transformer Example\n```TypeScript\n/** \n * Add a file to Program\n */\nimport * as path from 'path';\nimport type * as ts from 'typescript';\nimport type { ProgramTransformerExtras, PluginConfig } from 'ts-patch';\n\nexport const newFile = path.resolve(__dirname, 'added-file.ts');\n\nexport default function (\n  program: ts.Program, \n  host: ts.CompilerHost | undefined, \n  options: PluginConfig, \n  { ts: tsInstance }: ProgramTransformerExtras\n) {\n  return tsInstance.createProgram(\n    /* rootNames */ program.getRootFileNames().concat([ newFile ]),\n    program.getCompilerOptions(),\n    host,\n    /* oldProgram */ program\n  );\n}\n```\n\n**Note:** For a more complete example, see [Transforming Program with additional AST transformations](https://github.com/nonara/ts-patch/discussions/29#discussioncomment-325979)\n\n**Live Examples**:\n\n[`{ transform: \"@typescript-virtual-barrel/compiler-plugin\", transformProgram: true }`](https://github.com/zaguiini/typescript-virtual-barrel)\n\n[`{ transform: \"ts-overrides-plugin\", transformProgram: true }`](https://github.com/DiFuks/ts-overrides-plugin)\n\n## Plugin Package Configuration\n\nThe plugin package configuration allows you to specify custom options for your TypeScript plugin. \nThis configuration is defined in the `package.json` of your plugin under the `tsp` property.\n\nAn 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](https://devblogs.microsoft.com/typescript/announcing-typescript-5-3/#optimizations-by-skipping-jsdoc-parsing))\n\nFor all available options, see the `PluginPackageConfig` type in [plugin-types.ts](https://github.com/nonara/ts-patch/blob/master/projects/core/shared/plugin-types.ts)\n\n### Example\n\n```jsonc\n{\n  \"name\": \"your-plugin-name\",\n  \"version\": \"1.0.0\",\n  \"tsp\": {\n    \"tscOptions\": {\n      \"parseAllJsDoc\": true\n    }\n  }\n}\n```\n\n## Resources\n\n### Recommended Reading\n\n- How-To: [Advice for working with the TS Compiler API](https://github.com/nonara/ts-patch/discussions/31)\n- How-To: [TypeScript Transformer Handbook](https://github.com/madou/typescript-transformer-handbook)\n- Article: [How to Write a TypeScript Transform (Plugin)](https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943)\n- Article: [Creating a TypeScript Transformer](https://43081j.com/2018/08/creating-a-typescript-transform?source=post_page-----731e2b0b66e6----------------------)\n\n### Recommended Tools\n\n| Tool                                                                 | Type        | Description                                                                                 |\n|----------------------------------------------------------------------|-------------|---------------------------------------------------------------------------------------------|\n| [TS AST Viewer](https://ts-ast-viewer.com/)                          | Web App     | Allows you to see the `Node` structure and other TS properties of your source code.         |\n| [ts-expose-internals](https://github.com/nonara/ts-expose-internals) | NPM Package | Exposes internal types and methods of the TS compiler API                                   |\n\n### Discussion\n\n- `#compiler-internals-and-api` on [TypeScript Discord Server](https://discord.com/invite/typescript)\n- TSP [Discussions](https://github.com/nonara/ts-patch/discussions) Board\n\n# Advanced Options\n\n**(env) `TSP_SKIP_CACHE`**\n\nSkips patch cache when patching via cli or live compiler.\n\n**(env) `TSP_COMPILER_TS_PATH`**\n\nSpecify typescript library path to use for `ts-patch/compiler` (defaults to `require.resolve('typescript')`)\n\n**(env) `TSP_CACHE_DIR`**\n\nOverride patch cache directory\n\n**(cli) `ts-patch clear-cache`**\n\nCleans patch cache \u0026 lockfiles\n\n# Maintainers\n\n\u003c!-- prettier-ignore-start --\u003e\n\u003c!-- markdownlint-disable --\u003e\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003ctd align=\"center\"\u003e\u003ca href=\"https://github.com/nonara\"\u003e\u003cimg src=\"https://avatars0.githubusercontent.com/u/1427565?v=4\" width=\"100px;\" alt=\"\"/\u003e\u003cbr /\u003e\u003csub\u003e\u003cb\u003eRon S.\u003c/b\u003e\u003c/sub\u003e\u003c/a\u003e\u003c/td\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n## Help Wanted\n\nIf you're interested in helping and are knowledgeable with the TS compiler codebase, feel free to reach out!\n\n# License\n\nThis project is licensed under the MIT License, as described in `LICENSE.md`\n","funding_links":["https://github.com/sponsors/nonara"],"categories":["TypeScript","Packages"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonara%2Fts-patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnonara%2Fts-patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnonara%2Fts-patch/lists"}