codemod 1.0.18 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -1085
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -1,1170 +1,264 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<a href="https://codemod.com">
|
|
3
|
+
<picture>
|
|
4
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/codemod/codemod/main/apps/docs/images/intro/codemod-docs-hero-dark.jpg">
|
|
5
|
+
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/codemod/codemod/main/apps/docs/images/intro/codemod-docs-hero-light.jpg">
|
|
6
|
+
<img alt="Codemod CLI" src="https://raw.githubusercontent.com/codemod/codemod/main/apps/docs/images/intro/codemod-docs-hero-light.jpg">
|
|
7
|
+
</picture>
|
|
8
|
+
</a>
|
|
9
|
+
|
|
10
|
+
<p align="center">
|
|
11
|
+
<br />
|
|
12
|
+
<a href="https://go.codemod.com/app">Platform</a>
|
|
13
|
+
·
|
|
14
|
+
<a href="https://go.codemod.com/community">Community</a>
|
|
15
|
+
·
|
|
16
|
+
<a href="https://docs.codemod.com">Docs</a>
|
|
17
|
+
</p>
|
|
18
|
+
</p>
|
|
19
|
+
|
|
1
20
|
# Codemod CLI
|
|
2
21
|
|
|
3
|
-
|
|
22
|
+
[](https://go.codemod.com/community)
|
|
23
|
+
[](https://github.com/codemod/codemod/blob/main/LICENSE)
|
|
24
|
+
[](https://www.npmjs.com/package/codemod)
|
|
4
25
|
|
|
5
|
-
|
|
6
|
-
> For more information read the [blog post announcing the CLI](https://codemod.com/blog/new-codemod-cli).
|
|
7
|
-
> And any feedback is welcome!
|
|
26
|
+
**Codemod CLI** is an open-source command-line tool for building, testing, and running **codemod packages**—automated code transformations that help teams modernize codebases, upgrade frameworks, and refactor at scale.
|
|
8
27
|
|
|
9
|
-
|
|
28
|
+
Whether you're an individual developer tackling tech debt, an OSS maintainer shipping upgrade paths, or a platform team coordinating migrations across hundreds of services, Codemod CLI gives you the tools to automate repetitive code changes reliably.
|
|
10
29
|
|
|
11
|
-
|
|
30
|
+
## Installation
|
|
12
31
|
|
|
13
32
|
```bash
|
|
14
|
-
|
|
15
|
-
git clone https://github.com/codemod-com/codemod.git
|
|
16
|
-
cd codemod
|
|
17
|
-
|
|
18
|
-
# Build the project
|
|
19
|
-
cargo build --release
|
|
20
|
-
|
|
21
|
-
# The executable will be available at target/release/codemod
|
|
33
|
+
npm install -g codemod@latest
|
|
22
34
|
```
|
|
23
35
|
|
|
24
|
-
|
|
36
|
+
Or use via `npx` without installation:
|
|
25
37
|
|
|
26
38
|
```bash
|
|
27
|
-
|
|
39
|
+
npx codemod@latest <command>
|
|
28
40
|
```
|
|
29
41
|
|
|
30
42
|
## Quick Start
|
|
31
43
|
|
|
32
|
-
1. Create a workflow file `workflow.yaml`:
|
|
33
|
-
|
|
34
|
-
```yaml
|
|
35
|
-
version: "1"
|
|
36
|
-
nodes:
|
|
37
|
-
- id: hello-world
|
|
38
|
-
name: Hello World
|
|
39
|
-
type: automatic
|
|
40
|
-
runtime:
|
|
41
|
-
type: direct
|
|
42
|
-
steps:
|
|
43
|
-
- id: hello
|
|
44
|
-
name: Say Hello
|
|
45
|
-
run: echo "Hello, World!"
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
2. Run the workflow:
|
|
49
|
-
|
|
50
|
-
```bash
|
|
51
|
-
codemod run -w workflow.yaml
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
## Commands
|
|
55
|
-
|
|
56
|
-
### `codemod init`
|
|
57
|
-
|
|
58
|
-
Initialize a new Butterflow workflow project with interactive setup:
|
|
59
|
-
|
|
60
|
-
```bash
|
|
61
|
-
# Initialize a new project in current directory
|
|
62
|
-
codemod init
|
|
63
|
-
|
|
64
|
-
# Initialize a new project in a specific directory
|
|
65
|
-
codemod init my-project/
|
|
66
|
-
|
|
67
|
-
# Initialize with a specific name
|
|
68
|
-
codemod init --name my-workflow
|
|
69
|
-
```
|
|
70
|
-
|
|
71
|
-
**Options:**
|
|
72
|
-
- `--name <NAME>`: Set the project name (defaults to directory name)
|
|
73
|
-
- `--force`: Overwrite existing files if they exist
|
|
74
|
-
- Positional argument: Target directory path (defaults to current directory)
|
|
75
|
-
|
|
76
|
-
**Interactive Setup:**
|
|
77
|
-
|
|
78
|
-
The init command will prompt you with several questions to customize your project:
|
|
79
|
-
|
|
80
|
-
1. **Project Type Selection:**
|
|
81
|
-
```
|
|
82
|
-
? What type of workflow would you like to create?
|
|
83
|
-
❯ ast-grep with JavaScript/TypeScript rules
|
|
84
|
-
ast-grep with YAML rules
|
|
85
|
-
Blank workflow (custom commands)
|
|
86
|
-
```
|
|
87
|
-
|
|
88
|
-
2. **Language Selection** (if ast-grep is chosen):
|
|
89
|
-
```
|
|
90
|
-
? Which language would you like to target?
|
|
91
|
-
❯ JavaScript/TypeScript
|
|
92
|
-
Python
|
|
93
|
-
Rust
|
|
94
|
-
Go
|
|
95
|
-
Java
|
|
96
|
-
C/C++
|
|
97
|
-
Other
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
3. **Project Configuration:**
|
|
101
|
-
```
|
|
102
|
-
? Project name: my-codemod
|
|
103
|
-
? Description: Converts legacy API calls to new format
|
|
104
|
-
? Author: Your Name <your.email@example.com>
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
**Generated Project Structure:**
|
|
108
|
-
|
|
109
|
-
Depending on your selections, the init command creates different project templates:
|
|
110
|
-
|
|
111
|
-
#### ast-grep JavaScript Project
|
|
112
|
-
```
|
|
113
|
-
my-codemod/
|
|
114
|
-
├── workflow.yaml # Main workflow definition
|
|
115
|
-
├── package.json # Node.js dependencies
|
|
116
|
-
├── rules/
|
|
117
|
-
│ └── example-rule.js # JavaScript AST transformation rules
|
|
118
|
-
├── scripts/
|
|
119
|
-
│ └── apply-codemod.js # Script to apply transformations
|
|
120
|
-
├── tests/
|
|
121
|
-
│ ├── input/ # Test input files
|
|
122
|
-
│ └── expected/ # Expected output files
|
|
123
|
-
└── README.md # Project documentation
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
#### ast-grep YAML Project
|
|
127
|
-
```
|
|
128
|
-
my-codemod/
|
|
129
|
-
├── workflow.yaml # Main workflow definition
|
|
130
|
-
├── rules/
|
|
131
|
-
│ └── example-rule.yml # YAML AST pattern rules
|
|
132
|
-
├── scripts/
|
|
133
|
-
│ └── apply-rules.sh # Shell script to apply rules
|
|
134
|
-
├── tests/
|
|
135
|
-
│ ├── input/ # Test input files
|
|
136
|
-
│ └── expected/ # Expected output files
|
|
137
|
-
└── README.md # Project documentation
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
#### Blank Workflow Project
|
|
141
|
-
```
|
|
142
|
-
my-workflow/
|
|
143
|
-
├── workflow.yaml # Basic workflow template
|
|
144
|
-
├── scripts/
|
|
145
|
-
│ └── example.sh # Example script
|
|
146
|
-
└── README.md # Project documentation
|
|
147
|
-
```
|
|
148
|
-
|
|
149
|
-
**Example Usage:**
|
|
150
|
-
|
|
151
|
-
```bash
|
|
152
|
-
# Create a new ast-grep JavaScript project
|
|
153
|
-
$ codemod init my-js-codemod
|
|
154
|
-
? What type of workflow would you like to create? ast-grep with JavaScript/TypeScript rules
|
|
155
|
-
? Which language would you like to target? JavaScript/TypeScript
|
|
156
|
-
? Project name: my-js-codemod
|
|
157
|
-
? Description: Migrate from React class components to hooks
|
|
158
|
-
? Author: John Doe <john@example.com>
|
|
159
|
-
|
|
160
|
-
✓ Created workflow.yaml
|
|
161
|
-
✓ Created package.json with @ast-grep/cli dependency
|
|
162
|
-
✓ Created rules/migrate-to-hooks.js
|
|
163
|
-
✓ Created scripts/apply-codemod.js
|
|
164
|
-
✓ Created test structure
|
|
165
|
-
✓ Created README.md
|
|
166
|
-
|
|
167
|
-
Next steps:
|
|
168
|
-
cd my-js-codemod
|
|
169
|
-
npm install
|
|
170
|
-
codemod validate -w workflow.yaml
|
|
171
|
-
codemod run -w workflow.yaml
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
### `codemod run`
|
|
175
|
-
|
|
176
|
-
Execute a workflow from various sources:
|
|
177
|
-
|
|
178
44
|
```bash
|
|
179
|
-
#
|
|
180
|
-
codemod
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
# Run from a workflow bundle directory (containing workflow.yaml)
|
|
184
|
-
codemod run ./my-workflow-bundle/
|
|
185
|
-
|
|
186
|
-
# Run from a registry (Conceptual)
|
|
187
|
-
# codemod run my-registry/react-19-codemods:latest
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**Options:**
|
|
191
|
-
- `-w, --workflow <FILE>`: Path to the workflow definition file
|
|
192
|
-
- Positional argument: Path to workflow file or bundle directory
|
|
45
|
+
# 1. Create a codemod package
|
|
46
|
+
npx codemod init my-codemod
|
|
47
|
+
cd my-codemod
|
|
193
48
|
|
|
194
|
-
|
|
49
|
+
# You can create codemod packages with the help of AI using Codemod MCP or Studio
|
|
195
50
|
|
|
196
|
-
|
|
51
|
+
# 2. Run it locally
|
|
52
|
+
npx codemod workflow run -w ./example-codemod -t /abs/path/to/repo
|
|
197
53
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
codemod
|
|
201
|
-
|
|
202
|
-
# Trigger a specific task by UUID
|
|
203
|
-
codemod resume -i <workflow-run-id> -t <task-uuid>
|
|
54
|
+
# 3. Publish to registry
|
|
55
|
+
npx codemod login
|
|
56
|
+
npx codemod publish
|
|
204
57
|
|
|
205
|
-
#
|
|
206
|
-
codemod
|
|
58
|
+
# 4. Run from registry
|
|
59
|
+
npx codemod @your-org/example-codemod
|
|
207
60
|
```
|
|
208
61
|
|
|
209
|
-
|
|
210
|
-
- `-i, --id <UUID>`: Workflow run ID to resume
|
|
211
|
-
- `-t, --task <UUID>`: Specific task UUID to trigger
|
|
212
|
-
- `--trigger-all`: Trigger all tasks in `AwaitingTrigger` state
|
|
62
|
+
## What are Codemod Packages?
|
|
213
63
|
|
|
214
|
-
|
|
64
|
+
**Codemod packages** are portable, reusable code transformation units that can range from simple find-and-replace operations to complex, multi-step migration workflows. Each package includes:
|
|
215
65
|
|
|
216
|
-
|
|
66
|
+
- **Transformation logic** – Written in JavaScript/TypeScript (jssg), YAML ast-grep rules, or shell scripts
|
|
67
|
+
- **Workflow definition** – Orchestrates steps, handles dependencies, and manages execution
|
|
68
|
+
- **Package manifest** – Defines metadata, target languages, and publishing configuration
|
|
217
69
|
|
|
218
|
-
|
|
219
|
-
# Validate a workflow file
|
|
220
|
-
codemod validate -w workflow.yaml
|
|
221
|
-
codemod validate -w path/to/workflow.yaml
|
|
70
|
+
Packages are **fully portable**: run them locally during development, in CI/CD pipelines, or share them via the [Codemod Registry](https://go.codemod.com/registry) for your team or the community.
|
|
222
71
|
|
|
223
|
-
|
|
224
|
-
codemod validate ./my-workflow-bundle/
|
|
225
|
-
```
|
|
72
|
+
## Why Codemod CLI?
|
|
226
73
|
|
|
227
|
-
**
|
|
228
|
-
-
|
|
229
|
-
-
|
|
230
|
-
-
|
|
231
|
-
-
|
|
232
|
-
-
|
|
233
|
-
- Cyclic dependency detection
|
|
234
|
-
- Template reference validation
|
|
235
|
-
- Matrix strategy validation
|
|
236
|
-
- State schema validation
|
|
237
|
-
- Variable reference syntax validation
|
|
238
|
-
|
|
239
|
-
**Example Output:**
|
|
240
|
-
|
|
241
|
-
Valid workflow:
|
|
242
|
-
```bash
|
|
243
|
-
$ codemod validate -w valid-workflow.yaml
|
|
244
|
-
✓ Workflow definition is valid
|
|
245
|
-
Schema validation: Passed
|
|
246
|
-
Node dependencies: Valid (3 nodes, 2 dependency relationships)
|
|
247
|
-
Template references: Valid (2 templates, 3 references)
|
|
248
|
-
Matrix strategies: Valid (1 matrix node)
|
|
249
|
-
State schema: Valid (2 schema definitions)
|
|
250
|
-
```
|
|
74
|
+
- **🎯 Built for Automation** – Scaffold, test, and publish codemod packages from your terminal
|
|
75
|
+
- **📦 Registry Integration** – Share codemods via the [Codemod Registry](https://go.codemod.com/registry) or run community packages instantly
|
|
76
|
+
- **⚡ Powerful Engines** – Leverage ast-grep (YAML + jssg) for fast, accurate AST-based transformations
|
|
77
|
+
- **🤖 AI-Powered Creation** – Use [Codemod MCP](https://go.codemod.com/mcp-docs) in your IDE or [Codemod Studio](https://go.codemod.com/studio-docs) to build codemods with AI assistance
|
|
78
|
+
- **🧪 Built-in Testing** – Validate codemods with snapshot testing before running on production code
|
|
79
|
+
- **🔧 Flexible Runtime** – Run directly on your machine or in Docker/Podman containers
|
|
251
80
|
|
|
252
|
-
|
|
253
|
-
```bash
|
|
254
|
-
$ codemod validate -w invalid-workflow.yaml
|
|
255
|
-
✗ Workflow definition is invalid
|
|
256
|
-
Error at nodes[2].strategy: Matrix strategy requires 'values' or 'from_state' property
|
|
257
|
-
Error at nodes[1].depends_on[0]: Referenced node 'non-existent-node' does not exist
|
|
258
|
-
Error: Cyclic dependency detected: node-a → node-b → node-a
|
|
259
|
-
```
|
|
81
|
+
## Core Concepts
|
|
260
82
|
|
|
261
|
-
###
|
|
83
|
+
### Codemod Packages
|
|
262
84
|
|
|
263
|
-
|
|
85
|
+
A **codemod package** is a directory containing:
|
|
264
86
|
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
87
|
+
- `codemod.yaml` – Package metadata (name, version, description, target languages)
|
|
88
|
+
- `workflow.yaml` – Workflow steps and orchestration logic
|
|
89
|
+
- `scripts/` – JavaScript/TypeScript codemods (jssg)
|
|
90
|
+
- `rules/` – YAML ast-grep rule files
|
|
268
91
|
|
|
269
|
-
|
|
270
|
-
codemod login --registry https://registry.example.com
|
|
92
|
+
Packages can be as simple as a single transformation or as complex as multi-step migration workflows combining JavaScript codemods, YAML rules, shell scripts, and AI-assisted steps.
|
|
271
93
|
|
|
272
|
-
|
|
273
|
-
codemod login --token <your-token>
|
|
94
|
+
[Learn more about codemod packages →](https://docs.codemod.com/cli/packages)
|
|
274
95
|
|
|
275
|
-
|
|
276
|
-
codemod login --username <username>
|
|
277
|
-
```
|
|
96
|
+
### jssg (JavaScript ast-grep)
|
|
278
97
|
|
|
279
|
-
**
|
|
280
|
-
- `--registry <URL>`: Registry URL (defaults to official Butterflow registry)
|
|
281
|
-
- `--token <TOKEN>`: Authentication token (for non-interactive login)
|
|
282
|
-
- `--username <USERNAME>`: Username for interactive login
|
|
283
|
-
- `--scope <SCOPE>`: Organization or user scope for publishing
|
|
98
|
+
**jssg** enables you to write codemods in JavaScript/TypeScript that transform code in **any language** supported by ast-grep (JavaScript, TypeScript, Python, Rust, Go, Java, C++, and more).
|
|
284
99
|
|
|
285
|
-
|
|
100
|
+
```typescript
|
|
101
|
+
// Example: Replace console.log with logger.info
|
|
102
|
+
import type { Transform } from "codemod:ast-grep";
|
|
103
|
+
import type TSX from "codemod:ast-grep/langs/tsx";
|
|
286
104
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
? Registry URL: https://app.butterflow.com(default)
|
|
290
|
-
? Username: john.doe
|
|
291
|
-
? Password: ********
|
|
292
|
-
? Organization (optional): my-org
|
|
293
|
-
✓ Successfully logged in as john.doe
|
|
294
|
-
✓ Default publish scope set to @my-org
|
|
295
|
-
```
|
|
105
|
+
const transform: Transform<TSX> = (root) => {
|
|
106
|
+
const rootNode = root.root();
|
|
296
107
|
|
|
297
|
-
|
|
108
|
+
// Find all console.log calls
|
|
109
|
+
const consoleCalls = rootNode.findAll({
|
|
110
|
+
rule: { pattern: "console.log($$$ARGS)" }
|
|
111
|
+
});
|
|
298
112
|
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
codemod login --token $BUTTERFLOW_TOKEN
|
|
303
|
-
```
|
|
113
|
+
if (consoleCalls.length === 0) {
|
|
114
|
+
return null; // No changes needed
|
|
115
|
+
}
|
|
304
116
|
|
|
305
|
-
|
|
117
|
+
// Create edits
|
|
118
|
+
const edits = consoleCalls.map((node) => {
|
|
119
|
+
const args = node.getMatch('ARGS')?.text() || '';
|
|
120
|
+
return node.replace(`logger.info(${args})`);
|
|
121
|
+
});
|
|
306
122
|
|
|
307
|
-
|
|
123
|
+
return rootNode.commitEdits(edits);
|
|
124
|
+
};
|
|
308
125
|
|
|
309
|
-
|
|
310
|
-
# Publish current directory as a codemod
|
|
311
|
-
codemod publish
|
|
312
|
-
|
|
313
|
-
# Publish a specific codemod directory
|
|
314
|
-
codemod publish ./my-codemod/
|
|
315
|
-
|
|
316
|
-
# Publish with specific version
|
|
317
|
-
codemod publish --version 1.2.3
|
|
318
|
-
|
|
319
|
-
# Publish to specific registry
|
|
320
|
-
codemod publish --registry https://registry.example.com
|
|
321
|
-
|
|
322
|
-
# Dry run (validate without publishing)
|
|
323
|
-
codemod publish --dry-run
|
|
126
|
+
export default transform;
|
|
324
127
|
```
|
|
325
128
|
|
|
326
|
-
|
|
327
|
-
- `--version <VERSION>`: Explicit version (overrides manifest version)
|
|
328
|
-
- `--registry <URL>`: Target registry URL
|
|
329
|
-
- `--tag <TAG>`: Tag for the release (e.g., `beta`, `latest`)
|
|
330
|
-
- `--access <LEVEL>`: Access level (`public` or `private`)
|
|
331
|
-
- `--dry-run`: Validate and pack without uploading
|
|
332
|
-
- `--force`: Override existing version (use with caution)
|
|
333
|
-
|
|
334
|
-
**Publishing Flow:**
|
|
129
|
+
jssg combines the power of AST transformations with the flexibility of JavaScript, making complex transformations intuitive and testable.
|
|
335
130
|
|
|
336
|
-
|
|
337
|
-
$ codemod publish
|
|
338
|
-
✓ Validating codemod.yaml manifest
|
|
339
|
-
✓ Validating workflow.yaml
|
|
340
|
-
✓ Running tests (if present)
|
|
341
|
-
✓ Building codemod bundle
|
|
342
|
-
✓ Uploading to registry @my-org/react-hooks-migration@1.0.0
|
|
343
|
-
✓ Published successfully!
|
|
344
|
-
|
|
345
|
-
Install with: codemod run @my-org/react-hooks-migration@1.0.0
|
|
346
|
-
```
|
|
347
|
-
|
|
348
|
-
## Codemod Manifest Standard
|
|
131
|
+
[Learn more about jssg →](https://docs.codemod.com/jssg)
|
|
349
132
|
|
|
350
|
-
|
|
133
|
+
### Workflow Orchestration
|
|
351
134
|
|
|
352
|
-
|
|
135
|
+
Workflows define how your codemod package runs. They can orchestrate multiple steps, handle dependencies, manage state, and even include manual approval gates:
|
|
353
136
|
|
|
354
137
|
```yaml
|
|
355
|
-
# codemod.yaml
|
|
356
|
-
name: react-hooks-migration
|
|
357
|
-
version: 1.0.0
|
|
358
|
-
description: Migrates React class components to functional components with hooks
|
|
359
|
-
author: John Doe <john@example.com>
|
|
360
|
-
license: MIT
|
|
361
|
-
repository: https://github.com/user/react-hooks-migration
|
|
362
|
-
|
|
363
|
-
registry:
|
|
364
|
-
access: public
|
|
365
|
-
|
|
366
|
-
targets:
|
|
367
|
-
languages:
|
|
368
|
-
- javascript
|
|
369
|
-
- typescript
|
|
370
|
-
frameworks:
|
|
371
|
-
- react
|
|
372
|
-
versions:
|
|
373
|
-
react: ">=16.8.0"
|
|
374
|
-
```
|
|
375
|
-
|
|
376
|
-
### Required Fields
|
|
377
|
-
|
|
378
|
-
| Field | Type | Description |
|
|
379
|
-
|-------|------|-------------|
|
|
380
|
-
| `name` | string | Codemod package name (must be unique in scope) |
|
|
381
|
-
| `version` | string | Semantic version (e.g., "1.0.0") |
|
|
382
|
-
| `description` | string | Brief description of what the codemod does |
|
|
383
|
-
| `author` | string | Author name and email |
|
|
384
|
-
|
|
385
|
-
### Optional Fields
|
|
386
|
-
|
|
387
|
-
| Field | Type | Description |
|
|
388
|
-
|-------|------|-------------|
|
|
389
|
-
| `license` | string | License identifier (e.g., "MIT", "Apache-2.0") |
|
|
390
|
-
| `repository` | string | Repository URL for the codemod source code |
|
|
391
|
-
| `registry.access` | string | Access level: "public" or "private" |
|
|
392
|
-
| `targets.languages` | array | Supported programming languages |
|
|
393
|
-
| `targets.frameworks` | array | Supported frameworks or libraries |
|
|
394
|
-
| `targets.versions` | object | Version constraints for frameworks |
|
|
395
|
-
|
|
396
|
-
### Publishing Examples
|
|
397
|
-
|
|
398
|
-
#### Basic Codemod
|
|
399
|
-
|
|
400
|
-
```yaml
|
|
401
|
-
name: remove-console-logs
|
|
402
|
-
version: 1.0.0
|
|
403
|
-
description: Removes console.log statements from JavaScript/TypeScript files
|
|
404
|
-
author: Developer <dev@example.com>
|
|
405
|
-
license: MIT
|
|
406
|
-
repository: https://github.com/dev/remove-console-logs
|
|
407
|
-
|
|
408
|
-
targets:
|
|
409
|
-
languages: [javascript, typescript]
|
|
410
|
-
```
|
|
411
|
-
|
|
412
|
-
#### Framework-Specific Codemod
|
|
413
|
-
|
|
414
|
-
```yaml
|
|
415
|
-
name: api-migration-v2
|
|
416
|
-
version: 2.1.0
|
|
417
|
-
description: Migrates legacy API calls to new v2 endpoints
|
|
418
|
-
author: API Team <api-team@company.com>
|
|
419
|
-
license: Apache-2.0
|
|
420
|
-
repository: https://github.com/company/api-migration-v2
|
|
421
|
-
|
|
422
|
-
registry:
|
|
423
|
-
access: private
|
|
424
|
-
|
|
425
|
-
targets:
|
|
426
|
-
languages: [javascript, typescript]
|
|
427
|
-
frameworks: [react, vue, angular]
|
|
428
|
-
versions:
|
|
429
|
-
react: ">=16.0.0"
|
|
430
|
-
vue: ">=3.0.0"
|
|
431
|
-
```
|
|
432
|
-
|
|
433
|
-
## Workflow Sources
|
|
434
|
-
|
|
435
|
-
The CLI supports loading workflows from different sources:
|
|
436
|
-
|
|
437
|
-
### File Path
|
|
438
|
-
```bash
|
|
439
|
-
codemod run -w path/to/your/workflow.yaml
|
|
440
|
-
```
|
|
441
|
-
Loads the specific file. The base path for execution is the directory containing this file.
|
|
442
|
-
|
|
443
|
-
### Directory Path (Bundle)
|
|
444
|
-
```bash
|
|
445
|
-
codemod run path/to/your/bundle/
|
|
446
|
-
```
|
|
447
|
-
Butterflow looks for a standard workflow file (e.g., `workflow.yaml`) inside this directory. The base path for execution is this directory.
|
|
448
|
-
|
|
449
|
-
### Registry Identifier
|
|
450
|
-
```bash
|
|
451
|
-
# Install and run a published codemod
|
|
452
|
-
codemod run @my-org/react-hooks-migration@1.0.0
|
|
453
|
-
|
|
454
|
-
# Run latest version
|
|
455
|
-
codemod run @my-org/react-hooks-migration@latest
|
|
456
|
-
|
|
457
|
-
# Run with custom parameters
|
|
458
|
-
codemod run @my-org/api-migration-v2@2.1.0 --param api_base_url=https://staging-api.example.com
|
|
459
|
-
```
|
|
460
|
-
|
|
461
|
-
When running from a registry, Butterflow:
|
|
462
|
-
1. Downloads the codemod bundle from the registry
|
|
463
|
-
2. Caches it locally for faster subsequent runs
|
|
464
|
-
3. Validates the manifest and workflow
|
|
465
|
-
4. Executes with the bundle directory as the base path
|
|
466
|
-
|
|
467
|
-
For your information the defautl registry is `https://app.codemod.com/`. and you can visualize codemods on the [Codemod Registry webapp](https://app.codemod.com/registry).
|
|
468
|
-
|
|
469
|
-
## Workflow Bundles
|
|
470
|
-
|
|
471
|
-
A workflow bundle is a directory containing:
|
|
472
|
-
1. The main workflow definition file (e.g., `workflow.yaml`)
|
|
473
|
-
2. Any scripts, binaries, or configuration files referenced by the workflow steps
|
|
474
|
-
3. Additional assets needed by the tasks
|
|
475
|
-
|
|
476
|
-
When running from a directory, Butterflow uses that directory as the root for resolving relative paths during execution.
|
|
477
|
-
|
|
478
|
-
## Runtime Execution
|
|
479
|
-
|
|
480
|
-
### Container Runtimes
|
|
481
|
-
|
|
482
|
-
The CLI supports multiple execution runtimes:
|
|
483
|
-
|
|
484
|
-
- **Docker**: Uses Docker daemon for container execution
|
|
485
|
-
- **Podman**: Uses Podman for container execution
|
|
486
|
-
- **Direct**: Runs commands directly on the host machine
|
|
487
|
-
|
|
488
|
-
When using `runtime: direct`, commands execute with the same working directory as the `codemod` CLI invocation. Use the `$CODEMOD_PATH` environment variable to access files within the workflow bundle.
|
|
489
|
-
|
|
490
|
-
### Environment Variables
|
|
491
|
-
|
|
492
|
-
The CLI provides several environment variables to running tasks:
|
|
493
|
-
|
|
494
|
-
- `$STATE_OUTPUTS`: File descriptor for writing state updates
|
|
495
|
-
- `$CODEMOD_PATH`: Absolute path to the workflow bundle root (for `direct` runtime)
|
|
496
|
-
- `$BUTTERFLOW_STATE`: Path to state file for programmatic access
|
|
497
|
-
|
|
498
|
-
## Manual Triggers and Resumption
|
|
499
|
-
|
|
500
|
-
### Manual Nodes
|
|
501
|
-
|
|
502
|
-
Nodes with `type: manual` or `trigger: { type: manual }` will pause execution and await manual triggers:
|
|
503
|
-
|
|
504
|
-
```yaml
|
|
505
|
-
nodes:
|
|
506
|
-
- id: deploy-prod
|
|
507
|
-
name: Deploy to Production
|
|
508
|
-
type: automatic
|
|
509
|
-
trigger:
|
|
510
|
-
type: manual # Requires manual approval
|
|
511
|
-
steps:
|
|
512
|
-
- id: deploy
|
|
513
|
-
run: ./deploy.sh production
|
|
514
|
-
```
|
|
515
|
-
|
|
516
|
-
### Triggering Manual Tasks
|
|
517
|
-
|
|
518
|
-
When a workflow pauses for manual triggers:
|
|
519
|
-
|
|
520
|
-
1. The workflow state is persisted with tasks marked `AwaitingTrigger`
|
|
521
|
-
2. The CLI provides task UUIDs for manual triggering
|
|
522
|
-
3. Use `codemod resume` to trigger specific tasks or all awaiting tasks
|
|
523
|
-
|
|
524
|
-
```bash
|
|
525
|
-
# Trigger specific deployment task
|
|
526
|
-
codemod resume -i abc123-workflow-run-id -t def456-task-uuid
|
|
527
|
-
|
|
528
|
-
# Trigger all awaiting tasks and continue
|
|
529
|
-
codemod resume -i abc123-workflow-run-id --trigger-all
|
|
530
|
-
```
|
|
531
|
-
|
|
532
|
-
## Error Handling
|
|
533
|
-
|
|
534
|
-
### Automatic Validation
|
|
535
|
-
|
|
536
|
-
Validation is performed automatically when running workflows:
|
|
537
|
-
|
|
538
|
-
```bash
|
|
539
|
-
$ codemod run -w invalid-workflow.yaml
|
|
540
|
-
✗ Workflow definition is invalid
|
|
541
|
-
Error: Cyclic dependency detected: node-a → node-b → node-a
|
|
542
|
-
Workflow execution aborted
|
|
543
|
-
```
|
|
544
|
-
|
|
545
|
-
### Resume After Failures
|
|
546
|
-
|
|
547
|
-
If a workflow fails or is interrupted:
|
|
548
|
-
|
|
549
|
-
1. The state is automatically persisted
|
|
550
|
-
2. Use `codemod resume` to continue from the last checkpoint
|
|
551
|
-
3. Failed tasks can be retried while preserving completed work
|
|
552
|
-
|
|
553
|
-
## Examples
|
|
554
|
-
|
|
555
|
-
### Basic Workflow Execution
|
|
556
|
-
|
|
557
|
-
```bash
|
|
558
|
-
# Create and run a simple workflow
|
|
559
|
-
cat > hello.yaml << EOF
|
|
560
138
|
version: "1"
|
|
561
139
|
nodes:
|
|
562
|
-
- id:
|
|
563
|
-
name:
|
|
140
|
+
- id: transform
|
|
141
|
+
name: Update API Calls
|
|
564
142
|
type: automatic
|
|
565
|
-
runtime:
|
|
566
|
-
type: direct
|
|
567
143
|
steps:
|
|
568
|
-
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
144
|
+
- name: "Run jssg codemod"
|
|
145
|
+
js-ast-grep:
|
|
146
|
+
js_file: "scripts/update-api.ts"
|
|
147
|
+
language: "typescript"
|
|
148
|
+
include:
|
|
149
|
+
- "**/*.ts"
|
|
150
|
+
- "**/*.tsx"
|
|
151
|
+
|
|
152
|
+
- name: "Format code"
|
|
153
|
+
run: npx prettier --write "**/*.{ts,tsx}"
|
|
154
|
+
|
|
155
|
+
- name: "Run tests"
|
|
156
|
+
run: npm test
|
|
573
157
|
```
|
|
574
158
|
|
|
575
|
-
|
|
159
|
+
[Learn more about workflows →](https://docs.codemod.com/cli/packages/building-workflows)
|
|
576
160
|
|
|
577
|
-
|
|
578
|
-
# Run matrix workflow requiring manual triggers
|
|
579
|
-
codemod run -w deploy-workflow.yaml
|
|
161
|
+
## CLI Commands
|
|
580
162
|
|
|
581
|
-
|
|
582
|
-
codemod resume -i <run-id> -t <staging-task-uuid>
|
|
583
|
-
codemod resume -i <run-id> -t <prod-task-uuid>
|
|
584
|
-
```
|
|
163
|
+
### Package Management
|
|
585
164
|
|
|
586
|
-
|
|
165
|
+
| Command | Description |
|
|
166
|
+
|---------|-------------|
|
|
167
|
+
| `npx codemod init [path]` | Create a new codemod package with interactive setup |
|
|
168
|
+
| `npx codemod publish [path]` | Publish package to the Codemod Registry |
|
|
169
|
+
| `npx codemod login` | Authenticate with the registry (browser or API key) |
|
|
170
|
+
| `npx codemod logout` | Logout from registry |
|
|
171
|
+
| `npx codemod whoami` | Show current authentication status |
|
|
172
|
+
| `npx codemod search [query]` | Search for packages in the registry |
|
|
173
|
+
| `npx codemod unpublish <package>` | Remove a package from the registry |
|
|
587
174
|
|
|
588
|
-
|
|
589
|
-
# Validate before running
|
|
590
|
-
codemod validate -w complex-workflow.yaml
|
|
175
|
+
### Workflow Commands
|
|
591
176
|
|
|
592
|
-
|
|
593
|
-
|
|
177
|
+
| Command | Description |
|
|
178
|
+
|---------|-------------|
|
|
179
|
+
| `npx codemod workflow run -w <path>` | Run a codemod workflow on your codebase |
|
|
180
|
+
| `npx codemod workflow validate -w <path>` | Validate workflow syntax and structure |
|
|
181
|
+
| `npx codemod workflow resume -i <id>` | Resume a paused workflow |
|
|
182
|
+
| `npx codemod workflow status -i <id>` | Show workflow execution status |
|
|
183
|
+
| `npx codemod workflow list` | List recent workflow runs |
|
|
184
|
+
| `npx codemod workflow cancel -i <id>` | Cancel a running workflow |
|
|
594
185
|
|
|
595
|
-
|
|
596
|
-
codemod login
|
|
597
|
-
codemod publish ./my-codemod/
|
|
186
|
+
### jssg Commands
|
|
598
187
|
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
188
|
+
| Command | Description |
|
|
189
|
+
|---------|-------------|
|
|
190
|
+
| `npx codemod jssg run <file> <target> --language <lang>` | Run a jssg codemod directly |
|
|
191
|
+
| `npx codemod jssg test <file> --language <lang>` | Test jssg codemod with fixtures |
|
|
602
192
|
|
|
603
|
-
###
|
|
193
|
+
### Cache Management
|
|
604
194
|
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
codemod
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
# ... edit workflow.yaml, add rules, scripts, etc.
|
|
612
|
-
|
|
613
|
-
# Create manifest
|
|
614
|
-
cat > codemod.yaml << EOF
|
|
615
|
-
name: my-api-migration
|
|
616
|
-
version: 1.0.0
|
|
617
|
-
description: Migrates legacy API calls
|
|
618
|
-
author: Developer <dev@example.com>
|
|
619
|
-
workflow: workflow.yaml
|
|
620
|
-
targets:
|
|
621
|
-
languages: [javascript, typescript]
|
|
622
|
-
EOF
|
|
623
|
-
|
|
624
|
-
# Validate and publish
|
|
625
|
-
codemod validate
|
|
626
|
-
codemod publish --dry-run # Preview
|
|
627
|
-
codemod publish # Publish to registry
|
|
628
|
-
```
|
|
195
|
+
| Command | Description |
|
|
196
|
+
|---------|-------------|
|
|
197
|
+
| `npx codemod cache info` | Show cache statistics |
|
|
198
|
+
| `npx codemod cache list` | List all cached packages |
|
|
199
|
+
| `npx codemod cache clear [package]` | Clear cache for package or all |
|
|
200
|
+
| `npx codemod cache prune` | Remove old or unused cache entries |
|
|
629
201
|
|
|
630
|
-
|
|
202
|
+
**For detailed options and examples, see the [full CLI reference →](https://docs.codemod.com/cli/cli-reference)**
|
|
631
203
|
|
|
632
|
-
|
|
204
|
+
## Ecosystem & Platform
|
|
633
205
|
|
|
634
|
-
|
|
635
|
-
- `--version, -V`: Show version information
|
|
636
|
-
- `--verbose, -v`: Enable verbose output
|
|
637
|
-
- `--quiet, -q`: Suppress non-essential output
|
|
206
|
+
The Codemod CLI is part of a larger ecosystem designed to help teams modernize code at scale:
|
|
638
207
|
|
|
639
|
-
|
|
208
|
+
### Open-Source Tools
|
|
640
209
|
|
|
641
|
-
|
|
642
|
-
codemod
|
|
643
|
-
|
|
210
|
+
- **[Codemod CLI](https://docs.codemod.com/cli)** (this package) – Build, test, and run codemod packages
|
|
211
|
+
- **[Codemod MCP](https://go.codemod.com/mcp-docs)** – Build codemods with AI assistance in your IDE
|
|
212
|
+
- **[Public Registry](https://go.codemod.com/registry)** – Discover and share community codemods
|
|
644
213
|
|
|
645
|
-
|
|
214
|
+
### Enterprise Platform Features
|
|
646
215
|
|
|
647
|
-
|
|
216
|
+
For teams coordinating migrations across multiple repositories:
|
|
648
217
|
|
|
649
|
-
|
|
218
|
+
- **[Codemod Studio](https://go.codemod.com/studio)** – AI-powered web interface for creating codemods
|
|
219
|
+
- **[Campaigns](https://docs.codemod.com/migrations)** – Multi-repo orchestration with progress tracking
|
|
220
|
+
- **[Insights](https://docs.codemod.com/insights)** – Analytics dashboards for measuring migration impact
|
|
221
|
+
- **Private Registry** – Secure, organization-scoped codemod packages
|
|
650
222
|
|
|
651
|
-
|
|
223
|
+
[Learn more about the platform →](https://app.codemod.com)
|
|
652
224
|
|
|
653
|
-
|
|
654
|
-
codemod jssg run my-codemod.js ./src --language javascript
|
|
655
|
-
```
|
|
225
|
+
## Resources
|
|
656
226
|
|
|
657
|
-
|
|
658
|
-
-
|
|
659
|
-
-
|
|
660
|
-
-
|
|
661
|
-
-
|
|
662
|
-
- `--max-threads <N>`: Maximum number of concurrent threads
|
|
663
|
-
- `--dry-run`: Perform a dry run without making changes
|
|
227
|
+
### Documentation
|
|
228
|
+
- **[Full Documentation](https://docs.codemod.com)** – Comprehensive guides and tutorials
|
|
229
|
+
- **[CLI Reference](https://docs.codemod.com/cli/cli-reference)** – Detailed command documentation
|
|
230
|
+
- **[Codemod Packages](https://docs.codemod.com/cli/packages)** – Learn more about codemod packages and workflows
|
|
231
|
+
- **[jssg Documentation](https://docs.codemod.com/jssg)** – JavaScript ast-grep reference
|
|
664
232
|
|
|
665
|
-
|
|
233
|
+
### Get Help
|
|
234
|
+
- **[Slack Community](https://go.codemod.com/community)** – Ask questions and share codemods
|
|
235
|
+
- **[GitHub Discussions](https://github.com/codemod/codemod/discussions)** – Long-form Q&A
|
|
236
|
+
- **[GitHub Issues](https://github.com/codemod/codemod/issues)** – Report bugs or request features
|
|
666
237
|
|
|
667
|
-
###
|
|
238
|
+
### Explore
|
|
239
|
+
- **[Codemod Registry](https://go.codemod.com/registry)** – Browse community codemods
|
|
240
|
+
- **[Codemod Studio](https://go.codemod.com/studio)** – Try creating codemods with AI
|
|
241
|
+
- **[Example Codemods](https://github.com/codemod/codemod/tree/main/test-codemods)** – Reference implementations
|
|
668
242
|
|
|
669
|
-
|
|
670
|
-
codemod jssg run my-codemod.js ./src --language javascript --dry-run
|
|
671
|
-
```
|
|
243
|
+
## Contributing
|
|
672
244
|
|
|
673
|
-
|
|
245
|
+
Contributions are welcome! Help make codemod automation better for everyone.
|
|
674
246
|
|
|
675
|
-
|
|
247
|
+
**Ways to contribute:**
|
|
248
|
+
- 🐛 Report bugs via [GitHub Issues](https://github.com/codemod/codemod/issues)
|
|
249
|
+
- 💡 Suggest features on [Feedback Board](https://feedback.codemod.com)
|
|
250
|
+
- 📝 Improve documentation
|
|
251
|
+
- 🔧 Submit pull requests
|
|
252
|
+
- 🌟 Star the repo and spread the word
|
|
676
253
|
|
|
677
|
-
|
|
254
|
+
Read our [Contributing Guide](https://github.com/codemod/codemod/blob/main/CONTRIBUTING.md) and [Code of Conduct](https://github.com/codemod/codemod/blob/main/CODE_OF_CONDUCT.md).
|
|
678
255
|
|
|
679
|
-
|
|
256
|
+
## License
|
|
680
257
|
|
|
681
|
-
|
|
258
|
+
MIT License - see [LICENSE](https://github.com/codemod/codemod/blob/main/LICENSE) for details.
|
|
682
259
|
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
Create a test directory with the following structure:
|
|
686
|
-
|
|
687
|
-
```
|
|
688
|
-
tests/
|
|
689
|
-
├── simple-transform/
|
|
690
|
-
│ ├── input.js
|
|
691
|
-
│ └── expected.js
|
|
692
|
-
├── complex-case/
|
|
693
|
-
│ ├── input.ts
|
|
694
|
-
│ └── expected.ts
|
|
695
|
-
└── multi-file/
|
|
696
|
-
├── input/
|
|
697
|
-
│ ├── file1.js
|
|
698
|
-
│ └── file2.js
|
|
699
|
-
└── expected/
|
|
700
|
-
├── file1.js
|
|
701
|
-
└── file2.js
|
|
702
|
-
```
|
|
703
|
-
|
|
704
|
-
### 2. Running Tests
|
|
705
|
-
|
|
706
|
-
```bash
|
|
707
|
-
# Basic test run (language can be specified in config file)
|
|
708
|
-
codemod jssg test my-codemod.js --language javascript
|
|
709
|
-
|
|
710
|
-
# With custom test directory
|
|
711
|
-
codemod jssg test my-codemod.js --language typescript --test-directory ./my-tests
|
|
712
|
-
|
|
713
|
-
# Update snapshots (create/update expected files)
|
|
714
|
-
codemod jssg test my-codemod.js --language javascript --update-snapshots
|
|
715
|
-
|
|
716
|
-
# Verbose output with detailed diffs
|
|
717
|
-
codemod jssg test my-codemod.js --language javascript --verbose
|
|
718
|
-
|
|
719
|
-
# Watch mode (re-run tests on file changes)
|
|
720
|
-
codemod jssg test my-codemod.js --language javascript --watch
|
|
721
|
-
|
|
722
|
-
# Using configuration files (no CLI args needed)
|
|
723
|
-
codemod jssg test my-codemod.js
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
## CLI Options
|
|
727
|
-
|
|
728
|
-
### Required Arguments
|
|
729
|
-
- `codemod_file`: Path to the codemod JavaScript file
|
|
730
|
-
|
|
731
|
-
### Optional Arguments
|
|
732
|
-
- `--language`: Target language (javascript, typescript, etc.) - can be specified in config file
|
|
733
|
-
|
|
734
|
-
### Test Discovery
|
|
735
|
-
- `--test-directory`: Test directory (default: "tests")
|
|
736
|
-
- `--filter`: Run only tests matching pattern
|
|
737
|
-
|
|
738
|
-
### Output Control
|
|
739
|
-
- `--reporter`: Output format (console, json, terse)
|
|
740
|
-
- `--verbose`: Show detailed output
|
|
741
|
-
- `--context-lines`: Number of diff context lines (default: 3)
|
|
742
|
-
- `--ignore-whitespace`: Ignore whitespace in comparisons
|
|
743
|
-
|
|
744
|
-
### Test Execution
|
|
745
|
-
- `--timeout`: Test timeout in seconds (default: 30)
|
|
746
|
-
- `--max-threads`: Maximum concurrent threads
|
|
747
|
-
- `--sequential`: Run tests sequentially
|
|
748
|
-
- `--fail-fast`: Stop on first failure
|
|
749
|
-
|
|
750
|
-
### Snapshot Management
|
|
751
|
-
- `--update-snapshots`: Create/update expected files
|
|
752
|
-
- `--expect-errors`: Comma-separated patterns for tests expected to fail
|
|
753
|
-
|
|
754
|
-
### Development
|
|
755
|
-
- `--watch`: Watch for changes and re-run tests
|
|
756
|
-
|
|
757
|
-
## Test File Formats
|
|
758
|
-
|
|
759
|
-
### Single File Format
|
|
760
|
-
Each test case is a directory with `input.{ext}` and `expected.{ext}` files:
|
|
761
|
-
|
|
762
|
-
```
|
|
763
|
-
test-case-name/
|
|
764
|
-
├── input.js # Input code
|
|
765
|
-
└── expected.js # Expected output
|
|
766
|
-
```
|
|
767
|
-
|
|
768
|
-
### Multi-File Format
|
|
769
|
-
For testing multiple files, use `input/` and `expected/` directories:
|
|
770
|
-
|
|
771
|
-
```
|
|
772
|
-
test-case-name/
|
|
773
|
-
├── input/
|
|
774
|
-
│ ├── file1.js
|
|
775
|
-
│ └── file2.js
|
|
776
|
-
└── expected/
|
|
777
|
-
├── file1.js
|
|
778
|
-
└── file2.js
|
|
779
|
-
```
|
|
780
|
-
|
|
781
|
-
## Language Support
|
|
782
|
-
|
|
783
|
-
The framework automatically detects input files based on language extensions:
|
|
784
|
-
|
|
785
|
-
- **JavaScript**: `.js`, `.jsx`, `.mjs`
|
|
786
|
-
- **TypeScript**: `.ts`, `.tsx`, `.mts`
|
|
787
|
-
- **Other languages**: Determined by `get_extensions_for_language()`
|
|
788
|
-
|
|
789
|
-
## Error Handling
|
|
790
|
-
|
|
791
|
-
### Missing Expected Files
|
|
792
|
-
```bash
|
|
793
|
-
# Error: No expected file found
|
|
794
|
-
codemod jssg test my-codemod.js --language javascript
|
|
795
|
-
# Error: No expected file found for input.js in tests/my-test. Run with --update-snapshots to create it.
|
|
796
|
-
|
|
797
|
-
# Solution: Create expected files
|
|
798
|
-
codemod jssg test my-codemod.js --language javascript --update-snapshots
|
|
799
|
-
# Created expected file for my-test/input.js
|
|
800
|
-
```
|
|
801
|
-
|
|
802
|
-
### Ambiguous Input Files
|
|
803
|
-
```bash
|
|
804
|
-
# Error: Multiple input files found
|
|
805
|
-
# tests/my-test/input.js and tests/my-test/input.ts both exist
|
|
806
|
-
|
|
807
|
-
# Solution: Use only one input file or organize into directories
|
|
808
|
-
```
|
|
809
|
-
|
|
810
|
-
### Expected Test Failures
|
|
811
|
-
```bash
|
|
812
|
-
# Test cases that should fail
|
|
813
|
-
codemod jssg test my-codemod.js --language javascript --expect-errors "error-case,invalid-syntax"
|
|
814
|
-
```
|
|
815
|
-
|
|
816
|
-
## Output Formats
|
|
817
|
-
|
|
818
|
-
### Console (Default)
|
|
819
|
-
```
|
|
820
|
-
test my-test ... ok
|
|
821
|
-
test failing-test ... FAILED
|
|
822
|
-
|
|
823
|
-
failures:
|
|
824
|
-
|
|
825
|
-
---- failing-test stdout ----
|
|
826
|
-
Output mismatch for file expected.js:
|
|
827
|
-
-const x = 1;
|
|
828
|
-
+const y = 1;
|
|
829
|
-
|
|
830
|
-
test result: FAILED. 1 passed; 1 failed; 0 ignored
|
|
831
|
-
```
|
|
832
|
-
|
|
833
|
-
### JSON
|
|
834
|
-
```bash
|
|
835
|
-
codemod jssg test my-codemod.js --language javascript --reporter json
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
```json
|
|
839
|
-
{
|
|
840
|
-
"type": "suite",
|
|
841
|
-
"event": "started",
|
|
842
|
-
"test_count": 2
|
|
843
|
-
}
|
|
844
|
-
{
|
|
845
|
-
"type": "test",
|
|
846
|
-
"event": "started",
|
|
847
|
-
"name": "my-test"
|
|
848
|
-
}
|
|
849
|
-
{
|
|
850
|
-
"type": "test",
|
|
851
|
-
"name": "my-test",
|
|
852
|
-
"event": "ok"
|
|
853
|
-
}
|
|
854
|
-
```
|
|
855
|
-
|
|
856
|
-
### Terse
|
|
857
|
-
```bash
|
|
858
|
-
codemod jssg test my-codemod.js --language javascript --reporter terse
|
|
859
|
-
```
|
|
860
|
-
|
|
861
|
-
```
|
|
862
|
-
..F
|
|
863
|
-
|
|
864
|
-
failures:
|
|
865
|
-
...
|
|
866
|
-
```
|
|
867
|
-
|
|
868
|
-
## Advanced Features
|
|
869
|
-
|
|
870
|
-
### Snapshot Management
|
|
871
|
-
```bash
|
|
872
|
-
# Create initial snapshots
|
|
873
|
-
codemod jssg test my-codemod.js --language javascript --update-snapshots
|
|
874
|
-
|
|
875
|
-
# Update specific test snapshots
|
|
876
|
-
codemod jssg test my-codemod.js --language javascript --filter "specific-test" --update-snapshots
|
|
877
|
-
```
|
|
878
|
-
|
|
879
|
-
### Test Filtering
|
|
880
|
-
```bash
|
|
881
|
-
# Run tests matching pattern
|
|
882
|
-
codemod jssg test my-codemod.js --language javascript --filter "transform"
|
|
883
|
-
|
|
884
|
-
# Run specific test
|
|
885
|
-
codemod jssg test my-codemod.js --language javascript --filter "my-specific-test"
|
|
886
|
-
```
|
|
887
|
-
|
|
888
|
-
### Performance Tuning
|
|
889
|
-
```bash
|
|
890
|
-
# Limit concurrent threads
|
|
891
|
-
codemod jssg test my-codemod.js --language javascript --max-threads 2
|
|
892
|
-
|
|
893
|
-
# Run sequentially for debugging
|
|
894
|
-
codemod jssg test my-codemod.js --language javascript --sequential
|
|
895
|
-
|
|
896
|
-
# Set custom timeout
|
|
897
|
-
codemod jssg test my-codemod.js --language javascript --timeout 60
|
|
898
|
-
```
|
|
899
|
-
|
|
900
|
-
### Diff Customization
|
|
901
|
-
```bash
|
|
902
|
-
# More context in diffs
|
|
903
|
-
codemod jssg test my-codemod.js --language javascript --context-lines 5
|
|
904
|
-
|
|
905
|
-
# Ignore whitespace differences
|
|
906
|
-
codemod jssg test my-codemod.js --language javascript --ignore-whitespace
|
|
907
|
-
```
|
|
908
|
-
|
|
909
|
-
## Integration with Development Workflow
|
|
910
|
-
|
|
911
|
-
### CI/CD Integration
|
|
912
|
-
```yaml
|
|
913
|
-
# GitHub Actions example
|
|
914
|
-
- name: Run codemod tests
|
|
915
|
-
run: codemod jssg test my-codemod.js --language javascript --reporter json
|
|
916
|
-
```
|
|
917
|
-
|
|
918
|
-
### IDE Integration
|
|
919
|
-
The framework outputs standard test results that can be consumed by IDEs and test runners.
|
|
920
|
-
|
|
921
|
-
### Watch Mode Development
|
|
922
|
-
```bash
|
|
923
|
-
# Continuous testing during development
|
|
924
|
-
codemod jssg test my-codemod.js --language javascript --watch --verbose
|
|
925
|
-
```
|
|
926
|
-
|
|
927
|
-
## Best Practices
|
|
928
|
-
|
|
929
|
-
1. **Organize tests by functionality**: Group related test cases in descriptive directories
|
|
930
|
-
2. **Use meaningful test names**: Directory names become test names in output
|
|
931
|
-
3. **Start with --update-snapshots**: Generate initial expected files, then review and commit
|
|
932
|
-
4. **Use --expect-errors for negative tests**: Test error conditions explicitly
|
|
933
|
-
5. **Leverage --filter during development**: Focus on specific tests while developing
|
|
934
|
-
6. **Use --watch for rapid iteration**: Get immediate feedback on changes
|
|
935
|
-
|
|
936
|
-
## Troubleshooting
|
|
937
|
-
|
|
938
|
-
### Common Issues
|
|
939
|
-
|
|
940
|
-
1. **No tests found**: Check test directory path and file extensions
|
|
941
|
-
2. **Ambiguous input files**: Ensure only one input file per test case
|
|
942
|
-
3. **Timeout errors**: Increase timeout for complex codemods
|
|
943
|
-
4. **Memory issues**: Reduce max-threads for large test suites
|
|
944
|
-
|
|
945
|
-
### Debug Mode
|
|
946
|
-
```bash
|
|
947
|
-
# Verbose output for debugging
|
|
948
|
-
codemod jssg test my-codemod.js --language javascript --verbose --sequential
|
|
949
|
-
```
|
|
950
|
-
|
|
951
|
-
This framework provides a robust foundation for testing JavaScript codemods with familiar tooling and comprehensive features.
|
|
952
|
-
|
|
953
|
-
## Configuration System
|
|
954
|
-
|
|
955
|
-
jssg supports a hierarchical configuration system using configuration files, allowing you to specify test settings globally and override them per test case. Multiple file formats and aliases are supported.
|
|
956
|
-
|
|
957
|
-
### Configuration Files
|
|
958
|
-
|
|
959
|
-
#### Supported Formats and Names
|
|
960
|
-
|
|
961
|
-
Configuration files are searched in the following order of precedence (first found wins):
|
|
962
|
-
|
|
963
|
-
1. `test.config.json` - JSON format
|
|
964
|
-
2. `test.config.yaml` - YAML format
|
|
965
|
-
3. `codemod-test.config.json` - JSON format with codemod prefix
|
|
966
|
-
4. `codemod-test.config.yaml` - YAML format with codemod prefix
|
|
967
|
-
|
|
968
|
-
#### Global Configuration
|
|
969
|
-
|
|
970
|
-
Create a configuration file in your project root to set default configurations:
|
|
971
|
-
|
|
972
|
-
**JSON format (`test.config.json`):**
|
|
973
|
-
```json
|
|
974
|
-
{
|
|
975
|
-
"language": "typescript",
|
|
976
|
-
"timeout": 30,
|
|
977
|
-
"ignore_whitespace": false
|
|
978
|
-
}
|
|
979
|
-
```
|
|
980
|
-
|
|
981
|
-
**YAML format (`test.config.yaml`):**
|
|
982
|
-
```yaml
|
|
983
|
-
language: typescript
|
|
984
|
-
timeout: 30
|
|
985
|
-
ignore_whitespace: false
|
|
986
|
-
```
|
|
987
|
-
|
|
988
|
-
#### Test Case Configuration
|
|
989
|
-
|
|
990
|
-
Create configuration files in individual test case directories to override global settings:
|
|
991
|
-
|
|
992
|
-
```
|
|
993
|
-
tests/
|
|
994
|
-
├── test.config.yaml # Global config (YAML)
|
|
995
|
-
├── simple-transform/
|
|
996
|
-
│ ├── input.js
|
|
997
|
-
│ ├── expected.js
|
|
998
|
-
│ └── test.config.json # Test-specific config (JSON)
|
|
999
|
-
└── complex-case/
|
|
1000
|
-
├── input.ts
|
|
1001
|
-
├── expected.ts
|
|
1002
|
-
└── codemod-test.config.yaml # Different test-specific config (YAML with prefix)
|
|
1003
|
-
```
|
|
1004
|
-
|
|
1005
|
-
**Example test-specific configs:**
|
|
1006
|
-
|
|
1007
|
-
JSON format (`test.config.json`):
|
|
1008
|
-
```json
|
|
1009
|
-
{
|
|
1010
|
-
"language": "javascript",
|
|
1011
|
-
"expect_errors": ["syntax-error"],
|
|
1012
|
-
"timeout": 60
|
|
1013
|
-
}
|
|
1014
|
-
```
|
|
1015
|
-
|
|
1016
|
-
YAML format (`test.config.yaml`):
|
|
1017
|
-
```yaml
|
|
1018
|
-
language: javascript
|
|
1019
|
-
expect_errors:
|
|
1020
|
-
- syntax-error
|
|
1021
|
-
timeout: 60
|
|
1022
|
-
```
|
|
1023
|
-
|
|
1024
|
-
### Configuration Schema
|
|
1025
|
-
|
|
1026
|
-
Configuration options that can be specified in configuration files:
|
|
1027
|
-
|
|
1028
|
-
**Per-Test Configurable Options:**
|
|
1029
|
-
| Option | Type | Description |
|
|
1030
|
-
|--------|------|-------------|
|
|
1031
|
-
| `language` | string | Target language (javascript, typescript, etc.) |
|
|
1032
|
-
| `timeout` | number | Test timeout in seconds |
|
|
1033
|
-
| `ignore_whitespace` | boolean | Ignore whitespace differences in comparisons |
|
|
1034
|
-
| `expect_errors` | string[] | Test patterns expected to produce errors |
|
|
1035
|
-
|
|
1036
|
-
**Global-Only Options (CLI arguments only):**
|
|
1037
|
-
These options control test execution behavior and cannot be configured per-test:
|
|
1038
|
-
- `test_directory` - Directory containing test fixtures
|
|
1039
|
-
- `filter` - Run only tests matching this pattern
|
|
1040
|
-
- `update_snapshots` - Update expected outputs with actual results
|
|
1041
|
-
- `verbose` - Show detailed output for each test
|
|
1042
|
-
- `sequential` - Run tests sequentially instead of in parallel
|
|
1043
|
-
- `max_threads` - Maximum number of concurrent test threads
|
|
1044
|
-
- `fail_fast` - Stop on first test failure
|
|
1045
|
-
- `watch` - Watch for file changes and re-run tests
|
|
1046
|
-
- `reporter` - Output format (console, json, terse)
|
|
1047
|
-
- `context_lines` - Number of context lines in diff output
|
|
1048
|
-
|
|
1049
|
-
### Configuration Precedence
|
|
1050
|
-
|
|
1051
|
-
Configuration is resolved differently for per-test and global options:
|
|
1052
|
-
|
|
1053
|
-
**For Per-Test Options** (language, timeout, ignore_whitespace, expect_errors):
|
|
1054
|
-
1. Default values
|
|
1055
|
-
2. Root `test.config.json` (walking up directory tree)
|
|
1056
|
-
3. Parent directory configs (inheriting from root to test case)
|
|
1057
|
-
4. Test case `test.config.json` (highest priority for per-test options)
|
|
1058
|
-
5. CLI arguments (override everything)
|
|
1059
|
-
|
|
1060
|
-
**For Global Options** (all execution behavior settings):
|
|
1061
|
-
- Only CLI arguments are considered - config files are ignored for these options
|
|
1062
|
-
|
|
1063
|
-
### Usage Examples
|
|
1064
|
-
|
|
1065
|
-
#### Basic Global Configuration
|
|
1066
|
-
|
|
1067
|
-
**Using JSON:**
|
|
1068
|
-
```bash
|
|
1069
|
-
# Create global config (only per-test options)
|
|
1070
|
-
cat > test.config.json << EOF
|
|
1071
|
-
{
|
|
1072
|
-
"language": "typescript",
|
|
1073
|
-
"timeout": 60
|
|
1074
|
-
}
|
|
1075
|
-
EOF
|
|
1076
|
-
```
|
|
1077
|
-
|
|
1078
|
-
**Using YAML:**
|
|
1079
|
-
```bash
|
|
1080
|
-
# Create global config (only per-test options)
|
|
1081
|
-
cat > test.config.yaml << EOF
|
|
1082
|
-
language: typescript
|
|
1083
|
-
timeout: 60
|
|
1084
|
-
EOF
|
|
1085
|
-
```
|
|
1086
|
-
|
|
1087
|
-
**Running tests:**
|
|
1088
|
-
```bash
|
|
1089
|
-
# Run tests (use CLI for global execution options)
|
|
1090
|
-
codemod jssg test my-codemod.js --reporter json --max-threads 2
|
|
1091
|
-
```
|
|
1092
|
-
|
|
1093
|
-
#### Per-Test-Case Language Support
|
|
1094
|
-
|
|
1095
|
-
```bash
|
|
1096
|
-
# Global config (YAML)
|
|
1097
|
-
cat > test.config.yaml << EOF
|
|
1098
|
-
language: javascript
|
|
1099
|
-
EOF
|
|
1100
|
-
|
|
1101
|
-
# TypeScript-specific test (JSON)
|
|
1102
|
-
mkdir tests/typescript-test
|
|
1103
|
-
cat > tests/typescript-test/test.config.json << EOF
|
|
1104
|
-
{
|
|
1105
|
-
"language": "typescript"
|
|
1106
|
-
}
|
|
1107
|
-
EOF
|
|
1108
|
-
|
|
1109
|
-
# Another test with codemod prefix (YAML)
|
|
1110
|
-
mkdir tests/special-test
|
|
1111
|
-
cat > tests/special-test/codemod-test.config.yaml << EOF
|
|
1112
|
-
language: typescript
|
|
1113
|
-
timeout: 120
|
|
1114
|
-
expect_errors:
|
|
1115
|
-
- compile-error
|
|
1116
|
-
EOF
|
|
1117
|
-
|
|
1118
|
-
# Mixed language and format testing works automatically
|
|
1119
|
-
codemod jssg test my-codemod.js
|
|
1120
|
-
```
|
|
1121
|
-
|
|
1122
|
-
#### Development Workflow
|
|
1123
|
-
|
|
1124
|
-
```bash
|
|
1125
|
-
# Set up development-friendly defaults (per-test options only)
|
|
1126
|
-
cat > test.config.json << EOF
|
|
1127
|
-
{
|
|
1128
|
-
"language": "typescript",
|
|
1129
|
-
"timeout": 120
|
|
1130
|
-
}
|
|
1131
|
-
EOF
|
|
1132
|
-
|
|
1133
|
-
# Use CLI args for execution behavior
|
|
1134
|
-
# Development
|
|
1135
|
-
codemod jssg test my-codemod.js --verbose --fail-fast --context-lines 5
|
|
1136
|
-
|
|
1137
|
-
# CI
|
|
1138
|
-
codemod jssg test my-codemod.js --reporter json --max-threads 1 --sequential
|
|
1139
|
-
```
|
|
1140
|
-
|
|
1141
|
-
### Configuration Discovery
|
|
1142
|
-
|
|
1143
|
-
The system automatically discovers per-test configuration files by:
|
|
1144
|
-
|
|
1145
|
-
1. Starting from the current working directory
|
|
1146
|
-
2. Looking for configuration files in the supported formats and names
|
|
1147
|
-
3. Walking up the directory tree to find parent configs
|
|
1148
|
-
4. For each test case, checking for test-specific configuration files
|
|
1149
|
-
5. Merging configurations with proper inheritance (child overrides parent)
|
|
1150
|
-
6. Applying CLI argument overrides (for both global and per-test options)
|
|
1151
|
-
|
|
1152
|
-
**Configuration File Discovery Order:**
|
|
1153
|
-
At each directory level, the system checks for files in this order:
|
|
1154
|
-
1. `test.config.json`
|
|
1155
|
-
2. `test.config.yaml`
|
|
1156
|
-
3. `codemod-test.config.json`
|
|
1157
|
-
4. `codemod-test.config.yaml`
|
|
1158
|
-
|
|
1159
|
-
The first file found is used for that directory level.
|
|
1160
|
-
|
|
1161
|
-
This allows for flexible project organization where you can have:
|
|
1162
|
-
- Repository-wide defaults in the root configuration file
|
|
1163
|
-
- Module-specific configs in subdirectories (any supported format)
|
|
1164
|
-
- Test-case specific overrides in individual test folders (any supported format)
|
|
1165
|
-
|
|
1166
|
-
**Important:** Only per-test options (language, timeout, ignore_whitespace, expect_errors) are inherited from config files. Global execution options must be specified via CLI arguments.
|
|
260
|
+
---
|
|
1167
261
|
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
262
|
+
<p align="center">
|
|
263
|
+
<strong>Built with ❤️ by <a href="https://codemod.com">Codemod</a> and the <a href="https://github.com/codemod/codemod/graphs/contributors">open-source community</a></strong>
|
|
264
|
+
</p>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codemod",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,11 +29,11 @@
|
|
|
29
29
|
"postinstall": "node postinstall.js"
|
|
30
30
|
},
|
|
31
31
|
"optionalDependencies": {
|
|
32
|
-
"@codemod.com/cli-darwin-arm64": "1.
|
|
33
|
-
"@codemod.com/cli-darwin-x64": "1.
|
|
34
|
-
"@codemod.com/cli-linux-arm64-gnu": "1.
|
|
35
|
-
"@codemod.com/cli-linux-x64-gnu": "1.
|
|
36
|
-
"@codemod.com/cli-win32-x64-msvc": "1.
|
|
32
|
+
"@codemod.com/cli-darwin-arm64": "1.1.1",
|
|
33
|
+
"@codemod.com/cli-darwin-x64": "1.1.1",
|
|
34
|
+
"@codemod.com/cli-linux-arm64-gnu": "1.1.1",
|
|
35
|
+
"@codemod.com/cli-linux-x64-gnu": "1.1.1",
|
|
36
|
+
"@codemod.com/cli-win32-x64-msvc": "1.1.1"
|
|
37
37
|
},
|
|
38
38
|
"bin": {
|
|
39
39
|
"codemod": "codemod"
|