connectbase-client 5.6.4 → 5.8.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 +58 -6
- package/dist/connect-base.umd.js +4 -4
- package/dist/index.d.mts +120 -1
- package/dist/index.d.ts +120 -1
- package/dist/index.js +120 -4
- package/dist/index.mjs +120 -4
- package/package.json +75 -75
package/dist/index.mjs
CHANGED
|
@@ -3693,6 +3693,7 @@ function parseGameError(msg) {
|
|
|
3693
3693
|
available: get("available") || msg.available
|
|
3694
3694
|
});
|
|
3695
3695
|
}
|
|
3696
|
+
var SYNC_LOST_RESYNC_MIN_INTERVAL_MS = 1e3;
|
|
3696
3697
|
var getDefaultGameServerUrl = () => {
|
|
3697
3698
|
if (typeof window !== "undefined") {
|
|
3698
3699
|
const hostname = window.location.hostname;
|
|
@@ -3727,6 +3728,9 @@ var GameRoom = class {
|
|
|
3727
3728
|
this._scriptVersion = null;
|
|
3728
3729
|
this._isConnected = false;
|
|
3729
3730
|
this.msgIdCounter = 0;
|
|
3731
|
+
/** sync_lost 자동 재동기화 억제 상태 — handleSyncLost 참고. */
|
|
3732
|
+
this.resyncInFlight = false;
|
|
3733
|
+
this.lastResyncAt = 0;
|
|
3730
3734
|
this.config = {
|
|
3731
3735
|
gameServerUrl: getDefaultGameServerUrl(),
|
|
3732
3736
|
autoReconnect: true,
|
|
@@ -4037,6 +4041,11 @@ var GameRoom = class {
|
|
|
4037
4041
|
const baseUrl = this.config.gameServerUrl;
|
|
4038
4042
|
const wsUrl = baseUrl.replace(/^http/, "ws");
|
|
4039
4043
|
const params = new URLSearchParams();
|
|
4044
|
+
if (!this.config.clientId) {
|
|
4045
|
+
throw new Error(
|
|
4046
|
+
"cb.game: clientId is required to build a game connection URL. Pass it via `cb.game.createClient({ appId, clientId })`."
|
|
4047
|
+
);
|
|
4048
|
+
}
|
|
4040
4049
|
params.set("client_id", this.config.clientId);
|
|
4041
4050
|
if (roomId) {
|
|
4042
4051
|
params.set("room_id", roomId);
|
|
@@ -4127,6 +4136,25 @@ var GameRoom = class {
|
|
|
4127
4136
|
case "error":
|
|
4128
4137
|
this.handlers.onError?.(parseGameError(msg));
|
|
4129
4138
|
break;
|
|
4139
|
+
case "sync_lost":
|
|
4140
|
+
this.handleSyncLost(msg);
|
|
4141
|
+
break;
|
|
4142
|
+
case "room_stale":
|
|
4143
|
+
if (this.handlers.onRoomStale) {
|
|
4144
|
+
this.handlers.onRoomStale({
|
|
4145
|
+
reason: msg.reason || "unknown",
|
|
4146
|
+
roomId: msg.room_id || "",
|
|
4147
|
+
scriptId: msg.script_id,
|
|
4148
|
+
scriptVersion: msg.script_version,
|
|
4149
|
+
serverTime: msg.server_time || 0
|
|
4150
|
+
});
|
|
4151
|
+
} else {
|
|
4152
|
+
console.warn(
|
|
4153
|
+
"[connect-base game] room_stale received but onRoomStale handler not set:",
|
|
4154
|
+
msg.reason
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
break;
|
|
4130
4158
|
default:
|
|
4131
4159
|
this.handlers.onMessage?.(
|
|
4132
4160
|
msg
|
|
@@ -4137,6 +4165,34 @@ var GameRoom = class {
|
|
|
4137
4165
|
console.error("Failed to parse game message:", data);
|
|
4138
4166
|
}
|
|
4139
4167
|
}
|
|
4168
|
+
/**
|
|
4169
|
+
* `sync_lost` 처리 — broadcaster 가 이 클라이언트로 보내는 버퍼가 넘쳐서 delta 를
|
|
4170
|
+
* 몇 개 버렸다는 서버의 통지다. delta 는 이전 상태에 누적 적용되므로, 하나라도
|
|
4171
|
+
* 놓치면 이후 모든 상태가 어긋난 채로 계속 간다. 그래서 전체 상태를 다시 받아
|
|
4172
|
+
* 기준점을 맞춘다 (서버 규약: `app/game/room.go` 의 emitSyncLostHintIfNeeded).
|
|
4173
|
+
*
|
|
4174
|
+
* 서버는 버퍼가 계속 막혀 있으면 tick 마다 재시도하므로 두 겹으로 억제한다 —
|
|
4175
|
+
* 이미 재동기화가 진행 중이면 건너뛰고, 최소 간격 안의 중복 통지도 무시한다.
|
|
4176
|
+
* 안 그러면 혼잡한 상황에서 get_state 폭풍이 혼잡을 더 키운다.
|
|
4177
|
+
*/
|
|
4178
|
+
handleSyncLost(msg) {
|
|
4179
|
+
this.handlers.onSyncLost?.({
|
|
4180
|
+
roomId: msg.room_id || "",
|
|
4181
|
+
tick: msg.tick || 0,
|
|
4182
|
+
hint: msg.hint || "",
|
|
4183
|
+
serverTime: msg.server_time || 0
|
|
4184
|
+
});
|
|
4185
|
+
if (this.resyncInFlight) return;
|
|
4186
|
+
const now = Date.now();
|
|
4187
|
+
if (now - this.lastResyncAt < SYNC_LOST_RESYNC_MIN_INTERVAL_MS) return;
|
|
4188
|
+
this.resyncInFlight = true;
|
|
4189
|
+
this.lastResyncAt = now;
|
|
4190
|
+
this.requestState().catch((err) => {
|
|
4191
|
+
console.warn("[connect-base game] sync_lost resync failed:", err);
|
|
4192
|
+
}).finally(() => {
|
|
4193
|
+
this.resyncInFlight = false;
|
|
4194
|
+
});
|
|
4195
|
+
}
|
|
4140
4196
|
handleDelta(msg) {
|
|
4141
4197
|
const raw = msg.delta;
|
|
4142
4198
|
if (!raw) return;
|
|
@@ -4774,6 +4830,54 @@ var GameAPI = class {
|
|
|
4774
4830
|
"GAME_DELETE_SCRIPT_FAILED"
|
|
4775
4831
|
);
|
|
4776
4832
|
}
|
|
4833
|
+
/**
|
|
4834
|
+
* 스크립트 로그 조회 — 훅 에러 + Lua `log()` 출력.
|
|
4835
|
+
*
|
|
4836
|
+
* **서버 Lua 를 디버깅하는 유일한 경로다.** 업로드 → 활성화 후 게임을 돌려보고
|
|
4837
|
+
* 이 메서드로 실패 원인을 확인한다. 에러 줄에는 훅 이름, setup/hook 실측 시간,
|
|
4838
|
+
* Lua traceback 의 파일:줄이 함께 실린다:
|
|
4839
|
+
*
|
|
4840
|
+
* ```
|
|
4841
|
+
* [onTick] onTick error: <string>:12: attempt to index a nil value
|
|
4842
|
+
* (setup 3ms / hook 5ms)
|
|
4843
|
+
* ```
|
|
4844
|
+
*
|
|
4845
|
+
* 예산 초과(`SCRIPT_TIMEOUT`)면 한도와 조치 방향까지 덧붙는다.
|
|
4846
|
+
*
|
|
4847
|
+
* @param since epoch ms. 직전 호출의 최신 timestamp 를 넣어 증분 폴링한다.
|
|
4848
|
+
* @param limit 1~1000 (기본 100)
|
|
4849
|
+
*
|
|
4850
|
+
* 버퍼는 스크립트당 최근 ~500 엔트리이며 파드 로컬이라 재시작 시 소실된다.
|
|
4851
|
+
*/
|
|
4852
|
+
async getScriptLogs(appId, name, options = {}) {
|
|
4853
|
+
const params = new URLSearchParams();
|
|
4854
|
+
if (typeof options.since === "number")
|
|
4855
|
+
params.set("since", String(options.since));
|
|
4856
|
+
if (typeof options.limit === "number")
|
|
4857
|
+
params.set("limit", String(options.limit));
|
|
4858
|
+
const qs = params.toString();
|
|
4859
|
+
return this.gameFetch(
|
|
4860
|
+
"GET",
|
|
4861
|
+
`/v1/game/${appId}/scripts/${name}/logs${qs ? `?${qs}` : ""}`,
|
|
4862
|
+
void 0,
|
|
4863
|
+
"GAME_GET_SCRIPT_LOGS_FAILED"
|
|
4864
|
+
);
|
|
4865
|
+
}
|
|
4866
|
+
/**
|
|
4867
|
+
* 스크립트 메트릭 조회 — 호출 수, 에러율, setup/hook 레이턴시.
|
|
4868
|
+
*
|
|
4869
|
+
* `SCRIPT_TIMEOUT` 진단에 쓴다. `maxHookLatencyMs` 가 frame 훅 예산(기본 100ms)에
|
|
4870
|
+
* 근접하면 무거운 작업을 `onInit`(5s 예산)으로 옮겨야 한다는 신호다.
|
|
4871
|
+
* `entity.*` 같은 primitive 는 블로킹 I/O 라 호출한 훅의 예산을 소모한다.
|
|
4872
|
+
*/
|
|
4873
|
+
async getScriptMetrics(appId, name) {
|
|
4874
|
+
return this.gameFetch(
|
|
4875
|
+
"GET",
|
|
4876
|
+
`/v1/game/${appId}/scripts/${name}/metrics`,
|
|
4877
|
+
void 0,
|
|
4878
|
+
"GAME_GET_SCRIPT_METRICS_FAILED"
|
|
4879
|
+
);
|
|
4880
|
+
}
|
|
4777
4881
|
};
|
|
4778
4882
|
|
|
4779
4883
|
// src/api/knowledge.ts
|
|
@@ -11938,6 +12042,14 @@ var HttpClient = class {
|
|
|
11938
12042
|
};
|
|
11939
12043
|
|
|
11940
12044
|
// src/api/game-transport.ts
|
|
12045
|
+
function requireClientId(clientId) {
|
|
12046
|
+
if (!clientId) {
|
|
12047
|
+
throw new Error(
|
|
12048
|
+
"cb.game: clientId is required to build a game connection URL. Pass it via `cb.game.createClient({ appId, clientId })`."
|
|
12049
|
+
);
|
|
12050
|
+
}
|
|
12051
|
+
return clientId;
|
|
12052
|
+
}
|
|
11941
12053
|
var WebTransportTransport = class {
|
|
11942
12054
|
constructor(config, onMessage, onClose, onError) {
|
|
11943
12055
|
this.type = "webtransport";
|
|
@@ -11968,7 +12080,7 @@ var WebTransportTransport = class {
|
|
|
11968
12080
|
const baseUrl = this.config.gameServerUrl || "https://game.connectbase.world";
|
|
11969
12081
|
const httpsUrl = baseUrl.replace(/^ws/, "http").replace(/^http:/, "https:");
|
|
11970
12082
|
const params = new URLSearchParams();
|
|
11971
|
-
params.set("client_id", this.config.clientId);
|
|
12083
|
+
params.set("client_id", requireClientId(this.config.clientId));
|
|
11972
12084
|
if (this.config.publicKey) {
|
|
11973
12085
|
params.set("public_key", this.config.publicKey);
|
|
11974
12086
|
}
|
|
@@ -12093,15 +12205,19 @@ var WebSocketTransport = class {
|
|
|
12093
12205
|
const baseUrl = this.config.gameServerUrl || "wss://game.connectbase.world";
|
|
12094
12206
|
const wsUrl = baseUrl.replace(/^http/, "ws");
|
|
12095
12207
|
const params = new URLSearchParams();
|
|
12096
|
-
params.set("client_id", this.config.clientId);
|
|
12208
|
+
params.set("client_id", requireClientId(this.config.clientId));
|
|
12097
12209
|
if (this.config.publicKey) {
|
|
12098
12210
|
params.set("public_key", this.config.publicKey);
|
|
12099
12211
|
}
|
|
12100
12212
|
if (this.config.accessToken) {
|
|
12101
12213
|
params.set("token", this.config.accessToken);
|
|
12102
12214
|
}
|
|
12103
|
-
|
|
12104
|
-
|
|
12215
|
+
if (!this.config.appId) {
|
|
12216
|
+
throw new Error(
|
|
12217
|
+
"cb.game: appId is required to build a game connection URL. Pass it to `new ConnectBase({ appId })` or per-client via `cb.game.createClient({ appId, clientId })`."
|
|
12218
|
+
);
|
|
12219
|
+
}
|
|
12220
|
+
return `${wsUrl}/v1/game/${this.config.appId}/ws?${params.toString()}`;
|
|
12105
12221
|
}
|
|
12106
12222
|
disconnect() {
|
|
12107
12223
|
if (this.ws) {
|
package/package.json
CHANGED
|
@@ -1,77 +1,77 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
2
|
+
"name": "connectbase-client",
|
|
3
|
+
"version": "5.8.0",
|
|
4
|
+
"description": "Connect Base JavaScript/TypeScript SDK for browser and Node.js",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/connectbase-world/connectbase.git",
|
|
8
|
+
"directory": "frontend/package/public/connect-base-client"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/connectbase-world/connectbase/tree/release/frontend/package/public/connect-base-client#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/connectbase-world/connectbase/issues"
|
|
13
|
+
},
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
17
|
+
"sideEffects": false,
|
|
18
|
+
"main": "dist/index.js",
|
|
19
|
+
"module": "dist/index.mjs",
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"browser": "dist/connect-base.umd.js",
|
|
22
|
+
"unpkg": "dist/connect-base.umd.js",
|
|
23
|
+
"bin": {
|
|
24
|
+
"connectbase": "dist/cli.js",
|
|
25
|
+
"connectbase-client": "dist/cli.js"
|
|
26
|
+
},
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.mjs",
|
|
31
|
+
"require": "./dist/index.js"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"files": [
|
|
35
|
+
"dist",
|
|
36
|
+
"LICENSE",
|
|
37
|
+
"CHANGELOG.md",
|
|
38
|
+
"README.md",
|
|
39
|
+
"MIGRATION-v2.md"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsup",
|
|
43
|
+
"dev": "tsup --watch",
|
|
44
|
+
"typecheck": "tsc --noEmit",
|
|
45
|
+
"test": "vitest run",
|
|
46
|
+
"test:types": "tsc --noEmit -p test/tsconfig.json",
|
|
47
|
+
"release": "pnpm build && npm publish --access public",
|
|
48
|
+
"lint": "biome lint .",
|
|
49
|
+
"format": "biome format --write .",
|
|
50
|
+
"check": "biome check ."
|
|
51
|
+
},
|
|
52
|
+
"keywords": [
|
|
53
|
+
"connect-base",
|
|
54
|
+
"baas",
|
|
55
|
+
"backend-as-a-service",
|
|
56
|
+
"database",
|
|
57
|
+
"storage",
|
|
58
|
+
"sdk",
|
|
59
|
+
"cli",
|
|
60
|
+
"deploy",
|
|
61
|
+
"ai",
|
|
62
|
+
"streaming",
|
|
63
|
+
"realtime",
|
|
64
|
+
"tunnel"
|
|
65
|
+
],
|
|
66
|
+
"author": "Connect Base",
|
|
67
|
+
"license": "MIT",
|
|
68
|
+
"devDependencies": {
|
|
69
|
+
"@types/node": "^22.15.18",
|
|
70
|
+
"tsup": "^8.5.1",
|
|
71
|
+
"typescript": "^5.9.3",
|
|
72
|
+
"vitest": "^3.2.4"
|
|
73
|
+
},
|
|
74
|
+
"engines": {
|
|
75
|
+
"node": ">=16"
|
|
76
|
+
}
|
|
77
77
|
}
|