connectbase-client 0.15.1 → 0.16.1
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 +157 -0
- package/LICENSE +21 -0
- package/README.md +27 -17
- package/dist/cli.js +275 -15
- package/dist/connect-base.umd.js +3 -3
- package/dist/index.d.mts +19 -5
- package/dist/index.d.ts +19 -5
- package/dist/index.js +15 -2
- package/dist/index.mjs +15 -2
- package/package.json +11 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
본 SDK 의 모든 주요 변경사항을 [Keep a Changelog](https://keepachangelog.com/ko/1.1.0/) 형식으로 기록합니다.
|
|
4
|
+
버전은 [Semantic Versioning](https://semver.org/lang/ko/) 을 따릅니다.
|
|
5
|
+
|
|
6
|
+
## [0.16.1] - 2026-04-17
|
|
7
|
+
|
|
8
|
+
MCP/SDK 문서-코드 정합성 검증에서 발견된 불일치 소규모 정정. 런타임 동작 변경은 없으며, 이전 릴리스에서 도입된 타입 회귀를 롤백.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **`FetchDataResponse` 필드명 회귀 롤백**: `0.16.0` 에서 `datas→data`, `total_size→total_count` 로 바꿨으나 실제 서버 wire 는 여전히 `datas` / `total_size` 였음. 타입 정의를 서버 응답 그대로 `{ datas, total_size }` 로 되돌려 런타임 미스매치 제거.
|
|
13
|
+
- `cb.push.subscribeTopic()` JSDoc 예제가 `device_token` 인자 누락된 구 시그니처로 표기되던 문제 정정 (실 시그니처는 `subscribeTopic(deviceToken, topic)`).
|
|
14
|
+
- CLI 안내 문구·`setupMonorepoRoot` 로 추가되는 `cb:update`/`cb:docs`/`cb:mcp` 스크립트가 `connectbase-client` 를 가리키던 것을 정규 bin 이름인 `connectbase` 로 통일. 두 bin 은 모두 동작하지만 문서와 자동 생성 스크립트는 단일 이름 기준으로 일관화.
|
|
15
|
+
|
|
16
|
+
### Documentation
|
|
17
|
+
|
|
18
|
+
- README `### Push Notifications` 섹션의 예제를 실제 공개 API 와 일치하도록 수정: `push.register()` / `push.subscribeToTopic()` / `push.unsubscribeFromTopic()` (존재하지 않는 메서드) → `push.registerDevice()` / `push.subscribeTopic(deviceToken, topic)` / `push.unsubscribeTopic(deviceToken, topic)` / Web Push 등록 예제 추가.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
|
|
22
|
+
- `package.json` 메타데이터 보강: `author`, `homepage`, `bugs`, `sideEffects: false` 필드 추가, `files` 에 `LICENSE`/`CHANGELOG.md`/`README.md` 명시적 포함.
|
|
23
|
+
- 저장소 루트에 `LICENSE` (MIT) 파일 신설 (이전에는 `license: "MIT"` 선언만 존재).
|
|
24
|
+
|
|
25
|
+
## [0.16.0] - 2026-04-17
|
|
26
|
+
|
|
27
|
+
CLI `update` 커맨드와 신규 저장소 API 옵션, 토큰 영속성 옵션 추가. 일부 타입 정정.
|
|
28
|
+
|
|
29
|
+
### Added
|
|
30
|
+
|
|
31
|
+
- **CLI `update` 커맨드**: 현재 설치된 `connectbase-client` 버전을 npm 과 비교하고 `docs`·`mcp` 산출물을 일괄 최신화.
|
|
32
|
+
- **모노레포 지원**: `connectbase init --setup-root` 로 모노레포 루트 `package.json` 에 `cb:update`/`cb:docs`/`cb:mcp` 편의 스크립트 설치.
|
|
33
|
+
- **Storage `getFiles()` `parentId` 옵션**: 특정 폴더 하위 파일 목록 조회 지원.
|
|
34
|
+
- **토큰 영속성(persistence) 옵션**: `new ConnectBase({ persistence: 'localStorage' | 'sessionStorage' | 'none' })`.
|
|
35
|
+
- `localStorage` (기본값): 브라우저 종료 후에도 토큰 유지.
|
|
36
|
+
- `sessionStorage`: 탭 종료 시 삭제.
|
|
37
|
+
- `none`: 메모리에만 저장.
|
|
38
|
+
- 생성자에서 저장된 토큰 자동 복원 (명시적 토큰 전달 시 스킵). SSR 환경(`window` undefined) 안전 처리.
|
|
39
|
+
- **OAuthProvider 확장**: `kakao`, `apple` 프로바이더 추가 (서버 enum 과 동기화).
|
|
40
|
+
|
|
41
|
+
### Changed
|
|
42
|
+
|
|
43
|
+
- `VERSION` 상수가 `package.json` 에서 동적으로 로드되도록 변경 (이전: `0.10.6` 하드코딩).
|
|
44
|
+
- `FetchDataResponse` 필드명 변경: `datas` → `data`, `total_size` → `total_count` (서버 응답과 일치를 의도함).
|
|
45
|
+
- **⚠️ 본 변경은 실제 서버 wire 와 맞지 않는 회귀였으며 `0.16.1` 에서 롤백됩니다.** `0.16.0` 사용자는 `0.16.1` 이상으로 즉시 업그레이드 권장.
|
|
46
|
+
|
|
47
|
+
### Documentation
|
|
48
|
+
|
|
49
|
+
- SDK 문서 전체 감사 및 누락 섹션 보강.
|
|
50
|
+
|
|
51
|
+
## [0.15.0] - 2026-04-16
|
|
52
|
+
|
|
53
|
+
Web Analytics SDK 모듈 신설 및 터널 유틸 리팩터.
|
|
54
|
+
|
|
55
|
+
### Added
|
|
56
|
+
|
|
57
|
+
- **AnalyticsAPI** 모듈 (`cb.analytics`): `init` / `trackEvent` / `trackPageView` / `identify` / `setConsent` / `enableHeatmap` / `enableHeartbeat` / `destroy`.
|
|
58
|
+
- **SessionManager**: 30분 타임아웃, `visitor_uid` localStorage 영속화.
|
|
59
|
+
- 백엔드 측 12개 서비스·9개 Ent 스키마(이벤트/퍼널/세션/코호트/어트리뷰션/세그먼트/A-B 테스트/히트맵/녹화/프라이버시) 와 매칭.
|
|
60
|
+
|
|
61
|
+
### Changed
|
|
62
|
+
|
|
63
|
+
- CLI 내부에서 tunnel 관련 로직을 `src/tunnel-utils.ts` 로 추출 (테스트 용이성 확보).
|
|
64
|
+
- `vitest` 도입 및 tunnel/analytics 단위 테스트 23건 추가.
|
|
65
|
+
|
|
66
|
+
## [0.14.0] - 2026-04-15
|
|
67
|
+
|
|
68
|
+
Tunnel 안정성 개선.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- **Tunnel lockfile**: 앱+포트 기반 lockfile 로 동일 터널 중복 실행을 차단. stale lockfile 자동 감지(PID 생존 확인).
|
|
73
|
+
- `--force` 플래그: lockfile 무시 옵션.
|
|
74
|
+
|
|
75
|
+
### Changed
|
|
76
|
+
|
|
77
|
+
- 서버의 `tunnel_error code=replaced` 수신 시 재연결을 중단하고 안내 메시지 출력 (이전에는 끊임없이 재연결 시도).
|
|
78
|
+
- `TunnelMessage` 타입에 `code` / `error` / `message` 필드 추가.
|
|
79
|
+
|
|
80
|
+
## [0.13.0] - 2026-04-14
|
|
81
|
+
|
|
82
|
+
Database API 정합성 및 완성도 대규모 개선.
|
|
83
|
+
|
|
84
|
+
### Breaking Changes
|
|
85
|
+
|
|
86
|
+
- **`TableSchema` 응답 구조 전면 재정의**: 서버 ent 모델 (`backend/cmd/data-server/ent/schema/table.go`) 과 1:1 일치하도록 변경.
|
|
87
|
+
- `name` → `title`
|
|
88
|
+
- `columns: ColumnSchema[]` → `schema: TableSchemaDefinition` (평면 또는 중첩 맵)
|
|
89
|
+
- `created_at` → `create_time` (※ G2 작업에서 다시 `created_at` 로 표준화 예정)
|
|
90
|
+
- `updated_at` → `update_time`
|
|
91
|
+
- 신규 필드: `app_id`, `access_level`, `is_active`, `validation_schema?`
|
|
92
|
+
- **`CreateTableRequest` 형태 변경**: 서버 DTO 와 일치.
|
|
93
|
+
- `schema?: TableSchemaDefinition` 신규 필드. 평면 맵 (`{email: 'string'}`) 또는 중첩 객체 (`{email: {type: 'string', required: true}}`) 모두 지원. `$required` 키로 필수 컬럼 지정.
|
|
94
|
+
- `accessLevel?: 'Creator' | 'Public' | 'AppMember'` (기본 `'Creator'`)
|
|
95
|
+
- `description` 은 `@deprecated` — 서버에 저장되지 않음
|
|
96
|
+
- **`createTable()` 반환 타입**: `Promise<TableSchema>` → `Promise<void>`. 서버는 `{message}` 만 반환하므로 거짓 타입 제거.
|
|
97
|
+
- **`createColumn()` / `updateColumn()` 반환 타입**: 동일한 이유로 `Promise<void>` 로 변경.
|
|
98
|
+
- **`updateTable()` 시맨틱 정정**: PATCH 부분 업데이트가 정상 동작. 이전 버전에서는 모든 필드가 required 라 부분 업데이트 시 400 오류가 발생했음.
|
|
99
|
+
- **`DataType` 정렬**: 서버 `ValidSchemaTypes` 와 일치하도록 변경.
|
|
100
|
+
- 제거: `'boolean'`
|
|
101
|
+
- 추가: `'int'`, `'bool'`, `'uuid'`
|
|
102
|
+
- 최종 union: `'string' | 'int' | 'number' | 'bool' | 'uuid' | 'date' | 'object' | 'array'`
|
|
103
|
+
- **`CreateColumnRequest`**:
|
|
104
|
+
- `is_required` 가 optional 로 변경 (기본 false)
|
|
105
|
+
- `default_value` 타입 `string` → `unknown` (서버는 임의 타입 허용)
|
|
106
|
+
- `order`, `validation_rule` 은 `@deprecated` (서버 미지원)
|
|
107
|
+
- **`UpdateColumnRequest`**:
|
|
108
|
+
- `default_value` 타입 `string` → `unknown`
|
|
109
|
+
- `name` `@deprecated` (서버는 컬럼 rename 미지원)
|
|
110
|
+
- `order`, `validation_rule` `@deprecated`
|
|
111
|
+
- **`ColumnSchema`**:
|
|
112
|
+
- SDK 가 합성하는 객체임을 명시
|
|
113
|
+
- `default_value` 타입 `string` → `unknown`
|
|
114
|
+
- `created_at` 은 테이블의 `create_time` 으로 대체 (컬럼 개별 타임스탬프 없음)
|
|
115
|
+
- `order` 는 SDK 가 부여한 인덱스
|
|
116
|
+
- `updated_at`, `validation_rule` `@deprecated`
|
|
117
|
+
|
|
118
|
+
### Added
|
|
119
|
+
|
|
120
|
+
- `TableSchemaDefinition` interface — 컬럼 정의 맵 타입. 플랫 / 중첩 / `$required` 모두 지원.
|
|
121
|
+
- `TableColumnDef` union type — 단일 컬럼 정의 (플랫 string 또는 중첩 객체).
|
|
122
|
+
- `TableAccessLevel` type — `'Creator' | 'Public' | 'AppMember'`.
|
|
123
|
+
- `database.createTable()` 가 초기 schema 와 access level 을 한 번에 받아 1-step 생성 지원.
|
|
124
|
+
- `database.getColumns()` 가 플랫 / 중첩 schema 모두 정확히 파싱.
|
|
125
|
+
- `database` 모듈의 `getPublicPrefix()` 가 항상 `/v1/public` 반환 (이전: 인증 종류에 따라 `/v1/public` 또는 `/v1` — 후자는 dead path).
|
|
126
|
+
- `database.getValidationSchema()`, `setValidationSchema()`, `deleteValidationSchema()` — 테이블 검증 스키마 CRUD.
|
|
127
|
+
- `MemberInfoResponse` 에 `email?`, `role?` 필드 추가 — RLS `auth.email`/`auth.role` 과 일치.
|
|
128
|
+
- MCP `update_column` 툴 신설 (description, encrypted, data_type, is_required, default_value 변경).
|
|
129
|
+
- MCP `get_validation_schema`, `set_validation_schema`, `delete_validation_schema` 툴 신설.
|
|
130
|
+
|
|
131
|
+
### Fixed
|
|
132
|
+
|
|
133
|
+
- **🔴 `database.createTable()` 가 어떤 키로도 동작하지 않던 broken 상태 해결**.
|
|
134
|
+
- Public Key 경로: 요청 body 가 서버 DTO 와 불일치 (필드명 `name`/`title`, 누락 `access_level`, 빈 `schema`)
|
|
135
|
+
- Secret Key 경로: 존재하지 않는 `/v1/tables` 경로 호출 → 404
|
|
136
|
+
- 두 경로 모두 본 릴리스에서 정상 동작.
|
|
137
|
+
- **MCP `create_table` 툴이 빈 schema 거부로 항상 실패** 하던 문제 해결 (서버 hook 이 explicit 빈 맵을 거부했음). 서버 DTO/repository/MCP tool 세 곳을 동시에 수정.
|
|
138
|
+
- 서버 측 `CreateTableRequest.Schema` 가 `binding:"required"` 였으나 schema 생략 가능하도록 변경.
|
|
139
|
+
- 서버 측 `EditTableInternal` (PATCH) 가 full-replace 시맨틱이라 부분 업데이트 불가능했던 문제 해결. `PatchTableRequest` DTO 와 `PatchTable` repository 메서드 신설.
|
|
140
|
+
- MCP `create_column`, `update_column` 툴의 `data_type` enum 이 `'boolean'` 을 포함했으나 서버는 `'bool'` 만 허용 → 정정.
|
|
141
|
+
- `getColumns()` 가 플랫 schema (`"email": "string"`) 를 모두 `'string'` 으로 잘못 반환하던 문제 해결.
|
|
142
|
+
|
|
143
|
+
### Documentation
|
|
144
|
+
|
|
145
|
+
- `secretKey` 의 JSDoc 명확화: 앱 DB API 에는 사용 불가, CLI / tunnel 전용임을 명시.
|
|
146
|
+
- embedded SDK 문서 (04-sdk-database.md, 11-mcp-tools.md, 25-app-packaging.md) 의 `boolean` → `bool`, `auth.email`/`auth.role` 정합성 정리, `createTable` 예제 갱신.
|
|
147
|
+
- `TableSchemaDefinition` 의 `$required` 키 사용법, `TableColumnDef` 평면/중첩 형태 모두 JSDoc 예제 포함.
|
|
148
|
+
|
|
149
|
+
### Notes
|
|
150
|
+
|
|
151
|
+
본 변경의 대부분은 backwards-incompat 이지만, 이전 버전 (`0.12.x`) 의 `createTable` 자체가 broken 상태였으므로 해당 메서드를 사용하던 코드는 어차피 동작하지 않았습니다. read 메서드 (`getTables`, `getTable`, `getColumns`) 는 사용자 코드가 escape-hatch 캐스팅 (`as any`) 으로 우회하던 경우만 영향받습니다.
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## [0.12.2] - 2026-04-?? (이전)
|
|
156
|
+
|
|
157
|
+
이전 릴리스 — 본 CHANGELOG 도입 이전. git history 참조.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Connect Base
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -89,7 +89,7 @@ Deploy your web application to Connect Base Web Storage with a single command.
|
|
|
89
89
|
|
|
90
90
|
```bash
|
|
91
91
|
# 1. Initialize (one-time setup)
|
|
92
|
-
npx connectbase
|
|
92
|
+
npx connectbase init
|
|
93
93
|
|
|
94
94
|
# 2. Deploy
|
|
95
95
|
npm run deploy
|
|
@@ -115,7 +115,7 @@ The `init` command will:
|
|
|
115
115
|
If you prefer not to use `init`, you can pass options directly:
|
|
116
116
|
|
|
117
117
|
```bash
|
|
118
|
-
npx connectbase
|
|
118
|
+
npx connectbase deploy ./dist -s <storage-id> -k <public-key>
|
|
119
119
|
```
|
|
120
120
|
|
|
121
121
|
### Options
|
|
@@ -136,14 +136,14 @@ Expose a local server to the internet through a secure WebSocket tunnel. Useful
|
|
|
136
136
|
|
|
137
137
|
```bash
|
|
138
138
|
# Expose local port 8084 to the internet
|
|
139
|
-
npx connectbase
|
|
139
|
+
npx connectbase tunnel 8084 -k <public-key>
|
|
140
140
|
|
|
141
141
|
# With environment variable
|
|
142
142
|
export CONNECTBASE_PUBLIC_KEY=your-public-key
|
|
143
|
-
npx connectbase
|
|
143
|
+
npx connectbase tunnel 8084
|
|
144
144
|
|
|
145
145
|
# For GPU servers or long-running tasks (e.g., image generation)
|
|
146
|
-
npx connectbase
|
|
146
|
+
npx connectbase tunnel 7860 --timeout 300 --max-body 50
|
|
147
147
|
```
|
|
148
148
|
|
|
149
149
|
The tunnel creates a public URL like `https://tunnel.connectbase.world/<tunnel-id>/` that proxies all HTTP requests to your local service.
|
|
@@ -181,7 +181,7 @@ The `init` command creates `.connectbaserc` automatically. You can also create i
|
|
|
181
181
|
```bash
|
|
182
182
|
export CONNECTBASE_PUBLIC_KEY=your-public-key
|
|
183
183
|
export CONNECTBASE_STORAGE_ID=your-storage-id
|
|
184
|
-
npx connectbase
|
|
184
|
+
npx connectbase deploy ./dist
|
|
185
185
|
```
|
|
186
186
|
|
|
187
187
|
### Requirements
|
|
@@ -439,19 +439,19 @@ await cb.auth.signOut()
|
|
|
439
439
|
|
|
440
440
|
```typescript
|
|
441
441
|
// Query data
|
|
442
|
-
const {
|
|
442
|
+
const { datas, total_size } = await cb.database.getData('table-id', {
|
|
443
443
|
where: { status: 'active' },
|
|
444
444
|
limit: 10
|
|
445
445
|
})
|
|
446
446
|
|
|
447
447
|
// Query with field selection (Projection) - improves response speed
|
|
448
|
-
const {
|
|
448
|
+
const { datas } = await cb.database.getData('table-id', {
|
|
449
449
|
select: ['id', 'name', 'thumbnail'], // Only return these fields
|
|
450
450
|
limit: 20
|
|
451
451
|
})
|
|
452
452
|
|
|
453
453
|
// Exclude specific fields (e.g., large HTML/CSS content)
|
|
454
|
-
const {
|
|
454
|
+
const { datas } = await cb.database.getData('table-id', {
|
|
455
455
|
exclude: ['html_content', 'css_content'],
|
|
456
456
|
limit: 20
|
|
457
457
|
})
|
|
@@ -764,17 +764,27 @@ await session.stop()
|
|
|
764
764
|
### Push Notifications
|
|
765
765
|
|
|
766
766
|
```typescript
|
|
767
|
-
// Register for
|
|
768
|
-
await cb.push.
|
|
769
|
-
|
|
770
|
-
platform: 'android' //
|
|
767
|
+
// Register a device (FCM for Android, APNS for iOS)
|
|
768
|
+
const device = await cb.push.registerDevice({
|
|
769
|
+
device_token: 'fcm-token-or-apns-token',
|
|
770
|
+
platform: 'android', // 'android' | 'ios' | 'web'
|
|
771
|
+
device_name: 'Galaxy S24'
|
|
771
772
|
})
|
|
772
773
|
|
|
773
|
-
// Subscribe to
|
|
774
|
-
await cb.push.
|
|
774
|
+
// Subscribe the device to a topic (deviceToken is required)
|
|
775
|
+
await cb.push.subscribeTopic(device.device_token, 'news')
|
|
775
776
|
|
|
776
|
-
// Unsubscribe from topic
|
|
777
|
-
await cb.push.
|
|
777
|
+
// Unsubscribe the device from a topic
|
|
778
|
+
await cb.push.unsubscribeTopic(device.device_token, 'news')
|
|
779
|
+
|
|
780
|
+
// Web Push (browsers)
|
|
781
|
+
const vapidKey = await cb.push.getVAPIDPublicKey()
|
|
782
|
+
const registration = await navigator.serviceWorker.ready
|
|
783
|
+
const subscription = await registration.pushManager.subscribe({
|
|
784
|
+
userVisibleOnly: true,
|
|
785
|
+
applicationServerKey: vapidKey.public_key
|
|
786
|
+
})
|
|
787
|
+
await cb.push.registerWebPush(subscription)
|
|
778
788
|
```
|
|
779
789
|
|
|
780
790
|
### WebRTC
|
package/dist/cli.js
CHANGED
|
@@ -108,7 +108,18 @@ function handleTunnelError(msg, appId, localPort) {
|
|
|
108
108
|
}
|
|
109
109
|
|
|
110
110
|
// src/cli.ts
|
|
111
|
-
|
|
111
|
+
function getPackageVersion() {
|
|
112
|
+
try {
|
|
113
|
+
const pkgPath = path2.join(__dirname, "..", "package.json");
|
|
114
|
+
if (fs2.existsSync(pkgPath)) {
|
|
115
|
+
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
116
|
+
return pkg.version || "0.0.0";
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
}
|
|
120
|
+
return "0.15.1";
|
|
121
|
+
}
|
|
122
|
+
var VERSION = getPackageVersion();
|
|
112
123
|
var DEFAULT_BASE_URL = "https://api.connectbase.world";
|
|
113
124
|
var colors = {
|
|
114
125
|
reset: "\x1B[0m",
|
|
@@ -300,8 +311,8 @@ async function deploy(directory, config, isDev = false) {
|
|
|
300
311
|
try {
|
|
301
312
|
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
302
313
|
if (pkg.scripts?.build) {
|
|
303
|
-
warn(`\uBC30\uD3EC \uC804 \uBE4C\uB4DC\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694: ${colors.cyan}npm run build && npx connectbase
|
|
304
|
-
warn(`\uB610\uB294 package.json\uC5D0 deploy \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uB4F1\uB85D\uD558\uC138\uC694: ${colors.cyan}npx connectbase
|
|
314
|
+
warn(`\uBC30\uD3EC \uC804 \uBE4C\uB4DC\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694: ${colors.cyan}npm run build && npx connectbase deploy${colors.reset}`);
|
|
315
|
+
warn(`\uB610\uB294 package.json\uC5D0 deploy \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uB4F1\uB85D\uD558\uC138\uC694: ${colors.cyan}npx connectbase init${colors.reset}`);
|
|
305
316
|
}
|
|
306
317
|
} catch {
|
|
307
318
|
}
|
|
@@ -782,7 +793,7 @@ function addDeployScript(deployDir) {
|
|
|
782
793
|
info(`package.json\uC5D0 \uC774\uBBF8 deploy \uC2A4\uD06C\uB9BD\uD2B8\uAC00 \uC788\uC2B5\uB2C8\uB2E4: "${pkg.scripts.deploy}"`);
|
|
783
794
|
return;
|
|
784
795
|
}
|
|
785
|
-
const deployCmd = `connectbase
|
|
796
|
+
const deployCmd = `connectbase deploy ${deployDir}`;
|
|
786
797
|
pkg.scripts.deploy = pkg.scripts.build ? `${pkg.scripts.build} && ${deployCmd}` : deployCmd;
|
|
787
798
|
fs2.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
788
799
|
success(`package.json\uC5D0 deploy \uC2A4\uD06C\uB9BD\uD2B8 \uCD94\uAC00 \uC644\uB8CC`);
|
|
@@ -1043,6 +1054,229 @@ async function setupClaudeCode(publicKey, secretKey, projectRoot) {
|
|
|
1043
1054
|
await downloadDocs(publicKey, void 0, root);
|
|
1044
1055
|
await setupMcp(secretKey);
|
|
1045
1056
|
}
|
|
1057
|
+
async function fetchLatestVersion(packageName) {
|
|
1058
|
+
try {
|
|
1059
|
+
const res = await makeRequest(
|
|
1060
|
+
`https://registry.npmjs.org/${packageName}/latest`,
|
|
1061
|
+
"GET",
|
|
1062
|
+
{}
|
|
1063
|
+
);
|
|
1064
|
+
if (res.status === 200) {
|
|
1065
|
+
const data = res.data;
|
|
1066
|
+
return data.version || null;
|
|
1067
|
+
}
|
|
1068
|
+
} catch {
|
|
1069
|
+
}
|
|
1070
|
+
return null;
|
|
1071
|
+
}
|
|
1072
|
+
function compareVersions(a, b) {
|
|
1073
|
+
const pa = a.split(".").map(Number);
|
|
1074
|
+
const pb = b.split(".").map(Number);
|
|
1075
|
+
for (let i = 0; i < 3; i++) {
|
|
1076
|
+
const diff = (pa[i] || 0) - (pb[i] || 0);
|
|
1077
|
+
if (diff !== 0) return diff > 0 ? 1 : -1;
|
|
1078
|
+
}
|
|
1079
|
+
return 0;
|
|
1080
|
+
}
|
|
1081
|
+
function findSubPackagesWithConfig(gitRoot) {
|
|
1082
|
+
const results = [];
|
|
1083
|
+
const candidates = ["apps", "packages", "projects", "services", "libs"];
|
|
1084
|
+
for (const candidate of candidates) {
|
|
1085
|
+
const dir = path2.join(gitRoot, candidate);
|
|
1086
|
+
if (!fs2.existsSync(dir)) continue;
|
|
1087
|
+
try {
|
|
1088
|
+
const entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
1089
|
+
for (const entry of entries) {
|
|
1090
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
1091
|
+
const subDir = path2.join(dir, entry.name);
|
|
1092
|
+
if (fs2.existsSync(path2.join(subDir, ".connectbaserc"))) {
|
|
1093
|
+
results.push(subDir);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
} catch {
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
try {
|
|
1100
|
+
const entries = fs2.readdirSync(gitRoot, { withFileTypes: true });
|
|
1101
|
+
for (const entry of entries) {
|
|
1102
|
+
if (!entry.isDirectory() || entry.name.startsWith(".") || candidates.includes(entry.name)) continue;
|
|
1103
|
+
if (entry.name === "node_modules") continue;
|
|
1104
|
+
const subDir = path2.join(gitRoot, entry.name);
|
|
1105
|
+
if (fs2.existsSync(path2.join(subDir, ".connectbaserc")) && !results.includes(subDir)) {
|
|
1106
|
+
results.push(subDir);
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
} catch {
|
|
1110
|
+
}
|
|
1111
|
+
return results;
|
|
1112
|
+
}
|
|
1113
|
+
async function update(config, opts) {
|
|
1114
|
+
log(`
|
|
1115
|
+
${colors.cyan}ConnectBase Update${colors.reset}
|
|
1116
|
+
`);
|
|
1117
|
+
const gitRoot = getGitRoot();
|
|
1118
|
+
const projectRoot = gitRoot || process.cwd();
|
|
1119
|
+
const monorepo = detectMonorepo(projectRoot);
|
|
1120
|
+
info("\uCD5C\uC2E0 \uBC84\uC804 \uD655\uC778 \uC911...");
|
|
1121
|
+
const latestVersion = await fetchLatestVersion("connectbase-client");
|
|
1122
|
+
if (latestVersion) {
|
|
1123
|
+
const cmp = compareVersions(VERSION, latestVersion);
|
|
1124
|
+
if (cmp >= 0) {
|
|
1125
|
+
success(`\uCD5C\uC2E0 \uBC84\uC804\uC785\uB2C8\uB2E4 (v${VERSION})`);
|
|
1126
|
+
} else {
|
|
1127
|
+
warn(`\uC0C8 \uBC84\uC804\uC774 \uC788\uC2B5\uB2C8\uB2E4: v${VERSION} \u2192 v${colors.green}${latestVersion}${colors.reset}`);
|
|
1128
|
+
log(` ${colors.cyan}npm install connectbase-client@latest${colors.reset}`);
|
|
1129
|
+
log(` ${colors.cyan}pnpm add connectbase-client@latest${colors.reset}`);
|
|
1130
|
+
log("");
|
|
1131
|
+
}
|
|
1132
|
+
} else {
|
|
1133
|
+
warn("npm \uB808\uC9C0\uC2A4\uD2B8\uB9AC\uC5D0\uC11C \uBC84\uC804 \uC815\uBCF4\uB97C \uAC00\uC838\uC62C \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
1134
|
+
}
|
|
1135
|
+
if (opts.checkOnly) {
|
|
1136
|
+
return;
|
|
1137
|
+
}
|
|
1138
|
+
if (monorepo.type !== "none") {
|
|
1139
|
+
info(`\uBAA8\uB178\uB808\uD3EC \uAC10\uC9C0: ${monorepo.type} (\uB8E8\uD2B8: ${projectRoot})`);
|
|
1140
|
+
const subPackages = findSubPackagesWithConfig(projectRoot);
|
|
1141
|
+
if (subPackages.length > 0) {
|
|
1142
|
+
info(`ConnectBase\uB97C \uC0AC\uC6A9\uD558\uB294 \uC11C\uBE0C \uD328\uD0A4\uC9C0 ${subPackages.length}\uAC1C \uBC1C\uACAC:`);
|
|
1143
|
+
for (const sp of subPackages) {
|
|
1144
|
+
log(` ${colors.dim}\u2022 ${path2.relative(projectRoot, sp)}${colors.reset}`);
|
|
1145
|
+
}
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
if (!opts.skipDocs) {
|
|
1149
|
+
log("");
|
|
1150
|
+
info("SDK \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8 \uC911...");
|
|
1151
|
+
let docsKey = config.publicKey || config.secretKey;
|
|
1152
|
+
if (!docsKey) {
|
|
1153
|
+
const rootRcPath = path2.join(projectRoot, ".connectbaserc");
|
|
1154
|
+
if (fs2.existsSync(rootRcPath)) {
|
|
1155
|
+
try {
|
|
1156
|
+
const rc = JSON.parse(fs2.readFileSync(rootRcPath, "utf-8"));
|
|
1157
|
+
docsKey = rc.publicKey || rc.secretKey;
|
|
1158
|
+
} catch {
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
}
|
|
1162
|
+
if (!docsKey && monorepo.type !== "none") {
|
|
1163
|
+
const subPackages = findSubPackagesWithConfig(projectRoot);
|
|
1164
|
+
for (const sp of subPackages) {
|
|
1165
|
+
try {
|
|
1166
|
+
const rc = JSON.parse(fs2.readFileSync(path2.join(sp, ".connectbaserc"), "utf-8"));
|
|
1167
|
+
if (rc.publicKey || rc.secretKey) {
|
|
1168
|
+
docsKey = rc.publicKey || rc.secretKey;
|
|
1169
|
+
break;
|
|
1170
|
+
}
|
|
1171
|
+
} catch {
|
|
1172
|
+
}
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
if (docsKey) {
|
|
1176
|
+
await downloadDocs(docsKey, void 0, projectRoot);
|
|
1177
|
+
} else {
|
|
1178
|
+
warn("Public Key\uB97C \uCC3E\uC744 \uC218 \uC5C6\uC5B4 \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4");
|
|
1179
|
+
info(".connectbaserc \uD30C\uC77C\uC774\uB098 --public-key \uC635\uC158\uC73C\uB85C \uD0A4\uB97C \uC9C0\uC815\uD558\uC138\uC694");
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
if (!opts.skipMcp) {
|
|
1183
|
+
log("");
|
|
1184
|
+
const mcpConfigPath = path2.join(projectRoot, ".mcp.json");
|
|
1185
|
+
if (fs2.existsSync(mcpConfigPath)) {
|
|
1186
|
+
let secretKey = config.secretKey;
|
|
1187
|
+
if (!secretKey) {
|
|
1188
|
+
const rootRcPath = path2.join(projectRoot, ".connectbaserc");
|
|
1189
|
+
if (fs2.existsSync(rootRcPath)) {
|
|
1190
|
+
try {
|
|
1191
|
+
const rc = JSON.parse(fs2.readFileSync(rootRcPath, "utf-8"));
|
|
1192
|
+
secretKey = rc.secretKey;
|
|
1193
|
+
} catch {
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
}
|
|
1197
|
+
if (!secretKey && monorepo.type !== "none") {
|
|
1198
|
+
const subPackages = findSubPackagesWithConfig(projectRoot);
|
|
1199
|
+
for (const sp of subPackages) {
|
|
1200
|
+
try {
|
|
1201
|
+
const rc = JSON.parse(fs2.readFileSync(path2.join(sp, ".connectbaserc"), "utf-8"));
|
|
1202
|
+
if (rc.secretKey) {
|
|
1203
|
+
secretKey = rc.secretKey;
|
|
1204
|
+
break;
|
|
1205
|
+
}
|
|
1206
|
+
} catch {
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
if (secretKey) {
|
|
1211
|
+
try {
|
|
1212
|
+
const mcpConfig = JSON.parse(fs2.readFileSync(mcpConfigPath, "utf-8"));
|
|
1213
|
+
const servers = mcpConfig.mcpServers || {};
|
|
1214
|
+
if (servers["connect-base"]) {
|
|
1215
|
+
servers["connect-base"] = {
|
|
1216
|
+
type: "http",
|
|
1217
|
+
url: "https://mcp.connectbase.world/mcp",
|
|
1218
|
+
headers: { Authorization: `Bearer ${secretKey}` }
|
|
1219
|
+
};
|
|
1220
|
+
mcpConfig.mcpServers = servers;
|
|
1221
|
+
fs2.writeFileSync(mcpConfigPath, JSON.stringify(mcpConfig, null, 2) + "\n");
|
|
1222
|
+
success("MCP \uC124\uC815 \uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC");
|
|
1223
|
+
} else {
|
|
1224
|
+
info('.mcp.json\uC5D0 connect-base \uD56D\uBAA9\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. "connectbase mcp"\uB85C \uC124\uC815\uD558\uC138\uC694');
|
|
1225
|
+
}
|
|
1226
|
+
} catch {
|
|
1227
|
+
warn(".mcp.json \uC5C5\uB370\uC774\uD2B8 \uC2E4\uD328");
|
|
1228
|
+
}
|
|
1229
|
+
} else {
|
|
1230
|
+
info("Secret Key\uAC00 \uC5C6\uC5B4 MCP \uC124\uC815 \uC5C5\uB370\uC774\uD2B8\uB97C \uAC74\uB108\uB701\uB2C8\uB2E4");
|
|
1231
|
+
}
|
|
1232
|
+
} else {
|
|
1233
|
+
info('.mcp.json\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. "connectbase mcp"\uB85C \uCD5C\uCD08 \uC124\uC815\uD558\uC138\uC694');
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
if (opts.setupRoot || monorepo.type !== "none" && monorepo.isSubPackage) {
|
|
1237
|
+
log("");
|
|
1238
|
+
setupMonorepoRoot(projectRoot, monorepo);
|
|
1239
|
+
}
|
|
1240
|
+
log(`
|
|
1241
|
+
${colors.green}\uC5C5\uB370\uC774\uD2B8 \uC644\uB8CC!${colors.reset}
|
|
1242
|
+
`);
|
|
1243
|
+
}
|
|
1244
|
+
function setupMonorepoRoot(projectRoot, monorepo) {
|
|
1245
|
+
const rootPkgPath = path2.join(projectRoot, "package.json");
|
|
1246
|
+
if (!fs2.existsSync(rootPkgPath)) {
|
|
1247
|
+
warn("\uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 package.json\uC774 \uC5C6\uC5B4 \uD3B8\uC758 \uC2A4\uD06C\uB9BD\uD2B8\uB97C \uCD94\uAC00\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4");
|
|
1248
|
+
return;
|
|
1249
|
+
}
|
|
1250
|
+
try {
|
|
1251
|
+
const pkg = JSON.parse(fs2.readFileSync(rootPkgPath, "utf-8"));
|
|
1252
|
+
if (!pkg.scripts) pkg.scripts = {};
|
|
1253
|
+
let changed = false;
|
|
1254
|
+
if (!pkg.scripts["cb:update"]) {
|
|
1255
|
+
pkg.scripts["cb:update"] = "npx connectbase update";
|
|
1256
|
+
changed = true;
|
|
1257
|
+
}
|
|
1258
|
+
if (!pkg.scripts["cb:docs"]) {
|
|
1259
|
+
pkg.scripts["cb:docs"] = "npx connectbase docs";
|
|
1260
|
+
changed = true;
|
|
1261
|
+
}
|
|
1262
|
+
if (!pkg.scripts["cb:mcp"]) {
|
|
1263
|
+
pkg.scripts["cb:mcp"] = "npx connectbase mcp";
|
|
1264
|
+
changed = true;
|
|
1265
|
+
}
|
|
1266
|
+
if (changed) {
|
|
1267
|
+
fs2.writeFileSync(rootPkgPath, JSON.stringify(pkg, null, 2) + "\n");
|
|
1268
|
+
success("\uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8\uC5D0 \uD3B8\uC758 \uC2A4\uD06C\uB9BD\uD2B8 \uCD94\uAC00 \uC644\uB8CC");
|
|
1269
|
+
log(` ${colors.dim}\uC0AC\uC6A9\uBC95:${colors.reset}`);
|
|
1270
|
+
log(` ${colors.cyan}${monorepo.type === "pnpm" ? "pnpm" : monorepo.type === "yarn" ? "yarn" : "npm run"} cb:update${colors.reset} \u2014 SDK \uC5C5\uB370\uC774\uD2B8 + \uBB38\uC11C \uAC31\uC2E0`);
|
|
1271
|
+
log(` ${colors.cyan}${monorepo.type === "pnpm" ? "pnpm" : monorepo.type === "yarn" ? "yarn" : "npm run"} cb:docs${colors.reset} \u2014 \uBB38\uC11C\uB9CC \uAC31\uC2E0`);
|
|
1272
|
+
log(` ${colors.cyan}${monorepo.type === "pnpm" ? "pnpm" : monorepo.type === "yarn" ? "yarn" : "npm run"} cb:mcp${colors.reset} \u2014 MCP \uC124\uC815`);
|
|
1273
|
+
} else {
|
|
1274
|
+
info("\uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8\uC5D0 \uC774\uBBF8 \uD3B8\uC758 \uC2A4\uD06C\uB9BD\uD2B8\uAC00 \uC124\uC815\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4");
|
|
1275
|
+
}
|
|
1276
|
+
} catch {
|
|
1277
|
+
warn("\uB8E8\uD2B8 package.json \uC218\uC815\uC5D0 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4");
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1046
1280
|
function createWsTextFrame(payload) {
|
|
1047
1281
|
const data = Buffer.from(payload, "utf-8");
|
|
1048
1282
|
const len = data.length;
|
|
@@ -1576,13 +1810,14 @@ ${colors.dim}Ctrl+C\uB85C \uC885\uB8CC${colors.reset}
|
|
|
1576
1810
|
}
|
|
1577
1811
|
function showHelp() {
|
|
1578
1812
|
log(`
|
|
1579
|
-
${colors.cyan}connectbase
|
|
1813
|
+
${colors.cyan}connectbase${colors.reset} - Connect Base SDK & CLI
|
|
1580
1814
|
|
|
1581
1815
|
${colors.yellow}\uC0AC\uC6A9\uBC95:${colors.reset}
|
|
1582
|
-
npx connectbase
|
|
1816
|
+
npx connectbase <command> [options]
|
|
1583
1817
|
|
|
1584
1818
|
${colors.yellow}\uBA85\uB839\uC5B4:${colors.reset}
|
|
1585
1819
|
init \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (\uC571 \uC0DD\uC131, MCP \uC124\uC815, SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC)
|
|
1820
|
+
update SDK \uBC84\uC804 \uCCB4\uD06C + \uBB38\uC11C/MCP \uC77C\uAD04 \uC5C5\uB370\uC774\uD2B8 (\uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8 \uC9C0\uC6D0)
|
|
1586
1821
|
docs SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC/\uC5C5\uB370\uC774\uD2B8 (\uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
|
|
1587
1822
|
mcp MCP \uC11C\uBC84 \uC124\uC815 (.mcp.json \uC0DD\uC131/\uC5C5\uB370\uC774\uD2B8, \uBAA8\uB178\uB808\uD3EC \uC790\uB3D9 \uAC10\uC9C0)
|
|
1588
1823
|
deploy <directory> \uC6F9 \uC2A4\uD1A0\uB9AC\uC9C0\uC5D0 \uD30C\uC77C \uBC30\uD3EC (--dev: Dev \uD658\uACBD)
|
|
@@ -1603,25 +1838,35 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
|
|
|
1603
1838
|
--max-body <MB> \uD130\uB110 \uCD5C\uB300 \uBC14\uB514 \uD06C\uAE30 (MB, tunnel \uC804\uC6A9)
|
|
1604
1839
|
--force \uD130\uB110 lockfile \uBB34\uC2DC (\uC911\uBCF5 \uC2E4\uD589 \uAC15\uC81C, tunnel \uC804\uC6A9)
|
|
1605
1840
|
-d, --dev Dev \uD658\uACBD\uC5D0 \uBC30\uD3EC (deploy \uC804\uC6A9)
|
|
1606
|
-
|
|
1841
|
+
--check \uBC84\uC804\uB9CC \uD655\uC778 (update \uC804\uC6A9)
|
|
1842
|
+
--skip-docs \uBB38\uC11C \uC5C5\uB370\uC774\uD2B8 \uAC74\uB108\uB6F0\uAE30 (update \uC804\uC6A9)
|
|
1843
|
+
--skip-mcp MCP \uC5C5\uB370\uC774\uD2B8 \uAC74\uB108\uB6F0\uAE30 (update \uC804\uC6A9)
|
|
1844
|
+
--setup-root \uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8\uC5D0 \uD3B8\uC758 \uC2A4\uD06C\uB9BD\uD2B8 \uCD94\uAC00 (update \uC804\uC6A9)
|
|
1845
|
+
(docs, mcp, update\uB294 \uBAA8\uB178\uB808\uD3EC\uB97C \uC790\uB3D9 \uAC10\uC9C0\uD558\uC5EC \uD504\uB85C\uC81D\uD2B8 \uB8E8\uD2B8\uC5D0 \uC0DD\uC131)
|
|
1607
1846
|
-h, --help \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC
|
|
1608
1847
|
-v, --version \uBC84\uC804 \uD45C\uC2DC
|
|
1609
1848
|
|
|
1610
1849
|
${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
|
|
1611
1850
|
${colors.dim}# 1. \uCD08\uAE30\uD654 (\uCD5C\uCD08 1\uD68C)${colors.reset}
|
|
1612
|
-
npx connectbase
|
|
1851
|
+
npx connectbase init
|
|
1852
|
+
|
|
1853
|
+
${colors.dim}# 2. SDK \uC804\uCCB4 \uC5C5\uB370\uC774\uD2B8 (\uBC84\uC804 \uCCB4\uD06C + \uBB38\uC11C + MCP)${colors.reset}
|
|
1854
|
+
npx connectbase update
|
|
1613
1855
|
|
|
1614
|
-
${colors.dim}# 2.
|
|
1856
|
+
${colors.dim}# 2-1. \uBAA8\uB178\uB808\uD3EC \uB8E8\uD2B8\uC5D0 \uD3B8\uC758 \uC2A4\uD06C\uB9BD\uD2B8 \uC124\uCE58${colors.reset}
|
|
1857
|
+
npx connectbase update --setup-root
|
|
1858
|
+
|
|
1859
|
+
${colors.dim}# 3. SDK \uBB38\uC11C\uB9CC \uC5C5\uB370\uC774\uD2B8${colors.reset}
|
|
1615
1860
|
npx connectbase docs
|
|
1616
1861
|
|
|
1617
|
-
${colors.dim}#
|
|
1862
|
+
${colors.dim}# 4. MCP \uC11C\uBC84 \uC124\uC815${colors.reset}
|
|
1618
1863
|
npx connectbase mcp
|
|
1619
1864
|
|
|
1620
1865
|
${colors.dim}# 4. Prod \uBC30\uD3EC${colors.reset}
|
|
1621
1866
|
npm run deploy
|
|
1622
1867
|
|
|
1623
1868
|
${colors.dim}# 4. Dev \uD658\uACBD \uBC30\uD3EC (\uB0B4\uBD80 QA\uC6A9)${colors.reset}
|
|
1624
|
-
npx connectbase
|
|
1869
|
+
npx connectbase deploy ./dist --dev
|
|
1625
1870
|
|
|
1626
1871
|
${colors.dim}# 5. \uD130\uB110 (\uAE30\uBCF8)${colors.reset}
|
|
1627
1872
|
npx connectbase tunnel 3000
|
|
@@ -1671,6 +1916,14 @@ function parseArgs(args) {
|
|
|
1671
1916
|
result.options.force = "true";
|
|
1672
1917
|
} else if (arg === "-d" || arg === "--dev") {
|
|
1673
1918
|
result.options.dev = "true";
|
|
1919
|
+
} else if (arg === "--check") {
|
|
1920
|
+
result.options.check = "true";
|
|
1921
|
+
} else if (arg === "--skip-docs") {
|
|
1922
|
+
result.options.skipDocs = "true";
|
|
1923
|
+
} else if (arg === "--skip-mcp") {
|
|
1924
|
+
result.options.skipMcp = "true";
|
|
1925
|
+
} else if (arg === "--setup-root") {
|
|
1926
|
+
result.options.setupRoot = "true";
|
|
1674
1927
|
} else if (arg === "-h" || arg === "--help") {
|
|
1675
1928
|
result.options.help = "true";
|
|
1676
1929
|
} else if (arg === "-v" || arg === "--version") {
|
|
@@ -1689,7 +1942,7 @@ function parseArgs(args) {
|
|
|
1689
1942
|
async function main() {
|
|
1690
1943
|
const parsed = parseArgs(process.argv.slice(2));
|
|
1691
1944
|
if (parsed.options.version) {
|
|
1692
|
-
log(`connectbase
|
|
1945
|
+
log(`connectbase v${VERSION}`);
|
|
1693
1946
|
return;
|
|
1694
1947
|
}
|
|
1695
1948
|
if (parsed.options.help || !parsed.command) {
|
|
@@ -1705,6 +1958,13 @@ async function main() {
|
|
|
1705
1958
|
};
|
|
1706
1959
|
if (parsed.command === "init") {
|
|
1707
1960
|
await init();
|
|
1961
|
+
} else if (parsed.command === "update") {
|
|
1962
|
+
await update(config, {
|
|
1963
|
+
checkOnly: parsed.options.check === "true",
|
|
1964
|
+
skipDocs: parsed.options.skipDocs === "true",
|
|
1965
|
+
skipMcp: parsed.options.skipMcp === "true",
|
|
1966
|
+
setupRoot: parsed.options.setupRoot === "true"
|
|
1967
|
+
});
|
|
1708
1968
|
} else if (parsed.command === "docs") {
|
|
1709
1969
|
let docsPublicKey = config.publicKey ?? config.publicKey;
|
|
1710
1970
|
if (!docsPublicKey) {
|
|
@@ -1720,11 +1980,11 @@ async function main() {
|
|
|
1720
1980
|
} else if (parsed.command === "deploy") {
|
|
1721
1981
|
const directory = parsed.args[0] || fileConfig.deployDir || ".";
|
|
1722
1982
|
if (!config.publicKey && !config.publicKey) {
|
|
1723
|
-
error('Public Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase
|
|
1983
|
+
error('Public Key\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -k \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694');
|
|
1724
1984
|
process.exit(1);
|
|
1725
1985
|
}
|
|
1726
1986
|
if (!config.storageId) {
|
|
1727
|
-
error('\uC2A4\uD1A0\uB9AC\uC9C0 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase
|
|
1987
|
+
error('\uC2A4\uD1A0\uB9AC\uC9C0 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -s \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694');
|
|
1728
1988
|
process.exit(1);
|
|
1729
1989
|
}
|
|
1730
1990
|
const isDev = parsed.options.dev === "true";
|
|
@@ -1732,7 +1992,7 @@ async function main() {
|
|
|
1732
1992
|
} else if (parsed.command === "tunnel") {
|
|
1733
1993
|
const portStr = parsed.args[0];
|
|
1734
1994
|
if (!portStr) {
|
|
1735
|
-
error("\uD3EC\uD2B8 \uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: npx connectbase
|
|
1995
|
+
error("\uD3EC\uD2B8 \uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: npx connectbase tunnel 8084");
|
|
1736
1996
|
process.exit(1);
|
|
1737
1997
|
}
|
|
1738
1998
|
const port = parseInt(portStr, 10);
|