@bstage-sdk/cli 0.1.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/LICENSE +21 -0
- package/dist/MIGRATION.md +50 -0
- package/dist/chunk-S6HGR2U3.js +2076 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +2800 -0
- package/dist/vite/preset.d.ts +46 -0
- package/dist/vite/preset.js +8 -0
- package/package.json +47 -0
|
@@ -0,0 +1,2076 @@
|
|
|
1
|
+
// src/vite/preset.ts
|
|
2
|
+
import { defineConfig } from "vite";
|
|
3
|
+
import react from "@vitejs/plugin-react";
|
|
4
|
+
|
|
5
|
+
// src/dev/devVitePlugin.ts
|
|
6
|
+
import { createRequire } from "module";
|
|
7
|
+
import { readFileSync as readFileSync2 } from "fs";
|
|
8
|
+
import { join, dirname } from "path";
|
|
9
|
+
|
|
10
|
+
// src/constants.ts
|
|
11
|
+
import { readFileSync } from "fs";
|
|
12
|
+
import { resolve } from "path";
|
|
13
|
+
var BSTAGE_INTERNAL_PREFIX = "/__bstage__";
|
|
14
|
+
var LOGIN_PATH = `${BSTAGE_INTERNAL_PREFIX}/login`;
|
|
15
|
+
var PROXY_PATH_PREFIX = "/__proxy__";
|
|
16
|
+
var AUTH_PATH_PREFIX = "/__auth__";
|
|
17
|
+
var ACCESS_TOKEN_COOKIE = "bmf_bstage_access_token";
|
|
18
|
+
var ADMIN_ACCESS_TOKEN_COOKIE = "bmf_mybstage_admin_access_token";
|
|
19
|
+
var ACCESS_TOKEN_RE = new RegExp(`${ACCESS_TOKEN_COOKIE}=([^;]+)`);
|
|
20
|
+
var ADMIN_ACCESS_TOKEN_RE = new RegExp(`${ADMIN_ACCESS_TOKEN_COOKIE}=([^;]+)`);
|
|
21
|
+
var ACCESS_TOKEN_COOKIE_BY_MODE = {
|
|
22
|
+
user: ACCESS_TOKEN_COOKIE,
|
|
23
|
+
admin: ADMIN_ACCESS_TOKEN_COOKIE
|
|
24
|
+
};
|
|
25
|
+
var ACCESS_TOKEN_RE_BY_MODE = {
|
|
26
|
+
user: ACCESS_TOKEN_RE,
|
|
27
|
+
admin: ADMIN_ACCESS_TOKEN_RE
|
|
28
|
+
};
|
|
29
|
+
var TENANT_ID_HEADER = "x-bstage-tenant-id";
|
|
30
|
+
var GATEWAY_HOSTS = {
|
|
31
|
+
real: (id) => `${id}.bstage.in`,
|
|
32
|
+
// sandbox는 real식 — 테넌트 도메인이 곧 게이트웨이(공용 게이트웨이 호스트 아님)
|
|
33
|
+
sandbox: (id) => `${id}.sandstage.in`
|
|
34
|
+
};
|
|
35
|
+
var AUTH_HOSTS = {
|
|
36
|
+
real: (id) => `${id}.bstage.in`,
|
|
37
|
+
// sandbox는 real식 — 게이트웨이와 동일한 테넌트 도메인이 인증 호스트
|
|
38
|
+
sandbox: (id) => `${id}.sandstage.in`
|
|
39
|
+
};
|
|
40
|
+
var ADMIN_AUTH_HOSTS = {
|
|
41
|
+
real: () => "account.mybstage.in",
|
|
42
|
+
// sandbox는 real식 — phase 세그먼트 없는 단일 account 호스트
|
|
43
|
+
sandbox: () => "account.mysandstage.in"
|
|
44
|
+
};
|
|
45
|
+
function isPublicPhase(phase) {
|
|
46
|
+
return phase in GATEWAY_HOSTS;
|
|
47
|
+
}
|
|
48
|
+
var PHASE_PATH_PREFIX = {
|
|
49
|
+
dev: "/api",
|
|
50
|
+
qa: "/api",
|
|
51
|
+
real: "/gw",
|
|
52
|
+
// sandbox는 real식 게이트웨이 프리픽스
|
|
53
|
+
sandbox: "/gw"
|
|
54
|
+
};
|
|
55
|
+
var AUTH_TOKEN_PATH_BY_MODE = {
|
|
56
|
+
user: "/svc/account/api/v1/auth/token",
|
|
57
|
+
admin: "/svc/api/v1/auth/token"
|
|
58
|
+
};
|
|
59
|
+
var AUTH_TOKEN_REFRESH_PATH_BY_MODE = {
|
|
60
|
+
user: "/svc/account/api/v1/auth/token/refresh",
|
|
61
|
+
admin: "/svc/api/v1/auth/token/refresh"
|
|
62
|
+
};
|
|
63
|
+
var TRANSLATION_LANGUAGES = ["ko", "en", "ja", "zh-CN", "zh-TW", "es", "vi"];
|
|
64
|
+
var DEFAULT_TRANSLATION_TIER = "inhouse";
|
|
65
|
+
var TRANSLATION_CDN_ORIGIN = "https://cdn.static.bstage.in";
|
|
66
|
+
var TRANSLATION_CDN_BASE_KEY = "static/i18n";
|
|
67
|
+
var TRANSLATION_CDN_BUCKET_PREFIX = "cdn.bstage.in/";
|
|
68
|
+
function getAuthHost(mode, phase, tenantId) {
|
|
69
|
+
if (mode === "admin") {
|
|
70
|
+
const fn2 = ADMIN_AUTH_HOSTS[phase];
|
|
71
|
+
return fn2 ? fn2() : null;
|
|
72
|
+
}
|
|
73
|
+
const fn = AUTH_HOSTS[phase];
|
|
74
|
+
return fn ? fn(tenantId) : null;
|
|
75
|
+
}
|
|
76
|
+
function resolveProjectTarget(root) {
|
|
77
|
+
let pkg;
|
|
78
|
+
try {
|
|
79
|
+
pkg = JSON.parse(readFileSync(resolve(root, "package.json"), "utf-8"));
|
|
80
|
+
} catch {
|
|
81
|
+
return "user";
|
|
82
|
+
}
|
|
83
|
+
return pkg.bstage?.target === "admin" ? "admin" : "user";
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/dev/loginPage.ts
|
|
87
|
+
function getLoginPageHtml(phase, mode = "user") {
|
|
88
|
+
const tokenPath = AUTH_TOKEN_PATH_BY_MODE[mode].replace(/^\/svc/, AUTH_PATH_PREFIX);
|
|
89
|
+
const twoFactorVerifyPath = `${AUTH_PATH_PREFIX}/api/v1/operators/two-factor/validate-and-register`;
|
|
90
|
+
const modeLabel = mode === "admin" ? "admin" : "user";
|
|
91
|
+
const subtitle = mode === "admin" ? "\uB85C\uCEEC \uAC1C\uBC1C \uD658\uACBD \uC5B4\uB4DC\uBBFC \uB85C\uADF8\uC778" : "\uB85C\uCEEC \uAC1C\uBC1C \uD658\uACBD \uB85C\uADF8\uC778";
|
|
92
|
+
return (
|
|
93
|
+
/* html */
|
|
94
|
+
`<!DOCTYPE html>
|
|
95
|
+
<html lang="ko">
|
|
96
|
+
<head>
|
|
97
|
+
<meta charset="UTF-8" />
|
|
98
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
99
|
+
<title>bstage dev login (${modeLabel})</title>
|
|
100
|
+
<style>
|
|
101
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
102
|
+
|
|
103
|
+
body {
|
|
104
|
+
font-family: system-ui, sans-serif;
|
|
105
|
+
display: flex;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
min-height: 100vh;
|
|
108
|
+
padding-top: 100px;
|
|
109
|
+
color: #111;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.card {
|
|
113
|
+
width: 100%;
|
|
114
|
+
max-width: 380px;
|
|
115
|
+
padding: 36px 32px;
|
|
116
|
+
border: 1px solid #e5e5e5;
|
|
117
|
+
border-radius: 12px;
|
|
118
|
+
height: fit-content;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.header {
|
|
122
|
+
margin-bottom: 28px;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
.title {
|
|
126
|
+
font-size: 18px;
|
|
127
|
+
font-weight: 600;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.badge {
|
|
131
|
+
display: inline-block;
|
|
132
|
+
font-size: 11px;
|
|
133
|
+
font-weight: 600;
|
|
134
|
+
color: #fff;
|
|
135
|
+
padding: 2px 8px;
|
|
136
|
+
border-radius: 3px;
|
|
137
|
+
margin-left: 6px;
|
|
138
|
+
vertical-align: middle;
|
|
139
|
+
text-transform: uppercase;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.badge.phase { background: #111; }
|
|
143
|
+
.badge.mode-user { background: #06c; }
|
|
144
|
+
.badge.mode-admin { background: #c60; }
|
|
145
|
+
|
|
146
|
+
.subtitle {
|
|
147
|
+
font-size: 14px;
|
|
148
|
+
color: #999;
|
|
149
|
+
margin-top: 6px;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
form {
|
|
153
|
+
display: flex;
|
|
154
|
+
flex-direction: column;
|
|
155
|
+
gap: 18px;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
.field {
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-direction: column;
|
|
161
|
+
gap: 6px;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
label {
|
|
165
|
+
font-size: 14px;
|
|
166
|
+
font-weight: 500;
|
|
167
|
+
color: #555;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
input {
|
|
171
|
+
width: 100%;
|
|
172
|
+
padding: 12px 14px;
|
|
173
|
+
font-size: 15px;
|
|
174
|
+
border: 1px solid #e5e5e5;
|
|
175
|
+
border-radius: 8px;
|
|
176
|
+
outline: none;
|
|
177
|
+
transition: border-color 0.15s;
|
|
178
|
+
}
|
|
179
|
+
input::placeholder { color: #ccc; }
|
|
180
|
+
input:focus { border-color: #111; }
|
|
181
|
+
|
|
182
|
+
button {
|
|
183
|
+
width: 100%;
|
|
184
|
+
padding: 12px;
|
|
185
|
+
font-size: 15px;
|
|
186
|
+
font-weight: 600;
|
|
187
|
+
color: #fff;
|
|
188
|
+
background: #111;
|
|
189
|
+
border: none;
|
|
190
|
+
border-radius: 8px;
|
|
191
|
+
cursor: pointer;
|
|
192
|
+
margin-top: 6px;
|
|
193
|
+
transition: opacity 0.15s;
|
|
194
|
+
}
|
|
195
|
+
button:hover { opacity: 0.85; }
|
|
196
|
+
button:disabled { opacity: 0.4; cursor: not-allowed; }
|
|
197
|
+
|
|
198
|
+
.link {
|
|
199
|
+
background: none;
|
|
200
|
+
color: #06c;
|
|
201
|
+
font-weight: 500;
|
|
202
|
+
padding: 0;
|
|
203
|
+
margin: 8px 0 0;
|
|
204
|
+
width: auto;
|
|
205
|
+
align-self: flex-start;
|
|
206
|
+
}
|
|
207
|
+
.link:hover { opacity: 0.7; }
|
|
208
|
+
|
|
209
|
+
.error {
|
|
210
|
+
color: #c00;
|
|
211
|
+
font-size: 14px;
|
|
212
|
+
display: none;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
.info {
|
|
216
|
+
font-size: 13px;
|
|
217
|
+
color: #666;
|
|
218
|
+
line-height: 1.5;
|
|
219
|
+
padding: 10px 12px;
|
|
220
|
+
background: #f5f7fa;
|
|
221
|
+
border-radius: 6px;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
.success {
|
|
225
|
+
text-align: center;
|
|
226
|
+
padding: 24px 0;
|
|
227
|
+
font-size: 15px;
|
|
228
|
+
color: #666;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
.hidden { display: none; }
|
|
232
|
+
</style>
|
|
233
|
+
</head>
|
|
234
|
+
<body>
|
|
235
|
+
<div class="card">
|
|
236
|
+
<div class="header">
|
|
237
|
+
<div class="title">
|
|
238
|
+
b.stage
|
|
239
|
+
<span class="badge phase">${phase}</span>
|
|
240
|
+
<span class="badge mode-${mode}">${modeLabel}</span>
|
|
241
|
+
</div>
|
|
242
|
+
<div class="subtitle">${subtitle}</div>
|
|
243
|
+
</div>
|
|
244
|
+
|
|
245
|
+
<form id="loginForm">
|
|
246
|
+
<div class="field">
|
|
247
|
+
<label for="tenantId">Space ID</label>
|
|
248
|
+
<input id="tenantId" type="text" placeholder="e.g. bmf" autocomplete="off" required />
|
|
249
|
+
</div>
|
|
250
|
+
<div class="field">
|
|
251
|
+
<label for="email">Email</label>
|
|
252
|
+
<input id="email" type="email" placeholder="you@example.com" autocomplete="email" required />
|
|
253
|
+
</div>
|
|
254
|
+
<div class="field">
|
|
255
|
+
<label for="password">Password</label>
|
|
256
|
+
<input id="password" type="password" placeholder="password" autocomplete="current-password" required />
|
|
257
|
+
</div>
|
|
258
|
+
<div id="error" class="error"></div>
|
|
259
|
+
<button type="submit">Login</button>
|
|
260
|
+
</form>
|
|
261
|
+
|
|
262
|
+
<form id="otpForm" class="hidden">
|
|
263
|
+
<div class="info">2\uB2E8\uACC4 \uC778\uC99D \u2014 \uB4F1\uB85D\uB41C \uC218\uB2E8\uC73C\uB85C \uBC1C\uC1A1\uB41C OTP \uCF54\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694.</div>
|
|
264
|
+
<div class="field">
|
|
265
|
+
<label for="otp">OTP</label>
|
|
266
|
+
<input id="otp" type="text" inputmode="numeric" autocomplete="one-time-code" placeholder="6\uC790\uB9AC \uCF54\uB4DC" required />
|
|
267
|
+
</div>
|
|
268
|
+
<div id="otpError" class="error"></div>
|
|
269
|
+
<button type="submit">Verify</button>
|
|
270
|
+
<button type="button" class="link" id="otpBack">\u2190 \uC774\uBA54\uC77C/\uBE44\uBC00\uBC88\uD638 \uB2E4\uC2DC \uC785\uB825</button>
|
|
271
|
+
</form>
|
|
272
|
+
|
|
273
|
+
<div id="success" class="success hidden">
|
|
274
|
+
<p>Logged in \u2014 Redirecting...</p>
|
|
275
|
+
</div>
|
|
276
|
+
</div>
|
|
277
|
+
|
|
278
|
+
<script>
|
|
279
|
+
const loginForm = document.getElementById('loginForm');
|
|
280
|
+
const otpForm = document.getElementById('otpForm');
|
|
281
|
+
const errorEl = document.getElementById('error');
|
|
282
|
+
const otpErrorEl = document.getElementById('otpError');
|
|
283
|
+
const successEl = document.getElementById('success');
|
|
284
|
+
const otpBackBtn = document.getElementById('otpBack');
|
|
285
|
+
const TOKEN_PATH = ${JSON.stringify(tokenPath)};
|
|
286
|
+
const TWO_FACTOR_VERIFY_PATH = ${JSON.stringify(twoFactorVerifyPath)};
|
|
287
|
+
|
|
288
|
+
// 1\uB2E8\uACC4\uC5D0\uC11C \uBC1B\uC740 \uAC12 \u2014 2\uB2E8\uACC4(OTP)\uC5D0\uC11C \uC7AC\uC0AC\uC6A9
|
|
289
|
+
let pending = null;
|
|
290
|
+
|
|
291
|
+
function showError(el, msg) {
|
|
292
|
+
el.textContent = msg;
|
|
293
|
+
el.style.display = 'block';
|
|
294
|
+
}
|
|
295
|
+
function hideError(el) {
|
|
296
|
+
el.style.display = 'none';
|
|
297
|
+
}
|
|
298
|
+
function setBusy(form, busy, label) {
|
|
299
|
+
const btn = form.querySelector('button[type="submit"]');
|
|
300
|
+
btn.disabled = busy;
|
|
301
|
+
btn.textContent = busy ? label.busy : label.idle;
|
|
302
|
+
}
|
|
303
|
+
function finishSuccess() {
|
|
304
|
+
loginForm.classList.add('hidden');
|
|
305
|
+
otpForm.classList.add('hidden');
|
|
306
|
+
successEl.classList.remove('hidden');
|
|
307
|
+
setTimeout(() => { window.location.href = '/'; }, 1000);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
loginForm.addEventListener('submit', async (e) => {
|
|
311
|
+
e.preventDefault();
|
|
312
|
+
hideError(errorEl);
|
|
313
|
+
|
|
314
|
+
const tenantId = document.getElementById('tenantId').value;
|
|
315
|
+
const email = document.getElementById('email').value;
|
|
316
|
+
const password = document.getElementById('password').value;
|
|
317
|
+
|
|
318
|
+
setBusy(loginForm, true, { idle: 'Login', busy: 'Logging in...' });
|
|
319
|
+
|
|
320
|
+
try {
|
|
321
|
+
const res = await fetch(TOKEN_PATH, {
|
|
322
|
+
method: 'POST',
|
|
323
|
+
headers: {
|
|
324
|
+
'Content-Type': 'application/json',
|
|
325
|
+
'X-BSTAGE-TENANT-ID': tenantId,
|
|
326
|
+
},
|
|
327
|
+
credentials: 'include',
|
|
328
|
+
body: JSON.stringify({ email, password }),
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (!res.ok) {
|
|
332
|
+
const body = await res.json().catch(() => ({}));
|
|
333
|
+
throw new Error(body.message || 'Login failed (' + res.status + ')');
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const data = await res.json().catch(() => ({}));
|
|
337
|
+
|
|
338
|
+
// status === 'TWO_FACTOR_NEEDED' \uBA74 OTP \uB2E8\uACC4\uB85C \uC804\uD658.
|
|
339
|
+
// \uBC31\uC5D4\uB4DC\uAC00 \uC774 \uC751\uB2F5\uACFC \uD568\uAED8 OTP \uB97C \uC790\uB3D9 \uBC1C\uC1A1\uD55C\uB2E4.
|
|
340
|
+
if (data.status === 'TWO_FACTOR_NEEDED') {
|
|
341
|
+
pending = { tenantId, email, password };
|
|
342
|
+
loginForm.classList.add('hidden');
|
|
343
|
+
otpForm.classList.remove('hidden');
|
|
344
|
+
setBusy(loginForm, false, { idle: 'Login', busy: 'Logging in...' });
|
|
345
|
+
document.getElementById('otp').focus();
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
if (data.status === 'PASSWORD_RESET_NEEDED') {
|
|
350
|
+
throw new Error('\uBE44\uBC00\uBC88\uD638 \uC7AC\uC124\uC815\uC774 \uD544\uC694\uD55C \uACC4\uC815\uC785\uB2C8\uB2E4. \uC5B4\uB4DC\uBBFC \uC6F9\uC5D0\uC11C \uBA3C\uC800 \uBE44\uBC00\uBC88\uD638\uB97C \uAC31\uC2E0\uD574 \uC8FC\uC138\uC694.');
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
finishSuccess();
|
|
354
|
+
} catch (err) {
|
|
355
|
+
showError(errorEl, err.message);
|
|
356
|
+
setBusy(loginForm, false, { idle: 'Login', busy: 'Logging in...' });
|
|
357
|
+
}
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
otpForm.addEventListener('submit', async (e) => {
|
|
361
|
+
e.preventDefault();
|
|
362
|
+
hideError(otpErrorEl);
|
|
363
|
+
if (!pending) {
|
|
364
|
+
showError(otpErrorEl, '\uC138\uC158\uC774 \uB9CC\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB2E4\uC2DC \uB85C\uADF8\uC778\uD574 \uC8FC\uC138\uC694.');
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
367
|
+
const otp = document.getElementById('otp').value;
|
|
368
|
+
setBusy(otpForm, true, { idle: 'Verify', busy: 'Verifying...' });
|
|
369
|
+
|
|
370
|
+
try {
|
|
371
|
+
const res = await fetch(TWO_FACTOR_VERIFY_PATH, {
|
|
372
|
+
method: 'POST',
|
|
373
|
+
headers: {
|
|
374
|
+
'Content-Type': 'application/json',
|
|
375
|
+
'X-BSTAGE-TENANT-ID': pending.tenantId,
|
|
376
|
+
},
|
|
377
|
+
credentials: 'include',
|
|
378
|
+
body: JSON.stringify({
|
|
379
|
+
email: pending.email,
|
|
380
|
+
password: pending.password,
|
|
381
|
+
otp,
|
|
382
|
+
}),
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
if (!res.ok) {
|
|
386
|
+
const body = await res.json().catch(() => ({}));
|
|
387
|
+
throw new Error(body.message || 'OTP \uAC80\uC99D \uC2E4\uD328 (' + res.status + ')');
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
finishSuccess();
|
|
391
|
+
} catch (err) {
|
|
392
|
+
showError(otpErrorEl, err.message);
|
|
393
|
+
setBusy(otpForm, false, { idle: 'Verify', busy: 'Verifying...' });
|
|
394
|
+
}
|
|
395
|
+
});
|
|
396
|
+
|
|
397
|
+
otpBackBtn.addEventListener('click', () => {
|
|
398
|
+
pending = null;
|
|
399
|
+
otpForm.classList.add('hidden');
|
|
400
|
+
loginForm.classList.remove('hidden');
|
|
401
|
+
hideError(otpErrorEl);
|
|
402
|
+
document.getElementById('otp').value = '';
|
|
403
|
+
});
|
|
404
|
+
</script>
|
|
405
|
+
</body>
|
|
406
|
+
</html>`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
// src/dev/proxyUtils.ts
|
|
411
|
+
import { request as httpsRequest } from "https";
|
|
412
|
+
import { gunzipSync, brotliDecompressSync, inflateSync } from "zlib";
|
|
413
|
+
import { loadEnv } from "vite";
|
|
414
|
+
var CF_ACCESS_ENV_KEYS = ["VITE_CF_ACCESS_CLIENT_ID", "VITE_CF_ACCESS_CLIENT_SECRET"];
|
|
415
|
+
var cachedCreds;
|
|
416
|
+
var missingWarned = false;
|
|
417
|
+
function resolveCfAccessCreds() {
|
|
418
|
+
if (cachedCreds !== void 0) return cachedCreds;
|
|
419
|
+
const [idKey, secretKey] = CF_ACCESS_ENV_KEYS;
|
|
420
|
+
const fileEnv = loadEnv("development", process.cwd(), "");
|
|
421
|
+
const id = process.env[idKey] || fileEnv[idKey] || "";
|
|
422
|
+
const secret = process.env[secretKey] || fileEnv[secretKey] || "";
|
|
423
|
+
cachedCreds = id && secret ? { id, secret } : null;
|
|
424
|
+
return cachedCreds;
|
|
425
|
+
}
|
|
426
|
+
function stripCookieAttributes(cookie) {
|
|
427
|
+
return cookie.replace(/;\s*(Domain=[^;]*|HttpOnly|Secure|SameSite=[^;]*)/gi, "");
|
|
428
|
+
}
|
|
429
|
+
var CLOUDFLARE_COOKIE_RE = /^(CF_Authorization|__cf_bm|__cflb|cf_clearance)$/i;
|
|
430
|
+
function cookieName(pair) {
|
|
431
|
+
const i = pair.indexOf("=");
|
|
432
|
+
return (i >= 0 ? pair.slice(0, i) : pair).trim();
|
|
433
|
+
}
|
|
434
|
+
function decompressBody(raw, encoding) {
|
|
435
|
+
try {
|
|
436
|
+
if (encoding === "gzip") return gunzipSync(raw);
|
|
437
|
+
if (encoding === "br") return brotliDecompressSync(raw);
|
|
438
|
+
if (encoding === "deflate") return inflateSync(raw);
|
|
439
|
+
} catch {
|
|
440
|
+
}
|
|
441
|
+
return raw;
|
|
442
|
+
}
|
|
443
|
+
function proxyRequest(options) {
|
|
444
|
+
const headers = { ...options.headers };
|
|
445
|
+
for (const key of Object.keys(headers)) {
|
|
446
|
+
if (key.toLowerCase() === "accept-encoding") delete headers[key];
|
|
447
|
+
}
|
|
448
|
+
headers["accept-encoding"] = "gzip, deflate, br";
|
|
449
|
+
return new Promise((resolve2, reject) => {
|
|
450
|
+
const req = httpsRequest(
|
|
451
|
+
{
|
|
452
|
+
hostname: options.hostname,
|
|
453
|
+
port: 443,
|
|
454
|
+
path: options.path,
|
|
455
|
+
method: options.method,
|
|
456
|
+
headers,
|
|
457
|
+
timeout: options.timeout ?? 3e4
|
|
458
|
+
},
|
|
459
|
+
(res) => {
|
|
460
|
+
const chunks = [];
|
|
461
|
+
res.on("data", (c) => chunks.push(c));
|
|
462
|
+
res.on("end", () => {
|
|
463
|
+
const raw = Buffer.concat(chunks);
|
|
464
|
+
const encoding = res.headers["content-encoding"];
|
|
465
|
+
const body = decompressBody(raw, encoding);
|
|
466
|
+
const resHeaders = { ...res.headers };
|
|
467
|
+
delete resHeaders["content-encoding"];
|
|
468
|
+
delete resHeaders["content-length"];
|
|
469
|
+
delete resHeaders["transfer-encoding"];
|
|
470
|
+
resolve2({
|
|
471
|
+
statusCode: res.statusCode ?? 200,
|
|
472
|
+
headers: resHeaders,
|
|
473
|
+
body
|
|
474
|
+
});
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
);
|
|
478
|
+
req.on("timeout", () => {
|
|
479
|
+
req.destroy();
|
|
480
|
+
reject(
|
|
481
|
+
new Error(`Proxy request timeout: ${options.method} ${options.hostname}${options.path}`)
|
|
482
|
+
);
|
|
483
|
+
});
|
|
484
|
+
req.on("error", (err) => {
|
|
485
|
+
reject(new Error(`Proxy request failed: ${options.hostname}${options.path} \u2014 ${err.message}`));
|
|
486
|
+
});
|
|
487
|
+
req.end(options.body);
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
function addCfAccessHeaders(headers, phase) {
|
|
491
|
+
if (isPublicPhase(phase)) return;
|
|
492
|
+
const creds = resolveCfAccessCreds();
|
|
493
|
+
if (!creds) {
|
|
494
|
+
if (!missingWarned) {
|
|
495
|
+
missingWarned = true;
|
|
496
|
+
const [idKey, secretKey] = CF_ACCESS_ENV_KEYS;
|
|
497
|
+
console.warn(
|
|
498
|
+
`[bstage] ${phase}\uB294 \uC0AC\uB0B4 \uC804\uC6A9 \uD658\uACBD\uC774\uB77C Cloudflare Access \uAC8C\uC774\uD2B8 \uB4A4\uC5D0 \uC788\uC2B5\uB2C8\uB2E4.
|
|
499
|
+
\uC790\uACA9\uC99D\uBA85\uC774 \uC5C6\uC5B4 \uB85C\uADF8\uC778\xB7API \uD504\uB85D\uC2DC\uAC00 302(Cloudflare \uB85C\uADF8\uC778)\uB85C \uB9C9\uD799\uB2C8\uB2E4.
|
|
500
|
+
\xB7 \uC0AC\uB0B4: CF Access \uC11C\uBE44\uC2A4 \uD1A0\uD070\uC744 \uBC1C\uAE09\uBC1B\uC544 .env\uC5D0 ${idKey}\xB7${secretKey} \uC124\uC815
|
|
501
|
+
\xB7 \uADF8 \uC678: --phase sandbox \uB85C \uAC1C\uBC1C\uD558\uC138\uC694 (\uAC8C\uC774\uD2B8\uAC00 \uC5C6\uC5B4 \uC124\uC815\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4)`
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
headers["CF-Access-Client-Id"] = creds.id;
|
|
507
|
+
headers["CF-Access-Client-Secret"] = creds.secret;
|
|
508
|
+
}
|
|
509
|
+
function stripResponseCookies(headers, extraCookies) {
|
|
510
|
+
const cookies = (headers["set-cookie"] ?? []).filter((c) => !CLOUDFLARE_COOKIE_RE.test(cookieName(c))).map(stripCookieAttributes);
|
|
511
|
+
if (extraCookies) cookies.push(...extraCookies);
|
|
512
|
+
if (cookies.length) {
|
|
513
|
+
headers["set-cookie"] = cookies;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function collectBody(req) {
|
|
517
|
+
return new Promise((resolve2) => {
|
|
518
|
+
const chunks = [];
|
|
519
|
+
req.on("data", (c) => chunks.push(c));
|
|
520
|
+
req.on("end", () => resolve2(Buffer.concat(chunks)));
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
// src/dev/resolveHosts.ts
|
|
525
|
+
import { loadEnv as loadEnv2 } from "vite";
|
|
526
|
+
var HOST_ENV_KEYS = {
|
|
527
|
+
gateway: "VITE_BSTAGE_GATEWAY_HOST",
|
|
528
|
+
auth: "VITE_BSTAGE_AUTH_HOST",
|
|
529
|
+
adminAuth: "VITE_BSTAGE_ADMIN_AUTH_HOST"
|
|
530
|
+
};
|
|
531
|
+
function authKeyFor(mode) {
|
|
532
|
+
return mode === "admin" ? HOST_ENV_KEYS.adminAuth : HOST_ENV_KEYS.auth;
|
|
533
|
+
}
|
|
534
|
+
function resolveDevHosts(phase, mode, cwd = process.cwd()) {
|
|
535
|
+
if (isPublicPhase(phase)) {
|
|
536
|
+
const gatewayFn = GATEWAY_HOSTS[phase];
|
|
537
|
+
return {
|
|
538
|
+
gateway: (tenantId) => gatewayFn(tenantId),
|
|
539
|
+
auth: (tenantId) => getAuthHost(mode, phase, tenantId)
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
const fileEnv = loadEnv2("development", cwd, "");
|
|
543
|
+
const read = (key) => (process.env[key] || fileEnv[key] || "").trim();
|
|
544
|
+
const authKey = authKeyFor(mode);
|
|
545
|
+
const gatewayHost = read(HOST_ENV_KEYS.gateway);
|
|
546
|
+
const authHost = read(authKey);
|
|
547
|
+
const missing = [];
|
|
548
|
+
if (!gatewayHost) missing.push(HOST_ENV_KEYS.gateway);
|
|
549
|
+
if (!authHost) missing.push(authKey);
|
|
550
|
+
if (missing.length > 0) {
|
|
551
|
+
throw new Error(
|
|
552
|
+
`${phase}\uB294 \uC0AC\uB0B4 \uC804\uC6A9 \uD658\uACBD\uC774\uB77C \uD638\uC2A4\uD2B8\uAC00 SDK\uC5D0 \uB4E4\uC5B4 \uC788\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4.
|
|
553
|
+
\uC124\uC815\uB418\uC9C0 \uC54A\uC740 \uAC12: ${missing.join(", ")}
|
|
554
|
+
\xB7 \uC0AC\uB0B4: \uC704 \uAC12\uC744 .env\uC5D0 \uC124\uC815\uD558\uC138\uC694 (\uD638\uC2A4\uD2B8 \uAC12\uC740 \uC0AC\uB0B4 \uBB38\uC11C\uB97C \uCC38\uACE0\uD558\uC138\uC694)
|
|
555
|
+
\xB7 \uADF8 \uC678: --phase sandbox \uB85C \uAC1C\uBC1C\uD558\uC138\uC694 (\uC124\uC815\uC774 \uD544\uC694 \uC5C6\uC2B5\uB2C8\uB2E4)`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
return {
|
|
559
|
+
gateway: () => gatewayHost,
|
|
560
|
+
auth: () => authHost
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// src/dev/resolvePhase.ts
|
|
565
|
+
import { loadEnv as loadEnv3 } from "vite";
|
|
566
|
+
var PHASES = ["dev", "qa", "real", "sandbox"];
|
|
567
|
+
var DEFAULT_PHASE = "sandbox";
|
|
568
|
+
function isPhase(value) {
|
|
569
|
+
return PHASES.includes(value);
|
|
570
|
+
}
|
|
571
|
+
function resolvePhase(explicit, cwd = process.cwd()) {
|
|
572
|
+
if (explicit) {
|
|
573
|
+
if (!isPhase(explicit)) {
|
|
574
|
+
throw new Error(
|
|
575
|
+
`--phase \uAC12\uC740 ${PHASES.join(" | ")} \uC911 \uD558\uB098\uC5EC\uC57C \uD569\uB2C8\uB2E4. (\uBC1B\uC740 \uAC12: ${explicit})`
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
return { phase: explicit, source: "flag" };
|
|
579
|
+
}
|
|
580
|
+
const fileEnv = loadEnv3("development", cwd, "");
|
|
581
|
+
const fromEnv = process.env.VITE_BSTAGE_PHASE || fileEnv.VITE_BSTAGE_PHASE || "";
|
|
582
|
+
if (fromEnv) {
|
|
583
|
+
if (isPhase(fromEnv)) return { phase: fromEnv, source: "env" };
|
|
584
|
+
return { phase: DEFAULT_PHASE, source: "default", ignoredEnvValue: fromEnv };
|
|
585
|
+
}
|
|
586
|
+
return { phase: DEFAULT_PHASE, source: "default" };
|
|
587
|
+
}
|
|
588
|
+
function describePhase({ phase, source, ignoredEnvValue }) {
|
|
589
|
+
if (ignoredEnvValue) {
|
|
590
|
+
return `[bstage] VITE_BSTAGE_PHASE \uAC12 "${ignoredEnvValue}"\uC744(\uB97C) \uC54C \uC218 \uC5C6\uC5B4 \uBB34\uC2DC\uD588\uC2B5\uB2C8\uB2E4. phase: ${phase} (\uAE30\uBCF8\uAC12)`;
|
|
591
|
+
}
|
|
592
|
+
const label = source === "flag" ? "--phase" : source === "env" ? ".env\uC758 VITE_BSTAGE_PHASE" : "\uAE30\uBCF8\uAC12";
|
|
593
|
+
return `[bstage] phase: ${phase} (${label})`;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
// ../design/dist/user/index.js
|
|
597
|
+
var modeColors = {
|
|
598
|
+
"bg/base": {
|
|
599
|
+
"dark": "#151515",
|
|
600
|
+
"light": "#ffffff"
|
|
601
|
+
},
|
|
602
|
+
"bg/blue-grey": {
|
|
603
|
+
"dark": "#1f2023",
|
|
604
|
+
"light": "#eff1f7"
|
|
605
|
+
},
|
|
606
|
+
"bg/elevated": {
|
|
607
|
+
"dark": "#232323",
|
|
608
|
+
"light": "#ffffff"
|
|
609
|
+
},
|
|
610
|
+
"bg/grouped-strong": {
|
|
611
|
+
"dark": "#000000",
|
|
612
|
+
"light": "#f7f7f7"
|
|
613
|
+
},
|
|
614
|
+
"bg/grouped-weak": {
|
|
615
|
+
"dark": "#111111",
|
|
616
|
+
"light": "#f7f7f7"
|
|
617
|
+
},
|
|
618
|
+
"bg/grouped-weak-a": {
|
|
619
|
+
"dark": "#ffffff0f",
|
|
620
|
+
"light": "#0000000f"
|
|
621
|
+
},
|
|
622
|
+
"bg/highlight": {
|
|
623
|
+
"dark": "#2f2f2f",
|
|
624
|
+
"light": "#e6e6e6"
|
|
625
|
+
},
|
|
626
|
+
"bg/invert-weak-a": {
|
|
627
|
+
"dark": "#00000026",
|
|
628
|
+
"light": "#ffffff26"
|
|
629
|
+
},
|
|
630
|
+
"border/blue": {
|
|
631
|
+
"dark": "#0090ff",
|
|
632
|
+
"light": "#148aff"
|
|
633
|
+
},
|
|
634
|
+
"border/blue-weak-a": {
|
|
635
|
+
"dark": "#0090ff4d",
|
|
636
|
+
"light": "#148aff4d"
|
|
637
|
+
},
|
|
638
|
+
"border/default-a": {
|
|
639
|
+
"dark": "#ffffff1a",
|
|
640
|
+
"light": "#0000001a"
|
|
641
|
+
},
|
|
642
|
+
"border/divider-weaker": {
|
|
643
|
+
"dark": "#0d0d0d",
|
|
644
|
+
"light": "#f7f7f7"
|
|
645
|
+
},
|
|
646
|
+
"border/green": {
|
|
647
|
+
"dark": "#0be06f",
|
|
648
|
+
"light": "#00b84d"
|
|
649
|
+
},
|
|
650
|
+
"border/green-weak-a": {
|
|
651
|
+
"dark": "#0be06f4d",
|
|
652
|
+
"light": "#00b84d4d"
|
|
653
|
+
},
|
|
654
|
+
"border/grey": {
|
|
655
|
+
"dark": "#b3b3b3",
|
|
656
|
+
"light": "#7a7a7a"
|
|
657
|
+
},
|
|
658
|
+
"border/grey-weak-a": {
|
|
659
|
+
"dark": "#b3b3b34d",
|
|
660
|
+
"light": "#7a7a7a4d"
|
|
661
|
+
},
|
|
662
|
+
"border/invert": {
|
|
663
|
+
"dark": "#0d0d0d",
|
|
664
|
+
"light": "#ffffff"
|
|
665
|
+
},
|
|
666
|
+
"border/red": {
|
|
667
|
+
"dark": "#ff4747",
|
|
668
|
+
"light": "#ff4a40"
|
|
669
|
+
},
|
|
670
|
+
"border/red-weak-a": {
|
|
671
|
+
"dark": "#ff47474d",
|
|
672
|
+
"light": "#ff4a404d"
|
|
673
|
+
},
|
|
674
|
+
"border/strong-a": {
|
|
675
|
+
"dark": "#ffffff33",
|
|
676
|
+
"light": "#00000033"
|
|
677
|
+
},
|
|
678
|
+
"border/stronger": {
|
|
679
|
+
"dark": "#eeeeee",
|
|
680
|
+
"light": "#454545"
|
|
681
|
+
},
|
|
682
|
+
"border/weak-a": {
|
|
683
|
+
"dark": "#ffffff0a",
|
|
684
|
+
"light": "#0000000f"
|
|
685
|
+
},
|
|
686
|
+
"border/yellow": {
|
|
687
|
+
"dark": "#f5b625",
|
|
688
|
+
"light": "#f29900"
|
|
689
|
+
},
|
|
690
|
+
"border/yellow-weak-a": {
|
|
691
|
+
"dark": "#f5b6254d",
|
|
692
|
+
"light": "#f299004d"
|
|
693
|
+
},
|
|
694
|
+
"icon/blue": {
|
|
695
|
+
"dark": "#0090ff",
|
|
696
|
+
"light": "#148aff"
|
|
697
|
+
},
|
|
698
|
+
"icon/green": {
|
|
699
|
+
"dark": "#0be06f",
|
|
700
|
+
"light": "#00b84d"
|
|
701
|
+
},
|
|
702
|
+
"icon/grey": {
|
|
703
|
+
"dark": "#b3b3b3",
|
|
704
|
+
"light": "#7a7a7a"
|
|
705
|
+
},
|
|
706
|
+
"icon/invert": {
|
|
707
|
+
"dark": "#0d0d0d",
|
|
708
|
+
"light": "#ffffff"
|
|
709
|
+
},
|
|
710
|
+
"icon/primary": {
|
|
711
|
+
"dark": "#ffffff",
|
|
712
|
+
"light": "#000000"
|
|
713
|
+
},
|
|
714
|
+
"icon/quaternary-a": {
|
|
715
|
+
"dark": "#ffffff4d",
|
|
716
|
+
"light": "#0000004d"
|
|
717
|
+
},
|
|
718
|
+
"icon/red": {
|
|
719
|
+
"dark": "#ff4747",
|
|
720
|
+
"light": "#ff4a40"
|
|
721
|
+
},
|
|
722
|
+
"icon/secondary-a": {
|
|
723
|
+
"dark": "#ffffffba",
|
|
724
|
+
"light": "#000000ba"
|
|
725
|
+
},
|
|
726
|
+
"icon/tertiary-a": {
|
|
727
|
+
"dark": "#ffffff80",
|
|
728
|
+
"light": "#00000080"
|
|
729
|
+
},
|
|
730
|
+
"icon/yellow": {
|
|
731
|
+
"dark": "#f5b625",
|
|
732
|
+
"light": "#f29900"
|
|
733
|
+
},
|
|
734
|
+
"overlay/hover-a": {
|
|
735
|
+
"dark": "#ffffff14",
|
|
736
|
+
"light": "#0000001a"
|
|
737
|
+
},
|
|
738
|
+
"overlay/hover-grey-a": {
|
|
739
|
+
"dark": "#4545451a",
|
|
740
|
+
"light": "#4545451a"
|
|
741
|
+
},
|
|
742
|
+
"overlay/press-a": {
|
|
743
|
+
"dark": "#ffffff33",
|
|
744
|
+
"light": "#00000026"
|
|
745
|
+
},
|
|
746
|
+
"overlay/press-grey-a": {
|
|
747
|
+
"dark": "#45454526",
|
|
748
|
+
"light": "#45454526"
|
|
749
|
+
},
|
|
750
|
+
"service/live": {
|
|
751
|
+
"dark": "#e51a42",
|
|
752
|
+
"light": "#e2012d"
|
|
753
|
+
},
|
|
754
|
+
"service/live-weak-a": {
|
|
755
|
+
"dark": "#e51a4226",
|
|
756
|
+
"light": "#e2012d4d"
|
|
757
|
+
},
|
|
758
|
+
"service/membership": {
|
|
759
|
+
"dark": "#ffbf00",
|
|
760
|
+
"light": "#ffb010"
|
|
761
|
+
},
|
|
762
|
+
"service/membership-weak-a": {
|
|
763
|
+
"dark": "#ffbf001f",
|
|
764
|
+
"light": "#eb91001f"
|
|
765
|
+
},
|
|
766
|
+
"service/noti": {
|
|
767
|
+
"dark": "#0c198b",
|
|
768
|
+
"light": "#020f81"
|
|
769
|
+
},
|
|
770
|
+
"service/pop-bg": {
|
|
771
|
+
"dark": "linear-gradient(135deg, #3b3a2d 13.08%, #232732 87.56%)",
|
|
772
|
+
"light": "linear-gradient(135deg, #faf7de 13.08%, #e7edfd 87.56%)"
|
|
773
|
+
},
|
|
774
|
+
"surface/card": {
|
|
775
|
+
"dark": "#232323",
|
|
776
|
+
"light": "#ffffff"
|
|
777
|
+
},
|
|
778
|
+
"surface/display-bar-bottom": {
|
|
779
|
+
"dark": "#151515",
|
|
780
|
+
"light": "#fdfdfd"
|
|
781
|
+
},
|
|
782
|
+
"surface/display-bar-top": {
|
|
783
|
+
"dark": "#151515",
|
|
784
|
+
"light": "#ffffff"
|
|
785
|
+
},
|
|
786
|
+
"surface/display-lock": {
|
|
787
|
+
"dark": "#2f2f2f",
|
|
788
|
+
"light": "#bfbfbf"
|
|
789
|
+
},
|
|
790
|
+
"surface/form-blue": {
|
|
791
|
+
"dark": "#0090ff",
|
|
792
|
+
"light": "#148aff"
|
|
793
|
+
},
|
|
794
|
+
"surface/form-blue-weak-a": {
|
|
795
|
+
"dark": "#0f97ff1f",
|
|
796
|
+
"light": "#007aff26"
|
|
797
|
+
},
|
|
798
|
+
"surface/form-gradient-h": {
|
|
799
|
+
"dark": "linear-gradient(90deg, #151515 0%, #15151500 100%)",
|
|
800
|
+
"light": "linear-gradient(90deg, #ffffff 0%, #ffffff00 100%)"
|
|
801
|
+
},
|
|
802
|
+
"surface/form-green": {
|
|
803
|
+
"dark": "#00cc5f",
|
|
804
|
+
"light": "#00bf59"
|
|
805
|
+
},
|
|
806
|
+
"surface/form-green-weak-a": {
|
|
807
|
+
"dark": "#0be06f14",
|
|
808
|
+
"light": "#00b84d26"
|
|
809
|
+
},
|
|
810
|
+
"surface/form-grey": {
|
|
811
|
+
"dark": "#7a7a7a",
|
|
812
|
+
"light": "#999999"
|
|
813
|
+
},
|
|
814
|
+
"surface/form-grey-weak-a": {
|
|
815
|
+
"dark": "#b3b3b314",
|
|
816
|
+
"light": "#6666661f"
|
|
817
|
+
},
|
|
818
|
+
"surface/form-inverted": {
|
|
819
|
+
"dark": "#f7f7f7",
|
|
820
|
+
"light": "#151515"
|
|
821
|
+
},
|
|
822
|
+
"surface/form-inverted-deep": {
|
|
823
|
+
"dark": "#ffffff",
|
|
824
|
+
"light": "#000000"
|
|
825
|
+
},
|
|
826
|
+
"surface/form-primary-a": {
|
|
827
|
+
"dark": "#ffffff0f",
|
|
828
|
+
"light": "#0000000f"
|
|
829
|
+
},
|
|
830
|
+
"surface/form-red": {
|
|
831
|
+
"dark": "#ff4747",
|
|
832
|
+
"light": "#ff4a40"
|
|
833
|
+
},
|
|
834
|
+
"surface/form-red-weak-a": {
|
|
835
|
+
"dark": "#ff47471f",
|
|
836
|
+
"light": "#ff4a4026"
|
|
837
|
+
},
|
|
838
|
+
"surface/form-secondary-a": {
|
|
839
|
+
"dark": "#ffffff0a",
|
|
840
|
+
"light": "#0000000a"
|
|
841
|
+
},
|
|
842
|
+
"surface/form-yellow": {
|
|
843
|
+
"dark": "#f5b625",
|
|
844
|
+
"light": "#f29900"
|
|
845
|
+
},
|
|
846
|
+
"surface/form-yellow-weak-a": {
|
|
847
|
+
"dark": "#f5b62514",
|
|
848
|
+
"light": "#f299001f"
|
|
849
|
+
},
|
|
850
|
+
"text/blue": {
|
|
851
|
+
"dark": "#0090ff",
|
|
852
|
+
"light": "#148aff"
|
|
853
|
+
},
|
|
854
|
+
"text/green": {
|
|
855
|
+
"dark": "#0be06f",
|
|
856
|
+
"light": "#00b84d"
|
|
857
|
+
},
|
|
858
|
+
"text/grey": {
|
|
859
|
+
"dark": "#b3b3b3",
|
|
860
|
+
"light": "#666666"
|
|
861
|
+
},
|
|
862
|
+
"text/invert-a": {
|
|
863
|
+
"dark": "#000000ed",
|
|
864
|
+
"light": "#ffffffed"
|
|
865
|
+
},
|
|
866
|
+
"text/primary": {
|
|
867
|
+
"dark": "#eeeeee",
|
|
868
|
+
"light": "#151515"
|
|
869
|
+
},
|
|
870
|
+
"text/primary-a": {
|
|
871
|
+
"dark": "#ffffffed",
|
|
872
|
+
"light": "#000000ed"
|
|
873
|
+
},
|
|
874
|
+
"text/quaternary": {
|
|
875
|
+
"dark": "#777777",
|
|
876
|
+
"light": "#999999"
|
|
877
|
+
},
|
|
878
|
+
"text/quaternary-a": {
|
|
879
|
+
"dark": "#ffffff80",
|
|
880
|
+
"light": "#00000080"
|
|
881
|
+
},
|
|
882
|
+
"text/red": {
|
|
883
|
+
"dark": "#ff4747",
|
|
884
|
+
"light": "#ff4a40"
|
|
885
|
+
},
|
|
886
|
+
"text/secondary": {
|
|
887
|
+
"dark": "#bababa",
|
|
888
|
+
"light": "#454545"
|
|
889
|
+
},
|
|
890
|
+
"text/secondary-a": {
|
|
891
|
+
"dark": "#ffffffba",
|
|
892
|
+
"light": "#000000ba"
|
|
893
|
+
},
|
|
894
|
+
"text/tertiary": {
|
|
895
|
+
"dark": "#999999",
|
|
896
|
+
"light": "#666666"
|
|
897
|
+
},
|
|
898
|
+
"text/tertiary-a": {
|
|
899
|
+
"dark": "#ffffff99",
|
|
900
|
+
"light": "#00000099"
|
|
901
|
+
},
|
|
902
|
+
"text/yellow": {
|
|
903
|
+
"dark": "#f5b625",
|
|
904
|
+
"light": "#f29900"
|
|
905
|
+
}
|
|
906
|
+
};
|
|
907
|
+
var flatColors = {
|
|
908
|
+
"always/avatar-bg01": "#aa47bc",
|
|
909
|
+
"always/avatar-bg02": "#7a1fa2",
|
|
910
|
+
"always/avatar-bg03": "#7e57c2",
|
|
911
|
+
"always/avatar-bg04": "#512da7",
|
|
912
|
+
"always/avatar-bg05": "#5c6bc0",
|
|
913
|
+
"always/avatar-bg06": "#0288d1",
|
|
914
|
+
"always/avatar-bg07": "#00579c",
|
|
915
|
+
"always/avatar-bg08": "#0098a6",
|
|
916
|
+
"always/avatar-bg09": "#00887a",
|
|
917
|
+
"always/avatar-bg10": "#689f39",
|
|
918
|
+
"always/avatar-bg11": "#33691e",
|
|
919
|
+
"always/avatar-bg12": "#004c3f",
|
|
920
|
+
"always/avatar-bg13": "#ec407a",
|
|
921
|
+
"always/avatar-bg14": "#c2175b",
|
|
922
|
+
"always/avatar-bg15": "#bf360c",
|
|
923
|
+
"always/avatar-bg16": "#f5511e",
|
|
924
|
+
"always/avatar-bg17": "#ef6c00",
|
|
925
|
+
"always/avatar-bg18": "#8c6e63",
|
|
926
|
+
"always/avatar-bg19": "#5d4038",
|
|
927
|
+
"always/avatar-bg20": "#78909c",
|
|
928
|
+
"always/avatar-bg21": "#465a65",
|
|
929
|
+
"always/black006-a": "#0000000f",
|
|
930
|
+
"always/black010-a": "#0000001a",
|
|
931
|
+
"always/black015-a": "#00000026",
|
|
932
|
+
"always/black020-a": "#00000033",
|
|
933
|
+
"always/black030-a": "#0000004d",
|
|
934
|
+
"always/black050-a": "#00000080",
|
|
935
|
+
"always/black060-a": "#00000099",
|
|
936
|
+
"always/black080-a": "#000000cc",
|
|
937
|
+
"always/black100": "#000000",
|
|
938
|
+
"always/grey-strong": "#232323",
|
|
939
|
+
"always/grey085": "#5c5c5c",
|
|
940
|
+
"always/lightgrey006-a": "#9999990f",
|
|
941
|
+
"always/lightgrey010-a": "#9999991a",
|
|
942
|
+
"always/lightgrey015-a": "#99999926",
|
|
943
|
+
"always/lightgrey020-a": "#99999933",
|
|
944
|
+
"always/lightgrey030-a": "#9999994d",
|
|
945
|
+
"always/lightgrey050-a": "#99999980",
|
|
946
|
+
"always/lightgrey080-a": "#999999cc",
|
|
947
|
+
"always/lightgrey100": "#999999",
|
|
948
|
+
"always/palette05": "linear-gradient(135deg, #db2667 0%, #f4a368 100%)",
|
|
949
|
+
"always/service-live-pop": "#df3868",
|
|
950
|
+
"always/service-live-red": "#ff0000",
|
|
951
|
+
"always/service-mnet": "#ff477f",
|
|
952
|
+
"always/service-mnetapp": "#ff477f",
|
|
953
|
+
"always/service-point": "linear-gradient(135deg, #1cac3c 0%, #1ca6bb 100%)",
|
|
954
|
+
"always/service-pop-ing": "linear-gradient(135deg, #db2667 0%, #f4a368 100%)",
|
|
955
|
+
"always/service-popgrey-weak-a": "#707ca00f",
|
|
956
|
+
"always/service-post-thumb-a": "#aa89f5cc",
|
|
957
|
+
"always/service-rankingpoll-thumb-a": "#FFADDD80",
|
|
958
|
+
"always/service-red080-a": "#f5254acc",
|
|
959
|
+
"always/service-survey": "#597eff",
|
|
960
|
+
"always/service-survey-thumb-a": "#7192f5cc",
|
|
961
|
+
"always/service-ticket": "#00bf59",
|
|
962
|
+
"always/white006-a": "#ffffff0f",
|
|
963
|
+
"always/white010-a": "#ffffff1a",
|
|
964
|
+
"always/white015-a": "#ffffff26",
|
|
965
|
+
"always/white020-a": "#ffffff33",
|
|
966
|
+
"always/white030-a": "#ffffff4d",
|
|
967
|
+
"always/white050-a": "#ffffff80",
|
|
968
|
+
"always/white060-a": "#ffffff99",
|
|
969
|
+
"always/white080-a": "#ffffffcc",
|
|
970
|
+
"always/white100": "#ffffff",
|
|
971
|
+
"auto/icon-primary-on-dark": "#ffffff",
|
|
972
|
+
"auto/icon-primary-on-light": "#000000ed",
|
|
973
|
+
"auto/icon-secondary-on-dark": "#ffffff",
|
|
974
|
+
"auto/icon-secondary-on-light": "#000000ba",
|
|
975
|
+
"auto/text-primary-on-dark": "#ffffff",
|
|
976
|
+
"auto/text-primary-on-light": "#000000",
|
|
977
|
+
"auto/text-secondary-on-dark": "#ffffffcc",
|
|
978
|
+
"auto/text-secondary-on-light": "#000000cc",
|
|
979
|
+
"picker/button": "#654bff",
|
|
980
|
+
"picker/button-weak-a": "#654bff26",
|
|
981
|
+
"picker/on-button": "#ffffff",
|
|
982
|
+
"picker/star": "#7266ff",
|
|
983
|
+
"pop/bg-tl01": "#c9d0ea",
|
|
984
|
+
"pop/bg-tl02": "#f2de6f",
|
|
985
|
+
"pop/bg-tl03": "#fca783",
|
|
986
|
+
"pop/bg-tl04": "#a0dda6",
|
|
987
|
+
"pop/bg-tl05": "#a2bce3",
|
|
988
|
+
"pop/bg-tl06": "#f7b3cf",
|
|
989
|
+
"pop/bg-tl07": "#bfa2e3",
|
|
990
|
+
"pop/bg-tl08": "#fb8686",
|
|
991
|
+
"pop/bg-tl09": "#eec2c2",
|
|
992
|
+
"pop/bg-tl10": "#e2d1b0",
|
|
993
|
+
"pop/bubble-tl01": "#7984b1",
|
|
994
|
+
"pop/bubble-tl03": "#e3703f",
|
|
995
|
+
"pop/bubble-tl04": "#5fac70",
|
|
996
|
+
"pop/bubble-tl05": "#587ab1",
|
|
997
|
+
"pop/bubble-tl06": "#ca7094",
|
|
998
|
+
"pop/bubble-tl07": "#8067b5",
|
|
999
|
+
"pop/bubble-tl08": "#cb4e4e",
|
|
1000
|
+
"pop/bubble-tl09": "#cb8181",
|
|
1001
|
+
"pop/bubble-tl1": "#a79272",
|
|
1002
|
+
"pop/item-gradient01": "linear-gradient(135deg, #fbf3ac 0%, #ffe1fc 100%)",
|
|
1003
|
+
"pop/item-gradient02": "linear-gradient(135deg, #cbe6ff 0%, #d5ffdf 100%)",
|
|
1004
|
+
"pop/item-gradient03": "linear-gradient(135deg, #e4ceff 0%, #ffe4cc 100%)",
|
|
1005
|
+
"pop/item-gradient04": "linear-gradient(135deg, #ffdcb3 0%, #c9f8ff 100%)",
|
|
1006
|
+
"pop/item-gradient05": "linear-gradient(135deg, #ffd0ec 0%, #d3fcff 100%)",
|
|
1007
|
+
"pop/item-gradient06": "linear-gradient(135deg, #feb5b5 0%, #d6fee1 100%)"
|
|
1008
|
+
};
|
|
1009
|
+
var shadowTokens = {
|
|
1010
|
+
"shadow/default-large": {
|
|
1011
|
+
"dark": "0px 1px 2px 0px #00000033, 0px 8px 48px 0px #00000099",
|
|
1012
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 8px 48px 0px #1a1a1a26"
|
|
1013
|
+
},
|
|
1014
|
+
"shadow/default-medium": {
|
|
1015
|
+
"dark": "0px 1px 2px 0px #00000033, 0px 4px 24px 0px #00000066",
|
|
1016
|
+
"light": "0px 1px 2px 0px #00000005, 0px 4px 24px 0px #1a1a1a1a"
|
|
1017
|
+
},
|
|
1018
|
+
"shadow/default-small": {
|
|
1019
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 2px 8px 0px #00000066",
|
|
1020
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 2px 8px 0px #1a1a1a1a"
|
|
1021
|
+
},
|
|
1022
|
+
"shadow/default-xlarge": {
|
|
1023
|
+
"dark": "0px 1px 2px 0px #00000033, 0px 16px 72px 0px #00000099",
|
|
1024
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 16px 72px 0px #1a1a1a26"
|
|
1025
|
+
},
|
|
1026
|
+
"shadow/default-xsmall": {
|
|
1027
|
+
"dark": "0px 1px 2px 0px #00000033, 0px 0px 4px 0px #00000066",
|
|
1028
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 0px 4px 0px #1a1a1a26"
|
|
1029
|
+
},
|
|
1030
|
+
"shadow/weak-large": {
|
|
1031
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 8px 48px 0px #00000066",
|
|
1032
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 8px 48px 0px #1a1a1a1f"
|
|
1033
|
+
},
|
|
1034
|
+
"shadow/weak-medium": {
|
|
1035
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 4px 24px 0px #00000033",
|
|
1036
|
+
"light": "0px 1px 2px 0px #00000005, 0px 4px 20px 0px #1a1a1a14"
|
|
1037
|
+
},
|
|
1038
|
+
"shadow/weak-small": {
|
|
1039
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 2px 8px 0px #00000033",
|
|
1040
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 2px 8px 0px #1a1a1a14"
|
|
1041
|
+
},
|
|
1042
|
+
"shadow/weak-xlarge": {
|
|
1043
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 16px 72px 0px #00000066",
|
|
1044
|
+
"light": "0px 1px 2px 0px #1a1a1a05, 0px 16px 72px 0px #1a1a1a1f"
|
|
1045
|
+
},
|
|
1046
|
+
"shadow/weak-xsmall": {
|
|
1047
|
+
"dark": "0px 1px 2px 0px #0000001a, 0px 0px 4px 0px #00000033",
|
|
1048
|
+
"light": "0px 1px 1px 0px #1a1a1a05, 0px 0px 4px 0px #1a1a1a14"
|
|
1049
|
+
}
|
|
1050
|
+
};
|
|
1051
|
+
var fontFamily = "'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'";
|
|
1052
|
+
function cssVarName(slug, prefix, kind) {
|
|
1053
|
+
const s = slug.replace(/\//g, "-");
|
|
1054
|
+
return kind === "mode" ? `--${prefix}-mode-${s}` : `--${prefix}-${s}`;
|
|
1055
|
+
}
|
|
1056
|
+
function cssVarRef(slug, prefix, kind) {
|
|
1057
|
+
return `var(${cssVarName(slug, prefix, kind)})`;
|
|
1058
|
+
}
|
|
1059
|
+
function buildColorTree(modeColors22, flatColors22, prefix) {
|
|
1060
|
+
const tree = {};
|
|
1061
|
+
const add = (slug, kind) => {
|
|
1062
|
+
const [cat, ...rest] = slug.split("/");
|
|
1063
|
+
const leaf = rest.join("/").replace(/\//g, "-") || cat;
|
|
1064
|
+
(tree[cat] ?? (tree[cat] = {}))[leaf] = cssVarRef(slug, prefix, kind);
|
|
1065
|
+
};
|
|
1066
|
+
for (const slug of Object.keys(modeColors22)) add(slug, "mode");
|
|
1067
|
+
for (const slug of Object.keys(flatColors22)) add(slug, "flat");
|
|
1068
|
+
return tree;
|
|
1069
|
+
}
|
|
1070
|
+
function buildShadowRefs(shadowTokens22, prefix) {
|
|
1071
|
+
const out = {};
|
|
1072
|
+
for (const slug of Object.keys(shadowTokens22)) {
|
|
1073
|
+
const leaf = slug.replace(/^shadow\//, "");
|
|
1074
|
+
out[leaf] = cssVarRef(slug, prefix, "mode");
|
|
1075
|
+
}
|
|
1076
|
+
return out;
|
|
1077
|
+
}
|
|
1078
|
+
function colorLines(t, prefix, mode) {
|
|
1079
|
+
return [
|
|
1080
|
+
...Object.entries(t.modeColors).map(
|
|
1081
|
+
([slug, pair]) => ` ${cssVarName(slug, prefix, "mode")}: ${pair[mode]};`
|
|
1082
|
+
),
|
|
1083
|
+
...Object.entries(t.shadowTokens).map(
|
|
1084
|
+
([slug, pair]) => ` ${cssVarName(slug, prefix, "mode")}: ${pair[mode]};`
|
|
1085
|
+
)
|
|
1086
|
+
].join("\n");
|
|
1087
|
+
}
|
|
1088
|
+
function renderFallbackCss(t, opts) {
|
|
1089
|
+
const p = opts.prefix;
|
|
1090
|
+
const flat = Object.entries(t.flatColors).map(([slug, v]) => ` ${cssVarName(slug, p, "flat")}: ${v};`).join("\n");
|
|
1091
|
+
const lightColors = colorLines(t, p, "light");
|
|
1092
|
+
let css = `/* ================================================================
|
|
1093
|
+
* bstage \uB514\uC790\uC778 \uD1A0\uD070 \u2014 dev fallback (${p})
|
|
1094
|
+
* @bstage-sdk/design \uC0DD\uC131\uBB3C. \uAC1C\uBC1C/\uBBF8\uB9AC\uBCF4\uAE30 \uC804\uC6A9(:root fallback).
|
|
1095
|
+
* \uBC30\uD3EC \uC2DC\uC5D4 \uD50C\uB7AB\uD3FC :root \uAC12\uC744 \uC0C1\uC18D\uD558\uBA70 \uC774 \uD30C\uC77C\uC740 \uBC88\uB4E4\uB418\uC9C0 \uC54A\uB294\uB2E4.
|
|
1096
|
+
* ================================================================ */
|
|
1097
|
+
|
|
1098
|
+
:root {
|
|
1099
|
+
${lightColors}
|
|
1100
|
+
|
|
1101
|
+
${flat}
|
|
1102
|
+
|
|
1103
|
+
--${p}-font-family: ${t.fontFamily};
|
|
1104
|
+
}
|
|
1105
|
+
`;
|
|
1106
|
+
if (opts.dark) {
|
|
1107
|
+
const darkColors = colorLines(t, p, "dark");
|
|
1108
|
+
css += `
|
|
1109
|
+
@media (prefers-color-scheme: dark) {
|
|
1110
|
+
:root:not([data-bspoke="light"]) {
|
|
1111
|
+
${darkColors.replace(/^ {2}/gm, " ")}
|
|
1112
|
+
}
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
:root[data-bspoke="dark"],
|
|
1116
|
+
:root.dark {
|
|
1117
|
+
${darkColors}
|
|
1118
|
+
}
|
|
1119
|
+
`;
|
|
1120
|
+
}
|
|
1121
|
+
return css;
|
|
1122
|
+
}
|
|
1123
|
+
var PREFIX = "user";
|
|
1124
|
+
var color = buildColorTree(modeColors, flatColors, PREFIX);
|
|
1125
|
+
var shadow = buildShadowRefs(shadowTokens, PREFIX);
|
|
1126
|
+
function renderCss() {
|
|
1127
|
+
return renderFallbackCss(
|
|
1128
|
+
{ modeColors, flatColors, shadowTokens, fontFamily },
|
|
1129
|
+
{ prefix: PREFIX, dark: true }
|
|
1130
|
+
);
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
// ../design/dist/admin/index.js
|
|
1134
|
+
var modeColors2 = {
|
|
1135
|
+
"bg/base": {
|
|
1136
|
+
"dark": "#ffffff",
|
|
1137
|
+
"light": "#ffffff"
|
|
1138
|
+
},
|
|
1139
|
+
"bg/bstage-admin": {
|
|
1140
|
+
"dark": "#f5f6f8",
|
|
1141
|
+
"light": "#f5f6f8"
|
|
1142
|
+
},
|
|
1143
|
+
"bg/elevated": {
|
|
1144
|
+
"dark": "#ffffff",
|
|
1145
|
+
"light": "#ffffff"
|
|
1146
|
+
},
|
|
1147
|
+
"bg/grouped-blue": {
|
|
1148
|
+
"dark": "#f5f8ff",
|
|
1149
|
+
"light": "#f5f8ff"
|
|
1150
|
+
},
|
|
1151
|
+
"bg/grouped-default": {
|
|
1152
|
+
"dark": "#ffffff",
|
|
1153
|
+
"light": "#ffffff"
|
|
1154
|
+
},
|
|
1155
|
+
"bg/grouped-strong": {
|
|
1156
|
+
"dark": "#f5f6f8",
|
|
1157
|
+
"light": "#f5f6f8"
|
|
1158
|
+
},
|
|
1159
|
+
"bg/grouped-strong-weak": {
|
|
1160
|
+
"dark": "#f9fafb",
|
|
1161
|
+
"light": "#f9fafb"
|
|
1162
|
+
},
|
|
1163
|
+
"border/blue": {
|
|
1164
|
+
"dark": "#397af6",
|
|
1165
|
+
"light": "#397af6"
|
|
1166
|
+
},
|
|
1167
|
+
"border/blue-weak-a": {
|
|
1168
|
+
"dark": "#397af61a",
|
|
1169
|
+
"light": "#397af61a"
|
|
1170
|
+
},
|
|
1171
|
+
"border/bstage": {
|
|
1172
|
+
"dark": "#343d46",
|
|
1173
|
+
"light": "#343d46"
|
|
1174
|
+
},
|
|
1175
|
+
"border/bstage-strong": {
|
|
1176
|
+
"dark": "#1a1e23",
|
|
1177
|
+
"light": "#1a1e23"
|
|
1178
|
+
},
|
|
1179
|
+
"border/bstage-weak": {
|
|
1180
|
+
"dark": "#71777e",
|
|
1181
|
+
"light": "#71777e"
|
|
1182
|
+
},
|
|
1183
|
+
"border/default-a": {
|
|
1184
|
+
"dark": "#59667226",
|
|
1185
|
+
"light": "#59667226"
|
|
1186
|
+
},
|
|
1187
|
+
"border/divider-a": {
|
|
1188
|
+
"dark": "#5966721a",
|
|
1189
|
+
"light": "#5966721a"
|
|
1190
|
+
},
|
|
1191
|
+
"border/divider-weak-a": {
|
|
1192
|
+
"dark": "#5966720d",
|
|
1193
|
+
"light": "#5966720d"
|
|
1194
|
+
},
|
|
1195
|
+
"border/eraser": {
|
|
1196
|
+
"dark": "#ffffff",
|
|
1197
|
+
"light": "#ffffff"
|
|
1198
|
+
},
|
|
1199
|
+
"border/green": {
|
|
1200
|
+
"dark": "#32b27c",
|
|
1201
|
+
"light": "#32b27c"
|
|
1202
|
+
},
|
|
1203
|
+
"border/green-weak-a": {
|
|
1204
|
+
"dark": "#32b27c1a",
|
|
1205
|
+
"light": "#32b27c1a"
|
|
1206
|
+
},
|
|
1207
|
+
"border/red": {
|
|
1208
|
+
"dark": "#f41616",
|
|
1209
|
+
"light": "#f41616"
|
|
1210
|
+
},
|
|
1211
|
+
"border/red-weak-a": {
|
|
1212
|
+
"dark": "#f416161a",
|
|
1213
|
+
"light": "#f416161a"
|
|
1214
|
+
},
|
|
1215
|
+
"border/strong-a": {
|
|
1216
|
+
"dark": "#5966724d",
|
|
1217
|
+
"light": "#5966724d"
|
|
1218
|
+
},
|
|
1219
|
+
"border/stronger-a": {
|
|
1220
|
+
"dark": "#59667280",
|
|
1221
|
+
"light": "#59667280"
|
|
1222
|
+
},
|
|
1223
|
+
"border/yellow": {
|
|
1224
|
+
"dark": "#f29900",
|
|
1225
|
+
"light": "#f29900"
|
|
1226
|
+
},
|
|
1227
|
+
"border/yellow-weak-a": {
|
|
1228
|
+
"dark": "#ff99001a",
|
|
1229
|
+
"light": "#ff99001a"
|
|
1230
|
+
},
|
|
1231
|
+
"bstagein/plan-essential": {
|
|
1232
|
+
"dark": "#fdaffd",
|
|
1233
|
+
"light": "#fdaffd"
|
|
1234
|
+
},
|
|
1235
|
+
"bstagein/plan-plus": {
|
|
1236
|
+
"dark": "#151515",
|
|
1237
|
+
"light": "#151515"
|
|
1238
|
+
},
|
|
1239
|
+
"bstagein/plan-standard": {
|
|
1240
|
+
"dark": "#3067ec",
|
|
1241
|
+
"light": "#3067ec"
|
|
1242
|
+
},
|
|
1243
|
+
"chart/default": {
|
|
1244
|
+
"dark": "#595eff",
|
|
1245
|
+
"light": "#595eff"
|
|
1246
|
+
},
|
|
1247
|
+
"chart/green": {
|
|
1248
|
+
"dark": "#11ce8c",
|
|
1249
|
+
"light": "#11ce8c"
|
|
1250
|
+
},
|
|
1251
|
+
"chart/grey": {
|
|
1252
|
+
"dark": "#bdbdbd",
|
|
1253
|
+
"light": "#bdbdbd"
|
|
1254
|
+
},
|
|
1255
|
+
"chart/orange": {
|
|
1256
|
+
"dark": "#ff8057",
|
|
1257
|
+
"light": "#ff8057"
|
|
1258
|
+
},
|
|
1259
|
+
"chart/red": {
|
|
1260
|
+
"dark": "#ff505a",
|
|
1261
|
+
"light": "#ff505a"
|
|
1262
|
+
},
|
|
1263
|
+
"chart/sky": {
|
|
1264
|
+
"dark": "#54c1fb",
|
|
1265
|
+
"light": "#54c1fb"
|
|
1266
|
+
},
|
|
1267
|
+
"chart/strong": {
|
|
1268
|
+
"dark": "#5055e6",
|
|
1269
|
+
"light": "#5055e6"
|
|
1270
|
+
},
|
|
1271
|
+
"chart/stronger": {
|
|
1272
|
+
"dark": "#2c30b0",
|
|
1273
|
+
"light": "#2c30b0"
|
|
1274
|
+
},
|
|
1275
|
+
"chart/weak": {
|
|
1276
|
+
"dark": "#cdcfff",
|
|
1277
|
+
"light": "#cdcfff"
|
|
1278
|
+
},
|
|
1279
|
+
"chart/yellow": {
|
|
1280
|
+
"dark": "#ffce50",
|
|
1281
|
+
"light": "#ffce50"
|
|
1282
|
+
},
|
|
1283
|
+
"icon/blue": {
|
|
1284
|
+
"dark": "#397af6",
|
|
1285
|
+
"light": "#397af6"
|
|
1286
|
+
},
|
|
1287
|
+
"icon/green": {
|
|
1288
|
+
"dark": "#32b27c",
|
|
1289
|
+
"light": "#32b27c"
|
|
1290
|
+
},
|
|
1291
|
+
"icon/indigo": {
|
|
1292
|
+
"dark": "#5754f5",
|
|
1293
|
+
"light": "#5754f5"
|
|
1294
|
+
},
|
|
1295
|
+
"icon/primary": {
|
|
1296
|
+
"dark": "#3a424a",
|
|
1297
|
+
"light": "#3a424a"
|
|
1298
|
+
},
|
|
1299
|
+
"icon/red": {
|
|
1300
|
+
"dark": "#f41616",
|
|
1301
|
+
"light": "#f41616"
|
|
1302
|
+
},
|
|
1303
|
+
"icon/secondary-a": {
|
|
1304
|
+
"dark": "#596672d9",
|
|
1305
|
+
"light": "#596672d9"
|
|
1306
|
+
},
|
|
1307
|
+
"icon/tertiary-a": {
|
|
1308
|
+
"dark": "#5966724d",
|
|
1309
|
+
"light": "#5966724d"
|
|
1310
|
+
},
|
|
1311
|
+
"icon/yellow": {
|
|
1312
|
+
"dark": "#f29900",
|
|
1313
|
+
"light": "#f29900"
|
|
1314
|
+
},
|
|
1315
|
+
"overlay/dim-a": {
|
|
1316
|
+
"dark": "#00000080",
|
|
1317
|
+
"light": "#00000080"
|
|
1318
|
+
},
|
|
1319
|
+
"overlay/dim-weak-a": {
|
|
1320
|
+
"dark": "#0000001a",
|
|
1321
|
+
"light": "#0000001a"
|
|
1322
|
+
},
|
|
1323
|
+
"overlay/hover-a": {
|
|
1324
|
+
"dark": "#0000001a",
|
|
1325
|
+
"light": "#0000001a"
|
|
1326
|
+
},
|
|
1327
|
+
"overlay/hover-blue-a": {
|
|
1328
|
+
"dark": "#397af61a",
|
|
1329
|
+
"light": "#397af61a"
|
|
1330
|
+
},
|
|
1331
|
+
"overlay/hover-blue-weak-a": {
|
|
1332
|
+
"dark": "#397af60d",
|
|
1333
|
+
"light": "#397af60d"
|
|
1334
|
+
},
|
|
1335
|
+
"overlay/hover-red-a": {
|
|
1336
|
+
"dark": "#f416161a",
|
|
1337
|
+
"light": "#f416161a"
|
|
1338
|
+
},
|
|
1339
|
+
"overlay/hover-weak-a": {
|
|
1340
|
+
"dark": "#3453700d",
|
|
1341
|
+
"light": "#3453700d"
|
|
1342
|
+
},
|
|
1343
|
+
"surface/avatar-default-a": {
|
|
1344
|
+
"dark": "#3453700d",
|
|
1345
|
+
"light": "#3453700d"
|
|
1346
|
+
},
|
|
1347
|
+
"surface/avatar-random-01": {
|
|
1348
|
+
"dark": "#fa8a8a",
|
|
1349
|
+
"light": "#fa8a8a"
|
|
1350
|
+
},
|
|
1351
|
+
"surface/avatar-random-02": {
|
|
1352
|
+
"dark": "#ffcc80",
|
|
1353
|
+
"light": "#ffcc80"
|
|
1354
|
+
},
|
|
1355
|
+
"surface/avatar-random-03": {
|
|
1356
|
+
"dark": "#5bc196",
|
|
1357
|
+
"light": "#5bc196"
|
|
1358
|
+
},
|
|
1359
|
+
"surface/avatar-random-04": {
|
|
1360
|
+
"dark": "#4dbecd",
|
|
1361
|
+
"light": "#4dbecd"
|
|
1362
|
+
},
|
|
1363
|
+
"surface/avatar-random-05": {
|
|
1364
|
+
"dark": "#7976f7",
|
|
1365
|
+
"light": "#7976f7"
|
|
1366
|
+
},
|
|
1367
|
+
"surface/avatar-random-06": {
|
|
1368
|
+
"dark": "#aba9fa",
|
|
1369
|
+
"light": "#aba9fa"
|
|
1370
|
+
},
|
|
1371
|
+
"surface/avatar-random-07": {
|
|
1372
|
+
"dark": "#9c6beb",
|
|
1373
|
+
"light": "#9c6beb"
|
|
1374
|
+
},
|
|
1375
|
+
"surface/display-blue": {
|
|
1376
|
+
"dark": "#397af6",
|
|
1377
|
+
"light": "#397af6"
|
|
1378
|
+
},
|
|
1379
|
+
"surface/display-blue-weak-a": {
|
|
1380
|
+
"dark": "#397af61a",
|
|
1381
|
+
"light": "#397af61a"
|
|
1382
|
+
},
|
|
1383
|
+
"surface/display-blue-weakest-a": {
|
|
1384
|
+
"dark": "#397af608",
|
|
1385
|
+
"light": "#397af608"
|
|
1386
|
+
},
|
|
1387
|
+
"surface/display-bstage": {
|
|
1388
|
+
"dark": "#343d46",
|
|
1389
|
+
"light": "#343d46"
|
|
1390
|
+
},
|
|
1391
|
+
"surface/display-default": {
|
|
1392
|
+
"dark": "#ffffff",
|
|
1393
|
+
"light": "#ffffff"
|
|
1394
|
+
},
|
|
1395
|
+
"surface/display-green": {
|
|
1396
|
+
"dark": "#32b27c",
|
|
1397
|
+
"light": "#32b27c"
|
|
1398
|
+
},
|
|
1399
|
+
"surface/display-green-weak-a": {
|
|
1400
|
+
"dark": "#32b27c1a",
|
|
1401
|
+
"light": "#32b27c1a"
|
|
1402
|
+
},
|
|
1403
|
+
"surface/display-grey-a": {
|
|
1404
|
+
"dark": "#3453701a",
|
|
1405
|
+
"light": "#3453701a"
|
|
1406
|
+
},
|
|
1407
|
+
"surface/display-grey-weak-a": {
|
|
1408
|
+
"dark": "#3453700d",
|
|
1409
|
+
"light": "#3453700d"
|
|
1410
|
+
},
|
|
1411
|
+
"surface/display-red": {
|
|
1412
|
+
"dark": "#f41616",
|
|
1413
|
+
"light": "#f41616"
|
|
1414
|
+
},
|
|
1415
|
+
"surface/display-red-weak-a": {
|
|
1416
|
+
"dark": "#f416161a",
|
|
1417
|
+
"light": "#f416161a"
|
|
1418
|
+
},
|
|
1419
|
+
"surface/display-toast": {
|
|
1420
|
+
"dark": "#0a1116",
|
|
1421
|
+
"light": "#0a1116"
|
|
1422
|
+
},
|
|
1423
|
+
"surface/display-tooltip": {
|
|
1424
|
+
"dark": "#596672",
|
|
1425
|
+
"light": "#596672"
|
|
1426
|
+
},
|
|
1427
|
+
"surface/display-yellow": {
|
|
1428
|
+
"dark": "#ff9900",
|
|
1429
|
+
"light": "#ff9900"
|
|
1430
|
+
},
|
|
1431
|
+
"surface/display-yellow-weak-a": {
|
|
1432
|
+
"dark": "#ff99001a",
|
|
1433
|
+
"light": "#ff99001a"
|
|
1434
|
+
},
|
|
1435
|
+
"surface/form-base": {
|
|
1436
|
+
"dark": "#ffffff",
|
|
1437
|
+
"light": "#ffffff"
|
|
1438
|
+
},
|
|
1439
|
+
"surface/form-blue": {
|
|
1440
|
+
"dark": "#397af6",
|
|
1441
|
+
"light": "#397af6"
|
|
1442
|
+
},
|
|
1443
|
+
"surface/form-blue-weak-a": {
|
|
1444
|
+
"dark": "#397af626",
|
|
1445
|
+
"light": "#397af626"
|
|
1446
|
+
},
|
|
1447
|
+
"surface/form-bstage": {
|
|
1448
|
+
"dark": "#343d46",
|
|
1449
|
+
"light": "#343d46"
|
|
1450
|
+
},
|
|
1451
|
+
"surface/form-bstage-strong": {
|
|
1452
|
+
"dark": "#1a1e23",
|
|
1453
|
+
"light": "#1a1e23"
|
|
1454
|
+
},
|
|
1455
|
+
"surface/form-bstage-weak": {
|
|
1456
|
+
"dark": "#71777e",
|
|
1457
|
+
"light": "#71777e"
|
|
1458
|
+
},
|
|
1459
|
+
"surface/form-default": {
|
|
1460
|
+
"dark": "#ebeef1",
|
|
1461
|
+
"light": "#ebeef1"
|
|
1462
|
+
},
|
|
1463
|
+
"surface/form-default-a": {
|
|
1464
|
+
"dark": "#3453701a",
|
|
1465
|
+
"light": "#3453701a"
|
|
1466
|
+
},
|
|
1467
|
+
"surface/form-green-weak-a": {
|
|
1468
|
+
"dark": "#32b27c1a",
|
|
1469
|
+
"light": "#32b27c1a"
|
|
1470
|
+
},
|
|
1471
|
+
"surface/form-red": {
|
|
1472
|
+
"dark": "#f41616",
|
|
1473
|
+
"light": "#f41616"
|
|
1474
|
+
},
|
|
1475
|
+
"surface/form-red-weak-a": {
|
|
1476
|
+
"dark": "#f4161626",
|
|
1477
|
+
"light": "#f4161626"
|
|
1478
|
+
},
|
|
1479
|
+
"surface/form-strong-a": {
|
|
1480
|
+
"dark": "#34537033",
|
|
1481
|
+
"light": "#34537033"
|
|
1482
|
+
},
|
|
1483
|
+
"surface/form-toggle": {
|
|
1484
|
+
"dark": "#3453704d",
|
|
1485
|
+
"light": "#3453704d"
|
|
1486
|
+
},
|
|
1487
|
+
"surface/form-weak-a": {
|
|
1488
|
+
"dark": "#3453700d",
|
|
1489
|
+
"light": "#3453700d"
|
|
1490
|
+
},
|
|
1491
|
+
"surface/form-yellow-weak-a": {
|
|
1492
|
+
"dark": "#f299001a",
|
|
1493
|
+
"light": "#f299001a"
|
|
1494
|
+
},
|
|
1495
|
+
"text/blue": {
|
|
1496
|
+
"dark": "#397af6",
|
|
1497
|
+
"light": "#397af6"
|
|
1498
|
+
},
|
|
1499
|
+
"text/green": {
|
|
1500
|
+
"dark": "#32b27c",
|
|
1501
|
+
"light": "#32b27c"
|
|
1502
|
+
},
|
|
1503
|
+
"text/indigo": {
|
|
1504
|
+
"dark": "#5754f5",
|
|
1505
|
+
"light": "#5754f5"
|
|
1506
|
+
},
|
|
1507
|
+
"text/primary": {
|
|
1508
|
+
"dark": "#2a2b2f",
|
|
1509
|
+
"light": "#2a2b2f"
|
|
1510
|
+
},
|
|
1511
|
+
"text/purple": {
|
|
1512
|
+
"dark": "#8346e7",
|
|
1513
|
+
"light": "#8346e7"
|
|
1514
|
+
},
|
|
1515
|
+
"text/red": {
|
|
1516
|
+
"dark": "#f41616",
|
|
1517
|
+
"light": "#f41616"
|
|
1518
|
+
},
|
|
1519
|
+
"text/secondary": {
|
|
1520
|
+
"dark": "#676d72",
|
|
1521
|
+
"light": "#676d72"
|
|
1522
|
+
},
|
|
1523
|
+
"text/sub-a": {
|
|
1524
|
+
"dark": "#596672b3",
|
|
1525
|
+
"light": "#596672b3"
|
|
1526
|
+
},
|
|
1527
|
+
"text/tertiary-a": {
|
|
1528
|
+
"dark": "#596672b3",
|
|
1529
|
+
"light": "#596672b3"
|
|
1530
|
+
},
|
|
1531
|
+
"text/yellow": {
|
|
1532
|
+
"dark": "#f29900",
|
|
1533
|
+
"light": "#f29900"
|
|
1534
|
+
}
|
|
1535
|
+
};
|
|
1536
|
+
var flatColors2 = {
|
|
1537
|
+
"always/black005-a": "#0000000d",
|
|
1538
|
+
"always/black010-a": "#0000001a",
|
|
1539
|
+
"always/black030-a": "#0000004d",
|
|
1540
|
+
"always/black050-a": "#00000080",
|
|
1541
|
+
"always/black060-a": "#00000099",
|
|
1542
|
+
"always/black100-a": "#000000",
|
|
1543
|
+
"always/green100": "#32b27c",
|
|
1544
|
+
"always/grey135": "#243a4e",
|
|
1545
|
+
"always/indigo100": "#5754f5",
|
|
1546
|
+
"always/overlay-hover-white010-a": "#ffffff1a",
|
|
1547
|
+
"always/purple100": "#8346e7",
|
|
1548
|
+
"always/red085": "#f74444",
|
|
1549
|
+
"always/service-rankingpoll-thumb-a": "#ffadddcc",
|
|
1550
|
+
"always/white010-a": "#ffffff1a",
|
|
1551
|
+
"always/white015-a": "#ffffff26",
|
|
1552
|
+
"always/white025-a": "#ffffff40",
|
|
1553
|
+
"always/white050-a": "#ffffff80",
|
|
1554
|
+
"always/white060-a": "#ffffff99",
|
|
1555
|
+
"always/white070-a": "#ffffffb3",
|
|
1556
|
+
"always/white080-a": "#ffffffcc",
|
|
1557
|
+
"always/white100": "#ffffff",
|
|
1558
|
+
"always/yellow100": "#ff9900",
|
|
1559
|
+
"auto/border-divider-on-dark": "#ffffff26",
|
|
1560
|
+
"auto/border-divider-on-light": "#0000000f",
|
|
1561
|
+
"auto/icon-primary-on-dark": "#ffffff",
|
|
1562
|
+
"auto/icon-primary-on-light": "#00000099",
|
|
1563
|
+
"auto/icon-secondary-on-dark": "#ffffff80",
|
|
1564
|
+
"auto/icon-secondary-on-light": "#0000004d",
|
|
1565
|
+
"auto/overlay-hover-on-dark": "#ffffff1a",
|
|
1566
|
+
"auto/overlay-hover-on-light": "#0000001a",
|
|
1567
|
+
"auto/text-primary-on-dark": "#ffffff",
|
|
1568
|
+
"auto/text-primary-on-light": "#000000",
|
|
1569
|
+
"auto/text-secondary-on-dark": "#ffffff80",
|
|
1570
|
+
"auto/text-secondary-on-light": "#00000080"
|
|
1571
|
+
};
|
|
1572
|
+
var shadowTokens2 = {
|
|
1573
|
+
"shadow/default-large": {
|
|
1574
|
+
"dark": "0px 16px 36px -4px #1a1a1a33, 0px 0px 1px 0px #1a1a1a2e",
|
|
1575
|
+
"light": "0px 16px 36px -4px #1a1a1a33, 0px 0px 1px 0px #1a1a1a2e"
|
|
1576
|
+
},
|
|
1577
|
+
"shadow/default-medium": {
|
|
1578
|
+
"dark": "0px 8px 32px -2px #1a1a1a29, 0px 0px 1px 0px #00000026",
|
|
1579
|
+
"light": "0px 8px 32px -2px #1a1a1a29, 0px 0px 1px 0px #00000026"
|
|
1580
|
+
},
|
|
1581
|
+
"shadow/default-small": {
|
|
1582
|
+
"dark": "0px 4px 8px -1px #1a1a1a1f, 0px 0px 1px 0px #1a1a1a1f",
|
|
1583
|
+
"light": "0px 4px 8px -1px #1a1a1a1f, 0px 0px 1px 0px #1a1a1a1f"
|
|
1584
|
+
},
|
|
1585
|
+
"shadow/default-xsmall": {
|
|
1586
|
+
"dark": "0px 1px 1px 0px #1a1a1a1a, 0px 0px 1px 0px #1a1a1a1a",
|
|
1587
|
+
"light": "0px 1px 1px 0px #1a1a1a1a, 0px 0px 1px 0px #1a1a1a1a"
|
|
1588
|
+
}
|
|
1589
|
+
};
|
|
1590
|
+
var fontFamily2 = "'Pretendard Variable', Pretendard, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'";
|
|
1591
|
+
function cssVarName2(slug, prefix, kind) {
|
|
1592
|
+
const s = slug.replace(/\//g, "-");
|
|
1593
|
+
return kind === "mode" ? `--${prefix}-mode-${s}` : `--${prefix}-${s}`;
|
|
1594
|
+
}
|
|
1595
|
+
function cssVarRef2(slug, prefix, kind) {
|
|
1596
|
+
return `var(${cssVarName2(slug, prefix, kind)})`;
|
|
1597
|
+
}
|
|
1598
|
+
function buildColorTree2(modeColors22, flatColors22, prefix) {
|
|
1599
|
+
const tree = {};
|
|
1600
|
+
const add = (slug, kind) => {
|
|
1601
|
+
const [cat, ...rest] = slug.split("/");
|
|
1602
|
+
const leaf = rest.join("/").replace(/\//g, "-") || cat;
|
|
1603
|
+
(tree[cat] ?? (tree[cat] = {}))[leaf] = cssVarRef2(slug, prefix, kind);
|
|
1604
|
+
};
|
|
1605
|
+
for (const slug of Object.keys(modeColors22)) add(slug, "mode");
|
|
1606
|
+
for (const slug of Object.keys(flatColors22)) add(slug, "flat");
|
|
1607
|
+
return tree;
|
|
1608
|
+
}
|
|
1609
|
+
function buildShadowRefs2(shadowTokens22, prefix) {
|
|
1610
|
+
const out = {};
|
|
1611
|
+
for (const slug of Object.keys(shadowTokens22)) {
|
|
1612
|
+
const leaf = slug.replace(/^shadow\//, "");
|
|
1613
|
+
out[leaf] = cssVarRef2(slug, prefix, "mode");
|
|
1614
|
+
}
|
|
1615
|
+
return out;
|
|
1616
|
+
}
|
|
1617
|
+
function colorLines2(t, prefix, mode) {
|
|
1618
|
+
return [
|
|
1619
|
+
...Object.entries(t.modeColors).map(
|
|
1620
|
+
([slug, pair]) => ` ${cssVarName2(slug, prefix, "mode")}: ${pair[mode]};`
|
|
1621
|
+
),
|
|
1622
|
+
...Object.entries(t.shadowTokens).map(
|
|
1623
|
+
([slug, pair]) => ` ${cssVarName2(slug, prefix, "mode")}: ${pair[mode]};`
|
|
1624
|
+
)
|
|
1625
|
+
].join("\n");
|
|
1626
|
+
}
|
|
1627
|
+
function renderFallbackCss2(t, opts) {
|
|
1628
|
+
const p = opts.prefix;
|
|
1629
|
+
const flat = Object.entries(t.flatColors).map(([slug, v]) => ` ${cssVarName2(slug, p, "flat")}: ${v};`).join("\n");
|
|
1630
|
+
const lightColors = colorLines2(t, p, "light");
|
|
1631
|
+
let css = `/* ================================================================
|
|
1632
|
+
* bstage \uB514\uC790\uC778 \uD1A0\uD070 \u2014 dev fallback (${p})
|
|
1633
|
+
* @bstage-sdk/design \uC0DD\uC131\uBB3C. \uAC1C\uBC1C/\uBBF8\uB9AC\uBCF4\uAE30 \uC804\uC6A9(:root fallback).
|
|
1634
|
+
* \uBC30\uD3EC \uC2DC\uC5D4 \uD50C\uB7AB\uD3FC :root \uAC12\uC744 \uC0C1\uC18D\uD558\uBA70 \uC774 \uD30C\uC77C\uC740 \uBC88\uB4E4\uB418\uC9C0 \uC54A\uB294\uB2E4.
|
|
1635
|
+
* ================================================================ */
|
|
1636
|
+
|
|
1637
|
+
:root {
|
|
1638
|
+
${lightColors}
|
|
1639
|
+
|
|
1640
|
+
${flat}
|
|
1641
|
+
|
|
1642
|
+
--${p}-font-family: ${t.fontFamily};
|
|
1643
|
+
}
|
|
1644
|
+
`;
|
|
1645
|
+
if (opts.dark) {
|
|
1646
|
+
const darkColors = colorLines2(t, p, "dark");
|
|
1647
|
+
css += `
|
|
1648
|
+
@media (prefers-color-scheme: dark) {
|
|
1649
|
+
:root:not([data-bspoke="light"]) {
|
|
1650
|
+
${darkColors.replace(/^ {2}/gm, " ")}
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
|
|
1654
|
+
:root[data-bspoke="dark"],
|
|
1655
|
+
:root.dark {
|
|
1656
|
+
${darkColors}
|
|
1657
|
+
}
|
|
1658
|
+
`;
|
|
1659
|
+
}
|
|
1660
|
+
return css;
|
|
1661
|
+
}
|
|
1662
|
+
var PREFIX2 = "admin";
|
|
1663
|
+
var color2 = buildColorTree2(modeColors2, flatColors2, PREFIX2);
|
|
1664
|
+
var shadow2 = buildShadowRefs2(shadowTokens2, PREFIX2);
|
|
1665
|
+
function renderCss2() {
|
|
1666
|
+
return renderFallbackCss2(
|
|
1667
|
+
{ modeColors: modeColors2, flatColors: flatColors2, shadowTokens: shadowTokens2, fontFamily: fontFamily2 },
|
|
1668
|
+
{ prefix: PREFIX2, dark: false }
|
|
1669
|
+
);
|
|
1670
|
+
}
|
|
1671
|
+
|
|
1672
|
+
// src/dev/devVitePlugin.ts
|
|
1673
|
+
var RESOLVE_BASE_URL_RE = /function\s+resolveBaseUrl\(\)\s*\{[\s\S]*?\n\}/;
|
|
1674
|
+
var DEV_THEME_TOGGLE = `
|
|
1675
|
+
(function () {
|
|
1676
|
+
if (window.__bstage_theme_toggle__) return
|
|
1677
|
+
window.__bstage_theme_toggle__ = true
|
|
1678
|
+
var btn = document.createElement('button')
|
|
1679
|
+
var label = function () {
|
|
1680
|
+
return document.documentElement.dataset.bspoke === 'dark' ? '\u{1F319} Dark' : '\u2600\uFE0F Light'
|
|
1681
|
+
}
|
|
1682
|
+
btn.type = 'button'
|
|
1683
|
+
btn.title = 'bstage \uB514\uC790\uC778 \uD1A0\uD070 \uB77C\uC774\uD2B8/\uB2E4\uD06C \uBBF8\uB9AC\uBCF4\uAE30 (dev \uC804\uC6A9)'
|
|
1684
|
+
btn.textContent = label()
|
|
1685
|
+
btn.style.cssText =
|
|
1686
|
+
'position:fixed;right:12px;bottom:12px;z-index:2147483647;padding:6px 10px;' +
|
|
1687
|
+
"font:12px/1 system-ui,sans-serif;border:1px solid rgba(0,0,0,.15);border-radius:8px;" +
|
|
1688
|
+
'background:#fff;color:#151515;cursor:pointer;box-shadow:0 2px 8px rgba(0,0,0,.15)'
|
|
1689
|
+
btn.onclick = function () {
|
|
1690
|
+
var cur = document.documentElement.dataset.bspoke
|
|
1691
|
+
document.documentElement.dataset.bspoke = cur === 'dark' ? 'light' : 'dark'
|
|
1692
|
+
btn.textContent = label()
|
|
1693
|
+
}
|
|
1694
|
+
document.body.appendChild(btn)
|
|
1695
|
+
})()
|
|
1696
|
+
`;
|
|
1697
|
+
var DEV_LOCALE_SWITCHER = `
|
|
1698
|
+
window.__bstage_setLocale__ = function (locale) {
|
|
1699
|
+
document.documentElement.lang = locale
|
|
1700
|
+
document.cookie = 'bmf_bstage_lang=' + locale + '; path=/'
|
|
1701
|
+
document.cookie = 'bmf_mybstage_locale=' + locale + '; path=/'
|
|
1702
|
+
return locale
|
|
1703
|
+
}
|
|
1704
|
+
`.trim();
|
|
1705
|
+
function filterPseudoHeaders(headers) {
|
|
1706
|
+
const out = {};
|
|
1707
|
+
for (const [k, v] of Object.entries(headers)) {
|
|
1708
|
+
if (!k.startsWith(":")) out[k] = v;
|
|
1709
|
+
}
|
|
1710
|
+
return out;
|
|
1711
|
+
}
|
|
1712
|
+
async function refreshAccessToken(mode, phase, hosts, tenantId, accessToken, cookieStr) {
|
|
1713
|
+
try {
|
|
1714
|
+
const authHost = hosts.auth(tenantId);
|
|
1715
|
+
if (!authHost) return null;
|
|
1716
|
+
const postBody = JSON.stringify({ accessToken });
|
|
1717
|
+
const headers = {
|
|
1718
|
+
host: authHost,
|
|
1719
|
+
"Content-Type": "application/json",
|
|
1720
|
+
"Content-Length": String(Buffer.byteLength(postBody)),
|
|
1721
|
+
"x-bmf-sid": tenantId,
|
|
1722
|
+
cookie: cookieStr
|
|
1723
|
+
};
|
|
1724
|
+
addCfAccessHeaders(headers, phase);
|
|
1725
|
+
const result = await proxyRequest({
|
|
1726
|
+
hostname: authHost,
|
|
1727
|
+
path: AUTH_TOKEN_REFRESH_PATH_BY_MODE[mode],
|
|
1728
|
+
method: "POST",
|
|
1729
|
+
headers,
|
|
1730
|
+
body: Buffer.from(postBody)
|
|
1731
|
+
});
|
|
1732
|
+
const text = result.body.toString("utf-8");
|
|
1733
|
+
const json = JSON.parse(text);
|
|
1734
|
+
if (result.statusCode === 200 && json.accessToken) {
|
|
1735
|
+
console.info(`[bstage] token refreshed (${mode})`);
|
|
1736
|
+
return json.accessToken;
|
|
1737
|
+
}
|
|
1738
|
+
console.warn("[bstage] token refresh failed:", result.statusCode, text);
|
|
1739
|
+
return null;
|
|
1740
|
+
} catch {
|
|
1741
|
+
return null;
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
async function sendGatewayRequest(targetHost, targetPath, method, headers, body) {
|
|
1745
|
+
const result = await proxyRequest({
|
|
1746
|
+
hostname: targetHost,
|
|
1747
|
+
path: targetPath,
|
|
1748
|
+
method,
|
|
1749
|
+
headers,
|
|
1750
|
+
body
|
|
1751
|
+
});
|
|
1752
|
+
return {
|
|
1753
|
+
statusCode: result.statusCode,
|
|
1754
|
+
headers: result.headers,
|
|
1755
|
+
body: result.body.toString("utf-8")
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
function handleGatewayProxy(mode, phase, hosts, req, res) {
|
|
1759
|
+
const tenantId = req.headers[TENANT_ID_HEADER];
|
|
1760
|
+
if (!tenantId) {
|
|
1761
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1762
|
+
res.end(JSON.stringify({ message: `Missing ${TENANT_ID_HEADER} header` }));
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
const targetHost = hosts.gateway(tenantId);
|
|
1766
|
+
if (!targetHost) {
|
|
1767
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1768
|
+
res.end(JSON.stringify({ message: `Unknown phase: ${phase}` }));
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
const targetPath = (req.url ?? "").replace(new RegExp(`^${PROXY_PATH_PREFIX}/${phase}`), "");
|
|
1772
|
+
const cookieName2 = ACCESS_TOKEN_COOKIE_BY_MODE[mode];
|
|
1773
|
+
const cookieRe = ACCESS_TOKEN_RE_BY_MODE[mode];
|
|
1774
|
+
collectBody(req).then(async (body) => {
|
|
1775
|
+
const buildHeaders = (accessToken) => {
|
|
1776
|
+
const h = filterPseudoHeaders(req.headers);
|
|
1777
|
+
h["host"] = targetHost;
|
|
1778
|
+
addCfAccessHeaders(h, phase);
|
|
1779
|
+
const token = accessToken ?? (req.headers["cookie"] ?? "").match(cookieRe)?.[1];
|
|
1780
|
+
if (token) {
|
|
1781
|
+
h["authorization"] = `Bearer ${token}`;
|
|
1782
|
+
}
|
|
1783
|
+
return h;
|
|
1784
|
+
};
|
|
1785
|
+
console.info(`[bstage] ${req.method} https://${targetHost}${targetPath}`);
|
|
1786
|
+
try {
|
|
1787
|
+
const upstreamHeaders = buildHeaders();
|
|
1788
|
+
let result = await sendGatewayRequest(
|
|
1789
|
+
targetHost,
|
|
1790
|
+
targetPath,
|
|
1791
|
+
req.method ?? "GET",
|
|
1792
|
+
upstreamHeaders,
|
|
1793
|
+
body
|
|
1794
|
+
);
|
|
1795
|
+
if (result.statusCode === 401) {
|
|
1796
|
+
const cookieStr = req.headers["cookie"] ?? "";
|
|
1797
|
+
const oldToken = cookieStr.match(cookieRe)?.[1];
|
|
1798
|
+
if (oldToken) {
|
|
1799
|
+
const newToken = await refreshAccessToken(
|
|
1800
|
+
mode,
|
|
1801
|
+
phase,
|
|
1802
|
+
hosts,
|
|
1803
|
+
tenantId,
|
|
1804
|
+
oldToken,
|
|
1805
|
+
cookieStr
|
|
1806
|
+
);
|
|
1807
|
+
if (newToken) {
|
|
1808
|
+
const retryHeaders = buildHeaders(newToken);
|
|
1809
|
+
result = await sendGatewayRequest(
|
|
1810
|
+
targetHost,
|
|
1811
|
+
targetPath,
|
|
1812
|
+
req.method ?? "GET",
|
|
1813
|
+
retryHeaders,
|
|
1814
|
+
body
|
|
1815
|
+
);
|
|
1816
|
+
stripResponseCookies(result.headers, [`${cookieName2}=${newToken}; Path=/`]);
|
|
1817
|
+
}
|
|
1818
|
+
}
|
|
1819
|
+
}
|
|
1820
|
+
stripResponseCookies(result.headers);
|
|
1821
|
+
res.writeHead(result.statusCode, result.headers);
|
|
1822
|
+
res.end(result.body);
|
|
1823
|
+
} catch (err) {
|
|
1824
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1825
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
1826
|
+
res.end(JSON.stringify({ message: "Gateway proxy error", error: message }));
|
|
1827
|
+
}
|
|
1828
|
+
});
|
|
1829
|
+
}
|
|
1830
|
+
function subpathOf(source) {
|
|
1831
|
+
const segments = source.split("/");
|
|
1832
|
+
const rest = segments.slice(source.startsWith("@") ? 2 : 1);
|
|
1833
|
+
return rest.length === 0 ? "." : `./${rest.join("/")}`;
|
|
1834
|
+
}
|
|
1835
|
+
function findPackageDir(from) {
|
|
1836
|
+
let dir = dirname(from);
|
|
1837
|
+
while (dir !== dirname(dir)) {
|
|
1838
|
+
try {
|
|
1839
|
+
readFileSync2(join(dir, "package.json"));
|
|
1840
|
+
return dir;
|
|
1841
|
+
} catch {
|
|
1842
|
+
dir = dirname(dir);
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
return null;
|
|
1846
|
+
}
|
|
1847
|
+
function handleAuthProxy(mode, phase, hosts, req, res) {
|
|
1848
|
+
const tenantId = req.headers[TENANT_ID_HEADER];
|
|
1849
|
+
if (!tenantId) {
|
|
1850
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1851
|
+
res.end(JSON.stringify({ message: `Missing ${TENANT_ID_HEADER} header` }));
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
const targetHost = hosts.auth(tenantId);
|
|
1855
|
+
if (!targetHost) {
|
|
1856
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
1857
|
+
res.end(JSON.stringify({ message: `Unknown phase: ${phase} (mode: ${mode})` }));
|
|
1858
|
+
return;
|
|
1859
|
+
}
|
|
1860
|
+
const targetPath = (req.url ?? "").replace(new RegExp(`^${AUTH_PATH_PREFIX}`), "/svc");
|
|
1861
|
+
const cookieName2 = ACCESS_TOKEN_COOKIE_BY_MODE[mode];
|
|
1862
|
+
collectBody(req).then(async (body) => {
|
|
1863
|
+
const upstreamHeaders = filterPseudoHeaders(
|
|
1864
|
+
req.headers
|
|
1865
|
+
);
|
|
1866
|
+
upstreamHeaders["host"] = targetHost;
|
|
1867
|
+
addCfAccessHeaders(upstreamHeaders, phase);
|
|
1868
|
+
upstreamHeaders["x-bmf-sid"] = tenantId;
|
|
1869
|
+
try {
|
|
1870
|
+
const result = await proxyRequest({
|
|
1871
|
+
hostname: targetHost,
|
|
1872
|
+
path: targetPath,
|
|
1873
|
+
method: req.method ?? "POST",
|
|
1874
|
+
headers: upstreamHeaders,
|
|
1875
|
+
body
|
|
1876
|
+
});
|
|
1877
|
+
const textBody = result.body.toString("utf-8");
|
|
1878
|
+
const extraCookies = [];
|
|
1879
|
+
if (result.statusCode >= 200 && result.statusCode < 300) {
|
|
1880
|
+
try {
|
|
1881
|
+
const json = JSON.parse(textBody);
|
|
1882
|
+
const accessToken = json.accessToken ?? json.data?.accessToken;
|
|
1883
|
+
if (accessToken) {
|
|
1884
|
+
extraCookies.push(`${cookieName2}=${accessToken}; Path=/`);
|
|
1885
|
+
} else {
|
|
1886
|
+
console.warn(
|
|
1887
|
+
`[bstage] auth response missing accessToken (mode=${mode}, status=${result.statusCode}, body status=${json.status ?? "n/a"})`
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1890
|
+
} catch (parseErr) {
|
|
1891
|
+
console.warn(
|
|
1892
|
+
`[bstage] auth response JSON parse failed (mode=${mode}, status=${result.statusCode}):`,
|
|
1893
|
+
parseErr instanceof Error ? parseErr.message : parseErr
|
|
1894
|
+
);
|
|
1895
|
+
}
|
|
1896
|
+
} else {
|
|
1897
|
+
console.warn(
|
|
1898
|
+
`[bstage] auth proxy upstream non-2xx (mode=${mode}, status=${result.statusCode}):`,
|
|
1899
|
+
textBody.slice(0, 500)
|
|
1900
|
+
);
|
|
1901
|
+
}
|
|
1902
|
+
stripResponseCookies(result.headers, extraCookies);
|
|
1903
|
+
res.writeHead(result.statusCode, result.headers);
|
|
1904
|
+
res.end(textBody);
|
|
1905
|
+
} catch (err) {
|
|
1906
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
1907
|
+
res.writeHead(502, { "Content-Type": "application/json" });
|
|
1908
|
+
res.end(JSON.stringify({ message: "Auth proxy error", error: message }));
|
|
1909
|
+
}
|
|
1910
|
+
});
|
|
1911
|
+
}
|
|
1912
|
+
function bstageDevPlugin(options = {}) {
|
|
1913
|
+
const phase = options.phase ?? DEFAULT_PHASE;
|
|
1914
|
+
const mode = options.mode ?? "user";
|
|
1915
|
+
let isAdmin = false;
|
|
1916
|
+
let configPort;
|
|
1917
|
+
let actualPort;
|
|
1918
|
+
let projectRequire;
|
|
1919
|
+
let hosts;
|
|
1920
|
+
return {
|
|
1921
|
+
name: "bstage-dev",
|
|
1922
|
+
enforce: "pre",
|
|
1923
|
+
config() {
|
|
1924
|
+
const root = process.cwd();
|
|
1925
|
+
projectRequire = createRequire(join(root, "package.json"));
|
|
1926
|
+
return {
|
|
1927
|
+
optimizeDeps: {
|
|
1928
|
+
exclude: ["@bstage-sdk/core", "@bstage-sdk/react"]
|
|
1929
|
+
},
|
|
1930
|
+
resolve: {
|
|
1931
|
+
dedupe: ["react", "react-dom", "react/jsx-runtime"]
|
|
1932
|
+
}
|
|
1933
|
+
};
|
|
1934
|
+
},
|
|
1935
|
+
configResolved(config) {
|
|
1936
|
+
configPort = config.server.port ?? 5173;
|
|
1937
|
+
isAdmin = resolveProjectTarget(config.root) === "admin";
|
|
1938
|
+
hosts = resolveDevHosts(phase, mode, config.root);
|
|
1939
|
+
},
|
|
1940
|
+
resolveId(source) {
|
|
1941
|
+
if (!source.startsWith("@bstage-sdk/")) return null;
|
|
1942
|
+
try {
|
|
1943
|
+
const cjsPath = projectRequire.resolve(source);
|
|
1944
|
+
const pkgDir = findPackageDir(cjsPath);
|
|
1945
|
+
if (!pkgDir) return cjsPath;
|
|
1946
|
+
const pkg = JSON.parse(readFileSync2(join(pkgDir, "package.json"), "utf-8"));
|
|
1947
|
+
const entry = pkg.exports?.[subpathOf(source)];
|
|
1948
|
+
const esmEntry = (typeof entry === "string" ? entry : entry?.import?.default) ?? (subpathOf(source) === "." ? pkg.module : void 0);
|
|
1949
|
+
return esmEntry ? join(pkgDir, esmEntry) : cjsPath;
|
|
1950
|
+
} catch {
|
|
1951
|
+
return null;
|
|
1952
|
+
}
|
|
1953
|
+
},
|
|
1954
|
+
configureServer(server) {
|
|
1955
|
+
const httpServer = server.httpServer;
|
|
1956
|
+
if (httpServer) {
|
|
1957
|
+
httpServer.on("listening", () => {
|
|
1958
|
+
const addr = httpServer.address();
|
|
1959
|
+
if (addr && typeof addr === "object") {
|
|
1960
|
+
actualPort = addr.port;
|
|
1961
|
+
}
|
|
1962
|
+
});
|
|
1963
|
+
}
|
|
1964
|
+
server.middlewares.use((req, res, next) => {
|
|
1965
|
+
const url = req.url ?? "";
|
|
1966
|
+
if (url === LOGIN_PATH || url === `${LOGIN_PATH}/`) {
|
|
1967
|
+
res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
|
|
1968
|
+
res.end(getLoginPageHtml(phase, mode));
|
|
1969
|
+
return;
|
|
1970
|
+
}
|
|
1971
|
+
if (url.startsWith(`${PROXY_PATH_PREFIX}/${phase}/`)) {
|
|
1972
|
+
handleGatewayProxy(mode, phase, hosts, req, res);
|
|
1973
|
+
return;
|
|
1974
|
+
}
|
|
1975
|
+
if (url.startsWith(`${AUTH_PATH_PREFIX}/`)) {
|
|
1976
|
+
handleAuthProxy(mode, phase, hosts, req, res);
|
|
1977
|
+
return;
|
|
1978
|
+
}
|
|
1979
|
+
next();
|
|
1980
|
+
});
|
|
1981
|
+
},
|
|
1982
|
+
transformIndexHtml(_html, ctx) {
|
|
1983
|
+
const tags = [
|
|
1984
|
+
// dev 전용 로케일 스위처 주입 (useLocale 변경 감지 검증용)
|
|
1985
|
+
{
|
|
1986
|
+
tag: "script",
|
|
1987
|
+
attrs: { type: "text/javascript" },
|
|
1988
|
+
children: DEV_LOCALE_SWITCHER,
|
|
1989
|
+
injectTo: "head"
|
|
1990
|
+
},
|
|
1991
|
+
// 번역 사전 phase 주입 — core는 hostname으로 phase를 추론하는데 로컬 호스트에는
|
|
1992
|
+
// phase 마커가 없다(`localhost`, 로컬 별칭 호스트). dev 서버는 `--phase`를 아니까
|
|
1993
|
+
// 알려준다. core가 이 전역을 config 다음 우선순위로 읽는다(`resolvePhase`).
|
|
1994
|
+
{
|
|
1995
|
+
tag: "script",
|
|
1996
|
+
attrs: { type: "text/javascript" },
|
|
1997
|
+
children: `window.__bstage_i18n_phase__ = ${JSON.stringify(phase)}`,
|
|
1998
|
+
injectTo: "head"
|
|
1999
|
+
}
|
|
2000
|
+
];
|
|
2001
|
+
if (ctx?.server) {
|
|
2002
|
+
tags.push({
|
|
2003
|
+
tag: "style",
|
|
2004
|
+
attrs: { "data-bstage-design-fallback": isAdmin ? "admin" : "user" },
|
|
2005
|
+
children: isAdmin ? renderCss2() : renderCss(),
|
|
2006
|
+
injectTo: "head"
|
|
2007
|
+
});
|
|
2008
|
+
if (!isAdmin) {
|
|
2009
|
+
tags.push({
|
|
2010
|
+
tag: "script",
|
|
2011
|
+
attrs: { type: "text/javascript" },
|
|
2012
|
+
children: DEV_THEME_TOGGLE,
|
|
2013
|
+
injectTo: "body"
|
|
2014
|
+
});
|
|
2015
|
+
}
|
|
2016
|
+
}
|
|
2017
|
+
return tags;
|
|
2018
|
+
},
|
|
2019
|
+
transform(code, id) {
|
|
2020
|
+
if (!id.includes("bstage-core") && !id.includes("bstage-sdk/packages/core")) return null;
|
|
2021
|
+
if (!RESOLVE_BASE_URL_RE.test(code)) return null;
|
|
2022
|
+
const origin = `http://localhost:${actualPort ?? configPort}`;
|
|
2023
|
+
const proxyBase = `${origin}${PROXY_PATH_PREFIX}/${phase}${PHASE_PATH_PREFIX[phase] ?? ""}`;
|
|
2024
|
+
return {
|
|
2025
|
+
code: code.replace(
|
|
2026
|
+
RESOLVE_BASE_URL_RE,
|
|
2027
|
+
`function resolveBaseUrl() { return "${proxyBase}" }`
|
|
2028
|
+
),
|
|
2029
|
+
map: null
|
|
2030
|
+
};
|
|
2031
|
+
}
|
|
2032
|
+
};
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
// src/vite/preset.ts
|
|
2036
|
+
function createViteConfig(options = {}) {
|
|
2037
|
+
return defineConfig({
|
|
2038
|
+
plugins: [react()],
|
|
2039
|
+
define: {
|
|
2040
|
+
"process.env.NODE_ENV": JSON.stringify("production")
|
|
2041
|
+
},
|
|
2042
|
+
resolve: {
|
|
2043
|
+
dedupe: ["react", "react-dom", "react/jsx-runtime"]
|
|
2044
|
+
},
|
|
2045
|
+
build: {
|
|
2046
|
+
lib: {
|
|
2047
|
+
entry: options.entry ?? "src/index.tsx",
|
|
2048
|
+
formats: ["iife"],
|
|
2049
|
+
name: "BstageTemplate",
|
|
2050
|
+
fileName: () => "template.js"
|
|
2051
|
+
},
|
|
2052
|
+
cssCodeSplit: false,
|
|
2053
|
+
rollupOptions: {
|
|
2054
|
+
output: {
|
|
2055
|
+
inlineDynamicImports: true
|
|
2056
|
+
}
|
|
2057
|
+
},
|
|
2058
|
+
outDir: options.outDir ?? "dist",
|
|
2059
|
+
copyPublicDir: false
|
|
2060
|
+
}
|
|
2061
|
+
});
|
|
2062
|
+
}
|
|
2063
|
+
|
|
2064
|
+
export {
|
|
2065
|
+
LOGIN_PATH,
|
|
2066
|
+
TRANSLATION_LANGUAGES,
|
|
2067
|
+
DEFAULT_TRANSLATION_TIER,
|
|
2068
|
+
TRANSLATION_CDN_ORIGIN,
|
|
2069
|
+
TRANSLATION_CDN_BASE_KEY,
|
|
2070
|
+
TRANSLATION_CDN_BUCKET_PREFIX,
|
|
2071
|
+
resolveProjectTarget,
|
|
2072
|
+
resolvePhase,
|
|
2073
|
+
describePhase,
|
|
2074
|
+
bstageDevPlugin,
|
|
2075
|
+
createViteConfig
|
|
2076
|
+
};
|