@kamaalio/codemod-kit 0.0.14 → 0.0.15

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
@@ -44,6 +44,34 @@ Runs a single codemod.
44
44
  - `globItems`: An array of file paths to transform.
45
45
  - `options`: Optional configuration for the run.
46
46
 
47
+ ### `findAndReplace(content, rule, transformer)`
48
+
49
+ A utility function for finding and replacing AST nodes based on a rule.
50
+
51
+ - `content`: An `SgRoot<TypesMap>` object representing the parsed AST.
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.
54
+
55
+ Returns the transformed content as a string with all matching nodes replaced.
56
+
57
+ ```typescript
58
+ import { findAndReplace } from '@kamaalio/codemod-kit';
59
+ import { parseAsync } from '@ast-grep/napi';
60
+
61
+ const code = `
62
+ function oldFunction() {
63
+ return "hello";
64
+ }
65
+ `;
66
+
67
+ const ast = await parseAsync('javascript', code);
68
+ const result = findAndReplace(
69
+ ast,
70
+ { pattern: 'function oldFunction() { $$$ }' },
71
+ node => 'function newFunction() { return "hello world"; }',
72
+ );
73
+ ```
74
+
47
75
  ### `Codemod`
48
76
 
49
77
  A codemod is defined by the `Codemod` type:
@@ -1,2 +1,2 @@
1
- export { runCodemods, runCodemod, commitEditModifications } from './utils.js';
1
+ export { runCodemods, runCodemod, commitEditModifications, findAndReplace } from './utils.js';
2
2
  export type { Codemod, Modifications } from './types.js';
@@ -1,6 +1,8 @@
1
1
  import { type Result } from 'neverthrow';
2
- import { type Edit } from '@ast-grep/napi';
2
+ import { type Rule, type Edit, type SgNode, type SgRoot } from '@ast-grep/napi';
3
+ import type { Kinds, TypesMap } from '@ast-grep/napi/types/staticTypes.js';
3
4
  import type { Codemod, Modifications } from './types.js';
5
+ import type { Optional } from '../utils/type-utils.js';
4
6
  type RunCodemodHooks<C extends Codemod> = {
5
7
  targetFiltering?: (filepath: string, codemod: C) => boolean;
6
8
  preCodemodRun?: (codemod: C) => Promise<void>;
@@ -19,5 +21,6 @@ export declare function runCodemod<C extends Codemod>(codemod: C, transformation
19
21
  hasChanges: boolean;
20
22
  content: string;
21
23
  }, Error>>>;
24
+ export declare function findAndReplace(content: SgRoot<TypesMap>, rule: Rule<TypesMap>, transformer: (node: SgNode<TypesMap, Kinds<TypesMap>>) => Optional<string>): string;
22
25
  export declare function commitEditModifications(edits: Array<Edit>, modifications: Modifications): Promise<Modifications>;
23
26
  export {};
package/dist/index.cjs CHANGED
@@ -35,6 +35,7 @@ __webpack_require__.r(__webpack_exports__);
35
35
  __webpack_require__.d(__webpack_exports__, {
36
36
  commitEditModifications: ()=>commitEditModifications,
37
37
  runCodemod: ()=>runCodemod,
38
+ findAndReplace: ()=>findAndReplace,
38
39
  runCodemods: ()=>runCodemods
39
40
  });
40
41
  const external_node_path_namespaceObject = require("node:path");
@@ -45,6 +46,7 @@ const external_fast_glob_namespaceObject = require("fast-glob");
45
46
  var external_fast_glob_default = /*#__PURE__*/ __webpack_require__.n(external_fast_glob_namespaceObject);
46
47
  const external_neverthrow_namespaceObject = require("neverthrow");
47
48
  const napi_namespaceObject = require("@ast-grep/napi");
49
+ const kamaal_namespaceObject = require("@kamaalio/kamaal");
48
50
  const JAVASCRIPT_EXTENSIONS = [
49
51
  '.js',
50
52
  '.cjs',
@@ -126,6 +128,17 @@ async function runCodemod(codemod, transformationPath, options) {
126
128
  }
127
129
  }));
128
130
  }
131
+ function findAndReplace(content, rule, transformer) {
132
+ const root = content.root();
133
+ const edits = kamaal_namespaceObject.arrays.compactMap(root.findAll({
134
+ rule
135
+ }), (node)=>{
136
+ const transformed = transformer(node);
137
+ if (null == transformed) return null;
138
+ return node.replace(transformed);
139
+ });
140
+ return root.commitEdits(edits);
141
+ }
129
142
  async function commitEditModifications(edits, modifications) {
130
143
  if (0 === edits.length) return modifications;
131
144
  const root = modifications.ast.root();
@@ -160,10 +173,12 @@ function defaultedHooks(hooks) {
160
173
  };
161
174
  }
162
175
  exports.commitEditModifications = __webpack_exports__.commitEditModifications;
176
+ exports.findAndReplace = __webpack_exports__.findAndReplace;
163
177
  exports.runCodemod = __webpack_exports__.runCodemod;
164
178
  exports.runCodemods = __webpack_exports__.runCodemods;
165
179
  for(var __webpack_i__ in __webpack_exports__)if (-1 === [
166
180
  "commitEditModifications",
181
+ "findAndReplace",
167
182
  "runCodemod",
168
183
  "runCodemods"
169
184
  ].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
package/dist/index.d.ts CHANGED
@@ -1 +1 @@
1
- export { runCodemods, runCodemod, commitEditModifications, type Codemod, type Modifications, } from './codemods/index.js';
1
+ export { runCodemods, runCodemod, commitEditModifications, findAndReplace, type Codemod, type Modifications, } from './codemods/index.js';
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@ import promises from "node:fs/promises";
3
3
  import fast_glob from "fast-glob";
4
4
  import { err, ok } from "neverthrow";
5
5
  import { Lang, parseAsync } from "@ast-grep/napi";
6
+ import { arrays } from "@kamaalio/kamaal";
6
7
  const JAVASCRIPT_EXTENSIONS = [
7
8
  '.js',
8
9
  '.cjs',
@@ -84,6 +85,17 @@ async function runCodemod(codemod, transformationPath, options) {
84
85
  }
85
86
  }));
86
87
  }
88
+ function findAndReplace(content, rule, transformer) {
89
+ const root = content.root();
90
+ const edits = arrays.compactMap(root.findAll({
91
+ rule
92
+ }), (node)=>{
93
+ const transformed = transformer(node);
94
+ if (null == transformed) return null;
95
+ return node.replace(transformed);
96
+ });
97
+ return root.commitEdits(edits);
98
+ }
87
99
  async function commitEditModifications(edits, modifications) {
88
100
  if (0 === edits.length) return modifications;
89
101
  const root = modifications.ast.root();
@@ -117,4 +129,4 @@ function defaultedHooks(hooks) {
117
129
  preCodemodRun
118
130
  };
119
131
  }
120
- export { commitEditModifications, runCodemod, runCodemods };
132
+ export { commitEditModifications, findAndReplace, runCodemod, runCodemods };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kamaalio/codemod-kit",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "type": "module",
5
5
  "author": "Kamaal Farah",
6
6
  "license": "MIT",
@@ -20,6 +20,7 @@
20
20
  ],
21
21
  "dependencies": {
22
22
  "@ast-grep/napi": "^0.38.5",
23
+ "@kamaalio/kamaal": "^0.7.6",
23
24
  "fast-glob": "^3.3.3",
24
25
  "neverthrow": "^8.2.0"
25
26
  },