@cstar.help/js 0.12.1 → 0.14.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/dist/auth/index.cjs +217 -3
- package/dist/auth/index.js +215 -3
- package/dist/chat/index.cjs +84 -29
- package/dist/chat/index.d.cts +72 -27
- package/dist/chat/index.d.ts +72 -27
- package/dist/chat/index.js +84 -29
- package/dist/community/index.cjs +233 -9
- package/dist/community/index.d.cts +11 -0
- package/dist/community/index.d.ts +11 -0
- package/dist/community/index.js +231 -9
- package/dist/index.cjs +309 -74
- package/dist/index.d.cts +3287 -0
- package/dist/index.d.ts +3287 -0
- package/dist/index.js +308 -74
- package/dist/library/index.cjs +254 -9
- package/dist/library/index.d.cts +26 -3
- package/dist/library/index.d.ts +26 -3
- package/dist/library/index.js +252 -9
- package/dist/quickhelp/index.cjs +220 -7
- package/dist/quickhelp/index.d.cts +37 -4
- package/dist/quickhelp/index.d.ts +37 -4
- package/dist/quickhelp/index.js +218 -7
- package/dist/webhook/index.cjs +0 -18
- package/dist/webhook/index.d.cts +440 -0
- package/dist/webhook/index.d.ts +440 -0
- package/dist/webhook/index.js +0 -23
- package/dist/webhook/node.cjs +57 -0
- package/dist/webhook/node.d.cts +440 -0
- package/dist/webhook/node.d.ts +440 -0
- package/dist/webhook/node.js +30 -0
- package/package.json +14 -2
package/dist/index.js
CHANGED
|
@@ -6,102 +6,211 @@ var ErrorType = {
|
|
|
6
6
|
NOT_FOUND_ERROR: "not_found_error",
|
|
7
7
|
CONFLICT_ERROR: "conflict_error",
|
|
8
8
|
RATE_LIMIT_ERROR: "rate_limit_error",
|
|
9
|
+
FEATURE_NOT_CONFIGURED: "feature_not_configured",
|
|
9
10
|
API_ERROR: "api_error",
|
|
10
11
|
SERVER_ERROR: "server_error"
|
|
11
12
|
};
|
|
13
|
+
var DEFAULT_DOC_URL = "https://cstar.help/developers/api/errors";
|
|
14
|
+
function normalizeArgs(messageOrStatus, maybeBody, defaults) {
|
|
15
|
+
if (typeof messageOrStatus === "string") {
|
|
16
|
+
return {
|
|
17
|
+
statusCode: defaults?.code === "rate_limit_error" ? 429 : 0,
|
|
18
|
+
body: {
|
|
19
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
20
|
+
code: defaults?.code ?? "sdk_error",
|
|
21
|
+
message: messageOrStatus,
|
|
22
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL,
|
|
23
|
+
...defaults?.feature ? { feature: defaults.feature } : {},
|
|
24
|
+
...defaults?.enable_url ? { enable_url: defaults.enable_url } : {}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
statusCode: messageOrStatus,
|
|
30
|
+
body: maybeBody ?? {
|
|
31
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
32
|
+
code: defaults?.code ?? "unknown_error",
|
|
33
|
+
message: defaults?.message ?? `Request failed with status ${messageOrStatus}`,
|
|
34
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
12
38
|
var CStarError = class extends Error {
|
|
13
|
-
constructor(
|
|
14
|
-
|
|
39
|
+
constructor(messageOrStatus, body) {
|
|
40
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body);
|
|
41
|
+
super(resolved.message);
|
|
15
42
|
this.name = "CStarError";
|
|
16
|
-
this.type =
|
|
17
|
-
this.code =
|
|
18
|
-
this.param =
|
|
19
|
-
this.docUrl =
|
|
20
|
-
this.requestId =
|
|
43
|
+
this.type = resolved.type;
|
|
44
|
+
this.code = resolved.code;
|
|
45
|
+
this.param = resolved.param;
|
|
46
|
+
this.docUrl = resolved.doc_url;
|
|
47
|
+
this.requestId = resolved.request_id;
|
|
21
48
|
this.statusCode = statusCode;
|
|
22
49
|
}
|
|
23
50
|
};
|
|
24
51
|
var CStarAuthenticationError = class extends CStarError {
|
|
25
|
-
constructor(
|
|
26
|
-
|
|
52
|
+
constructor(messageOrStatus, body) {
|
|
53
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
54
|
+
type: ErrorType.AUTHENTICATION_ERROR,
|
|
55
|
+
code: "authentication_failed",
|
|
56
|
+
doc_url: `${DEFAULT_DOC_URL}#authentication-error`
|
|
57
|
+
});
|
|
58
|
+
super(statusCode, resolved);
|
|
27
59
|
this.name = "CStarAuthenticationError";
|
|
28
60
|
}
|
|
29
61
|
};
|
|
30
62
|
var CStarRateLimitError = class extends CStarError {
|
|
31
|
-
constructor(
|
|
32
|
-
|
|
63
|
+
constructor(messageOrStatus, body, retryAfter) {
|
|
64
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
65
|
+
type: ErrorType.RATE_LIMIT_ERROR,
|
|
66
|
+
code: "rate_limit_exceeded",
|
|
67
|
+
doc_url: `${DEFAULT_DOC_URL}#rate-limit-error`
|
|
68
|
+
});
|
|
69
|
+
super(statusCode === 0 ? 429 : statusCode, resolved);
|
|
33
70
|
this.name = "CStarRateLimitError";
|
|
34
|
-
this.retryAfter = retryAfter;
|
|
71
|
+
this.retryAfter = retryAfter ?? 60;
|
|
35
72
|
}
|
|
36
73
|
};
|
|
37
74
|
var CStarNotFoundError = class extends CStarError {
|
|
38
|
-
constructor(
|
|
39
|
-
|
|
75
|
+
constructor(messageOrStatus, body) {
|
|
76
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
77
|
+
type: ErrorType.NOT_FOUND_ERROR,
|
|
78
|
+
code: "resource_not_found",
|
|
79
|
+
doc_url: `${DEFAULT_DOC_URL}#not-found-error`
|
|
80
|
+
});
|
|
81
|
+
super(statusCode, resolved);
|
|
40
82
|
this.name = "CStarNotFoundError";
|
|
41
83
|
}
|
|
42
84
|
};
|
|
43
85
|
var CStarValidationError = class extends CStarError {
|
|
44
|
-
constructor(
|
|
45
|
-
|
|
86
|
+
constructor(messageOrStatus, body) {
|
|
87
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
88
|
+
type: ErrorType.INVALID_REQUEST_ERROR,
|
|
89
|
+
code: "validation_error",
|
|
90
|
+
doc_url: `${DEFAULT_DOC_URL}#validation-error`
|
|
91
|
+
});
|
|
92
|
+
super(statusCode, resolved);
|
|
46
93
|
this.name = "CStarValidationError";
|
|
47
94
|
}
|
|
48
95
|
};
|
|
49
96
|
var CStarPermissionError = class extends CStarError {
|
|
50
|
-
constructor(
|
|
51
|
-
|
|
97
|
+
constructor(messageOrStatus, body) {
|
|
98
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
99
|
+
type: ErrorType.PERMISSION_ERROR,
|
|
100
|
+
code: "permission_denied",
|
|
101
|
+
doc_url: `${DEFAULT_DOC_URL}#permission-error`
|
|
102
|
+
});
|
|
103
|
+
super(statusCode, resolved);
|
|
52
104
|
this.name = "CStarPermissionError";
|
|
53
105
|
}
|
|
54
106
|
};
|
|
55
107
|
var CStarConflictError = class extends CStarError {
|
|
56
|
-
constructor(
|
|
57
|
-
|
|
108
|
+
constructor(messageOrStatus, body) {
|
|
109
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
110
|
+
type: ErrorType.CONFLICT_ERROR,
|
|
111
|
+
code: "conflict",
|
|
112
|
+
doc_url: `${DEFAULT_DOC_URL}#conflict-error`
|
|
113
|
+
});
|
|
114
|
+
super(statusCode, resolved);
|
|
58
115
|
this.name = "CStarConflictError";
|
|
59
116
|
}
|
|
60
117
|
};
|
|
61
118
|
var CStarServerError = class extends CStarError {
|
|
62
|
-
constructor(
|
|
63
|
-
|
|
119
|
+
constructor(messageOrStatus, body) {
|
|
120
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
121
|
+
type: ErrorType.SERVER_ERROR,
|
|
122
|
+
code: "server_error",
|
|
123
|
+
doc_url: `${DEFAULT_DOC_URL}#server-error`
|
|
124
|
+
});
|
|
125
|
+
super(statusCode, resolved);
|
|
64
126
|
this.name = "CStarServerError";
|
|
65
127
|
}
|
|
66
128
|
};
|
|
129
|
+
var CStarFeatureDisabledError = class extends CStarError {
|
|
130
|
+
constructor(messageOrStatus, body) {
|
|
131
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
132
|
+
type: ErrorType.FEATURE_NOT_CONFIGURED,
|
|
133
|
+
code: "feature_not_configured",
|
|
134
|
+
doc_url: `${DEFAULT_DOC_URL}#feature-not-configured`
|
|
135
|
+
});
|
|
136
|
+
super(statusCode, resolved);
|
|
137
|
+
this.name = "CStarFeatureDisabledError";
|
|
138
|
+
this.feature = resolved.feature ?? "unknown";
|
|
139
|
+
this.enableUrl = resolved.enable_url ?? "";
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
var CStarRealtimeUnavailableError = class extends CStarError {
|
|
143
|
+
constructor(message) {
|
|
144
|
+
const resolved = message ?? "EventSource is not available in this environment. Real-time subscriptions only work in the browser. Move the call to a client-only path (`useEffect` / `onMount`), or pass an `eventSource` polyfill via the realtime options. See https://cstar.help/developers/sdk/realtime#ssr";
|
|
145
|
+
super(0, {
|
|
146
|
+
type: ErrorType.API_ERROR,
|
|
147
|
+
code: "realtime_unavailable",
|
|
148
|
+
message: resolved,
|
|
149
|
+
doc_url: "https://cstar.help/developers/sdk/realtime#ssr"
|
|
150
|
+
});
|
|
151
|
+
this.name = "CStarRealtimeUnavailableError";
|
|
152
|
+
}
|
|
153
|
+
};
|
|
154
|
+
var STATUS_TO_CLASS = {
|
|
155
|
+
400: CStarValidationError,
|
|
156
|
+
401: CStarAuthenticationError,
|
|
157
|
+
403: CStarPermissionError,
|
|
158
|
+
404: CStarNotFoundError,
|
|
159
|
+
409: CStarConflictError,
|
|
160
|
+
422: CStarValidationError,
|
|
161
|
+
429: CStarRateLimitError
|
|
162
|
+
};
|
|
163
|
+
var TYPE_TO_CLASS = {
|
|
164
|
+
[ErrorType.AUTHENTICATION_ERROR]: CStarAuthenticationError,
|
|
165
|
+
[ErrorType.PERMISSION_ERROR]: CStarPermissionError,
|
|
166
|
+
[ErrorType.RATE_LIMIT_ERROR]: CStarRateLimitError,
|
|
167
|
+
[ErrorType.NOT_FOUND_ERROR]: CStarNotFoundError,
|
|
168
|
+
[ErrorType.INVALID_REQUEST_ERROR]: CStarValidationError,
|
|
169
|
+
[ErrorType.CONFLICT_ERROR]: CStarConflictError,
|
|
170
|
+
[ErrorType.SERVER_ERROR]: CStarServerError,
|
|
171
|
+
[ErrorType.FEATURE_NOT_CONFIGURED]: CStarFeatureDisabledError
|
|
172
|
+
};
|
|
67
173
|
function parseError(statusCode, body, retryAfter) {
|
|
68
174
|
const errorBody = body?.error ?? {
|
|
69
175
|
type: ErrorType.API_ERROR,
|
|
70
176
|
code: "unknown_error",
|
|
71
177
|
message: `Request failed with status ${statusCode}`,
|
|
72
|
-
doc_url:
|
|
178
|
+
doc_url: DEFAULT_DOC_URL
|
|
73
179
|
};
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
81
|
-
case ErrorType.NOT_FOUND_ERROR:
|
|
82
|
-
return new CStarNotFoundError(statusCode, errorBody);
|
|
83
|
-
case ErrorType.INVALID_REQUEST_ERROR:
|
|
84
|
-
return new CStarValidationError(statusCode, errorBody);
|
|
85
|
-
case ErrorType.CONFLICT_ERROR:
|
|
86
|
-
return new CStarConflictError(statusCode, errorBody);
|
|
87
|
-
case ErrorType.SERVER_ERROR:
|
|
88
|
-
return new CStarServerError(statusCode, errorBody);
|
|
89
|
-
default:
|
|
90
|
-
if (statusCode === 403) return new CStarPermissionError(statusCode, errorBody);
|
|
91
|
-
if (statusCode === 409) return new CStarConflictError(statusCode, errorBody);
|
|
92
|
-
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
93
|
-
return new CStarError(statusCode, errorBody);
|
|
180
|
+
if (statusCode === 429) {
|
|
181
|
+
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
182
|
+
}
|
|
183
|
+
const StatusCls = STATUS_TO_CLASS[statusCode];
|
|
184
|
+
if (StatusCls) {
|
|
185
|
+
return new StatusCls(statusCode, errorBody);
|
|
94
186
|
}
|
|
187
|
+
const TypeCls = TYPE_TO_CLASS[errorBody.type];
|
|
188
|
+
if (TypeCls) {
|
|
189
|
+
return new TypeCls(statusCode, errorBody);
|
|
190
|
+
}
|
|
191
|
+
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
192
|
+
return new CStarError(statusCode, errorBody);
|
|
95
193
|
}
|
|
96
194
|
|
|
97
195
|
// src/client.ts
|
|
98
|
-
var SDK_VERSION = "0.
|
|
196
|
+
var SDK_VERSION = "0.14.0";
|
|
99
197
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
100
198
|
var DEFAULT_API_VERSION = "2026-03-01";
|
|
101
199
|
var DEFAULT_MAX_RETRIES = 3;
|
|
102
200
|
var DEFAULT_TIMEOUT = 3e4;
|
|
103
201
|
var HttpClient = class {
|
|
104
202
|
constructor(config) {
|
|
203
|
+
/**
|
|
204
|
+
* Side-channel metadata from the most recent response. Holds the server
|
|
205
|
+
* `requestId`, `timestamp`, and (for list endpoints) `pagination`. Mutable
|
|
206
|
+
* per-call — read it immediately after awaiting the call.
|
|
207
|
+
*
|
|
208
|
+
* ```ts
|
|
209
|
+
* const ticket = await cstar.tickets.create({...});
|
|
210
|
+
* console.error('Created ticket', ticket.id, 'request:', cstar.lastMeta.requestId);
|
|
211
|
+
* ```
|
|
212
|
+
*/
|
|
213
|
+
this.lastMeta = { requestId: null, timestamp: null, pagination: null };
|
|
105
214
|
if (!config || typeof config.apiKey !== "string" || config.apiKey.length === 0) {
|
|
106
215
|
throw new Error(
|
|
107
216
|
"[cStar] CStarClient: apiKey is required. Pass a secret key (sk_live_... / sk_test_...) or a publishable key (pk_live_... / pk_test_...). See https://cstar.help/developers/quickstart"
|
|
@@ -132,7 +241,32 @@ var HttpClient = class {
|
|
|
132
241
|
* Automatically retries on 5xx errors and rate limits.
|
|
133
242
|
*/
|
|
134
243
|
async request(method, path, options) {
|
|
135
|
-
|
|
244
|
+
return this._sendRequest(method, this.buildUrl(path, options?.query), options);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Like `request()` but skips the `/api/v1/teams/{teamId}` prefix. Used for
|
|
248
|
+
* the small set of non-team-scoped endpoints (`/auth/whoami`, etc).
|
|
249
|
+
*
|
|
250
|
+
* @internal — exposed to CStarClient for `whoami()` and similar; not part
|
|
251
|
+
* of the documented public surface.
|
|
252
|
+
*/
|
|
253
|
+
async requestUnscoped(method, path, options) {
|
|
254
|
+
const baseUrl = this.config.baseUrl + "/api/v1" + path;
|
|
255
|
+
const finalUrl = this.appendQuery(baseUrl, options?.query);
|
|
256
|
+
return this._sendRequest(method, finalUrl, options);
|
|
257
|
+
}
|
|
258
|
+
appendQuery(url, query) {
|
|
259
|
+
if (!query) return url;
|
|
260
|
+
const params = new URLSearchParams();
|
|
261
|
+
for (const [key, value] of Object.entries(query)) {
|
|
262
|
+
if (value === void 0 || value === null) continue;
|
|
263
|
+
if (Array.isArray(value)) for (const v of value) params.append(`${key}[]`, v);
|
|
264
|
+
else params.set(key, String(value));
|
|
265
|
+
}
|
|
266
|
+
const qs = params.toString();
|
|
267
|
+
return qs ? `${url}?${qs}` : url;
|
|
268
|
+
}
|
|
269
|
+
async _sendRequest(method, url, options) {
|
|
136
270
|
const headers = this.buildHeaders(options?.idempotencyKey);
|
|
137
271
|
const body = options?.body ? JSON.stringify(options.body) : void 0;
|
|
138
272
|
let lastError = null;
|
|
@@ -163,13 +297,9 @@ var HttpClient = class {
|
|
|
163
297
|
if (response.ok) {
|
|
164
298
|
if (response.status === 204) return void 0;
|
|
165
299
|
const json = await response.json();
|
|
166
|
-
const
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const metaBase = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
170
|
-
json.meta = { ...metaBase, requestId: requestId2 };
|
|
171
|
-
}
|
|
172
|
-
return json;
|
|
300
|
+
const headerRequestId = response.headers.get("x-request-id") ?? response.headers.get("x-cstar-request-id");
|
|
301
|
+
this.captureMeta(json, headerRequestId);
|
|
302
|
+
return this.unwrapEnvelope(json);
|
|
173
303
|
}
|
|
174
304
|
const errorBody = await response.json().catch(() => null);
|
|
175
305
|
const retryAfter = parseInt(response.headers.get("Retry-After") ?? "", 10) || void 0;
|
|
@@ -191,6 +321,51 @@ var HttpClient = class {
|
|
|
191
321
|
}
|
|
192
322
|
throw lastError ?? new Error("Request failed after retries");
|
|
193
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Capture `meta`, `requestId`, and `pagination` from the raw response
|
|
326
|
+
* into `this.lastMeta` before unwrapping the envelope.
|
|
327
|
+
*/
|
|
328
|
+
captureMeta(body, headerRequestId) {
|
|
329
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
330
|
+
const obj = body;
|
|
331
|
+
const meta = obj.meta && typeof obj.meta === "object" ? obj.meta : null;
|
|
332
|
+
const pagination = obj.pagination && typeof obj.pagination === "object" ? obj.pagination : null;
|
|
333
|
+
this.lastMeta = {
|
|
334
|
+
requestId: headerRequestId ?? (typeof meta?.requestId === "string" ? meta.requestId : null),
|
|
335
|
+
timestamp: typeof meta?.timestamp === "string" ? meta.timestamp : null,
|
|
336
|
+
pagination
|
|
337
|
+
};
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
this.lastMeta = { requestId: headerRequestId, timestamp: null, pagination: null };
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Unwrap the legacy `{success, data, meta, pagination?}` envelope.
|
|
344
|
+
* - `{success:true, data: array, pagination}` → `{data, pagination, hasMore}`
|
|
345
|
+
* - `{success:true, data: object}` → `data` (bare resource)
|
|
346
|
+
* - other shapes pass through unchanged so subpath SDKs (chat, library) keep
|
|
347
|
+
* their bespoke shapes for now.
|
|
348
|
+
*/
|
|
349
|
+
unwrapEnvelope(body) {
|
|
350
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return body;
|
|
351
|
+
const obj = body;
|
|
352
|
+
if (obj.success !== true || !("data" in obj)) return body;
|
|
353
|
+
const data = obj.data;
|
|
354
|
+
if (Array.isArray(data)) {
|
|
355
|
+
const pagination = obj.pagination ?? null;
|
|
356
|
+
return {
|
|
357
|
+
data,
|
|
358
|
+
pagination: pagination ?? {
|
|
359
|
+
total: data.length,
|
|
360
|
+
page: 1,
|
|
361
|
+
pageSize: data.length,
|
|
362
|
+
hasMore: false
|
|
363
|
+
},
|
|
364
|
+
hasMore: pagination?.hasMore ?? false
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
return data;
|
|
368
|
+
}
|
|
194
369
|
buildUrl(path, query) {
|
|
195
370
|
const base = `${this.config.baseUrl}/api/v1/teams/${this.config.teamId}${path}`;
|
|
196
371
|
if (!query) return base;
|
|
@@ -263,6 +438,18 @@ var CStarRealtime = class {
|
|
|
263
438
|
this.autoReconnect = options?.autoReconnect ?? true;
|
|
264
439
|
this.maxRetries = options?.maxRetries ?? 10;
|
|
265
440
|
this.types = options?.types;
|
|
441
|
+
this.eventSourceCtor = options?.eventSource;
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Resolve the EventSource constructor to use for this connection.
|
|
445
|
+
* Returns the explicit polyfill when one was injected, otherwise the
|
|
446
|
+
* global. Returns `undefined` when neither is available — callers must
|
|
447
|
+
* convert to `CStarRealtimeUnavailableError` before touching it.
|
|
448
|
+
*/
|
|
449
|
+
resolveEventSource() {
|
|
450
|
+
if (this.eventSourceCtor) return this.eventSourceCtor;
|
|
451
|
+
const fromGlobal = globalThis.EventSource;
|
|
452
|
+
return typeof fromGlobal === "function" ? fromGlobal : void 0;
|
|
266
453
|
}
|
|
267
454
|
/** Subscribe to a specific event type. Supports wildcards (e.g., 'ticket.*'). Returns an unsubscribe function. */
|
|
268
455
|
on(eventType, handler) {
|
|
@@ -317,6 +504,9 @@ var CStarRealtime = class {
|
|
|
317
504
|
/** Start the SSE connection. Called automatically on first handler registration. */
|
|
318
505
|
connect() {
|
|
319
506
|
if (this.eventSource || this.destroyed || this.connecting) return;
|
|
507
|
+
if (!this.resolveEventSource()) {
|
|
508
|
+
throw new CStarRealtimeUnavailableError();
|
|
509
|
+
}
|
|
320
510
|
this.connecting = true;
|
|
321
511
|
const headers = this.httpClient.getAuthHeaders();
|
|
322
512
|
const rawKey = headers.Authorization?.replace("Bearer ", "") ?? "";
|
|
@@ -355,7 +545,12 @@ var CStarRealtime = class {
|
|
|
355
545
|
}
|
|
356
546
|
const separator = qs ? "&" : "?";
|
|
357
547
|
const authenticatedUrl = authToken ? `${url}${separator}token=${authToken}` : url;
|
|
358
|
-
|
|
548
|
+
const Ctor = this.resolveEventSource();
|
|
549
|
+
if (!Ctor) {
|
|
550
|
+
this.connecting = false;
|
|
551
|
+
throw new CStarRealtimeUnavailableError();
|
|
552
|
+
}
|
|
553
|
+
this.eventSource = new Ctor(authenticatedUrl);
|
|
359
554
|
this.eventSource.onopen = () => {
|
|
360
555
|
this.connecting = false;
|
|
361
556
|
this.retryCount = 0;
|
|
@@ -774,6 +969,14 @@ var BaseResource = class {
|
|
|
774
969
|
async del(id) {
|
|
775
970
|
return this.client.request("DELETE", `${this.basePath}/${id}`);
|
|
776
971
|
}
|
|
972
|
+
/**
|
|
973
|
+
* Delete a resource by ID. Alias for `del()` — kept because IDE
|
|
974
|
+
* auto-complete and documentation both surface `delete` first. Closes
|
|
975
|
+
* NEW-v2-06.
|
|
976
|
+
*/
|
|
977
|
+
async delete(id) {
|
|
978
|
+
return this.del(id);
|
|
979
|
+
}
|
|
777
980
|
/**
|
|
778
981
|
* Auto-paginating async iterator that yields every item across all pages.
|
|
779
982
|
*
|
|
@@ -1872,7 +2075,12 @@ var GameResource = class {
|
|
|
1872
2075
|
async getPlayer(memberId) {
|
|
1873
2076
|
return this.client.request("GET", `/game/player/${memberId}`);
|
|
1874
2077
|
}
|
|
1875
|
-
/**
|
|
2078
|
+
/**
|
|
2079
|
+
* Get the team leaderboard. Returns the unwrapped envelope from the
|
|
2080
|
+
* `/game/leaderboard` endpoint (`{entries, totalParticipants, period, ...}`)
|
|
2081
|
+
* — wider than a flat array because the server includes the period and
|
|
2082
|
+
* a participant count alongside the entries.
|
|
2083
|
+
*/
|
|
1876
2084
|
async leaderboard(params) {
|
|
1877
2085
|
return this.client.request("GET", "/game/leaderboard", {
|
|
1878
2086
|
query: params
|
|
@@ -1895,12 +2103,12 @@ var GameResource = class {
|
|
|
1895
2103
|
*/
|
|
1896
2104
|
subscribeBoss(realtime) {
|
|
1897
2105
|
const fetchFn = async () => {
|
|
1898
|
-
const
|
|
2106
|
+
const boss = await this.boss.current();
|
|
2107
|
+
const list = boss.active ? [boss] : [];
|
|
1899
2108
|
return {
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
meta: { requestId: "", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2109
|
+
data: list,
|
|
2110
|
+
pagination: { total: list.length, page: 1, pageSize: 1, hasMore: false },
|
|
2111
|
+
hasMore: false
|
|
1904
2112
|
};
|
|
1905
2113
|
};
|
|
1906
2114
|
return new Subscription(realtime, fetchFn, "/game/boss");
|
|
@@ -1911,12 +2119,11 @@ var GameResource = class {
|
|
|
1911
2119
|
*/
|
|
1912
2120
|
subscribePlayer(realtime, userId) {
|
|
1913
2121
|
const fetchFn = async () => {
|
|
1914
|
-
const
|
|
2122
|
+
const player = await this.player({ userId });
|
|
1915
2123
|
return {
|
|
1916
|
-
|
|
1917
|
-
data: [res.data],
|
|
2124
|
+
data: [player],
|
|
1918
2125
|
pagination: { total: 1, page: 1, pageSize: 1, hasMore: false },
|
|
1919
|
-
|
|
2126
|
+
hasMore: false
|
|
1920
2127
|
};
|
|
1921
2128
|
};
|
|
1922
2129
|
return new Subscription(realtime, fetchFn, "/game/player");
|
|
@@ -1927,14 +2134,12 @@ var GameResource = class {
|
|
|
1927
2134
|
*/
|
|
1928
2135
|
subscribeLeaderboard(realtime, params) {
|
|
1929
2136
|
const fetchFn = async () => {
|
|
1930
|
-
const
|
|
1931
|
-
const
|
|
1932
|
-
const entries = Array.isArray(envelope) ? envelope : envelope?.entries ?? [];
|
|
2137
|
+
const board = await this.leaderboard(params);
|
|
2138
|
+
const entries = board.entries ?? [];
|
|
1933
2139
|
return {
|
|
1934
|
-
success: true,
|
|
1935
2140
|
data: entries,
|
|
1936
2141
|
pagination: { total: entries.length, page: 1, pageSize: 100, hasMore: false },
|
|
1937
|
-
|
|
2142
|
+
hasMore: false
|
|
1938
2143
|
};
|
|
1939
2144
|
};
|
|
1940
2145
|
return new Subscription(realtime, fetchFn, "/game/leaderboard");
|
|
@@ -1945,13 +2150,12 @@ var GameResource = class {
|
|
|
1945
2150
|
*/
|
|
1946
2151
|
subscribeActivity(realtime) {
|
|
1947
2152
|
const fetchFn = async () => {
|
|
1948
|
-
const
|
|
1949
|
-
const
|
|
2153
|
+
const feed = await this.activity.list({ limit: 50 });
|
|
2154
|
+
const items = feed.data ?? [];
|
|
1950
2155
|
return {
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
meta: { requestId: "", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2156
|
+
data: items,
|
|
2157
|
+
pagination: { total: items.length, page: 1, pageSize: 50, hasMore: false },
|
|
2158
|
+
hasMore: false
|
|
1955
2159
|
};
|
|
1956
2160
|
};
|
|
1957
2161
|
return new Subscription(realtime, fetchFn, "/game/activity");
|
|
@@ -2189,12 +2393,42 @@ var CStarClient = class {
|
|
|
2189
2393
|
get isTestMode() {
|
|
2190
2394
|
return this._httpClient.environment === "test";
|
|
2191
2395
|
}
|
|
2396
|
+
/**
|
|
2397
|
+
* Validate the configured API key and return the team + key metadata it
|
|
2398
|
+
* resolves to. Useful for confirming the key is wired up correctly during
|
|
2399
|
+
* onboarding (and for AI assistants that want a one-call sanity check).
|
|
2400
|
+
*
|
|
2401
|
+
* Closes F-018.
|
|
2402
|
+
*
|
|
2403
|
+
* ```ts
|
|
2404
|
+
* const me = await cstar.whoami();
|
|
2405
|
+
* console.log(me.teamSlug, me.environment); // 'acme', 'test'
|
|
2406
|
+
* ```
|
|
2407
|
+
*/
|
|
2408
|
+
async whoami() {
|
|
2409
|
+
return this._httpClient.requestUnscoped("GET", "/auth/whoami");
|
|
2410
|
+
}
|
|
2411
|
+
/**
|
|
2412
|
+
* Side-channel metadata from the most recent HTTP response. Holds the
|
|
2413
|
+
* server `requestId` (for support escalations), `timestamp`, and the
|
|
2414
|
+
* `pagination` info from list endpoints. Reset on every call — read it
|
|
2415
|
+
* immediately after awaiting the call you care about.
|
|
2416
|
+
*
|
|
2417
|
+
* ```ts
|
|
2418
|
+
* const ticket = await cstar.tickets.create({...});
|
|
2419
|
+
* console.error('Created', ticket.id, 'request:', cstar.lastMeta.requestId);
|
|
2420
|
+
* ```
|
|
2421
|
+
*/
|
|
2422
|
+
get lastMeta() {
|
|
2423
|
+
return this._httpClient.lastMeta;
|
|
2424
|
+
}
|
|
2192
2425
|
};
|
|
2193
2426
|
export {
|
|
2194
2427
|
CStarAuthenticationError,
|
|
2195
2428
|
CStarClient,
|
|
2196
2429
|
CStarConflictError,
|
|
2197
2430
|
CStarError,
|
|
2431
|
+
CStarFeatureDisabledError,
|
|
2198
2432
|
CStarNotFoundError,
|
|
2199
2433
|
CStarPermissionError,
|
|
2200
2434
|
CStarRateLimitError,
|