connectbase-client 0.16.0 → 1.2.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 ADDED
@@ -0,0 +1,205 @@
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
+ ## [1.2.0] - 2026-04-18
7
+
8
+ Replay SDK 4개 메서드 활성화. 백엔드가 `REPLAY_STORAGE_PATH` 환경변수로 replay 저장소를 구성한 경우에만 동작하며, 미설정 시 SDK 가 명시적 에러를 throw (404 분기).
9
+
10
+ ### Added
11
+
12
+ - **Replay**: `cb.game.listReplays/getReplay/downloadReplay/getReplayHighlights` 활성화 (backend `/v1/game/:appID/replays/*`). 서버의 `REPLAY_STORAGE_PATH` 설정 여부에 따라 파일 스토리지 기반으로 동작. 서버 미구성 시 `cb.game.listReplays: replay storage is not configured on this server (REPLAY_STORAGE_PATH unset).` 형태의 명확한 에러 발생.
13
+
14
+ ## [1.1.0] - 2026-04-18
15
+
16
+ game-server 의 party/spectator/ranking/voice public 라우트 오픈에 맞춰 SDK 의 throw 해제. 백엔드 미제공 기능은 여전히 throw 로 남김.
17
+
18
+ ### Added
19
+
20
+ - **Party**: `cb.game.createParty/leaveParty/kickFromParty/inviteToParty/sendPartyChat` 활성화 (backend `/v1/game/:appID/parties/...`). `joinParty` 는 백엔드에 직접 join 엔드포인트가 없어서 `inviteToParty` → `acceptInvite` 플로우로 대체 — `joinParty` 호출 시 해당 안내 Error throw.
21
+ - **Spectator**: `cb.game.joinSpectator/leaveSpectator/getSpectators` 활성화 (backend `/v1/game/:appID/rooms/:roomID/spectators`).
22
+ - **Ranking**: `cb.game.getLeaderboard/getPlayerStats/getPlayerRank` 활성화. **시그니처 변경** — 백엔드가 `game_type` 쿼리를 필수로 요구하므로 SDK 에서도 첫 인자로 `gameType` 을 받음. `getLeaderboard(gameType, top?, season?)`, `getPlayerStats(playerId, gameType, season?)`, `getPlayerRank(playerId, gameType, season?)`.
23
+ - **Voice**: `cb.game.joinVoiceChannel` 활성화 (backend `/v1/game/:appID/voice/rooms/:roomID/join`).
24
+
25
+ ### Still disabled (throws Error — 백엔드 public 경로 미제공)
26
+
27
+ - `cb.game.createRoom`, `cb.game.deleteRoom` — 콘솔 전용
28
+ - `cb.game.joinParty` — 초대 수락 플로우 사용
29
+ - `cb.game.listReplays`, `getReplay`, `downloadReplay`, `getReplayHighlights` — replay 스토리지 아직 미연결
30
+
31
+ ## [1.0.0] - 2026-04-18
32
+
33
+ 문서-코드 정합성 9라운드 감사 후속. 런타임 동작이 실제 백엔드와 일치하지 않던 메서드들을 정정. `GoogleConnectionStatus` shape 변경은 breaking change 이므로 major bump.
34
+
35
+ ### Breaking
36
+
37
+ - **`ads.getConnectionStatus()` 반환 타입 중첩 구조로 변경**: 백엔드 실제 응답(`{adsense, admob}`) 과 불일치하여 `.admob_account_id` 접근 시 `undefined` 였음. 이제 `status.adsense.is_connected`, `status.adsense.account_id`, `status.admob.is_connected`, `status.admob.account_id`, `status.admob.publisher_id` 로 접근. `AdsenseConnectionInfo`, `AdmobConnectionInfo` 타입 추가 export.
38
+ - **game.ts 다수 메서드에 public 경로 미오픈 Error throw 적용** (호출 시 즉시 Error): `createRoom`, `deleteRoom`, `createParty`/`joinParty`/`leaveParty`/`kickFromParty`/`inviteToParty`/`sendPartyChat`, `joinSpectator`/`leaveSpectator`/`getSpectators`, `getLeaderboard`/`getPlayerStats`/`getPlayerRank`, `joinVoiceChannel`, `listReplays`/`getReplay`/`downloadReplay`/`getReplayHighlights`. 기존에도 백엔드 경로가 admin 전용이라 404 였으나, 침묵 실패 대신 명시적 에러로 전환. 해당 기능은 콘솔에서 진행하거나 백엔드 public 경로 오픈 요청 필요.
39
+
40
+ ### Fixed
41
+
42
+ - **`webrtc.getICEServers()` / `getStats()` / `getRooms()` 경로 정정**: 각각 `/v1/ice-servers`, `/v1/apps/:appID/webrtc/stats`, `/v1/apps/:appID/webrtc/rooms` 로 호출하여 404. 실제 webrtc-server 는 `/v1/apps/:appID/ice-servers`, `/stats`, `/rooms` 로 노출됨. `getICEServers` 는 이제 `this.appId` 를 사용하며 없으면 Error.
43
+ - **`storage.moveFile()` / `renameFile()` Public Key 404 명시적 에러**: 해당 라우트는 `/v1/public/...` 에 노출되어 있지 않음. Public Key 만 있고 JWT 없을 때 호출하면 이제 즉시 명시적 Error. JWT 인증 시 `/v1/storages/...` 로 정상 호출.
44
+
45
+ ### Changed
46
+
47
+ - `HttpClient.hasJWT()` 메서드 추가 — Access Token(JWT) 존재 여부 확인용.
48
+ - `payment.prepare()` JSDoc 예제를 Toss Payments V2 시그니처(`payment.requestPayment({ method, amount: { currency, value }, ... })`) 로 갱신.
49
+
50
+ ### Documentation
51
+
52
+ - `KnowledgeSearchRequest`, `ImportDataRequest` 타입에 JSDoc `@example` 추가 — IDE 자동완성 툴팁 보강.
53
+
54
+ ## [0.16.1] - 2026-04-17
55
+
56
+ MCP/SDK 문서-코드 정합성 검증에서 발견된 불일치 소규모 정정. 런타임 동작 변경은 없으며, 이전 릴리스에서 도입된 타입 회귀를 롤백.
57
+
58
+ ### Fixed
59
+
60
+ - **`FetchDataResponse` 필드명 회귀 롤백**: `0.16.0` 에서 `datas→data`, `total_size→total_count` 로 바꿨으나 실제 서버 wire 는 여전히 `datas` / `total_size` 였음. 타입 정의를 서버 응답 그대로 `{ datas, total_size }` 로 되돌려 런타임 미스매치 제거.
61
+ - `cb.push.subscribeTopic()` JSDoc 예제가 `device_token` 인자 누락된 구 시그니처로 표기되던 문제 정정 (실 시그니처는 `subscribeTopic(deviceToken, topic)`).
62
+ - CLI 안내 문구·`setupMonorepoRoot` 로 추가되는 `cb:update`/`cb:docs`/`cb:mcp` 스크립트가 `connectbase-client` 를 가리키던 것을 정규 bin 이름인 `connectbase` 로 통일. 두 bin 은 모두 동작하지만 문서와 자동 생성 스크립트는 단일 이름 기준으로 일관화.
63
+
64
+ ### Documentation
65
+
66
+ - README `### Push Notifications` 섹션의 예제를 실제 공개 API 와 일치하도록 수정: `push.register()` / `push.subscribeToTopic()` / `push.unsubscribeFromTopic()` (존재하지 않는 메서드) → `push.registerDevice()` / `push.subscribeTopic(deviceToken, topic)` / `push.unsubscribeTopic(deviceToken, topic)` / Web Push 등록 예제 추가.
67
+
68
+ ### Changed
69
+
70
+ - `package.json` 메타데이터 보강: `author`, `homepage`, `bugs`, `sideEffects: false` 필드 추가, `files` 에 `LICENSE`/`CHANGELOG.md`/`README.md` 명시적 포함.
71
+ - 저장소 루트에 `LICENSE` (MIT) 파일 신설 (이전에는 `license: "MIT"` 선언만 존재).
72
+
73
+ ## [0.16.0] - 2026-04-17
74
+
75
+ CLI `update` 커맨드와 신규 저장소 API 옵션, 토큰 영속성 옵션 추가. 일부 타입 정정.
76
+
77
+ ### Added
78
+
79
+ - **CLI `update` 커맨드**: 현재 설치된 `connectbase-client` 버전을 npm 과 비교하고 `docs`·`mcp` 산출물을 일괄 최신화.
80
+ - **모노레포 지원**: `connectbase init --setup-root` 로 모노레포 루트 `package.json` 에 `cb:update`/`cb:docs`/`cb:mcp` 편의 스크립트 설치.
81
+ - **Storage `getFiles()` `parentId` 옵션**: 특정 폴더 하위 파일 목록 조회 지원.
82
+ - **토큰 영속성(persistence) 옵션**: `new ConnectBase({ persistence: 'localStorage' | 'sessionStorage' | 'none' })`.
83
+ - `localStorage` (기본값): 브라우저 종료 후에도 토큰 유지.
84
+ - `sessionStorage`: 탭 종료 시 삭제.
85
+ - `none`: 메모리에만 저장.
86
+ - 생성자에서 저장된 토큰 자동 복원 (명시적 토큰 전달 시 스킵). SSR 환경(`window` undefined) 안전 처리.
87
+ - **OAuthProvider 확장**: `kakao`, `apple` 프로바이더 추가 (서버 enum 과 동기화).
88
+
89
+ ### Changed
90
+
91
+ - `VERSION` 상수가 `package.json` 에서 동적으로 로드되도록 변경 (이전: `0.10.6` 하드코딩).
92
+ - `FetchDataResponse` 필드명 변경: `datas` → `data`, `total_size` → `total_count` (서버 응답과 일치를 의도함).
93
+ - **⚠️ 본 변경은 실제 서버 wire 와 맞지 않는 회귀였으며 `0.16.1` 에서 롤백됩니다.** `0.16.0` 사용자는 `0.16.1` 이상으로 즉시 업그레이드 권장.
94
+
95
+ ### Documentation
96
+
97
+ - SDK 문서 전체 감사 및 누락 섹션 보강.
98
+
99
+ ## [0.15.0] - 2026-04-16
100
+
101
+ Web Analytics SDK 모듈 신설 및 터널 유틸 리팩터.
102
+
103
+ ### Added
104
+
105
+ - **AnalyticsAPI** 모듈 (`cb.analytics`): `init` / `trackEvent` / `trackPageView` / `identify` / `setConsent` / `enableHeatmap` / `enableHeartbeat` / `destroy`.
106
+ - **SessionManager**: 30분 타임아웃, `visitor_uid` localStorage 영속화.
107
+ - 백엔드 측 12개 서비스·9개 Ent 스키마(이벤트/퍼널/세션/코호트/어트리뷰션/세그먼트/A-B 테스트/히트맵/녹화/프라이버시) 와 매칭.
108
+
109
+ ### Changed
110
+
111
+ - CLI 내부에서 tunnel 관련 로직을 `src/tunnel-utils.ts` 로 추출 (테스트 용이성 확보).
112
+ - `vitest` 도입 및 tunnel/analytics 단위 테스트 23건 추가.
113
+
114
+ ## [0.14.0] - 2026-04-15
115
+
116
+ Tunnel 안정성 개선.
117
+
118
+ ### Added
119
+
120
+ - **Tunnel lockfile**: 앱+포트 기반 lockfile 로 동일 터널 중복 실행을 차단. stale lockfile 자동 감지(PID 생존 확인).
121
+ - `--force` 플래그: lockfile 무시 옵션.
122
+
123
+ ### Changed
124
+
125
+ - 서버의 `tunnel_error code=replaced` 수신 시 재연결을 중단하고 안내 메시지 출력 (이전에는 끊임없이 재연결 시도).
126
+ - `TunnelMessage` 타입에 `code` / `error` / `message` 필드 추가.
127
+
128
+ ## [0.13.0] - 2026-04-14
129
+
130
+ Database API 정합성 및 완성도 대규모 개선.
131
+
132
+ ### Breaking Changes
133
+
134
+ - **`TableSchema` 응답 구조 전면 재정의**: 서버 ent 모델 (`backend/cmd/data-server/ent/schema/table.go`) 과 1:1 일치하도록 변경.
135
+ - `name` → `title`
136
+ - `columns: ColumnSchema[]` → `schema: TableSchemaDefinition` (평면 또는 중첩 맵)
137
+ - `created_at` → `create_time` (※ G2 작업에서 다시 `created_at` 로 표준화 예정)
138
+ - `updated_at` → `update_time`
139
+ - 신규 필드: `app_id`, `access_level`, `is_active`, `validation_schema?`
140
+ - **`CreateTableRequest` 형태 변경**: 서버 DTO 와 일치.
141
+ - `schema?: TableSchemaDefinition` 신규 필드. 평면 맵 (`{email: 'string'}`) 또는 중첩 객체 (`{email: {type: 'string', required: true}}`) 모두 지원. `$required` 키로 필수 컬럼 지정.
142
+ - `accessLevel?: 'Creator' | 'Public' | 'AppMember'` (기본 `'Creator'`)
143
+ - `description` 은 `@deprecated` — 서버에 저장되지 않음
144
+ - **`createTable()` 반환 타입**: `Promise<TableSchema>` → `Promise<void>`. 서버는 `{message}` 만 반환하므로 거짓 타입 제거.
145
+ - **`createColumn()` / `updateColumn()` 반환 타입**: 동일한 이유로 `Promise<void>` 로 변경.
146
+ - **`updateTable()` 시맨틱 정정**: PATCH 부분 업데이트가 정상 동작. 이전 버전에서는 모든 필드가 required 라 부분 업데이트 시 400 오류가 발생했음.
147
+ - **`DataType` 정렬**: 서버 `ValidSchemaTypes` 와 일치하도록 변경.
148
+ - 제거: `'boolean'`
149
+ - 추가: `'int'`, `'bool'`, `'uuid'`
150
+ - 최종 union: `'string' | 'int' | 'number' | 'bool' | 'uuid' | 'date' | 'object' | 'array'`
151
+ - **`CreateColumnRequest`**:
152
+ - `is_required` 가 optional 로 변경 (기본 false)
153
+ - `default_value` 타입 `string` → `unknown` (서버는 임의 타입 허용)
154
+ - `order`, `validation_rule` 은 `@deprecated` (서버 미지원)
155
+ - **`UpdateColumnRequest`**:
156
+ - `default_value` 타입 `string` → `unknown`
157
+ - `name` `@deprecated` (서버는 컬럼 rename 미지원)
158
+ - `order`, `validation_rule` `@deprecated`
159
+ - **`ColumnSchema`**:
160
+ - SDK 가 합성하는 객체임을 명시
161
+ - `default_value` 타입 `string` → `unknown`
162
+ - `created_at` 은 테이블의 `create_time` 으로 대체 (컬럼 개별 타임스탬프 없음)
163
+ - `order` 는 SDK 가 부여한 인덱스
164
+ - `updated_at`, `validation_rule` `@deprecated`
165
+
166
+ ### Added
167
+
168
+ - `TableSchemaDefinition` interface — 컬럼 정의 맵 타입. 플랫 / 중첩 / `$required` 모두 지원.
169
+ - `TableColumnDef` union type — 단일 컬럼 정의 (플랫 string 또는 중첩 객체).
170
+ - `TableAccessLevel` type — `'Creator' | 'Public' | 'AppMember'`.
171
+ - `database.createTable()` 가 초기 schema 와 access level 을 한 번에 받아 1-step 생성 지원.
172
+ - `database.getColumns()` 가 플랫 / 중첩 schema 모두 정확히 파싱.
173
+ - `database` 모듈의 `getPublicPrefix()` 가 항상 `/v1/public` 반환 (이전: 인증 종류에 따라 `/v1/public` 또는 `/v1` — 후자는 dead path).
174
+ - `database.getValidationSchema()`, `setValidationSchema()`, `deleteValidationSchema()` — 테이블 검증 스키마 CRUD.
175
+ - `MemberInfoResponse` 에 `email?`, `role?` 필드 추가 — RLS `auth.email`/`auth.role` 과 일치.
176
+ - MCP `update_column` 툴 신설 (description, encrypted, data_type, is_required, default_value 변경).
177
+ - MCP `get_validation_schema`, `set_validation_schema`, `delete_validation_schema` 툴 신설.
178
+
179
+ ### Fixed
180
+
181
+ - **🔴 `database.createTable()` 가 어떤 키로도 동작하지 않던 broken 상태 해결**.
182
+ - Public Key 경로: 요청 body 가 서버 DTO 와 불일치 (필드명 `name`/`title`, 누락 `access_level`, 빈 `schema`)
183
+ - Secret Key 경로: 존재하지 않는 `/v1/tables` 경로 호출 → 404
184
+ - 두 경로 모두 본 릴리스에서 정상 동작.
185
+ - **MCP `create_table` 툴이 빈 schema 거부로 항상 실패** 하던 문제 해결 (서버 hook 이 explicit 빈 맵을 거부했음). 서버 DTO/repository/MCP tool 세 곳을 동시에 수정.
186
+ - 서버 측 `CreateTableRequest.Schema` 가 `binding:"required"` 였으나 schema 생략 가능하도록 변경.
187
+ - 서버 측 `EditTableInternal` (PATCH) 가 full-replace 시맨틱이라 부분 업데이트 불가능했던 문제 해결. `PatchTableRequest` DTO 와 `PatchTable` repository 메서드 신설.
188
+ - MCP `create_column`, `update_column` 툴의 `data_type` enum 이 `'boolean'` 을 포함했으나 서버는 `'bool'` 만 허용 → 정정.
189
+ - `getColumns()` 가 플랫 schema (`"email": "string"`) 를 모두 `'string'` 으로 잘못 반환하던 문제 해결.
190
+
191
+ ### Documentation
192
+
193
+ - `secretKey` 의 JSDoc 명확화: 앱 DB API 에는 사용 불가, CLI / tunnel 전용임을 명시.
194
+ - embedded SDK 문서 (04-sdk-database.md, 11-mcp-tools.md, 25-app-packaging.md) 의 `boolean` → `bool`, `auth.email`/`auth.role` 정합성 정리, `createTable` 예제 갱신.
195
+ - `TableSchemaDefinition` 의 `$required` 키 사용법, `TableColumnDef` 평면/중첩 형태 모두 JSDoc 예제 포함.
196
+
197
+ ### Notes
198
+
199
+ 본 변경의 대부분은 backwards-incompat 이지만, 이전 버전 (`0.12.x`) 의 `createTable` 자체가 broken 상태였으므로 해당 메서드를 사용하던 코드는 어차피 동작하지 않았습니다. read 메서드 (`getTables`, `getTable`, `getColumns`) 는 사용자 코드가 escape-hatch 캐스팅 (`as any`) 으로 우회하던 경우만 영향받습니다.
200
+
201
+ ---
202
+
203
+ ## [0.12.2] - 2026-04-?? (이전)
204
+
205
+ 이전 릴리스 — 본 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-client init
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-client deploy ./dist -s <storage-id> -k <public-key>
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-client tunnel 8084 -k <public-key>
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-client tunnel 8084
143
+ npx connectbase tunnel 8084
144
144
 
