@bstage-sdk/cli 0.8.3 → 0.8.5
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/MIGRATION.md +57 -0
- package/dist/index.js +364 -140
- package/package.json +4 -4
package/dist/MIGRATION.md
CHANGED
|
@@ -51,6 +51,63 @@
|
|
|
51
51
|
|
|
52
52
|
---
|
|
53
53
|
|
|
54
|
+
## → cli 0.8.5 · ai-toolkit 0.8.5
|
|
55
|
+
|
|
56
|
+
### `bstage doctor`: 포털 진단이 실패해도 종료 코드 1 — `자동` · `선택`
|
|
57
|
+
|
|
58
|
+
**영향**
|
|
59
|
+
|
|
60
|
+
- CI·스크립트·에이전트가 `bstage doctor`의 종료 코드를 보는 프로젝트. 로그인·링크가 없는 환경(포털 진단 `skipped`)은 영향이 없다.
|
|
61
|
+
|
|
62
|
+
**변경 내용**
|
|
63
|
+
|
|
64
|
+
- 포털 진단 자체가 실패하면 — 배치 목록 조회 실패, 일부 배치 진단의 권한 부족(403)·서버 오류(5xx) 등으로 `portal.status`가 `"error"`면 — 종료 코드 **1**로 끝난다. 전에는 `error` 심각도 항목이 없으면 0이라, 진단을 못 끝낸 것을 "문제 없음"으로 읽을 수 있었다.
|
|
65
|
+
- 그대로인 것: `error` 항목이 있으면 1, 건너뜀(`skipped`)·서버 미지원(`unsupported`)·`warn`/`info`만 있으면 0, 로컬 진단 결과는 종료 코드에 영향 없음.
|
|
66
|
+
|
|
67
|
+
**적용**
|
|
68
|
+
|
|
69
|
+
1. (자동) CLI를 올린다. 종료 코드 1을 실패로 처리하던 CI는 그대로 동작한다. 1이 나오면 `--json`의 `portal.status`·`portal.reason`·`portal.placements[].error`로 원인을 본다(권한 부족이면 스테이지 관리 권한이 있는 계정·토큰인지 확인).
|
|
70
|
+
|
|
71
|
+
### 어드민 템플릿도 `BstageClient`로 어드민 API를 부른다(에이전트 안내 정정) — `자동`
|
|
72
|
+
|
|
73
|
+
**영향**
|
|
74
|
+
|
|
75
|
+
- 코드·빌드 동작은 바뀌지 않는다. 에이전트 안내 문서만 바로잡았다.
|
|
76
|
+
- `AGENTS.md` 관리 영역과 `bstage-template` 스킬이 "BstageClient는 유저단 API만 지원하고 어드민용 API는 미지원"이라고 안내했다. 어드민 게이트웨이가 열린 지금 이 문구를 따르면 에이전트가 어드민 템플릿의 데이터 호출을 거부하거나 사용자 확인을 되풀이한다.
|
|
77
|
+
|
|
78
|
+
**변경 내용**
|
|
79
|
+
|
|
80
|
+
- 어드민 템플릿도 같은 `BstageClient`를 쓴다. 어드민 도메인에 임베드되면 `baseUrl` 기본값이 어드민 게이트웨이(`/gw`)가 되고, 게이트웨이가 어드민 로그인 쿠키와 MANAGEMENT 키(`bsm_`)를 함께 확인한다. PUBLIC 키로는 `KEY_TYPE_NOT_ALLOWED`다.
|
|
81
|
+
- 호출 가능한 경로는 포털 API 레퍼런스(유저/운영자 탭)에 있는 것뿐이며, 목록에 없는 API는 경로를 추측하지 말고 사용자에게 먼저 확인한다는 안내는 그대로다.
|
|
82
|
+
- **AGENTS.md 관리 영역 v17**: 파일 트리의 `client.ts` 설명과 API 금지 사항 절을 위 내용으로 고쳤다. `bstage-template` 스킬도 같은 내용으로 고쳤다. 상세는 [GETTING_STARTED.md](./GETTING_STARTED.md) "8. 어드민 템플릿 › API 호출".
|
|
83
|
+
|
|
84
|
+
**적용**
|
|
85
|
+
|
|
86
|
+
1. (자동) `npx @bstage-sdk/cli@latest ai update` — 스킬·`AGENTS.md` 관리 영역을 v17로 갱신한다.
|
|
87
|
+
|
|
88
|
+
## → cli 0.8.4 · ai-toolkit 0.8.4
|
|
89
|
+
|
|
90
|
+
### `bstage doctor`가 포털 배치 진단을 함께 본다 — `자동` · `선택`
|
|
91
|
+
|
|
92
|
+
**영향**
|
|
93
|
+
|
|
94
|
+
- 로그인(`bstage login`)·링크(`bstage link`)된 디렉터리에서 `bstage doctor`를 실행하는 모든 프로젝트. 로그인·링크가 없으면 지금과 같다(포털 진단 절만 "건너뜀"으로 표시).
|
|
95
|
+
- **종료 코드가 새로 생긴다.** 포털 진단에 `error` 심각도 항목이 하나라도 있으면 `bstage doctor`가 **1**로 끝난다. 예전엔 항상 0이었다. CI·스크립트에서 doctor의 종료 코드를 실패로 처리하고 있다면 확인한다(로컬 진단 결과는 여전히 종료 코드에 영향이 없다).
|
|
96
|
+
- 감지: `bstage doctor --json` 출력에 `portal` 필드가 있으면 이 버전 이상이다.
|
|
97
|
+
|
|
98
|
+
**변경 내용**
|
|
99
|
+
|
|
100
|
+
- 로컬 진단 뒤에 **"포털 진단"** 절이 붙는다. 이 레포(링크된 레포)의 배치마다 포털이 판정한 문제를 심각도(`✗` error · `!` warn · `·` info), 제목, 상세, 조치와 함께 보여 준다 — 스테이지 커스텀 페이지 꺼짐, 배치 게시 꺼짐, 게시된 빌드 없음, 게시 빌드의 APP ID·KEY 문제(만료·스코프·짝 불일치·앞뒤 공백), 다시 빌드하지 않은 환경변수, 반영하지 않은 새 성공 빌드, 최신 빌드 실패 등. 문제가 없으면 `✓ 문제 없음`이다.
|
|
101
|
+
- 배치는 30개까지(동시 4개) 진단한다. **`--placement <id|경로|슬롯 id>`**로 하나만 볼 수 있다(`bstage deploy --placement`와 같은 정확 일치). `--placement`를 줬는데 링크가 없으면 종료 코드 2, 토큰이 없으면 3이다.
|
|
102
|
+
- `--json`(stdout 객체 하나)에 **`portal`** 필드가 더해진다(기존 필드는 그대로): `{ status: 'ok'|'skipped'|'unsupported'|'error', reason?, hint?, omitted?, placements: [{ placementId, path, slotId, surface, findings: [{ id, severity, title, detail?, fix?, evidence? }], error? }] }`. `findings[].id`(예: `appkey.expired`, `placement.not_deployed`)는 바뀌지 않는 식별자라 스크립트·에이전트가 분기에 쓸 수 있다. 진단 요청이 실패한 배치는 `error`에 이유가 담기고 `status`는 `error`다.
|
|
103
|
+
- 포털 서버가 아직 진단을 지원하지 않으면(`status: 'unsupported'`) 그 절만 건너뛴다. CLI 토큰은 `read` 등급이면 된다.
|
|
104
|
+
- `bstage-deploy` 스킬: 배포 후 401이 나거나 페이지가 기대와 다르면 `bstage doctor --json`부터 실행해 `portal.placements[].findings`의 `id`·`fix`를 따르도록 안내한다.
|
|
105
|
+
|
|
106
|
+
**적용**
|
|
107
|
+
|
|
108
|
+
1. (자동) CLI를 올리면 된다. 스킬 문구는 `npx @bstage-sdk/cli@latest ai update`로 갱신한다.
|
|
109
|
+
2. (판단) CI에서 `bstage doctor`를 돌리고 있다면 새 종료 코드 1을 실패로 볼지 정한다. 로그인·링크가 없는 CI라면 영향이 없다.
|
|
110
|
+
|
|
54
111
|
## → cli 0.8.3 · ai-toolkit 0.8.3
|
|
55
112
|
|
|
56
113
|
### sandbox 포털 기본 주소가 공개 주소로 바뀌었다 — `자동`
|
package/dist/index.js
CHANGED
|
@@ -156,6 +156,18 @@ var PortalClient = class {
|
|
|
156
156
|
);
|
|
157
157
|
return unwrap(body, "placements");
|
|
158
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* `GET .../placements/{id}/diagnosis` — 배치 하나가 "왜 기대대로 안 뜨는가"를 서버가 판정한 결과.
|
|
161
|
+
* 이 경로가 없는 구버전 서버는 404(CLI 토큰이면 등급 허용 목록 403)로 답한다 — 해석은 호출자 몫이다.
|
|
162
|
+
* `findings`가 빠진 응답도 빈 배열로 맞춰 호출자가 분기하지 않게 한다.
|
|
163
|
+
*/
|
|
164
|
+
async getPlacementDiagnosis(org, space, placementId) {
|
|
165
|
+
const d = await this.json(
|
|
166
|
+
"GET",
|
|
167
|
+
`${this.stage(org, space)}/placements/${enc(placementId)}/diagnosis`
|
|
168
|
+
);
|
|
169
|
+
return { ...d, findings: d.findings ?? [] };
|
|
170
|
+
}
|
|
159
171
|
/**
|
|
160
172
|
* `expectedLiveBuildId`는 CAS(compare-and-swap) — 서버 측 live 빌드와 다르면 409.
|
|
161
173
|
* 응답은 배치 전체가 아니라 `{id, liveBuildId}`만 온다(포털 핸들러 그대로).
|
|
@@ -4438,6 +4450,125 @@ async function i18nPullCommand(options) {
|
|
|
4438
4450
|
console.log(pc15.dim(" \uC0DD\uC131 \uD30C\uC77C\uC744 \uD55C \uBC88 import\uD558\uBA74 useBstageTranslations().t() \uD0A4\uAC00 \uC881\uD600\uC9D1\uB2C8\uB2E4."));
|
|
4439
4451
|
}
|
|
4440
4452
|
|
|
4453
|
+
// src/commands/doctor/portal.ts
|
|
4454
|
+
var MAX_DIAGNOSED_PLACEMENTS = 30;
|
|
4455
|
+
var DIAGNOSIS_CONCURRENCY = 4;
|
|
4456
|
+
function portalHasErrorFinding(p5) {
|
|
4457
|
+
return (p5?.placements ?? []).some((row) => row.findings.some((f) => f.severity === "error"));
|
|
4458
|
+
}
|
|
4459
|
+
function portalNeedsWork(p5) {
|
|
4460
|
+
return p5 !== void 0 && (p5.status === "error" || portalHasErrorFinding(p5));
|
|
4461
|
+
}
|
|
4462
|
+
async function diagnosePortal(opts, deps = {}) {
|
|
4463
|
+
const explicit = Boolean(opts.placement);
|
|
4464
|
+
const ctx = await openContext(deps, explicit);
|
|
4465
|
+
if (!("client" in ctx)) return ctx;
|
|
4466
|
+
const { client, link } = ctx;
|
|
4467
|
+
let all;
|
|
4468
|
+
try {
|
|
4469
|
+
all = await client.listPlacements(link.organizationId, link.spaceId, link.surface);
|
|
4470
|
+
} catch (err) {
|
|
4471
|
+
return {
|
|
4472
|
+
status: "error",
|
|
4473
|
+
reason: `\uBC30\uCE58 \uBAA9\uB85D\uC744 \uAC00\uC838\uC624\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${describeError(err)}`,
|
|
4474
|
+
placements: []
|
|
4475
|
+
};
|
|
4476
|
+
}
|
|
4477
|
+
const targets = explicit ? requireTargets(all, link.repoId, opts.placement) : selectPlacements(all, link.repoId);
|
|
4478
|
+
if (targets.length === 0) {
|
|
4479
|
+
return {
|
|
4480
|
+
status: "ok",
|
|
4481
|
+
reason: "\uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4.",
|
|
4482
|
+
hint: "bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984>",
|
|
4483
|
+
placements: []
|
|
4484
|
+
};
|
|
4485
|
+
}
|
|
4486
|
+
const picked = targets.slice(0, MAX_DIAGNOSED_PLACEMENTS);
|
|
4487
|
+
const omitted = targets.length - picked.length;
|
|
4488
|
+
const outcomes = await mapLimit(picked, DIAGNOSIS_CONCURRENCY, (p5) => diagnoseOne(ctx, p5));
|
|
4489
|
+
if (outcomes.every((o) => o.unsupported)) {
|
|
4490
|
+
return {
|
|
4491
|
+
status: "unsupported",
|
|
4492
|
+
reason: "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uBC30\uCE58 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.",
|
|
4493
|
+
placements: []
|
|
4494
|
+
};
|
|
4495
|
+
}
|
|
4496
|
+
const placements = outcomes.map((o) => o.row);
|
|
4497
|
+
return {
|
|
4498
|
+
status: placements.some((r) => r.error !== void 0) ? "error" : "ok",
|
|
4499
|
+
placements,
|
|
4500
|
+
...omitted > 0 ? { omitted } : {}
|
|
4501
|
+
};
|
|
4502
|
+
}
|
|
4503
|
+
async function openContext(deps, explicit) {
|
|
4504
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
4505
|
+
const env2 = deps.env ?? process.env;
|
|
4506
|
+
const hasLink = await loadLink(cwd, env2) !== null;
|
|
4507
|
+
try {
|
|
4508
|
+
return await resolveContext({ cwd, env: env2, fetch: deps.fetch });
|
|
4509
|
+
} catch (err) {
|
|
4510
|
+
if (explicit) throw err;
|
|
4511
|
+
const reason = scrub(err instanceof Error ? err.message : String(err));
|
|
4512
|
+
const isAuth = err instanceof CliExit && err.code === ExitCode.AUTH;
|
|
4513
|
+
const hint = isAuth ? "bstage login" : hasLink ? void 0 : "bstage link";
|
|
4514
|
+
return { status: "skipped", reason, ...hint ? { hint } : {}, placements: [] };
|
|
4515
|
+
}
|
|
4516
|
+
}
|
|
4517
|
+
async function diagnoseOne(ctx, p5) {
|
|
4518
|
+
const base = {
|
|
4519
|
+
placementId: p5.id,
|
|
4520
|
+
path: p5.path ?? "",
|
|
4521
|
+
slotId: p5.slotId ?? "",
|
|
4522
|
+
surface: p5.surface
|
|
4523
|
+
};
|
|
4524
|
+
try {
|
|
4525
|
+
const d = await ctx.client.getPlacementDiagnosis(
|
|
4526
|
+
ctx.link.organizationId,
|
|
4527
|
+
ctx.link.spaceId,
|
|
4528
|
+
p5.id
|
|
4529
|
+
);
|
|
4530
|
+
return {
|
|
4531
|
+
row: {
|
|
4532
|
+
...base,
|
|
4533
|
+
path: d.path || base.path,
|
|
4534
|
+
slotId: d.slotId || base.slotId,
|
|
4535
|
+
surface: d.surface ?? base.surface,
|
|
4536
|
+
findings: d.findings
|
|
4537
|
+
},
|
|
4538
|
+
unsupported: false
|
|
4539
|
+
};
|
|
4540
|
+
} catch (err) {
|
|
4541
|
+
return {
|
|
4542
|
+
row: { ...base, findings: [], error: describeError(err) },
|
|
4543
|
+
unsupported: isUnsupported(err)
|
|
4544
|
+
};
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
var PLACEMENT_NOT_FOUND = "\uBC30\uCE58\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4";
|
|
4548
|
+
function isUnsupported(err) {
|
|
4549
|
+
if (!(err instanceof PortalError)) return false;
|
|
4550
|
+
if (err.status === 404) return !err.message.includes(PLACEMENT_NOT_FOUND);
|
|
4551
|
+
return err.status === 403 && err.message.includes("\uD1A0\uD070 \uB4F1\uAE09\uC73C\uB85C \uD5C8\uC6A9\uB418\uC9C0 \uC54A\uB294");
|
|
4552
|
+
}
|
|
4553
|
+
function describeError(err) {
|
|
4554
|
+
if (err instanceof PortalError && err.status > 0) {
|
|
4555
|
+
return scrub(`${err.message} (HTTP ${err.status})`);
|
|
4556
|
+
}
|
|
4557
|
+
return scrub(err instanceof Error ? err.message : String(err));
|
|
4558
|
+
}
|
|
4559
|
+
async function mapLimit(items, limit, fn) {
|
|
4560
|
+
const results = new Array(items.length);
|
|
4561
|
+
let next = 0;
|
|
4562
|
+
const worker = async () => {
|
|
4563
|
+
while (next < items.length) {
|
|
4564
|
+
const i = next++;
|
|
4565
|
+
results[i] = await fn(items[i]);
|
|
4566
|
+
}
|
|
4567
|
+
};
|
|
4568
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, worker));
|
|
4569
|
+
return results;
|
|
4570
|
+
}
|
|
4571
|
+
|
|
4441
4572
|
// src/commands/doctor/report.ts
|
|
4442
4573
|
import { readFile as readFile9 } from "fs/promises";
|
|
4443
4574
|
import { join as join15 } from "path";
|
|
@@ -4839,18 +4970,90 @@ async function fetchLatestVersion2(packageName) {
|
|
|
4839
4970
|
}
|
|
4840
4971
|
|
|
4841
4972
|
// src/commands/doctor/render.ts
|
|
4973
|
+
import pc17 from "picocolors";
|
|
4974
|
+
|
|
4975
|
+
// src/commands/doctor/renderPortal.ts
|
|
4842
4976
|
import pc16 from "picocolors";
|
|
4977
|
+
var MARKERS = {
|
|
4978
|
+
error: pc16.red("\u2717"),
|
|
4979
|
+
warn: pc16.yellow("!"),
|
|
4980
|
+
info: pc16.dim("\xB7")
|
|
4981
|
+
};
|
|
4982
|
+
function clean(s) {
|
|
4983
|
+
return (s ?? "").replace(/\t/g, " ").replace(/[\p{Cc}\p{Cf}\p{Co}\p{Cs}\p{Zl}\p{Zp}\p{Variation_Selector}\u00ad\u180e]/gu, "");
|
|
4984
|
+
}
|
|
4985
|
+
function marker(severity) {
|
|
4986
|
+
return MARKERS[severity] ?? pc16.dim("\xB7");
|
|
4987
|
+
}
|
|
4988
|
+
function hintSuffix(reason, hint) {
|
|
4989
|
+
return hint && !(reason ?? "").includes(hint) ? ` (\uD560 \uC77C: ${hint})` : "";
|
|
4990
|
+
}
|
|
4991
|
+
function formatFinding(f) {
|
|
4992
|
+
const lines = [` ${marker(f.severity)} ${clean(f.title)} ${pc16.dim(`[${clean(f.id)}]`)}`];
|
|
4993
|
+
if (f.detail) lines.push(pc16.dim(` ${clean(f.detail)}`));
|
|
4994
|
+
if (f.fix) lines.push(pc16.dim(` \uC870\uCE58: ${clean(f.fix)}`));
|
|
4995
|
+
return lines;
|
|
4996
|
+
}
|
|
4997
|
+
function formatPlacement(row) {
|
|
4998
|
+
const label = clean(row.path || row.slotId || row.placementId);
|
|
4999
|
+
const lines = [` ${pc16.bold(label)}`];
|
|
5000
|
+
if (row.error !== void 0) {
|
|
5001
|
+
lines.push(` ${pc16.red("\u2717")} \uC9C4\uB2E8\uC744 \uBC1B\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4 \u2014 ${clean(row.error)}`);
|
|
5002
|
+
} else if (row.findings.length === 0) {
|
|
5003
|
+
lines.push(` ${pc16.green("\u2713")} \uBB38\uC81C \uC5C6\uC74C`);
|
|
5004
|
+
} else {
|
|
5005
|
+
lines.push(...row.findings.flatMap(formatFinding));
|
|
5006
|
+
}
|
|
5007
|
+
return lines;
|
|
5008
|
+
}
|
|
5009
|
+
function formatPortal(p5) {
|
|
5010
|
+
const lines = [pc16.bold("\uD3EC\uD138 \uC9C4\uB2E8")];
|
|
5011
|
+
if (p5.status === "skipped") {
|
|
5012
|
+
lines.push(
|
|
5013
|
+
pc16.dim(
|
|
5014
|
+
` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uB85C\uADF8\uC778\xB7\uB9C1\uD06C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
|
|
5015
|
+
)
|
|
5016
|
+
);
|
|
5017
|
+
} else if (p5.status === "unsupported") {
|
|
5018
|
+
lines.push(
|
|
5019
|
+
pc16.dim(` \uAC74\uB108\uB700 \u2014 ${clean(p5.reason) || "\uD3EC\uD138 \uC11C\uBC84\uAC00 \uC544\uC9C1 \uC9C4\uB2E8\uC744 \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."}`)
|
|
5020
|
+
);
|
|
5021
|
+
} else if (p5.placements.length === 0) {
|
|
5022
|
+
lines.push(
|
|
5023
|
+
p5.status === "error" ? pc16.red(` \u2717 ${clean(p5.reason) || "\uD3EC\uD138 \uC9C4\uB2E8\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4."}`) : pc16.dim(
|
|
5024
|
+
` ${clean(p5.reason) || "\uC9C4\uB2E8\uD560 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4."}${hintSuffix(p5.reason, p5.hint)}`
|
|
5025
|
+
)
|
|
5026
|
+
);
|
|
5027
|
+
} else {
|
|
5028
|
+
lines.push(...p5.placements.flatMap(formatPlacement));
|
|
5029
|
+
}
|
|
5030
|
+
if (p5.omitted) {
|
|
5031
|
+
lines.push(
|
|
5032
|
+
pc16.dim(
|
|
5033
|
+
` (\uBC30\uCE58\uAC00 \uB9CE\uC544 ${p5.omitted}\uAC1C\uB294 \uC9C4\uB2E8\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 bstage doctor --placement <\uACBD\uB85C|\uC2AC\uB86F id>\uB85C \uB530\uB85C \uBCF4\uC138\uC694.)`
|
|
5034
|
+
)
|
|
5035
|
+
);
|
|
5036
|
+
}
|
|
5037
|
+
return lines;
|
|
5038
|
+
}
|
|
5039
|
+
function printPortal(p5) {
|
|
5040
|
+
if (!p5) return;
|
|
5041
|
+
for (const line of formatPortal(p5)) console.log(line);
|
|
5042
|
+
console.log("");
|
|
5043
|
+
}
|
|
5044
|
+
|
|
5045
|
+
// src/commands/doctor/render.ts
|
|
4843
5046
|
function printVersions(r) {
|
|
4844
|
-
console.log(
|
|
5047
|
+
console.log(pc17.bold("\u{1F4E6} SDK \uBC84\uC804"));
|
|
4845
5048
|
if (!r.latestChecked) {
|
|
4846
|
-
console.log(
|
|
5049
|
+
console.log(pc17.dim(" \uB808\uC9C0\uC2A4\uD2B8\uB9AC \uC870\uD68C\uB97C \uAC74\uB108\uB6F0\uC5B4 \uC124\uCE58 \uBC84\uC804\uB9CC \uD45C\uC2DC\uD569\uB2C8\uB2E4."));
|
|
4847
5050
|
}
|
|
4848
5051
|
const nameWidth = Math.max(12, ...r.versions.map((v) => v.pkg.replace("@bstage-sdk/", "").length));
|
|
4849
5052
|
for (const v of r.versions) {
|
|
4850
5053
|
const name = v.pkg.replace("@bstage-sdk/", "").padEnd(nameWidth);
|
|
4851
5054
|
const inst = v.installed ?? "?";
|
|
4852
5055
|
if (v.latest && v.installed) {
|
|
4853
|
-
const arrow = v.outdated ?
|
|
5056
|
+
const arrow = v.outdated ? pc17.yellow(`\u2192 ${v.latest} (\uB4A4\uCC98\uC9D0)`) : pc17.green("(\uCD5C\uC2E0)");
|
|
4854
5057
|
console.log(` ${name} ${inst.padEnd(8)} ${arrow}`);
|
|
4855
5058
|
} else {
|
|
4856
5059
|
console.log(` ${name} ${inst}`);
|
|
@@ -4859,89 +5062,89 @@ function printVersions(r) {
|
|
|
4859
5062
|
console.log("");
|
|
4860
5063
|
}
|
|
4861
5064
|
function printFiles(r) {
|
|
4862
|
-
console.log(
|
|
5065
|
+
console.log(pc17.bold("\u{1F4C1} init \uAE30\uBCF8 \uD30C\uC77C (\uCC38\uACE0)"));
|
|
4863
5066
|
const absent = r.files.filter((f) => !f.present);
|
|
4864
5067
|
if (absent.length === 0) {
|
|
4865
|
-
console.log(
|
|
5068
|
+
console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
|
|
4866
5069
|
} else {
|
|
4867
|
-
console.log(
|
|
5070
|
+
console.log(pc17.dim(" init \uAE30\uBCF8\uAC12\uACFC\uC758 \uCC28\uC774\uC77C \uBFD0 \u2014 \uD504\uB85C\uC81D\uD2B8\uAC00 \uB2E4\uB974\uAC8C \uCC98\uB9AC \uC911\uC774\uBA74 \uBB34\uC2DC\uD558\uC138\uC694."));
|
|
4868
5071
|
for (const f of r.files) {
|
|
4869
|
-
if (f.present) console.log(` ${
|
|
4870
|
-
else console.log(` ${
|
|
5072
|
+
if (f.present) console.log(` ${pc17.green("\u2713")} ${f.path}`);
|
|
5073
|
+
else console.log(` ${pc17.dim("\xB7")} ${f.path.padEnd(20)} ${pc17.dim(`\uC5C6\uC74C (${f.note})`)}`);
|
|
4871
5074
|
}
|
|
4872
5075
|
}
|
|
4873
5076
|
console.log("");
|
|
4874
5077
|
}
|
|
4875
5078
|
function printLayout(r) {
|
|
4876
|
-
console.log(
|
|
5079
|
+
console.log(pc17.bold("\u{1F5C2} \uD15C\uD50C\uB9BF \uB514\uB809\uD1A0\uB9AC"));
|
|
4877
5080
|
if (r.layout.legacyPresent) {
|
|
4878
|
-
console.log(` ${
|
|
4879
|
-
console.log(
|
|
4880
|
-
console.log(
|
|
5081
|
+
console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("src/templates/ \uAC00 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 (\uC61B \uAD6C\uC870)")}`);
|
|
5082
|
+
console.log(pc17.dim(" \uBE4C\uB4DC \uC0B0\uCD9C\uBB3C \uACBD\uB85C\uAC00 \uD3F4\uB354 \uAD6C\uC870\uB97C \uB530\uB77C\uAC00\uB3C4\uB85D \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4."));
|
|
5083
|
+
console.log(pc17.dim(" \uD398\uC774\uC9C0 \u2192 src/pages/{\uACBD\uB85C}/ \xB7 \uC704\uC82F \u2192 src/slots/{\uC544\uBB34\uC774\uB984}/"));
|
|
4881
5084
|
if (r.layout.legacyTemplates.length > 0) {
|
|
4882
|
-
console.log(
|
|
5085
|
+
console.log(pc17.dim(` \uC62E\uACA8\uC57C \uD560 \uD15C\uD50C\uB9BF: ${r.layout.legacyTemplates.join(", ")}`));
|
|
4883
5086
|
}
|
|
4884
|
-
console.log(
|
|
5087
|
+
console.log(pc17.dim(' \uBCC0\uD658: \uC5D0\uC774\uC804\uD2B8\uC5D0\uAC8C "bstage \uB9C8\uC774\uADF8\uB808\uC774\uC158" \uC694\uCCAD'));
|
|
4885
5088
|
} else if (!r.layout.pagesPresent && !r.layout.slotsPresent) {
|
|
4886
|
-
console.log(` ${
|
|
5089
|
+
console.log(` ${pc17.dim("\xB7")} src/pages/ \xB7 src/slots/ \uB458 \uB2E4 \uC5C6\uC74C`);
|
|
4887
5090
|
} else {
|
|
4888
|
-
console.log(
|
|
5091
|
+
console.log(pc17.green(" \u2713 src/pages/ \xB7 src/slots/ \uAD6C\uC870"));
|
|
4889
5092
|
}
|
|
4890
5093
|
console.log("");
|
|
4891
5094
|
}
|
|
4892
5095
|
function printPnpmWorkspace(r) {
|
|
4893
5096
|
if (!r.pnpmWorkspace.relevant) return;
|
|
4894
|
-
console.log(
|
|
5097
|
+
console.log(pc17.bold("\u{1F4E6} pnpm workspace \uC124\uC815"));
|
|
4895
5098
|
if (r.pnpmWorkspace.allowBuildsDeclared) {
|
|
4896
|
-
console.log(
|
|
5099
|
+
console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 allowBuilds \uC120\uC5B8\uB428"));
|
|
4897
5100
|
} else {
|
|
4898
|
-
console.log(` ${
|
|
5101
|
+
console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 allowBuilds \uC5C6\uC74C")}`);
|
|
4899
5102
|
console.log(
|
|
4900
|
-
|
|
5103
|
+
pc17.dim(" pnpm\uC740 \uC758\uC874\uC131 build script\uB97C \uAE30\uBCF8 \uCC28\uB2E8\uD558\uACE0, pnpm 11\uC740 \uADF8\uAC83\uC744 \uC5D0\uB7EC\uB85C \uB0B8\uB2E4")
|
|
4901
5104
|
);
|
|
4902
5105
|
console.log(
|
|
4903
|
-
|
|
5106
|
+
pc17.dim(" \u2192 `pnpm install`\uC774 ERR_PNPM_IGNORED_BUILDS\uB85C \uC2E4\uD328\uD558\uACE0 `pnpm dev`\uB3C4 \uC8FD\uB294\uB2E4")
|
|
4904
5107
|
);
|
|
4905
|
-
console.log(
|
|
4906
|
-
console.log(
|
|
5108
|
+
console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml\uC5D0 `allowBuilds:` + `esbuild: true`"));
|
|
5109
|
+
console.log(pc17.dim(" \uB610\uB294 `pnpm approve-builds`\uB85C \uB300\uD654\uC2DD \uC120\uD0DD"));
|
|
4907
5110
|
}
|
|
4908
5111
|
if (r.pnpmWorkspace.filePresent && !r.pnpmWorkspace.packagesDeclared) {
|
|
4909
|
-
console.log(` ${
|
|
4910
|
-
console.log(
|
|
4911
|
-
console.log(
|
|
4912
|
-
console.log(
|
|
5112
|
+
console.log(` ${pc17.yellow("\u2192")} ${pc17.yellow("pnpm-workspace.yaml\uC5D0 packages \uC5C6\uC74C")}`);
|
|
5113
|
+
console.log(pc17.dim(" pnpm 9\uB294 \uC774 \uD30C\uC77C\uC774 \uC788\uC73C\uBA74 workspace \uB8E8\uD2B8\uB85C \uBCF4\uACE0 packages\uB97C \uC694\uAD6C\uD55C\uB2E4"));
|
|
5114
|
+
console.log(pc17.dim(" \u2192 pnpm 9\uC5D0\uC11C `ERROR packages field missing or empty`\uB85C \uC8FD\uB294\uB2E4"));
|
|
5115
|
+
console.log(pc17.dim(" \uCD94\uAC00: pnpm-workspace.yaml \uB9E8 \uC704\uC5D0 `packages:` + `- '.'`"));
|
|
4913
5116
|
} else if (r.pnpmWorkspace.packagesDeclared) {
|
|
4914
|
-
console.log(
|
|
5117
|
+
console.log(pc17.green(" \u2713 pnpm-workspace.yaml\uC5D0 packages \uC120\uC5B8\uB428"));
|
|
4915
5118
|
}
|
|
4916
5119
|
console.log("");
|
|
4917
5120
|
}
|
|
4918
5121
|
function printScriptRow(sc) {
|
|
4919
5122
|
if (sc.actual === null) {
|
|
4920
|
-
console.log(` ${
|
|
5123
|
+
console.log(` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uC5C6\uC74C")}`);
|
|
4921
5124
|
} else {
|
|
4922
5125
|
console.log(
|
|
4923
|
-
` ${
|
|
5126
|
+
` ${pc17.yellow("\u2192")} ${sc.name} ${pc17.yellow("\uB2E4\uB984")} ${pc17.dim(`\u2014 \uD604\uC7AC \`${sc.actual}\``)}`
|
|
4924
5127
|
);
|
|
4925
5128
|
if (sc.actual.includes("--noEmit") && !sc.actual.includes("-p ")) {
|
|
4926
5129
|
console.log(
|
|
4927
|
-
|
|
5130
|
+
pc17.dim(
|
|
4928
5131
|
" \uC8FC\uC758: solution-style tsconfig\uC5D0\uC11C `tsc --noEmit`\uC740 \uC544\uBB34 \uD30C\uC77C\uB3C4 \uAC80\uC0AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
|
|
4929
5132
|
)
|
|
4930
5133
|
);
|
|
4931
5134
|
}
|
|
4932
5135
|
}
|
|
4933
|
-
console.log(
|
|
4934
|
-
console.log(
|
|
5136
|
+
console.log(pc17.dim(` ${sc.why}`));
|
|
5137
|
+
console.log(pc17.dim(` \uAD8C\uC7A5: "${sc.name}": "${sc.expected}"`));
|
|
4935
5138
|
}
|
|
4936
5139
|
function printScripts(r) {
|
|
4937
|
-
console.log(
|
|
5140
|
+
console.log(pc17.bold("\u{1F6E0} package.json \uC2A4\uD06C\uB9BD\uD2B8"));
|
|
4938
5141
|
const scriptIssues = r.scripts.filter((sc) => sc.actual !== sc.expected);
|
|
4939
5142
|
if (scriptIssues.length === 0) {
|
|
4940
|
-
console.log(
|
|
5143
|
+
console.log(pc17.green(" \u2713 init \uAE30\uBCF8 \uAD6C\uC131\uACFC \uB3D9\uC77C"));
|
|
4941
5144
|
} else {
|
|
4942
5145
|
for (const sc of r.scripts) {
|
|
4943
5146
|
if (sc.actual === sc.expected) {
|
|
4944
|
-
console.log(` ${
|
|
5147
|
+
console.log(` ${pc17.green("\u2713")} ${sc.name}`);
|
|
4945
5148
|
continue;
|
|
4946
5149
|
}
|
|
4947
5150
|
printScriptRow(sc);
|
|
@@ -4951,76 +5154,76 @@ function printScripts(r) {
|
|
|
4951
5154
|
}
|
|
4952
5155
|
function printLiquid(r) {
|
|
4953
5156
|
if (r.liquid === null) return;
|
|
4954
|
-
console.log(
|
|
5157
|
+
console.log(pc17.bold("\u{1F4A7} liquid \uAC80\uC99D"));
|
|
4955
5158
|
const errors = r.liquid.issues.filter((i) => i.level === "error");
|
|
4956
5159
|
const warns = r.liquid.issues.filter((i) => i.level === "warn");
|
|
4957
5160
|
if (errors.length === 0 && warns.length === 0) {
|
|
4958
|
-
console.log(
|
|
5161
|
+
console.log(pc17.green(" \u2713 \uADDC\uC57D\xB7\uBB38\uBC95 \uC774\uC0C1 \uC5C6\uC74C"));
|
|
4959
5162
|
}
|
|
4960
|
-
for (const i of errors) console.log(` ${
|
|
4961
|
-
for (const i of warns) console.log(` ${
|
|
5163
|
+
for (const i of errors) console.log(` ${pc17.red("\u2717")} ${i.path} ${pc17.red(i.message)}`);
|
|
5164
|
+
for (const i of warns) console.log(` ${pc17.yellow("\u26A0")} ${i.path} ${pc17.dim(i.message)}`);
|
|
4962
5165
|
if (errors.length > 0) {
|
|
4963
5166
|
console.log(
|
|
4964
|
-
|
|
5167
|
+
pc17.dim(" \uACE0\uCE5C \uB4A4 `bstage build`\uB85C \uB2E4\uC2DC \uD655\uC778\uD558\uC138\uC694 \u2014 \uD3EC\uD138 \uBE4C\uB4DC\uB3C4 \uAC19\uC740 \uAC80\uC0AC\uB97C \uD569\uB2C8\uB2E4.")
|
|
4965
5168
|
);
|
|
4966
5169
|
}
|
|
4967
5170
|
console.log("");
|
|
4968
5171
|
}
|
|
4969
5172
|
function printRecommendedDeps(r) {
|
|
4970
5173
|
if (r.recommendedDeps.length === 0) return;
|
|
4971
|
-
console.log(
|
|
5174
|
+
console.log(pc17.bold("\u{1F9F1} \uAD8C\uC7A5 \uC758\uC874\uC131"));
|
|
4972
5175
|
if (r.recommendedDeps.every((d) => d.declared)) {
|
|
4973
|
-
console.log(
|
|
5176
|
+
console.log(pc17.green(" \u2713 \uBAA8\uB450 \uC120\uC5B8\uB428"));
|
|
4974
5177
|
} else {
|
|
4975
5178
|
for (const d of r.recommendedDeps) {
|
|
4976
5179
|
if (d.declared) {
|
|
4977
|
-
console.log(` ${
|
|
5180
|
+
console.log(` ${pc17.green("\u2713")} ${d.pkg}`);
|
|
4978
5181
|
continue;
|
|
4979
5182
|
}
|
|
4980
|
-
console.log(` ${
|
|
4981
|
-
console.log(
|
|
4982
|
-
console.log(
|
|
5183
|
+
console.log(` ${pc17.yellow("\u2192")} ${d.pkg} ${pc17.yellow("\uBBF8\uC120\uC5B8")} ${pc17.dim(`\u2014 ${d.note}`)}`);
|
|
5184
|
+
console.log(pc17.dim(` ${d.why}`));
|
|
5185
|
+
console.log(pc17.dim(` \uCD94\uAC00: npm i ${d.pkg} (\uD504\uB85C\uC81D\uD2B8 \uD328\uD0A4\uC9C0 \uB9E4\uB2C8\uC800\uB85C)`));
|
|
4983
5186
|
}
|
|
4984
5187
|
}
|
|
4985
5188
|
console.log("");
|
|
4986
5189
|
}
|
|
4987
5190
|
function printMigrations(r) {
|
|
4988
|
-
console.log(
|
|
5191
|
+
console.log(pc17.bold("\u{1F4D6} \uC801\uC6A9 \uAC00\uB2A5\uD55C \uB9C8\uC774\uADF8\uB808\uC774\uC158"));
|
|
4989
5192
|
if (r.migrations.length === 0) {
|
|
4990
|
-
console.log(
|
|
5193
|
+
console.log(pc17.dim(" \uD574\uB2F9 \uD56D\uBAA9 \uC5C6\uC74C."));
|
|
4991
5194
|
} else {
|
|
4992
5195
|
for (const m of r.migrations) {
|
|
4993
|
-
console.log(` ${
|
|
5196
|
+
console.log(` ${pc17.cyan(`\u2192 ${m.label}`)}`);
|
|
4994
5197
|
for (const item of m.items) console.log(` \u2022 ${item}`);
|
|
4995
5198
|
}
|
|
4996
5199
|
}
|
|
4997
5200
|
console.log("");
|
|
4998
5201
|
}
|
|
4999
5202
|
function printAgentsMd(r) {
|
|
5000
|
-
console.log(
|
|
5203
|
+
console.log(pc17.bold("\u{1F4DD} AGENTS.md"));
|
|
5001
5204
|
switch (r.agentsMd.status) {
|
|
5002
5205
|
case "ok":
|
|
5003
|
-
console.log(
|
|
5206
|
+
console.log(pc17.green(" \u2713 \uAD00\uB9AC \uC601\uC5ED \uCD5C\uC2E0"));
|
|
5004
5207
|
break;
|
|
5005
5208
|
case "missing":
|
|
5006
|
-
console.log(
|
|
5209
|
+
console.log(pc17.dim(" \xB7 \uD30C\uC77C \uC5C6\uC74C \u2014 bstage \uD504\uB85C\uC81D\uD2B8\uB77C\uBA74 init/\uB9C8\uC774\uADF8\uB808\uC774\uC158\uC73C\uB85C \uC0DD\uC131\uD558\uC138\uC694."));
|
|
5007
5210
|
break;
|
|
5008
5211
|
case "stale":
|
|
5009
5212
|
if (r.agentsMd.downgrade) {
|
|
5010
5213
|
console.log(
|
|
5011
|
-
|
|
5214
|
+
pc17.yellow(" ! \uAD00\uB9AC \uC601\uC5ED\uC774 \uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804") + pc17.dim(
|
|
5012
5215
|
" \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uAC31\uC2E0\uD558\uBA74 \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uC544\uAC11\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
|
|
5013
5216
|
)
|
|
5014
5217
|
);
|
|
5015
5218
|
break;
|
|
5016
5219
|
}
|
|
5017
5220
|
console.log(
|
|
5018
|
-
|
|
5221
|
+
pc17.yellow(" \u2192 \uAD00\uB9AC \uC601\uC5ED\uC774 \uC624\uB798\uB428") + pc17.dim(" \u2014 `bstage ai update`\uB85C \uAC31\uC2E0(\uC790\uC720 \uC601\uC5ED\uC740 \uBCF4\uC874).")
|
|
5019
5222
|
);
|
|
5020
5223
|
break;
|
|
5021
5224
|
case "legacy":
|
|
5022
5225
|
console.log(
|
|
5023
|
-
|
|
5226
|
+
pc17.yellow(" \u2192 \uB808\uAC70\uC2DC \uD3EC\uB9F7(\uAD00\uB9AC \uC601\uC5ED \uB9C8\uCEE4 \uC5C6\uC74C)") + pc17.dim(
|
|
5024
5227
|
" \u2014 `bstage ai install`\uB85C \uC2A4\uD0AC\uC744 \uBA3C\uC800 \uC124\uCE58\uD55C \uB4A4, `bstage-migrate` \uC2A4\uD0AC\uB85C reconcile(SDK \uC601\uC5ED \uAD50\uCCB4 + \uC0AC\uC6A9\uC790 \uB0B4\uC6A9 \uBCF4\uC874)."
|
|
5025
5228
|
)
|
|
5026
5229
|
);
|
|
@@ -5029,29 +5232,29 @@ function printAgentsMd(r) {
|
|
|
5029
5232
|
console.log("");
|
|
5030
5233
|
}
|
|
5031
5234
|
function printSkills(r) {
|
|
5032
|
-
console.log(
|
|
5235
|
+
console.log(pc17.bold("\u{1F9E9} \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC (.claude/skills/)"));
|
|
5033
5236
|
const skillsNeedWork = r.skills.filter((s) => s.status !== "ok");
|
|
5034
5237
|
if (r.skillsSkipped) {
|
|
5035
5238
|
console.log(
|
|
5036
|
-
|
|
5239
|
+
pc17.yellow(" ! sdk\uC640 liquid\uAC00 \uC11E\uC5EC \uC788\uC5B4 \uC2A4\uD0AC \uAC80\uC0AC\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4 \u2014 \uD558\uB098\uB9CC \uB0A8\uACA8 \uC8FC\uC138\uC694.")
|
|
5037
5240
|
);
|
|
5038
5241
|
} else if (skillsNeedWork.length === 0) {
|
|
5039
|
-
console.log(
|
|
5242
|
+
console.log(pc17.green(" \u2713 \uBAA8\uB4E0 \uC2A4\uD0AC \uCD5C\uC2E0"));
|
|
5040
5243
|
} else {
|
|
5041
5244
|
for (const s of r.skills) {
|
|
5042
|
-
if (s.status === "ok") console.log(` ${
|
|
5245
|
+
if (s.status === "ok") console.log(` ${pc17.green("\u2713")} ${s.name}`);
|
|
5043
5246
|
else if (s.status === "missing")
|
|
5044
|
-
console.log(` ${
|
|
5247
|
+
console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uBBF8\uC124\uCE58")}`);
|
|
5045
5248
|
else if (s.status === "newer")
|
|
5046
5249
|
console.log(
|
|
5047
|
-
` ${
|
|
5250
|
+
` ${pc17.yellow("!")} ${s.name.padEnd(16)} ${pc17.yellow("\uC774 CLI\uBCF4\uB2E4 \uC0C8 \uBC84\uC804")}` + pc17.dim(
|
|
5048
5251
|
" \u2014 \uC774 CLI\uAC00 \uC624\uB798\uB3FC \uC61B \uBCF8\uBB38\uC73C\uB85C \uB418\uB3CC\uB9BD\uB2C8\uB2E4(\uD558\uD5A5). \uCD5C\uC2E0 CLI(npx @bstage-sdk/cli@latest)\uB85C \uB2E4\uC2DC \uC2E4\uD589\uD558\uC138\uC694."
|
|
5049
5252
|
)
|
|
5050
5253
|
);
|
|
5051
|
-
else console.log(` ${
|
|
5254
|
+
else console.log(` ${pc17.yellow("\u2192")} ${s.name.padEnd(16)} ${pc17.yellow("\uAD6C\uBC84\uC804/\uC218\uC815\uB428")}`);
|
|
5052
5255
|
}
|
|
5053
5256
|
console.log(
|
|
5054
|
-
|
|
5257
|
+
pc17.dim(
|
|
5055
5258
|
" \uC544\uB798\uC5D0\uC11C \uC790\uB3D9 \uB3D9\uAE30\uD654\uD569\uB2C8\uB2E4 \u2014 bstage-* \uC2A4\uD0AC\uB9CC \uB36E\uC5B4\uC4F0\uBA70, \uADF8 \uC678 \uC0AC\uC6A9\uC790 \uC2A4\uD0AC\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4."
|
|
5056
5259
|
)
|
|
5057
5260
|
);
|
|
@@ -5061,36 +5264,43 @@ function printSkills(r) {
|
|
|
5061
5264
|
function printNextSteps(r) {
|
|
5062
5265
|
const agentsNeedsWork = r.agentsMd.status === "legacy" || r.agentsMd.status === "stale";
|
|
5063
5266
|
const liquidBroken = (r.liquid?.issues ?? []).some((i) => i.level === "error");
|
|
5064
|
-
const
|
|
5267
|
+
const portalBroken = portalNeedsWork(r.portal);
|
|
5268
|
+
const migrationWork = r.versions.some((v) => v.outdated) || r.migrations.length > 0 || agentsNeedsWork || liquidBroken;
|
|
5269
|
+
const hasWork = migrationWork || portalBroken;
|
|
5270
|
+
if (portalBroken) {
|
|
5271
|
+
console.log(pc17.yellow("\uC704 \uD3EC\uD138 \uC9C4\uB2E8 \uD56D\uBAA9\uC744 \uBA3C\uC800 \uD574\uACB0\uD558\uC138\uC694 \u2014 \uAC01 \uD56D\uBAA9\uC758 \uC870\uCE58\uB97C \uB530\uB974\uBA74 \uB429\uB2C8\uB2E4."));
|
|
5272
|
+
}
|
|
5065
5273
|
if (liquidBroken) {
|
|
5066
5274
|
console.log(
|
|
5067
|
-
|
|
5275
|
+
pc17.yellow("\uC704 liquid \uAC80\uC99D \uC624\uB958\uB97C \uBA3C\uC800 \uACE0\uCE58\uC138\uC694 \u2014 \uADF8\uB300\uB85C push\uD558\uBA74 \uD3EC\uD138 \uBE4C\uB4DC\uAC00 \uB9C9\uD799\uB2C8\uB2E4.")
|
|
5068
5276
|
);
|
|
5069
5277
|
}
|
|
5070
|
-
if (
|
|
5278
|
+
if (migrationWork) {
|
|
5071
5279
|
console.log(
|
|
5072
|
-
|
|
5280
|
+
pc17.dim(
|
|
5073
5281
|
"\uB2E4\uC74C \uB2E8\uACC4: \uB9C8\uC774\uADF8\uB808\uC774\uC158 \uC2A4\uD0AC\uC744 \uC2E4\uD589\uD574 \uC704 \uD56D\uBAA9\uC744 \uD504\uB85C\uC81D\uD2B8\uC5D0 \uB9DE\uCDB0 \uC801\uC6A9\uD558\uC138\uC694.\n \uC0C1\uC138 \uAC00\uC774\uB4DC: SDK \uBB38\uC11C\uC758 MIGRATION.md (\uC704 \uD56D\uBAA9\uBCC4 \uC801\uC6A9 \uC808\uCC28)"
|
|
5074
5282
|
)
|
|
5075
5283
|
);
|
|
5076
|
-
} else {
|
|
5077
|
-
console.log(
|
|
5284
|
+
} else if (!hasWork) {
|
|
5285
|
+
console.log(pc17.green("\u2713 \uCD5C\uC2E0 \uC0C1\uD0DC\uC785\uB2C8\uB2E4. \uB9C8\uC774\uADF8\uB808\uC774\uC158\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
5078
5286
|
if (r.files.some((f) => !f.present)) {
|
|
5079
|
-
console.log(
|
|
5287
|
+
console.log(pc17.dim(" (\uC704 init \uAE30\uBCF8 \uD30C\uC77C \uCC28\uC774\uB294 \uC120\uD0DD \uC0AC\uD56D\uC785\uB2C8\uB2E4.)"));
|
|
5080
5288
|
}
|
|
5081
5289
|
if (r.recommendedDeps.some((d) => !d.declared)) {
|
|
5082
|
-
console.log(
|
|
5290
|
+
console.log(pc17.dim(" (\uC704 \uAD8C\uC7A5 \uC758\uC874\uC131\uC740 \uBC84\uC804\uACFC \uBB34\uAD00\uD569\uB2C8\uB2E4 \u2014 \uC4F8 \uAC70\uBA74 \uB530\uB85C \uCD94\uAC00\uD558\uC138\uC694.)"));
|
|
5083
5291
|
}
|
|
5084
5292
|
}
|
|
5085
5293
|
console.log("");
|
|
5086
5294
|
}
|
|
5087
5295
|
function printReport(r) {
|
|
5088
5296
|
console.log("");
|
|
5089
|
-
console.log(`${
|
|
5297
|
+
console.log(`${pc17.cyan(pc17.bold("bstage doctor"))} ${pc17.dim(`\u2014 ${r.project ?? "(\uC774\uB984 \uC5C6\uC74C)"}`)}`);
|
|
5090
5298
|
console.log("");
|
|
5091
5299
|
if (!r.isBstageProject) {
|
|
5092
|
-
console.log(
|
|
5093
|
-
console.log(
|
|
5300
|
+
console.log(pc17.yellow("\uC774 \uB514\uB809\uD1A0\uB9AC\uB294 bstage \uD15C\uD50C\uB9BF \uD504\uB85C\uC81D\uD2B8\uAC00 \uC544\uB2CC \uAC83 \uAC19\uC2B5\uB2C8\uB2E4."));
|
|
5301
|
+
console.log(pc17.dim(" package.json\uC5D0 @bstage-sdk/* \uC758\uC874\uC131\uC774 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
5302
|
+
console.log("");
|
|
5303
|
+
printPortal(r.portal);
|
|
5094
5304
|
return;
|
|
5095
5305
|
}
|
|
5096
5306
|
printVersions(r);
|
|
@@ -5103,15 +5313,24 @@ function printReport(r) {
|
|
|
5103
5313
|
printMigrations(r);
|
|
5104
5314
|
printAgentsMd(r);
|
|
5105
5315
|
printSkills(r);
|
|
5316
|
+
printPortal(r.portal);
|
|
5106
5317
|
printNextSteps(r);
|
|
5107
5318
|
}
|
|
5108
5319
|
|
|
5109
5320
|
// src/commands/doctor.ts
|
|
5110
|
-
async function doctorCommand(options) {
|
|
5111
|
-
const root = process.cwd();
|
|
5112
|
-
const
|
|
5321
|
+
async function doctorCommand(options, deps = {}) {
|
|
5322
|
+
const root = deps.cwd ?? process.cwd();
|
|
5323
|
+
const [local, portal] = await Promise.all([
|
|
5324
|
+
diagnose2(root),
|
|
5325
|
+
diagnosePortal(
|
|
5326
|
+
{ placement: options.placement },
|
|
5327
|
+
{ cwd: root, env: deps.env, fetch: deps.fetch }
|
|
5328
|
+
)
|
|
5329
|
+
]);
|
|
5330
|
+
const report2 = { ...local, portal };
|
|
5331
|
+
if (portalNeedsWork(portal)) process.exitCode = ExitCode.FAILURE;
|
|
5113
5332
|
if (options.json) {
|
|
5114
|
-
|
|
5333
|
+
printJson(report2);
|
|
5115
5334
|
return;
|
|
5116
5335
|
}
|
|
5117
5336
|
printReport(report2);
|
|
@@ -5120,7 +5339,7 @@ async function doctorCommand(options) {
|
|
|
5120
5339
|
|
|
5121
5340
|
// src/commands/link.ts
|
|
5122
5341
|
import * as p4 from "@clack/prompts";
|
|
5123
|
-
import
|
|
5342
|
+
import pc18 from "picocolors";
|
|
5124
5343
|
var clackSelect = async (message, items) => {
|
|
5125
5344
|
const options = items.map((i) => ({
|
|
5126
5345
|
value: i.value,
|
|
@@ -5232,15 +5451,15 @@ function printLinked(link, repoLabel, repoFromOrigin, json) {
|
|
|
5232
5451
|
return;
|
|
5233
5452
|
}
|
|
5234
5453
|
if (repoFromOrigin) {
|
|
5235
|
-
console.log(
|
|
5454
|
+
console.log(pc18.dim(` git origin(${repoLabel})\uACFC \uC77C\uCE58\uD558\uB294 \uB808\uD3EC\uB97C \uAE30\uBCF8\uAC12\uC73C\uB85C \uC120\uD0DD\uD588\uC2B5\uB2C8\uB2E4.`));
|
|
5236
5455
|
}
|
|
5237
5456
|
console.log(
|
|
5238
|
-
|
|
5457
|
+
pc18.green(
|
|
5239
5458
|
`\u2713 \uC5F0\uACB0\uD588\uC2B5\uB2C8\uB2E4: ${link.organizationId} / ${link.spaceId} / ${repoLabel} [${link.surface}]`
|
|
5240
5459
|
)
|
|
5241
5460
|
);
|
|
5242
5461
|
console.log(
|
|
5243
|
-
|
|
5462
|
+
pc18.dim(
|
|
5244
5463
|
" .bstage/project.json \uC5D0 \uC800\uC7A5 (gitignore \uB300\uC0C1). CI\uC5D0\uC11C\uB294 BSTAGE_ORG\xB7BSTAGE_SPACE\xB7BSTAGE_REPO\xB7BSTAGE_SURFACE\xB7BSTAGE_PORTAL_URL \uD658\uACBD\uBCC0\uC218\uB97C \uC4F0\uC138\uC694."
|
|
5245
5464
|
)
|
|
5246
5465
|
);
|
|
@@ -5295,7 +5514,7 @@ async function linkCommand(options, deps = {}) {
|
|
|
5295
5514
|
}
|
|
5296
5515
|
|
|
5297
5516
|
// src/commands/list.ts
|
|
5298
|
-
import
|
|
5517
|
+
import pc19 from "picocolors";
|
|
5299
5518
|
|
|
5300
5519
|
// src/portal/buildRepo.ts
|
|
5301
5520
|
function buildMatchesRepo(b, repo) {
|
|
@@ -5327,10 +5546,10 @@ function artifactKinds(build) {
|
|
|
5327
5546
|
function renderList(placements, builds, repo) {
|
|
5328
5547
|
const mine = placements.filter((p5) => p5.stageRepoId === repo.id);
|
|
5329
5548
|
const lines = [];
|
|
5330
|
-
lines.push(
|
|
5549
|
+
lines.push(pc19.bold("\uBC30\uCE58"));
|
|
5331
5550
|
if (mine.length === 0) {
|
|
5332
5551
|
lines.push(
|
|
5333
|
-
|
|
5552
|
+
pc19.yellow(
|
|
5334
5553
|
" \uC774 \uB808\uD3EC\uC5D0 \uC5F0\uACB0\uB41C \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. bstage placement create \uB85C \uD398\uC774\uC9C0 \uBC30\uCE58\uB97C \uBA3C\uC800 \uB9CC\uB4DC\uC138\uC694."
|
|
5335
5554
|
)
|
|
5336
5555
|
);
|
|
@@ -5349,10 +5568,10 @@ function renderList(placements, builds, repo) {
|
|
|
5349
5568
|
);
|
|
5350
5569
|
}
|
|
5351
5570
|
lines.push("");
|
|
5352
|
-
lines.push(
|
|
5571
|
+
lines.push(pc19.bold("\uCD5C\uADFC \uBE4C\uB4DC"));
|
|
5353
5572
|
const recent = builds.filter((b) => buildMatchesRepo(b, repo));
|
|
5354
5573
|
lines.push(
|
|
5355
|
-
recent.length === 0 ?
|
|
5574
|
+
recent.length === 0 ? pc19.dim(" \uBE4C\uB4DC \uC774\uB825\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.") : table([
|
|
5356
5575
|
["\uBE4C\uB4DC", "\uC0C1\uD0DC", "\uC885\uB958", "\uCEE4\uBC0B", "\uC694\uCCAD \uC2DC\uAC01"],
|
|
5357
5576
|
...recent.map((b) => [
|
|
5358
5577
|
b.id,
|
|
@@ -5366,7 +5585,7 @@ function renderList(placements, builds, repo) {
|
|
|
5366
5585
|
if (mine.length === 0) {
|
|
5367
5586
|
lines.push("");
|
|
5368
5587
|
lines.push(
|
|
5369
|
-
|
|
5588
|
+
pc19.yellow(
|
|
5370
5589
|
"\uC774 \uB808\uD3EC\uC5D0 \uBC30\uCE58\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C: bstage placement create --template <\uC0B0\uCD9C\uBB3C \uC774\uB984> [--path /\uACBD\uB85C] \u2192 bstage deploy. \uC704\uC82F(\uC2AC\uB86F) \uBC30\uCE58\uB294 \uD3EC\uD138 \uD654\uBA74(\uC2A4\uD14C\uC774\uC9C0 > \uD398\uC774\uC9C0 > \uC0C8 \uD398\uC774\uC9C0)\uC5D0\uC11C \uB9CC\uB4ED\uB2C8\uB2E4. (bstage-deploy \uC2A4\uD0AC \uCC38\uC870)"
|
|
5371
5590
|
)
|
|
5372
5591
|
);
|
|
@@ -5392,12 +5611,12 @@ async function listCommand(options, deps = {}) {
|
|
|
5392
5611
|
printJson({ link, placements: mine, builds: myBuilds });
|
|
5393
5612
|
return;
|
|
5394
5613
|
}
|
|
5395
|
-
out(
|
|
5614
|
+
out(pc19.dim(`${link.organizationId} / ${link.spaceId} [${link.surface}]`));
|
|
5396
5615
|
out(renderList(placements, builds, repo));
|
|
5397
5616
|
}
|
|
5398
5617
|
|
|
5399
5618
|
// src/commands/logs.ts
|
|
5400
|
-
import
|
|
5619
|
+
import pc20 from "picocolors";
|
|
5401
5620
|
function statusLine(build) {
|
|
5402
5621
|
return `[bstage] \uBE4C\uB4DC ${build.id} \xB7 ${build.status}${build.failureReason ? ` \xB7 ${build.failureReason}` : ""}`;
|
|
5403
5622
|
}
|
|
@@ -5411,7 +5630,7 @@ async function latestBuildId(ctx) {
|
|
|
5411
5630
|
return latest.id;
|
|
5412
5631
|
}
|
|
5413
5632
|
function logSink(json) {
|
|
5414
|
-
return json ? (delta) => void process.stderr.write(
|
|
5633
|
+
return json ? (delta) => void process.stderr.write(pc20.dim(delta)) : (delta) => void process.stdout.write(delta);
|
|
5415
5634
|
}
|
|
5416
5635
|
async function logsCommand(buildId, options, deps = {}) {
|
|
5417
5636
|
const out = deps.out ?? ((s) => void process.stdout.write(s));
|
|
@@ -5435,17 +5654,17 @@ async function report(client, org, space, id, build, options, out, following) {
|
|
|
5435
5654
|
return;
|
|
5436
5655
|
}
|
|
5437
5656
|
if (following) {
|
|
5438
|
-
console.error(
|
|
5657
|
+
console.error(pc20.dim(`
|
|
5439
5658
|
${statusLine(build)}`));
|
|
5440
5659
|
return;
|
|
5441
5660
|
}
|
|
5442
5661
|
const log3 = await client.getBuildLog(org, space, id);
|
|
5443
5662
|
out(log3.endsWith("\n") ? log3 : log3 + "\n");
|
|
5444
|
-
console.error(
|
|
5663
|
+
console.error(pc20.dim(statusLine(build)));
|
|
5445
5664
|
}
|
|
5446
5665
|
|
|
5447
5666
|
// src/commands/placement.ts
|
|
5448
|
-
import
|
|
5667
|
+
import pc21 from "picocolors";
|
|
5449
5668
|
|
|
5450
5669
|
// src/portal/pagePlacement.ts
|
|
5451
5670
|
function normalizePagePath(raw) {
|
|
@@ -5516,7 +5735,7 @@ async function ensureBuildWithArtifact(ctx, repo, template, options, deps) {
|
|
|
5516
5735
|
const latest = options.build ? void 0 : latestSucceeded(await ctx.client.listBuilds(org, space, RECENT_BUILDS), repo);
|
|
5517
5736
|
const found = latest && resolvePageArtifact(latest, template, surface);
|
|
5518
5737
|
if (latest && found) return { build: latest, artifact: found };
|
|
5519
|
-
if (!options.json) console.error(
|
|
5738
|
+
if (!options.json) console.error(pc21.dim(`[bstage] ${buildReason(latest, options)}`));
|
|
5520
5739
|
if (!options.skipGitCheck) await precheckGit(deps, repo.defaultBranch);
|
|
5521
5740
|
const created = await createAndAnnounceBuild(ctx, options.json);
|
|
5522
5741
|
const done = await waitForCompletedBuild(ctx, deps, created, options.json);
|
|
@@ -5547,9 +5766,9 @@ function reportExisting(owner, resolved, repoId, options, out) {
|
|
|
5547
5766
|
return;
|
|
5548
5767
|
}
|
|
5549
5768
|
out(
|
|
5550
|
-
`${
|
|
5769
|
+
`${pc21.green("\u2713")} ${label} \uC5D0 \uC774 \uB808\uD3EC\uC758 '${resolved.artifact.name}' \uBC30\uCE58\uAC00 \uC774\uBBF8 \uC788\uC2B5\uB2C8\uB2E4 (${owner.id}).`
|
|
5551
5770
|
);
|
|
5552
|
-
out(
|
|
5771
|
+
out(pc21.dim(` \uB2E4\uC74C: ${nextCommand(label)}`));
|
|
5553
5772
|
return;
|
|
5554
5773
|
}
|
|
5555
5774
|
const who = `\uBC30\uCE58 ${owner.id}, \uC0B0\uCD9C\uBB3C ${owner.artifact ?? "-"}${owner.stageRepoId === repoId ? "" : ", \uB2E4\uB978 \uB808\uD3EC"}`;
|
|
@@ -5623,9 +5842,9 @@ function reportCreated(created, resolved, options, out) {
|
|
|
5623
5842
|
return;
|
|
5624
5843
|
}
|
|
5625
5844
|
out(
|
|
5626
|
-
`${
|
|
5845
|
+
`${pc21.green("\u2713")} \uBC30\uCE58\uB97C \uB9CC\uB4E4\uC5C8\uC2B5\uB2C8\uB2E4: ${label} \u2190 ${resolved.artifact.name} (${created.id}, \uBE4C\uB4DC ${resolved.build.id} \xB7 ${shortSha(resolved.build.commitSha)})`
|
|
5627
5846
|
);
|
|
5628
|
-
out(
|
|
5847
|
+
out(pc21.dim(` \uC544\uC9C1 \uB77C\uC774\uBE0C\uAC00 \uC544\uB2D9\uB2C8\uB2E4. \uB2E4\uC74C: ${nextCommand(label)}`));
|
|
5629
5848
|
}
|
|
5630
5849
|
async function placementCreateCommand(options, deps = {}) {
|
|
5631
5850
|
if (options.json && !options.yes) {
|
|
@@ -5678,7 +5897,7 @@ async function placementCreateCommand(options, deps = {}) {
|
|
|
5678
5897
|
|
|
5679
5898
|
// src/commands/login.ts
|
|
5680
5899
|
import { hostname as osHostname } from "os";
|
|
5681
|
-
import
|
|
5900
|
+
import pc22 from "picocolors";
|
|
5682
5901
|
|
|
5683
5902
|
// src/portal/openBrowser.ts
|
|
5684
5903
|
import { execFile as execFile2 } from "child_process";
|
|
@@ -5746,7 +5965,7 @@ async function loginWithToken(portalUrl, token, options, deps, env2) {
|
|
|
5746
5965
|
return;
|
|
5747
5966
|
}
|
|
5748
5967
|
console.log(
|
|
5749
|
-
|
|
5968
|
+
pc22.green(`\u2713 ${portalUrl} \uC5D0 ${me.user.email} \uB85C \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4 (\uC870\uC9C1 ${organizationId}).`)
|
|
5750
5969
|
);
|
|
5751
5970
|
}
|
|
5752
5971
|
function nextIntervalOnSlowDown(interval, retryAfterSec) {
|
|
@@ -5757,11 +5976,11 @@ function printDeviceCodePrompt(userCode, verificationUriComplete, expiresIn) {
|
|
|
5757
5976
|
console.log("");
|
|
5758
5977
|
console.log(` \uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uC544\uB798 \uCF54\uB4DC\uB97C \uD655\uC778\uD558\uACE0 \uC2B9\uC778\uD558\uC138\uC694.`);
|
|
5759
5978
|
console.log("");
|
|
5760
|
-
console.log(` \uCF54\uB4DC ${
|
|
5761
|
-
console.log(` \uC8FC\uC18C ${
|
|
5979
|
+
console.log(` \uCF54\uB4DC ${pc22.bold(userCode)}`);
|
|
5980
|
+
console.log(` \uC8FC\uC18C ${pc22.underline(verificationUriComplete)}`);
|
|
5762
5981
|
console.log("");
|
|
5763
5982
|
console.log(
|
|
5764
|
-
|
|
5983
|
+
pc22.dim(
|
|
5765
5984
|
` \uD130\uBBF8\uB110\uC758 \uCF54\uB4DC\uC640 \uBE0C\uB77C\uC6B0\uC800\uC758 \uCF54\uB4DC\uAC00 \uAC19\uC740\uC9C0 \uAF2D \uD655\uC778\uD558\uC138\uC694. ${Math.round(expiresIn / 60)}\uBD84 \uC548\uC5D0 \uC2B9\uC778\uB418\uC9C0 \uC54A\uC73C\uBA74 \uB9CC\uB8CC\uB429\uB2C8\uB2E4.`
|
|
5766
5985
|
)
|
|
5767
5986
|
);
|
|
@@ -5802,7 +6021,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
|
|
|
5802
6021
|
if (!sameOrigin(portalUrl, verificationUriComplete)) {
|
|
5803
6022
|
if (!options.json) {
|
|
5804
6023
|
console.log(
|
|
5805
|
-
|
|
6024
|
+
pc22.yellow(
|
|
5806
6025
|
" \uC2B9\uC778 \uC8FC\uC18C\uAC00 \uD3EC\uD138\uACFC \uB2E4\uB978 \uC0AC\uC774\uD2B8\uC785\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uB97C \uC5F4\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4 \u2014 \uC8FC\uC18C\uB97C \uD655\uC778\uD55C \uB4A4 \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."
|
|
5807
6026
|
)
|
|
5808
6027
|
);
|
|
@@ -5811,7 +6030,7 @@ async function openVerificationUri(portalUrl, verificationUriComplete, options,
|
|
|
5811
6030
|
}
|
|
5812
6031
|
const opened = await (deps.openBrowser ?? openBrowser)(verificationUriComplete);
|
|
5813
6032
|
if (!opened && !options.json) {
|
|
5814
|
-
console.log(
|
|
6033
|
+
console.log(pc22.dim(" \uBE0C\uB77C\uC6B0\uC800\uB97C \uC790\uB3D9\uC73C\uB85C \uC5F4\uC9C0 \uBABB\uD588\uC2B5\uB2C8\uB2E4. \uC704 \uC8FC\uC18C\uB97C \uC9C1\uC811 \uC5F4\uC5B4 \uC8FC\uC138\uC694."));
|
|
5815
6034
|
}
|
|
5816
6035
|
}
|
|
5817
6036
|
function sameOrigin(a, b) {
|
|
@@ -5876,13 +6095,13 @@ function reportIssued(portalUrl, issued, organizationId, json) {
|
|
|
5876
6095
|
});
|
|
5877
6096
|
return;
|
|
5878
6097
|
}
|
|
5879
|
-
console.log(
|
|
6098
|
+
console.log(pc22.green(`\u2713 ${portalUrl} \uC5D0 \uB85C\uADF8\uC778\uD588\uC2B5\uB2C8\uB2E4.`));
|
|
5880
6099
|
console.log(
|
|
5881
|
-
|
|
6100
|
+
pc22.dim(
|
|
5882
6101
|
` \uC870\uC9C1 ${orgLabel(organizationId ?? UNKNOWN_ORG)} \xB7 \uD1A0\uD070 ${issued.prefix}\u2026 \xB7 \uB4F1\uAE09 ${issued.permission} \xB7 ${scopeLabel(issued.allSpaces, issued.spaceIds)} \xB7 \uB9CC\uB8CC ${issued.expiresAt.slice(0, 10)}`
|
|
5883
6102
|
)
|
|
5884
6103
|
);
|
|
5885
|
-
console.log(
|
|
6104
|
+
console.log(pc22.dim(" \uB2E4\uC74C: \uD504\uB85C\uC81D\uD2B8 \uB514\uB809\uD130\uB9AC\uC5D0\uC11C bstage link"));
|
|
5886
6105
|
}
|
|
5887
6106
|
async function loginCommand(options, deps = {}) {
|
|
5888
6107
|
const env2 = deps.env ?? process.env;
|
|
@@ -5899,7 +6118,7 @@ async function loginCommand(options, deps = {}) {
|
|
|
5899
6118
|
}
|
|
5900
6119
|
|
|
5901
6120
|
// src/commands/logout.ts
|
|
5902
|
-
import
|
|
6121
|
+
import pc23 from "picocolors";
|
|
5903
6122
|
async function logoutCommand(options, deps = {}) {
|
|
5904
6123
|
const cwd = deps.cwd ?? process.cwd();
|
|
5905
6124
|
const env2 = deps.env ?? process.env;
|
|
@@ -5913,16 +6132,16 @@ async function logoutCommand(options, deps = {}) {
|
|
|
5913
6132
|
const removed = await deleteCredential(portalUrl, options.org, env2);
|
|
5914
6133
|
if (removed.length === 0) {
|
|
5915
6134
|
const scope = options.org ? `\uC870\uC9C1 ${options.org} \uC758 ` : "";
|
|
5916
|
-
console.log(
|
|
6135
|
+
console.log(pc23.yellow(`${portalUrl} \uC5D0 \uC800\uC7A5\uB41C ${scope}\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC2B5\uB2C8\uB2E4.`));
|
|
5917
6136
|
} else {
|
|
5918
6137
|
const orgs = removed.map(orgLabel).join(", ");
|
|
5919
|
-
console.log(
|
|
6138
|
+
console.log(pc23.green(`\u2713 ${portalUrl} \uC790\uACA9\uC99D\uBA85\uC744 \uC0AD\uC81C\uD588\uC2B5\uB2C8\uB2E4 \u2014 \uC870\uC9C1 ${orgs}`));
|
|
5920
6139
|
}
|
|
5921
|
-
console.log(
|
|
6140
|
+
console.log(pc23.dim(" \uD3EC\uD138 \uD654\uBA74\uC5D0\uC11C \uD1A0\uD070 \uC790\uCCB4\uB97C \uD3D0\uAE30\uD558\uBA74 \uB2E4\uB978 \uAE30\uAE30\uC5D0\uC11C\uB3C4 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4."));
|
|
5922
6141
|
}
|
|
5923
6142
|
|
|
5924
6143
|
// src/commands/publish.ts
|
|
5925
|
-
import
|
|
6144
|
+
import pc24 from "picocolors";
|
|
5926
6145
|
function parseOnOff(v) {
|
|
5927
6146
|
const s = v.toLowerCase();
|
|
5928
6147
|
if (s === "on") return true;
|
|
@@ -5961,13 +6180,13 @@ async function togglePlacement(ctx, p5, enabled) {
|
|
|
5961
6180
|
}
|
|
5962
6181
|
function printResults2(results, enabled, out) {
|
|
5963
6182
|
for (const r of results) {
|
|
5964
|
-
const mark = r.status === "failed" ?
|
|
6183
|
+
const mark = r.status === "failed" ? pc24.red("\u2717") : r.status === "conflict" ? pc24.yellow("!") : pc24.green("\u2713");
|
|
5965
6184
|
const stateLabel = r.status === "unchanged" ? "\uBCC0\uACBD \uC5C6\uC74C" : `\uAC8C\uC2DC ${r.enabled ? "on" : "off"}`;
|
|
5966
|
-
const suffix = r.message && r.status !== "unchanged" ?
|
|
6185
|
+
const suffix = r.message && r.status !== "unchanged" ? pc24.dim(` ${r.message}`) : "";
|
|
5967
6186
|
out(`${mark} ${r.label} ${stateLabel}${suffix}`);
|
|
5968
6187
|
}
|
|
5969
6188
|
if (!enabled) {
|
|
5970
|
-
out(
|
|
6189
|
+
out(pc24.dim(" \uB77C\uC774\uBE0C \uBC84\uC804 \uD3EC\uC778\uD130\uB294 \uC720\uC9C0\uB429\uB2C8\uB2E4 \u2014 \uB2E4\uC2DC \uCF1C\uBA74 \uAC19\uC740 \uBE4C\uB4DC\uAC00 \uC989\uC2DC \uC11C\uBE59\uB429\uB2C8\uB2E4."));
|
|
5971
6190
|
}
|
|
5972
6191
|
}
|
|
5973
6192
|
function reportOutcome2(results, options, enabled, out) {
|
|
@@ -6007,7 +6226,7 @@ async function publishCommand(state, options, deps = {}) {
|
|
|
6007
6226
|
}
|
|
6008
6227
|
|
|
6009
6228
|
// src/commands/rollback.ts
|
|
6010
|
-
import
|
|
6229
|
+
import pc25 from "picocolors";
|
|
6011
6230
|
function pickRollbackTarget(builds, repo, currentLive) {
|
|
6012
6231
|
const ok = builds.filter((b) => buildMatchesRepo(b, repo) && b.status === "SUCCEEDED").sort((a, b) => a.requestedAt < b.requestedAt ? 1 : -1);
|
|
6013
6232
|
if (!currentLive) return ok[0] ?? null;
|
|
@@ -6092,16 +6311,16 @@ async function rollbackCommand(buildId, options, deps = {}) {
|
|
|
6092
6311
|
reportOutcome(results, options, out);
|
|
6093
6312
|
if (!options.json) {
|
|
6094
6313
|
out(
|
|
6095
|
-
|
|
6314
|
+
pc25.dim(" \uB418\uB3CC\uB9B0 \uB4A4\uC5D0\uB3C4 \uCD5C\uC2E0 \uBE4C\uB4DC\uB294 \uB0A8\uC544 \uC788\uC2B5\uB2C8\uB2E4 \u2014 bstage deploy \uB85C \uB2E4\uC2DC \uC62C\uB9B4 \uC218 \uC788\uC2B5\uB2C8\uB2E4.")
|
|
6096
6315
|
);
|
|
6097
6316
|
}
|
|
6098
6317
|
}
|
|
6099
6318
|
|
|
6100
6319
|
// src/commands/skills.ts
|
|
6101
|
-
import
|
|
6320
|
+
import pc26 from "picocolors";
|
|
6102
6321
|
async function skillsInstallCommand(options) {
|
|
6103
6322
|
console.warn(
|
|
6104
|
-
|
|
6323
|
+
pc26.yellow(
|
|
6105
6324
|
"bstage skills install\uC740 bstage ai install\uB85C \uBC14\uB00C\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC74C \uB9B4\uB9AC\uC988\uC5D0\uC11C \uC81C\uAC70\uB429\uB2C8\uB2E4."
|
|
6106
6325
|
)
|
|
6107
6326
|
);
|
|
@@ -6111,7 +6330,7 @@ async function skillsInstallCommand(options) {
|
|
|
6111
6330
|
// src/commands/docs.ts
|
|
6112
6331
|
import { existsSync as existsSync8, readdirSync as readdirSync3 } from "fs";
|
|
6113
6332
|
import { join as join16 } from "path";
|
|
6114
|
-
import
|
|
6333
|
+
import pc27 from "picocolors";
|
|
6115
6334
|
var DOC_ORDER = [
|
|
6116
6335
|
["GETTING_STARTED.md", "\uBE60\uB978 \uC2DC\uC791 \uAC00\uC774\uB4DC"],
|
|
6117
6336
|
["API_REFERENCE.md", "createTemplate, hooks, BstageClient, PlatformBridge API"],
|
|
@@ -6131,10 +6350,10 @@ var CORE_DOCS_SEGMENTS = ["node_modules", "@bstage-sdk", "core", "docs"];
|
|
|
6131
6350
|
async function docsCommand() {
|
|
6132
6351
|
const docsDir = join16(process.cwd(), ...CORE_DOCS_SEGMENTS);
|
|
6133
6352
|
if (!existsSync8(docsDir)) {
|
|
6134
|
-
console.log(
|
|
6135
|
-
console.log(
|
|
6353
|
+
console.log(pc27.yellow("SDK \uBB38\uC11C\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4."));
|
|
6354
|
+
console.log(pc27.dim(" @bstage-sdk/core\uAC00 \uC124\uCE58\uB418\uC5B4 \uC788\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694 (npm install \uD6C4 \uC7AC\uC2DC\uB3C4)."));
|
|
6136
6355
|
console.log(
|
|
6137
|
-
|
|
6356
|
+
pc27.dim(
|
|
6138
6357
|
" SDK \uC758\uC874\uC774 \uC5C6\uB294 \uB808\uD3EC\uC5D0\uB294 \uC774 \uACBD\uB85C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 liquid \uADDC\uC57D\xB7\uB370\uC774\uD130\uB294 bstage-liquid \uC2A4\uD0AC\uC744 \uBCF4\uC138\uC694."
|
|
6139
6358
|
)
|
|
6140
6359
|
);
|
|
@@ -6146,24 +6365,24 @@ async function docsCommand() {
|
|
|
6146
6365
|
const known = new Set(DOC_ORDER.map(([f]) => f));
|
|
6147
6366
|
const extras = [...present].filter((f) => !known.has(f)).sort();
|
|
6148
6367
|
console.log("");
|
|
6149
|
-
console.log(
|
|
6150
|
-
console.log(
|
|
6368
|
+
console.log(pc27.bold("bstage SDK \uBB38\uC11C"));
|
|
6369
|
+
console.log(pc27.dim(` ${docsDir}`));
|
|
6151
6370
|
console.log("");
|
|
6152
6371
|
for (const [file3, desc] of ordered) {
|
|
6153
|
-
console.log(` ${
|
|
6372
|
+
console.log(` ${pc27.cyan(file3.padEnd(22))} ${pc27.dim(desc)}`);
|
|
6154
6373
|
}
|
|
6155
6374
|
for (const file3 of extras) {
|
|
6156
|
-
console.log(` ${
|
|
6375
|
+
console.log(` ${pc27.cyan(file3.padEnd(22))}`);
|
|
6157
6376
|
}
|
|
6158
6377
|
console.log("");
|
|
6159
6378
|
console.log(
|
|
6160
|
-
|
|
6379
|
+
pc27.dim("\uD30C\uC77C\uC744 \uC5F4\uC5B4 \uC0C1\uC138 \uB0B4\uC6A9\uC744 \uD655\uC778\uD558\uC138\uC694. \uCEE4\uB9E8\uB4DC \uB3C4\uC6C0\uB9D0\uC740 `bstage <command> --help`.")
|
|
6161
6380
|
);
|
|
6162
6381
|
console.log("");
|
|
6163
6382
|
}
|
|
6164
6383
|
|
|
6165
6384
|
// src/commands/whoami.ts
|
|
6166
|
-
import
|
|
6385
|
+
import pc28 from "picocolors";
|
|
6167
6386
|
function jsonEntry(c, active) {
|
|
6168
6387
|
return {
|
|
6169
6388
|
organizationId: c.organizationId,
|
|
@@ -6177,21 +6396,21 @@ function jsonEntry(c, active) {
|
|
|
6177
6396
|
}
|
|
6178
6397
|
function printCredentials(stored, activeOrg) {
|
|
6179
6398
|
if (stored.length === 0) return;
|
|
6180
|
-
console.log(
|
|
6399
|
+
console.log(pc28.dim("\uC800\uC7A5\uB41C \uD1A0\uD070"));
|
|
6181
6400
|
const rows = stored.map((c) => [
|
|
6182
6401
|
` \uC870\uC9C1 ${orgLabel(c.organizationId)}`,
|
|
6183
6402
|
`\uB4F1\uAE09 ${c.permission ?? "-"}`,
|
|
6184
6403
|
scopeLabel(c.allSpaces, c.spaceIds),
|
|
6185
6404
|
`\uB9CC\uB8CC ${c.expiresAt ? c.expiresAt.slice(0, 10) : "-"}`,
|
|
6186
|
-
c.organizationId === activeOrg ?
|
|
6405
|
+
c.organizationId === activeOrg ? pc28.dim("(\uC0AC\uC6A9 \uC911)") : ""
|
|
6187
6406
|
]);
|
|
6188
6407
|
console.log(table(rows));
|
|
6189
6408
|
}
|
|
6190
6409
|
function printMe(me, portalUrl) {
|
|
6191
|
-
console.log(`${
|
|
6410
|
+
console.log(`${pc28.bold(me.user.email)} ${pc28.dim(portalUrl)}`);
|
|
6192
6411
|
for (const m of me.memberships) {
|
|
6193
6412
|
const stages = Object.entries(m.stageRoles ?? {}).map(([s, r]) => `${s}:${r}`).join(", ");
|
|
6194
|
-
console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${
|
|
6413
|
+
console.log(` \uC870\uC9C1 ${m.organizationId} ${m.organizationRole ?? ""} ${pc28.dim(stages)}`);
|
|
6195
6414
|
}
|
|
6196
6415
|
}
|
|
6197
6416
|
async function whoamiCommand(options, deps = {}) {
|
|
@@ -6247,10 +6466,10 @@ function reportStoredOnly(portalUrl, stored, json) {
|
|
|
6247
6466
|
});
|
|
6248
6467
|
return;
|
|
6249
6468
|
}
|
|
6250
|
-
console.log(
|
|
6469
|
+
console.log(pc28.dim(portalUrl));
|
|
6251
6470
|
printCredentials(stored);
|
|
6252
6471
|
console.log(
|
|
6253
|
-
|
|
6472
|
+
pc28.yellow(" \uC5EC\uB7EC \uC870\uC9C1\uC758 \uD1A0\uD070\uC774 \uC788\uC2B5\uB2C8\uB2E4 \u2014 --org <id> \uB85C \uC870\uC9C1\uC744 \uC9C0\uC815\uD558\uBA74 \uACC4\uC815 \uC815\uBCF4\uB3C4 \uBD05\uB2C8\uB2E4.")
|
|
6254
6473
|
);
|
|
6255
6474
|
}
|
|
6256
6475
|
|
|
@@ -6270,8 +6489,11 @@ program.command("build").description(
|
|
|
6270
6489
|
).option("--json", "\uAC80\uC99D \uACB0\uACFC\xB7\uC0B0\uCD9C\uBB3C \uC694\uC57D\uC744 JSON\uC73C\uB85C \uCD9C\uB825 (liquid\xB7\uD63C\uD569 \uB808\uD3EC)").action((options) => buildCommand(options));
|
|
6271
6490
|
program.command("docs").description("\uC124\uCE58\uB41C SDK \uBB38\uC11C \uBAA9\uB85D\xB7\uACBD\uB85C \uCD9C\uB825").action(docsCommand);
|
|
6272
6491
|
program.command("doctor").description(
|
|
6273
|
-
"SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
|
|
6274
|
-
).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").
|
|
6492
|
+
"SDK \uBC84\uC804\xB7\uBCF4\uC77C\uB7EC\uD50C\uB808\uC774\uD2B8 \uB4DC\uB9AC\uD504\uD2B8 + \uD3EC\uD138 \uBC30\uCE58 \uC9C4\uB2E8 (\uC9C4\uB2E8 + SDK \uC18C\uC720 \uC2A4\uD0AC \uC790\uB3D9 \uB3D9\uAE30\uD654; package.json\xB7\uD6C5\uC740 \uAC74\uB4DC\uB9AC\uC9C0 \uC54A\uC74C)"
|
|
6493
|
+
).option("--json", "\uAD6C\uC870\uD654 \uCD9C\uB825 (\uC2A4\uD0AC\xB7CI\uC6A9)").option(
|
|
6494
|
+
"--placement <target>",
|
|
6495
|
+
"\uD3EC\uD138 \uC9C4\uB2E8\uC744 \uBC30\uCE58 \uD558\uB098\uB85C \uC881\uD798 (id\xB7\uACBD\uB85C\xB7\uC2AC\uB86F id). \uB9C1\uD06C\xB7\uB85C\uADF8\uC778\uC774 \uC5C6\uC73C\uBA74 \uC885\uB8CC \uCF54\uB4DC 2\xB73"
|
|
6496
|
+
).action((o) => runCommand(() => doctorCommand(o)));
|
|
6275
6497
|
program.command("dev").description("\uC778\uC99D \uD504\uB85D\uC2DC \uD3EC\uD568 \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)").option("-p, --port <port>", "Dev server port", "5173").option(
|
|
6276
6498
|
"--phase <phase>",
|
|
6277
6499
|
"Target phase (dev, qa, real, sandbox). \uC0DD\uB7B5 \uC2DC .env\uC758 VITE_BSTAGE_PHASE, \uADF8\uAC83\uB3C4 \uC5C6\uC73C\uBA74 sandbox"
|
|
@@ -6326,6 +6548,8 @@ program.addHelpText(
|
|
|
6326
6548
|
$ bstage dev \uB85C\uCEEC \uAC1C\uBC1C \uC11C\uBC84 (\uC778\uC99D \uD504\uB85D\uC2DC \xB7 liquid \uB808\uD3EC\uB294 liquidjs \uD504\uB9AC\uBDF0)
|
|
6327
6549
|
$ bstage build IIFE \uBC88\uB4E4 \uBE4C\uB4DC (dist/{\uACBD\uB85C} \xB7 dist/{\uC2AC\uB86F})
|
|
6328
6550
|
$ bstage doctor SDK \uBC84\uC804\xB7\uB4DC\uB9AC\uD504\uD2B8 \uC9C4\uB2E8
|
|
6551
|
+
$ bstage doctor --placement /me
|
|
6552
|
+
\uBC30\uCE58 \uD558\uB098\uB9CC \uD3EC\uD138 \uC9C4\uB2E8 (\uAC8C\uC2DC\xB7\uBE4C\uB4DC\xB7\uC571 \uD0A4 \uBB38\uC81C\uC640 \uC870\uCE58)
|
|
6329
6553
|
$ bstage ai install \uC5D0\uC774\uC804\uD2B8 \uC2A4\uD0AC\xB7AGENTS.md \uC124\uCE58/\uCD5C\uC2E0\uD654 (+ \uC2DC\uD06C\uB9BF \uAC00\uB4DC)
|
|
6330
6554
|
$ bstage ai doctor \uC5D0\uC774\uC804\uD2B8 \uC790\uC0B0 \uCD5C\uC2E0 \uC5EC\uBD80 \uC9C4\uB2E8
|
|
6331
6555
|
$ bstage i18n pull \uD50C\uB7AB\uD3FC \uBC88\uC5ED \uBC1B\uAE30 + \uD0C0\uC785 \uC0DD\uC131
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bstage-sdk/cli",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"description": "bstage SDK CLI — build b.stage templates",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -32,14 +32,14 @@
|
|
|
32
32
|
"liquidjs": "^10.24.0",
|
|
33
33
|
"picocolors": "^1.1.1",
|
|
34
34
|
"vite": "^7.0.0",
|
|
35
|
-
"@bstage-sdk/ai-toolkit": "0.8.
|
|
36
|
-
"@bstage-sdk/core": "0.8.
|
|
35
|
+
"@bstage-sdk/ai-toolkit": "0.8.5",
|
|
36
|
+
"@bstage-sdk/core": "0.8.5"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"@types/node": "^25.5.0",
|
|
40
40
|
"tsup": "^8.0.0",
|
|
41
41
|
"typescript": "^5.5.0",
|
|
42
|
-
"@bstage-sdk/design": "0.8.
|
|
42
|
+
"@bstage-sdk/design": "0.8.5"
|
|
43
43
|
},
|
|
44
44
|
"license": "MIT",
|
|
45
45
|
"scripts": {
|