@kamaalio/codemod-kit 0.0.16 → 0.0.18

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
@@ -103,6 +103,85 @@ const edits = findAndReplaceEdits(
103
103
  const result = ast.root().commitEdits(edits);
104
104
  ```
105
105
 
106
+ ### `findAndReplaceConfig(content, lang, config)`
107
+
108
+ A utility function for applying multiple find-and-replace operations sequentially on AST content.
109
+
110
+ - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
111
+ - `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.
113
+
114
+ Returns the final transformed content as a string after applying all transformations.
115
+
116
+ ```typescript
117
+ import { findAndReplaceConfig } from '@kamaalio/codemod-kit';
118
+ import { parseAsync } from '@ast-grep/napi';
119
+
120
+ const code = `
121
+ function oldFunction() {
122
+ return "hello";
123
+ }
124
+ const value = 42;
125
+ `;
126
+
127
+ const ast = await parseAsync('javascript', code);
128
+ const result = await findAndReplaceConfig(ast, 'javascript', [
129
+ {
130
+ rule: { pattern: 'function oldFunction() { $$$ }' },
131
+ transformer: node => 'function newFunction() { return "hello world"; }',
132
+ },
133
+ {
134
+ rule: { pattern: 'const value = $VAL' },
135
+ transformer: node => 'const value = 100',
136
+ },
137
+ ]);
138
+ ```
139
+
140
+ ### `findAndReplaceConfigModifications(modifications, config)`
141
+
142
+ A utility function for applying multiple find-and-replace operations sequentially on a `Modifications` object.
143
+
144
+ - `modifications`: A `Modifications` object containing the AST, language, and transformation history.
145
+ - `config`: An array of objects containing `rule` and `transformer` pairs to apply sequentially.
146
+
147
+ Returns a `Promise<Modifications>` with the updated AST, accumulated edit count, and transformation history.
148
+
149
+ ```typescript
150
+ import { findAndReplaceConfigModifications } from '@kamaalio/codemod-kit';
151
+ import { parseAsync } from '@ast-grep/napi';
152
+
153
+ const code = `
154
+ function oldFunction() {
155
+ return "hello";
156
+ }
157
+ const value = 42;
158
+ `;
159
+
160
+ const ast = await parseAsync('javascript', code);
161
+ const initialModifications = {
162
+ ast,
163
+ lang: 'javascript' as const,
164
+ filename: 'example.js',
165
+ report: { changesApplied: 0 },
166
+ history: [ast],
167
+ };
168
+
169
+ const result = await findAndReplaceConfigModifications(initialModifications, [
170
+ {
171
+ rule: { pattern: 'function oldFunction() { $$$ }' },
172
+ transformer: node => 'function newFunction() { return "hello world"; }',
173
+ },
174
+ {
175
+ rule: { pattern: 'const value = $VAL' },
176
+ transformer: node => 'const value = 100',
177
+ },
178
+ ]);
179
+
180
+ // result.ast contains the final transformed AST
181
+ // result.report.changesApplied contains the total number of edits applied
182
+ // result.history contains the transformation history
183
+ ```
184
+
106
185
  ### `Codemod`
107
186
 
108
187
  A codemod is defined by the `Codemod` type:
@@ -1,2 +1,2 @@
1
- export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits } from './utils.js';
1
+ export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, findAndReplaceConfig, findAndReplaceConfigModifications, } from './utils.js';
2
2
  export type { Codemod, Modifications } from './types.js';
@@ -1,6 +1,7 @@
1
1
  import { type Result } from 'neverthrow';
2
2
  import { type Rule, type Edit, type SgNode, type SgRoot } from '@ast-grep/napi';
3
3
  import type { Kinds, TypesMap } from '@ast-grep/napi/types/staticTypes.js';
4
+ import type { NapiLang } from '@ast-grep/napi/types/lang.js';
4
5
  import type { Codemod, Modifications } from './types.js';
5
6
  import type { Optional } from '../utils/type-utils.js';