145
145
  # For GPU servers or long-running tasks (e.g., image generation)
146
- npx connectbase-client tunnel 7860 --timeout 300 --max-body 50
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-client deploy ./dist
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 { data } = await cb.database.getData('table-id', {
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 { data } = await cb.database.getData('table-id', {
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 { data } = await cb.database.getData('table-id', {
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 push notifications
768
- await cb.push.register({
769
- token: 'fcm-token-or-apns-token',
770
- platform: 'android' // or 'ios', 'web'
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 topics
774
- await cb.push.subscribeToTopic('news')
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.unsubscribeFromTopic('news')
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
@@ -311,8 +311,8 @@ async function deploy(directory, config, isDev = false) {
311
311
  try {
312
312
  const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
313
313
  if (pkg.scripts?.build) {
314
- warn(`\uBC30\uD3EC \uC804 \uBE4C\uB4DC\uB97C \uBA3C\uC800 \uC2E4\uD589\uD558\uC138\uC694: ${colors.cyan}npm run build && npx connectbase-client 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-client init${colors.reset}`);
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}`);
316
316
  }
317
317
  } catch {
318
318
  }
@@ -793,7 +793,7 @@ function addDeployScript(deployDir) {
793
793
  info(`package.json\uC5D0 \uC774\uBBF8 deploy \uC2A4\uD06C\uB9BD\uD2B8\uAC00 \uC788\uC2B5\uB2C8\uB2E4: "${pkg.scripts.deploy}"`);
794
794
  return;
795
795
  }
796
- const deployCmd = `connectbase-client deploy ${deployDir}`;
796
+ const deployCmd = `connectbase deploy ${deployDir}`;
797
797
  pkg.scripts.deploy = pkg.scripts.build ? `${pkg.scripts.build} && ${deployCmd}` : deployCmd;
798
798
  fs2.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
799
799
  success(`package.json\uC5D0 deploy \uC2A4\uD06C\uB9BD\uD2B8 \uCD94\uAC00 \uC644\uB8CC`);
@@ -1252,15 +1252,15 @@ function setupMonorepoRoot(projectRoot, monorepo) {
1252
1252
  if (!pkg.scripts) pkg.scripts = {};
1253
1253
  let changed = false;
1254
1254
  if (!pkg.scripts["cb:update"]) {
1255
- pkg.scripts["cb:update"] = "npx connectbase-client update";
1255
+ pkg.scripts["cb:update"] = "npx connectbase update";
1256
1256
  changed = true;
1257
1257
  }
1258
1258
  if (!pkg.scripts["cb:docs"]) {
1259
- pkg.scripts["cb:docs"] = "npx connectbase-client docs";
1259
+ pkg.scripts["cb:docs"] = "npx connectbase docs";
1260
1260
  changed = true;
1261
1261
  }
1262
1262
  if (!pkg.scripts["cb:mcp"]) {
1263
- pkg.scripts["cb:mcp"] = "npx connectbase-client mcp";
1263
+ pkg.scripts["cb:mcp"] = "npx connectbase mcp";
1264
1264
  changed = true;
1265
1265
  }
1266
1266
  if (changed) {
@@ -1810,10 +1810,10 @@ ${colors.dim}Ctrl+C\uB85C \uC885\uB8CC${colors.reset}
1810
1810
  }
1811
1811
  function showHelp() {
1812
1812
  log(`
1813
- ${colors.cyan}connectbase-client${colors.reset} - Connect Base SDK & CLI
1813
+ ${colors.cyan}connectbase${colors.reset} - Connect Base SDK & CLI
1814
1814
 
1815
1815
  ${colors.yellow}\uC0AC\uC6A9\uBC95:${colors.reset}
1816
- npx connectbase-client <command> [options]
1816
+ npx connectbase <command> [options]
1817
1817
 
1818
1818
  ${colors.yellow}\uBA85\uB839\uC5B4:${colors.reset}
1819
1819
  init \uD504\uB85C\uC81D\uD2B8 \uCD08\uAE30\uD654 (\uC571 \uC0DD\uC131, MCP \uC124\uC815, SDK \uBB38\uC11C \uB2E4\uC6B4\uB85C\uB4DC)
@@ -1848,7 +1848,7 @@ ${colors.yellow}\uC635\uC158:${colors.reset}
1848
1848
 
1849
1849
  ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
1850
1850
  ${colors.dim}# 1. \uCD08\uAE30\uD654 (\uCD5C\uCD08 1\uD68C)${colors.reset}
1851
- npx connectbase-client init
1851
+ npx connectbase init
1852
1852
 
1853
1853
  ${colors.dim}# 2. SDK \uC804\uCCB4 \uC5C5\uB370\uC774\uD2B8 (\uBC84\uC804 \uCCB4\uD06C + \uBB38\uC11C + MCP)${colors.reset}
1854
1854
  npx connectbase update
@@ -1866,7 +1866,7 @@ ${colors.yellow}\uBE60\uB978 \uC2DC\uC791:${colors.reset}
1866
1866
  npm run deploy
1867
1867
 
1868
1868
  ${colors.dim}# 4. Dev \uD658\uACBD \uBC30\uD3EC (\uB0B4\uBD80 QA\uC6A9)${colors.reset}
1869
- npx connectbase-client deploy ./dist --dev
1869
+ npx connectbase deploy ./dist --dev
1870
1870
 
1871
1871
  ${colors.dim}# 5. \uD130\uB110 (\uAE30\uBCF8)${colors.reset}
1872
1872
  npx connectbase tunnel 3000
@@ -1942,7 +1942,7 @@ function parseArgs(args) {
1942
1942
  async function main() {
1943
1943
  const parsed = parseArgs(process.argv.slice(2));
1944
1944
  if (parsed.options.version) {
1945
- log(`connectbase-client v${VERSION}`);
1945
+ log(`connectbase v${VERSION}`);
1946
1946
  return;
1947
1947
  }
1948
1948
  if (parsed.options.help || !parsed.command) {
@@ -1980,11 +1980,11 @@ async function main() {
1980
1980
  } else if (parsed.command === "deploy") {
1981
1981
  const directory = parsed.args[0] || fileConfig.deployDir || ".";
1982
1982
  if (!config.publicKey && !config.publicKey) {
1983
- error('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');
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');
1984
1984
  process.exit(1);
1985
1985
  }
1986
1986
  if (!config.storageId) {
1987
- error('\uC2A4\uD1A0\uB9AC\uC9C0 ID\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. "npx connectbase-client init"\uC73C\uB85C \uC124\uC815\uD558\uAC70\uB098 -s \uC635\uC158\uC744 \uC0AC\uC6A9\uD558\uC138\uC694');
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');
1988
1988
  process.exit(1);
1989
1989
  }
1990
1990
  const isDev = parsed.options.dev === "true";
@@ -1992,7 +1992,7 @@ async function main() {
1992
1992
  } else if (parsed.command === "tunnel") {
1993
1993
  const portStr = parsed.args[0];
1994
1994
  if (!portStr) {
1995
- error("\uD3EC\uD2B8 \uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: npx connectbase-client tunnel 8084");
1995
+ error("\uD3EC\uD2B8 \uBC88\uD638\uAC00 \uD544\uC694\uD569\uB2C8\uB2E4. \uC608: npx connectbase tunnel 8084");
1996
1996
  process.exit(1);
1997
1997
  }
1998
1998
  const port = parseInt(portStr, 10);