@ait-co/console-cli 0.1.16 → 0.1.17
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 +12 -0
- package/dist/cli.mjs +77 -3
- package/dist/cli.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -99,3 +99,15 @@ Every command accepts `--json`. When set:
|
|
|
99
99
|
## Status
|
|
100
100
|
|
|
101
101
|
`login`, `logout`, `whoami`, and `upgrade` are implemented end-to-end — `login` drives a real browser over CDP and `whoami` reads the live console member API. `deploy`, `logs`, `status` are next — see [TODO.md](./TODO.md). See the [organization landing page](https://apps-in-toss-community.github.io/) for the full roadmap.
|
|
102
|
+
|
|
103
|
+
## Pre-commit hook
|
|
104
|
+
|
|
105
|
+
Optional but recommended. After cloning, activate the standard pre-commit hook (runs `biome check` on staged files):
|
|
106
|
+
|
|
107
|
+
```sh
|
|
108
|
+
git config core.hooksPath .githooks
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
This is a developer convenience for fast feedback before push. CI runs the same checks as the enforcement layer, so contributors who don't activate the hook will still see lint failures in their PR.
|
|
112
|
+
|
|
113
|
+
선택 사항이지만 권장합니다. clone 후 표준 pre-commit hook을 활성화하면 staged 파일에 `biome check`가 자동으로 돕니다 (push 전에 빠른 피드백). 활성화하지 않아도 동일한 검사가 CI에서 실행되므로 PR 단계에서 lint 실패를 볼 수 있습니다.
|
package/dist/cli.mjs
CHANGED
|
@@ -7,7 +7,8 @@ import { unzipSync } from "fflate";
|
|
|
7
7
|
import { parse } from "yaml";
|
|
8
8
|
import { imageSize } from "image-size";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
|
-
import { constants } from "node:fs";
|
|
10
|
+
import { constants, createReadStream } from "node:fs";
|
|
11
|
+
import { createHash } from "node:crypto";
|
|
11
12
|
//#region src/api/http.ts
|
|
12
13
|
var TossApiError = class extends Error {
|
|
13
14
|
constructor(status, errorCode, reason, errorType) {
|
|
@@ -718,7 +719,8 @@ const ExitCode = {
|
|
|
718
719
|
LoginCookieCaptureFailed: 16,
|
|
719
720
|
ApiError: 17,
|
|
720
721
|
UpgradeUnavailable: 20,
|
|
721
|
-
UpgradeAlreadyLatest: 21
|
|
722
|
+
UpgradeAlreadyLatest: 21,
|
|
723
|
+
UpgradeChecksumFailed: 22
|
|
722
724
|
};
|
|
723
725
|
//#endregion
|
|
724
726
|
//#region src/flush.ts
|
|
@@ -5459,6 +5461,9 @@ async function fetchLatestReleaseConditional(previousEtag) {
|
|
|
5459
5461
|
etag
|
|
5460
5462
|
};
|
|
5461
5463
|
}
|
|
5464
|
+
function findSha256SumsAsset(release) {
|
|
5465
|
+
return release.assets.find((a) => a.name === "SHA256SUMS");
|
|
5466
|
+
}
|
|
5462
5467
|
function versionFromTag(tag) {
|
|
5463
5468
|
const at = tag.lastIndexOf("@");
|
|
5464
5469
|
const candidate = at >= 0 ? tag.slice(at + 1) : tag;
|
|
@@ -5522,6 +5527,31 @@ function compareSemver(a, b) {
|
|
|
5522
5527
|
return pa.pre > pb.pre ? 1 : -1;
|
|
5523
5528
|
}
|
|
5524
5529
|
//#endregion
|
|
5530
|
+
//#region src/sha256.ts
|
|
5531
|
+
function parseSha256Sums(text) {
|
|
5532
|
+
const out = /* @__PURE__ */ new Map();
|
|
5533
|
+
for (const rawLine of text.split(/\r?\n/)) {
|
|
5534
|
+
const line = rawLine.trim();
|
|
5535
|
+
if (line === "" || line.startsWith("#")) continue;
|
|
5536
|
+
const match = line.match(/^([0-9a-fA-F]{64})\s+\*?(.+)$/);
|
|
5537
|
+
if (!match) continue;
|
|
5538
|
+
const hash = match[1]?.toLowerCase();
|
|
5539
|
+
const name = match[2]?.trim();
|
|
5540
|
+
if (!hash || !name) continue;
|
|
5541
|
+
out.set(name, hash);
|
|
5542
|
+
}
|
|
5543
|
+
return out;
|
|
5544
|
+
}
|
|
5545
|
+
function sha256OfFile(path) {
|
|
5546
|
+
return new Promise((resolve, reject) => {
|
|
5547
|
+
const hash = createHash("sha256");
|
|
5548
|
+
const stream = createReadStream(path);
|
|
5549
|
+
stream.on("error", reject);
|
|
5550
|
+
stream.on("data", (chunk) => hash.update(chunk));
|
|
5551
|
+
stream.on("end", () => resolve(hash.digest("hex")));
|
|
5552
|
+
});
|
|
5553
|
+
}
|
|
5554
|
+
//#endregion
|
|
5525
5555
|
//#region src/version.ts
|
|
5526
5556
|
function resolveVersion() {
|
|
5527
5557
|
try {
|
|
@@ -5529,7 +5559,7 @@ function resolveVersion() {
|
|
|
5529
5559
|
if (typeof injected === "string" && injected.length > 0) return injected;
|
|
5530
5560
|
} catch {}
|
|
5531
5561
|
try {
|
|
5532
|
-
return "0.1.
|
|
5562
|
+
return "0.1.17";
|
|
5533
5563
|
} catch {}
|
|
5534
5564
|
return "0.0.0-dev";
|
|
5535
5565
|
}
|
|
@@ -5650,6 +5680,50 @@ const upgradeCommand = defineCommand({
|
|
|
5650
5680
|
}, `Failed to download new binary: ${err.message}`);
|
|
5651
5681
|
process.exit(ExitCode.NetworkError);
|
|
5652
5682
|
}
|
|
5683
|
+
const sumsAsset = findSha256SumsAsset(release);
|
|
5684
|
+
if (!sumsAsset) {
|
|
5685
|
+
await unlink(stagingPath).catch(() => {});
|
|
5686
|
+
emitError({
|
|
5687
|
+
reason: "sums-missing",
|
|
5688
|
+
tag: release.tag_name
|
|
5689
|
+
}, `Release ${release.tag_name} has no SHA256SUMS asset. It may still be uploading; retry shortly.`);
|
|
5690
|
+
process.exit(ExitCode.UpgradeChecksumFailed);
|
|
5691
|
+
}
|
|
5692
|
+
let expected;
|
|
5693
|
+
let actual;
|
|
5694
|
+
try {
|
|
5695
|
+
const sumsRes = await fetch(sumsAsset.browser_download_url);
|
|
5696
|
+
if (!sumsRes.ok) throw new Error(`SHA256SUMS download failed: ${sumsRes.status} ${sumsRes.statusText}`);
|
|
5697
|
+
expected = parseSha256Sums(await sumsRes.text()).get(platform.assetName);
|
|
5698
|
+
actual = (await sha256OfFile(stagingPath)).toLowerCase();
|
|
5699
|
+
} catch (err) {
|
|
5700
|
+
await unlink(stagingPath).catch(() => {});
|
|
5701
|
+
emitError({
|
|
5702
|
+
reason: "sums-fetch-failed",
|
|
5703
|
+
message: err.message
|
|
5704
|
+
}, `Failed to verify checksum: ${err.message}`);
|
|
5705
|
+
process.exit(ExitCode.UpgradeChecksumFailed);
|
|
5706
|
+
}
|
|
5707
|
+
if (!expected) {
|
|
5708
|
+
await unlink(stagingPath).catch(() => {});
|
|
5709
|
+
emitError({
|
|
5710
|
+
reason: "sums-no-entry",
|
|
5711
|
+
assetName: platform.assetName,
|
|
5712
|
+
tag: release.tag_name
|
|
5713
|
+
}, `SHA256SUMS for ${release.tag_name} has no entry for ${platform.assetName}.`);
|
|
5714
|
+
process.exit(ExitCode.UpgradeChecksumFailed);
|
|
5715
|
+
}
|
|
5716
|
+
if (expected.toLowerCase() !== actual) {
|
|
5717
|
+
await unlink(stagingPath).catch(() => {});
|
|
5718
|
+
emitError({
|
|
5719
|
+
reason: "sha256-mismatch",
|
|
5720
|
+
assetName: platform.assetName,
|
|
5721
|
+
expected: expected.toLowerCase(),
|
|
5722
|
+
actual
|
|
5723
|
+
}, `Checksum mismatch for ${platform.assetName}: expected ${expected.toLowerCase()}, got ${actual}.`);
|
|
5724
|
+
process.exit(ExitCode.UpgradeChecksumFailed);
|
|
5725
|
+
}
|
|
5726
|
+
if (!args.json) process.stdout.write("Checksum OK.\n");
|
|
5653
5727
|
try {
|
|
5654
5728
|
if (process.platform === "win32") {
|
|
5655
5729
|
await rename(exePath, `${exePath}.old`);
|