@timmo001/oxlint-rules 0.6.1 → 0.6.2

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
@@ -138,8 +138,8 @@ they only run when the consumer enables `typeAware`.
138
138
  - `no-raw-gh`: reports the raw `execute`, `json` and `stream` methods called on
139
139
  a `yield* Gh` binding from `@timmo001/effect-gh`, `Api.raw` from that package,
140
140
  and calls that launch gh: `"gh"` followed by its arguments, such as
141
- `executor.run("gh", ...)`, or an argument array starting with `"gh"`, such
142
- as `Bun.spawn(["gh", ...])`. Use the
141
+ `executor.run("gh", ...)`, or an argument array starting with `"gh"` passed
142
+ to a spawn, exec, run or command function, such as `Bun.spawn(["gh", ...])`. Use the
143
143
  package's typed operations, and add one to effect-gh when a command has none.
144
144
  effect-gh's own relative imports are not reported.
145
145
  - `no-try-catch-in-effect-generators`: diagnoses synchronous `try/catch` owned
package/dist/cli.js CHANGED
@@ -3004,14 +3004,20 @@ function isYieldGh(sourceCode, node) {
3004
3004
  function isGhBinding(sourceCode, identifier) {
3005
3005
  return resolveVariable(sourceCode, identifier)?.defs.some((definition) => definition.type === "Variable" && definition.node.type === "VariableDeclarator" && isYieldGh(sourceCode, definition.node.init)) ?? false;
3006
3006
  }
3007
- function launchesGh(args) {
3008
- const [command, argv] = args;
3007
+ var launcherName = /spawn|exec|run|command/i;
3008
+ function calleeName(callee) {
3009
+ if (callee.type === "Identifier")
3010
+ return callee.name;
3011
+ return staticMemberName(callee);
3012
+ }
3013
+ function launchesGh(node) {
3014
+ const [command, argv] = node.arguments;
3009
3015
  if (command?.type === "Literal")
3010
3016
  return command.value === "gh" && argv !== undefined;
3011
3017
  if (command?.type !== "ArrayExpression")
3012
3018
  return false;
3013
3019
  const first = command.elements[0];
3014
- return first?.type === "Literal" && first.value === "gh";
3020
+ return first?.type === "Literal" && first.value === "gh" && launcherName.test(calleeName(node.callee) ?? "");
3015
3021
  }
3016
3022
  var noRawGhRule = defineRule24({
3017
3023
  meta: {
@@ -3041,7 +3047,7 @@ var noRawGhRule = defineRule24({
3041
3047
  return;
3042
3048
  }
3043
3049
  }
3044
- if (launchesGh(node.arguments))
3050
+ if (launchesGh(node))
3045
3051
  context.report({ node, messageId: "spawnGh" });
3046
3052
  }
3047
3053
  };
@@ -55,14 +55,20 @@ function isYieldGh(sourceCode, node) {
55
55
  function isGhBinding(sourceCode, identifier) {
56
56
  return resolveVariable(sourceCode, identifier)?.defs.some((definition) => definition.type === "Variable" && definition.node.type === "VariableDeclarator" && isYieldGh(sourceCode, definition.node.init)) ?? false;
57
57
  }
58
- function launchesGh(args) {
59
- const [command, argv] = args;
58
+ var launcherName = /spawn|exec|run|command/i;
59
+ function calleeName(callee) {
60
+ if (callee.type === "Identifier")
61
+ return callee.name;
62
+ return staticMemberName(callee);
63
+ }
64
+ function launchesGh(node) {
65
+ const [command, argv] = node.arguments;
60
66
  if (command?.type === "Literal")
61
67
  return command.value === "gh" && argv !== undefined;
62
68
  if (command?.type !== "ArrayExpression")
63
69
  return false;
64
70
  const first = command.elements[0];
65
- return first?.type === "Literal" && first.value === "gh";
71
+ return first?.type === "Literal" && first.value === "gh" && launcherName.test(calleeName(node.callee) ?? "");
66
72
  }
67
73
  var noRawGhRule = defineRule({
68
74
  meta: {
@@ -92,7 +98,7 @@ var noRawGhRule = defineRule({
92
98
  return;
93
99
  }
94
100
  }
95
- if (launchesGh(node.arguments))
101
+ if (launchesGh(node))
96
102
  context.report({ node, messageId: "spawnGh" });
97
103
  }
98
104
  };
@@ -50,14 +50,20 @@ function isYieldGh(sourceCode, node) {
50
50
  function isGhBinding(sourceCode, identifier) {
51
51
  return resolveVariable(sourceCode, identifier)?.defs.some((definition) => definition.type === "Variable" && definition.node.type === "VariableDeclarator" && isYieldGh(sourceCode, definition.node.init)) ?? false;
52
52
  }
53
- function launchesGh(args) {
54
- const [command, argv] = args;
53
+ var launcherName = /spawn|exec|run|command/i;
54
+ function calleeName(callee) {
55
+ if (callee.type === "Identifier")
56
+ return callee.name;
57
+ return staticMemberName(callee);
58
+ }
59
+ function launchesGh(node) {
60
+ const [command, argv] = node.arguments;
55
61
  if (command?.type === "Literal")
56
62
  return command.value === "gh" && argv !== undefined;
57
63
  if (command?.type !== "ArrayExpression")
58
64
  return false;
59
65
  const first = command.elements[0];
60
- return first?.type === "Literal" && first.value === "gh";
66
+ return first?.type === "Literal" && first.value === "gh" && launcherName.test(calleeName(node.callee) ?? "");
61
67
  }
62
68
  var noRawGhRule = defineRule({
63
69
  meta: {
@@ -87,7 +93,7 @@ var noRawGhRule = defineRule({
87
93
  return;
88
94
  }
89
95
  }
90
- if (launchesGh(node.arguments))
96
+ if (launchesGh(node))
91
97
  context.report({ node, messageId: "spawnGh" });
92
98
  }
93
99
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@timmo001/oxlint-rules",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "Shared Oxlint plugins and configs with optional Effect rules.",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
@@ -61,12 +61,23 @@ function isGhBinding(
61
61
  );
62
62
  }
63
63
 
64
+ /** Callee names that take an argv array to launch, such as `Bun.spawn` or `execFileSync`. */
65
+ const launcherName = /spawn|exec|run|command/i;
66
+
67
+ function calleeName(callee: ESTree.Expression): string | null {
68
+ if (callee.type === "Identifier") return callee.name;
69
+
70
+ return staticMemberName(callee);
71
+ }
72
+
64
73
  /**
65
- * Whether call arguments launch gh: `"gh"` followed by its argv, as in
66
- * `run("gh", args)`, or an argv array starting with `"gh"`.
74
+ * Whether a call launches gh: `"gh"` followed by its argv, as in
75
+ * `run("gh", args)`, or an argv array starting with `"gh"` passed to a
76
+ * spawn, exec, run or command function. Recording argv, as in
77
+ * `calls.push(["gh", ...args])`, is not launching it.
67
78
  */
68
- function launchesGh(args: ESTree.CallExpression["arguments"]): boolean {
69
- const [command, argv] = args;
79
+ function launchesGh(node: ESTree.CallExpression): boolean {
80
+ const [command, argv] = node.arguments;
70
81
 
71
82
  if (command?.type === "Literal")
72
83
  return command.value === "gh" && argv !== undefined;
@@ -74,7 +85,11 @@ function launchesGh(args: ESTree.CallExpression["arguments"]): boolean {
74
85
  if (command?.type !== "ArrayExpression") return false;
75
86
  const first = command.elements[0];
76
87
 
77
- return first?.type === "Literal" && first.value === "gh";
88
+ return (
89
+ first?.type === "Literal" &&
90
+ first.value === "gh" &&
91
+ launcherName.test(calleeName(node.callee) ?? "")
92
+ );
78
93
  }
79
94
 
80
95
  /** Route gh through effect-gh's typed operations instead of raw argv or direct spawns. */
@@ -125,8 +140,7 @@ export const noRawGhRule = defineRule({
125
140
  }
126
141
  }
127
142
 
128
- if (launchesGh(node.arguments))
129
- context.report({ node, messageId: "spawnGh" });
143
+ if (launchesGh(node)) context.report({ node, messageId: "spawnGh" });
130
144
  },
131
145
  };
132
146
  },