6
7
  type RunCodemodHooks<C extends Codemod> = {
@@ -21,6 +22,14 @@ export declare function runCodemod<C extends Codemod>(codemod: C, transformation
21
22
  hasChanges: boolean;
22
23
  content: string;
23
24
  }, Error>>>;
25
+ export declare function findAndReplaceConfigModifications(modifications: Modifications, config: Array<{
26
+ rule: Rule<TypesMap>;
27
+ transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>;
28
+ }>): Promise<Modifications>;
29
+ export declare function findAndReplaceConfig(content: SgRoot<TypesMap>, lang: NapiLang, config: Array<{
30
+ rule: Rule<TypesMap>;
31
+ transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>;
32
+ }>): Promise<string>;
24
33
  export declare function findAndReplaceEdits(content: SgRoot<TypesMap>, rule: Rule<TypesMap>, transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>): Array<Edit>;
25
34
  export declare function findAndReplace(content: SgRoot<TypesMap>, rule: Rule<TypesMap>, transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>): string;
26
35
  export declare function commitEditModifications(edits: Array<Edit>, modifications: Modifications): Promise<Modifications>;
package/dist/index.cjs CHANGED
@@ -34,10 +34,12 @@ var __webpack_exports__ = {};
34
34
  __webpack_require__.r(__webpack_exports__);
35
35
  __webpack_require__.d(__webpack_exports__, {
36
36
  commitEditModifications: ()=>commitEditModifications,
37
+ runCodemods: ()=>runCodemods,
37
38
  runCodemod: ()=>runCodemod,
38
39
  findAndReplace: ()=>findAndReplace,
40
+ findAndReplaceConfigModifications: ()=>findAndReplaceConfigModifications,
39
41
  findAndReplaceEdits: ()=>findAndReplaceEdits,
40
- runCodemods: ()=>runCodemods
42
+ findAndReplaceConfig: ()=>findAndReplaceConfig
41
43
  });
42
44
  const external_node_path_namespaceObject = require("node:path");
43
45
  var external_node_path_default = /*#__PURE__*/ __webpack_require__.n(external_node_path_namespaceObject);
@@ -129,6 +131,34 @@ async function runCodemod(codemod, transformationPath, options) {
129
131
  }
130
132
  }));
131
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
+ }
144
+ async function findAndReplaceConfigEdits(content, lang, config) {
145
+ let currentContent = content;
146
+ const editsAndContent = [];
147
+ for (const { rule, transformer } of config){
148
+ const edits = findAndReplaceEdits(currentContent, rule, transformer);
149
+ const updatedContent = currentContent.root().commitEdits(edits);
150
+ editsAndContent.push({
151
+ content: currentContent,
152
+ edits
153
+ });
154
+ currentContent = await (0, napi_namespaceObject.parseAsync)(lang, updatedContent);
155
+ }
156
+ return editsAndContent;
157
+ }
158
+ async function findAndReplaceConfig(content, lang, config) {
159
+ const edits = await findAndReplaceConfigEdits(content, lang, config);
160
+ return edits.at(-1)?.content.root().text() ?? content.root().text();
161
+ }
132
162
  function findAndReplaceEdits(content, rule, transformer) {
133
163
  const nodes = content.root().findAll({
134
164
  rule
@@ -179,12 +209,16 @@ function defaultedHooks(hooks) {
179
209
  }
180
210
  exports.commitEditModifications = __webpack_exports__.commitEditModifications;
181
211
  exports.findAndReplace = __webpack_exports__.findAndReplace;
212
+ exports.findAndReplaceConfig = __webpack_exports__.findAndReplaceConfig;
213
+ exports.findAndReplaceConfigModifications = __webpack_exports__.findAndReplaceConfigModifications;
182
214
  exports.findAndReplaceEdits = __webpack_exports__.findAndReplaceEdits;
183
215
  exports.runCodemod = __webpack_exports__.runCodemod;
184
216
  exports.runCodemods = __webpack_exports__.runCodemods;
185
217
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
186
218
  "commitEditModifications",
187
219
  "findAndReplace",
220
+ "findAndReplaceConfig",
221
+ "findAndReplaceConfigModifications",
188
222
  "findAndReplaceEdits",
189
223
  "runCodemod",
190
224
  "runCodemods"
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { runCodemods, runCodemod, commitEditModifications, findAndReplace, findAndReplaceEdits, 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,34 @@ 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
+ }
98
+ async function findAndReplaceConfigEdits(content, lang, config) {
99
+ let currentContent = content;
100
+ const editsAndContent = [];
101
+ for (const { rule, transformer } of config){
102
+ const edits = findAndReplaceEdits(currentContent, rule, transformer);
103
+ const updatedContent = currentContent.root().commitEdits(edits);
104
+ editsAndContent.push({
105
+ content: currentContent,
106
+ edits
107
+ });
108
+ currentContent = await parseAsync(lang, updatedContent);
109
+ }
110
+ return editsAndContent;
111
+ }
112
+ async function findAndReplaceConfig(content, lang, config) {
113
+ const edits = await findAndReplaceConfigEdits(content, lang, config);
114
+ return edits.at(-1)?.content.root().text() ?? content.root().text();
115
+ }
88
116
  function findAndReplaceEdits(content, rule, transformer) {
89
117
  const nodes = content.root().findAll({
90
118
  rule
@@ -133,4 +161,4 @@ function defaultedHooks(hooks) {
133
161
  preCodemodRun
134
162
  };
135
163
  }
136
- export { commitEditModifications, findAndReplace, findAndReplaceEdits, runCodemod, runCodemods };
164
+ 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.16",
3
+ "version": "0.0.18",
4
4
  "type": "module",
5
5
  "author": "Kamaal Farah",
6
6
  "license": "MIT",