miniread 1.84.0 → 1.85.0

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.
@@ -212,6 +212,10 @@ const manifestData = {
212
212
  notes: "Measured with baseline none: 0.00%.",
213
213
  evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T20:05:17.827Z", "changedLines": 208, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 100 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T23:22:33.139Z", "changedLines": 208, "durationSeconds": 54.654894917, "stableNames": 1358 } },
214
214
  },
215
+ "rename-object-entries-parameters": {
216
+ recommended: true,
217
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T17:39:17.299Z", "changedLines": 248, "durationSeconds": 215.530500649, "stableNames": 1358 } },
218
+ },
215
219
  "rename-object-keys-iterator-variables": {
216
220
  recommended: true,
217
221
  evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-04T12:47:49.357Z", "changedLines": 606, "durationSeconds": 152.335242224, "stableNames": 1359 } },
@@ -302,6 +306,11 @@ const manifestData = {
302
306
  notes: "Measured with baseline none: 100.00% of original diff. Added to recommended for readability.",
303
307
  evaluations: { "legacy:evaluation": { "diffSizePercent": 100, "evaluatedAt": "2026-01-25T09:49:29.000Z", "changedLines": 0, "durationSeconds": 0, "stableNames": 0 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-01-26T07:05:01.592Z", "changedLines": 32, "durationSeconds": 54.402595083, "stableNames": 1358 } },
304
308
  },
309
+ "rename-setstate-updater-parameters": {
310
+ recommended: true,
311
+ notes: "Added to recommended for readability.",
312
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T14:45:47.110Z", "changedLines": 44, "durationSeconds": 167.840422062, "stableNames": 1358 } },
313
+ },
305
314
  "rename-string-split-variables": {
306
315
  recommended: true,
307
316
  notes: "Measured with baseline none: 0.00%. Added to recommended for readability.",
@@ -496,6 +505,7 @@ export const recommendedTransformIds = [
496
505
  "rename-object-keys-variables",
497
506
  "rename-object-keys-iterator-variables",
498
507
  "rename-object-keys-reducer-parameters",
508
+ "rename-object-entries-parameters",
499
509
  "rename-parameters-to-match-properties-v2",
500
510
  "rename-invalid-parameter-arguments",
501
511
  "rename-promise-executor-parameters-v2",
@@ -504,6 +514,7 @@ export const recommendedTransformIds = [
504
514
  "rename-regex-builders",
505
515
  "rename-regex-source-parameters",
506
516
  "rename-search-parameters-variables",
517
+ "rename-setstate-updater-parameters",
507
518
  "rename-file-extension-variables",
508
519
  "rename-string-split-variables",
509
520
  "rename-this-aliases",
@@ -43,6 +43,7 @@ import { renameLoopIndexVariablesTransform } from "../rename-loop-index-variable
43
43
  import { renameLoopIndexVariablesV2Transform } from "../rename-loop-index-variables-v2/rename-loop-index-variables-v2-transform.js";
44
44
  import { renameLoopIndexVariablesV3Transform } from "../rename-loop-index-variables-v3/rename-loop-index-variables-v3-transform.js";
45
45
  import { renameLoopLengthVariablesTransform } from "../rename-loop-length-variables/rename-loop-length-variables-transform.js";
46
+ import { renameObjectEntriesParametersTransform } from "../rename-object-entries-parameters/rename-object-entries-parameters-transform.js";
46
47
  import { renameObjectKeysIteratorVariablesTransform } from "../rename-object-keys-iterator-variables/rename-object-keys-iterator-variables-transform.js";
47
48
  import { renameObjectKeysReducerParametersTransform } from "../rename-object-keys-reducer-parameters/rename-object-keys-reducer-parameters-transform.js";
48
49
  import { renameObjectKeysVariablesTransform } from "../rename-object-keys-variables/rename-object-keys-variables-transform.js";
@@ -62,6 +63,7 @@ import { renameRestParametersTransform } from "../rename-rest-parameters/rename-
62
63
  import { renameRestPopCallbacksTransform } from "../rename-rest-pop-callbacks/rename-rest-pop-callbacks-transform.js";
63
64
  import { renameSafePropertyAccessorParametersTransform } from "../rename-safe-property-accessor-parameters/rename-safe-property-accessor-parameters-transform.js";
64
65
  import { renameSearchParametersVariablesTransform } from "../rename-search-parameters-variables/rename-search-parameters-variables-transform.js";
66
+ import { renameSetstateUpdaterParametersTransform } from "../rename-setstate-updater-parameters/rename-setstate-updater-parameters-transform.js";
65
67
  import { renameStringSplitVariablesTransform } from "../rename-string-split-variables/rename-string-split-variables-transform.js";
66
68
  import { renameThisAliasesTransform } from "../rename-this-aliases/rename-this-aliases-transform.js";
67
69
  import { renameTimeoutDurationParametersTransform } from "../rename-timeout-duration-parameters/rename-timeout-duration-parameters-transform.js";
@@ -133,6 +135,7 @@ export const transformRegistry = {
133
135
  [renameLoopIndexVariablesV2Transform.id]: renameLoopIndexVariablesV2Transform,
134
136
  [renameLoopIndexVariablesV3Transform.id]: renameLoopIndexVariablesV3Transform,
135
137
  [renameLoopLengthVariablesTransform.id]: renameLoopLengthVariablesTransform,
138
+ [renameObjectEntriesParametersTransform.id]: renameObjectEntriesParametersTransform,
136
139
  [renameObjectKeysIteratorVariablesTransform.id]: renameObjectKeysIteratorVariablesTransform,
137
140
  [renameObjectKeysReducerParametersTransform.id]: renameObjectKeysReducerParametersTransform,
138
141
  [renameObjectKeysVariablesTransform.id]: renameObjectKeysVariablesTransform,
@@ -152,6 +155,7 @@ export const transformRegistry = {
152
155
  [renameRestPopCallbacksTransform.id]: renameRestPopCallbacksTransform,
153
156
  [renameSafePropertyAccessorParametersTransform.id]: renameSafePropertyAccessorParametersTransform,
154
157
  [renameSearchParametersVariablesTransform.id]: renameSearchParametersVariablesTransform,
158
+ [renameSetstateUpdaterParametersTransform.id]: renameSetstateUpdaterParametersTransform,
155
159
  [renameStringSplitVariablesTransform.id]: renameStringSplitVariablesTransform,
156
160
  [renameThisAliasesTransform.id]: renameThisAliasesTransform,
157
161
  [renameTimeoutDurationParametersTransform.id]: renameTimeoutDurationParametersTransform,
@@ -4,4 +4,4 @@
4
4
  * This lets us tune transform interactions intentionally instead of relying on
5
5
  * alphabetical ID sorting.
6
6
  */
7
- export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
7
+ export declare const recommendedTransformOrder: readonly ["stabilize-top-level-bindings", "stabilize-nested-bindings", "stabilize-deferred-top-level-bindings", "stabilize-deferred-stable-rhs", "expand-boolean-literals", "expand-sequence-expressions-v5", "expand-special-number-literals", "expand-typeof-undefined-comparisons", "expand-undefined-literals", "remove-redundant-else", "rename-arguments-length-flags", "rename-asap-wrappers", "rename-awaiter-parameters", "rename-awaiter-helper-functions", "rename-buffer-variables", "rename-to-buffer-results", "rename-catch-parameters", "rename-promise-catch-parameters", "rename-char-code-at", "rename-charcode-variables-v2", "rename-client-aliases", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-deferred-resolve-parameters", "rename-deferred-resolve-parameters-v2", "rename-destructured-aliases", "rename-rest-parameters", "rename-rest-pop-callbacks", "rename-execfile-arguments", "rename-file-reader-variables", "rename-error-first-callback-parameters", "rename-error-first-callback-parameters-v2", "rename-error-variables", "rename-event-parameters", "rename-add-event-listener-parameters", "rename-http-server-parameters", "rename-fs-sync-variables", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-loop-length-variables", "rename-document-fragment-variables", "rename-object-keys-variables", "rename-object-keys-iterator-variables", "rename-object-keys-reducer-parameters", "rename-object-entries-parameters", "rename-parameters-to-match-properties-v2", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables", "rename-this-aliases", "rename-timeout-promises", "rename-timeout-ids", "rename-typeof-variables", "rename-typescript-helper-aliases", "rename-uint8array-concat-variables", "rename-url-parameters", "rename-url-variables", "rename-use-reference-guards-v2", "rename-use-reference-sets", "rename-worker-handles", "rename-zod-check-parameters", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
@@ -65,6 +65,7 @@ export const recommendedTransformOrder = [
65
65
  "rename-object-keys-variables",
66
66
  "rename-object-keys-iterator-variables",
67
67
  "rename-object-keys-reducer-parameters",
68
+ "rename-object-entries-parameters",
68
69
  "rename-parameters-to-match-properties-v2",
69
70
  "rename-invalid-parameter-arguments",
70
71
  "rename-promise-executor-parameters-v2",
@@ -73,6 +74,7 @@ export const recommendedTransformOrder = [
73
74
  "rename-regex-builders",
74
75
  "rename-regex-source-parameters",
75
76
  "rename-search-parameters-variables",
77
+ "rename-setstate-updater-parameters",
76
78
  "rename-file-extension-variables",
77
79
  "rename-string-split-variables",
78
80
  "rename-this-aliases",
@@ -0,0 +1,4 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { CallExpression, OptionalCallExpression } from "@babel/types";
3
+ export type EntriesConsumerCall = CallExpression | OptionalCallExpression;
4
+ export declare const isObjectEntriesConsumerCall: (path: NodePath<EntriesConsumerCall>) => boolean;
@@ -0,0 +1,95 @@
1
+ import * as t from "@babel/types";
2
+ import { isRuntimeBindingInScope } from "../is-runtime-binding-in-scope.js";
3
+ const ARRAY_METHODS = new Set([
4
+ "filter",
5
+ "map",
6
+ "flatMap",
7
+ "forEach",
8
+ "some",
9
+ "every",
10
+ "find",
11
+ "findIndex",
12
+ ]);
13
+ const SHAPE_PRESERVING_CHAIN_METHODS = new Set(["filter"]);
14
+ const getMemberPropertyName = (member) => {
15
+ if (!member.computed && member.property.type === "Identifier") {
16
+ return member.property.name;
17
+ }
18
+ if (member.computed && t.isStringLiteral(member.property)) {
19
+ return member.property.value;
20
+ }
21
+ if (member.computed &&
22
+ t.isTemplateLiteral(member.property) &&
23
+ member.property.expressions.length === 0) {
24
+ const quasi = member.property.quasis[0];
25
+ const cooked = quasi?.value.cooked;
26
+ return cooked ?? quasi?.value.raw;
27
+ }
28
+ return undefined;
29
+ };
30
+ const isObjectEntriesCall = (path) => {
31
+ const callee = path.node.callee;
32
+ if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
33
+ return false;
34
+ }
35
+ if (!t.isIdentifier(callee.object) || callee.object.name !== "Object") {
36
+ return false;
37
+ }
38
+ const propertyName = getMemberPropertyName(callee);
39
+ if (propertyName !== "entries")
40
+ return false;
41
+ if (isRuntimeBindingInScope(path.scope, "Object"))
42
+ return false;
43
+ return path.node.arguments.length > 0;
44
+ };
45
+ const getArrayMethodName = (path) => {
46
+ const callee = path.node.callee;
47
+ if (!t.isMemberExpression(callee) && !t.isOptionalMemberExpression(callee)) {
48
+ return undefined;
49
+ }
50
+ const propertyName = getMemberPropertyName(callee);
51
+ if (!propertyName || !ARRAY_METHODS.has(propertyName))
52
+ return undefined;
53
+ return propertyName;
54
+ };
55
+ const getReceiverCallPath = (path) => {
56
+ const objectPath = path.get("callee.object");
57
+ if (objectPath.isCallExpression() || objectPath.isOptionalCallExpression()) {
58
+ return objectPath;
59
+ }
60
+ // Optional member calls like `Object.entries(data).map?.(...)` produce a
61
+ // member-expression receiver whose object is the actual call-chain source.
62
+ if (!objectPath.isMemberExpression() &&
63
+ !objectPath.isOptionalMemberExpression()) {
64
+ return undefined;
65
+ }
66
+ const memberObjectPath = objectPath;
67
+ const nestedObjectPath = memberObjectPath.get("object");
68
+ if (nestedObjectPath.isCallExpression() ||
69
+ nestedObjectPath.isOptionalCallExpression()) {
70
+ return nestedObjectPath;
71
+ }
72
+ return undefined;
73
+ };
74
+ export const isObjectEntriesConsumerCall = (path) => {
75
+ if (!getArrayMethodName(path))
76
+ return false;
77
+ let receiverPath = getReceiverCallPath(path);
78
+ if (!receiverPath)
79
+ return false;
80
+ // Rename callbacks for direct Object.entries consumers and for downstream
81
+ // calls whose intermediate chain is known to preserve entry tuple shape.
82
+ for (;;) {
83
+ if (isObjectEntriesCall(receiverPath))
84
+ return true;
85
+ const receiverMethodName = getArrayMethodName(receiverPath);
86
+ if (!receiverMethodName ||
87
+ !SHAPE_PRESERVING_CHAIN_METHODS.has(receiverMethodName)) {
88
+ return false;
89
+ }
90
+ const nextReceiverPath = getReceiverCallPath(receiverPath);
91
+ if (!nextReceiverPath)
92
+ return false;
93
+ receiverPath = nextReceiverPath;
94
+ }
95
+ };
@@ -0,0 +1,12 @@
1
+ {
2
+ "recommended": true,
3
+ "evaluations": {
4
+ "claude-code-2.1.10:claude-code-2.1.11": {
5
+ "diffSizePercent": 100,
6
+ "evaluatedAt": "2026-02-06T17:39:17.299Z",
7
+ "changedLines": 248,
8
+ "durationSeconds": 215.530500649,
9
+ "stableNames": 1358
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameObjectEntriesParametersTransform: Transform;
@@ -0,0 +1,86 @@
1
+ import { createRequire } from "node:module";
2
+ import { isStableRenamed, RenameGroup } from "../../core/stable-naming.js";
3
+ import { getFilesToProcess, } from "../../core/types.js";
4
+ import { hasDynamicNameLookup } from "../has-dynamic-name-lookup.js";
5
+ import { isObjectEntriesConsumerCall, } from "./is-object-entries-consumer-call.js";
6
+ const require = createRequire(import.meta.url);
7
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
8
+ const traverse = require("@babel/traverse").default;
9
+ const getEntryArrayPattern = (functionPath) => {
10
+ const parameters = functionPath.get("params");
11
+ const firstParameter = parameters[0];
12
+ if (!firstParameter?.isArrayPattern())
13
+ return undefined;
14
+ const elements = firstParameter.get("elements");
15
+ if (elements.length !== 2)
16
+ return undefined;
17
+ const keyParameter = elements[0];
18
+ const valueParameter = elements[1];
19
+ if (!keyParameter?.isIdentifier() || !valueParameter?.isIdentifier()) {
20
+ return undefined;
21
+ }
22
+ return firstParameter;
23
+ };
24
+ const addEntryRenames = (group, patternPath) => {
25
+ const elements = patternPath.get("elements");
26
+ const keyParameter = elements[0];
27
+ const valueParameter = elements[1];
28
+ if (!keyParameter?.isIdentifier() || !valueParameter?.isIdentifier())
29
+ return;
30
+ const keyName = keyParameter.node.name;
31
+ const valueName = valueParameter.node.name;
32
+ // Keep destructured pairs visually consistent: if either side is already
33
+ // stable-renamed, leave the pair untouched instead of producing mixed names.
34
+ if (isStableRenamed(keyName) || isStableRenamed(valueName))
35
+ return;
36
+ group.add({
37
+ scope: keyParameter.scope,
38
+ currentName: keyName,
39
+ baseName: "key",
40
+ });
41
+ group.add({
42
+ scope: valueParameter.scope,
43
+ currentName: valueName,
44
+ baseName: "value",
45
+ });
46
+ };
47
+ const collectEntriesConsumerRenames = (path, group) => {
48
+ if (!isObjectEntriesConsumerCall(path))
49
+ return;
50
+ const callbackPath = path.get("arguments.0");
51
+ if (!callbackPath.isFunctionExpression() &&
52
+ !callbackPath.isArrowFunctionExpression()) {
53
+ return;
54
+ }
55
+ const patternPath = getEntryArrayPattern(callbackPath);
56
+ if (!patternPath)
57
+ return;
58
+ addEntryRenames(group, patternPath);
59
+ };
60
+ export const renameObjectEntriesParametersTransform = {
61
+ id: "rename-object-entries-parameters",
62
+ description: "Renames Object.entries callback parameters to $key/$value when safe, with stable/readable fallback managed by RenameGroup",
63
+ scope: "file",
64
+ parallelizable: true,
65
+ transform(context) {
66
+ let nodesVisited = 0;
67
+ let transformationsApplied = 0;
68
+ for (const fileInfo of getFilesToProcess(context)) {
69
+ if (hasDynamicNameLookup(fileInfo.ast))
70
+ continue;
71
+ const group = new RenameGroup();
72
+ traverse(fileInfo.ast, {
73
+ CallExpression(path) {
74
+ nodesVisited++;
75
+ collectEntriesConsumerRenames(path, group);
76
+ },
77
+ OptionalCallExpression(path) {
78
+ nodesVisited++;
79
+ collectEntriesConsumerRenames(path, group);
80
+ },
81
+ });
82
+ transformationsApplied += group.apply();
83
+ }
84
+ return Promise.resolve({ nodesVisited, transformationsApplied });
85
+ },
86
+ };
@@ -0,0 +1,6 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import type { ArrowFunctionExpression, CallExpression, FunctionExpression, OptionalCallExpression } from "@babel/types";
3
+ export type UpdaterFunctionPath = NodePath<ArrowFunctionExpression | FunctionExpression>;
4
+ type SetStateCallPath = NodePath<CallExpression | OptionalCallExpression>;
5
+ export declare const getUpdaterFunctionPath: (path: SetStateCallPath) => UpdaterFunctionPath | undefined;
6
+ export {};
@@ -0,0 +1,81 @@
1
+ const isSetStateMemberExpression = (member) => {
2
+ if (member.computed) {
3
+ return member.property.type === "StringLiteral"
4
+ ? member.property.value === "setState"
5
+ : false;
6
+ }
7
+ return member.property.type === "Identifier"
8
+ ? member.property.name === "setState"
9
+ : false;
10
+ };
11
+ const isThisAliasIdentifier = (scope, name) => {
12
+ const binding = scope.getBinding(name);
13
+ if (!binding)
14
+ return false;
15
+ if (!binding.constant)
16
+ return false;
17
+ if (!binding.path.isVariableDeclarator())
18
+ return false;
19
+ const init = binding.path.node.init;
20
+ if (!init)
21
+ return false;
22
+ return unwrapExpression(init).type === "ThisExpression";
23
+ };
24
+ const unwrapExpression = (expression) => {
25
+ let current = expression;
26
+ for (;;) {
27
+ if (current.type === "TSNonNullExpression") {
28
+ current = current.expression;
29
+ continue;
30
+ }
31
+ if (current.type === "TSAsExpression") {
32
+ current = current.expression;
33
+ continue;
34
+ }
35
+ if (current.type === "TSSatisfiesExpression") {
36
+ current = current.expression;
37
+ continue;
38
+ }
39
+ if (current.type === "TSTypeAssertion") {
40
+ current = current.expression;
41
+ continue;
42
+ }
43
+ if (current.type === "ParenthesizedExpression") {
44
+ current = current.expression;
45
+ continue;
46
+ }
47
+ return current;
48
+ }
49
+ };
50
+ const isThisSetStateReceiver = (scope, object) => {
51
+ if (object.type === "Super")
52
+ return false;
53
+ const unwrapped = unwrapExpression(object);
54
+ if (unwrapped.type === "ThisExpression")
55
+ return true;
56
+ if (unwrapped.type !== "Identifier")
57
+ return false;
58
+ return isThisAliasIdentifier(scope, unwrapped.name);
59
+ };
60
+ export const getUpdaterFunctionPath = (path) => {
61
+ const callee = path.node.callee;
62
+ if (callee.type !== "MemberExpression" &&
63
+ callee.type !== "OptionalMemberExpression") {
64
+ return undefined;
65
+ }
66
+ if (!isSetStateMemberExpression(callee))
67
+ return undefined;
68
+ if (!isThisSetStateReceiver(path.scope, callee.object))
69
+ return undefined;
70
+ const argumentPaths = path.get("arguments");
71
+ if (!Array.isArray(argumentPaths))
72
+ return undefined;
73
+ const updaterPath = argumentPaths.at(0);
74
+ if (updaterPath === undefined)
75
+ return undefined;
76
+ if (!updaterPath.isArrowFunctionExpression() &&
77
+ !updaterPath.isFunctionExpression()) {
78
+ return undefined;
79
+ }
80
+ return updaterPath;
81
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "recommended": true,
3
+ "evaluations": {
4
+ "claude-code-2.1.10:claude-code-2.1.11": {
5
+ "diffSizePercent": 100,
6
+ "evaluatedAt": "2026-02-06T14:45:47.110Z",
7
+ "changedLines": 44,
8
+ "durationSeconds": 167.840422062,
9
+ "stableNames": 1358
10
+ }
11
+ },
12
+ "notes": "Added to recommended for readability."
13
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameSetstateUpdaterParametersTransform: Transform;
@@ -0,0 +1,83 @@
1
+ import { createRequire } from "node:module";
2
+ import { isIdentifierName, isKeyword, isStrictBindReservedWord, } from "@babel/helper-validator-identifier";
3
+ import { RenameGroup, isStableRenamed } from "../../core/stable-naming.js";
4
+ import { getFilesToProcess, } from "../../core/types.js";
5
+ import { hasDynamicNameLookup } from "../stabilize-nested-bindings/has-dynamic-name-lookup.js";
6
+ import { getUpdaterFunctionPath, } from "./get-updater-function-path.js";
7
+ const BASE_NAME = "prevState";
8
+ const require = createRequire(import.meta.url);
9
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
10
+ const traverse = require("@babel/traverse").default;
11
+ const isSafeIdentifierName = (name) => {
12
+ if (!isIdentifierName(name))
13
+ return false;
14
+ if (isKeyword(name))
15
+ return false;
16
+ if (isStrictBindReservedWord(name, true))
17
+ return false;
18
+ return true;
19
+ };
20
+ const getUpdaterParameter = (path) => {
21
+ const parameter = path.node.params[0];
22
+ if (!parameter)
23
+ return undefined;
24
+ if (parameter.type !== "Identifier")
25
+ return undefined;
26
+ return parameter;
27
+ };
28
+ const addRenameCandidate = (path, renameGroup) => {
29
+ if (hasDynamicNameLookup(path))
30
+ return;
31
+ const parameter = getUpdaterParameter(path);
32
+ if (!parameter)
33
+ return;
34
+ if (isStableRenamed(parameter.name))
35
+ return;
36
+ const binding = path.scope.getBinding(parameter.name);
37
+ if (!binding)
38
+ return;
39
+ if (!binding.constant)
40
+ return;
41
+ // Skip unused updater parameters to avoid adding semantic noise.
42
+ if (binding.referencePaths.length === 0)
43
+ return;
44
+ renameGroup.add({
45
+ scope: path.scope,
46
+ currentName: parameter.name,
47
+ baseName: BASE_NAME,
48
+ });
49
+ };
50
+ export const renameSetstateUpdaterParametersTransform = {
51
+ id: "rename-setstate-updater-parameters",
52
+ description: "Renames updater parameters from this.setState calls to $prevState",
53
+ scope: "file",
54
+ parallelizable: true,
55
+ transform(context) {
56
+ let nodesVisited = 0;
57
+ let transformationsApplied = 0;
58
+ if (!isSafeIdentifierName(`$${BASE_NAME}`)) {
59
+ return Promise.resolve({ nodesVisited, transformationsApplied });
60
+ }
61
+ for (const fileInfo of getFilesToProcess(context)) {
62
+ const renameGroup = new RenameGroup();
63
+ traverse(fileInfo.ast, {
64
+ CallExpression(path) {
65
+ nodesVisited++;
66
+ const updaterPath = getUpdaterFunctionPath(path);
67
+ if (!updaterPath)
68
+ return;
69
+ addRenameCandidate(updaterPath, renameGroup);
70
+ },
71
+ OptionalCallExpression(path) {
72
+ nodesVisited++;
73
+ const updaterPath = getUpdaterFunctionPath(path);
74
+ if (!updaterPath)
75
+ return;
76
+ addRenameCandidate(updaterPath, renameGroup);
77
+ },
78
+ });
79
+ transformationsApplied += renameGroup.apply();
80
+ }
81
+ return Promise.resolve({ nodesVisited, transformationsApplied });
82
+ },
83
+ };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "miniread",
3
3
  "author": "Łukasz Jerciński",
4
4
  "license": "MIT",
5
- "version": "1.84.0",
5
+ "version": "1.85.0",
6
6
  "description": "Transform minified JavaScript/TypeScript into a more readable form using deterministic AST-based transforms.",
7
7
  "repository": {
8
8
  "type": "git",