expose-kit 0.7.0 → 0.9.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.
- package/README.md +63 -2
- package/dist/index.js +454 -26
- package/dist/package.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -285,9 +285,70 @@ Notes:
|
|
|
285
285
|
|
|
286
286
|
---
|
|
287
287
|
|
|
288
|
+
### `expose remove-reassign`
|
|
289
|
+
|
|
290
|
+
Inline safe alias assignments and wrapper calls.
|
|
291
|
+
```js
|
|
292
|
+
const a = 0;
|
|
293
|
+
const b = a;
|
|
294
|
+
const c = b;
|
|
295
|
+
console.log(c); // => console.log(a);
|
|
296
|
+
```
|
|
297
|
+
```js
|
|
298
|
+
function a(arg) {
|
|
299
|
+
return b(arg);
|
|
300
|
+
}
|
|
301
|
+
function c(arg) {
|
|
302
|
+
return d[arg];
|
|
303
|
+
}
|
|
304
|
+
a(0); // => b(0)
|
|
305
|
+
c(0); // => d[0]
|
|
306
|
+
```
|
|
307
|
+
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/remove-reassign/mocks).
|
|
308
|
+
|
|
309
|
+
```bash
|
|
310
|
+
expose remove-reassign path/to/file.js --output path/to/file.remove-reassign.js
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
- `--o, --output <file>`
|
|
315
|
+
Output file path
|
|
316
|
+
|
|
317
|
+
Notes:
|
|
318
|
+
- Only inlines const/immutable alias chains.
|
|
319
|
+
- Skips object shorthand replacements and shadowed bindings.
|
|
320
|
+
- Wrapper inlining is limited to single-return passthroughs.
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|
|
324
|
+
### `expose fn-inliner`
|
|
325
|
+
|
|
326
|
+
Inline proxy function calls into expressions.
|
|
327
|
+
```js
|
|
328
|
+
const add = (a, b) => a + b;
|
|
329
|
+
const sum = add(1, 2);
|
|
330
|
+
// after
|
|
331
|
+
const sum = 1 + 2;
|
|
332
|
+
```
|
|
333
|
+
Example is [here](https://github.com/evex-dev/expose-kit/tree/main/commands/fn-inliner/mocks).
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
expose fn-inliner path/to/file.js --output path/to/file.fn-inliner.js
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
Args:
|
|
340
|
+
- `--o, --output <file>`
|
|
341
|
+
Output file path
|
|
342
|
+
|
|
343
|
+
Notes:
|
|
344
|
+
- Only inlines functions that return a single expression.
|
|
345
|
+
- Skips return expressions with assignments, functions, blocks, or sequences.
|
|
346
|
+
|
|
347
|
+
---
|
|
348
|
+
|
|
288
349
|
### `expose remove-unused`
|
|
289
|
-
|
|
290
|
-
Remove unused variabless.
|
|
350
|
+
|
|
351
|
+
Remove unused variabless.
|
|
291
352
|
```js
|
|
292
353
|
// before
|
|
293
354
|
var a = 0, b = 1;
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// index.ts
|
|
4
4
|
import { Command } from "commander";
|
|
5
|
-
import { dirname as
|
|
5
|
+
import { dirname as dirname10, join as join10 } from "path";
|
|
6
6
|
import { fileURLToPath } from "url";
|
|
7
7
|
import chalk4 from "chalk";
|
|
8
8
|
|
|
@@ -746,11 +746,7 @@ var expand_object_default = createCommand((program2) => {
|
|
|
746
746
|
}
|
|
747
747
|
const loader = loading4("Expanding object access...").start();
|
|
748
748
|
try {
|
|
749
|
-
const { code: output, replacedCount } = await expandObjectAccess(
|
|
750
|
-
fileContent,
|
|
751
|
-
filename,
|
|
752
|
-
targetName
|
|
753
|
-
);
|
|
749
|
+
const { code: output, replacedCount } = await expandObjectAccess(fileContent, filename, targetName);
|
|
754
750
|
writeFileSync3(outputPath, output, "utf8");
|
|
755
751
|
loader.succeed(
|
|
756
752
|
`Saved expand-object file to: ${outputPath} (${diff(fileContent, output).length} lines changed, ${replacedCount} replacements)`
|
|
@@ -932,7 +928,11 @@ var object_packer_default = createCommand((program2) => {
|
|
|
932
928
|
}
|
|
933
929
|
const loader = loading5("Packing object properties...").start();
|
|
934
930
|
try {
|
|
935
|
-
const {
|
|
931
|
+
const {
|
|
932
|
+
code: output,
|
|
933
|
+
packedCount,
|
|
934
|
+
removedStatements
|
|
935
|
+
} = packObjectProperties(fileContent, filename);
|
|
936
936
|
writeFileSync4(outputPath, output, "utf8");
|
|
937
937
|
loader.succeed(
|
|
938
938
|
`Saved object-packer file to: ${outputPath} (${diff(fileContent, output).length} lines changed, ${packedCount} properties packed, ${removedStatements} statements removed)`
|
|
@@ -1311,7 +1311,7 @@ var remove_updater_default = createCommand((program2) => {
|
|
|
1311
1311
|
);
|
|
1312
1312
|
});
|
|
1313
1313
|
|
|
1314
|
-
// commands/remove-
|
|
1314
|
+
// commands/remove-reassign/index.ts
|
|
1315
1315
|
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7 } from "fs";
|
|
1316
1316
|
import { basename as basename7, dirname as dirname7, extname as extname7, join as join7 } from "path";
|
|
1317
1317
|
import { parse as parse8 } from "@babel/parser";
|
|
@@ -1322,19 +1322,263 @@ import loading8 from "loading-cli";
|
|
|
1322
1322
|
var createDefaultOutputPath7 = (inputPath) => {
|
|
1323
1323
|
const ext = extname7(inputPath);
|
|
1324
1324
|
if (!ext) {
|
|
1325
|
-
return `${inputPath}.remove-
|
|
1325
|
+
return `${inputPath}.remove-reassign.js`;
|
|
1326
1326
|
}
|
|
1327
1327
|
const base = basename7(inputPath, ext);
|
|
1328
|
-
return join7(dirname7(inputPath), `${base}.remove-
|
|
1328
|
+
return join7(dirname7(inputPath), `${base}.remove-reassign${ext}`);
|
|
1329
1329
|
};
|
|
1330
|
-
var
|
|
1330
|
+
var isShorthandObjectKey = (path) => {
|
|
1331
|
+
const parent = path.parentPath;
|
|
1332
|
+
if (!parent || !parent.isObjectProperty()) return false;
|
|
1333
|
+
return parent.node.shorthand && parent.get("key") === path;
|
|
1334
|
+
};
|
|
1335
|
+
var resolveFinalAlias = (binding, getBinding) => {
|
|
1336
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1337
|
+
let currentBinding = binding;
|
|
1338
|
+
let currentName = null;
|
|
1339
|
+
while (currentBinding && !visited.has(currentBinding)) {
|
|
1340
|
+
visited.add(currentBinding);
|
|
1341
|
+
if (!t6.isVariableDeclarator(currentBinding.path.node)) break;
|
|
1342
|
+
const init = currentBinding.path.node.init;
|
|
1343
|
+
if (!init || !t6.isIdentifier(init)) break;
|
|
1344
|
+
const nextBinding = getBinding(init.name);
|
|
1345
|
+
if (!nextBinding || !nextBinding.constant) break;
|
|
1346
|
+
currentBinding = nextBinding;
|
|
1347
|
+
currentName = init.name;
|
|
1348
|
+
}
|
|
1349
|
+
if (!currentBinding || !currentName) {
|
|
1350
|
+
return null;
|
|
1351
|
+
}
|
|
1352
|
+
return { targetBinding: currentBinding, targetName: currentName };
|
|
1353
|
+
};
|
|
1354
|
+
var getReturnExpression = (functionPath) => {
|
|
1355
|
+
const body = functionPath.node.body;
|
|
1356
|
+
if (!t6.isBlockStatement(body)) {
|
|
1357
|
+
return body;
|
|
1358
|
+
}
|
|
1359
|
+
if (body.body.length !== 1) return null;
|
|
1360
|
+
const statement = body.body[0];
|
|
1361
|
+
if (!t6.isReturnStatement(statement) || !statement.argument) return null;
|
|
1362
|
+
return statement.argument;
|
|
1363
|
+
};
|
|
1364
|
+
var getWrapperInfo = (functionPath, wrapperBinding) => {
|
|
1365
|
+
const params = functionPath.node.params;
|
|
1366
|
+
if (params.length === 0) return null;
|
|
1367
|
+
const paramNames = [];
|
|
1368
|
+
for (const param of params) {
|
|
1369
|
+
if (!t6.isIdentifier(param)) return null;
|
|
1370
|
+
paramNames.push(param.name);
|
|
1371
|
+
}
|
|
1372
|
+
const expression = getReturnExpression(functionPath);
|
|
1373
|
+
if (!expression) return null;
|
|
1374
|
+
if (t6.isCallExpression(expression)) {
|
|
1375
|
+
if (!t6.isIdentifier(expression.callee)) return null;
|
|
1376
|
+
if (expression.arguments.length !== paramNames.length) return null;
|
|
1377
|
+
for (let i = 0; i < expression.arguments.length; i++) {
|
|
1378
|
+
const arg = expression.arguments[i];
|
|
1379
|
+
if (!t6.isIdentifier(arg)) return null;
|
|
1380
|
+
if (arg.name !== paramNames[i]) return null;
|
|
1381
|
+
}
|
|
1382
|
+
const targetBinding = functionPath.scope.getBinding(expression.callee.name);
|
|
1383
|
+
if (!targetBinding) return null;
|
|
1384
|
+
return {
|
|
1385
|
+
kind: "call",
|
|
1386
|
+
wrapperBinding,
|
|
1387
|
+
targetName: expression.callee.name,
|
|
1388
|
+
targetBinding,
|
|
1389
|
+
paramNames
|
|
1390
|
+
};
|
|
1391
|
+
}
|
|
1392
|
+
if (t6.isMemberExpression(expression) && expression.computed && t6.isIdentifier(expression.object) && t6.isIdentifier(expression.property) && paramNames.length === 1 && expression.property.name === paramNames[0]) {
|
|
1393
|
+
const targetBinding = functionPath.scope.getBinding(expression.object.name);
|
|
1394
|
+
if (!targetBinding) return null;
|
|
1395
|
+
return {
|
|
1396
|
+
kind: "member",
|
|
1397
|
+
wrapperBinding,
|
|
1398
|
+
targetName: expression.object.name,
|
|
1399
|
+
targetBinding
|
|
1400
|
+
};
|
|
1401
|
+
}
|
|
1402
|
+
return null;
|
|
1403
|
+
};
|
|
1404
|
+
var removeReassign = (code, filename) => {
|
|
1331
1405
|
const ast = parse8(code, createParseOptions(filename));
|
|
1332
|
-
|
|
1406
|
+
const aliases = [];
|
|
1407
|
+
const wrappers = [];
|
|
1333
1408
|
patchDefault(traverse7)(ast, {
|
|
1409
|
+
VariableDeclarator(path) {
|
|
1410
|
+
if (!t6.isIdentifier(path.node.id)) return;
|
|
1411
|
+
if (!path.node.init || !t6.isIdentifier(path.node.init)) return;
|
|
1412
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
1413
|
+
if (!binding || !binding.constant) return;
|
|
1414
|
+
const targetBinding = path.scope.getBinding(path.node.init.name);
|
|
1415
|
+
if (!targetBinding || !targetBinding.constant) return;
|
|
1416
|
+
const resolved = resolveFinalAlias(
|
|
1417
|
+
binding,
|
|
1418
|
+
(name) => path.scope.getBinding(name)
|
|
1419
|
+
);
|
|
1420
|
+
if (!resolved) return;
|
|
1421
|
+
aliases.push({
|
|
1422
|
+
aliasBinding: binding,
|
|
1423
|
+
targetBinding: resolved.targetBinding,
|
|
1424
|
+
targetName: resolved.targetName
|
|
1425
|
+
});
|
|
1426
|
+
},
|
|
1427
|
+
FunctionDeclaration(path) {
|
|
1428
|
+
if (!path.node.id) return;
|
|
1429
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
1430
|
+
if (!binding) return;
|
|
1431
|
+
const wrapper = getWrapperInfo(path, binding);
|
|
1432
|
+
if (wrapper) wrappers.push(wrapper);
|
|
1433
|
+
}
|
|
1434
|
+
});
|
|
1435
|
+
patchDefault(traverse7)(ast, {
|
|
1436
|
+
VariableDeclarator(path) {
|
|
1437
|
+
if (!t6.isIdentifier(path.node.id)) return;
|
|
1438
|
+
const initPath = path.get("init");
|
|
1439
|
+
if (!initPath || !initPath.isFunctionExpression() && !initPath.isArrowFunctionExpression()) {
|
|
1440
|
+
return;
|
|
1441
|
+
}
|
|
1442
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
1443
|
+
if (!binding || !binding.constant) return;
|
|
1444
|
+
const wrapper = getWrapperInfo(
|
|
1445
|
+
initPath,
|
|
1446
|
+
binding
|
|
1447
|
+
);
|
|
1448
|
+
if (wrapper) wrappers.push(wrapper);
|
|
1449
|
+
}
|
|
1450
|
+
});
|
|
1451
|
+
let aliasReplacedCount = 0;
|
|
1452
|
+
let wrapperReplacedCount = 0;
|
|
1453
|
+
for (const alias of aliases) {
|
|
1454
|
+
for (const referencePath of alias.aliasBinding.referencePaths) {
|
|
1455
|
+
if (isShorthandObjectKey(referencePath)) continue;
|
|
1456
|
+
const targetBinding = referencePath.scope.getBinding(alias.targetName);
|
|
1457
|
+
if (targetBinding !== alias.targetBinding) continue;
|
|
1458
|
+
referencePath.replaceWith(t6.identifier(alias.targetName));
|
|
1459
|
+
aliasReplacedCount += 1;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
const wrapperMap = /* @__PURE__ */ new Map();
|
|
1463
|
+
for (const wrapper of wrappers) {
|
|
1464
|
+
wrapperMap.set(wrapper.wrapperBinding, wrapper);
|
|
1465
|
+
}
|
|
1466
|
+
patchDefault(traverse7)(ast, {
|
|
1467
|
+
CallExpression(path) {
|
|
1468
|
+
if (!t6.isIdentifier(path.node.callee)) return;
|
|
1469
|
+
const calleeBinding = path.scope.getBinding(path.node.callee.name);
|
|
1470
|
+
if (!calleeBinding) return;
|
|
1471
|
+
const wrapper = wrapperMap.get(calleeBinding);
|
|
1472
|
+
if (!wrapper) return;
|
|
1473
|
+
const targetBinding = path.scope.getBinding(wrapper.targetName);
|
|
1474
|
+
if (targetBinding !== wrapper.targetBinding) return;
|
|
1475
|
+
if (wrapper.kind === "call") {
|
|
1476
|
+
if (path.node.arguments.length !== wrapper.paramNames.length) return;
|
|
1477
|
+
for (const arg2 of path.node.arguments) {
|
|
1478
|
+
if (t6.isSpreadElement(arg2)) return;
|
|
1479
|
+
}
|
|
1480
|
+
const nextArgs = path.node.arguments.map(
|
|
1481
|
+
(arg2) => t6.cloneNode(arg2, true)
|
|
1482
|
+
);
|
|
1483
|
+
path.replaceWith(
|
|
1484
|
+
t6.callExpression(t6.identifier(wrapper.targetName), nextArgs)
|
|
1485
|
+
);
|
|
1486
|
+
wrapperReplacedCount += 1;
|
|
1487
|
+
return;
|
|
1488
|
+
}
|
|
1489
|
+
if (path.node.arguments.length !== 1) return;
|
|
1490
|
+
const arg = path.node.arguments[0];
|
|
1491
|
+
if (!t6.isExpression(arg) || t6.isSpreadElement(arg)) return;
|
|
1492
|
+
path.replaceWith(
|
|
1493
|
+
t6.memberExpression(
|
|
1494
|
+
t6.identifier(wrapper.targetName),
|
|
1495
|
+
t6.cloneNode(arg, true),
|
|
1496
|
+
true
|
|
1497
|
+
)
|
|
1498
|
+
);
|
|
1499
|
+
wrapperReplacedCount += 1;
|
|
1500
|
+
}
|
|
1501
|
+
});
|
|
1502
|
+
return {
|
|
1503
|
+
code: patchDefault(generate7)(ast).code,
|
|
1504
|
+
aliasReplacedCount,
|
|
1505
|
+
wrapperReplacedCount
|
|
1506
|
+
};
|
|
1507
|
+
};
|
|
1508
|
+
var remove_reassign_default = createCommand((program2) => {
|
|
1509
|
+
program2.command("remove-reassign").description("Inline safe alias assignments and wrapper calls").argument("[file]", "The file to transform").option("--input, --file <file>", "The file to transform").option("--o, --output <file>", "Output file path").option("--unlimited", "Unlimited timeout").action(
|
|
1510
|
+
async (fileArgument, options) => {
|
|
1511
|
+
await timeout(
|
|
1512
|
+
async ({ finish }) => {
|
|
1513
|
+
const filename = fileArgument ?? options.file ?? await createPrompt("Enter the file path:");
|
|
1514
|
+
if (!filename) {
|
|
1515
|
+
showError("No file provided");
|
|
1516
|
+
return finish();
|
|
1517
|
+
}
|
|
1518
|
+
try {
|
|
1519
|
+
const fileContent = readFileSync8(filename, "utf8");
|
|
1520
|
+
const defaultOutputPath = createDefaultOutputPath7(filename);
|
|
1521
|
+
let outputPath = options.output;
|
|
1522
|
+
if (!outputPath) {
|
|
1523
|
+
const promptPath = (await createPrompt("Enter the output file path:"))?.trim();
|
|
1524
|
+
outputPath = promptPath || defaultOutputPath;
|
|
1525
|
+
}
|
|
1526
|
+
const loader = loading8("Removing reassign aliases...").start();
|
|
1527
|
+
try {
|
|
1528
|
+
const {
|
|
1529
|
+
code: output,
|
|
1530
|
+
aliasReplacedCount,
|
|
1531
|
+
wrapperReplacedCount
|
|
1532
|
+
} = removeReassign(fileContent, filename);
|
|
1533
|
+
writeFileSync7(outputPath, output, "utf8");
|
|
1534
|
+
loader.succeed(
|
|
1535
|
+
`Saved remove-reassign file to: ${outputPath} (${diff(fileContent, output).length} lines changed, ${aliasReplacedCount} aliases, ${wrapperReplacedCount} calls inlined)`
|
|
1536
|
+
);
|
|
1537
|
+
return finish();
|
|
1538
|
+
} catch (error) {
|
|
1539
|
+
loader.fail("Failed to apply remove-reassign transform");
|
|
1540
|
+
showError(
|
|
1541
|
+
`Error transforming file '${filename}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1542
|
+
);
|
|
1543
|
+
return finish();
|
|
1544
|
+
}
|
|
1545
|
+
} catch (error) {
|
|
1546
|
+
showError(
|
|
1547
|
+
`Error reading file '${filename}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1548
|
+
);
|
|
1549
|
+
return finish();
|
|
1550
|
+
}
|
|
1551
|
+
},
|
|
1552
|
+
options.unlimited ? null : 120 * 1e3
|
|
1553
|
+
);
|
|
1554
|
+
}
|
|
1555
|
+
);
|
|
1556
|
+
});
|
|
1557
|
+
|
|
1558
|
+
// commands/remove-unused/index.ts
|
|
1559
|
+
import { readFileSync as readFileSync9, writeFileSync as writeFileSync8 } from "fs";
|
|
1560
|
+
import { basename as basename8, dirname as dirname8, extname as extname8, join as join8 } from "path";
|
|
1561
|
+
import { parse as parse9 } from "@babel/parser";
|
|
1562
|
+
import traverse8 from "@babel/traverse";
|
|
1563
|
+
import generate8 from "@babel/generator";
|
|
1564
|
+
import * as t7 from "@babel/types";
|
|
1565
|
+
import loading9 from "loading-cli";
|
|
1566
|
+
var createDefaultOutputPath8 = (inputPath) => {
|
|
1567
|
+
const ext = extname8(inputPath);
|
|
1568
|
+
if (!ext) {
|
|
1569
|
+
return `${inputPath}.remove-unused.js`;
|
|
1570
|
+
}
|
|
1571
|
+
const base = basename8(inputPath, ext);
|
|
1572
|
+
return join8(dirname8(inputPath), `${base}.remove-unused${ext}`);
|
|
1573
|
+
};
|
|
1574
|
+
var removeUnusedVariables = (code, filename) => {
|
|
1575
|
+
const ast = parse9(code, createParseOptions(filename));
|
|
1576
|
+
let changed = false;
|
|
1577
|
+
patchDefault(traverse8)(ast, {
|
|
1334
1578
|
Scope(path) {
|
|
1335
1579
|
for (const binding of Object.values(path.scope.bindings)) {
|
|
1336
1580
|
if (!binding.referenced && binding.constantViolations.length === 0 && binding.path.key !== "handler" && !binding.path.isFunctionExpression()) {
|
|
1337
|
-
if (
|
|
1581
|
+
if (t7.isProgram(binding.scope.block) && (binding.kind === "var" || binding.kind === "hoisted")) {
|
|
1338
1582
|
continue;
|
|
1339
1583
|
}
|
|
1340
1584
|
const targets = binding.path.parentKey === "params" ? [...binding.referencePaths, ...binding.constantViolations] : [
|
|
@@ -1343,11 +1587,11 @@ var removeUnusedVariables = (code, filename) => {
|
|
|
1343
1587
|
...binding.constantViolations
|
|
1344
1588
|
];
|
|
1345
1589
|
for (const targetPath of targets) {
|
|
1346
|
-
if (targetPath.isVariableDeclarator() && (
|
|
1590
|
+
if (targetPath.isVariableDeclarator() && (t7.isArrayPattern(targetPath.node.id) && targetPath.node.id.elements.length > 1 || t7.isObjectPattern(targetPath.node.id) && targetPath.node.id.properties.length > 1)) {
|
|
1347
1591
|
continue;
|
|
1348
1592
|
}
|
|
1349
1593
|
if (targetPath.key === "consequent" || targetPath.key === "alternate" || targetPath.key === "body") {
|
|
1350
|
-
targetPath.replaceWith(
|
|
1594
|
+
targetPath.replaceWith(t7.blockStatement([]));
|
|
1351
1595
|
} else {
|
|
1352
1596
|
const parentPath = targetPath.parentPath;
|
|
1353
1597
|
if (parentPath?.isVariableDeclaration() && parentPath.node.declarations.length === 1) {
|
|
@@ -1363,7 +1607,7 @@ var removeUnusedVariables = (code, filename) => {
|
|
|
1363
1607
|
}
|
|
1364
1608
|
});
|
|
1365
1609
|
return {
|
|
1366
|
-
code: patchDefault(
|
|
1610
|
+
code: patchDefault(generate8)(ast).code,
|
|
1367
1611
|
changed
|
|
1368
1612
|
};
|
|
1369
1613
|
};
|
|
@@ -1378,20 +1622,20 @@ var remove_unused_default = createCommand((program2) => {
|
|
|
1378
1622
|
return finish();
|
|
1379
1623
|
}
|
|
1380
1624
|
try {
|
|
1381
|
-
const fileContent =
|
|
1382
|
-
const defaultOutputPath =
|
|
1625
|
+
const fileContent = readFileSync9(filename, "utf8");
|
|
1626
|
+
const defaultOutputPath = createDefaultOutputPath8(filename);
|
|
1383
1627
|
let outputPath = options.output;
|
|
1384
1628
|
if (!outputPath) {
|
|
1385
1629
|
const promptPath = (await createPrompt("Enter the output file path:"))?.trim();
|
|
1386
1630
|
outputPath = promptPath || defaultOutputPath;
|
|
1387
1631
|
}
|
|
1388
|
-
const loader =
|
|
1632
|
+
const loader = loading9("Removing unused variables...").start();
|
|
1389
1633
|
try {
|
|
1390
1634
|
const { code: output, changed } = removeUnusedVariables(
|
|
1391
1635
|
fileContent,
|
|
1392
1636
|
filename
|
|
1393
1637
|
);
|
|
1394
|
-
|
|
1638
|
+
writeFileSync8(outputPath, output, "utf8");
|
|
1395
1639
|
const diffLines = diff(fileContent, output).length;
|
|
1396
1640
|
loader.succeed(
|
|
1397
1641
|
`Saved remove-unused file to: ${outputPath} (${diffLines} lines changed${changed ? ", removed unused declarations" : ", no changes"})`
|
|
@@ -1417,6 +1661,188 @@ var remove_unused_default = createCommand((program2) => {
|
|
|
1417
1661
|
);
|
|
1418
1662
|
});
|
|
1419
1663
|
|
|
1664
|
+
// commands/fn-inliner/index.ts
|
|
1665
|
+
import { readFileSync as readFileSync10, writeFileSync as writeFileSync9 } from "fs";
|
|
1666
|
+
import { basename as basename9, dirname as dirname9, extname as extname9, join as join9 } from "path";
|
|
1667
|
+
import { parse as parse10 } from "@babel/parser";
|
|
1668
|
+
import traverse9 from "@babel/traverse";
|
|
1669
|
+
import generate9 from "@babel/generator";
|
|
1670
|
+
import * as t8 from "@babel/types";
|
|
1671
|
+
import loading10 from "loading-cli";
|
|
1672
|
+
var walk = patchDefault(traverse9);
|
|
1673
|
+
var createDefaultOutputPath9 = (inputPath) => {
|
|
1674
|
+
const ext = extname9(inputPath);
|
|
1675
|
+
if (!ext) {
|
|
1676
|
+
return `${inputPath}.fn-inliner.js`;
|
|
1677
|
+
}
|
|
1678
|
+
const base = basename9(inputPath, ext);
|
|
1679
|
+
return join9(dirname9(inputPath), `${base}.fn-inliner${ext}`);
|
|
1680
|
+
};
|
|
1681
|
+
var isProxyFunctionExpression = (node) => {
|
|
1682
|
+
return t8.isFunction(node) && node.params.every((param) => t8.isIdentifier(param)) && (t8.isBlockStatement(node.body) && node.body.body.length === 1 && t8.isReturnStatement(node.body.body[0]) && (node.body.body[0].argument === void 0 || t8.isExpression(node.body.body[0].argument) && isProxyValue(node.body.body[0].argument)) || t8.isArrowFunctionExpression(node) && t8.isExpression(node.body) && isProxyValue(node.body));
|
|
1683
|
+
};
|
|
1684
|
+
var isProxyValue = (node) => {
|
|
1685
|
+
if (t8.isFunction(node) || t8.isBlockStatement(node) || t8.isSequenceExpression(node)) {
|
|
1686
|
+
return false;
|
|
1687
|
+
}
|
|
1688
|
+
let isValid = true;
|
|
1689
|
+
walk(node, {
|
|
1690
|
+
"SequenceExpression|BlockStatement|Function|AssignmentExpression"(path) {
|
|
1691
|
+
isValid = false;
|
|
1692
|
+
path.stop();
|
|
1693
|
+
},
|
|
1694
|
+
noScope: true
|
|
1695
|
+
});
|
|
1696
|
+
return isValid;
|
|
1697
|
+
};
|
|
1698
|
+
var copyExpression = (expression) => {
|
|
1699
|
+
return t8.cloneNode(expression, true);
|
|
1700
|
+
};
|
|
1701
|
+
var ProxyFunction = class {
|
|
1702
|
+
expression;
|
|
1703
|
+
constructor(expression) {
|
|
1704
|
+
this.expression = expression;
|
|
1705
|
+
}
|
|
1706
|
+
getReplacement(args) {
|
|
1707
|
+
const expression = t8.isExpression(this.expression.body) ? copyExpression(this.expression.body) : this.expression.body.body[0].argument ? copyExpression(this.expression.body.body[0].argument) : t8.identifier("undefined");
|
|
1708
|
+
this.replaceParameters(expression, args);
|
|
1709
|
+
return expression;
|
|
1710
|
+
}
|
|
1711
|
+
replaceParameters(expression, args) {
|
|
1712
|
+
const paramMap = new Map(
|
|
1713
|
+
this.expression.params.map((param, index) => [
|
|
1714
|
+
param.name,
|
|
1715
|
+
args[index] ?? t8.identifier("undefined")
|
|
1716
|
+
])
|
|
1717
|
+
);
|
|
1718
|
+
const pathsToReplace = [];
|
|
1719
|
+
walk(expression, {
|
|
1720
|
+
enter(path) {
|
|
1721
|
+
if (t8.isIdentifier(path.node) && !(path.parentPath?.isMemberExpression() && path.key === "property") && paramMap.has(path.node.name)) {
|
|
1722
|
+
const replacement = paramMap.get(path.node.name);
|
|
1723
|
+
pathsToReplace.push([path, replacement]);
|
|
1724
|
+
}
|
|
1725
|
+
},
|
|
1726
|
+
noScope: true
|
|
1727
|
+
});
|
|
1728
|
+
for (const [path, replacement] of pathsToReplace) {
|
|
1729
|
+
path.replaceWith(t8.cloneNode(replacement, true));
|
|
1730
|
+
}
|
|
1731
|
+
}
|
|
1732
|
+
};
|
|
1733
|
+
var ProxyFunctionVariable = class extends ProxyFunction {
|
|
1734
|
+
binding;
|
|
1735
|
+
constructor(binding, expression) {
|
|
1736
|
+
super(expression);
|
|
1737
|
+
this.binding = binding;
|
|
1738
|
+
}
|
|
1739
|
+
getCalls() {
|
|
1740
|
+
return this.binding.referencePaths;
|
|
1741
|
+
}
|
|
1742
|
+
replaceCall(path) {
|
|
1743
|
+
if (!path.parentPath || !path.parentPath.isCallExpression() || path.key !== "callee") {
|
|
1744
|
+
return false;
|
|
1745
|
+
}
|
|
1746
|
+
const argumentNodes = path.parentPath.node.arguments;
|
|
1747
|
+
const args = [];
|
|
1748
|
+
for (const argument of argumentNodes) {
|
|
1749
|
+
if (!t8.isExpression(argument)) {
|
|
1750
|
+
return false;
|
|
1751
|
+
}
|
|
1752
|
+
args.push(t8.cloneNode(argument, true));
|
|
1753
|
+
}
|
|
1754
|
+
const expression = this.getReplacement(args);
|
|
1755
|
+
path.parentPath.replaceWith(expression);
|
|
1756
|
+
return true;
|
|
1757
|
+
}
|
|
1758
|
+
};
|
|
1759
|
+
var collectProxyFunctions = (ast) => {
|
|
1760
|
+
const proxies = [];
|
|
1761
|
+
walk(ast, {
|
|
1762
|
+
FunctionDeclaration(path) {
|
|
1763
|
+
if (!path.node.id) return;
|
|
1764
|
+
if (!isProxyFunctionExpression(path.node)) return;
|
|
1765
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
1766
|
+
if (!binding || !binding.constant) return;
|
|
1767
|
+
proxies.push(new ProxyFunctionVariable(binding, path.node));
|
|
1768
|
+
},
|
|
1769
|
+
VariableDeclarator(path) {
|
|
1770
|
+
if (!t8.isIdentifier(path.node.id)) return;
|
|
1771
|
+
const init = path.node.init;
|
|
1772
|
+
if (!init || !isProxyFunctionExpression(init)) return;
|
|
1773
|
+
const binding = path.scope.getBinding(path.node.id.name);
|
|
1774
|
+
if (!binding || !binding.constant) return;
|
|
1775
|
+
proxies.push(new ProxyFunctionVariable(binding, init));
|
|
1776
|
+
}
|
|
1777
|
+
});
|
|
1778
|
+
return proxies;
|
|
1779
|
+
};
|
|
1780
|
+
var inlineProxyFunctions = (code, filename) => {
|
|
1781
|
+
const ast = parse10(code, createParseOptions(filename));
|
|
1782
|
+
const proxies = collectProxyFunctions(ast);
|
|
1783
|
+
let replacedCount = 0;
|
|
1784
|
+
for (const proxy of proxies) {
|
|
1785
|
+
for (const referencePath of proxy.getCalls()) {
|
|
1786
|
+
if (referencePath.removed) continue;
|
|
1787
|
+
if (proxy.replaceCall(referencePath)) {
|
|
1788
|
+
replacedCount += 1;
|
|
1789
|
+
}
|
|
1790
|
+
}
|
|
1791
|
+
}
|
|
1792
|
+
return {
|
|
1793
|
+
code: patchDefault(generate9)(ast).code,
|
|
1794
|
+
replacedCount
|
|
1795
|
+
};
|
|
1796
|
+
};
|
|
1797
|
+
var fn_inliner_default = createCommand((program2) => {
|
|
1798
|
+
program2.command("fn-inliner").description("Inline proxy function calls into expressions").argument("[file]", "The file to transform").option("--input, --file <file>", "The file to transform").option("--o, --output <file>", "Output file path").option("--unlimited", "Unlimited timeout").action(
|
|
1799
|
+
async (fileArgument, options) => {
|
|
1800
|
+
await timeout(
|
|
1801
|
+
async ({ finish }) => {
|
|
1802
|
+
const filename = fileArgument ?? options.file ?? await createPrompt("Enter the file path:");
|
|
1803
|
+
if (!filename) {
|
|
1804
|
+
showError("No file provided");
|
|
1805
|
+
return finish();
|
|
1806
|
+
}
|
|
1807
|
+
try {
|
|
1808
|
+
const fileContent = readFileSync10(filename, "utf8");
|
|
1809
|
+
const defaultOutputPath = createDefaultOutputPath9(filename);
|
|
1810
|
+
let outputPath = options.output;
|
|
1811
|
+
if (!outputPath) {
|
|
1812
|
+
const promptPath = (await createPrompt("Enter the output file path:"))?.trim();
|
|
1813
|
+
outputPath = promptPath || defaultOutputPath;
|
|
1814
|
+
}
|
|
1815
|
+
const loader = loading10("Inlining proxy functions...").start();
|
|
1816
|
+
try {
|
|
1817
|
+
const { code: output, replacedCount } = inlineProxyFunctions(
|
|
1818
|
+
fileContent,
|
|
1819
|
+
filename
|
|
1820
|
+
);
|
|
1821
|
+
writeFileSync9(outputPath, output, "utf8");
|
|
1822
|
+
loader.succeed(
|
|
1823
|
+
`Saved fn-inliner file to: ${outputPath} (${diff(fileContent, output).length} lines changed, ${replacedCount} replacements)`
|
|
1824
|
+
);
|
|
1825
|
+
return finish();
|
|
1826
|
+
} catch (error) {
|
|
1827
|
+
loader.fail("Failed to apply fn-inliner transform");
|
|
1828
|
+
showError(
|
|
1829
|
+
`Error transforming file '${filename}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1830
|
+
);
|
|
1831
|
+
return finish();
|
|
1832
|
+
}
|
|
1833
|
+
} catch (error) {
|
|
1834
|
+
showError(
|
|
1835
|
+
`Error reading file '${filename}': ${error instanceof Error ? error.message : "Unknown error"}`
|
|
1836
|
+
);
|
|
1837
|
+
return finish();
|
|
1838
|
+
}
|
|
1839
|
+
},
|
|
1840
|
+
options.unlimited ? null : 120 * 1e3
|
|
1841
|
+
);
|
|
1842
|
+
}
|
|
1843
|
+
);
|
|
1844
|
+
});
|
|
1845
|
+
|
|
1420
1846
|
// utils/cli/showCredit.ts
|
|
1421
1847
|
import chalk3 from "chalk";
|
|
1422
1848
|
var beautify = (strings, ...values) => {
|
|
@@ -1441,10 +1867,10 @@ var calmGradienrain = (text) => {
|
|
|
1441
1867
|
const endHue = 300;
|
|
1442
1868
|
const saturation = 0.45;
|
|
1443
1869
|
const value = 0.8;
|
|
1444
|
-
const ease = (
|
|
1870
|
+
const ease = (t9) => t9 * t9 * (3 - 2 * t9);
|
|
1445
1871
|
return text.split("").map((char, i) => {
|
|
1446
|
-
const
|
|
1447
|
-
const hue = startHue + (endHue - startHue) *
|
|
1872
|
+
const t9 = ease(i / Math.max(text.length - 1, 1));
|
|
1873
|
+
const hue = startHue + (endHue - startHue) * t9;
|
|
1448
1874
|
const c = value * saturation;
|
|
1449
1875
|
const h = hue / 60;
|
|
1450
1876
|
const x = c * (1 - Math.abs(h % 2 - 1));
|
|
@@ -1468,10 +1894,10 @@ ${calmGradienrain(`Expose Kit v${VERSION}`)}
|
|
|
1468
1894
|
`;
|
|
1469
1895
|
|
|
1470
1896
|
// index.ts
|
|
1471
|
-
import { readFileSync as
|
|
1897
|
+
import { readFileSync as readFileSync11 } from "fs";
|
|
1472
1898
|
var __filename = fileURLToPath(import.meta.url);
|
|
1473
|
-
var __dirname =
|
|
1474
|
-
var pkg = JSON.parse(
|
|
1899
|
+
var __dirname = dirname10(__filename);
|
|
1900
|
+
var pkg = JSON.parse(readFileSync11(join10(__dirname, "package.json"), "utf8"));
|
|
1475
1901
|
console.log(showCredit(pkg.version));
|
|
1476
1902
|
console.log();
|
|
1477
1903
|
var program = new Command();
|
|
@@ -1488,6 +1914,8 @@ var commands = [
|
|
|
1488
1914
|
object_packer_default,
|
|
1489
1915
|
pre_evaluate_default,
|
|
1490
1916
|
remove_updater_default,
|
|
1917
|
+
remove_reassign_default,
|
|
1918
|
+
fn_inliner_default,
|
|
1491
1919
|
remove_unused_default
|
|
1492
1920
|
];
|
|
1493
1921
|
for (const command of commands) {
|
package/dist/package.json
CHANGED