ast-search 0.2.1 → 0.2.3

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
@@ -92,6 +92,21 @@ The original Vue `this` example using shorthands:
92
92
  ast-search 'ObjectMethod[key.name="setup"] this'
93
93
  ```
94
94
 
95
+ ### Optional chaining
96
+
97
+ Optional chains (`?.`) are normalized transparently — `CallExpression` and `MemberExpression` selectors match both regular and optional-chain variants:
98
+
99
+ ```bash
100
+ # Matches both items.map(...) and items?.map(...)
101
+ ast-search 'CallExpression[callee.property.name="map"]'
102
+ ```
103
+
104
+ The `optional` flag is preserved on matched nodes, so you can still narrow to strictly optional calls:
105
+
106
+ ```bash
107
+ ast-search 'CallExpression[optional=true]'
108
+ ```
109
+
95
110
  ## Supported file types
96
111
 
97
112
  `.js`, `.ts`, `.jsx`, `.tsx`, `.mjs`, `.cjs`, `.vue`
package/build/main.js CHANGED
@@ -16,10 +16,13 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
16
16
  function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
17
17
  };
18
18
  import yargs from "yargs/yargs";
19
+ import { createRequire } from "module";
19
20
  import { walkRepoFiles } from "./walk.js";
20
21
  import { getAstFromPath } from "./file.js";
21
22
  import { runQuery, validateSelector } from "./search.js";
22
23
  import { formatMatches } from "./output.js";
24
+ const require = createRequire(import.meta.url);
25
+ const { version } = require("../package.json");
23
26
  export function searchRepo(selector, dir) {
24
27
  return __awaiter(this, void 0, void 0, function* () {
25
28
  var _a, e_1, _b, _c;
@@ -115,6 +118,8 @@ const y = yargs(process.argv.slice(2))
115
118
  "reformat all files containing async functions",
116
119
  ],
117
120
  ])
121
+ .version(version)
122
+ .alias("version", "V")
118
123
  .help();
119
124
  if (process.env.NODE_ENV !== "test") {
120
125
  y.parse();
package/build/search.js CHANGED
@@ -52,8 +52,31 @@ function extractFirstLine(source, node) {
52
52
  export function validateSelector(selector) {
53
53
  esquery.parse(expandShorthands(selector));
54
54
  }
55
+ // Normalize Babel's optional-chain node types so esquery selectors like
56
+ // CallExpression[callee.property.name="map"] transparently match optional
57
+ // chains (foo?.bar()). The `optional` flag is preserved, so callers can
58
+ // still narrow to optional-only with [optional=true] or [callee.optional=true].
59
+ export function normalizeOptionalChaining(node) {
60
+ var _a;
61
+ if (!node || typeof node !== "object")
62
+ return;
63
+ // Capture visitor keys before renaming so we use the original type's keys.
64
+ const keys = (_a = VISITOR_KEYS[node.type]) !== null && _a !== void 0 ? _a : [];
65
+ if (node.type === "OptionalCallExpression")
66
+ node.type = "CallExpression";
67
+ else if (node.type === "OptionalMemberExpression")
68
+ node.type = "MemberExpression";
69
+ for (const key of keys) {
70
+ const child = node[key];
71
+ if (Array.isArray(child))
72
+ child.forEach(normalizeOptionalChaining);
73
+ else
74
+ normalizeOptionalChaining(child);
75
+ }
76
+ }
55
77
  export function runQuery(selector, ast, source = "", filename = "") {
56
78
  const expanded = expandShorthands(selector);
79
+ normalizeOptionalChaining(ast);
57
80
  // Cast to any: esquery expects estree.Node but Babel AST is structurally
58
81
  // compatible; VISITOR_KEYS ensures correct traversal of Babel-specific nodes.
59
82
  const nodes = esquery.query(ast, expanded, {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ast-search",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "",
5
5
  "main": "main.js",
6
6
  "scripts": {
@@ -22,7 +22,7 @@
22
22
  "license": "ISC",
23
23
  "repository": {
24
24
  "type": "git",
25
- "url": "https://github.com/shiplet/ast-search.git"
25
+ "url": "https://github.com/willey-shiplet/ast-search.git"
26
26
  },
27
27
  "packageManager": "pnpm@10.33.0",
28
28
  "dependencies": {