{"id":16117932,"url":"https://github.com/wessberg/ts-clone-node","last_synced_at":"2025-04-17T12:29:57.685Z","repository":{"id":53740145,"uuid":"220643928","full_name":"wessberg/ts-clone-node","owner":"wessberg","description":"A library that helps you clone Nodes from a Typescript AST","archived":false,"fork":false,"pushed_at":"2024-09-25T13:09:36.000Z","size":1669,"stargazers_count":35,"open_issues_count":5,"forks_count":6,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-29T06:04:47.841Z","etag":null,"topics":["ast","clone","copy","duplicate","node","typescript"],"latest_commit_sha":null,"homepage":null,"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/wessberg.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":"wessberg","patreon":"wessberg"}},"created_at":"2019-11-09T13:10:03.000Z","updated_at":"2024-10-13T07:22:29.000Z","dependencies_parsed_at":"2024-06-18T15:23:07.014Z","dependency_job_id":"b4cca274-fdd1-47bc-a0f9-50a49c13b2aa","html_url":"https://github.com/wessberg/ts-clone-node","commit_stats":null,"previous_names":[],"tags_count":46,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wessberg%2Fts-clone-node","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wessberg%2Fts-clone-node/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wessberg%2Fts-clone-node/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wessberg%2Fts-clone-node/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wessberg","download_url":"https://codeload.github.com/wessberg/ts-clone-node/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249341758,"owners_count":21254189,"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":["ast","clone","copy","duplicate","node","typescript"],"created_at":"2024-10-09T20:47:49.976Z","updated_at":"2025-04-17T12:29:57.661Z","avatar_url":"https://github.com/wessberg.png","language":"TypeScript","funding_links":["https://github.com/sponsors/wessberg","https://patreon.com/wessberg","https://www.patreon.com/bePatron?u=11315442"],"categories":[],"sub_categories":[],"readme":"\u003c!-- SHADOW_SECTION_LOGO_START --\u003e\n\n\u003cdiv\u003e\u003cimg alt=\"Logo\" src=\"https://raw.githubusercontent.com/wessberg/ts-clone-node/master/documentation/asset/logo.png\" height=\"100\"   /\u003e\u003c/div\u003e\n\n\u003c!-- SHADOW_SECTION_LOGO_END --\u003e\n\n\u003c!-- SHADOW_SECTION_DESCRIPTION_SHORT_START --\u003e\n\n\u003e A library that helps you clone Nodes from a Typescript AST\n\n\u003c!-- SHADOW_SECTION_DESCRIPTION_SHORT_END --\u003e\n\n\u003c!-- SHADOW_SECTION_BADGES_START --\u003e\n\n\u003ca href=\"https://npmcharts.com/compare/ts-clone-node?minimal=true\"\u003e\u003cimg alt=\"Downloads per month\" src=\"https://img.shields.io/npm/dm/ts-clone-node.svg\"    /\u003e\u003c/a\u003e\n\u003ca href=\"https://www.npmjs.com/package/ts-clone-node\"\u003e\u003cimg alt=\"NPM version\" src=\"https://badge.fury.io/js/ts-clone-node.svg\"    /\u003e\u003c/a\u003e\n\u003cimg alt=\"Dependencies\" src=\"https://img.shields.io/librariesio/github/wessberg%2Fts-clone-node.svg\"    /\u003e\n\u003ca href=\"https://github.com/wessberg/ts-clone-node/graphs/contributors\"\u003e\u003cimg alt=\"Contributors\" src=\"https://img.shields.io/github/contributors/wessberg%2Fts-clone-node.svg\"    /\u003e\u003c/a\u003e\n\u003ca href=\"https://github.com/prettier/prettier\"\u003e\u003cimg alt=\"code style: prettier\" src=\"https://img.shields.io/badge/code_style-prettier-ff69b4.svg\"    /\u003e\u003c/a\u003e\n\u003ca href=\"https://opensource.org/licenses/MIT\"\u003e\u003cimg alt=\"License: MIT\" src=\"https://img.shields.io/badge/License-MIT-yellow.svg\"    /\u003e\u003c/a\u003e\n\u003ca href=\"https://www.patreon.com/bePatron?u=11315442\"\u003e\u003cimg alt=\"Support on Patreon\" src=\"https://img.shields.io/badge/patreon-donate-green.svg\"    /\u003e\u003c/a\u003e\n\n\u003c!-- SHADOW_SECTION_BADGES_END --\u003e\n\n\u003c!-- SHADOW_SECTION_DESCRIPTION_LONG_START --\u003e\n\n## Description\n\n\u003c!-- SHADOW_SECTION_DESCRIPTION_LONG_END --\u003e\n\nThe Typescript Compiler API is very powerful and comes with a lot of `create` and `update` functions that can be used for creating and updating nodes in [Custom transformers](https://github.com/Microsoft/TypeScript/pull/13940) while visiting\na `SourceFile`. Under such circumstances, it is easy to run into problems if you reuse a Node in another part of the tree without properly cloning it, since the `parent` chain, as well as the `pos` and `end` values will have wrong values and will lead to malformed output after your transformations have been applied.\n\nThis can be cumbersome for example when you want to simply add or remove a specific modifier from an arbitrary node in a given position.\nThis library exports a `cloneNode` function that makes it easy to deep-clone a Node from a Typescript AST without any faulty parent links.\nAdditionally, you get a simple hook with which you can do simple things such as edit the top-level properties of the cloned object such as its modifiers, decorators, etc.\n\n\u003c!-- SHADOW_SECTION_FEATURES_START --\u003e\n\n### Features\n\n\u003c!-- SHADOW_SECTION_FEATURES_END --\u003e\n\n- Simple to use\n- Extensible\n- Supports dynamic TypeScript versions\n\n\u003c!-- SHADOW_SECTION_FEATURE_IMAGE_START --\u003e\n\n\u003c!-- SHADOW_SECTION_FEATURE_IMAGE_END --\u003e\n\n\u003c!-- SHADOW_SECTION_BACKERS_START --\u003e\n\n## Backers\n\n### Patreon\n\n\u003ca href=\"https://www.patreon.com/bePatron?u=11315442\"\u003e\u003cimg alt=\"Patrons on Patreon\" src=\"https://img.shields.io/endpoint.svg?url=https%3A%2F%2Fshieldsio-patreon.vercel.app%2Fapi%3Fusername%3Dwessberg%26type%3Dpatrons\"  width=\"200\"  /\u003e\u003c/a\u003e\n\n\u003c!-- SHADOW_SECTION_BACKERS_END --\u003e\n\n\u003c!-- SHADOW_SECTION_TOC_START --\u003e\n\n## Table of Contents\n\n- [Description](#description)\n  - [Features](#features)\n- [Backers](#backers)\n  - [Patreon](#patreon)\n- [Table of Contents](#table-of-contents)\n- [Install](#install)\n  - [npm](#npm)\n  - [Yarn](#yarn)\n  - [pnpm](#pnpm)\n  - [Peer Dependencies](#peer-dependencies)\n- [Usage](#usage)\n- [Configuration](#configuration)\n  - [Hooking into and altering transformations](#hooking-into-and-altering-transformations)\n  - [Passing in a specific TypeScript version](#passing-in-a-specific-typescript-version)\n  - [Passing in a specific NodeFactory](#passing-in-a-specific-nodefactory)\n  - [Setting parent pointers](#setting-parent-pointers)\n  - [Setting original node pointers](#setting-original-node-pointers)\n  - [Preserving comments](#preserving-comments)\n  - [Preserving symbols](#preserving-symbols)\n- [Contributing](#contributing)\n- [Maintainers](#maintainers)\n- [FAQ](#faq)\n  - [What is the point of this library](#what-is-the-point-of-this-library)\n- [License](#license)\n\n\u003c!-- SHADOW_SECTION_TOC_END --\u003e\n\n\u003c!-- SHADOW_SECTION_INSTALL_START --\u003e\n\n## Install\n\n### npm\n\n```\n$ npm install ts-clone-node\n```\n\n### Yarn\n\n```\n$ yarn add ts-clone-node\n```\n\n### pnpm\n\n```\n$ pnpm add ts-clone-node\n```\n\n### Peer Dependencies\n\n`ts-clone-node` depends on `typescript`, so you need to manually install this as well.\n\n\u003c!-- SHADOW_SECTION_INSTALL_END --\u003e\n\n\u003c!-- SHADOW_SECTION_USAGE_START --\u003e\n\n## Usage\n\n\u003c!-- SHADOW_SECTION_USAGE_END --\u003e\n\nTo clone a Node from a Typescript AST, all you have to do is:\n\n```typescript\nimport {cloneNode} from \"ts-clone-node\";\n\n// Clone the Node\nconst clonedNode = cloneNode(someNode);\n```\n\n## Configuration\n\n### Hooking into and altering transformations\n\nYou can pass in a hook that enables you to modify the clone, agnostic to the kind of Node it is.\nFor example:\n\n```typescript\nimport {cloneNode} from \"ts-clone-node\";\n\n// Clone the Node, and alter the modifiers such that they don't include a modifier pointing\n// to the 'declare' keyword\nconst clonedNode = cloneNode(someNode, {\n\thook: node =\u003e {\n\t\treturn {\n\t\t\tmodifiers: modifiers =\u003e ensureNoDeclareModifier(modifiers)\n\t\t};\n\t}\n});\n```\n\nThere is also a _'finalize'_ which is invoked after a node has been cloned at any recursive step from the top node, allowing you to perform\nfinal alterations or track the node for other purposes.\n\n```typescript\nconst clonedNode = cloneNode(someNode, {\n\tfinalize: (clonedNode, oldNode) =\u003e trackSomething(clonedNode, oldNode)\n});\n```\n\n### Passing in a specific TypeScript version\n\nYou can use pass a specific TypeScript to use as an option to `cloneNode`:\n\n```typescript\ncloneNode(someNode, {\n\ttypescript: specialTypescriptVersion\n});\n```\n\nThis can be useful, for example, in an environment where multiple packages in the same project depends\non different TypeScript versions and you're relying on `cloneNode`.\n\n### Passing in a specific NodeFactory\n\nFrom TypeScript v4 and forward, a `NodeFactory` can be retrieved from a `TransformationContext` to signal which transformer was responsible for creating or altering nodes. If you want to pass a specific `NodeFactory`, you can pass it as an option to `cloneNode`:\n\n```typescript\ncloneNode(someNode, {\n\tfactory: nodeFactoryFromTransformationContext\n});\n```\n\n### Setting parent pointers\n\nBy default, when you clone a node, it won't update the parent pointers such that you and TypeScripts compiler APIs can traverse the parent tree.\nYou can toggle this behavior with the `setParents` option:\n\n```typescript\ncloneNode(someNode, {\n\tsetParents: true\n});\n```\n\n### Setting original node pointers\n\nBy default, when you clone a node, it won't keep references to the original nodes recursively.\nYou can toggle this behavior with the `setOriginalNodes` option:\n\n```typescript\ncloneNode(someNode, {\n\tsetOriginalNodes: true\n});\n```\n\n### Preserving comments\n\nBy default, when you clone a node, comments will be preserved as much as possible and added to the cloned nodes as `emitNodes`.\nYou can toggle this behavior with the `preserveComments` option:\n\n```typescript\ncloneNode(someNode, {\n\tpreserveComments: false\n});\n```\n\n### Preserving symbols\n\nBy default, when you clone a node, it won't preserve symbols from the original nodes.\nYou can toggle this behavior with the `preserveSymbols` option:\n\n```typescript\ncloneNode(someNode, {\n\tpreserveSymbols: true\n});\n```\n\n\u003c!-- SHADOW_SECTION_CONTRIBUTING_START --\u003e\n\n## Contributing\n\nDo you want to contribute? Awesome! Please follow [these recommendations](./CONTRIBUTING.md).\n\n\u003c!-- SHADOW_SECTION_CONTRIBUTING_END --\u003e\n\n\u003c!-- SHADOW_SECTION_MAINTAINERS_START --\u003e\n\n## Maintainers\n\n| \u003ca href=\"mailto:frederikwessberg@hotmail.com\"\u003e\u003cimg alt=\"Frederik Wessberg\" src=\"https://avatars2.githubusercontent.com/u/20454213?s=460\u0026v=4\" height=\"70\"   /\u003e\u003c/a\u003e                                                                |\n| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [Frederik Wessberg](mailto:frederikwessberg@hotmail.com)\u003cbr\u003e\u003cstrong\u003eTwitter\u003c/strong\u003e: [@FredWessberg](https://twitter.com/FredWessberg)\u003cbr\u003e\u003cstrong\u003eGithub\u003c/strong\u003e: [@wessberg](https://github.com/wessberg)\u003cbr\u003e_Lead Developer_ |\n\n\u003c!-- SHADOW_SECTION_MAINTAINERS_END --\u003e\n\n\u003c!-- SHADOW_SECTION_FAQ_START --\u003e\n\n## FAQ\n\n\u003c!-- SHADOW_SECTION_FAQ_END --\u003e\n\n### What is the point of this library\n\nIf you've run into the kind of trouble I'm explaining here, you'll understand. If not, I'm happy for you. You can move along!\n\n\u003c!-- SHADOW_SECTION_LICENSE_START --\u003e\n\n## License\n\nMIT © [Frederik Wessberg](mailto:frederikwessberg@hotmail.com) ([@FredWessberg](https://twitter.com/FredWessberg)) ([Website](https://github.com/wessberg))\n\n\u003c!-- SHADOW_SECTION_LICENSE_END --\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwessberg%2Fts-clone-node","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwessberg%2Fts-clone-node","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwessberg%2Fts-clone-node/lists"}