connectbase-client 3.52.0 → 3.53.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 +17 -0
- package/dist/cli.js +38 -109
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,23 @@
|
|
|
3
3
|
본 SDK 의 모든 주요 변경사항을 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) 형식으로 기록합니다.
|
|
4
4
|
버전은 [Semantic Versioning](https://semver.org/lang/ko/) 을 따릅니다.
|
|
5
5
|
|
|
6
|
+
## [3.53.0] - 2026-07-23
|
|
7
|
+
|
|
8
|
+
### Changed — 웹 스토리지 배포: `--dev` → QA 채널 별칭(deprecated)
|
|
9
|
+
|
|
10
|
+
웹 스토리지 배포를 **QA → promote 불변배포 단일 파이프라인**으로 수렴했다. 막다른 길이던
|
|
11
|
+
레거시 dev 배포(별도 `.dev.web.connectbase.world` 호스트 + `{id}/dev` 저장경로)는 서버에서
|
|
12
|
+
제거됐고, `--dev` 플래그는 남아 있으나 이제 **QA 채널 배포의 별칭**으로 동작한다.
|
|
13
|
+
|
|
14
|
+
- `deploy --dev` 는 `promote_mode` 와 무관하게 이번 릴리스를 **QA 포인터에만** 반영한다
|
|
15
|
+
(production 미반영). 실행 시 deprecation 안내를 출력하며, 검증 후 `promote` 로 production
|
|
16
|
+
에 반영한다. **deprecated** — 정식 흐름 `deploy`(신규 스토리지 기본 `manual` → QA)
|
|
17
|
+
→ `releases` → `promote` 사용을 권장한다.
|
|
18
|
+
- `deploy` / `promote` / `releases` 명령의 인터페이스와 프로그래매틱 API 는 변경 없음.
|
|
19
|
+
|
|
20
|
+
> 참고(서버 측): 신규 웹 스토리지는 기본 `promote_mode=manual` 로 생성된다 — `deploy` 는
|
|
21
|
+
> QA 에만 반영되고 production 은 명시적 `promote` 로만 바뀐다. 기존 스토리지는 영향 없다.
|
|
22
|
+
|
|
6
23
|
## [3.52.0] - 2026-07-22
|
|
7
24
|
|
|
8
25
|
### Added — Paddle(MoR) 임베디드 결제 타입
|
package/dist/cli.js
CHANGED
|
@@ -377,8 +377,8 @@ function validateFileSizes(files) {
|
|
|
377
377
|
);
|
|
378
378
|
process.exit(1);
|
|
379
379
|
}
|
|
380
|
-
async function requestDeployPresign(baseStorageUrl, headers, files, timeoutMs
|
|
381
|
-
const body = JSON.stringify(
|
|
380
|
+
async function requestDeployPresign(baseStorageUrl, headers, files, timeoutMs) {
|
|
381
|
+
const body = JSON.stringify({ files });
|
|
382
382
|
const res = await makeRequest(
|
|
383
383
|
`${baseStorageUrl}/deploy/presign`,
|
|
384
384
|
"POST",
|
|
@@ -547,73 +547,6 @@ async function offloadLargeBinaries(baseStorageUrl, headers, diff, _envLabel, ti
|
|
|
547
547
|
f.content = "";
|
|
548
548
|
}
|
|
549
549
|
}
|
|
550
|
-
async function offloadDevLargeBinaries(baseStorageUrl, headers, files, timeoutMs) {
|
|
551
|
-
const large = files.filter(
|
|
552
|
-
(f) => f.isBinary && Buffer.byteLength(f.content, "utf8") > WEB_FILE_MAX_STORED_BYTES
|
|
553
|
-
);
|
|
554
|
-
if (large.length === 0) return files;
|
|
555
|
-
const presignFiles = large.map((f) => ({
|
|
556
|
-
path: f.path,
|
|
557
|
-
size: Buffer.from(f.content, "base64").length,
|
|
558
|
-
mime_type: guessMimeType(f.path)
|
|
559
|
-
}));
|
|
560
|
-
let presigned;
|
|
561
|
-
try {
|
|
562
|
-
presigned = await requestDeployPresign(
|
|
563
|
-
baseStorageUrl,
|
|
564
|
-
headers,
|
|
565
|
-
presignFiles,
|
|
566
|
-
timeoutMs,
|
|
567
|
-
true
|
|
568
|
-
);
|
|
569
|
-
} catch (err) {
|
|
570
|
-
error(
|
|
571
|
-
`dev \uB300\uC6A9\uB7C9 \uD30C\uC77C \uC5C5\uB85C\uB4DC \uC900\uBE44 \uC2E4\uD328: ${err instanceof Error ? err.message : err}`
|
|
572
|
-
);
|
|
573
|
-
process.exit(1);
|
|
574
|
-
}
|
|
575
|
-
if (presigned === null) {
|
|
576
|
-
info(
|
|
577
|
-
"\uC11C\uBC84\uAC00 \uB300\uC6A9\uB7C9 \uC9C1\uC811 \uC5C5\uB85C\uB4DC\uB97C \uBBF8\uC9C0\uC6D0 \u2014 dev \uB294 \uC804\uB7C9 \uC5C5\uB85C\uB4DC\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4."
|
|
578
|
-
);
|
|
579
|
-
return files;
|
|
580
|
-
}
|
|
581
|
-
if (!presigned.every((p) => p.object_key.includes("/dev/"))) {
|
|
582
|
-
info(
|
|
583
|
-
"\uC11C\uBC84\uAC00 dev \uC9C1\uC811 \uC5C5\uB85C\uB4DC\uB97C \uBBF8\uC9C0\uC6D0(\uC751\uB2F5 \uD0A4\uAC00 dev \uACBD\uB85C \uC544\uB2D8) \u2014 dev \uB294 \uC804\uB7C9 \uC5C5\uB85C\uB4DC\uB85C \uC9C4\uD589\uD569\uB2C8\uB2E4."
|
|
584
|
-
);
|
|
585
|
-
return files;
|
|
586
|
-
}
|
|
587
|
-
const urlByPath = new Map(presigned.map((p) => [p.path, p.upload_url]));
|
|
588
|
-
info(
|
|
589
|
-
`\uB300\uC6A9\uB7C9 \uBC14\uC774\uB108\uB9AC ${large.length}\uAC1C\uB97C dev Object Storage \uB85C \uC9C1\uC811 \uC5C5\uB85C\uB4DC\uD569\uB2C8\uB2E4...`
|
|
590
|
-
);
|
|
591
|
-
const offloaded = /* @__PURE__ */ new Set();
|
|
592
|
-
for (const f of large) {
|
|
593
|
-
const uploadUrl = urlByPath.get(f.path);
|
|
594
|
-
if (!uploadUrl) {
|
|
595
|
-
error(`presign \uC751\uB2F5\uC5D0 \uC5C5\uB85C\uB4DC URL \uC774 \uC5C6\uC2B5\uB2C8\uB2E4: ${f.path}`);
|
|
596
|
-
process.exit(1);
|
|
597
|
-
}
|
|
598
|
-
const bytes = Buffer.from(f.content, "base64");
|
|
599
|
-
try {
|
|
600
|
-
await putToPresignedUrl(
|
|
601
|
-
uploadUrl,
|
|
602
|
-
bytes,
|
|
603
|
-
guessMimeType(f.path),
|
|
604
|
-
timeoutMs
|
|
605
|
-
);
|
|
606
|
-
} catch (err) {
|
|
607
|
-
error(
|
|
608
|
-
`dev \uC5C5\uB85C\uB4DC \uC2E4\uD328 (${f.path}): ${err instanceof Error ? err.message : err}`
|
|
609
|
-
);
|
|
610
|
-
process.exit(1);
|
|
611
|
-
}
|
|
612
|
-
success(`\uC9C1\uC811 \uC5C5\uB85C\uB4DC(dev): ${f.path} (${formatSize(bytes.length)})`);
|
|
613
|
-
offloaded.add(f.path);
|
|
614
|
-
}
|
|
615
|
-
return files.filter((f) => !offloaded.has(f.path));
|
|
616
|
-
}
|
|
617
550
|
var DEFAULT_REQUEST_TIMEOUT_MS = 6e4;
|
|
618
551
|
async function makeRequest(url, method, headers, body, reqOpts = {}) {
|
|
619
552
|
return new Promise((resolve2, reject) => {
|
|
@@ -722,30 +655,19 @@ async function deploy(directory, config, isDev = false, deployOpts = {}) {
|
|
|
722
655
|
log(
|
|
723
656
|
`${colors.green}\u2713${colors.reset} ${files.length}\uAC1C \uD30C\uC77C \uBC1C\uACAC (${sizeKB} KB)`
|
|
724
657
|
);
|
|
725
|
-
const
|
|
658
|
+
const target = isDev ? "qa" : void 0;
|
|
659
|
+
const envLabel = isDev ? "QA" : "Prod";
|
|
660
|
+
if (isDev) {
|
|
661
|
+
warn(
|
|
662
|
+
`${colors.yellow}--dev \uB294 deprecated${colors.reset} \uC785\uB2C8\uB2E4 \u2014 QA \uCC44\uB110\uB85C \uBC30\uD3EC\uD569\uB2C8\uB2E4(production \uBBF8\uBC18\uC601). \uC774\uD6C4 ${colors.cyan}npx connectbase promote${colors.reset} \uB85C production \uC5D0 \uBC18\uC601\uD558\uC138\uC694. promote_mode=manual \uC774\uBA74 \uC77C\uBC18 ${colors.cyan}deploy${colors.reset} \uB3C4 \uB3D9\uC77C\uD558\uAC8C QA \uB85C \uBC30\uD3EC\uB429\uB2C8\uB2E4.`
|
|
663
|
+
);
|
|
664
|
+
}
|
|
726
665
|
const baseStorageUrl = `${config.baseUrl}/v1/public/storages/webs/${config.storageId}`;
|
|
727
666
|
const headers = { "X-Public-Key": config.publicKey };
|
|
728
667
|
const timeoutMs = computeDeployTimeout(totalSize, deployOpts.timeoutMs);
|
|
729
668
|
log(
|
|
730
669
|
`${colors.dim}\uD0C0\uC784\uC544\uC6C3: ${Math.round(timeoutMs / 1e3)}\uCD08${colors.reset}`
|
|
731
670
|
);
|
|
732
|
-
if (isDev) {
|
|
733
|
-
const toSend = await offloadDevLargeBinaries(
|
|
734
|
-
baseStorageUrl,
|
|
735
|
-
headers,
|
|
736
|
-
files,
|
|
737
|
-
timeoutMs
|
|
738
|
-
);
|
|
739
|
-
await fullDeploy(
|
|
740
|
-
baseStorageUrl,
|
|
741
|
-
headers,
|
|
742
|
-
toSend,
|
|
743
|
-
envLabel,
|
|
744
|
-
"deploy/dev",
|
|
745
|
-
timeoutMs
|
|
746
|
-
);
|
|
747
|
-
return;
|
|
748
|
-
}
|
|
749
671
|
try {
|
|
750
672
|
const manifest = await tryFetchManifest(baseStorageUrl, headers);
|
|
751
673
|
if (!manifest) {
|
|
@@ -756,18 +678,27 @@ async function deploy(directory, config, isDev = false, deployOpts = {}) {
|
|
|
756
678
|
files,
|
|
757
679
|
envLabel,
|
|
758
680
|
"deploy",
|
|
759
|
-
timeoutMs
|
|
681
|
+
timeoutMs,
|
|
682
|
+
target
|
|
760
683
|
);
|
|
761
684
|
return;
|
|
762
685
|
}
|
|
763
686
|
const diff = computeDeployDiff(files, manifest);
|
|
764
687
|
if (diff.upsert.length === 0 && diff.delete.length === 0) {
|
|
765
688
|
success(`\uBCC0\uACBD\uC0AC\uD56D \uC5C6\uC74C (${files.length}\uAC1C \uD30C\uC77C \uC77C\uCE58)`);
|
|
766
|
-
|
|
767
|
-
|
|
689
|
+
if (target === "qa") {
|
|
690
|
+
log(
|
|
691
|
+
`
|
|
692
|
+
${colors.dim}QA/production \uD3EC\uC778\uD130\uB294 \uADF8\uB300\uB85C\uC785\uB2C8\uB2E4. \uC0C8 \uBC30\uD3EC\uAC00 \uC5C6\uC73C\uBA74 \uBC18\uC601\uD560 \uAC83\uB3C4 \uC5C6\uC2B5\uB2C8\uB2E4.${colors.reset}
|
|
693
|
+
`
|
|
694
|
+
);
|
|
695
|
+
} else {
|
|
696
|
+
log(
|
|
697
|
+
`
|
|
768
698
|
${colors.cyan}URL: https://${config.storageId}.web.connectbase.world${colors.reset}
|
|
769
699
|
`
|
|
770
|
-
|
|
700
|
+
);
|
|
701
|
+
}
|
|
771
702
|
return;
|
|
772
703
|
}
|
|
773
704
|
await offloadLargeBinaries(
|
|
@@ -788,7 +719,8 @@ ${colors.cyan}URL: https://${config.storageId}.web.connectbase.world${colors.res
|
|
|
788
719
|
diff,
|
|
789
720
|
manifest.revision,
|
|
790
721
|
envLabel,
|
|
791
|
-
timeoutMs
|
|
722
|
+
timeoutMs,
|
|
723
|
+
target
|
|
792
724
|
);
|
|
793
725
|
} catch (err) {
|
|
794
726
|
process.stdout.write("\r \r");
|
|
@@ -847,7 +779,7 @@ function startUploadHeartbeat(envLabel, suffix = "\uBC30\uD3EC \uC911") {
|
|
|
847
779
|
);
|
|
848
780
|
}, 1e3);
|
|
849
781
|
}
|
|
850
|
-
async function incrementalDeploy(baseStorageUrl, headers, diff, baseRevision, envLabel, timeoutMs) {
|
|
782
|
+
async function incrementalDeploy(baseStorageUrl, headers, diff, baseRevision, envLabel, timeoutMs, target) {
|
|
851
783
|
process.stdout.write(
|
|
852
784
|
`${colors.blue}\u27F3${colors.reset} ${envLabel} \uC99D\uBD84 \uBC30\uD3EC \uC911...`
|
|
853
785
|
);
|
|
@@ -855,7 +787,8 @@ async function incrementalDeploy(baseStorageUrl, headers, diff, baseRevision, en
|
|
|
855
787
|
const body = JSON.stringify({
|
|
856
788
|
upsert: diff.upsert,
|
|
857
789
|
delete: diff.delete,
|
|
858
|
-
base_revision: baseRevision
|
|
790
|
+
base_revision: baseRevision,
|
|
791
|
+
...target ? { target } : {}
|
|
859
792
|
});
|
|
860
793
|
const res = await makeRequest(
|
|
861
794
|
`${baseStorageUrl}/deploy/incremental`,
|
|
@@ -876,7 +809,8 @@ async function incrementalDeploy(baseStorageUrl, headers, diff, baseRevision, en
|
|
|
876
809
|
const body2 = JSON.stringify({
|
|
877
810
|
upsert: diff.upsert,
|
|
878
811
|
delete: diff.delete,
|
|
879
|
-
base_revision: manifest.revision
|
|
812
|
+
base_revision: manifest.revision,
|
|
813
|
+
...target ? { target } : {}
|
|
880
814
|
});
|
|
881
815
|
process.stdout.write(
|
|
882
816
|
`${colors.blue}\u27F3${colors.reset} ${envLabel} \uC99D\uBD84 \uBC30\uD3EC \uC7AC\uC2DC\uB3C4...`
|
|
@@ -896,7 +830,7 @@ async function incrementalDeploy(baseStorageUrl, headers, diff, baseRevision, en
|
|
|
896
830
|
}
|
|
897
831
|
handleDeployResponse(res, envLabel);
|
|
898
832
|
}
|
|
899
|
-
async function fullDeploy(baseStorageUrl, headers, files, envLabel, endpoint, timeoutMs) {
|
|
833
|
+
async function fullDeploy(baseStorageUrl, headers, files, envLabel, endpoint, timeoutMs, target) {
|
|
900
834
|
process.stdout.write(`${colors.blue}\u27F3${colors.reset} ${envLabel} \uBC30\uD3EC \uC911...`);
|
|
901
835
|
const heartbeat = startUploadHeartbeat(envLabel);
|
|
902
836
|
const body = JSON.stringify({
|
|
@@ -904,7 +838,8 @@ async function fullDeploy(baseStorageUrl, headers, files, envLabel, endpoint, ti
|
|
|
904
838
|
path: f.path,
|
|
905
839
|
content: f.content,
|
|
906
840
|
is_binary: f.isBinary
|
|
907
|
-
}))
|
|
841
|
+
})),
|
|
842
|
+
...target ? { target } : {}
|
|
908
843
|
});
|
|
909
844
|
const res = await makeRequest(
|
|
910
845
|
`${baseStorageUrl}/${endpoint}`,
|
|
@@ -947,11 +882,7 @@ ${colors.yellow}QA URL: ${dep.qa_url}${colors.reset}`);
|
|
|
947
882
|
return;
|
|
948
883
|
}
|
|
949
884
|
success(`${envLabel} \uBC30\uD3EC \uC644\uB8CC!`);
|
|
950
|
-
if (data?.
|
|
951
|
-
log(`
|
|
952
|
-
${colors.yellow}Dev URL: ${data.dev_url}${colors.reset}
|
|
953
|
-
`);
|
|
954
|
-
} else if (data?.url) {
|
|
885
|
+
if (data?.url) {
|
|
955
886
|
log(`
|
|
956
887
|
${colors.cyan}URL: ${data.url}${colors.reset}
|
|
957
888
|
`);
|
|
@@ -3422,8 +3353,9 @@ ${colors.yellow}\uBA85\uB839\uC5B4:${colors.reset}
|
|
|
3422
3353
|
update SDK \uBC84\uC804 \uCCB4\uD06C + \uBB38\uC11C/MCP \uC77C\uAD04 \uC5C5\uB370\uC774\uD2B8 (\uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8 \uC9C0\uC6D0)
|
|
3423
3354
|
docs SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC/\uC5C5\uB370\uC774\uD2B8 (\uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
|
|
3424
3355
|
mcp MCP \uC11C\uBC84 \uC124\uC815 (.mcp.json \uC0DD\uC131/\uC5C5\uB370\uC774\uD2B8, \uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
|
|
3425
|
-
deploy <directory> \uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uD30C\uC77C \uBC30\uD3EC
|
|
3426
|
-
promote_mode=manual \uC774\uBA74 QA \uD658\uACBD\uC5D0\uB9CC \uBC30\uD3EC\uB429\uB2C8\uB2E4
|
|
3356
|
+
deploy <directory> \uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uD30C\uC77C \uBC30\uD3EC
|
|
3357
|
+
promote_mode=manual \uC774\uBA74 QA \uD658\uACBD\uC5D0\uB9CC \uBC30\uD3EC\uB429\uB2C8\uB2E4 (\uC2E0\uADDC \uC2A4\uD1A0\uB9AC\uC9C0 \uAE30\uBCF8\uAC12)
|
|
3358
|
+
--dev \uB294 promote_mode \uBB34\uAD00 QA \uBC30\uD3EC (deprecated: QA \uBCC4\uCE6D)
|
|
3427
3359
|
promote [releaseId] QA \uAC80\uC99D \uD6C4 production \uBC18\uC601 (\uBBF8\uC9C0\uC815: \uCD5C\uC2E0 \uBC30\uD3EC, \uACFC\uAC70 id: \uB864\uBC31)
|
|
3428
3360
|
releases \uBC30\uD3EC \uC774\uB825 \uC870\uD68C (release \uBC88\uD638/\uC0C1\uD0DC/production\xB7QA \uD3EC\uC778\uD130)
|
|
3429
3361
|
tunnel <port> \uB85C\uCEEC \uC11C\uBE44\uC2A4\uB97C \uC778\uD130\uB137\uC5D0 \uB178\uCD9C
|
|
@@ -3447,7 +3379,7 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
|
|
|
3447
3379
|
--token <value> proxy_token \uACE0\uC815\uAC12 (16-128\uC790 [A-Za-z0-9_-]) \u2014 \uC7AC\uC5F0\uACB0\uC5D0\uB3C4 \uD1A0\uD070 \uD68C\uC804 \uBC29\uC9C0. \uC678\uBD80 MCP custom_header \uB4F1 \uC548\uC815 \uD1B5\uD569\uC6A9 (tunnel \uC804\uC6A9)
|
|
3448
3380
|
--label <name> Endpoint binding \uC790\uB3D9 \uB4F1\uB85D (tunnel \uC804\uC6A9) \u2014 SDK \uC758 cb.endpoint.call(label) \uD638\uCD9C \uAC00\uB2A5
|
|
3449
3381
|
--description <text> Endpoint binding \uC124\uBA85 (--label \uB3D9\uBC18 \uC2DC\uB9CC)
|
|
3450
|
-
-d, --dev
|
|
3382
|
+
-d, --dev QA \uD658\uACBD\uC5D0\uB9CC \uBC30\uD3EC (deploy \uC804\uC6A9, deprecated \u2014 QA \uBCC4\uCE6D)
|
|
3451
3383
|
-y, --yes \uBE44\uB300\uD654\uD615 \uCD08\uAE30\uD654 \u2014 \uD504\uB86C\uD504\uD2B8 \uC5C6\uC774 \uAE30\uBCF8\uAC12/\uD50C\uB798\uADF8\uB85C \uC9C4\uD589 (init \uC804\uC6A9, CI/AI \uC5D0\uC774\uC804\uD2B8\uC6A9)
|
|
3452
3384
|
-a, --app <id> \uAE30\uC874 \uC571 ID \uC9C0\uC815 (init \uC804\uC6A9)
|
|
3453
3385
|
--secret-key <key> Secret Key (cb_sk_) \uC9C0\uC815 (init/mcp)
|
|
@@ -3482,14 +3414,11 @@ ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
|
|
|
3482
3414
|
${colors.dim}# 4. Prod \uBC30\uD3EC${colors.reset}
|
|
3483
3415
|
npm run deploy
|
|
3484
3416
|
|
|
3485
|
-
${colors.dim}# 4-1. QA \uC6CC\uD06C\uD50C\uB85C\uC6B0 (\
|
|
3417
|
+
${colors.dim}# 4-1. QA \uC6CC\uD06C\uD50C\uB85C\uC6B0 (\uC2E0\uADDC \uC2A4\uD1A0\uB9AC\uC9C0 \uAE30\uBCF8 promote_mode=manual)${colors.reset}
|
|
3486
3418
|
npx connectbase deploy ./dist ${colors.dim}# QA \uD658\uACBD\uC5D0\uB9CC \uBC30\uD3EC${colors.reset}
|
|
3487
3419
|
npx connectbase releases ${colors.dim}# \uBC30\uD3EC \uC774\uB825 \uD655\uC778${colors.reset}
|
|
3488
3420
|
npx connectbase promote ${colors.dim}# QA \uAC80\uC99D \uD6C4 production \uBC18\uC601${colors.reset}
|
|
3489
3421
|
|
|
3490
|
-
${colors.dim}# 4-2. Dev \uD658\uACBD \uBC30\uD3EC (\uB0B4\uBD80 \uD655\uC778\uC6A9)${colors.reset}
|
|
3491
|
-
npx connectbase deploy ./dist --dev
|
|
3492
|
-
|
|
3493
3422
|
${colors.dim}# 5. \uD130\uB110 (\uAE30\uBCF8)${colors.reset}
|
|
3494
3423
|
npx connectbase tunnel 3000
|
|
3495
3424
|
|