@kamaalio/codemods 0.0.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/LICENSE +21 -0
- package/README.md +363 -0
- package/bin/dev.cmd +3 -0
- package/bin/dev.mjs +5 -0
- package/bin/run.cmd +3 -0
- package/bin/run.mjs +5 -0
- package/package.json +80 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kamaal Farah
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
# Codemods
|
|
2
|
+
|
|
3
|
+
A collection of codemods, runnable as a single CLI.
|
|
4
|
+
|
|
5
|
+
- [Codemods](#codemods)
|
|
6
|
+
- [Available codemods](#available-codemods)
|
|
7
|
+
- [Usage](#usage)
|
|
8
|
+
- [Flags](#flags)
|
|
9
|
+
- [Examples](#examples)
|
|
10
|
+
- [Config](#config)
|
|
11
|
+
- [joi-to-zod](#joi-to-zod)
|
|
12
|
+
- [What it transforms](#what-it-transforms)
|
|
13
|
+
- [Example](#example)
|
|
14
|
+
- [Current constraints](#current-constraints)
|
|
15
|
+
- [Library usage](#library-usage)
|
|
16
|
+
- [Development](#development)
|
|
17
|
+
- [Contributing](#contributing)
|
|
18
|
+
- [License](#license)
|
|
19
|
+
|
|
20
|
+
## Available codemods
|
|
21
|
+
|
|
22
|
+
| Codemod | What it does |
|
|
23
|
+
| ------------ | ---------------------------------------------------------- |
|
|
24
|
+
| `joi-to-zod` | Rewrite supported Joi schema patterns into Zod equivalents |
|
|
25
|
+
|
|
26
|
+
`codemods list` prints the same table from the registry.
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Run it without installing anything:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npx @kamaalio/codemods joi-to-zod ./src
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Or install it globally:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
npm install -g @kamaalio/codemods
|
|
40
|
+
codemods joi-to-zod ./src
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
The CLI takes the codemod name as its command, followed by a path:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
codemods <codemod> [PATH] [FLAGS]
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
`PATH` may be a file or a directory, and defaults to `.`.
|
|
50
|
+
|
|
51
|
+
### Flags
|
|
52
|
+
|
|
53
|
+
| Flag | Default | Description |
|
|
54
|
+
| ---------- | ------- | ------------------------------------------------------------------------------- |
|
|
55
|
+
| `--dry` | `false` | Print what would change without writing files |
|
|
56
|
+
| `--no-log` | `false` | Disable log output |
|
|
57
|
+
| `--config` | — | Path to a JSON config file listing the paths to migrate (see [Config](#config)) |
|
|
58
|
+
|
|
59
|
+
`--config` and `PATH` are mutually exclusive: pass one or the other, not both.
|
|
60
|
+
|
|
61
|
+
Each flag also accepts a short form (`-d`, `-n`, `-c`) and its uppercase alias (`-D`, `-N`, `-C`).
|
|
62
|
+
|
|
63
|
+
### Examples
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Transform the current directory
|
|
67
|
+
codemods joi-to-zod
|
|
68
|
+
|
|
69
|
+
# Transform a specific directory
|
|
70
|
+
codemods joi-to-zod src
|
|
71
|
+
|
|
72
|
+
# Transform a single file
|
|
73
|
+
codemods joi-to-zod src/schemas.ts
|
|
74
|
+
|
|
75
|
+
# Preview changes without writing them
|
|
76
|
+
codemods joi-to-zod src --dry
|
|
77
|
+
|
|
78
|
+
# Run quietly
|
|
79
|
+
codemods joi-to-zod src --no-log
|
|
80
|
+
|
|
81
|
+
# Transform the paths listed in a config file
|
|
82
|
+
codemods joi-to-zod --config joi-migration-phase1.json
|
|
83
|
+
|
|
84
|
+
# List the available codemods
|
|
85
|
+
codemods list
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Config
|
|
89
|
+
|
|
90
|
+
For larger or staged migrations, pass `--config` with a JSON file listing the paths to transform instead of a single `PATH`:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"paths": ["src/controllers"]
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
Each entry in `paths` is transformed the same way a positional `PATH` argument would be. The config file can also set `dry_run` to default that run to dry-run mode, without needing `--dry` on the command line, and `log` to control log output, without needing `--no-log`:
|
|
99
|
+
|
|
100
|
+
```json
|
|
101
|
+
{
|
|
102
|
+
"paths": ["src/controllers"],
|
|
103
|
+
"dry_run": true,
|
|
104
|
+
"log": false
|
|
105
|
+
}
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
Passing both `--dry` and a config `dry_run` at the same time is an error — pick one. The same applies to `--no-log` and a config `log` — pick one.
|
|
109
|
+
|
|
110
|
+
## joi-to-zod
|
|
111
|
+
|
|
112
|
+
Rewrites supported Joi schema patterns into Zod equivalents. It only touches files that use a default Joi import:
|
|
113
|
+
|
|
114
|
+
```ts
|
|
115
|
+
import Joi from 'joi';
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
If a file does not match that shape, it is ignored.
|
|
119
|
+
|
|
120
|
+
### What it transforms
|
|
121
|
+
|
|
122
|
+
The codemod pipeline currently covers these Joi-to-Zod rewrites:
|
|
123
|
+
|
|
124
|
+
- Adds `import { z } from "zod"` when needed, and removes the `joi` import once the file no longer references it.
|
|
125
|
+
|
|
126
|
+
**Structure**
|
|
127
|
+
|
|
128
|
+
- `Joi.object().keys({...})` -> `z.object({...}).strict()`
|
|
129
|
+
- `Joi.array().items(schema)` -> `z.array(schema)`
|
|
130
|
+
- `Joi.alternatives().try(a, b)` -> `z.union([a, b])`
|
|
131
|
+
- `Joi.object().pattern(key, value)` -> `z.record(key, value)`
|
|
132
|
+
- `Joi.binary()` -> `z.instanceof(Buffer)`
|
|
133
|
+
- `schema.concat(other)` -> `z.intersection(schema, other)`
|
|
134
|
+
- `Joi.forbidden()` -> `z.never()`
|
|
135
|
+
- `.valid(...)` -> `z.enum(...)`, or `z.literal(...)` for a non-string primitive
|
|
136
|
+
- `.required()` / its absence -> required and `.optional()` object keys
|
|
137
|
+
|
|
138
|
+
**String formats** are emitted as Zod 4 top-level schemas, replacing the primitive rather
|
|
139
|
+
than chaining onto it, because `z.string().hex()` and friends do not exist in Zod 4. This
|
|
140
|
+
holds wherever the format sits in the chain, so `Joi.string().min(6).hex()` becomes
|
|
141
|
+
`z.hex().min(6)`:
|
|
142
|
+
|
|
143
|
+
- `guid` -> `z.uuid()`, `uri` -> `z.url()`, `email` -> `z.email()`, `domain` -> `z.hostname()`
|
|
144
|
+
- `hex` -> `z.hex()`, `base64` -> `z.base64()`
|
|
145
|
+
- `isoDate` -> `z.iso.datetime()`, `isoDuration` -> `z.iso.duration()`
|
|
146
|
+
|
|
147
|
+
**Dates** become coercing schemas, since Joi accepts ISO strings where `z.date()` would not:
|
|
148
|
+
|
|
149
|
+
- `Joi.date()` -> `z.coerce.date()`; `.iso()` and `.timestamp()` are dropped as redundant
|
|
150
|
+
- `.min('2020-01-01')` -> `.min(new Date('2020-01-01'))`, `.max('now')` -> `.max(new Date())`
|
|
151
|
+
- `.greater` / `.less` -> `.min` / `.max`
|
|
152
|
+
|
|
153
|
+
**Validations that need composed Zod.** Where Joi has no single Zod counterpart, the
|
|
154
|
+
codemod composes one rather than leaving the call behind:
|
|
155
|
+
|
|
156
|
+
- `alphanum` -> `regex(/^[a-zA-Z0-9]+$/)` (both cases, matching Joi), `token` -> `regex(/^\w+$/)`
|
|
157
|
+
- `precision(n)` -> `transform(value => Number(value.toFixed(n)))`, matching Joi's rounding
|
|
158
|
+
- `port()` -> `int().min(0).max(65535)`, `sign('positive')` -> `positive()`
|
|
159
|
+
- `Joi.array().unique()` -> `refine(value => new Set(value).size === value.length)`
|
|
160
|
+
- `Joi.object()` peer rules `and` / `or` / `xor` / `oxor` / `nand` / `with` / `without` -> `refine(...)`
|
|
161
|
+
- `Joi.object().min(n)` / `.max(n)` / `.length(n)` -> `refine` over `Object.keys(value).length`
|
|
162
|
+
- `invalid(...)` / `disallow(...)` -> `refine(value => ![...].includes(value))`
|
|
163
|
+
- `ip()` -> a refine over `z.ipv4()` and `z.ipv6()`
|
|
164
|
+
|
|
165
|
+
**Direct mappings**
|
|
166
|
+
|
|
167
|
+
- `integer` -> `int`, `greater` / `less` -> `gt` / `lt`, `multiple` -> `multipleOf`
|
|
168
|
+
- `description` / `label` -> `describe`, `allow(null)` -> `nullable`, `required(false)` -> `optional`
|
|
169
|
+
- `unknown(true)` / `unknown(false)` -> `passthrough()` / `strict()`
|
|
170
|
+
- `lowercase` / `uppercase` / `case(...)` -> `toLowerCase()` / `toUpperCase()`
|
|
171
|
+
- `pattern(...)` -> `regex(...)`, `failover` -> `catch`, `bool()` -> `boolean()`
|
|
172
|
+
- Annotation-only calls (`meta`, `tag`, `note`, `example`, `raw`, `cast`, `prefs`) are dropped
|
|
173
|
+
|
|
174
|
+
**Conditionals and callbacks.** A Joi conditional lives on the property but needs the whole
|
|
175
|
+
object to evaluate, so it is lifted to an object-level refinement and the property becomes
|
|
176
|
+
optional, with presence enforced by the refinement instead:
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
// before
|
|
180
|
+
detail: Joi.string().when('type', { is: 'a', then: Joi.required(), otherwise: Joi.forbidden() });
|
|
181
|
+
|
|
182
|
+
// after
|
|
183
|
+
detail: z.string().optional();
|
|
184
|
+
// ...on the object:
|
|
185
|
+
.refine(value => !(value['type'] === 'a') || value['detail'] !== undefined, { path: ['detail'] })
|
|
186
|
+
.refine(value => (value['type'] === 'a') || value['detail'] === undefined, { path: ['detail'] })
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
- `.when()` handles `is` as a literal, a `Joi.ref(...)`, or a schema, and `then` / `otherwise`
|
|
190
|
+
as `required()`, `optional()`, `forbidden()`, or a full schema. A bare schema `is` also
|
|
191
|
+
matches an absent key, because a Joi schema is optional unless it says otherwise.
|
|
192
|
+
- `.assert(subject, schema, message?)` -> a refinement comparing against the referenced key,
|
|
193
|
+
or parsing the subject against the schema.
|
|
194
|
+
- `.custom(fn)` -> `.transform(fn)`. When the callback uses Joi's `helpers`, it is kept
|
|
195
|
+
verbatim and handed a shim mapping `helpers.error` / `helpers.message` onto Zod's `ctx`.
|
|
196
|
+
|
|
197
|
+
**Flagged for manual migration.** What is left has no mechanical equivalent, so the codemod
|
|
198
|
+
leaves a `TODO(joi-to-zod)` comment naming the Zod construct to reach for:
|
|
199
|
+
|
|
200
|
+
- `.when(...)` using `switch`, `not`, or `break`, or applied outside an object property
|
|
201
|
+
- `.custom(...)` whose callback needs helpers beyond `error` and `message`, or which is
|
|
202
|
+
followed by calls that a transform would remove (`z.string().transform(f).min` does not exist)
|
|
203
|
+
- `.assert(...)` whose subject is not a plain reference
|
|
204
|
+
|
|
205
|
+
### Example
|
|
206
|
+
|
|
207
|
+
Input:
|
|
208
|
+
|
|
209
|
+
```ts
|
|
210
|
+
import Joi from 'joi';
|
|
211
|
+
|
|
212
|
+
enum MemberStatus {
|
|
213
|
+
Active = 'active',
|
|
214
|
+
Inactive = 'inactive',
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export const memberSchema = Joi.object().keys({
|
|
218
|
+
id: Joi.alternatives().try(Joi.string(), Joi.number()).required(),
|
|
219
|
+
status: Joi.string()
|
|
220
|
+
.valid(...Object.values(MemberStatus))
|
|
221
|
+
.required(),
|
|
222
|
+
website: Joi.string().uri(),
|
|
223
|
+
metadata: Joi.object().pattern(Joi.string(), Joi.number()),
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
Output:
|
|
228
|
+
|
|
229
|
+
```ts
|
|
230
|
+
import { z } from 'zod';
|
|
231
|
+
|
|
232
|
+
enum MemberStatus {
|
|
233
|
+
Active = 'active',
|
|
234
|
+
Inactive = 'inactive',
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
export const memberSchema = z
|
|
238
|
+
.object({
|
|
239
|
+
id: z.union([z.string(), z.number()]),
|
|
240
|
+
status: z.enum(MemberStatus),
|
|
241
|
+
website: z.url().optional(),
|
|
242
|
+
metadata: z.record(z.string(), z.number()).optional(),
|
|
243
|
+
})
|
|
244
|
+
.strict();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
The codemod does not format its output. Run your formatter over the changed files afterwards.
|
|
248
|
+
|
|
249
|
+
### Current constraints
|
|
250
|
+
|
|
251
|
+
- The codemod only targets files with a default `import Joi from 'joi'`.
|
|
252
|
+
- The AST language is configured as TypeScript, so this project is best suited to TypeScript-style source files.
|
|
253
|
+
- Coverage is driven by the rules and tests in [`src/codemods/joi-to-zod`](./src/codemods/joi-to-zod) and [`test/codemods/joi-to-zod`](./test/codemods/joi-to-zod). Patterns outside those rules may remain unchanged.
|
|
254
|
+
- `precision(n)` reproduces Joi's default rounding behaviour. A source schema validated with `convert: false` rejects imprecise input instead of rounding it, and the generated Zod will not match that.
|
|
255
|
+
- [`example/`](./example) is a live before/after fixture: CI type-checks, lints, and runs its behavioural tests against the Joi source, transforms it in place, then runs all three again against the generated Zod.
|
|
256
|
+
- The codemod migrates schema declarations. Consumers of Joi's `schema.validate()` result shape and framework-specific schema contracts, such as Hapi route validation, require a manual migration to Zod's parsing APIs.
|
|
257
|
+
- The tool is a codemod, not a semantic migration assistant. Review the output before committing.
|
|
258
|
+
|
|
259
|
+
## Library usage
|
|
260
|
+
|
|
261
|
+
The package has a small programmatic API for embedding the Joi-to-Zod migration in your own tooling. It does not write files unless you use the CLI entry point; the transformer functions operate on source strings.
|
|
262
|
+
|
|
263
|
+
### Transform a source string
|
|
264
|
+
|
|
265
|
+
Use the default export when you want the transformed source. Pass a filename when available so custom tooling can retain it in transformation metadata.
|
|
266
|
+
|
|
267
|
+
```ts
|
|
268
|
+
import joiToZod from '@kamaalio/codemods';
|
|
269
|
+
|
|
270
|
+
const source = "import Joi from 'joi';\n\nexport const id = Joi.string().required();\n";
|
|
271
|
+
const transformed = await joiToZod(source, 'src/schema.ts');
|
|
272
|
+
|
|
273
|
+
// import { z } from "zod";
|
|
274
|
+
//
|
|
275
|
+
// export const id = z.string();
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
Files without a default `Joi` import are returned unchanged.
|
|
279
|
+
|
|
280
|
+
### Inspect transformation details
|
|
281
|
+
|
|
282
|
+
Use `joiToZodTransformer` when you need the AST, number of edits, or transformation history in addition to the generated source.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
import { joiToZodTransformer } from '@kamaalio/codemods';
|
|
286
|
+
|
|
287
|
+
const source = "import Joi from 'joi';\n\nexport const id = Joi.string().required();\n";
|
|
288
|
+
const result = await joiToZodTransformer(source, 'src/schema.ts');
|
|
289
|
+
|
|
290
|
+
console.log(result.report.changesApplied);
|
|
291
|
+
const transformed = result.ast.root().text();
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
### Integrate with a codemod runner
|
|
295
|
+
|
|
296
|
+
`JOI_TO_ZOD_CODEMOD` is the complete codemod definition, including its name, supported language, and string transformer. `JOI_TO_ZOD_LANGUAGE` is the corresponding ast-grep language constant.
|
|
297
|
+
|
|
298
|
+
```ts
|
|
299
|
+
import { JOI_TO_ZOD_CODEMOD, JOI_TO_ZOD_LANGUAGE } from '@kamaalio/codemods';
|
|
300
|
+
|
|
301
|
+
const source = "import Joi from 'joi';\n\nexport const id = Joi.string().required();\n";
|
|
302
|
+
const transformed = await JOI_TO_ZOD_CODEMOD.transformer(source, 'src/schema.ts');
|
|
303
|
+
console.log(JOI_TO_ZOD_LANGUAGE, transformed);
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
### Invoke the CLI from JavaScript
|
|
307
|
+
|
|
308
|
+
`run` accepts the same arguments as the `codemods` executable. It logs to the console and reports command failures through `process.exitCode`.
|
|
309
|
+
|
|
310
|
+
```ts
|
|
311
|
+
import { run } from '@kamaalio/codemods';
|
|
312
|
+
|
|
313
|
+
await run(['joi-to-zod', 'src', '--dry']);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## Development
|
|
317
|
+
|
|
318
|
+
Use `yarn` on Node.js `22` (see [`.nvmrc`](./.nvmrc)). Yarn 4 is activated through Corepack:
|
|
319
|
+
|
|
320
|
+
```bash
|
|
321
|
+
corepack enable
|
|
322
|
+
yarn install
|
|
323
|
+
yarn build
|
|
324
|
+
yarn test
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
Every task lives in `package.json` — there is no task runner to install:
|
|
328
|
+
|
|
329
|
+
| Script | What it does |
|
|
330
|
+
| ------------------------- | ---------------------------------------------------- |
|
|
331
|
+
| `yarn bootstrap` | Install dependencies from the lockfile |
|
|
332
|
+
| `yarn build` | Compile `src/` to `dist/` with `tsc` |
|
|
333
|
+
| `yarn clean:build` | Remove `dist/` and rebuild |
|
|
334
|
+
| `yarn test` | Run the test suite once |
|
|
335
|
+
| `yarn test:watch` | Run the test suite in watch mode |
|
|
336
|
+
| `yarn test:cov` | Run the test suite with coverage |
|
|
337
|
+
| `yarn test:u` | Update snapshots |
|
|
338
|
+
| `yarn test:example` | Run the `example/` behavioural tests |
|
|
339
|
+
| `yarn type-check` | Type-check `src/` |
|
|
340
|
+
| `yarn type-check:test` | Type-check tests and scripts |
|
|
341
|
+
| `yarn type-check:example` | Type-check `example/` |
|
|
342
|
+
| `yarn lint` | Lint with rslint |
|
|
343
|
+
| `yarn format` | Format with prettier |
|
|
344
|
+
| `yarn format:check` | Check formatting |
|
|
345
|
+
| `yarn quality` | Lint, format check, and both type checks |
|
|
346
|
+
| `yarn preview` | Run the CLI against `test/resources` in dry-run mode |
|
|
347
|
+
| `yarn transform:example` | Run the CLI against `example/` |
|
|
348
|
+
| `yarn new:codemod <name>` | Scaffold a new codemod |
|
|
349
|
+
| `yarn release <version>` | Publish to npm |
|
|
350
|
+
|
|
351
|
+
The release workflow uses npm trusted publishing through GitHub Actions. To
|
|
352
|
+
bootstrap the first release, add a write-capable `NPM_TOKEN` repository secret
|
|
353
|
+
temporarily. The release script passes it only to Yarn's npm authentication.
|
|
354
|
+
After the package exists, configure `kamaal111/codemods` and `release.yml` as
|
|
355
|
+
its trusted publisher in npm, then remove the secret; future releases use OIDC.
|
|
356
|
+
|
|
357
|
+
## Contributing
|
|
358
|
+
|
|
359
|
+
Adding a codemod takes about ten minutes. See [CONTRIBUTING.md](./CONTRIBUTING.md).
|
|
360
|
+
|
|
361
|
+
## License
|
|
362
|
+
|
|
363
|
+
MIT. See [LICENSE](./LICENSE).
|
package/bin/dev.cmd
ADDED
package/bin/dev.mjs
ADDED
package/bin/run.cmd
ADDED
package/bin/run.mjs
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@kamaalio/codemods",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "A collection of codemods, runnable as a single CLI.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"codemod",
|
|
7
|
+
"ast-grep",
|
|
8
|
+
"joi",
|
|
9
|
+
"zod",
|
|
10
|
+
"migration"
|
|
11
|
+
],
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"author": "Kamaal Farah",
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/kamaal111/codemods.git"
|
|
17
|
+
},
|
|
18
|
+
"type": "module",
|
|
19
|
+
"bin": "./bin/run.mjs",
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"bin"
|
|
25
|
+
],
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
},
|
|
29
|
+
"engines": {
|
|
30
|
+
"node": ">=22.0.0"
|
|
31
|
+
},
|
|
32
|
+
"packageManager": "yarn@4.18.0",
|
|
33
|
+
"scripts": {
|
|
34
|
+
"bootstrap": "yarn install --immutable",
|
|
35
|
+
"build": "yarn run compile",
|
|
36
|
+
"compile": "tsc",
|
|
37
|
+
"clean:build": "rm -rf dist tsconfig.tsbuildinfo && yarn run build",
|
|
38
|
+
"test": "rstest run",
|
|
39
|
+
"test:watch": "rstest",
|
|
40
|
+
"test:cov": "rstest run --coverage",
|
|
41
|
+
"test:u": "rstest run --update",
|
|
42
|
+
"test:example": "rstest run --config example/rstest.config.ts example/",
|
|
43
|
+
"type-check": "tsc --noEmit",
|
|
44
|
+
"type-check:test": "tsc --noEmit --project tsconfig.test.json",
|
|
45
|
+
"type-check:example": "tsc --noEmit --project example/tsconfig.json",
|
|
46
|
+
"lint": "rslint",
|
|
47
|
+
"lint:example": "rslint example/",
|
|
48
|
+
"format": "prettier --write .",
|
|
49
|
+
"format:check": "prettier --check .",
|
|
50
|
+
"quality": "yarn run lint && yarn run format:check && yarn run type-check && yarn run type-check:test && yarn run check:example-snapshot",
|
|
51
|
+
"preview": "node ./bin/dev.mjs joi-to-zod test/resources --dry",
|
|
52
|
+
"transform:example": "node ./scripts/cli-entry.ts joi-to-zod example",
|
|
53
|
+
"generate:example-snapshot": "node ./scripts/generate-example-snapshot.ts --write",
|
|
54
|
+
"check:example-snapshot": "node ./scripts/generate-example-snapshot.ts --check",
|
|
55
|
+
"new:codemod": "node ./scripts/new-codemod.ts",
|
|
56
|
+
"release": "node ./scripts/publish.ts",
|
|
57
|
+
"prepare": "husky"
|
|
58
|
+
},
|
|
59
|
+
"dependencies": {
|
|
60
|
+
"@ast-grep/napi": "^0.45.3",
|
|
61
|
+
"fast-glob": "^3.3.3",
|
|
62
|
+
"neverthrow": "^8.2.0",
|
|
63
|
+
"zod": "^4.5.4"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@rslint/core": "^0.9.1",
|
|
67
|
+
"@rstest/core": "^0.11.12",
|
|
68
|
+
"@rstest/coverage-istanbul": "0.11.12",
|
|
69
|
+
"@types/node": "^26.4.1",
|
|
70
|
+
"husky": "^9.1.7",
|
|
71
|
+
"joi": "^18.2.8",
|
|
72
|
+
"lint-staged": "^17.5.0",
|
|
73
|
+
"prettier": "^3.9.6",
|
|
74
|
+
"typescript": "^7.0.2"
|
|
75
|
+
},
|
|
76
|
+
"lint-staged": {
|
|
77
|
+
"*.{js,mjs,cjs,ts}": "yarn lint",
|
|
78
|
+
"*": "prettier --write --ignore-unknown"
|
|
79
|
+
}
|
|
80
|
+
}
|