miniread 1.93.0 → 1.94.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.
@@ -131,6 +131,11 @@ const manifestData = {
131
131
  notes: "Auto-added by evaluation script. Measured with baseline none: 0.09%.",
132
132
  evaluations: { "legacy:evaluation": { "evaluatedAt": "2026-01-25T19:59:48.188Z", "changedLines": 38927, "durationSeconds": 0, "stableNames": 0, "diffSizePercent": 97.80020410477378 }, "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 97.80020410477378, "evaluatedAt": "2026-01-25T23:15:44.243Z", "changedLines": 38927, "durationSeconds": 76.61873741599999, "stableNames": 4505 } },
133
133
  },
134
+ "rename-dirent-parameters": {
135
+ recommended: true,
136
+ notes: "stableNames counts unique `$...` identifiers in transformed output for this transform run, so this value can differ across transforms.",
137
+ evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-06T21:03:02.730Z", "changedLines": 518, "durationSeconds": 177.77177340999998, "stableNames": 1360 } },
138
+ },
134
139
  "rename-document-fragment-variables": {
135
140
  recommended: true,
136
141
  evaluations: { "claude-code-2.1.10:claude-code-2.1.11": { "diffSizePercent": 100, "evaluatedAt": "2026-02-02T22:12:52.993Z", "changedLines": 20, "durationSeconds": 207.34089557, "stableNames": 1358 } },
@@ -536,6 +541,7 @@ export const recommendedTransformIds = [
536
541
  "rename-add-event-listener-parameters",
537
542
  "rename-http-server-parameters",
538
543
  "rename-fs-sync-variables",
544
+ "rename-dirent-parameters",
539
545
  "rename-http-method-parameters",
540
546
  "rename-interval-ids",
541
547
  "rename-indexeddb-request-variables",
@@ -26,6 +26,7 @@ import { renameDefaultOptionsParametersV3Transform } from "../rename-default-opt
26
26
  import { renameDeferredResolveParametersTransform } from "../rename-deferred-resolve-parameters/rename-deferred-resolve-parameters-transform.js";
27
27
  import { renameDeferredResolveParametersV2Transform } from "../rename-deferred-resolve-parameters-v2/rename-deferred-resolve-parameters-v2-transform.js";
28
28
  import { renameDestructuredAliasesTransform } from "../rename-destructured-aliases/rename-destructured-aliases-transform.js";
29
+ import { renameDirentParametersTransform } from "../rename-dirent-parameters/rename-dirent-parameters-transform.js";
29
30
  import { renameDocumentFragmentVariablesTransform } from "../rename-document-fragment-variables/rename-document-fragment-variables-transform.js";
30
31
  import { renameErrorFirstCallbackParametersTransform } from "../rename-error-first-callback-parameters/rename-error-first-callback-parameters-transform.js";
31
32
  import { renameErrorFirstCallbackParametersV2Transform } from "../rename-error-first-callback-parameters-v2/rename-error-first-callback-parameters-v2-transform.js";
@@ -126,6 +127,7 @@ export const transformRegistry = {
126
127
  [renameDeferredResolveParametersTransform.id]: renameDeferredResolveParametersTransform,
127
128
  [renameDeferredResolveParametersV2Transform.id]: renameDeferredResolveParametersV2Transform,
128
129
  [renameDestructuredAliasesTransform.id]: renameDestructuredAliasesTransform,
130
+ [renameDirentParametersTransform.id]: renameDirentParametersTransform,
129
131
  [renameDocumentFragmentVariablesTransform.id]: renameDocumentFragmentVariablesTransform,
130
132
  [renameErrorFirstCallbackParametersTransform.id]: renameErrorFirstCallbackParametersTransform,
131
133
  [renameErrorFirstCallbackParametersV2Transform.id]: renameErrorFirstCallbackParametersV2Transform,
@@ -6,4 +6,4 @@
6
6
  * `recommended` prioritizes readability and includes documented heuristics
7
7
  * where edge-case behavioral differences are possible.
8
8
  */
9
- 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-memoized-instance-variables", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-default-options-parameters-v3", "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-queue-traversal-variables", "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-v3", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-exec-results", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables-v2", "rename-queue-entry-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-filter-boolean-coercion", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
9
+ 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-memoized-instance-variables", "rename-comparison-flags", "rename-platform-win32-flags", "rename-date-now-start-times", "rename-default-options-parameters-v2", "rename-default-options-parameters-v3", "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-dirent-parameters", "rename-http-method-parameters", "rename-interval-ids", "rename-indexeddb-request-variables", "rename-loop-index-variables-v3", "rename-queue-traversal-variables", "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-v3", "rename-invalid-parameter-arguments", "rename-promise-executor-parameters-v2", "rename-range-parameters", "rename-read-file-lines", "rename-regex-builders", "rename-regex-exec-results", "rename-regex-source-parameters", "rename-search-parameters-variables", "rename-setstate-updater-parameters", "rename-file-extension-variables", "rename-string-split-variables-v2", "rename-queue-entry-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-filter-boolean-coercion", "simplify-boolean-negations", "simplify-string-trim", "split-variable-declarations", "use-optional-chaining", "use-object-property-shorthand", "use-object-shorthand", "replace-dynamic-require-eval"];
@@ -60,6 +60,7 @@ export const recommendedTransformOrder = [
60
60
  // are already stable-hashed. This transform gives remaining non-stable `fs` helpers stable
61
61
  // `$fs`-style names.
62
62
  "rename-fs-sync-variables",
63
+ "rename-dirent-parameters",
63
64
  "rename-http-method-parameters",
64
65
  "rename-interval-ids",
65
66
  "rename-indexeddb-request-variables",
@@ -0,0 +1,3 @@
1
+ import type { MemberExpression, OptionalMemberExpression } from "@babel/types";
2
+ export type MemberLikeExpression = MemberExpression | OptionalMemberExpression;
3
+ export declare const getMemberPropertyName: (member: MemberLikeExpression) => string | undefined;
@@ -0,0 +1,10 @@
1
+ export const getMemberPropertyName = (member) => {
2
+ if (member.computed) {
3
+ if (member.property.type !== "StringLiteral")
4
+ return;
5
+ return member.property.value;
6
+ }
7
+ if (member.property.type !== "Identifier")
8
+ return;
9
+ return member.property.name;
10
+ };
@@ -0,0 +1,2 @@
1
+ import type { Binding } from "@babel/traverse";
2
+ export declare const isDirentCallbackParameterBinding: (binding: Binding) => boolean;
@@ -0,0 +1,111 @@
1
+ import { getMemberPropertyName } from "./get-member-property-name.js";
2
+ const iterableMethodNames = new Set([
3
+ "every",
4
+ "filter",
5
+ "flatMap",
6
+ "find",
7
+ "findLast",
8
+ "findLastIndex",
9
+ "findIndex",
10
+ "forEach",
11
+ "map",
12
+ "some",
13
+ ]);
14
+ const unwrapTransparentExpressionNode = (expression) => {
15
+ if (expression.type === "ParenthesizedExpression") {
16
+ return unwrapTransparentExpressionNode(expression.expression);
17
+ }
18
+ if (expression.type === "TSAsExpression") {
19
+ return unwrapTransparentExpressionNode(expression.expression);
20
+ }
21
+ if (expression.type === "TSSatisfiesExpression") {
22
+ return unwrapTransparentExpressionNode(expression.expression);
23
+ }
24
+ if (expression.type === "TSTypeAssertion") {
25
+ return unwrapTransparentExpressionNode(expression.expression);
26
+ }
27
+ if (expression.type === "TSNonNullExpression") {
28
+ return unwrapTransparentExpressionNode(expression.expression);
29
+ }
30
+ return expression;
31
+ };
32
+ const isIterableCallbackCall = (path) => {
33
+ const callee = path.node.callee;
34
+ if ((callee.type !== "MemberExpression" &&
35
+ callee.type !== "OptionalMemberExpression") ||
36
+ !iterableMethodNames.has(getMemberPropertyName(callee) ?? "")) {
37
+ return false;
38
+ }
39
+ const [firstArgument] = path.node.arguments;
40
+ if (!firstArgument)
41
+ return false;
42
+ if (firstArgument.type === "SpreadElement")
43
+ return false;
44
+ if (firstArgument.type === "ArgumentPlaceholder")
45
+ return false;
46
+ const unwrappedFirstArgument = unwrapTransparentExpressionNode(firstArgument);
47
+ return (unwrappedFirstArgument.type === "FunctionExpression" ||
48
+ unwrappedFirstArgument.type === "ArrowFunctionExpression");
49
+ };
50
+ const unwrapTransparentExpressionPath = (path) => {
51
+ const parentPath = path.parentPath;
52
+ const parentNode = parentPath.node;
53
+ if (parentNode.type !== "ParenthesizedExpression" &&
54
+ parentNode.type !== "TSAsExpression" &&
55
+ parentNode.type !== "TSSatisfiesExpression" &&
56
+ parentNode.type !== "TSTypeAssertion" &&
57
+ parentNode.type !== "TSNonNullExpression") {
58
+ return path;
59
+ }
60
+ if (parentNode.expression !== path.node)
61
+ return path;
62
+ return unwrapTransparentExpressionPath(parentPath);
63
+ };
64
+ const hasNamePropertyUsage = (binding) => {
65
+ return binding.referencePaths.some((referencePath) => {
66
+ if (!referencePath.isIdentifier())
67
+ return false;
68
+ const objectPath = unwrapTransparentExpressionPath(referencePath);
69
+ const parentPath = objectPath.parentPath;
70
+ if ((!parentPath.isMemberExpression() &&
71
+ !parentPath.isOptionalMemberExpression()) ||
72
+ parentPath.node.object !== objectPath.node) {
73
+ return false;
74
+ }
75
+ return getMemberPropertyName(parentPath.node) === "name";
76
+ });
77
+ };
78
+ export const isDirentCallbackParameterBinding = (binding) => {
79
+ const bindingPath = binding.path;
80
+ if (!bindingPath.isIdentifier())
81
+ return false;
82
+ const callbackPath = bindingPath.parentPath;
83
+ if (!callbackPath.isFunctionExpression() &&
84
+ !callbackPath.isArrowFunctionExpression()) {
85
+ return false;
86
+ }
87
+ const [firstParameter] = callbackPath.node.params;
88
+ if (firstParameter?.type !== "Identifier")
89
+ return false;
90
+ if (firstParameter !== binding.identifier)
91
+ return false;
92
+ const callbackContainerPath = unwrapTransparentExpressionPath(callbackPath);
93
+ const callbackCallPath = callbackContainerPath.parentPath;
94
+ if (!callbackCallPath.isCallExpression() &&
95
+ !callbackCallPath.isOptionalCallExpression()) {
96
+ return false;
97
+ }
98
+ if (!isIterableCallbackCall(callbackCallPath))
99
+ return false;
100
+ // Require reading dirent.name somewhere in the callback to avoid Stats-like false positives.
101
+ if (!hasNamePropertyUsage(binding))
102
+ return false;
103
+ const [firstArgument] = callbackCallPath.node.arguments;
104
+ if (!firstArgument)
105
+ return false;
106
+ if (firstArgument.type === "SpreadElement")
107
+ return false;
108
+ if (firstArgument.type === "ArgumentPlaceholder")
109
+ return false;
110
+ return unwrapTransparentExpressionNode(firstArgument) === callbackPath.node;
111
+ };
@@ -0,0 +1,3 @@
1
+ import type { NodePath } from "@babel/traverse";
2
+ import { type MemberLikeExpression } from "./get-member-property-name.js";
3
+ export declare const isDirentMethodCall: (path: NodePath<MemberLikeExpression>) => boolean;
@@ -0,0 +1,26 @@
1
+ import { getMemberPropertyName, } from "./get-member-property-name.js";
2
+ const direntMethodNames = new Set([
3
+ "isBlockDevice",
4
+ "isCharacterDevice",
5
+ "isDirectory",
6
+ "isFIFO",
7
+ "isFile",
8
+ "isSocket",
9
+ "isSymbolicLink",
10
+ ]);
11
+ // Intentional heuristic: these names are a readability signal, not strict type inference.
12
+ // Additional callback-shape guards in is-dirent-callback-parameter-binding keep this conservative.
13
+ const isCallLikePath = (path) => {
14
+ return path.isCallExpression() || path.isOptionalCallExpression();
15
+ };
16
+ export const isDirentMethodCall = (path) => {
17
+ const propertyName = getMemberPropertyName(path.node);
18
+ if (!propertyName)
19
+ return false;
20
+ if (!direntMethodNames.has(propertyName))
21
+ return false;
22
+ const callPath = path.parentPath;
23
+ if (!isCallLikePath(callPath))
24
+ return false;
25
+ return callPath.node.callee === path.node;
26
+ };
@@ -0,0 +1,13 @@
1
+ {
2
+ "recommended": true,
3
+ "notes": "stableNames counts unique `$...` identifiers in transformed output for this transform run, so this value can differ across transforms.",
4
+ "evaluations": {
5
+ "claude-code-2.1.10:claude-code-2.1.11": {
6
+ "diffSizePercent": 100,
7
+ "evaluatedAt": "2026-02-06T21:03:02.730Z",
8
+ "changedLines": 518,
9
+ "durationSeconds": 177.77177340999998,
10
+ "stableNames": 1360
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,2 @@
1
+ import { type Transform } from "../../core/types.js";
2
+ export declare const renameDirentParametersTransform: Transform;
@@ -0,0 +1,70 @@
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 {} from "./get-member-property-name.js";
6
+ import { isDirentCallbackParameterBinding } from "./is-dirent-callback-parameter-binding.js";
7
+ import { isDirentMethodCall } from "./is-dirent-method-call.js";
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 addDirentBinding = (path, group, seenBindings) => {
12
+ if (!isDirentMethodCall(path))
13
+ return;
14
+ const object = path.node.object;
15
+ if (object.type !== "Identifier")
16
+ return;
17
+ const binding = path.scope.getBinding(object.name);
18
+ if (!binding)
19
+ return;
20
+ // Reassigned parameters may stop representing a dirent in the same scope.
21
+ if (!binding.constant)
22
+ return;
23
+ if (!isDirentCallbackParameterBinding(binding))
24
+ return;
25
+ if (seenBindings.has(binding))
26
+ return;
27
+ const currentName = binding.identifier.name;
28
+ if (isStableRenamed(currentName))
29
+ return;
30
+ // Keep already-semantic names readable; we avoid adding `$` noise when intent is clear.
31
+ if (currentName === "dirent")
32
+ return;
33
+ group.add({
34
+ scope: binding.scope,
35
+ currentName,
36
+ baseName: "dirent",
37
+ });
38
+ seenBindings.add(binding);
39
+ };
40
+ export const renameDirentParametersTransform = {
41
+ id: "rename-dirent-parameters",
42
+ description: "Renames iterable callback bindings that call Dirent-style predicate methods and read .name to semantic dirent names",
43
+ scope: "file",
44
+ parallelizable: true,
45
+ transform(context) {
46
+ let nodesVisited = 0;
47
+ let transformationsApplied = 0;
48
+ for (const fileInfo of getFilesToProcess(context)) {
49
+ if (hasDynamicNameLookup(fileInfo.ast))
50
+ continue;
51
+ const group = new RenameGroup();
52
+ const seenBindings = new Set();
53
+ traverse(fileInfo.ast, {
54
+ MemberExpression(path) {
55
+ nodesVisited++;
56
+ addDirentBinding(path, group, seenBindings);
57
+ },
58
+ OptionalMemberExpression(path) {
59
+ nodesVisited++;
60
+ addDirentBinding(path, group, seenBindings);
61
+ },
62
+ });
63
+ transformationsApplied += group.apply();
64
+ }
65
+ return Promise.resolve({
66
+ nodesVisited,
67
+ transformationsApplied,
68
+ });
69
+ },
70
+ };
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.93.0",
5
+ "version": "1.94.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",