@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.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(src_exports, {
|
|
|
24
24
|
CStarClient: () => CStarClient,
|
|
25
25
|
CStarConflictError: () => CStarConflictError,
|
|
26
26
|
CStarError: () => CStarError,
|
|
27
|
+
CStarFeatureDisabledError: () => CStarFeatureDisabledError,
|
|
27
28
|
CStarNotFoundError: () => CStarNotFoundError,
|
|
28
29
|
CStarPermissionError: () => CStarPermissionError,
|
|
29
30
|
CStarRateLimitError: () => CStarRateLimitError,
|
|
@@ -44,102 +45,211 @@ var ErrorType = {
|
|
|
44
45
|
NOT_FOUND_ERROR: "not_found_error",
|
|
45
46
|
CONFLICT_ERROR: "conflict_error",
|
|
46
47
|
RATE_LIMIT_ERROR: "rate_limit_error",
|
|
48
|
+
FEATURE_NOT_CONFIGURED: "feature_not_configured",
|
|
47
49
|
API_ERROR: "api_error",
|
|
48
50
|
SERVER_ERROR: "server_error"
|
|
49
51
|
};
|
|
52
|
+
var DEFAULT_DOC_URL = "https://cstar.help/developers/api/errors";
|
|
53
|
+
function normalizeArgs(messageOrStatus, maybeBody, defaults) {
|
|
54
|
+
if (typeof messageOrStatus === "string") {
|
|
55
|
+
return {
|
|
56
|
+
statusCode: defaults?.code === "rate_limit_error" ? 429 : 0,
|
|
57
|
+
body: {
|
|
58
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
59
|
+
code: defaults?.code ?? "sdk_error",
|
|
60
|
+
message: messageOrStatus,
|
|
61
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL,
|
|
62
|
+
...defaults?.feature ? { feature: defaults.feature } : {},
|
|
63
|
+
...defaults?.enable_url ? { enable_url: defaults.enable_url } : {}
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
statusCode: messageOrStatus,
|
|
69
|
+
body: maybeBody ?? {
|
|
70
|
+
type: defaults?.type ?? ErrorType.API_ERROR,
|
|
71
|
+
code: defaults?.code ?? "unknown_error",
|
|
72
|
+
message: defaults?.message ?? `Request failed with status ${messageOrStatus}`,
|
|
73
|
+
doc_url: defaults?.doc_url ?? DEFAULT_DOC_URL
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
50
77
|
var CStarError = class extends Error {
|
|
51
|
-
constructor(
|
|
52
|
-
|
|
78
|
+
constructor(messageOrStatus, body) {
|
|
79
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body);
|
|
80
|
+
super(resolved.message);
|
|
53
81
|
this.name = "CStarError";
|
|
54
|
-
this.type =
|
|
55
|
-
this.code =
|
|
56
|
-
this.param =
|
|
57
|
-
this.docUrl =
|
|
58
|
-
this.requestId =
|
|
82
|
+
this.type = resolved.type;
|
|
83
|
+
this.code = resolved.code;
|
|
84
|
+
this.param = resolved.param;
|
|
85
|
+
this.docUrl = resolved.doc_url;
|
|
86
|
+
this.requestId = resolved.request_id;
|
|
59
87
|
this.statusCode = statusCode;
|
|
60
88
|
}
|
|
61
89
|
};
|
|
62
90
|
var CStarAuthenticationError = class extends CStarError {
|
|
63
|
-
constructor(
|
|
64
|
-
|
|
91
|
+
constructor(messageOrStatus, body) {
|
|
92
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
93
|
+
type: ErrorType.AUTHENTICATION_ERROR,
|
|
94
|
+
code: "authentication_failed",
|
|
95
|
+
doc_url: `${DEFAULT_DOC_URL}#authentication-error`
|
|
96
|
+
});
|
|
97
|
+
super(statusCode, resolved);
|
|
65
98
|
this.name = "CStarAuthenticationError";
|
|
66
99
|
}
|
|
67
100
|
};
|
|
68
101
|
var CStarRateLimitError = class extends CStarError {
|
|
69
|
-
constructor(
|
|
70
|
-
|
|
102
|
+
constructor(messageOrStatus, body, retryAfter) {
|
|
103
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
104
|
+
type: ErrorType.RATE_LIMIT_ERROR,
|
|
105
|
+
code: "rate_limit_exceeded",
|
|
106
|
+
doc_url: `${DEFAULT_DOC_URL}#rate-limit-error`
|
|
107
|
+
});
|
|
108
|
+
super(statusCode === 0 ? 429 : statusCode, resolved);
|
|
71
109
|
this.name = "CStarRateLimitError";
|
|
72
|
-
this.retryAfter = retryAfter;
|
|
110
|
+
this.retryAfter = retryAfter ?? 60;
|
|
73
111
|
}
|
|
74
112
|
};
|
|
75
113
|
var CStarNotFoundError = class extends CStarError {
|
|
76
|
-
constructor(
|
|
77
|
-
|
|
114
|
+
constructor(messageOrStatus, body) {
|
|
115
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
116
|
+
type: ErrorType.NOT_FOUND_ERROR,
|
|
117
|
+
code: "resource_not_found",
|
|
118
|
+
doc_url: `${DEFAULT_DOC_URL}#not-found-error`
|
|
119
|
+
});
|
|
120
|
+
super(statusCode, resolved);
|
|
78
121
|
this.name = "CStarNotFoundError";
|
|
79
122
|
}
|
|
80
123
|
};
|
|
81
124
|
var CStarValidationError = class extends CStarError {
|
|
82
|
-
constructor(
|
|
83
|
-
|
|
125
|
+
constructor(messageOrStatus, body) {
|
|
126
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
127
|
+
type: ErrorType.INVALID_REQUEST_ERROR,
|
|
128
|
+
code: "validation_error",
|
|
129
|
+
doc_url: `${DEFAULT_DOC_URL}#validation-error`
|
|
130
|
+
});
|
|
131
|
+
super(statusCode, resolved);
|
|
84
132
|
this.name = "CStarValidationError";
|
|
85
133
|
}
|
|
86
134
|
};
|
|
87
135
|
var CStarPermissionError = class extends CStarError {
|
|
88
|
-
constructor(
|
|
89
|
-
|
|
136
|
+
constructor(messageOrStatus, body) {
|
|
137
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
138
|
+
type: ErrorType.PERMISSION_ERROR,
|
|
139
|
+
code: "permission_denied",
|
|
140
|
+
doc_url: `${DEFAULT_DOC_URL}#permission-error`
|
|
141
|
+
});
|
|
142
|
+
super(statusCode, resolved);
|
|
90
143
|
this.name = "CStarPermissionError";
|
|
91
144
|
}
|
|
92
145
|
};
|
|
93
146
|
var CStarConflictError = class extends CStarError {
|
|
94
|
-
constructor(
|
|
95
|
-
|
|
147
|
+
constructor(messageOrStatus, body) {
|
|
148
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
149
|
+
type: ErrorType.CONFLICT_ERROR,
|
|
150
|
+
code: "conflict",
|
|
151
|
+
doc_url: `${DEFAULT_DOC_URL}#conflict-error`
|
|
152
|
+
});
|
|
153
|
+
super(statusCode, resolved);
|
|
96
154
|
this.name = "CStarConflictError";
|
|
97
155
|
}
|
|
98
156
|
};
|
|
99
157
|
var CStarServerError = class extends CStarError {
|
|
100
|
-
constructor(
|
|
101
|
-
|
|
158
|
+
constructor(messageOrStatus, body) {
|
|
159
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
160
|
+
type: ErrorType.SERVER_ERROR,
|
|
161
|
+
code: "server_error",
|
|
162
|
+
doc_url: `${DEFAULT_DOC_URL}#server-error`
|
|
163
|
+
});
|
|
164
|
+
super(statusCode, resolved);
|
|
102
165
|
this.name = "CStarServerError";
|
|
103
166
|
}
|
|
104
167
|
};
|
|
168
|
+
var CStarFeatureDisabledError = class extends CStarError {
|
|
169
|
+
constructor(messageOrStatus, body) {
|
|
170
|
+
const { statusCode, body: resolved } = normalizeArgs(messageOrStatus, body, {
|
|
171
|
+
type: ErrorType.FEATURE_NOT_CONFIGURED,
|
|
172
|
+
code: "feature_not_configured",
|
|
173
|
+
doc_url: `${DEFAULT_DOC_URL}#feature-not-configured`
|
|
174
|
+
});
|
|
175
|
+
super(statusCode, resolved);
|
|
176
|
+
this.name = "CStarFeatureDisabledError";
|
|
177
|
+
this.feature = resolved.feature ?? "unknown";
|
|
178
|
+
this.enableUrl = resolved.enable_url ?? "";
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
var CStarRealtimeUnavailableError = class extends CStarError {
|
|
182
|
+
constructor(message) {
|
|
183
|
+
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";
|
|
184
|
+
super(0, {
|
|
185
|
+
type: ErrorType.API_ERROR,
|
|
186
|
+
code: "realtime_unavailable",
|
|
187
|
+
message: resolved,
|
|
188
|
+
doc_url: "https://cstar.help/developers/sdk/realtime#ssr"
|
|
189
|
+
});
|
|
190
|
+
this.name = "CStarRealtimeUnavailableError";
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
var STATUS_TO_CLASS = {
|
|
194
|
+
400: CStarValidationError,
|
|
195
|
+
401: CStarAuthenticationError,
|
|
196
|
+
403: CStarPermissionError,
|
|
197
|
+
404: CStarNotFoundError,
|
|
198
|
+
409: CStarConflictError,
|
|
199
|
+
422: CStarValidationError,
|
|
200
|
+
429: CStarRateLimitError
|
|
201
|
+
};
|
|
202
|
+
var TYPE_TO_CLASS = {
|
|
203
|
+
[ErrorType.AUTHENTICATION_ERROR]: CStarAuthenticationError,
|
|
204
|
+
[ErrorType.PERMISSION_ERROR]: CStarPermissionError,
|
|
205
|
+
[ErrorType.RATE_LIMIT_ERROR]: CStarRateLimitError,
|
|
206
|
+
[ErrorType.NOT_FOUND_ERROR]: CStarNotFoundError,
|
|
207
|
+
[ErrorType.INVALID_REQUEST_ERROR]: CStarValidationError,
|
|
208
|
+
[ErrorType.CONFLICT_ERROR]: CStarConflictError,
|
|
209
|
+
[ErrorType.SERVER_ERROR]: CStarServerError,
|
|
210
|
+
[ErrorType.FEATURE_NOT_CONFIGURED]: CStarFeatureDisabledError
|
|
211
|
+
};
|
|
105
212
|
function parseError(statusCode, body, retryAfter) {
|
|
106
213
|
const errorBody = body?.error ?? {
|
|
107
214
|
type: ErrorType.API_ERROR,
|
|
108
215
|
code: "unknown_error",
|
|
109
216
|
message: `Request failed with status ${statusCode}`,
|
|
110
|
-
doc_url:
|
|
217
|
+
doc_url: DEFAULT_DOC_URL
|
|
111
218
|
};
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
119
|
-
case ErrorType.NOT_FOUND_ERROR:
|
|
120
|
-
return new CStarNotFoundError(statusCode, errorBody);
|
|
121
|
-
case ErrorType.INVALID_REQUEST_ERROR:
|
|
122
|
-
return new CStarValidationError(statusCode, errorBody);
|
|
123
|
-
case ErrorType.CONFLICT_ERROR:
|
|
124
|
-
return new CStarConflictError(statusCode, errorBody);
|
|
125
|
-
case ErrorType.SERVER_ERROR:
|
|
126
|
-
return new CStarServerError(statusCode, errorBody);
|
|
127
|
-
default:
|
|
128
|
-
if (statusCode === 403) return new CStarPermissionError(statusCode, errorBody);
|
|
129
|
-
if (statusCode === 409) return new CStarConflictError(statusCode, errorBody);
|
|
130
|
-
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
131
|
-
return new CStarError(statusCode, errorBody);
|
|
219
|
+
if (statusCode === 429) {
|
|
220
|
+
return new CStarRateLimitError(statusCode, errorBody, retryAfter ?? 60);
|
|
221
|
+
}
|
|
222
|
+
const StatusCls = STATUS_TO_CLASS[statusCode];
|
|
223
|
+
if (StatusCls) {
|
|
224
|
+
return new StatusCls(statusCode, errorBody);
|
|
132
225
|
}
|
|
226
|
+
const TypeCls = TYPE_TO_CLASS[errorBody.type];
|
|
227
|
+
if (TypeCls) {
|
|
228
|
+
return new TypeCls(statusCode, errorBody);
|
|
229
|
+
}
|
|
230
|
+
if (statusCode >= 500) return new CStarServerError(statusCode, errorBody);
|
|
231
|
+
return new CStarError(statusCode, errorBody);
|
|
133
232
|
}
|
|
134
233
|
|
|
135
234
|
// src/client.ts
|
|
136
|
-
var SDK_VERSION = "0.
|
|
235
|
+
var SDK_VERSION = "0.14.0";
|
|
137
236
|
var DEFAULT_BASE_URL = "https://www.cstar.help";
|
|
138
237
|
var DEFAULT_API_VERSION = "2026-03-01";
|
|
139
238
|
var DEFAULT_MAX_RETRIES = 3;
|
|
140
239
|
var DEFAULT_TIMEOUT = 3e4;
|
|
141
240
|
var HttpClient = class {
|
|
142
241
|
constructor(config) {
|
|
242
|
+
/**
|
|
243
|
+
* Side-channel metadata from the most recent response. Holds the server
|
|
244
|
+
* `requestId`, `timestamp`, and (for list endpoints) `pagination`. Mutable
|
|
245
|
+
* per-call — read it immediately after awaiting the call.
|
|
246
|
+
*
|
|
247
|
+
* ```ts
|
|
248
|
+
* const ticket = await cstar.tickets.create({...});
|
|
249
|
+
* console.error('Created ticket', ticket.id, 'request:', cstar.lastMeta.requestId);
|
|
250
|
+
* ```
|
|
251
|
+
*/
|
|
252
|
+
this.lastMeta = { requestId: null, timestamp: null, pagination: null };
|
|
143
253
|
if (!config || typeof config.apiKey !== "string" || config.apiKey.length === 0) {
|
|
144
254
|
throw new Error(
|
|
145
255
|
"[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"
|
|
@@ -170,7 +280,32 @@ var HttpClient = class {
|
|
|
170
280
|
* Automatically retries on 5xx errors and rate limits.
|
|
171
281
|
*/
|
|
172
282
|
async request(method, path, options) {
|
|
173
|
-
|
|
283
|
+
return this._sendRequest(method, this.buildUrl(path, options?.query), options);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Like `request()` but skips the `/api/v1/teams/{teamId}` prefix. Used for
|
|
287
|
+
* the small set of non-team-scoped endpoints (`/auth/whoami`, etc).
|
|
288
|
+
*
|
|
289
|
+
* @internal — exposed to CStarClient for `whoami()` and similar; not part
|
|
290
|
+
* of the documented public surface.
|
|
291
|
+
*/
|
|
292
|
+
async requestUnscoped(method, path, options) {
|
|
293
|
+
const baseUrl = this.config.baseUrl + "/api/v1" + path;
|
|
294
|
+
const finalUrl = this.appendQuery(baseUrl, options?.query);
|
|
295
|
+
return this._sendRequest(method, finalUrl, options);
|
|
296
|
+
}
|
|
297
|
+
appendQuery(url, query) {
|
|
298
|
+
if (!query) return url;
|
|
299
|
+
const params = new URLSearchParams();
|
|
300
|
+
for (const [key, value] of Object.entries(query)) {
|
|
301
|
+
if (value === void 0 || value === null) continue;
|
|
302
|
+
if (Array.isArray(value)) for (const v of value) params.append(`${key}[]`, v);
|
|
303
|
+
else params.set(key, String(value));
|
|
304
|
+
}
|
|
305
|
+
const qs = params.toString();
|
|
306
|
+
return qs ? `${url}?${qs}` : url;
|
|
307
|
+
}
|
|
308
|
+
async _sendRequest(method, url, options) {
|
|
174
309
|
const headers = this.buildHeaders(options?.idempotencyKey);
|
|
175
310
|
const body = options?.body ? JSON.stringify(options.body) : void 0;
|
|
176
311
|
let lastError = null;
|
|
@@ -201,13 +336,9 @@ var HttpClient = class {
|
|
|
201
336
|
if (response.ok) {
|
|
202
337
|
if (response.status === 204) return void 0;
|
|
203
338
|
const json = await response.json();
|
|
204
|
-
const
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
const metaBase = existing && typeof existing === "object" && !Array.isArray(existing) ? existing : {};
|
|
208
|
-
json.meta = { ...metaBase, requestId: requestId2 };
|
|
209
|
-
}
|
|
210
|
-
return json;
|
|
339
|
+
const headerRequestId = response.headers.get("x-request-id") ?? response.headers.get("x-cstar-request-id");
|
|
340
|
+
this.captureMeta(json, headerRequestId);
|
|
341
|
+
return this.unwrapEnvelope(json);
|
|
211
342
|
}
|
|
212
343
|
const errorBody = await response.json().catch(() => null);
|
|
213
344
|
const retryAfter = parseInt(response.headers.get("Retry-After") ?? "", 10) || void 0;
|
|
@@ -229,6 +360,51 @@ var HttpClient = class {
|
|
|
229
360
|
}
|
|
230
361
|
throw lastError ?? new Error("Request failed after retries");
|
|
231
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Capture `meta`, `requestId`, and `pagination` from the raw response
|
|
365
|
+
* into `this.lastMeta` before unwrapping the envelope.
|
|
366
|
+
*/
|
|
367
|
+
captureMeta(body, headerRequestId) {
|
|
368
|
+
if (body && typeof body === "object" && !Array.isArray(body)) {
|
|
369
|
+
const obj = body;
|
|
370
|
+
const meta = obj.meta && typeof obj.meta === "object" ? obj.meta : null;
|
|
371
|
+
const pagination = obj.pagination && typeof obj.pagination === "object" ? obj.pagination : null;
|
|
372
|
+
this.lastMeta = {
|
|
373
|
+
requestId: headerRequestId ?? (typeof meta?.requestId === "string" ? meta.requestId : null),
|
|
374
|
+
timestamp: typeof meta?.timestamp === "string" ? meta.timestamp : null,
|
|
375
|
+
pagination
|
|
376
|
+
};
|
|
377
|
+
return;
|
|
378
|
+
}
|
|
379
|
+
this.lastMeta = { requestId: headerRequestId, timestamp: null, pagination: null };
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Unwrap the legacy `{success, data, meta, pagination?}` envelope.
|
|
383
|
+
* - `{success:true, data: array, pagination}` → `{data, pagination, hasMore}`
|
|
384
|
+
* - `{success:true, data: object}` → `data` (bare resource)
|
|
385
|
+
* - other shapes pass through unchanged so subpath SDKs (chat, library) keep
|
|
386
|
+
* their bespoke shapes for now.
|
|
387
|
+
*/
|
|
388
|
+
unwrapEnvelope(body) {
|
|
389
|
+
if (!body || typeof body !== "object" || Array.isArray(body)) return body;
|
|
390
|
+
const obj = body;
|
|
391
|
+
if (obj.success !== true || !("data" in obj)) return body;
|
|
392
|
+
const data = obj.data;
|
|
393
|
+
if (Array.isArray(data)) {
|
|
394
|
+
const pagination = obj.pagination ?? null;
|
|
395
|
+
return {
|
|
396
|
+
data,
|
|
397
|
+
pagination: pagination ?? {
|
|
398
|
+
total: data.length,
|
|
399
|
+
page: 1,
|
|
400
|
+
pageSize: data.length,
|
|
401
|
+
hasMore: false
|
|
402
|
+
},
|
|
403
|
+
hasMore: pagination?.hasMore ?? false
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
return data;
|
|
407
|
+
}
|
|
232
408
|
buildUrl(path, query) {
|
|
233
409
|
const base = `${this.config.baseUrl}/api/v1/teams/${this.config.teamId}${path}`;
|
|
234
410
|
if (!query) return base;
|
|
@@ -301,6 +477,18 @@ var CStarRealtime = class {
|
|
|
301
477
|
this.autoReconnect = options?.autoReconnect ?? true;
|
|
302
478
|
this.maxRetries = options?.maxRetries ?? 10;
|
|
303
479
|
this.types = options?.types;
|
|
480
|
+
this.eventSourceCtor = options?.eventSource;
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Resolve the EventSource constructor to use for this connection.
|
|
484
|
+
* Returns the explicit polyfill when one was injected, otherwise the
|
|
485
|
+
* global. Returns `undefined` when neither is available — callers must
|
|
486
|
+
* convert to `CStarRealtimeUnavailableError` before touching it.
|
|
487
|
+
*/
|
|
488
|
+
resolveEventSource() {
|
|
489
|
+
if (this.eventSourceCtor) return this.eventSourceCtor;
|
|
490
|
+
const fromGlobal = globalThis.EventSource;
|
|
491
|
+
return typeof fromGlobal === "function" ? fromGlobal : void 0;
|
|
304
492
|
}
|
|
305
493
|
/** Subscribe to a specific event type. Supports wildcards (e.g., 'ticket.*'). Returns an unsubscribe function. */
|
|
306
494
|
on(eventType, handler) {
|
|
@@ -355,6 +543,9 @@ var CStarRealtime = class {
|
|
|
355
543
|
/** Start the SSE connection. Called automatically on first handler registration. */
|
|
356
544
|
connect() {
|
|
357
545
|
if (this.eventSource || this.destroyed || this.connecting) return;
|
|
546
|
+
if (!this.resolveEventSource()) {
|
|
547
|
+
throw new CStarRealtimeUnavailableError();
|
|
548
|
+
}
|
|
358
549
|
this.connecting = true;
|
|
359
550
|
const headers = this.httpClient.getAuthHeaders();
|
|
360
551
|
const rawKey = headers.Authorization?.replace("Bearer ", "") ?? "";
|
|
@@ -393,7 +584,12 @@ var CStarRealtime = class {
|
|
|
393
584
|
}
|
|
394
585
|
const separator = qs ? "&" : "?";
|
|
395
586
|
const authenticatedUrl = authToken ? `${url}${separator}token=${authToken}` : url;
|
|
396
|
-
|
|
587
|
+
const Ctor = this.resolveEventSource();
|
|
588
|
+
if (!Ctor) {
|
|
589
|
+
this.connecting = false;
|
|
590
|
+
throw new CStarRealtimeUnavailableError();
|
|
591
|
+
}
|
|
592
|
+
this.eventSource = new Ctor(authenticatedUrl);
|
|
397
593
|
this.eventSource.onopen = () => {
|
|
398
594
|
this.connecting = false;
|
|
399
595
|
this.retryCount = 0;
|
|
@@ -812,6 +1008,14 @@ var BaseResource = class {
|
|
|
812
1008
|
async del(id) {
|
|
813
1009
|
return this.client.request("DELETE", `${this.basePath}/${id}`);
|
|
814
1010
|
}
|
|
1011
|
+
/**
|
|
1012
|
+
* Delete a resource by ID. Alias for `del()` — kept because IDE
|
|
1013
|
+
* auto-complete and documentation both surface `delete` first. Closes
|
|
1014
|
+
* NEW-v2-06.
|
|
1015
|
+
*/
|
|
1016
|
+
async delete(id) {
|
|
1017
|
+
return this.del(id);
|
|
1018
|
+
}
|
|
815
1019
|
/**
|
|
816
1020
|
* Auto-paginating async iterator that yields every item across all pages.
|
|
817
1021
|
*
|
|
@@ -1910,7 +2114,12 @@ var GameResource = class {
|
|
|
1910
2114
|
async getPlayer(memberId) {
|
|
1911
2115
|
return this.client.request("GET", `/game/player/${memberId}`);
|
|
1912
2116
|
}
|
|
1913
|
-
/**
|
|
2117
|
+
/**
|
|
2118
|
+
* Get the team leaderboard. Returns the unwrapped envelope from the
|
|
2119
|
+
* `/game/leaderboard` endpoint (`{entries, totalParticipants, period, ...}`)
|
|
2120
|
+
* — wider than a flat array because the server includes the period and
|
|
2121
|
+
* a participant count alongside the entries.
|
|
2122
|
+
*/
|
|
1914
2123
|
async leaderboard(params) {
|
|
1915
2124
|
return this.client.request("GET", "/game/leaderboard", {
|
|
1916
2125
|
query: params
|
|
@@ -1933,12 +2142,12 @@ var GameResource = class {
|
|
|
1933
2142
|
*/
|
|
1934
2143
|
subscribeBoss(realtime) {
|
|
1935
2144
|
const fetchFn = async () => {
|
|
1936
|
-
const
|
|
2145
|
+
const boss = await this.boss.current();
|
|
2146
|
+
const list = boss.active ? [boss] : [];
|
|
1937
2147
|
return {
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
meta: { requestId: "", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2148
|
+
data: list,
|
|
2149
|
+
pagination: { total: list.length, page: 1, pageSize: 1, hasMore: false },
|
|
2150
|
+
hasMore: false
|
|
1942
2151
|
};
|
|
1943
2152
|
};
|
|
1944
2153
|
return new Subscription(realtime, fetchFn, "/game/boss");
|
|
@@ -1949,12 +2158,11 @@ var GameResource = class {
|
|
|
1949
2158
|
*/
|
|
1950
2159
|
subscribePlayer(realtime, userId) {
|
|
1951
2160
|
const fetchFn = async () => {
|
|
1952
|
-
const
|
|
2161
|
+
const player = await this.player({ userId });
|
|
1953
2162
|
return {
|
|
1954
|
-
|
|
1955
|
-
data: [res.data],
|
|
2163
|
+
data: [player],
|
|
1956
2164
|
pagination: { total: 1, page: 1, pageSize: 1, hasMore: false },
|
|
1957
|
-
|
|
2165
|
+
hasMore: false
|
|
1958
2166
|
};
|
|
1959
2167
|
};
|
|
1960
2168
|
return new Subscription(realtime, fetchFn, "/game/player");
|
|
@@ -1965,14 +2173,12 @@ var GameResource = class {
|
|
|
1965
2173
|
*/
|
|
1966
2174
|
subscribeLeaderboard(realtime, params) {
|
|
1967
2175
|
const fetchFn = async () => {
|
|
1968
|
-
const
|
|
1969
|
-
const
|
|
1970
|
-
const entries = Array.isArray(envelope) ? envelope : envelope?.entries ?? [];
|
|
2176
|
+
const board = await this.leaderboard(params);
|
|
2177
|
+
const entries = board.entries ?? [];
|
|
1971
2178
|
return {
|
|
1972
|
-
success: true,
|
|
1973
2179
|
data: entries,
|
|
1974
2180
|
pagination: { total: entries.length, page: 1, pageSize: 100, hasMore: false },
|
|
1975
|
-
|
|
2181
|
+
hasMore: false
|
|
1976
2182
|
};
|
|
1977
2183
|
};
|
|
1978
2184
|
return new Subscription(realtime, fetchFn, "/game/leaderboard");
|
|
@@ -1983,13 +2189,12 @@ var GameResource = class {
|
|
|
1983
2189
|
*/
|
|
1984
2190
|
subscribeActivity(realtime) {
|
|
1985
2191
|
const fetchFn = async () => {
|
|
1986
|
-
const
|
|
1987
|
-
const
|
|
2192
|
+
const feed = await this.activity.list({ limit: 50 });
|
|
2193
|
+
const items = feed.data ?? [];
|
|
1988
2194
|
return {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
meta: { requestId: "", timestamp: (/* @__PURE__ */ new Date()).toISOString() }
|
|
2195
|
+
data: items,
|
|
2196
|
+
pagination: { total: items.length, page: 1, pageSize: 50, hasMore: false },
|
|
2197
|
+
hasMore: false
|
|
1993
2198
|
};
|
|
1994
2199
|
};
|
|
1995
2200
|
return new Subscription(realtime, fetchFn, "/game/activity");
|
|
@@ -2227,6 +2432,35 @@ var CStarClient = class {
|
|
|
2227
2432
|
get isTestMode() {
|
|
2228
2433
|
return this._httpClient.environment === "test";
|
|
2229
2434
|
}
|
|
2435
|
+
/**
|
|
2436
|
+
* Validate the configured API key and return the team + key metadata it
|
|
2437
|
+
* resolves to. Useful for confirming the key is wired up correctly during
|
|
2438
|
+
* onboarding (and for AI assistants that want a one-call sanity check).
|
|
2439
|
+
*
|
|
2440
|
+
* Closes F-018.
|
|
2441
|
+
*
|
|
2442
|
+
* ```ts
|
|
2443
|
+
* const me = await cstar.whoami();
|
|
2444
|
+
* console.log(me.teamSlug, me.environment); // 'acme', 'test'
|
|
2445
|
+
* ```
|
|
2446
|
+
*/
|
|
2447
|
+
async whoami() {
|
|
2448
|
+
return this._httpClient.requestUnscoped("GET", "/auth/whoami");
|
|
2449
|
+
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Side-channel metadata from the most recent HTTP response. Holds the
|
|
2452
|
+
* server `requestId` (for support escalations), `timestamp`, and the
|
|
2453
|
+
* `pagination` info from list endpoints. Reset on every call — read it
|
|
2454
|
+
* immediately after awaiting the call you care about.
|
|
2455
|
+
*
|
|
2456
|
+
* ```ts
|
|
2457
|
+
* const ticket = await cstar.tickets.create({...});
|
|
2458
|
+
* console.error('Created', ticket.id, 'request:', cstar.lastMeta.requestId);
|
|
2459
|
+
* ```
|
|
2460
|
+
*/
|
|
2461
|
+
get lastMeta() {
|
|
2462
|
+
return this._httpClient.lastMeta;
|
|
2463
|
+
}
|
|
2230
2464
|
};
|
|
2231
2465
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2232
2466
|
0 && (module.exports = {
|
|
@@ -2234,6 +2468,7 @@ var CStarClient = class {
|
|
|
2234
2468
|
CStarClient,
|
|
2235
2469
|
CStarConflictError,
|
|
2236
2470
|
CStarError,
|
|
2471
|
+
CStarFeatureDisabledError,
|
|
2237
2472
|
CStarNotFoundError,
|
|
2238
2473
|
CStarPermissionError,
|
|
2239
2474
|
CStarRateLimitError,
|