@kamaalio/codemod-kit 0.0.17 → 0.0.19

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 CHANGED
@@ -50,7 +50,7 @@ A utility function for finding and replacing AST nodes based on a rule.
50
50
 
51
51
  - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
52
52
  - `rule`: A `Rule<TypesMap>` object defining the pattern to search for.
53
- - `transformer`: A function that takes a matched node and returns an optional string replacement.
53
+ - `transformer`: A function that takes a matched node and returns an optional string replacement, or a string for direct replacement.
54
54
 
55
55
  Returns the transformed content as a string with all matching nodes replaced.
56
56
 
@@ -65,11 +65,20 @@ function oldFunction() {
65
65
  `;
66
66
 
67
67
  const ast = await parseAsync('javascript', code);
68
- const result = findAndReplace(
68
+
69
+ // Using a function transformer
70
+ const result1 = findAndReplace(
69
71
  ast,
70
72
  { pattern: 'function oldFunction() { $$$ }' },
71
73
  node => 'function newFunction() { return "hello world"; }',
72
74
  );
75
+
76
+ // Using a string transformer
77
+ const result2 = findAndReplace(
78
+ ast,
79
+ { pattern: 'function oldFunction() { $$$ }' },
80
+ 'function newFunction() { return "hello world"; }',
81
+ );
73
82
  ```
74
83
 
75
84
  ### `findAndReplaceEdits(content, rule, transformer)`
@@ -78,7 +87,7 @@ A utility function for finding AST nodes and generating edit operations without
78
87
 
79
88
  - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
80
89
  - `rule`: A `Rule<TypesMap>` object defining the pattern to search for.
81
- - `transformer`: A function that takes a matched node and returns an optional string replacement.
90
+ - `transformer`: A function that takes a matched node and returns an optional string replacement, or a string for direct replacement.
82
91
 
83
92
  Returns an array of `Edit` objects that can be committed later using `commitEdits()`.
84
93
 
@@ -93,14 +102,23 @@ function oldFunction() {
93
102
  `;
94
103
 
95
104
  const ast = await parseAsync('javascript', code);
96
- const edits = findAndReplaceEdits(
105
+
106
+ // Using a function transformer
107
+ const edits1 = findAndReplaceEdits(
97
108
  ast,
98
109
  { pattern: 'function oldFunction() { $$$ }' },
99
110
  node => 'function newFunction() { return "hello world"; }',
100
111
  );
101
112
 
113
+ // Using a string transformer
114
+ const edits2 = findAndReplaceEdits(
115
+ ast,
116
+ { pattern: 'function oldFunction() { $$$ }' },
117
+ 'function newFunction() { return "hello world"; }',
118
+ );
119
+
102
120
  // Commit the edits later
103
- const result = ast.root().commitEdits(edits);
121
+ const result = ast.root().commitEdits(edits1);
104
122
  ```
105
123
 
106
124
  ### `findAndReplaceConfig(content, lang, config)`
@@ -109,7 +127,7 @@ A utility function for applying multiple find-and-replace operations sequentiall
109
127
 
110
128
  - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
111
129
  - `lang`: A `NapiLang` value specifying the language for re-parsing after each transformation.
112
- - `config`: An array of objects containing `rule` and `transformer` pairs to apply sequentially.
130
+ - `config`: An array of objects containing `rule` and `transformer` pairs to apply sequentially. The `transformer` can be either a function or a string.
113
131
 
114
132
  Returns the final transformed content as a string after applying all transformations.
115
133
 
@@ -132,41 +150,54 @@ const result = await findAndReplaceConfig(ast, 'javascript', [
132
150
  },
133
151
  {
134
152
  rule: { pattern: 'const value = $VAL' },
135
- transformer: node => 'const value = 100',
153
+ transformer: 'const value = 100', // String transformer
136
154
  },
137
155
  ]);
138
156
  ```
139
157
 
140
- ### `findAndReplaceConfigEdits(content, lang, config)`
158
+ ### `findAndReplaceConfigModifications(modifications, config)`
141
159
 
142
- A utility function for applying multiple find-and-replace operations sequentially and returning the edit history.
160
+ A utility function for applying multiple find-and-replace operations sequentially on a `Modifications` object.
143
161
 
144
- - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
145
- - `lang`: A `NapiLang` value specifying the language for re-parsing after each transformation.
146
- - `config`: An array of objects containing `rule` and `transformer` pairs to apply sequentially.
162
+ - `modifications`: A `Modifications` object containing the AST, language, and transformation history.
163
+ - `config`: An array of objects containing `rule` and `transformer` pairs to apply sequentially. The `transformer` can be either a function or a string.
147
164
 
148
- Returns an array of objects containing the AST content and edits for each transformation step.
165
+ Returns a `Promise<Modifications>` with the updated AST, accumulated edit count, and transformation history.
149
166
 
150
167
  ```typescript
151
- import { findAndReplaceConfigEdits } from '@kamaalio/codemod-kit';
168
+ import { findAndReplaceConfigModifications } from '@kamaalio/codemod-kit';
152
169
  import { parseAsync } from '@ast-grep/napi';
153
170
 
154
171
  const code = `
155
172
  function oldFunction() {
156
173
  return "hello";
157
174
  }
175
+ const value = 42;
158
176
  `;
159
177
 
160
178
  const ast = await parseAsync('javascript', code);
161
- const editsHistory = await findAndReplaceConfigEdits(ast, 'javascript', [
179
+ const initialModifications = {
180
+ ast,
181
+ lang: 'javascript' as const,
182
+ filename: 'example.js',
183
+ report: { changesApplied: 0 },
184
+ history: [ast],
185
+ };
186
+
187
+ const result = await findAndReplaceConfigModifications(initialModifications, [
162
188
  {
163
189
  rule: { pattern: 'function oldFunction() { $$$ }' },
164
190
  transformer: node => 'function newFunction() { return "hello world"; }',
165
191
  },
192
+ {
193
+ rule: { pattern: 'const value = $VAL' },
194
+ transformer: 'const value = 100', // String transformer
195
+ },
166
196
  ]);
167
197
 
168
- // Each element contains { content: SgRoot, edits: Edit[] }
169
- // Useful for tracking transformation history or debugging
198
+ // result.ast contains the final transformed AST
199
+ // result.report.changesApplied contains the total number of edits applied
200
+ // result.history contains the transformation history
170
201
  ```
171
202
 
172
203
  ### `Codemod`
@@ -1,2 +1,2 @@
1
- export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, findAndReplaceConfig, findAndReplaceConfigEdits, } from './utils.js';
1
+ export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, findAndReplaceConfig, findAndReplaceConfigModifications, } from './utils.js';
2
2
  export type { Codemod, Modifications } from './types.js';
@@ -14,6 +14,10 @@ type RunCodemodOptions<C extends Codemod> = {
14
14
  log?: boolean;
15
15
  dry?: boolean;
16
16
  };
17
+ type FindAndReplaceConfig = {
18
+ rule: Rule<TypesMap>;
19
+ transformer: ((node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>) | string;
20
+ };
17
21
  export declare function runCodemods<C extends Codemod>(codemods: Array<C>, transformationPath: string, options?: RunCodemodOptions<C>): Promise<Record<string, Array<Result<{
18
22
  hasChanges: boolean;
19
23
  content: string;
@@ -22,18 +26,9 @@ export declare function runCodemod<C extends Codemod>(codemod: C, transformation
22
26
  hasChanges: boolean;
23
27
  content: string;
24
28
  }, Error>>>;
25
- export declare function findAndReplaceConfigEdits(content: SgRoot<TypesMap>, lang: NapiLang, config: Array<{
26
- rule: Rule<TypesMap>;
27
- transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>;
28
- }>): Promise<Array<{
29
- content: SgRoot<TypesMap>;
30
- edits: Array<Edit>;
31
- }>>;
32
- export declare function findAndReplaceConfig(content: SgRoot<TypesMap>, lang: NapiLang, config: Array<{
33
- rule: Rule<TypesMap>;
34
- transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>;
35
- }>): Promise<string>;
36
- export declare function findAndReplaceEdits(content: SgRoot<TypesMap>, rule: Rule<TypesMap>, transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>): Array<Edit>;
37
- export declare function findAndReplace(content: SgRoot<TypesMap>, rule: Rule<TypesMap>, transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>): string;
29
+ export declare function findAndReplaceConfigModifications(modifications: Modifications, config: Array<FindAndReplaceConfig>): Promise<Modifications>;
30
+ export declare function findAndReplaceConfig(content: SgRoot<TypesMap>, lang: NapiLang, config: Array<FindAndReplaceConfig>): Promise<string>;
31
+ export declare function findAndReplaceEdits(content: SgRoot<TypesMap>, rule: FindAndReplaceConfig['rule'], transformer: FindAndReplaceConfig['transformer']): Array<Edit>;
32
+ export declare function findAndReplace(content: SgRoot<TypesMap>, rule: FindAndReplaceConfig['rule'], transformer: FindAndReplaceConfig['transformer']): string;
38
33
  export declare function commitEditModifications(edits: Array<Edit>, modifications: Modifications): Promise<Modifications>;
39
34
  export {};
package/dist/index.cjs CHANGED
@@ -34,11 +34,11 @@ var __webpack_exports__ = {};
34
34
  __webpack_require__.r(__webpack_exports__);
35
35
  __webpack_require__.d(__webpack_exports__, {
36
36
  commitEditModifications: ()=>commitEditModifications,
37
- findAndReplaceConfigEdits: ()=>findAndReplaceConfigEdits,
37
+ runCodemods: ()=>runCodemods,
38
38
  runCodemod: ()=>runCodemod,
39
39
  findAndReplace: ()=>findAndReplace,
40
+ findAndReplaceConfigModifications: ()=>findAndReplaceConfigModifications,
40
41
  findAndReplaceEdits: ()=>findAndReplaceEdits,
41
- runCodemods: ()=>runCodemods,
42
42
  findAndReplaceConfig: ()=>findAndReplaceConfig
43
43
  });
44
44
  const external_node_path_namespaceObject = require("node:path");
@@ -131,6 +131,16 @@ async function runCodemod(codemod, transformationPath, options) {
131
131
  }
132
132
  }));
133
133
  }
134
+ async function findAndReplaceConfigModifications(modifications, config) {
135
+ let currentModifications = {
136
+ ...modifications
137
+ };
138
+ for (const { rule, transformer } of config){
139
+ const edits = findAndReplaceEdits(currentModifications.ast, rule, transformer);
140
+ currentModifications = await commitEditModifications(edits, currentModifications);
141
+ }
142
+ return currentModifications;
143
+ }
134
144
  async function findAndReplaceConfigEdits(content, lang, config) {
135
145
  let currentContent = content;
136
146
  const editsAndContent = [];
@@ -154,8 +164,9 @@ function findAndReplaceEdits(content, rule, transformer) {
154
164
  rule
155
165
  });
156
166
  return kamaal_namespaceObject.arrays.compactMap(nodes, (node)=>{
157
- const transformed = transformer(node);
167
+ const transformed = 'string' == typeof transformer ? transformer : transformer(node);
158
168
  if (null == transformed) return null;
169
+ if (transformed === node.text()) return null;
159
170
  return node.replace(transformed);
160
171
  });
161
172
  }
@@ -200,7 +211,7 @@ function defaultedHooks(hooks) {
200
211
  exports.commitEditModifications = __webpack_exports__.commitEditModifications;
201
212
  exports.findAndReplace = __webpack_exports__.findAndReplace;
202
213
  exports.findAndReplaceConfig = __webpack_exports__.findAndReplaceConfig;
203
- exports.findAndReplaceConfigEdits = __webpack_exports__.findAndReplaceConfigEdits;
214
+ exports.findAndReplaceConfigModifications = __webpack_exports__.findAndReplaceConfigModifications;
204
215
  exports.findAndReplaceEdits = __webpack_exports__.findAndReplaceEdits;
205
216
  exports.runCodemod = __webpack_exports__.runCodemod;
206
217
  exports.runCodemods = __webpack_exports__.runCodemods;
@@ -208,7 +219,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
208
219
  "commitEditModifications",
209
220
  "findAndReplace",
210
221
  "findAndReplaceConfig",
211
- "findAndReplaceConfigEdits",
222
+ "findAndReplaceConfigModifications",
212
223
  "findAndReplaceEdits",
213
224
  "runCodemod",
214
225
  "runCodemods"
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, findAndReplaceConfig, findAndReplaceConfigEdits, type Codemod, type Modifications, } from './codemods/index.js';
1
+ export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, findAndReplaceConfig, findAndReplaceConfigModifications, type Codemod, type Modifications, } from './codemods/index.js';
package/dist/index.js CHANGED
@@ -85,6 +85,16 @@ async function runCodemod(codemod, transformationPath, options) {
85
85
  }
86
86
  }));
87
87
  }
88
+ async function findAndReplaceConfigModifications(modifications, config) {
89
+ let currentModifications = {
90
+ ...modifications
91
+ };
92
+ for (const { rule, transformer } of config){
93
+ const edits = findAndReplaceEdits(currentModifications.ast, rule, transformer);
94
+ currentModifications = await commitEditModifications(edits, currentModifications);
95
+ }
96
+ return currentModifications;
97
+ }
88
98
  async function findAndReplaceConfigEdits(content, lang, config) {
89
99
  let currentContent = content;
90
100
  const editsAndContent = [];
@@ -108,8 +118,9 @@ function findAndReplaceEdits(content, rule, transformer) {
108
118
  rule
109
119
  });
110
120
  return arrays.compactMap(nodes, (node)=>{
111
- const transformed = transformer(node);
121
+ const transformed = 'string' == typeof transformer ? transformer : transformer(node);
112
122
  if (null == transformed) return null;
123
+ if (transformed === node.text()) return null;
113
124
  return node.replace(transformed);
114
125
  });
115
126
  }
@@ -151,4 +162,4 @@ function defaultedHooks(hooks) {
151
162
  preCodemodRun
152
163
  };
153
164
  }
154
- export { commitEditModifications, findAndReplace, findAndReplaceConfig, findAndReplaceConfigEdits, findAndReplaceEdits, runCodemod, runCodemods };
165
+ export { commitEditModifications, findAndReplace, findAndReplaceConfig, findAndReplaceConfigModifications, findAndReplaceEdits, runCodemod, runCodemods };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kamaalio/codemod-kit",
3
- "version": "0.0.17",
3
+ "version": "0.0.19",
4
4
  "type": "module",
5
5
  "author": "Kamaal Farah",
6
6
  "license": "MIT",