connectbase-client 6.10.0 → 6.12.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/CHANGELOG.md +128 -0
- package/README.md +20 -1
- package/dist/cli.js +230 -35
- package/dist/connect-base.umd.js +5 -5
- package/dist/index.d.mts +410 -75
- package/dist/index.d.ts +410 -75
- package/dist/index.js +11213 -10261
- package/dist/index.mjs +11213 -10261
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -31,12 +31,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
31
31
|
// src/cli.ts
|
|
32
32
|
var cli_exports = {};
|
|
33
33
|
__export(cli_exports, {
|
|
34
|
+
DEPLOY_REQUEST_BUDGET_BYTES: () => DEPLOY_REQUEST_BUDGET_BYTES,
|
|
34
35
|
TunnelConnectSelector: () => TunnelConnectSelector,
|
|
35
36
|
ancestorCommandLines: () => ancestorCommandLines,
|
|
36
37
|
apiErrorMessage: () => apiErrorMessage,
|
|
38
|
+
browserAuthStartBody: () => browserAuthStartBody,
|
|
39
|
+
browserAuthUrl: () => browserAuthUrl,
|
|
40
|
+
browserOpenCommand: () => browserOpenCommand,
|
|
37
41
|
buildFirstHint: () => buildFirstHint,
|
|
38
42
|
collectDeployFiles: () => collectDeployFiles,
|
|
39
43
|
computeDeployDiff: () => computeDeployDiff,
|
|
44
|
+
decideBaseUrl: () => decideBaseUrl,
|
|
45
|
+
describeBaseUrl: () => describeBaseUrl,
|
|
40
46
|
detectPackageManager: () => detectPackageManager,
|
|
41
47
|
formatSkippedFilesReport: () => formatSkippedFilesReport,
|
|
42
48
|
getTunnelConnectCandidates: () => getTunnelConnectCandidates,
|
|
@@ -44,21 +50,28 @@ __export(cli_exports, {
|
|
|
44
50
|
isAllowedDeployExt: () => isAllowedDeployExt,
|
|
45
51
|
isBinaryDeployExt: () => isBinaryDeployExt,
|
|
46
52
|
isExtensionlessDataFile: () => isExtensionlessDataFile,
|
|
53
|
+
isOutsideProject: () => isOutsideProject,
|
|
54
|
+
isPlatformBaseUrl: () => isPlatformBaseUrl,
|
|
55
|
+
loadConfig: () => loadConfig,
|
|
47
56
|
makeRequest: () => makeRequest,
|
|
48
57
|
normalizeRelativePath: () => normalizeRelativePath,
|
|
58
|
+
openBrowser: () => openBrowser,
|
|
49
59
|
packageManagerCommands: () => packageManagerCommands,
|
|
50
60
|
packageScriptInvocationPattern: () => packageScriptInvocationPattern,
|
|
51
61
|
parseArgs: () => parseArgs,
|
|
52
62
|
registerEndpointBinding: () => registerEndpointBinding,
|
|
53
63
|
runningInsidePackageScript: () => runningInsidePackageScript,
|
|
64
|
+
selectBinariesToOffload: () => selectBinariesToOffload,
|
|
54
65
|
sha256Hex: () => sha256Hex,
|
|
55
|
-
storageAdminHeaders: () => storageAdminHeaders
|
|
66
|
+
storageAdminHeaders: () => storageAdminHeaders,
|
|
67
|
+
writeSecretFile: () => writeSecretFile
|
|
56
68
|
});
|
|
57
69
|
module.exports = __toCommonJS(cli_exports);
|
|
58
70
|
var crypto = __toESM(require("crypto"));
|
|
59
71
|
var fs2 = __toESM(require("fs"));
|
|
60
72
|
var http = __toESM(require("http"));
|
|
61
73
|
var https = __toESM(require("https"));
|
|
74
|
+
var os2 = __toESM(require("os"));
|
|
62
75
|
var path2 = __toESM(require("path"));
|
|
63
76
|
var readline = __toESM(require("readline"));
|
|
64
77
|
|
|
@@ -157,7 +170,7 @@ function handleTunnelError(msg, appId, localPort) {
|
|
|
157
170
|
}
|
|
158
171
|
|
|
159
172
|
// src/cli.ts
|
|
160
|
-
var VERSION = "6.
|
|
173
|
+
var VERSION = "6.12.0" ? "6.12.0" : getPackageVersion();
|
|
161
174
|
var DEFAULT_BASE_URL = "https://api.connectbase.world";
|
|
162
175
|
var colors = {
|
|
163
176
|
reset: "\x1B[0m",
|
|
@@ -315,6 +328,32 @@ function isExtensionlessDataFile(filePath) {
|
|
|
315
328
|
return path2.extname(base) === "" && !ALLOWED_EXTENSIONLESS_FILES.has(base);
|
|
316
329
|
}
|
|
317
330
|
var WEB_FILE_MAX_STORED_BYTES = 6 * 1024 * 1024 - 64 * 1024;
|
|
331
|
+
var DEPLOY_REQUEST_BUDGET_BYTES = 96 * 1024 * 1024;
|
|
332
|
+
function deployEntryBytes(f) {
|
|
333
|
+
return Buffer.byteLength(f.content, "utf8") + Buffer.byteLength(f.path, "utf8") + 256;
|
|
334
|
+
}
|
|
335
|
+
function selectBinariesToOffload(upsert, perFileLimit = WEB_FILE_MAX_STORED_BYTES, budget = DEPLOY_REQUEST_BUDGET_BYTES) {
|
|
336
|
+
const offload = new Set(
|
|
337
|
+
upsert.filter(
|
|
338
|
+
(f) => f.is_binary && Buffer.byteLength(f.content, "utf8") > perFileLimit
|
|
339
|
+
)
|
|
340
|
+
);
|
|
341
|
+
let inlineBytes = upsert.reduce(
|
|
342
|
+
(sum, f) => offload.has(f) ? sum : sum + deployEntryBytes(f),
|
|
343
|
+
0
|
|
344
|
+
);
|
|
345
|
+
if (inlineBytes > budget) {
|
|
346
|
+
const rest = upsert.filter((f) => f.is_binary && !offload.has(f)).sort(
|
|
347
|
+
(a, b) => Buffer.byteLength(b.content, "utf8") - Buffer.byteLength(a.content, "utf8")
|
|
348
|
+
);
|
|
349
|
+
for (const f of rest) {
|
|
350
|
+
if (inlineBytes <= budget) break;
|
|
351
|
+
offload.add(f);
|
|
352
|
+
inlineBytes -= deployEntryBytes(f);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return { offload: upsert.filter((f) => offload.has(f)), inlineBytes };
|
|
356
|
+
}
|
|
318
357
|
function sha256Hex(value) {
|
|
319
358
|
return crypto.createHash("sha256").update(value, "utf8").digest("hex");
|
|
320
359
|
}
|
|
@@ -359,11 +398,13 @@ function reportDeployAuthError(status, data) {
|
|
|
359
398
|
return true;
|
|
360
399
|
}
|
|
361
400
|
function loadConfig() {
|
|
401
|
+
const envBaseUrl = process.env.CONNECTBASE_BASE_URL;
|
|
362
402
|
const config = {
|
|
363
403
|
publicKey: process.env.CONNECTBASE_PUBLIC_KEY,
|
|
364
404
|
secretKey: process.env.CONNECTBASE_SECRET_KEY,
|
|
365
405
|
storageId: process.env.CONNECTBASE_STORAGE_ID,
|
|
366
|
-
baseUrl:
|
|
406
|
+
baseUrl: envBaseUrl || DEFAULT_BASE_URL,
|
|
407
|
+
baseUrlFromRepo: false
|
|
367
408
|
};
|
|
368
409
|
const rcPath = path2.join(process.cwd(), ".connectbaserc");
|
|
369
410
|
if (fs2.existsSync(rcPath)) {
|
|
@@ -372,7 +413,10 @@ function loadConfig() {
|
|
|
372
413
|
if (rcContent.publicKey) config.publicKey = rcContent.publicKey;
|
|
373
414
|
if (rcContent.secretKey) config.secretKey = rcContent.secretKey;
|
|
374
415
|
if (rcContent.storageId) config.storageId = rcContent.storageId;
|
|
375
|
-
if (rcContent.baseUrl
|
|
416
|
+
if (!envBaseUrl && rcContent.baseUrl && typeof rcContent.baseUrl === "string") {
|
|
417
|
+
config.baseUrl = rcContent.baseUrl;
|
|
418
|
+
config.baseUrlFromRepo = true;
|
|
419
|
+
}
|
|
376
420
|
if (rcContent.deployDir) config.deployDir = rcContent.deployDir;
|
|
377
421
|
if (rcContent.includeExtensionless === true)
|
|
378
422
|
config.includeExtensionless = true;
|
|
@@ -573,12 +617,9 @@ function putToPresignedUrl(uploadUrl, body, contentType, timeoutMs) {
|
|
|
573
617
|
});
|
|
574
618
|
}
|
|
575
619
|
async function offloadLargeBinaries(baseStorageUrl, headers, diff, _envLabel, timeoutMs) {
|
|
576
|
-
const
|
|
577
|
-
(f) => Buffer.byteLength(f.content, "utf8") > WEB_FILE_MAX_STORED_BYTES
|
|
620
|
+
const largeText = diff.upsert.filter(
|
|
621
|
+
(f) => !f.is_binary && Buffer.byteLength(f.content, "utf8") > WEB_FILE_MAX_STORED_BYTES
|
|
578
622
|
);
|
|
579
|
-
if (oversized.length === 0) return;
|
|
580
|
-
const largeText = oversized.filter((f) => !f.is_binary);
|
|
581
|
-
const largeBinaries = oversized.filter((f) => f.is_binary);
|
|
582
623
|
if (largeText.length > 0) {
|
|
583
624
|
error(
|
|
584
625
|
`\uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0 \uD30C\uC77C\uB2F9 \uD06C\uAE30 \uD55C\uB3C4(\uC57D ${formatSize(WEB_FILE_MAX_STORED_BYTES)})\uB97C \uCD08\uACFC\uD55C \uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC774 \uC788\uC5B4 \uBC30\uD3EC\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4:`
|
|
@@ -593,6 +634,18 @@ async function offloadLargeBinaries(baseStorageUrl, headers, diff, _envLabel, ti
|
|
|
593
634
|
);
|
|
594
635
|
process.exit(1);
|
|
595
636
|
}
|
|
637
|
+
const { offload: largeBinaries, inlineBytes } = selectBinariesToOffload(
|
|
638
|
+
diff.upsert
|
|
639
|
+
);
|
|
640
|
+
if (inlineBytes > DEPLOY_REQUEST_BUDGET_BYTES) {
|
|
641
|
+
error(
|
|
642
|
+
`\uD14D\uC2A4\uD2B8 \uD30C\uC77C\uB9CC\uC73C\uB85C \uBC30\uD3EC \uC694\uCCAD \uD55C\uB3C4(\uC57D ${formatSize(DEPLOY_REQUEST_BUDGET_BYTES)})\uB97C \uB118\uC2B5\uB2C8\uB2E4. \uD14D\uC2A4\uD2B8\uB294 \uC9C1\uC811 \uC5C5\uB85C\uB4DC\uB85C \uB3CC\uB9B4 \uC218 \uC5C6\uC5B4\uC694.`
|
|
643
|
+
);
|
|
644
|
+
warn(
|
|
645
|
+
"\uBCC0\uACBD\uD55C \uD14D\uC2A4\uD2B8 \uD30C\uC77C\uC744 \uB098\uB220 \uC5EC\uB7EC \uBC88 \uBC30\uD3EC\uD558\uAC70\uB098, \uD070 \uB370\uC774\uD130 \uD30C\uC77C\uC740 \uD30C\uC77C \uC2A4\uD1A0\uB9AC\uC9C0(cb.storage)\uB85C \uC62E\uAE30\uC138\uC694."
|
|
646
|
+
);
|
|
647
|
+
process.exit(1);
|
|
648
|
+
}
|
|
596
649
|
if (largeBinaries.length === 0) return;
|
|
597
650
|
const presignFiles = largeBinaries.map((f) => ({
|
|
598
651
|
path: f.path,
|
|
@@ -632,7 +685,7 @@ async function offloadLargeBinaries(baseStorageUrl, headers, diff, _envLabel, ti
|
|
|
632
685
|
}
|
|
633
686
|
const entryByPath = new Map(presigned.map((p) => [p.path, p]));
|
|
634
687
|
info(
|
|
635
|
-
`\
|
|
688
|
+
`\uBC14\uC774\uB108\uB9AC ${largeBinaries.length}\uAC1C\uB97C Object Storage \uB85C \uC9C1\uC811 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4(\uD30C\uC77C\uB2F9 \uD55C\uB3C4 \uCD08\uACFC\uC774\uAC70\uB098 \uC694\uCCAD \uD558\uB098\uAC00 \uC57D ${formatSize(DEPLOY_REQUEST_BUDGET_BYTES)} \uB97C \uB118\uC5B4\uC11C)...`
|
|
636
689
|
);
|
|
637
690
|
for (const f of largeBinaries) {
|
|
638
691
|
const entry = entryByPath.get(f.path);
|
|
@@ -1197,26 +1250,59 @@ function getProjectRoot() {
|
|
|
1197
1250
|
function consoleUrlFor(baseUrl) {
|
|
1198
1251
|
return baseUrl.replace("api.", "");
|
|
1199
1252
|
}
|
|
1200
|
-
function
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1253
|
+
function browserOpenCommand(url, platform2 = process.platform) {
|
|
1254
|
+
let target;
|
|
1255
|
+
try {
|
|
1256
|
+
const parsed = new URL(url);
|
|
1257
|
+
if (parsed.protocol !== "https:" && parsed.protocol !== "http:") {
|
|
1258
|
+
return null;
|
|
1259
|
+
}
|
|
1260
|
+
target = parsed.toString();
|
|
1261
|
+
} catch {
|
|
1262
|
+
return null;
|
|
1263
|
+
}
|
|
1264
|
+
if (platform2 === "darwin") return { command: "open", args: [target] };
|
|
1265
|
+
if (platform2 === "win32") {
|
|
1266
|
+
return {
|
|
1267
|
+
command: "rundll32",
|
|
1268
|
+
args: ["url.dll,FileProtocolHandler", target]
|
|
1269
|
+
};
|
|
1210
1270
|
}
|
|
1211
|
-
|
|
1271
|
+
return { command: "xdg-open", args: [target] };
|
|
1272
|
+
}
|
|
1273
|
+
function openBrowser(url) {
|
|
1274
|
+
const opener = browserOpenCommand(url);
|
|
1275
|
+
if (!opener) return;
|
|
1276
|
+
const { spawn } = require("child_process");
|
|
1277
|
+
const child = spawn(opener.command, opener.args, {
|
|
1278
|
+
stdio: "ignore",
|
|
1279
|
+
detached: true
|
|
1280
|
+
});
|
|
1281
|
+
child.on("error", () => {
|
|
1212
1282
|
});
|
|
1283
|
+
child.unref();
|
|
1284
|
+
}
|
|
1285
|
+
function browserAuthStartBody() {
|
|
1286
|
+
return {
|
|
1287
|
+
flow: "user_code",
|
|
1288
|
+
hostname: os2.hostname(),
|
|
1289
|
+
os: `${process.platform} ${process.arch}`,
|
|
1290
|
+
cli_version: VERSION
|
|
1291
|
+
};
|
|
1292
|
+
}
|
|
1293
|
+
function browserAuthUrl(baseUrl, start) {
|
|
1294
|
+
if (!start.user_code) {
|
|
1295
|
+
return `${consoleUrlFor(baseUrl)}/auth/cli-auth?session=${start.session_id}`;
|
|
1296
|
+
}
|
|
1297
|
+
return `${consoleUrlFor(baseUrl)}/auth/cli-auth`;
|
|
1213
1298
|
}
|
|
1214
1299
|
async function browserAuthFlow(baseUrl = DEFAULT_BASE_URL) {
|
|
1215
1300
|
info("\uBE0C\uB77C\uC6B0\uC800 \uC778\uC99D \uC138\uC158\uC744 \uC2DC\uC791\uD569\uB2C8\uB2E4...");
|
|
1216
1301
|
const startRes = await makeRequest(
|
|
1217
1302
|
`${baseUrl}/v1/public/cli-auth/start`,
|
|
1218
1303
|
"POST",
|
|
1219
|
-
{}
|
|
1304
|
+
{},
|
|
1305
|
+
JSON.stringify(browserAuthStartBody())
|
|
1220
1306
|
);
|
|
1221
1307
|
if (startRes.status !== 200) {
|
|
1222
1308
|
error(
|
|
@@ -1224,15 +1310,28 @@ async function browserAuthFlow(baseUrl = DEFAULT_BASE_URL) {
|
|
|
1224
1310
|
);
|
|
1225
1311
|
process.exit(1);
|
|
1226
1312
|
}
|
|
1227
|
-
const
|
|
1228
|
-
const
|
|
1313
|
+
const start = startRes.data;
|
|
1314
|
+
const { session_id } = start;
|
|
1315
|
+
const authUrl = browserAuthUrl(baseUrl, start);
|
|
1229
1316
|
log(`
|
|
1230
1317
|
${colors.cyan}\uBE0C\uB77C\uC6B0\uC800\uC5D0\uC11C \uB85C\uADF8\uC778\uD558\uC138\uC694:${colors.reset}`);
|
|
1231
1318
|
log(`${colors.dim}${authUrl}${colors.reset}
|
|
1232
1319
|
`);
|
|
1320
|
+
if (start.user_code) {
|
|
1321
|
+
log(`${colors.cyan}\uBE0C\uB77C\uC6B0\uC800\uC5D0 \uC774 \uCF54\uB4DC\uB97C \uC785\uB825\uD558\uC138\uC694:${colors.reset}`);
|
|
1322
|
+
log(`
|
|
1323
|
+
${colors.green}${start.user_code}${colors.reset}
|
|
1324
|
+
`);
|
|
1325
|
+
log(
|
|
1326
|
+
`${colors.dim}\uC774 \uBA85\uB839\uC744 \uC9C1\uC811 \uC2E4\uD589\uD558\uC9C0 \uC54A\uC558\uB2E4\uBA74 \uC2B9\uC778\uD558\uC9C0 \uB9C8\uC138\uC694.${colors.reset}
|
|
1327
|
+
`
|
|
1328
|
+
);
|
|
1329
|
+
}
|
|
1233
1330
|
openBrowser(authUrl);
|
|
1234
|
-
const pollInterval =
|
|
1235
|
-
const maxAttempts =
|
|
1331
|
+
const pollInterval = (start.interval ?? 3) * 1e3;
|
|
1332
|
+
const maxAttempts = Math.ceil(
|
|
1333
|
+
(start.expires_in ?? 300) * 1e3 / pollInterval
|
|
1334
|
+
);
|
|
1236
1335
|
let attempts = 0;
|
|
1237
1336
|
let consecutive404 = 0;
|
|
1238
1337
|
const max404Retries = 5;
|
|
@@ -1346,7 +1445,7 @@ function saveSecretKeyToRc(secretKey, dir = process.cwd()) {
|
|
|
1346
1445
|
}
|
|
1347
1446
|
}
|
|
1348
1447
|
rcData.secretKey = secretKey;
|
|
1349
|
-
|
|
1448
|
+
writeSecretFile(rcPath, `${JSON.stringify(rcData, null, 2)}
|
|
1350
1449
|
`);
|
|
1351
1450
|
}
|
|
1352
1451
|
async function fetchAppsWithSecretKey(baseUrl, secretKey) {
|
|
@@ -1679,7 +1778,7 @@ ${colors.blue}?${colors.reset} \uC120\uD0DD (\uBC88\uD638): `
|
|
|
1679
1778
|
if (secretKey) {
|
|
1680
1779
|
rcData.secretKey = secretKey;
|
|
1681
1780
|
}
|
|
1682
|
-
|
|
1781
|
+
writeSecretFile(rcPath, `${JSON.stringify(rcData, null, 2)}
|
|
1683
1782
|
`);
|
|
1684
1783
|
success(".connectbaserc \uC0DD\uC131 \uC644\uB8CC");
|
|
1685
1784
|
addToGitignore(".connectbaserc");
|
|
@@ -1723,6 +1822,13 @@ function detectBuildDir() {
|
|
|
1723
1822
|
return "./dist";
|
|
1724
1823
|
return "./dist";
|
|
1725
1824
|
}
|
|
1825
|
+
function writeSecretFile(filePath, content) {
|
|
1826
|
+
try {
|
|
1827
|
+
if (fs2.existsSync(filePath)) fs2.chmodSync(filePath, 384);
|
|
1828
|
+
} catch {
|
|
1829
|
+
}
|
|
1830
|
+
fs2.writeFileSync(filePath, content, { mode: 384 });
|
|
1831
|
+
}
|
|
1726
1832
|
function addToGitignore(entry, basePath) {
|
|
1727
1833
|
const dir = basePath || process.cwd();
|
|
1728
1834
|
const gitignorePath = path2.join(dir, ".gitignore");
|
|
@@ -2248,12 +2354,16 @@ async function setupMcp(secretKey, baseUrl = DEFAULT_BASE_URL) {
|
|
|
2248
2354
|
} catch {
|
|
2249
2355
|
const backupPath = `${mcpConfigPath}.backup`;
|
|
2250
2356
|
fs2.copyFileSync(mcpConfigPath, backupPath);
|
|
2357
|
+
try {
|
|
2358
|
+
fs2.chmodSync(backupPath, 384);
|
|
2359
|
+
} catch {
|
|
2360
|
+
}
|
|
2251
2361
|
warn(`.mcp.json \uD30C\uC2F1 \uC2E4\uD328, \uBC31\uC5C5 \uC0DD\uC131: ${backupPath}`);
|
|
2252
2362
|
mcpConfig = { mcpServers: {} };
|
|
2253
2363
|
}
|
|
2254
2364
|
}
|
|
2255
2365
|
mcpConfig.mcpServers["connect-base"] = mcpEntry;
|
|
2256
|
-
|
|
2366
|
+
writeSecretFile(mcpConfigPath, `${JSON.stringify(mcpConfig, null, 2)}
|
|
2257
2367
|
`);
|
|
2258
2368
|
success(`${mcpConfigPath} \uC0DD\uC131 \uC644\uB8CC`);
|
|
2259
2369
|
addToGitignore(".mcp.json", root);
|
|
@@ -2422,7 +2532,7 @@ ${colors.cyan}ConnectBase Update${colors.reset}
|
|
|
2422
2532
|
headers: { Authorization: `Bearer ${secretKey}` }
|
|
2423
2533
|
};
|
|
2424
2534
|
mcpConfig.mcpServers = servers;
|
|
2425
|
-
|
|
2535
|
+
writeSecretFile(
|
|
2426
2536
|
mcpConfigPath,
|
|
2427
2537
|
`${JSON.stringify(mcpConfig, null, 2)}
|
|
2428
2538
|
`
|
|
@@ -2973,7 +3083,7 @@ async function startTunnel(port, config, tunnelOpts) {
|
|
|
2973
3083
|
}
|
|
2974
3084
|
}
|
|
2975
3085
|
rcData.secretKey = sk;
|
|
2976
|
-
|
|
3086
|
+
writeSecretFile(rcPath2, `${JSON.stringify(rcData, null, 2)}
|
|
2977
3087
|
`);
|
|
2978
3088
|
addToGitignore(".connectbaserc");
|
|
2979
3089
|
success("Secret Key \uBC1C\uAE09 \uBC0F \uC800\uC7A5 \uC644\uB8CC");
|
|
@@ -3007,7 +3117,7 @@ async function startTunnel(port, config, tunnelOpts) {
|
|
|
3007
3117
|
}
|
|
3008
3118
|
if (rcData.tunnelAppId !== appId) {
|
|
3009
3119
|
rcData.tunnelAppId = appId;
|
|
3010
|
-
|
|
3120
|
+
writeSecretFile(rcPath, `${JSON.stringify(rcData, null, 2)}
|
|
3011
3121
|
`);
|
|
3012
3122
|
}
|
|
3013
3123
|
} catch {
|
|
@@ -3688,6 +3798,7 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
|
|
|
3688
3798
|
-s, --storage <id> \uC2A4\uD1A0\uB9AC\uC9C0 ID
|
|
3689
3799
|
-k, --public-key <key> API Key
|
|
3690
3800
|
-u, --base-url <url> \uC11C\uBC84 URL (\uAE30\uBCF8: ${DEFAULT_BASE_URL})
|
|
3801
|
+
--allow-repo-base-url .connectbaserc \uC758 \uBE44\uACF5\uC2DD \uC11C\uBC84 URL \uC744 \uD655\uC778 \uC5C6\uC774 \uD5C8\uC6A9 (Secret Key \uAC00 \uADF8 \uC11C\uBC84\uB85C \uC804\uC1A1\uB428)
|
|
3691
3802
|
-t, --timeout <sec> \uC694\uCCAD \uD0C0\uC784\uC544\uC6C3 (\uCD08, tunnel/deploy \uACF5\uD1B5. deploy \uBBF8\uC9C0\uC815 \uC2DC \uD30C\uC77C \uD06C\uAE30\uC5D0 \uB530\uB77C \uC790\uB3D9 \uC0B0\uC815)
|
|
3692
3803
|
--max-body <MB> \uD130\uB110 \uCD5C\uB300 \uBC14\uB514 \uD06C\uAE30 (MB, tunnel \uC804\uC6A9)
|
|
3693
3804
|
--force \uD130\uB110 lockfile \uBB34\uC2DC (\uC911\uBCF5 \uC2E4\uD589 \uAC15\uC81C, tunnel \uC804\uC6A9)
|
|
@@ -3748,7 +3859,7 @@ ${colors.yellow}\uD658\uACBD\uBCC0\uC218:${colors.reset}
|
|
|
3748
3859
|
CONNECTBASE_SECRET_KEY Secret Key (cb_sk_*) \u2014 \uBC30\uD3EC/\uC2B9\uACA9/\uD130\uB110\uC5D0 \uD544\uC218
|
|
3749
3860
|
CONNECTBASE_PUBLIC_KEY (deprecated) \uB808\uAC70\uC2DC \u2014 publicKey \uB610\uB294 secretKey \uB85C \uC0AC\uC6A9
|
|
3750
3861
|
CONNECTBASE_STORAGE_ID \uC2A4\uD1A0\uB9AC\uC9C0 ID
|
|
3751
|
-
CONNECTBASE_BASE_URL \uC11C\uBC84 URL
|
|
3862
|
+
CONNECTBASE_BASE_URL \uC11C\uBC84 URL (.connectbaserc \uBCF4\uB2E4 \uC6B0\uC120)
|
|
3752
3863
|
|
|
3753
3864
|
${colors.yellow}\uC124\uC815 \uD30C\uC77C (.connectbaserc):${colors.reset}
|
|
3754
3865
|
{
|
|
@@ -3760,6 +3871,65 @@ ${colors.yellow}\uC124\uC815 \uD30C\uC77C (.connectbaserc):${colors.reset}
|
|
|
3760
3871
|
}
|
|
3761
3872
|
`);
|
|
3762
3873
|
}
|
|
3874
|
+
var PLATFORM_API_HOST = new URL(DEFAULT_BASE_URL).host;
|
|
3875
|
+
var LOCAL_HOSTNAMES = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "[::1]"]);
|
|
3876
|
+
function isPlatformBaseUrl(baseUrl) {
|
|
3877
|
+
try {
|
|
3878
|
+
const url = new URL(baseUrl);
|
|
3879
|
+
if (url.protocol === "https:" && url.host === PLATFORM_API_HOST) {
|
|
3880
|
+
return true;
|
|
3881
|
+
}
|
|
3882
|
+
return (url.protocol === "http:" || url.protocol === "https:") && LOCAL_HOSTNAMES.has(url.hostname);
|
|
3883
|
+
} catch {
|
|
3884
|
+
return false;
|
|
3885
|
+
}
|
|
3886
|
+
}
|
|
3887
|
+
function describeBaseUrl(baseUrl) {
|
|
3888
|
+
try {
|
|
3889
|
+
return new URL(baseUrl).origin;
|
|
3890
|
+
} catch {
|
|
3891
|
+
return JSON.stringify(baseUrl);
|
|
3892
|
+
}
|
|
3893
|
+
}
|
|
3894
|
+
function decideBaseUrl(opts) {
|
|
3895
|
+
if (isPlatformBaseUrl(opts.baseUrl)) return "proceed";
|
|
3896
|
+
if (!opts.fromRepoConfig || opts.allowRepoBaseUrl) return "notice";
|
|
3897
|
+
return opts.interactive ? "confirm" : "refuse";
|
|
3898
|
+
}
|
|
3899
|
+
async function enforceBaseUrlPolicy(baseUrl, opts) {
|
|
3900
|
+
const decision = decideBaseUrl({
|
|
3901
|
+
baseUrl,
|
|
3902
|
+
...opts,
|
|
3903
|
+
interactive: process.stdin.isTTY === true
|
|
3904
|
+
});
|
|
3905
|
+
if (decision === "proceed") return;
|
|
3906
|
+
const target = describeBaseUrl(baseUrl);
|
|
3907
|
+
if (decision === "notice") {
|
|
3908
|
+
warn(
|
|
3909
|
+
`\uC11C\uBC84 URL \uC774 ConnectBase \uACF5\uC2DD \uC8FC\uC18C\uAC00 \uC544\uB2D9\uB2C8\uB2E4: ${target}. Secret Key \uB97C \uD3EC\uD568\uD55C \uC790\uACA9\uC99D\uBA85\uC774 \uC774 \uC11C\uBC84\uB85C \uC804\uC1A1\uB429\uB2C8\uB2E4.`
|
|
3910
|
+
);
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
warn(`\uC774 \uC800\uC7A5\uC18C\uC758 .connectbaserc \uAC00 \uC11C\uBC84 URL \uC744 ${target} \uB85C \uC9C0\uC815\uD569\uB2C8\uB2E4.`);
|
|
3914
|
+
log(
|
|
3915
|
+
" \uACC4\uC18D\uD558\uBA74 Secret Key(CONNECTBASE_SECRET_KEY \uD3EC\uD568)\uAC00 \uC774 \uC11C\uBC84\uB85C \uC804\uC1A1\uB429\uB2C8\uB2E4. \uBC1B\uC740 \uC800\uC7A5\uC18C\uB77C\uBA74 \uC911\uB2E8\uD558\uC138\uC694."
|
|
3916
|
+
);
|
|
3917
|
+
if (decision === "confirm") {
|
|
3918
|
+
const answer = await prompt(` ${target} \uB85C \uACC4\uC18D\uD560\uAE4C\uC694? (y/N): `);
|
|
3919
|
+
if (answer.toLowerCase() === "y") return;
|
|
3920
|
+
error("\uC911\uB2E8\uD588\uC2B5\uB2C8\uB2E4.");
|
|
3921
|
+
process.exit(1);
|
|
3922
|
+
}
|
|
3923
|
+
error("\uBE44\uB300\uD654\uD615 \uD658\uACBD\uC774\uB77C \uD655\uC778\uD560 \uC218 \uC5C6\uC5B4 \uC911\uB2E8\uD569\uB2C8\uB2E4.");
|
|
3924
|
+
log(
|
|
3925
|
+
` \uC774 \uC11C\uBC84\uAC00 \uB9DE\uB2E4\uBA74 ${colors.cyan}--allow-repo-base-url${colors.reset} \uB97C \uBD99\uC774\uAC70\uB098 ${colors.cyan}--base-url${colors.reset}, ${colors.cyan}CONNECTBASE_BASE_URL${colors.reset} \uB85C \uC9C1\uC811 \uC9C0\uC815\uD558\uC138\uC694.`
|
|
3926
|
+
);
|
|
3927
|
+
process.exit(1);
|
|
3928
|
+
}
|
|
3929
|
+
function isOutsideProject(dir, root) {
|
|
3930
|
+
const relative2 = path2.relative(path2.resolve(root), path2.resolve(root, dir));
|
|
3931
|
+
return relative2 === ".." || relative2.startsWith(`..${path2.sep}`) || path2.isAbsolute(relative2);
|
|
3932
|
+
}
|
|
3763
3933
|
function parseArgs(args) {
|
|
3764
3934
|
const result = {
|
|
3765
3935
|
options: {},
|
|
@@ -3776,6 +3946,8 @@ function parseArgs(args) {
|
|
|
3776
3946
|
result.options.secretKey = args[++i];
|
|
3777
3947
|
} else if (arg === "-u" || arg === "--base-url") {
|
|
3778
3948
|
result.options.baseUrl = args[++i];
|
|
3949
|
+
} else if (arg === "--allow-repo-base-url") {
|
|
3950
|
+
result.options.allowRepoBaseUrl = "true";
|
|
3779
3951
|
} else if (arg === "-t" || arg === "--timeout") {
|
|
3780
3952
|
result.options.timeout = args[++i];
|
|
3781
3953
|
} else if (arg === "--max-body") {
|
|
@@ -3840,8 +4012,12 @@ async function main() {
|
|
|
3840
4012
|
publicKey: parsed.options.publicKey || fileConfig.publicKey,
|
|
3841
4013
|
secretKey: parsed.options.secretKey || fileConfig.secretKey,
|
|
3842
4014
|
storageId: parsed.options.storageId || fileConfig.storageId,
|
|
3843
|
-
baseUrl: parsed.options.baseUrl || fileConfig.baseUrl
|
|
4015
|
+
baseUrl: parsed.options.baseUrl || fileConfig.baseUrl
|
|
3844
4016
|
};
|
|
4017
|
+
await enforceBaseUrlPolicy(config.baseUrl, {
|
|
4018
|
+
fromRepoConfig: !parsed.options.baseUrl && fileConfig.baseUrlFromRepo,
|
|
4019
|
+
allowRepoBaseUrl: parsed.options.allowRepoBaseUrl === "true"
|
|
4020
|
+
});
|
|
3845
4021
|
if (parsed.command === "init") {
|
|
3846
4022
|
await init(config, {
|
|
3847
4023
|
yes: parsed.options.yes === "true",
|
|
@@ -3863,6 +4039,13 @@ async function main() {
|
|
|
3863
4039
|
await setupMcp(config.secretKey, config.baseUrl);
|
|
3864
4040
|
} else if (parsed.command === "deploy") {
|
|
3865
4041
|
const directory = parsed.args[0] || fileConfig.deployDir || ".";
|
|
4042
|
+
if (!parsed.args[0] && fileConfig.deployDir && isOutsideProject(fileConfig.deployDir, getProjectRoot())) {
|
|
4043
|
+
error(
|
|
4044
|
+
`.connectbaserc \uC758 deployDir \uC774 \uD504\uB85C\uC81D\uD2B8 \uBC16\uC744 \uAC00\uB9AC\uCF1C \uBC30\uD3EC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: ${JSON.stringify(fileConfig.deployDir)}`
|
|
4045
|
+
);
|
|
4046
|
+
log(" \uC774 \uD3F4\uB354\uAC00 \uB9DE\uB2E4\uBA74 \uBA85\uB839\uC904\uC5D0\uC11C \uC9C1\uC811 \uC9C0\uC815\uD558\uC138\uC694: deploy <\uD3F4\uB354>");
|
|
4047
|
+
process.exit(1);
|
|
4048
|
+
}
|
|
3866
4049
|
if (!config.publicKey) {
|
|
3867
4050
|
error(
|
|
3868
4051
|
'Public Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase-client init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -k \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694'
|
|
@@ -3981,12 +4164,18 @@ main().catch((err) => {
|
|
|
3981
4164
|
});
|
|
3982
4165
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3983
4166
|
0 && (module.exports = {
|
|
4167
|
+
DEPLOY_REQUEST_BUDGET_BYTES,
|
|
3984
4168
|
TunnelConnectSelector,
|
|
3985
4169
|
ancestorCommandLines,
|
|
3986
4170
|
apiErrorMessage,
|
|
4171
|
+
browserAuthStartBody,
|
|
4172
|
+
browserAuthUrl,
|
|
4173
|
+
browserOpenCommand,
|
|
3987
4174
|
buildFirstHint,
|
|
3988
4175
|
collectDeployFiles,
|
|
3989
4176
|
computeDeployDiff,
|
|
4177
|
+
decideBaseUrl,
|
|
4178
|
+
describeBaseUrl,
|
|
3990
4179
|
detectPackageManager,
|
|
3991
4180
|
formatSkippedFilesReport,
|
|
3992
4181
|
getTunnelConnectCandidates,
|
|
@@ -3994,13 +4183,19 @@ main().catch((err) => {
|
|
|
3994
4183
|
isAllowedDeployExt,
|
|
3995
4184
|
isBinaryDeployExt,
|
|
3996
4185
|
isExtensionlessDataFile,
|
|
4186
|
+
isOutsideProject,
|
|
4187
|
+
isPlatformBaseUrl,
|
|
4188
|
+
loadConfig,
|
|
3997
4189
|
makeRequest,
|
|
3998
4190
|
normalizeRelativePath,
|
|
4191
|
+
openBrowser,
|
|
3999
4192
|
packageManagerCommands,
|
|
4000
4193
|
packageScriptInvocationPattern,
|
|
4001
4194
|
parseArgs,
|
|
4002
4195
|
registerEndpointBinding,
|
|
4003
4196
|
runningInsidePackageScript,
|
|
4197
|
+
selectBinariesToOffload,
|
|
4004
4198
|
sha256Hex,
|
|
4005
|
-
storageAdminHeaders
|
|
4199
|
+
storageAdminHeaders,
|
|
4200
|
+
writeSecretFile
|
|
4006
4201
|
});
|