@ucdjs/release-scripts 0.1.0-beta.17 → 0.1.0-beta.18
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/dist/index.d.mts +8 -2
- package/dist/index.mjs +171 -35
- package/package.json +3 -1
package/dist/index.d.mts
CHANGED
|
@@ -180,7 +180,13 @@ interface ReleaseResult {
|
|
|
180
180
|
declare function release(options: ReleaseOptions): Promise<ReleaseResult | null>;
|
|
181
181
|
//#endregion
|
|
182
182
|
//#region src/verify.d.ts
|
|
183
|
-
interface VerifyOptions extends SharedOptions {
|
|
184
|
-
|
|
183
|
+
interface VerifyOptions extends SharedOptions {
|
|
184
|
+
branch?: {
|
|
185
|
+
release?: string;
|
|
186
|
+
default?: string;
|
|
187
|
+
};
|
|
188
|
+
safeguards?: boolean;
|
|
189
|
+
}
|
|
190
|
+
declare function verify(options: VerifyOptions): Promise<void>;
|
|
185
191
|
//#endregion
|
|
186
192
|
export { type PublishOptions, type ReleaseOptions, type ReleaseResult, type VerifyOptions, publish, release, verify };
|
package/dist/index.mjs
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import { t as Eta } from "./eta-j5TFRbI4.mjs";
|
|
2
|
-
import { readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
3
|
import { join, relative } from "node:path";
|
|
4
4
|
import process from "node:process";
|
|
5
|
+
import readline from "node:readline";
|
|
5
6
|
import farver from "farver";
|
|
6
7
|
import mri from "mri";
|
|
7
8
|
import { exec } from "tinyexec";
|
|
8
9
|
import { dedent } from "@luxass/utils";
|
|
9
10
|
import { getCommits, groupByType } from "commit-parser";
|
|
10
11
|
import prompts from "prompts";
|
|
12
|
+
import { gt } from "semver";
|
|
11
13
|
|
|
12
14
|
//#region src/publish.ts
|
|
13
15
|
function publish(_options) {}
|
|
@@ -57,6 +59,13 @@ const logger = {
|
|
|
57
59
|
},
|
|
58
60
|
success: (message) => {
|
|
59
61
|
console.log(` ${farver.green("✓")} ${message}`);
|
|
62
|
+
},
|
|
63
|
+
clearScreen: () => {
|
|
64
|
+
const repeatCount = process.stdout.rows - 2;
|
|
65
|
+
const blank = repeatCount > 0 ? "\n".repeat(repeatCount) : "";
|
|
66
|
+
console.log(blank);
|
|
67
|
+
readline.cursorTo(process.stdout, 0, 0);
|
|
68
|
+
readline.clearScreenDown(process.stdout);
|
|
60
69
|
}
|
|
61
70
|
};
|
|
62
71
|
async function run(bin, args$1, opts = {}) {
|
|
@@ -386,6 +395,7 @@ async function getGroupedFilesByCommitSha(workspaceRoot, from, to) {
|
|
|
386
395
|
|
|
387
396
|
//#endregion
|
|
388
397
|
//#region src/core/changelog.ts
|
|
398
|
+
const globalAuthorCache = /* @__PURE__ */ new Map();
|
|
389
399
|
const DEFAULT_CHANGELOG_TEMPLATE = dedent`
|
|
390
400
|
<% if (it.previousVersion) { -%>
|
|
391
401
|
## [<%= it.version %>](<%= it.compareUrl %>) (<%= it.date %>)
|
|
@@ -492,24 +502,28 @@ async function updateChangelog(options) {
|
|
|
492
502
|
await writeFile(changelogPath, updatedContent, "utf-8");
|
|
493
503
|
}
|
|
494
504
|
async function resolveCommitAuthors(commits, githubClient) {
|
|
495
|
-
const
|
|
505
|
+
const authorsToResolve = /* @__PURE__ */ new Set();
|
|
496
506
|
const commitAuthors = /* @__PURE__ */ new Map();
|
|
497
507
|
for (const commit of commits) {
|
|
498
508
|
const authorsForCommit = [];
|
|
499
509
|
commit.authors.forEach((author, idx) => {
|
|
500
510
|
if (!author.email || !author.name) return;
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
511
|
+
let info = globalAuthorCache.get(author.email);
|
|
512
|
+
if (!info) {
|
|
513
|
+
info = {
|
|
514
|
+
commits: [],
|
|
515
|
+
name: author.name,
|
|
516
|
+
email: author.email
|
|
517
|
+
};
|
|
518
|
+
globalAuthorCache.set(author.email, info);
|
|
519
|
+
}
|
|
507
520
|
if (idx === 0) info.commits.push(commit.shortHash);
|
|
508
521
|
authorsForCommit.push(info);
|
|
522
|
+
if (!info.login) authorsToResolve.add(info);
|
|
509
523
|
});
|
|
510
524
|
commitAuthors.set(commit.hash, authorsForCommit);
|
|
511
525
|
}
|
|
512
|
-
await Promise.all(Array.from(
|
|
526
|
+
await Promise.all(Array.from(authorsToResolve).map((info) => githubClient.resolveAuthorInfo(info)));
|
|
513
527
|
return commitAuthors;
|
|
514
528
|
}
|
|
515
529
|
function formatCommitLine({ commit, owner, repo, authors }) {
|
|
@@ -1087,9 +1101,16 @@ function formatCommitsForDisplay(commits) {
|
|
|
1087
1101
|
/**
|
|
1088
1102
|
* Calculate version updates for packages based on their commits
|
|
1089
1103
|
*/
|
|
1090
|
-
async function calculateVersionUpdates({ workspacePackages, packageCommits, workspaceRoot, showPrompt, globalCommitsPerPackage }) {
|
|
1104
|
+
async function calculateVersionUpdates({ workspacePackages, packageCommits, workspaceRoot, showPrompt, globalCommitsPerPackage, overrides: initialOverrides = {} }) {
|
|
1091
1105
|
const versionUpdates = [];
|
|
1092
1106
|
const processedPackages = /* @__PURE__ */ new Set();
|
|
1107
|
+
const newOverrides = { ...initialOverrides };
|
|
1108
|
+
const bumpRanks = {
|
|
1109
|
+
major: 3,
|
|
1110
|
+
minor: 2,
|
|
1111
|
+
patch: 1,
|
|
1112
|
+
none: 0
|
|
1113
|
+
};
|
|
1093
1114
|
logger.verbose(`Starting version inference for ${packageCommits.size} packages with commits`);
|
|
1094
1115
|
for (const [pkgName, pkgCommits] of packageCommits) {
|
|
1095
1116
|
const pkg = workspacePackages.find((p) => p.name === pkgName);
|
|
@@ -1099,30 +1120,39 @@ async function calculateVersionUpdates({ workspacePackages, packageCommits, work
|
|
|
1099
1120
|
}
|
|
1100
1121
|
processedPackages.add(pkgName);
|
|
1101
1122
|
const globalCommits = globalCommitsPerPackage.get(pkgName) || [];
|
|
1102
|
-
if (globalCommits.length > 0) logger.verbose(` - Global commits for this package: ${globalCommits.length}`);
|
|
1103
1123
|
const allCommitsForPackage = [...pkgCommits, ...globalCommits];
|
|
1104
|
-
const
|
|
1105
|
-
|
|
1106
|
-
|
|
1124
|
+
const determinedBump = determineHighestBump(allCommitsForPackage);
|
|
1125
|
+
const effectiveBump = newOverrides[pkgName] || determinedBump;
|
|
1126
|
+
if (effectiveBump === "none") continue;
|
|
1127
|
+
let newVersion = getNextVersion(pkg.version, effectiveBump);
|
|
1107
1128
|
if (!isCI && showPrompt) {
|
|
1108
|
-
logger.
|
|
1129
|
+
logger.clearScreen();
|
|
1130
|
+
logger.section(`📝 Commits for ${farver.cyan(pkg.name)}`);
|
|
1109
1131
|
formatCommitsForDisplay(allCommitsForPackage).split("\n").forEach((line) => logger.item(line));
|
|
1110
1132
|
logger.emptyLine();
|
|
1111
1133
|
const selectedVersion = await selectVersionPrompt(workspaceRoot, pkg, pkg.version, newVersion);
|
|
1112
1134
|
if (selectedVersion === null) continue;
|
|
1135
|
+
const userBump = _calculateBumpType(pkg.version, selectedVersion);
|
|
1136
|
+
if (bumpRanks[userBump] < bumpRanks[determinedBump]) {
|
|
1137
|
+
newOverrides[pkgName] = userBump;
|
|
1138
|
+
logger.info(`Version override recorded for ${pkgName}: ${determinedBump} → ${userBump}`);
|
|
1139
|
+
} else if (newOverrides[pkgName] && bumpRanks[userBump] >= bumpRanks[determinedBump]) {
|
|
1140
|
+
delete newOverrides[pkgName];
|
|
1141
|
+
logger.info(`Version override removed for ${pkgName}.`);
|
|
1142
|
+
}
|
|
1113
1143
|
newVersion = selectedVersion;
|
|
1114
1144
|
}
|
|
1115
|
-
logger.verbose(`Version update: ${pkg.version} → ${newVersion}`);
|
|
1116
1145
|
versionUpdates.push({
|
|
1117
1146
|
package: pkg,
|
|
1118
1147
|
currentVersion: pkg.version,
|
|
1119
1148
|
newVersion,
|
|
1120
|
-
bumpType:
|
|
1121
|
-
hasDirectChanges:
|
|
1149
|
+
bumpType: effectiveBump,
|
|
1150
|
+
hasDirectChanges: allCommitsForPackage.length > 0
|
|
1122
1151
|
});
|
|
1123
1152
|
}
|
|
1124
1153
|
if (!isCI && showPrompt) for (const pkg of workspacePackages) {
|
|
1125
1154
|
if (processedPackages.has(pkg.name)) continue;
|
|
1155
|
+
logger.clearScreen();
|
|
1126
1156
|
logger.section(`📦 Package: ${pkg.name}`);
|
|
1127
1157
|
logger.item("No direct commits found");
|
|
1128
1158
|
const newVersion = await selectVersionPrompt(workspaceRoot, pkg, pkg.version, pkg.version);
|
|
@@ -1138,19 +1168,23 @@ async function calculateVersionUpdates({ workspacePackages, packageCommits, work
|
|
|
1138
1168
|
});
|
|
1139
1169
|
}
|
|
1140
1170
|
}
|
|
1141
|
-
return
|
|
1171
|
+
return {
|
|
1172
|
+
updates: versionUpdates,
|
|
1173
|
+
overrides: newOverrides
|
|
1174
|
+
};
|
|
1142
1175
|
}
|
|
1143
1176
|
/**
|
|
1144
1177
|
* Calculate version updates and prepare dependent updates
|
|
1145
1178
|
* Returns both the updates and a function to apply them
|
|
1146
1179
|
*/
|
|
1147
|
-
async function calculateAndPrepareVersionUpdates({ workspacePackages, packageCommits, workspaceRoot, showPrompt, globalCommitsPerPackage }) {
|
|
1148
|
-
const directUpdates = await calculateVersionUpdates({
|
|
1180
|
+
async function calculateAndPrepareVersionUpdates({ workspacePackages, packageCommits, workspaceRoot, showPrompt, globalCommitsPerPackage, overrides }) {
|
|
1181
|
+
const { updates: directUpdates, overrides: newOverrides } = await calculateVersionUpdates({
|
|
1149
1182
|
workspacePackages,
|
|
1150
1183
|
packageCommits,
|
|
1151
1184
|
workspaceRoot,
|
|
1152
1185
|
showPrompt,
|
|
1153
|
-
globalCommitsPerPackage
|
|
1186
|
+
globalCommitsPerPackage,
|
|
1187
|
+
overrides
|
|
1154
1188
|
});
|
|
1155
1189
|
const allUpdates = createDependentUpdates(buildPackageDependencyGraph(workspacePackages), workspacePackages, directUpdates);
|
|
1156
1190
|
const applyUpdates = async () => {
|
|
@@ -1161,7 +1195,8 @@ async function calculateAndPrepareVersionUpdates({ workspacePackages, packageCom
|
|
|
1161
1195
|
};
|
|
1162
1196
|
return {
|
|
1163
1197
|
allUpdates,
|
|
1164
|
-
applyUpdates
|
|
1198
|
+
applyUpdates,
|
|
1199
|
+
overrides: newOverrides
|
|
1165
1200
|
};
|
|
1166
1201
|
}
|
|
1167
1202
|
async function updatePackageJson(pkg, newVersion, dependencyUpdates) {
|
|
@@ -1458,17 +1493,6 @@ async function release(options) {
|
|
|
1458
1493
|
logger.emptyLine();
|
|
1459
1494
|
const groupedPackageCommits = await getWorkspacePackageGroupedCommits(workspaceRoot, workspacePackages);
|
|
1460
1495
|
const globalCommitsPerPackage = await getGlobalCommitsPerPackage(workspaceRoot, groupedPackageCommits, workspacePackages, normalizedOptions.globalCommitMode);
|
|
1461
|
-
const { allUpdates, applyUpdates } = await calculateAndPrepareVersionUpdates({
|
|
1462
|
-
workspacePackages,
|
|
1463
|
-
packageCommits: groupedPackageCommits,
|
|
1464
|
-
workspaceRoot,
|
|
1465
|
-
showPrompt: options.prompts?.versions !== false,
|
|
1466
|
-
globalCommitsPerPackage
|
|
1467
|
-
});
|
|
1468
|
-
if (allUpdates.filter((u) => u.hasDirectChanges).length === 0) logger.warn("No packages have changes requiring a release");
|
|
1469
|
-
logger.section("🔄 Version Updates");
|
|
1470
|
-
logger.item(`Updating ${allUpdates.length} packages (including dependents)`);
|
|
1471
|
-
for (const update of allUpdates) logger.item(`${update.package.name}: ${update.currentVersion} → ${update.newVersion}`);
|
|
1472
1496
|
const githubClient = createGitHubClient({
|
|
1473
1497
|
owner: normalizedOptions.owner,
|
|
1474
1498
|
repo: normalizedOptions.repo,
|
|
@@ -1483,6 +1507,38 @@ async function release(options) {
|
|
|
1483
1507
|
pullRequestBody: options.pullRequest?.body
|
|
1484
1508
|
});
|
|
1485
1509
|
await prOps.prepareBranch();
|
|
1510
|
+
const overridesPath = join(workspaceRoot, ".github", "ucdjs.release.overrides.json");
|
|
1511
|
+
let existingOverrides = {};
|
|
1512
|
+
try {
|
|
1513
|
+
const overridesContent = await readFile(overridesPath, "utf-8");
|
|
1514
|
+
existingOverrides = JSON.parse(overridesContent);
|
|
1515
|
+
logger.info("Found existing version overrides file.");
|
|
1516
|
+
} catch {
|
|
1517
|
+
logger.info("No existing version overrides file found. Continuing...");
|
|
1518
|
+
}
|
|
1519
|
+
const { allUpdates, applyUpdates, overrides: newOverrides } = await calculateAndPrepareVersionUpdates({
|
|
1520
|
+
workspacePackages,
|
|
1521
|
+
packageCommits: groupedPackageCommits,
|
|
1522
|
+
workspaceRoot,
|
|
1523
|
+
showPrompt: options.prompts?.versions !== false,
|
|
1524
|
+
globalCommitsPerPackage,
|
|
1525
|
+
overrides: existingOverrides
|
|
1526
|
+
});
|
|
1527
|
+
if (Object.keys(newOverrides).length > 0) {
|
|
1528
|
+
logger.info("Writing version overrides file...");
|
|
1529
|
+
try {
|
|
1530
|
+
await mkdir(join(workspaceRoot, ".github"), { recursive: true });
|
|
1531
|
+
await writeFile(overridesPath, JSON.stringify(newOverrides, null, 2), "utf-8");
|
|
1532
|
+
logger.success("Successfully wrote version overrides file.");
|
|
1533
|
+
} catch (e) {
|
|
1534
|
+
logger.error("Failed to write version overrides file:", e);
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
if (allUpdates.filter((u) => u.hasDirectChanges).length === 0) logger.warn("No packages have changes requiring a release");
|
|
1538
|
+
logger.section("🔄 Version Updates");
|
|
1539
|
+
logger.item(`Updating ${allUpdates.length} packages (including dependents)`);
|
|
1540
|
+
for (const update of allUpdates) logger.item(`${update.package.name}: ${update.currentVersion} → ${update.newVersion}`);
|
|
1541
|
+
await prOps.prepareBranch();
|
|
1486
1542
|
await applyUpdates();
|
|
1487
1543
|
if (normalizedOptions.changelog.enabled) {
|
|
1488
1544
|
logger.step("Updating changelogs");
|
|
@@ -1593,7 +1649,87 @@ async function orchestrateReleasePullRequest({ workspaceRoot, githubClient, rele
|
|
|
1593
1649
|
|
|
1594
1650
|
//#endregion
|
|
1595
1651
|
//#region src/verify.ts
|
|
1596
|
-
function verify(
|
|
1652
|
+
async function verify(options) {
|
|
1653
|
+
const { workspaceRoot,...normalizedOptions } = await normalizeReleaseOptions(options);
|
|
1654
|
+
if (normalizedOptions.safeguards && !await isWorkingDirectoryClean(workspaceRoot)) exitWithError("Working directory is not clean. Please commit or stash your changes before proceeding.");
|
|
1655
|
+
const githubClient = createGitHubClient({
|
|
1656
|
+
owner: normalizedOptions.owner,
|
|
1657
|
+
repo: normalizedOptions.repo,
|
|
1658
|
+
githubToken: normalizedOptions.githubToken
|
|
1659
|
+
});
|
|
1660
|
+
const releaseBranch = normalizedOptions.branch.release;
|
|
1661
|
+
const defaultBranch = normalizedOptions.branch.default;
|
|
1662
|
+
const releasePr = await githubClient.getExistingPullRequest(releaseBranch);
|
|
1663
|
+
if (!releasePr || !releasePr.head) {
|
|
1664
|
+
logger.warn(`No open release pull request found for branch "${releaseBranch}". Nothing to verify.`);
|
|
1665
|
+
return;
|
|
1666
|
+
}
|
|
1667
|
+
logger.info(`Found release PR #${releasePr.number}. Verifying against default branch "${defaultBranch}"...`);
|
|
1668
|
+
const originalBranch = await getCurrentBranch(workspaceRoot);
|
|
1669
|
+
if (originalBranch !== defaultBranch) await checkoutBranch(defaultBranch, workspaceRoot);
|
|
1670
|
+
const overridesPath = join(".github", "ucdjs.release.overrides.json");
|
|
1671
|
+
let existingOverrides = {};
|
|
1672
|
+
try {
|
|
1673
|
+
const overridesContent = await readFileFromGit(workspaceRoot, releasePr.head.sha, overridesPath);
|
|
1674
|
+
if (overridesContent) {
|
|
1675
|
+
existingOverrides = JSON.parse(overridesContent);
|
|
1676
|
+
logger.info("Found existing version overrides file on release branch.");
|
|
1677
|
+
}
|
|
1678
|
+
} catch {
|
|
1679
|
+
logger.info("No version overrides file found on release branch. Continuing...");
|
|
1680
|
+
}
|
|
1681
|
+
const mainPackages = await discoverWorkspacePackages(workspaceRoot, options);
|
|
1682
|
+
const mainCommits = await getWorkspacePackageGroupedCommits(workspaceRoot, mainPackages);
|
|
1683
|
+
const { allUpdates: expectedUpdates } = await calculateAndPrepareVersionUpdates({
|
|
1684
|
+
workspacePackages: mainPackages,
|
|
1685
|
+
packageCommits: mainCommits,
|
|
1686
|
+
workspaceRoot,
|
|
1687
|
+
showPrompt: false,
|
|
1688
|
+
globalCommitsPerPackage: await getGlobalCommitsPerPackage(workspaceRoot, mainCommits, mainPackages, normalizedOptions.globalCommitMode),
|
|
1689
|
+
overrides: existingOverrides
|
|
1690
|
+
});
|
|
1691
|
+
const expectedVersionMap = new Map(expectedUpdates.map((u) => [u.package.name, u.newVersion]));
|
|
1692
|
+
const prVersionMap = /* @__PURE__ */ new Map();
|
|
1693
|
+
for (const pkg of mainPackages) {
|
|
1694
|
+
const pkgJsonPath = join(pkg.path.replace(workspaceRoot, ""), "package.json").substring(1);
|
|
1695
|
+
const pkgJsonContent = await readFileFromGit(workspaceRoot, releasePr.head.sha, pkgJsonPath);
|
|
1696
|
+
if (pkgJsonContent) {
|
|
1697
|
+
const pkgJson = JSON.parse(pkgJsonContent);
|
|
1698
|
+
prVersionMap.set(pkg.name, pkgJson.version);
|
|
1699
|
+
}
|
|
1700
|
+
}
|
|
1701
|
+
if (originalBranch !== defaultBranch) await checkoutBranch(originalBranch, workspaceRoot);
|
|
1702
|
+
let isOutOfSync = false;
|
|
1703
|
+
for (const [pkgName, expectedVersion] of expectedVersionMap.entries()) {
|
|
1704
|
+
const prVersion = prVersionMap.get(pkgName);
|
|
1705
|
+
if (!prVersion) {
|
|
1706
|
+
logger.warn(`Package "${pkgName}" found in default branch but not in release branch. Skipping.`);
|
|
1707
|
+
continue;
|
|
1708
|
+
}
|
|
1709
|
+
if (gt(expectedVersion, prVersion)) {
|
|
1710
|
+
logger.error(`Package "${pkgName}" is out of sync. Expected version >= ${expectedVersion}, but PR has ${prVersion}.`);
|
|
1711
|
+
isOutOfSync = true;
|
|
1712
|
+
} else logger.success(`Package "${pkgName}" is up to date (PR version: ${prVersion}, Expected: ${expectedVersion})`);
|
|
1713
|
+
}
|
|
1714
|
+
const statusContext = "ucdjs/release-verify";
|
|
1715
|
+
if (isOutOfSync) {
|
|
1716
|
+
await githubClient.setCommitStatus({
|
|
1717
|
+
sha: releasePr.head.sha,
|
|
1718
|
+
state: "failure",
|
|
1719
|
+
context: statusContext,
|
|
1720
|
+
description: "Release PR is out of sync with the default branch. Please re-run the release process."
|
|
1721
|
+
});
|
|
1722
|
+
logger.error("Verification failed. Commit status set to 'failure'.");
|
|
1723
|
+
} else {
|
|
1724
|
+
await githubClient.setCommitStatus({
|
|
1725
|
+
sha: releasePr.head.sha,
|
|
1726
|
+
state: "success",
|
|
1727
|
+
context: statusContext,
|
|
1728
|
+
description: "Release PR is up to date."
|
|
1729
|
+
});
|
|
1730
|
+
logger.success("Verification successful. Commit status set to 'success'.");
|
|
1731
|
+
}
|
|
1732
|
+
}
|
|
1597
1733
|
|
|
1598
1734
|
//#endregion
|
|
1599
1735
|
export { publish, release, verify };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ucdjs/release-scripts",
|
|
3
|
-
"version": "0.1.0-beta.
|
|
3
|
+
"version": "0.1.0-beta.18",
|
|
4
4
|
"description": "@ucdjs release scripts",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,12 +32,14 @@
|
|
|
32
32
|
"farver": "1.0.0-beta.1",
|
|
33
33
|
"mri": "1.2.0",
|
|
34
34
|
"prompts": "2.4.2",
|
|
35
|
+
"semver": "7.7.3",
|
|
35
36
|
"tinyexec": "1.0.2"
|
|
36
37
|
},
|
|
37
38
|
"devDependencies": {
|
|
38
39
|
"@luxass/eslint-config": "6.0.1",
|
|
39
40
|
"@types/node": "22.18.12",
|
|
40
41
|
"@types/prompts": "2.4.9",
|
|
42
|
+
"@types/semver": "7.7.1",
|
|
41
43
|
"eslint": "9.39.1",
|
|
42
44
|
"eta": "4.0.1",
|
|
43
45
|
"tsdown": "0.16.0",
|