@bstage-sdk/cli 0.2.0 → 0.3.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/dist/MIGRATION.md +31 -2
- package/dist/{chunk-FER3TEK7.js → chunk-COUDGZIA.js} +44 -12
- package/dist/index.js +92 -65
- package/dist/vite/preset.d.ts +21 -1
- package/dist/vite/preset.js +5 -1
- package/package.json +3 -3
package/dist/MIGRATION.md
CHANGED
|
@@ -45,6 +45,35 @@
|
|
|
45
45
|
|
|
46
46
|
> **`적용` 단계는 옛 프로젝트에서 실제로 따라가 본 뒤 적는다.** 새 `bstage init` 프로젝트에서 되는 것과, 기존 프로젝트가 이 절차만 보고 도달하는 것은 다르다. 따라 했을 때 깨지는 선행 조건이 있으면 **그 조건까지 적는다** — `core 0.44.0` 항목이 그 사례다(스크립트만 넣으면 `@types/node` 부재로 `TS2688`이 난다. 스캐폴드 템플릿을 고쳐 새 프로젝트는 해결됐지만, 먼저 써둔 적용 절차를 되짚지 않아 기존 프로젝트용 지침이 깨진 채 남았다).
|
|
47
47
|
|
|
48
|
-
> **헤더 규칙**: `
|
|
48
|
+
> **헤더 규칙**: `## → {패키지} {버전}` 형식으로, 그 변경을 실제로 낸 패키지와 버전을 명시한다(예: `→ cli 0.3.0`, `→ core 0.3.0`). 한 변경이 여러 패키지를 함께 범프시켰으면 소비자가 올려야 할 패키지를 `·`로 나열한다(예: `→ core 0.3.0 · cli 0.3.0`). 소비자는 이 헤더의 패키지를 해당 버전 **이상**으로 올려야 한다. 단순 의존성 재핀(dependency bump)만 된 패키지는 헤더에 적지 않는다.
|
|
49
|
+
>
|
|
50
|
+
> **정렬**: 릴리즈 **시점 최신이 위**. 패키지가 독립 버전이라 헤더 숫자만으로는 시간순 정렬이 되지 않으므로 릴리즈 순서를 기준으로 한다.
|
|
49
51
|
|
|
50
|
-
|
|
52
|
+
---
|
|
53
|
+
## → core 0.3.0 · cli 0.3.0
|
|
54
|
+
|
|
55
|
+
### 앱 키 이름 정리(`appSecret` → `appKey`, `VITE_BSTAGE_APP_SECRET` → `VITE_BSTAGE_APP_KEY`) — `판단` · `선택`
|
|
56
|
+
|
|
57
|
+
**영향**
|
|
58
|
+
|
|
59
|
+
- **기존 프로젝트가 반드시 할 일은 없다.** `appSecret`·`VITE_BSTAGE_APP_SECRET`은 deprecated 별칭으로 그대로 동작한다. 별칭은 **0.4.0**에서 제거되므로 그 전에 옮긴다.
|
|
60
|
+
- 감지: `src/shared/client.ts`에 `appSecret:`이 있거나, `.env`·`.env.example`에 `VITE_BSTAGE_APP_SECRET`이 있는 경우.
|
|
61
|
+
|
|
62
|
+
**변경 내용**
|
|
63
|
+
|
|
64
|
+
- 같은 값을 포털 화면(APP KEY)·포털 API(`appKey`)·게이트웨이 헤더(`X-BSTAGE-APP-KEY`)는 모두 KEY라고 부르는데 SDK만 `secret`이라고 불렀다. 이 값은 `VITE_` 환경변수라 **빌드 결과물에 평문으로 실려 브라우저에서 보이는 값**이고 비밀값이 아니다 — 이름이 사실과 반대여서 "숨겨야 하는 값"으로 오해하게 했다. SDK 이름을 나머지와 맞췄다.
|
|
65
|
+
- `BstageConfig.appKey`가 정본이고 `appSecret`은 deprecated 별칭이다(둘 다 주면 `appKey` 우선). 타입 주석도 "앱 시크릿"에서 "앱 키(APP KEY) — 브라우저에 노출되는 값"으로 바꿨다.
|
|
66
|
+
- 새 `bstage init` 스캐폴드는 `.env`·`.env.example`·`client.ts`·`vite-env.d.ts`에 새 이름을 쓴다.
|
|
67
|
+
- **소스와 `.env`가 다른 이름을 써도 빌드가 이어 붙인다.** `bstage build`(프리셋)와 `bstageDevPlugin`이 `VITE_BSTAGE_APP_KEY`·`VITE_BSTAGE_APP_SECRET` 중 한쪽만 있으면 다른 이름으로도 같은 값이 읽히게 `define`한다. 그래서 옛 `client.ts`(`appSecret: import.meta.env.VITE_BSTAGE_APP_SECRET`)를 둔 채 `.env`만 새 이름으로 바꿔도, 포털의 환경변수 입력이 새 이름으로 들어와도 번들에 값이 실린다. 둘 다 있으면 각자 실제 값이 그대로 쓰인다.
|
|
68
|
+
- `bstage build`의 인증 값 점검도 같은 순서로 본다 — 소스가 읽는 이름의 값이 우선, 다른 이름은 폴백. 보고에는 소스가 실제로 읽는 이름을 쓴다.
|
|
69
|
+
- 앱 키가 아예 없으면 `X-BSTAGE-APP-KEY` 헤더에 `"undefined"` 문자열을 실던 것을 헤더 생략 + 생성 시 콘솔 경고로 바꿨다. 게이트웨이 응답(401)은 같다.
|
|
70
|
+
|
|
71
|
+
**적용**
|
|
72
|
+
|
|
73
|
+
1. (자동) `@bstage-sdk/core`·`@bstage-sdk/cli`를 `0.3.0` 이상으로 올린다.
|
|
74
|
+
2. (판단) `src/shared/client.ts`의 `appSecret: import.meta.env.VITE_BSTAGE_APP_SECRET`을 `appKey: import.meta.env.VITE_BSTAGE_APP_KEY`로 바꾼다. 리터럴 키를 박아 둔 옛 프로젝트는 키 이름만 `appSecret` → `appKey`로 바꾼다.
|
|
75
|
+
3. (판단) `.env`·`.env.example`의 `VITE_BSTAGE_APP_SECRET=`을 `VITE_BSTAGE_APP_KEY=`로 바꾼다. 값은 그대로다 — 재발급이 아니다.
|
|
76
|
+
4. (판단) `src/vite-env.d.ts`의 `readonly VITE_BSTAGE_APP_SECRET: string`을 `readonly VITE_BSTAGE_APP_KEY: string`으로 바꾼다.
|
|
77
|
+
5. CI·배포 환경에 `VITE_BSTAGE_APP_SECRET`을 주입하고 있었다면 같은 값을 `VITE_BSTAGE_APP_KEY`로 주입한다. 2~4를 한 번에 못 옮기는 기간에는 위 별칭 덕에 어느 한쪽 이름만 있어도 빌드가 통과한다.
|
|
78
|
+
|
|
79
|
+
---
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
import { defineConfig } from "vite";
|
|
3
3
|
import react from "@vitejs/plugin-react";
|
|
4
4
|
|
|
5
|
-
// src/
|
|
6
|
-
import {
|
|
7
|
-
import { readFileSync as readFileSync2 } from "fs";
|
|
8
|
-
import { join, dirname } from "path";
|
|
5
|
+
// src/vite/appKeyEnvAlias.ts
|
|
6
|
+
import { loadEnv } from "vite";
|
|
9
7
|
|
|
10
8
|
// src/constants.ts
|
|
11
9
|
import { readFileSync } from "fs";
|
|
12
10
|
import { resolve } from "path";
|
|
11
|
+
var APP_KEY_VAR = "VITE_BSTAGE_APP_KEY";
|
|
12
|
+
var LEGACY_APP_KEY_VAR = "VITE_BSTAGE_APP_SECRET";
|
|
13
13
|
var BSTAGE_INTERNAL_PREFIX = "/__bstage__";
|
|
14
14
|
var LOGIN_PATH = `${BSTAGE_INTERNAL_PREFIX}/login`;
|
|
15
15
|
var PROXY_PATH_PREFIX = "/__proxy__";
|
|
@@ -88,6 +88,31 @@ function resolveProjectTarget(root) {
|
|
|
88
88
|
return pkg.bstage?.target === "admin" ? "admin" : "user";
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
+
// src/vite/appKeyEnvAlias.ts
|
|
92
|
+
function appKeyEnvDefine(env) {
|
|
93
|
+
const key = env[APP_KEY_VAR]?.trim();
|
|
94
|
+
const legacy = env[LEGACY_APP_KEY_VAR]?.trim();
|
|
95
|
+
if (key && !legacy) return { [`import.meta.env.${LEGACY_APP_KEY_VAR}`]: JSON.stringify(key) };
|
|
96
|
+
if (legacy && !key) return { [`import.meta.env.${APP_KEY_VAR}`]: JSON.stringify(legacy) };
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
function loadProjectEnv(config, mode) {
|
|
100
|
+
return loadEnv(mode, config.envDir ?? config.root ?? process.cwd(), "VITE_");
|
|
101
|
+
}
|
|
102
|
+
function appKeyEnvAliasPlugin() {
|
|
103
|
+
return {
|
|
104
|
+
name: "bstage-app-key-env-alias",
|
|
105
|
+
config(config, { mode }) {
|
|
106
|
+
return { define: appKeyEnvDefine(loadProjectEnv(config, mode)) };
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
// src/dev/devVitePlugin.ts
|
|
112
|
+
import { createRequire } from "module";
|
|
113
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
114
|
+
import { join, dirname } from "path";
|
|
115
|
+
|
|
91
116
|
// src/dev/loginPage.ts
|
|
92
117
|
function getLoginPageHtml(phase, mode = "user") {
|
|
93
118
|
const tokenPath = AUTH_TOKEN_PATH_BY_MODE[mode].replace(/^\/svc/, AUTH_PATH_PREFIX);
|
|
@@ -415,14 +440,14 @@ function getLoginPageHtml(phase, mode = "user") {
|
|
|
415
440
|
// src/dev/proxyUtils.ts
|
|
416
441
|
import { request as httpsRequest } from "https";
|
|
417
442
|
import { gunzipSync, brotliDecompressSync, inflateSync } from "zlib";
|
|
418
|
-
import { loadEnv } from "vite";
|
|
443
|
+
import { loadEnv as loadEnv2 } from "vite";
|
|
419
444
|
var CF_ACCESS_ENV_KEYS = ["VITE_CF_ACCESS_CLIENT_ID", "VITE_CF_ACCESS_CLIENT_SECRET"];
|
|
420
445
|
var cachedCreds;
|
|
421
446
|
var missingWarned = false;
|
|
422
447
|
function resolveCfAccessCreds() {
|
|
423
448
|
if (cachedCreds !== void 0) return cachedCreds;
|
|
424
449
|
const [idKey, secretKey] = CF_ACCESS_ENV_KEYS;
|
|
425
|
-
const fileEnv =
|
|
450
|
+
const fileEnv = loadEnv2("development", process.cwd(), "");
|
|
426
451
|
const id = process.env[idKey] || fileEnv[idKey] || "";
|
|
427
452
|
const secret = process.env[secretKey] || fileEnv[secretKey] || "";
|
|
428
453
|
cachedCreds = id && secret ? { id, secret } : null;
|
|
@@ -542,7 +567,7 @@ function collectBody(req, maxBytes = MAX_REQUEST_BODY_BYTES) {
|
|
|
542
567
|
}
|
|
543
568
|
|
|
544
569
|
// src/dev/resolveHosts.ts
|
|
545
|
-
import { loadEnv as
|
|
570
|
+
import { loadEnv as loadEnv3 } from "vite";
|
|
546
571
|
var HOST_ENV_KEYS = {
|
|
547
572
|
gateway: "VITE_BSTAGE_GATEWAY_HOST",
|
|
548
573
|
auth: "VITE_BSTAGE_AUTH_HOST",
|
|
@@ -559,7 +584,7 @@ function resolveDevHosts(phase, mode, cwd = process.cwd()) {
|
|
|
559
584
|
auth: (tenantId) => getAuthHost(mode, phase, tenantId)
|
|
560
585
|
};
|
|
561
586
|
}
|
|
562
|
-
const fileEnv =
|
|
587
|
+
const fileEnv = loadEnv3("development", cwd, "");
|
|
563
588
|
const read = (key) => (process.env[key] || fileEnv[key] || "").trim();
|
|
564
589
|
const authKey = authKeyFor(mode);
|
|
565
590
|
const gatewayHost = read(HOST_ENV_KEYS.gateway);
|
|
@@ -582,7 +607,7 @@ function resolveDevHosts(phase, mode, cwd = process.cwd()) {
|
|
|
582
607
|
}
|
|
583
608
|
|
|
584
609
|
// src/dev/resolvePhase.ts
|
|
585
|
-
import { loadEnv as
|
|
610
|
+
import { loadEnv as loadEnv4 } from "vite";
|
|
586
611
|
var PHASES = ["dev", "qa", "real", "sandbox"];
|
|
587
612
|
var DEFAULT_PHASE = "sandbox";
|
|
588
613
|
function isPhase(value) {
|
|
@@ -597,7 +622,7 @@ function resolvePhase(explicit, cwd = process.cwd(), env = process.env) {
|
|
|
597
622
|
}
|
|
598
623
|
return { phase: explicit, source: "flag" };
|
|
599
624
|
}
|
|
600
|
-
const fileEnv =
|
|
625
|
+
const fileEnv = loadEnv4("development", cwd, "");
|
|
601
626
|
const fromEnv = env.VITE_BSTAGE_PHASE || fileEnv.VITE_BSTAGE_PHASE || "";
|
|
602
627
|
if (fromEnv) {
|
|
603
628
|
if (isPhase(fromEnv)) return { phase: fromEnv, source: "env" };
|
|
@@ -1949,10 +1974,13 @@ function bstageDevPlugin(options = {}) {
|
|
|
1949
1974
|
return {
|
|
1950
1975
|
name: "bstage-dev",
|
|
1951
1976
|
enforce: "pre",
|
|
1952
|
-
config() {
|
|
1977
|
+
config(config, { mode: mode2 }) {
|
|
1953
1978
|
const root = process.cwd();
|
|
1954
1979
|
projectRequire = createRequire(join(root, "package.json"));
|
|
1955
1980
|
return {
|
|
1981
|
+
// 앱 키 env 별칭 — 소비자 `vite.config.ts`는 이 플러그인만 얹으므로 여기서도 이어 붙인다
|
|
1982
|
+
// (`bstage build`는 프리셋이 맡는다). 상세는 appKeyEnvAlias.ts.
|
|
1983
|
+
define: appKeyEnvDefine(loadProjectEnv(config, mode2)),
|
|
1956
1984
|
optimizeDeps: {
|
|
1957
1985
|
exclude: ["@bstage-sdk/core", "@bstage-sdk/react"]
|
|
1958
1986
|
},
|
|
@@ -2064,7 +2092,7 @@ function bstageDevPlugin(options = {}) {
|
|
|
2064
2092
|
// src/vite/preset.ts
|
|
2065
2093
|
function createViteConfig(options = {}) {
|
|
2066
2094
|
return defineConfig({
|
|
2067
|
-
plugins: [react()],
|
|
2095
|
+
plugins: [react(), appKeyEnvAliasPlugin()],
|
|
2068
2096
|
define: {
|
|
2069
2097
|
"process.env.NODE_ENV": JSON.stringify("production")
|
|
2070
2098
|
},
|
|
@@ -2091,6 +2119,8 @@ function createViteConfig(options = {}) {
|
|
|
2091
2119
|
}
|
|
2092
2120
|
|
|
2093
2121
|
export {
|
|
2122
|
+
APP_KEY_VAR,
|
|
2123
|
+
LEGACY_APP_KEY_VAR,
|
|
2094
2124
|
LOGIN_PATH,
|
|
2095
2125
|
isPublicPhase,
|
|
2096
2126
|
TRANSLATION_LANGUAGES,
|
|
@@ -2101,6 +2131,8 @@ export {
|
|
|
2101
2131
|
PORTAL_HOSTS,
|
|
2102
2132
|
PORTAL_HOST_ENV_KEY,
|
|
2103
2133
|
resolveProjectTarget,
|
|
2134
|
+
appKeyEnvDefine,
|
|
2135
|
+
appKeyEnvAliasPlugin,
|
|
2104
2136
|
resolvePhase,
|
|
2105
2137
|
describePhase,
|
|
2106
2138
|
bstageDevPlugin,
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
+
APP_KEY_VAR,
|
|
3
4
|
DEFAULT_TRANSLATION_TIER,
|
|
5
|
+
LEGACY_APP_KEY_VAR,
|
|
4
6
|
LOGIN_PATH,
|
|
5
7
|
PORTAL_HOSTS,
|
|
6
8
|
PORTAL_HOST_ENV_KEY,
|
|
@@ -14,7 +16,7 @@ import {
|
|
|
14
16
|
isPublicPhase,
|
|
15
17
|
resolvePhase,
|
|
16
18
|
resolveProjectTarget
|
|
17
|
-
} from "./chunk-
|
|
19
|
+
} from "./chunk-COUDGZIA.js";
|
|
18
20
|
|
|
19
21
|
// src/index.ts
|
|
20
22
|
import { readFileSync as readFileSync2 } from "fs";
|
|
@@ -157,10 +159,11 @@ __reg__.forEach(__registerTemplate__);
|
|
|
157
159
|
// src/build/credentialCheck.ts
|
|
158
160
|
var CLIENT_MARKER = "X-BSTAGE-APP-ID";
|
|
159
161
|
var APP_ID_PREFIX = "bsa_";
|
|
160
|
-
var
|
|
162
|
+
var APP_KEY_PREFIX = "bsp_";
|
|
161
163
|
var CREDENTIAL_ENV_VARS = [
|
|
162
164
|
"VITE_BSTAGE_APP_ID",
|
|
163
|
-
|
|
165
|
+
APP_KEY_VAR,
|
|
166
|
+
LEGACY_APP_KEY_VAR,
|
|
164
167
|
"VITE_BSTAGE_TENANT_ID"
|
|
165
168
|
];
|
|
166
169
|
function usesBstageClient(bundle) {
|
|
@@ -180,54 +183,77 @@ function collectReferencedVars(sources) {
|
|
|
180
183
|
return referenced;
|
|
181
184
|
}
|
|
182
185
|
function checkCredentials(env2, referenced) {
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
186
|
+
const appId = referenced.has("VITE_BSTAGE_APP_ID") ? env2.VITE_BSTAGE_APP_ID?.trim() : void 0;
|
|
187
|
+
const appKeys = resolveAppKeys(env2, referenced);
|
|
188
|
+
const targets = [
|
|
189
|
+
...referenced.has("VITE_BSTAGE_APP_ID") ? [{ varName: "VITE_BSTAGE_APP_ID", value: appId }] : [],
|
|
190
|
+
...appKeys,
|
|
191
|
+
...referenced.has("VITE_BSTAGE_TENANT_ID") ? [{ varName: "VITE_BSTAGE_TENANT_ID", value: env2.VITE_BSTAGE_TENANT_ID?.trim() }] : []
|
|
192
|
+
];
|
|
193
|
+
const presenceIssues = targets.flatMap(({ varName, value }) => {
|
|
187
194
|
if (!value) {
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
195
|
+
return [
|
|
196
|
+
{
|
|
197
|
+
level: "error",
|
|
198
|
+
varName,
|
|
199
|
+
message: "\uAC12\uC774 \uC5C6\uC2B5\uB2C8\uB2E4 \u2014 \uBC88\uB4E4\uC5D0 undefined\uAC00 \uBC15\uD600 \uBC30\uD3EC \uD6C4 401\uC774 \uB0A9\uB2C8\uB2E4."
|
|
200
|
+
}
|
|
201
|
+
];
|
|
194
202
|
}
|
|
195
203
|
if (isPlaceholderValue(value)) {
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
204
|
+
return [
|
|
205
|
+
{
|
|
206
|
+
level: "error",
|
|
207
|
+
varName,
|
|
208
|
+
message: "\uC790\uB9AC\uD45C\uC2DC\uC790\uAC00 \uADF8\uB300\uB85C\uC785\uB2C8\uB2E4 \u2014 \uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 \uAC12\uC73C\uB85C \uBC14\uAFB8\uC138\uC694."
|
|
209
|
+
}
|
|
210
|
+
];
|
|
201
211
|
}
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
const
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
212
|
+
return [];
|
|
213
|
+
});
|
|
214
|
+
const usableAppId = appId && !isPlaceholderValue(appId) ? appId : void 0;
|
|
215
|
+
const usableAppKeys = appKeys.filter(
|
|
216
|
+
(k) => !!k.value && !isPlaceholderValue(k.value)
|
|
217
|
+
);
|
|
218
|
+
const swappedKey = usableAppKeys.find((k) => k.value.startsWith(APP_ID_PREFIX));
|
|
219
|
+
const swapped = usableAppId?.startsWith(APP_KEY_PREFIX) || swappedKey !== void 0;
|
|
208
220
|
if (swapped) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
221
|
+
const keyLabel = shortName(swappedKey?.varName ?? appKeys[0]?.varName ?? APP_KEY_VAR);
|
|
222
|
+
return [
|
|
223
|
+
...presenceIssues,
|
|
224
|
+
{
|
|
225
|
+
level: "error",
|
|
226
|
+
varName: "VITE_BSTAGE_APP_ID",
|
|
227
|
+
message: `APP_ID\uC640 ${keyLabel}\uAC00 \uC11C\uB85C \uBC14\uB010 \uAC83 \uAC19\uC2B5\uB2C8\uB2E4 \u2014 APP_ID\uB294 "${APP_ID_PREFIX}", ${keyLabel}\uB294 "${APP_KEY_PREFIX}"\uB85C \uC2DC\uC791\uD574\uC57C \uD569\uB2C8\uB2E4.`
|
|
228
|
+
}
|
|
229
|
+
];
|
|
230
|
+
}
|
|
231
|
+
const prefixWarnings = [
|
|
232
|
+
...usableAppId && !usableAppId.startsWith(APP_ID_PREFIX) ? [
|
|
233
|
+
{
|
|
234
|
+
level: "warn",
|
|
235
|
+
varName: "VITE_BSTAGE_APP_ID",
|
|
236
|
+
message: `"${APP_ID_PREFIX}"\uB85C \uC2DC\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 \uD30C\uD2B8\uB108 \uCF58\uC194 \uBC1C\uAE09 \uAC12\uC774 \uB9DE\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.`
|
|
237
|
+
}
|
|
238
|
+
] : [],
|
|
239
|
+
...usableAppKeys.filter((k) => !k.value.startsWith(APP_KEY_PREFIX)).map(
|
|
240
|
+
(k) => ({
|
|
241
|
+
level: "warn",
|
|
242
|
+
varName: k.varName,
|
|
243
|
+
message: `"${APP_KEY_PREFIX}"\uB85C \uC2DC\uC791\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 \u2014 \uD30C\uD2B8\uB108 \uCF58\uC194 \uBC1C\uAE09 \uAC12\uC774 \uB9DE\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694.`
|
|
244
|
+
})
|
|
245
|
+
)
|
|
246
|
+
];
|
|
247
|
+
return [...presenceIssues, ...prefixWarnings];
|
|
248
|
+
}
|
|
249
|
+
function resolveAppKeys(env2, referenced) {
|
|
250
|
+
return [APP_KEY_VAR, LEGACY_APP_KEY_VAR].filter((varName) => referenced.has(varName)).map((varName) => {
|
|
251
|
+
const other = varName === APP_KEY_VAR ? LEGACY_APP_KEY_VAR : APP_KEY_VAR;
|
|
252
|
+
return { varName, value: env2[varName]?.trim() || env2[other]?.trim() || void 0 };
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
function shortName(varName) {
|
|
256
|
+
return varName.replace(/^VITE_BSTAGE_/, "");
|
|
231
257
|
}
|
|
232
258
|
|
|
233
259
|
// src/commands/build.ts
|
|
@@ -1739,7 +1765,7 @@ ${commandsSection}
|
|
|
1739
1765
|
- \uC804\uC5ED CSS \uD30C\uC77C(\`<link>\`, \uC678\uBD80 \uC2A4\uD0C0\uC77C\uC2DC\uD2B8)\uC744 \uC0AC\uC6A9\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 Shadow DOM \uB0B4\uBD80\uC5D0 \uC801\uC6A9\uB418\uC9C0 \uC54A\uB294\uB2E4.
|
|
1740
1766
|
- **\`import './style.css'\`\uB85C \uC2A4\uD0C0\uC77C\uC744 \uB123\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uBC30\uD3EC \uC0B0\uCD9C\uBB3C\uC5D0\uC11C \uC0AC\uB77C\uC9C4\uB2E4.** \uB85C\uCEEC \uAC1C\uBC1C \uD654\uBA74\uC5D0\uC11C\uB294 \uC801\uC6A9\uB418\uC5B4 \uB208\uCE58\uCC44\uAE30 \uC5B4\uB835\uB2E4. CSS \uD30C\uC77C\uC744 \uC4F0\uB824\uBA74 \`import css from './style.css?inline'\`\uC73C\uB85C \uBB38\uC790\uC5F4\uC744 \uAC00\uC838\uC640 \`createTemplate(..., { styles: css })\`\uC5D0 \uB118\uAE30\uAC70\uB098 \uCEF4\uD3EC\uB10C\uD2B8 \uC548 \`<style>{css}</style>\`\uB85C \uB80C\uB354\uD55C\uB2E4. inline \`style={{}}\`\uB3C4 \uB41C\uB2E4
|
|
1741
1767
|
- UI \uC0C9\xB7\uD0C0\uC774\uD3EC\xB7\uADF8\uB9BC\uC790\uB97C hex/rgb\uB85C \uD558\uB4DC\uCF54\uB529\uD558\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC704 '\uB514\uC790\uC778' \uC139\uC158\uC758 \uB514\uC790\uC778 \uD1A0\uD070\uC744 \uC0AC\uC6A9
|
|
1742
|
-
- \uC571\uD0A4(APP-ID \`bsa_\u2026\`\
|
|
1768
|
+
- \uC571\uD0A4(APP-ID \`bsa_\u2026\`\xB7APP KEY \`bsp_\u2026\`, \uC5B4\uB4DC\uBBFC \uAC8C\uC774\uD2B8\uC6E8\uC774 \`bsm_\u2026\`)\uB97C \uC18C\uC2A4 \uCF54\uB4DC\uC5D0 \uB9AC\uD130\uB7F4\uB85C \uB123\uC9C0 \uC54A\uB294\uB2E4 \u2014 \uC778\uC99D \uAC12\uC740 \`.env\`(\uCEE4\uBC0B \uC548 \uB428)\uC5D0\uC11C \`import.meta.env.VITE_BSTAGE_*\`\uB85C\uB9CC \uC8FC\uC785\uD55C\uB2E4. pre-commit \uD6C5\uC774 \uCEE4\uBC0B \uC804 \uAC80\uCD9C\xB7\uCC28\uB2E8\uD558\uBA70 \`--no-verify\`\uB85C \uC6B0\uD68C\uD558\uC9C0 \uC54A\uB294\uB2E4
|
|
1743
1769
|
${apiForbidBullet}
|
|
1744
1770
|
`;
|
|
1745
1771
|
}
|
|
@@ -1761,14 +1787,15 @@ function claudeMd() {
|
|
|
1761
1787
|
}
|
|
1762
1788
|
|
|
1763
1789
|
// src/templates/env.ts
|
|
1764
|
-
function env({ phase, appId,
|
|
1790
|
+
function env({ phase, appId, appKey, tenantId }) {
|
|
1765
1791
|
return `VITE_BSTAGE_PHASE=${phase}
|
|
1766
1792
|
|
|
1767
1793
|
# \uC778\uC99D \uC815\uBCF4(\uC120\uD0DD) \u2014 BstageClient\uB85C API\uB97C \uD638\uCD9C\uD560 \uB54C\uB9CC \uD544\uC694\uD569\uB2C8\uB2E4.
|
|
1768
1794
|
# API \uC5C6\uC774 UI\uB9CC \uB80C\uB354\uD558\uB294 \uD15C\uD50C\uB9BF\uC740 \uAC12\uC744 \uCC44\uC6B0\uC9C0 \uC54A\uC544\uB3C4 \uB429\uB2C8\uB2E4.
|
|
1769
1795
|
# .env\uB294 \uCEE4\uBC0B\uB418\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(.gitignore). \uAC12\uC740 b.stage \uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09.
|
|
1796
|
+
# APP_KEY\uB294 \uD3EC\uD138\uC758 "APP KEY"\uC640 \uAC19\uC740 \uAC12\uC785\uB2C8\uB2E4. \uBE0C\uB77C\uC6B0\uC800\uC5D0 \uB178\uCD9C\uB418\uB294 \uAC12\uC774\uB77C \uBE44\uBC00\uAC12\uC774 \uC544\uB2D9\uB2C8\uB2E4.
|
|
1770
1797
|
VITE_BSTAGE_APP_ID=${appId}
|
|
1771
|
-
|
|
1798
|
+
VITE_BSTAGE_APP_KEY=${appKey}
|
|
1772
1799
|
VITE_BSTAGE_TENANT_ID=${tenantId}
|
|
1773
1800
|
|
|
1774
1801
|
# CF Access \uC790\uACA9\uC99D\uBA85 \u2014 dev\xB7qa phase\uB85C \uAC1C\uBC1C\uD560 \uB54C\uB9CC \uD544\uC694\uD569\uB2C8\uB2E4.
|
|
@@ -1892,9 +1919,9 @@ createTemplate(MyWidget, {
|
|
|
1892
1919
|
VITE_BSTAGE_PHASE=dev # dev | qa | real | sandbox
|
|
1893
1920
|
\`\`\`
|
|
1894
1921
|
|
|
1895
|
-
API \uD0A4(APP-ID/
|
|
1922
|
+
API \uD0A4(APP-ID/APP KEY)\uB294 \`.env\`\uC5D0\uC11C \uC124\uC815\uD569\uB2C8\uB2E4. \`.env\`\uB294 \uCEE4\uBC0B\uB418\uC9C0 \uC54A\uC73C\uB2C8, clone \uD6C4 \`.env.example\`\uC744 \`.env\`\uB85C \uBCF5\uC0AC\uD574 \uAC12\uC744 \uCC44\uC6B0\uC138\uC694.
|
|
1896
1923
|
|
|
1897
|
-
> **\
|
|
1924
|
+
> **\uADDC\uCE59**: \uC571\uD0A4 \uAC12\uC744 \uC18C\uC2A4 \uCF54\uB4DC(\uC608: \`client.ts\`)\uC5D0 \uC9C1\uC811 \uB123\uC9C0 \uB9C8\uC138\uC694 \u2014 \uBC18\uB4DC\uC2DC \`.env\`\uB85C\uB9CC \uC8FC\uC785\uD569\uB2C8\uB2E4. APP KEY\uB294 \uBE0C\uB77C\uC6B0\uC800\uC5D0 \uB178\uCD9C\uB418\uB294 \uAC12\uC774\uB77C \uBE44\uBC00\uC740 \uC544\uB2C8\uC9C0\uB9CC, \uD658\uACBD\uB9C8\uB2E4 \uAC12\uC774 \uB2E4\uB974\uACE0 \uC800\uC7A5\uC18C\uC5D0 \uBC15\uD788\uBA74 \uC7AC\uBC1C\uAE09 \uB54C \uCF54\uB4DC \uC218\uC815\uC774 \uB530\uB77C\uC635\uB2C8\uB2E4. \`bstage init\`\uC774 \uC124\uCE58\uD55C pre-commit \uD6C5\uC774 \uCEE4\uBC0B \uC804 \uD0A4 \uB9AC\uD130\uB7F4\uC744 \uCC28\uB2E8\uD558\uBA70, \`--no-verify\`\uB85C \uC6B0\uD68C\uD558\uC9C0 \uB9C8\uC138\uC694.
|
|
1898
1925
|
|
|
1899
1926
|
## SDK \uC5C5\uB370\uC774\uD2B8
|
|
1900
1927
|
|
|
@@ -2541,7 +2568,7 @@ function viteEnvDts() {
|
|
|
2541
2568
|
interface ImportMetaEnv {
|
|
2542
2569
|
readonly VITE_BSTAGE_PHASE: string
|
|
2543
2570
|
readonly VITE_BSTAGE_APP_ID: string
|
|
2544
|
-
readonly
|
|
2571
|
+
readonly VITE_BSTAGE_APP_KEY: string
|
|
2545
2572
|
readonly VITE_BSTAGE_TENANT_ID: string
|
|
2546
2573
|
}
|
|
2547
2574
|
|
|
@@ -2559,7 +2586,7 @@ function clientTs() {
|
|
|
2559
2586
|
// clone \uD6C4 .env.example\uC744 .env\uB85C \uBCF5\uC0AC\uD574 \uAC12\uC744 \uCC44\uC6B0\uC138\uC694.
|
|
2560
2587
|
export const client = new BstageClient({
|
|
2561
2588
|
appId: import.meta.env.VITE_BSTAGE_APP_ID,
|
|
2562
|
-
|
|
2589
|
+
appKey: import.meta.env.VITE_BSTAGE_APP_KEY,
|
|
2563
2590
|
tenantId: import.meta.env.VITE_BSTAGE_TENANT_ID,
|
|
2564
2591
|
})
|
|
2565
2592
|
`;
|
|
@@ -2665,7 +2692,7 @@ async function initCommand(options) {
|
|
|
2665
2692
|
let phase;
|
|
2666
2693
|
let target;
|
|
2667
2694
|
let appId = "";
|
|
2668
|
-
let
|
|
2695
|
+
let appKey = "";
|
|
2669
2696
|
let tenantId = "";
|
|
2670
2697
|
if (options.yes) {
|
|
2671
2698
|
const targetOpt = options.target ?? "user";
|
|
@@ -2758,11 +2785,11 @@ async function initCommand(options) {
|
|
|
2758
2785
|
message: "\uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 APP-ID\uB97C \uC785\uB825\uD574 \uC8FC\uC138\uC694."
|
|
2759
2786
|
}) ?? "";
|
|
2760
2787
|
if (p2.isCancel(appId)) return cancelled();
|
|
2761
|
-
|
|
2762
|
-
message: "\uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740
|
|
2788
|
+
appKey = await p2.text({
|
|
2789
|
+
message: "\uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 APP KEY\uB97C \uC785\uB825\uD574 \uC8FC\uC138\uC694."
|
|
2763
2790
|
}) ?? "";
|
|
2764
|
-
if (p2.isCancel(
|
|
2765
|
-
warnIfCredentialsSwapped(appId,
|
|
2791
|
+
if (p2.isCancel(appKey)) return cancelled();
|
|
2792
|
+
warnIfCredentialsSwapped(appId, appKey);
|
|
2766
2793
|
tenantId = space;
|
|
2767
2794
|
}
|
|
2768
2795
|
}
|
|
@@ -2816,7 +2843,7 @@ async function initCommand(options) {
|
|
|
2816
2843
|
env({
|
|
2817
2844
|
phase,
|
|
2818
2845
|
appId: appId || "YOUR_APP_ID",
|
|
2819
|
-
|
|
2846
|
+
appKey: appKey || "YOUR_APP_KEY",
|
|
2820
2847
|
tenantId: tenantId || "YOUR_TENANT_ID"
|
|
2821
2848
|
})
|
|
2822
2849
|
],
|
|
@@ -2825,7 +2852,7 @@ async function initCommand(options) {
|
|
|
2825
2852
|
env({
|
|
2826
2853
|
phase,
|
|
2827
2854
|
appId: "YOUR_APP_ID",
|
|
2828
|
-
|
|
2855
|
+
appKey: "YOUR_APP_KEY",
|
|
2829
2856
|
tenantId: "YOUR_TENANT_ID"
|
|
2830
2857
|
})
|
|
2831
2858
|
]
|
|
@@ -2925,12 +2952,12 @@ function validateElementName(v) {
|
|
|
2925
2952
|
}
|
|
2926
2953
|
}
|
|
2927
2954
|
var APP_ID_PREFIX2 = "bsa_";
|
|
2928
|
-
var
|
|
2929
|
-
function warnIfCredentialsSwapped(appId,
|
|
2930
|
-
if (!appId.startsWith(
|
|
2955
|
+
var APP_KEY_PREFIX2 = "bsp_";
|
|
2956
|
+
function warnIfCredentialsSwapped(appId, appKey) {
|
|
2957
|
+
if (!appId.startsWith(APP_KEY_PREFIX2) && !appKey.startsWith(APP_ID_PREFIX2)) return;
|
|
2931
2958
|
p2.log.warn(
|
|
2932
|
-
`APP-ID\uC640
|
|
2933
|
-
APP-ID\uB294 "${APP_ID_PREFIX2}",
|
|
2959
|
+
`APP-ID\uC640 APP KEY\uAC00 \uC11C\uB85C \uBC14\uB010 \uAC83 \uAC19\uC2B5\uB2C8\uB2E4.
|
|
2960
|
+
APP-ID\uB294 "${APP_ID_PREFIX2}", APP KEY\uB294 "${APP_KEY_PREFIX2}"\uB85C \uC2DC\uC791\uD569\uB2C8\uB2E4.
|
|
2934
2961
|
\uD30C\uD2B8\uB108 \uCF58\uC194\uC5D0\uC11C \uBC1C\uAE09\uBC1B\uC740 \uAC12\uC744 \uB2E4\uC2DC \uD655\uC778\uD574 \uC8FC\uC138\uC694.`
|
|
2935
2962
|
);
|
|
2936
2963
|
}
|
package/dist/vite/preset.d.ts
CHANGED
|
@@ -28,6 +28,25 @@ interface BstageDevPluginOptions {
|
|
|
28
28
|
*/
|
|
29
29
|
declare function bstageDevPlugin(options?: BstageDevPluginOptions): Plugin;
|
|
30
30
|
|
|
31
|
+
/**
|
|
32
|
+
* 앱 키 환경변수의 새 이름(`VITE_BSTAGE_APP_KEY`)과 옛 이름(`VITE_BSTAGE_APP_SECRET`)을 서로 이어 붙이는
|
|
33
|
+
* `define` 항목을 만든다.
|
|
34
|
+
*
|
|
35
|
+
* 별칭 기간에는 소스와 `.env`가 다른 이름을 쓰는 조합이 실제로 생긴다 — 기존 프로젝트의 `client.ts`는
|
|
36
|
+
* 옛 이름을 읽는데 포털의 환경변수 입력은 새 이름을 넣고, 반대로 새 스캐폴드에 옛 `.env`를 복사해
|
|
37
|
+
* 오기도 한다. Vite는 `import.meta.env.X`를 빌드 시점에 문자열로 치환하므로 이 조합은 번들에
|
|
38
|
+
* undefined가 박혀 배포 뒤 401로만 드러난다. 한쪽만 있으면 다른 이름으로도 같은 값이 읽히게 한다.
|
|
39
|
+
*
|
|
40
|
+
* - 둘 다 있으면 손대지 않는다(각자 실제 값). 둘 다 없으면 아무것도 정의하지 않는다(UI 전용 템플릿).
|
|
41
|
+
* - 값은 `JSON.stringify`로 감싼다 — define은 코드 조각 치환이라 따옴표가 없으면 식별자가 된다.
|
|
42
|
+
*/
|
|
43
|
+
declare function appKeyEnvDefine(env: Record<string, string | undefined>): Record<string, string>;
|
|
44
|
+
/**
|
|
45
|
+
* `appKeyEnvDefine`을 Vite 설정에 얹는 플러그인. `bstage build`(프리셋)와 `bstageDevPlugin`(dev 서버)이
|
|
46
|
+
* 함께 쓴다.
|
|
47
|
+
*/
|
|
48
|
+
declare function appKeyEnvAliasPlugin(): Plugin;
|
|
49
|
+
|
|
31
50
|
interface VitePresetOptions {
|
|
32
51
|
/** Entry file path (default: 'src/index.tsx') */
|
|
33
52
|
entry?: string;
|
|
@@ -40,7 +59,8 @@ interface VitePresetOptions {
|
|
|
40
59
|
*
|
|
41
60
|
* `<script>` 태그로 로드 가능한 IIFE 번들(`template.js`)을 출력.
|
|
42
61
|
* React를 번들에 포함(외부화하지 않음). CSS는 Shadow DOM 주입을 위해 JS에 인라인.
|
|
62
|
+
* 앱 키 env 별칭(`appKeyEnvAliasPlugin`)을 얹어 옛 이름·새 이름 어느 쪽 `.env`든 번들에 실리게 한다.
|
|
43
63
|
*/
|
|
44
64
|
declare function createViteConfig(options?: VitePresetOptions): UserConfig;
|
|
45
65
|
|
|
46
|
-
export { type BstageDevPluginOptions, type VitePresetOptions, bstageDevPlugin, createViteConfig };
|
|
66
|
+
export { type BstageDevPluginOptions, type VitePresetOptions, appKeyEnvAliasPlugin, appKeyEnvDefine, bstageDevPlugin, createViteConfig };
|
package/dist/vite/preset.js
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
|
+
appKeyEnvAliasPlugin,
|
|
3
|
+
appKeyEnvDefine,
|
|
2
4
|
bstageDevPlugin,
|
|
3
5
|
createViteConfig
|
|
4
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-COUDGZIA.js";
|
|
5
7
|
export {
|
|
8
|
+
appKeyEnvAliasPlugin,
|
|
9
|
+
appKeyEnvDefine,
|
|
6
10
|
bstageDevPlugin,
|
|
7
11
|
createViteConfig
|
|
8
12
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bstage-sdk/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "bstage SDK CLI — build b.stage templates",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -31,13 +31,13 @@
|
|
|
31
31
|
"commander": "^12.0.0",
|
|
32
32
|
"picocolors": "^1.1.1",
|
|
33
33
|
"vite": "^7.0.0",
|
|
34
|
-
"@bstage-sdk/core": "0.
|
|
34
|
+
"@bstage-sdk/core": "0.3.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "^25.5.0",
|
|
38
38
|
"tsup": "^8.0.0",
|
|
39
39
|
"typescript": "^5.5.0",
|
|
40
|
-
"@bstage-sdk/design": "0.
|
|
40
|
+
"@bstage-sdk/design": "0.3.0"
|
|
41
41
|
},
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"scripts": {
|