scorezilla 0.1.0-next.3 → 0.3.0-next.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 +184 -0
- package/README.md +13 -0
- package/dist/{errors-CUAQsaVS.d.cts → errors-B7hyC-C5.d.cts} +79 -5
- package/dist/{errors-CUAQsaVS.d.ts → errors-B7hyC-C5.d.ts} +79 -5
- package/dist/identity.cjs +87 -0
- package/dist/identity.cjs.map +1 -0
- package/dist/identity.d.cts +151 -0
- package/dist/identity.d.ts +151 -0
- package/dist/identity.js +82 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.cjs +96 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -6
- package/dist/index.d.ts +18 -6
- package/dist/index.js +96 -10
- package/dist/index.js.map +1 -1
- package/dist/server.cjs +95 -9
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.cts +19 -13
- package/dist/server.d.ts +19 -13
- package/dist/server.js +95 -9
- package/dist/server.js.map +1 -1
- package/package.json +14 -1
package/dist/index.js
CHANGED
|
@@ -31,6 +31,7 @@ function validateConfig(cfg) {
|
|
|
31
31
|
timeoutMs: cfg.timeoutMs,
|
|
32
32
|
maxRetries: cfg.maxRetries,
|
|
33
33
|
sleepImpl: cfg.sleepImpl,
|
|
34
|
+
warn: cfg.warn,
|
|
34
35
|
userAgent: cfg.userAgent,
|
|
35
36
|
auth
|
|
36
37
|
};
|
|
@@ -117,7 +118,9 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
117
118
|
* {@link ScorezillaErrorCode}. For network errors, this is `'network_error'`;
|
|
118
119
|
* for aborts, `'aborted'`; for timeouts, `'timeout'`. */
|
|
119
120
|
code;
|
|
120
|
-
/** Sub-classifier — present on
|
|
121
|
+
/** Sub-classifier — present on:
|
|
122
|
+
* - `out_of_bounds`: `'below_min' | 'above_max'`
|
|
123
|
+
* - `usage_cap_exceeded`: `'over_cap' | 'suspended'`
|
|
121
124
|
* and possibly other codes in future minor releases. */
|
|
122
125
|
reason;
|
|
123
126
|
/** Seconds — present on `rate_limited`. Honored by the transport's retry
|
|
@@ -130,6 +133,20 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
130
133
|
bound;
|
|
131
134
|
/** Which rate-limit layer fired on `rate_limited`. */
|
|
132
135
|
layer;
|
|
136
|
+
/** Tenant's billing tier — present on `usage_cap_exceeded`. */
|
|
137
|
+
tier;
|
|
138
|
+
/** The cap value crossed on `usage_cap_exceeded`. `0` indicates a
|
|
139
|
+
* suspended tenant. `undefined` on all other error codes. */
|
|
140
|
+
cap;
|
|
141
|
+
/** The post-increment submit count on `usage_cap_exceeded`. Always
|
|
142
|
+
* `> cap` when `reason === 'over_cap'`. */
|
|
143
|
+
count;
|
|
144
|
+
/** The period the count belongs to on `usage_cap_exceeded`, in `YYYY-MM`
|
|
145
|
+
* UTC form. */
|
|
146
|
+
period;
|
|
147
|
+
/** ISO-8601 timestamp of midnight UTC on the 1st of the next month —
|
|
148
|
+
* the counter's natural reset point on `usage_cap_exceeded`. */
|
|
149
|
+
resetsAt;
|
|
133
150
|
/** The underlying cause (e.g., a `TypeError: fetch failed`) for
|
|
134
151
|
* network/abort/timeout paths. `undefined` when the error came from a
|
|
135
152
|
* successfully-parsed API error body. */
|
|
@@ -144,6 +161,11 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
144
161
|
this.requestId = truncateField(init.requestId);
|
|
145
162
|
this.bound = init.bound;
|
|
146
163
|
this.layer = truncateField(init.layer);
|
|
164
|
+
this.tier = truncateField(init.tier);
|
|
165
|
+
this.cap = init.cap;
|
|
166
|
+
this.count = init.count;
|
|
167
|
+
this.period = truncateField(init.period);
|
|
168
|
+
this.resetsAt = truncateField(init.resetsAt);
|
|
147
169
|
this.cause = init.cause;
|
|
148
170
|
Object.setPrototypeOf(this, _ScorezillaError.prototype);
|
|
149
171
|
if (typeof Error.captureStackTrace === "function") {
|
|
@@ -157,6 +179,22 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
157
179
|
isRateLimited() {
|
|
158
180
|
return this.code === "rate_limited";
|
|
159
181
|
}
|
|
182
|
+
/**
|
|
183
|
+
* `true` when this error is a 402 / `usage_cap_exceeded`. The tenant
|
|
184
|
+
* has either hit their tier's monthly submit cap (`reason ===
|
|
185
|
+
* 'over_cap'`) or is suspended (`reason === 'suspended'`).
|
|
186
|
+
*
|
|
187
|
+
* Consumers SHOULD NOT auto-retry on this error — the cap doesn't lift
|
|
188
|
+
* until `resetsAt`. Surface to the developer with an upgrade prompt
|
|
189
|
+
* (over_cap) or contact-support message (suspended).
|
|
190
|
+
*/
|
|
191
|
+
isUsageCapExceeded() {
|
|
192
|
+
return this.code === "usage_cap_exceeded";
|
|
193
|
+
}
|
|
194
|
+
/** `true` when this error is a 402 + reason 'suspended' (vs over-cap). */
|
|
195
|
+
isSuspended() {
|
|
196
|
+
return this.code === "usage_cap_exceeded" && this.reason === "suspended";
|
|
197
|
+
}
|
|
160
198
|
/** `true` when this error is a 401 / `unauthorized` (or 403 / `forbidden`). */
|
|
161
199
|
isAuth() {
|
|
162
200
|
return this.code === "unauthorized" || this.code === "forbidden";
|
|
@@ -169,13 +207,21 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
169
207
|
isOutOfBounds() {
|
|
170
208
|
return this.code === "out_of_bounds";
|
|
171
209
|
}
|
|
172
|
-
/** `true` for
|
|
173
|
-
*
|
|
210
|
+
/** `true` for the SDK's retryable conditions: pure network errors, 5xx, and
|
|
211
|
+
* 429. Deliberately excludes `timeout` and `aborted` — those are caller-
|
|
212
|
+
* observable terminal states, not transient. Aligned with `shouldRetryError`
|
|
213
|
+
* in `retry.ts` so a consumer mirroring the SDK's retry policy gets the
|
|
214
|
+
* same answer the transport does. */
|
|
174
215
|
isTransient() {
|
|
175
|
-
if (this.
|
|
216
|
+
if (this.code === "network_error") return true;
|
|
176
217
|
if (this.status >= 500 && this.status < 600) return true;
|
|
177
218
|
return this.isRateLimited();
|
|
178
219
|
}
|
|
220
|
+
/** `true` when this error is a 409 / `conflict` (idempotency-key conflict
|
|
221
|
+
* on retry). */
|
|
222
|
+
isConflict() {
|
|
223
|
+
return this.code === "conflict";
|
|
224
|
+
}
|
|
179
225
|
// ─── Factory ─────────────────────────────────────────────────────────
|
|
180
226
|
/**
|
|
181
227
|
* Build a `ScorezillaError` from a fetch round-trip outcome.
|
|
@@ -196,6 +242,13 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
196
242
|
retryAfter: body.retryAfter,
|
|
197
243
|
bound: body.bound,
|
|
198
244
|
layer: body.layer,
|
|
245
|
+
// Usage-cap fields from `ApiError` (populated by the server on
|
|
246
|
+
// 402 responses; undefined on other errors).
|
|
247
|
+
tier: body.tier,
|
|
248
|
+
cap: body.cap,
|
|
249
|
+
count: body.count,
|
|
250
|
+
period: body.period,
|
|
251
|
+
resetsAt: body.resetsAt,
|
|
199
252
|
requestId,
|
|
200
253
|
cause
|
|
201
254
|
});
|
|
@@ -237,8 +290,10 @@ var ScorezillaError = class _ScorezillaError extends Error {
|
|
|
237
290
|
};
|
|
238
291
|
function codeForStatus(status) {
|
|
239
292
|
if (status === 401) return "unauthorized";
|
|
293
|
+
if (status === 402) return "usage_cap_exceeded";
|
|
240
294
|
if (status === 403) return "forbidden";
|
|
241
295
|
if (status === 404) return "not_found";
|
|
296
|
+
if (status === 409) return "conflict";
|
|
242
297
|
if (status === 422) return "out_of_bounds";
|
|
243
298
|
if (status === 429) return "rate_limited";
|
|
244
299
|
if (status >= 500) return "internal_error";
|
|
@@ -349,6 +404,7 @@ async function request(opts) {
|
|
|
349
404
|
}
|
|
350
405
|
const response = await fetchImpl(url, init);
|
|
351
406
|
if (response.ok) {
|
|
407
|
+
warnOnDeprecationOnce(response, opts.warnImpl);
|
|
352
408
|
return await parseJson(response);
|
|
353
409
|
}
|
|
354
410
|
const body = await safelyParseErrorBody(response);
|
|
@@ -460,6 +516,29 @@ function readRetryAfter(response) {
|
|
|
460
516
|
const n = Number(raw);
|
|
461
517
|
return Number.isFinite(n) && n >= 0 ? n : void 0;
|
|
462
518
|
}
|
|
519
|
+
var seenDeprecations = /* @__PURE__ */ new Set();
|
|
520
|
+
function warnOnDeprecationOnce(response, warnImpl) {
|
|
521
|
+
const deprecation = response.headers.get("Deprecation");
|
|
522
|
+
const sunset = response.headers.get("Sunset");
|
|
523
|
+
if (!deprecation && !sunset) return;
|
|
524
|
+
const link = response.headers.get("Link") ?? "";
|
|
525
|
+
const key = `${deprecation ?? ""}|${sunset ?? ""}|${link}`;
|
|
526
|
+
if (seenDeprecations.has(key)) return;
|
|
527
|
+
seenDeprecations.add(key);
|
|
528
|
+
const detail = [];
|
|
529
|
+
if (deprecation === "true" || deprecation) detail.push(`Deprecation: ${deprecation}`);
|
|
530
|
+
if (sunset) detail.push(`Sunset: ${sunset}`);
|
|
531
|
+
if (link) {
|
|
532
|
+
const m = link.match(/<([^>]+)>/);
|
|
533
|
+
if (m) detail.push(`Docs: ${m[1]}`);
|
|
534
|
+
}
|
|
535
|
+
const message = `[scorezilla-sdk] API responded with deprecation signal: ${detail.join(" \xB7 ")}. Upgrade your SDK before the sunset date.`;
|
|
536
|
+
if (warnImpl) {
|
|
537
|
+
warnImpl(message);
|
|
538
|
+
} else {
|
|
539
|
+
console.warn(message);
|
|
540
|
+
}
|
|
541
|
+
}
|
|
463
542
|
function combineSignalsWithTimeout(caller, timeoutMs) {
|
|
464
543
|
const ctrl = new AbortController();
|
|
465
544
|
let didTimeOut = false;
|
|
@@ -548,10 +627,11 @@ function validateMetadata(metadata) {
|
|
|
548
627
|
`scorezilla: metadata exceeds ${METADATA_MAX_BYTES} bytes (got ${byteLength} bytes when JSON-stringified)`
|
|
549
628
|
);
|
|
550
629
|
}
|
|
630
|
+
return serialized;
|
|
551
631
|
}
|
|
552
632
|
var Scorezilla = class _Scorezilla {
|
|
553
633
|
/** The package version, injected at build time from `package.json`. */
|
|
554
|
-
static version = "0.
|
|
634
|
+
static version = "0.3.0-next.0";
|
|
555
635
|
#config;
|
|
556
636
|
#userAgent;
|
|
557
637
|
#authHeader;
|
|
@@ -609,7 +689,8 @@ var Scorezilla = class _Scorezilla {
|
|
|
609
689
|
return this.#request({
|
|
610
690
|
path: submitScorePath(input.boardId),
|
|
611
691
|
method: "POST",
|
|
612
|
-
body
|
|
692
|
+
body,
|
|
693
|
+
signal: input.signal
|
|
613
694
|
});
|
|
614
695
|
}
|
|
615
696
|
/**
|
|
@@ -633,7 +714,8 @@ var Scorezilla = class _Scorezilla {
|
|
|
633
714
|
if (input.offset !== void 0) q.offset = input.offset;
|
|
634
715
|
return this.#request({
|
|
635
716
|
path: getLeaderboardPath(input.boardId, q),
|
|
636
|
-
method: "GET"
|
|
717
|
+
method: "GET",
|
|
718
|
+
signal: input.signal
|
|
637
719
|
});
|
|
638
720
|
}
|
|
639
721
|
/**
|
|
@@ -662,7 +744,8 @@ var Scorezilla = class _Scorezilla {
|
|
|
662
744
|
async getPlayerRank(input) {
|
|
663
745
|
return this.#request({
|
|
664
746
|
path: getPlayerRankPath(input.boardId, input.playerId),
|
|
665
|
-
method: "GET"
|
|
747
|
+
method: "GET",
|
|
748
|
+
signal: input.signal
|
|
666
749
|
});
|
|
667
750
|
}
|
|
668
751
|
/**
|
|
@@ -687,7 +770,8 @@ var Scorezilla = class _Scorezilla {
|
|
|
687
770
|
if (input.after !== void 0) q.after = input.after;
|
|
688
771
|
return this.#request({
|
|
689
772
|
path: getWindowAroundPath(input.boardId, input.playerId, q),
|
|
690
|
-
method: "GET"
|
|
773
|
+
method: "GET",
|
|
774
|
+
signal: input.signal
|
|
691
775
|
});
|
|
692
776
|
}
|
|
693
777
|
// ─── Internal ────────────────────────────────────────────────────────
|
|
@@ -714,7 +798,9 @@ var Scorezilla = class _Scorezilla {
|
|
|
714
798
|
headers
|
|
715
799
|
};
|
|
716
800
|
if (opts.body !== void 0) requestOpts.body = opts.body;
|
|
801
|
+
if (opts.signal !== void 0) requestOpts.signal = opts.signal;
|
|
717
802
|
if (this.#config.fetch !== void 0) requestOpts.fetchImpl = this.#config.fetch;
|
|
803
|
+
if (this.#config.warn !== void 0) requestOpts.warnImpl = this.#config.warn;
|
|
718
804
|
if (this.#config.timeoutMs !== void 0) requestOpts.timeoutMs = this.#config.timeoutMs;
|
|
719
805
|
if (this.#config.maxRetries !== void 0 || this.#config.sleepImpl !== void 0) {
|
|
720
806
|
requestOpts.retry = {
|
|
@@ -730,7 +816,7 @@ function createClient(config) {
|
|
|
730
816
|
}
|
|
731
817
|
|
|
732
818
|
// src/index.ts
|
|
733
|
-
var SDK_VERSION = "0.
|
|
819
|
+
var SDK_VERSION = "0.3.0-next.0";
|
|
734
820
|
|
|
735
821
|
export { SDK_VERSION, Scorezilla, ScorezillaError, createClient, detectRuntime };
|
|
736
822
|
//# sourceMappingURL=index.js.map
|