@bedrock-rbx/ocale 0.1.0-beta.13 → 0.1.0-beta.15

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.
Files changed (55) hide show
  1. package/README.md +128 -0
  2. package/dist/badges.d.mts +1 -1
  3. package/dist/badges.mjs +3 -2
  4. package/dist/badges.mjs.map +1 -1
  5. package/dist/developer-products.d.mts +1 -1
  6. package/dist/developer-products.mjs +4 -3
  7. package/dist/developer-products.mjs.map +1 -1
  8. package/dist/game-passes.d.mts +1 -1
  9. package/dist/game-passes.mjs +4 -3
  10. package/dist/game-passes.mjs.map +1 -1
  11. package/dist/index.d.mts +3 -12
  12. package/dist/index.d.mts.map +1 -1
  13. package/dist/index.mjs +5 -5
  14. package/dist/luau-execution.d.mts +3 -3
  15. package/dist/luau-execution.mjs +5 -4
  16. package/dist/luau-execution.mjs.map +1 -1
  17. package/dist/places.d.mts +2 -2
  18. package/dist/places.mjs +5 -4
  19. package/dist/places.mjs.map +1 -1
  20. package/dist/{poll-timeout-Dg_QFEqi.mjs → poll-timeout-DMS4UPro.mjs} +2 -2
  21. package/dist/{poll-timeout-Dg_QFEqi.mjs.map → poll-timeout-DMS4UPro.mjs.map} +1 -1
  22. package/dist/{polling-BMrYajok.d.mts → polling-Vn5MT-fh.d.mts} +38 -9
  23. package/dist/{polling-BMrYajok.d.mts.map → polling-Vn5MT-fh.d.mts.map} +1 -1
  24. package/dist/{polling-helpers-QGjvYq3c.mjs → polling-helpers-B35M3ViY.mjs} +166 -54
  25. package/dist/{polling-helpers-QGjvYq3c.mjs.map → polling-helpers-B35M3ViY.mjs.map} +1 -1
  26. package/dist/{price-information-DIrvwCmd.mjs → price-information-DT7_QJN-.mjs} +2 -2
  27. package/dist/{price-information-DIrvwCmd.mjs.map → price-information-DT7_QJN-.mjs.map} +1 -1
  28. package/dist/{rate-limit-D1q2Js-z.mjs → rate-limit-nY4BF079.mjs} +19 -2
  29. package/dist/rate-limit-nY4BF079.mjs.map +1 -0
  30. package/dist/{resource-client-D6Efj9fU.mjs → resource-client-CG9-BG81.mjs} +67 -237
  31. package/dist/resource-client-CG9-BG81.mjs.map +1 -0
  32. package/dist/retry-BzX29aw_.mjs +333 -0
  33. package/dist/retry-BzX29aw_.mjs.map +1 -0
  34. package/dist/retry-CXnj3gXI.d.mts +163 -0
  35. package/dist/retry-CXnj3gXI.d.mts.map +1 -0
  36. package/dist/storage.d.mts +2 -27
  37. package/dist/storage.d.mts.map +1 -1
  38. package/dist/storage.mjs +3 -2
  39. package/dist/storage.mjs.map +1 -1
  40. package/dist/testing.d.mts +1 -1
  41. package/dist/testing.mjs +1 -1
  42. package/dist/{types-CwtZT1ek.d.mts → types-rzs1NB-j.d.mts} +12 -2
  43. package/dist/{types-CwtZT1ek.d.mts.map → types-rzs1NB-j.d.mts.map} +1 -1
  44. package/dist/universes.d.mts +1 -1
  45. package/dist/universes.mjs +4 -3
  46. package/dist/universes.mjs.map +1 -1
  47. package/dist/{validation-DkL5KQqz.mjs → validation-CGsK8aey.mjs} +2 -2
  48. package/dist/{validation-DkL5KQqz.mjs.map → validation-CGsK8aey.mjs.map} +1 -1
  49. package/package.json +3 -3
  50. package/dist/permission-error-DOVtNq3A.mjs +0 -46
  51. package/dist/permission-error-DOVtNq3A.mjs.map +0 -1
  52. package/dist/rate-limit-BYuizHoD.d.mts +0 -92
  53. package/dist/rate-limit-BYuizHoD.d.mts.map +0 -1
  54. package/dist/rate-limit-D1q2Js-z.mjs.map +0 -1
  55. package/dist/resource-client-D6Efj9fU.mjs.map +0 -1
@@ -0,0 +1,333 @@
1
+ import { n as NetworkError, r as ApiError, t as RateLimitError } from "./rate-limit-nY4BF079.mjs";
2
+ //#region src/errors/permission-error.ts
3
+ /**
4
+ * Thrown when the Roblox Open Cloud API returns a 401 or 403 for an operation
5
+ * whose required scopes are known. Subclass of {@link ApiError} carrying the
6
+ * scope strings the caller's credential is missing plus the operation key, so
7
+ * a CLI consumer can tell the user exactly which scope to grant on their API
8
+ * key.
9
+ *
10
+ * @example
11
+ *
12
+ * ```ts
13
+ * import { PermissionError } from "@bedrock-rbx/ocale";
14
+ *
15
+ * const error = new PermissionError("HTTP 403", {
16
+ * operationKey: "developer-products.create",
17
+ * requiredScopes: ["creator-store-product:write"],
18
+ * statusCode: 403,
19
+ * });
20
+ *
21
+ * expect(error).toBeInstanceOf(PermissionError);
22
+ * expect(error.requiredScopes).toStrictEqual(["creator-store-product:write"]);
23
+ * expect(error.operationKey).toBe("developer-products.create");
24
+ * ```
25
+ */
26
+ var PermissionError = class extends ApiError {
27
+ name = "PermissionError";
28
+ operationKey;
29
+ requiredScopes;
30
+ /**
31
+ * Creates a new PermissionError.
32
+ *
33
+ * @param message - Human-readable error description.
34
+ * @param options - Error options including status code, the operation key,
35
+ * and the scopes the caller's credential must carry.
36
+ */
37
+ constructor(message, options) {
38
+ super(message, options);
39
+ this.operationKey = options.operationKey;
40
+ this.requiredScopes = options.requiredScopes;
41
+ }
42
+ };
43
+ //#endregion
44
+ //#region src/internal/utils/find-error-code.ts
45
+ /**
46
+ * Maximum cause-chain depth walked by {@link findErrorCode}. Caps pathological
47
+ * self-referential or deeply nested chains; transport failures surface as
48
+ * `NetworkError → TypeError("fetch failed") → OS Error{code}`, so three
49
+ * levels is the expected shape and five leaves headroom.
50
+ */
51
+ const MAX_DEPTH = 5;
52
+ /**
53
+ * Walks an error's `cause` chain and returns the first node-style string
54
+ * `code` it finds (for example `"ECONNRESET"`, `"ETIMEDOUT"`). Native `fetch`
55
+ * surfaces a transport reset as a `NetworkError` wrapping a
56
+ * `TypeError("fetch failed")` whose own cause carries the OS-level `code`, so
57
+ * the code lives several links down the chain.
58
+ *
59
+ * @example
60
+ *
61
+ * ```ts
62
+ * import { findErrorCode } from "./find-error-code";
63
+ *
64
+ * const root = Object.assign(new Error("read ECONNRESET"), { code: "ECONNRESET" });
65
+ * const outer = new Error("Network request failed", {
66
+ * cause: new TypeError("fetch failed", { cause: root }),
67
+ * });
68
+ *
69
+ * expect(findErrorCode(outer)).toBe("ECONNRESET");
70
+ * ```
71
+ *
72
+ * @param error - The error to inspect; typically a `NetworkError`.
73
+ * @returns The first string `code` in the chain, or `undefined` if none.
74
+ */
75
+ function findErrorCode(error) {
76
+ let current = error;
77
+ for (let depth = 0; depth < MAX_DEPTH && current instanceof Error; depth += 1) {
78
+ const code = readCode(current);
79
+ if (code !== void 0) return code;
80
+ current = current.cause;
81
+ }
82
+ }
83
+ function readCode(error) {
84
+ const code = Reflect.get(error, "code");
85
+ return typeof code === "string" ? code : void 0;
86
+ }
87
+ //#endregion
88
+ //#region src/internal/http/retry.ts
89
+ /**
90
+ * Transient transport error codes that are safe to retry for idempotent
91
+ * operations. Connection resets, timeouts, and DNS hiccups are recoverable on
92
+ * a retry; a self-aborted request timeout carries no `code` and so is excluded
93
+ * by construction.
94
+ */
95
+ const TRANSIENT_TRANSPORT_CODES = Object.freeze([
96
+ "ECONNRESET",
97
+ "ECONNREFUSED",
98
+ "ETIMEDOUT",
99
+ "EPIPE",
100
+ "ENETUNREACH",
101
+ "EHOSTDOWN",
102
+ "EAI_AGAIN",
103
+ "UND_ERR_SOCKET"
104
+ ]);
105
+ /**
106
+ * Default retry policy for idempotent operations (read, list, update,
107
+ * delete). Safe to retry on rate limits, transient server errors, and
108
+ * transient transport failures.
109
+ */
110
+ const IDEMPOTENT_METHOD_DEFAULTS = Object.freeze({
111
+ retryableStatuses: Object.freeze([
112
+ 429,
113
+ 500,
114
+ 502,
115
+ 503,
116
+ 504
117
+ ]),
118
+ retryableTransportCodes: TRANSIENT_TRANSPORT_CODES
119
+ });
120
+ /**
121
+ * Default retry policy for create operations. Retries rate limits only (no
122
+ * 5xx and no transport-error retries) to prevent duplicate resources, since
123
+ * Roblox Open Cloud has no idempotency-key support. Consumers who can tolerate
124
+ * a duplicate opt in per request.
125
+ */
126
+ const CREATE_METHOD_DEFAULTS = Object.freeze({
127
+ retryableStatuses: Object.freeze([429]),
128
+ retryableTransportCodes: Object.freeze([])
129
+ });
130
+ /**
131
+ * Default exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s (capped).
132
+ *
133
+ * @example
134
+ *
135
+ * ```ts
136
+ * import { defaultRetryDelay } from "./retry";
137
+ *
138
+ * expect(defaultRetryDelay(0)).toBe(1000);
139
+ * expect(defaultRetryDelay(4)).toBe(16_000);
140
+ * expect(defaultRetryDelay(10)).toBe(30_000);
141
+ * ```
142
+ *
143
+ * @param attempt - Zero-indexed retry attempt number.
144
+ * @returns Wait duration in milliseconds.
145
+ */
146
+ function defaultRetryDelay(attempt) {
147
+ return Math.min(1e3 * 2 ** attempt, 3e4);
148
+ }
149
+ /**
150
+ * Computes how long to wait before the next retry. Prefers the server's
151
+ * suggested delay when the error is a {@link RateLimitError} with a positive
152
+ * `retryAfterSeconds`; otherwise falls through to `retryDelay(attempt)`.
153
+ *
154
+ * @example
155
+ *
156
+ * ```ts
157
+ * import { RateLimitError } from "../../errors/rate-limit.ts";
158
+ * import { computeRetryWaitMs, defaultRetryDelay } from "./retry";
159
+ *
160
+ * const error = new RateLimitError("slow down", { retryAfterSeconds: 3 });
161
+ *
162
+ * expect(computeRetryWaitMs(error, { attempt: 0, retryDelay: defaultRetryDelay })).toBe(
163
+ * 3000,
164
+ * );
165
+ * ```
166
+ *
167
+ * @example
168
+ *
169
+ * ```ts
170
+ * import { ApiError } from "../../errors/api-error.ts";
171
+ * import { computeRetryWaitMs, defaultRetryDelay } from "./retry";
172
+ *
173
+ * const error = new ApiError("server error", { statusCode: 503 });
174
+ *
175
+ * expect(computeRetryWaitMs(error, { attempt: 2, retryDelay: defaultRetryDelay })).toBe(
176
+ * 4000,
177
+ * );
178
+ * ```
179
+ *
180
+ * @param error - The error returned by the failing request.
181
+ * @param options - Retry attempt index and fallback delay function.
182
+ * @returns Wait duration in milliseconds before the next attempt.
183
+ */
184
+ function computeRetryWaitMs(error, options) {
185
+ if (error instanceof RateLimitError && error.retryAfterSeconds > 0) return error.retryAfterSeconds * 1e3;
186
+ return options.retryDelay(options.attempt);
187
+ }
188
+ /**
189
+ * Decides whether a failed request is eligible for retry. {@link RateLimitError}
190
+ * (checked against 429) and {@link ApiError} (checked against its `statusCode`)
191
+ * are retryable when their status is in `retryableStatuses`. A
192
+ * {@link NetworkError} is retryable when its transport code
193
+ * ({@link findErrorCode}) is in `retryableTransportCodes`. This is how
194
+ * transient connection resets recover. All other failures return `false`.
195
+ *
196
+ * @example
197
+ *
198
+ * ```ts
199
+ * import { RateLimitError } from "../../errors/rate-limit.ts";
200
+ * import { shouldRetry } from "./retry";
201
+ *
202
+ * const error = new RateLimitError("", { retryAfterSeconds: 1 });
203
+ *
204
+ * expect(shouldRetry(error, { retryableStatuses: [429], retryableTransportCodes: [] })).toBe(
205
+ * true,
206
+ * );
207
+ * ```
208
+ *
209
+ * @example
210
+ *
211
+ * ```ts
212
+ * import { NetworkError } from "../../errors/network-error.ts";
213
+ * import { shouldRetry } from "./retry";
214
+ *
215
+ * const reset = Object.assign(new Error("read ECONNRESET"), { code: "ECONNRESET" });
216
+ * const error = new NetworkError("Network request failed", { cause: reset });
217
+ *
218
+ * expect(
219
+ * shouldRetry(error, { retryableStatuses: [], retryableTransportCodes: ["ECONNRESET"] }),
220
+ * ).toBe(true);
221
+ * ```
222
+ *
223
+ * @param error - The error returned by the failing request.
224
+ * @param config - Object carrying the retry-eligible status and transport-code lists.
225
+ * @returns `true` if the error should be retried, `false` otherwise.
226
+ */
227
+ function shouldRetry(error, config) {
228
+ if (error instanceof RateLimitError) return config.retryableStatuses.includes(429);
229
+ if (error instanceof ApiError) return config.retryableStatuses.includes(error.statusCode);
230
+ if (error instanceof NetworkError) {
231
+ const code = findErrorCode(error);
232
+ return code !== void 0 && config.retryableTransportCodes.includes(code);
233
+ }
234
+ return false;
235
+ }
236
+ /**
237
+ * Resolves the effective config for a single request by shallow-merging the
238
+ * client config, method defaults, and per-request options. Precedence depends
239
+ * on `methodKind`:
240
+ *
241
+ * - `"create"`: method defaults override client config, so client-level
242
+ * settings cannot silently relax create-method safety. Only explicit
243
+ * per-request `requestOptions` can.
244
+ * - `"idempotent"`: client config overrides method defaults, so consumers
245
+ * can loosen or tighten retry policy globally. `requestOptions` still wins
246
+ * when provided.
247
+ *
248
+ * Array-valued fields like `retryableStatuses` are *replaced*, not extended.
249
+ *
250
+ * @template T - Concrete `RetryResolvable` subtype being merged.
251
+ *
252
+ * @example
253
+ *
254
+ * ```ts
255
+ * import {
256
+ * CREATE_METHOD_DEFAULTS,
257
+ * defaultRetryDelay,
258
+ * mergeConfig,
259
+ * type RetryResolvable,
260
+ * } from "./retry";
261
+ *
262
+ * const clientConfig: RetryResolvable = {
263
+ * apiKey: "k",
264
+ * baseUrl: "https://apis.roblox.com",
265
+ * maxRetries: 3,
266
+ * retryableStatuses: [429, 500],
267
+ * retryableTransportCodes: [],
268
+ * retryDelay: defaultRetryDelay,
269
+ * timeout: 30_000,
270
+ * };
271
+ *
272
+ * const merged = mergeConfig(clientConfig, {
273
+ * methodDefaults: CREATE_METHOD_DEFAULTS,
274
+ * methodKind: "create",
275
+ * });
276
+ *
277
+ * expect(merged.retryableStatuses).toStrictEqual([429]);
278
+ * ```
279
+ *
280
+ * @example
281
+ *
282
+ * ```ts
283
+ * import {
284
+ * defaultRetryDelay,
285
+ * IDEMPOTENT_METHOD_DEFAULTS,
286
+ * mergeConfig,
287
+ * type RetryResolvable,
288
+ * } from "./retry";
289
+ *
290
+ * const clientConfig: RetryResolvable = {
291
+ * apiKey: "k",
292
+ * baseUrl: "https://apis.roblox.com",
293
+ * maxRetries: 3,
294
+ * retryableStatuses: [429],
295
+ * retryableTransportCodes: [],
296
+ * retryDelay: defaultRetryDelay,
297
+ * timeout: 30_000,
298
+ * };
299
+ *
300
+ * const merged = mergeConfig(clientConfig, {
301
+ * methodDefaults: IDEMPOTENT_METHOD_DEFAULTS,
302
+ * methodKind: "idempotent",
303
+ * requestOptions: { timeout: 10_000 },
304
+ * });
305
+ *
306
+ * expect(merged.retryableStatuses).toStrictEqual([429]);
307
+ * expect(merged.timeout).toBe(10_000);
308
+ * ```
309
+ *
310
+ * @param clientConfig - Config frozen at client construction.
311
+ * @param options - Method defaults, method kind, and optional per-request overrides.
312
+ * @returns A new merged config object. Inputs are not mutated.
313
+ */
314
+ function mergeConfig(clientConfig, options) {
315
+ const { methodDefaults, methodKind, requestOptions } = options;
316
+ switch (methodKind) {
317
+ case "create": return {
318
+ ...clientConfig,
319
+ ...methodDefaults,
320
+ ...requestOptions
321
+ };
322
+ case "idempotent": return {
323
+ ...methodDefaults,
324
+ ...clientConfig,
325
+ ...requestOptions
326
+ };
327
+ default: throw new Error(`Unexpected methodKind: ${String(methodKind)}`);
328
+ }
329
+ }
330
+ //#endregion
331
+ export { defaultRetryDelay as a, findErrorCode as c, computeRetryWaitMs as i, PermissionError as l, IDEMPOTENT_METHOD_DEFAULTS as n, mergeConfig as o, TRANSIENT_TRANSPORT_CODES as r, shouldRetry as s, CREATE_METHOD_DEFAULTS as t };
332
+
333
+ //# sourceMappingURL=retry-BzX29aw_.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-BzX29aw_.mjs","names":[],"sources":["../src/errors/permission-error.ts","../src/internal/utils/find-error-code.ts","../src/internal/http/retry.ts"],"sourcesContent":["import { ApiError, type ApiErrorOptions } from \"./api-error.ts\";\n\n/**\n * Options for constructing a {@link PermissionError}.\n */\nexport interface PermissionErrorOptions extends ApiErrorOptions {\n\t/**\n\t * Stable identifier of the Open Cloud operation that returned the\n\t * permission failure (matches `OperationLimit.operationKey`, e.g.\n\t * `\"developer-products.create\"`).\n\t */\n\toperationKey: string;\n\t/**\n\t * Scope strings the API key or OAuth token must carry for the failing\n\t * operation, sourced from the vendored OpenAPI schema's `x-roblox-scopes`\n\t * for that operationId.\n\t */\n\trequiredScopes: ReadonlyArray<string>;\n}\n\n/**\n * Thrown when the Roblox Open Cloud API returns a 401 or 403 for an operation\n * whose required scopes are known. Subclass of {@link ApiError} carrying the\n * scope strings the caller's credential is missing plus the operation key, so\n * a CLI consumer can tell the user exactly which scope to grant on their API\n * key.\n *\n * @example\n *\n * ```ts\n * import { PermissionError } from \"@bedrock-rbx/ocale\";\n *\n * const error = new PermissionError(\"HTTP 403\", {\n * operationKey: \"developer-products.create\",\n * requiredScopes: [\"creator-store-product:write\"],\n * statusCode: 403,\n * });\n *\n * expect(error).toBeInstanceOf(PermissionError);\n * expect(error.requiredScopes).toStrictEqual([\"creator-store-product:write\"]);\n * expect(error.operationKey).toBe(\"developer-products.create\");\n * ```\n */\nexport class PermissionError extends ApiError {\n\tpublic override readonly name: string = \"PermissionError\";\n\tpublic readonly operationKey: string;\n\tpublic readonly requiredScopes: ReadonlyArray<string>;\n\n\t/**\n\t * Creates a new PermissionError.\n\t *\n\t * @param message - Human-readable error description.\n\t * @param options - Error options including status code, the operation key,\n\t * and the scopes the caller's credential must carry.\n\t */\n\tconstructor(message: string, options: PermissionErrorOptions) {\n\t\tsuper(message, options);\n\t\tthis.operationKey = options.operationKey;\n\t\tthis.requiredScopes = options.requiredScopes;\n\t}\n}\n","/**\n * Maximum cause-chain depth walked by {@link findErrorCode}. Caps pathological\n * self-referential or deeply nested chains; transport failures surface as\n * `NetworkError → TypeError(\"fetch failed\") → OS Error{code}`, so three\n * levels is the expected shape and five leaves headroom.\n */\nconst MAX_DEPTH = 5;\n\n/**\n * Walks an error's `cause` chain and returns the first node-style string\n * `code` it finds (for example `\"ECONNRESET\"`, `\"ETIMEDOUT\"`). Native `fetch`\n * surfaces a transport reset as a `NetworkError` wrapping a\n * `TypeError(\"fetch failed\")` whose own cause carries the OS-level `code`, so\n * the code lives several links down the chain.\n *\n * @example\n *\n * ```ts\n * import { findErrorCode } from \"./find-error-code\";\n *\n * const root = Object.assign(new Error(\"read ECONNRESET\"), { code: \"ECONNRESET\" });\n * const outer = new Error(\"Network request failed\", {\n * cause: new TypeError(\"fetch failed\", { cause: root }),\n * });\n *\n * expect(findErrorCode(outer)).toBe(\"ECONNRESET\");\n * ```\n *\n * @param error - The error to inspect; typically a `NetworkError`.\n * @returns The first string `code` in the chain, or `undefined` if none.\n */\nexport function findErrorCode(error: unknown): string | undefined {\n\tlet current: unknown = error;\n\tfor (let depth = 0; depth < MAX_DEPTH && current instanceof Error; depth += 1) {\n\t\tconst code = readCode(current);\n\t\tif (code !== undefined) {\n\t\t\treturn code;\n\t\t}\n\n\t\tcurrent = current.cause;\n\t}\n\n\treturn undefined;\n}\n\nfunction readCode(error: Error): string | undefined {\n\tconst code = Reflect.get(error, \"code\");\n\treturn typeof code === \"string\" ? code : undefined;\n}\n","import { ApiError } from \"../../errors/api-error.ts\";\nimport { NetworkError } from \"../../errors/network-error.ts\";\nimport { RateLimitError } from \"../../errors/rate-limit.ts\";\nimport { findErrorCode } from \"../utils/find-error-code.ts\";\n\n/**\n * Fully-resolved retry config shape that {@link mergeConfig} and\n * {@link shouldRetry} operate on. Fields are required because this represents\n * the post-defaulting, internal view; callers should supply every field (or\n * resolve them via a test factory / client constructor). The partial,\n * user-facing type lives on client construction options; method defaults and\n * per-request overrides use `Partial<RetryResolvable>`.\n */\nexport interface RetryResolvable {\n\t/** Roblox Open Cloud API key. */\n\treadonly apiKey: string;\n\t/** Base URL for the Open Cloud API. */\n\treadonly baseUrl: string;\n\t/** Maximum retry attempts before giving up. */\n\treadonly maxRetries: number;\n\t/** Status codes that are eligible for retry. */\n\treadonly retryableStatuses: ReadonlyArray<number>;\n\t/**\n\t * Node-style transport error codes ({@link findErrorCode}) eligible for\n\t * retry when surfaced as a {@link NetworkError}. Empty for create\n\t * operations by default; consumers opt a create in via a per-request\n\t * override.\n\t */\n\treadonly retryableTransportCodes: ReadonlyArray<string>;\n\t/** Fallback delay function when no server hint is available. */\n\treadonly retryDelay: (attempt: number) => number;\n\t/** Per-request timeout in milliseconds. */\n\treadonly timeout: number;\n}\n\n/**\n * Transient transport error codes that are safe to retry for idempotent\n * operations. Connection resets, timeouts, and DNS hiccups are recoverable on\n * a retry; a self-aborted request timeout carries no `code` and so is excluded\n * by construction.\n */\nexport const TRANSIENT_TRANSPORT_CODES: ReadonlyArray<string> = Object.freeze([\n\t\"ECONNRESET\",\n\t\"ECONNREFUSED\",\n\t\"ETIMEDOUT\",\n\t\"EPIPE\",\n\t\"ENETUNREACH\",\n\t\"EHOSTDOWN\",\n\t\"EAI_AGAIN\",\n\t\"UND_ERR_SOCKET\",\n]);\n\n/** Method-level retry defaults, keyed by {@link MethodKind}. */\ntype MethodDefaults = Readonly<\n\tPick<RetryResolvable, \"retryableStatuses\" | \"retryableTransportCodes\">\n>;\n\n/**\n * Default retry policy for idempotent operations (read, list, update,\n * delete). Safe to retry on rate limits, transient server errors, and\n * transient transport failures.\n */\nexport const IDEMPOTENT_METHOD_DEFAULTS: MethodDefaults = Object.freeze({\n\tretryableStatuses: Object.freeze([429, 500, 502, 503, 504] as const),\n\tretryableTransportCodes: TRANSIENT_TRANSPORT_CODES,\n});\n\n/**\n * Default retry policy for create operations. Retries rate limits only (no\n * 5xx and no transport-error retries) to prevent duplicate resources, since\n * Roblox Open Cloud has no idempotency-key support. Consumers who can tolerate\n * a duplicate opt in per request.\n */\nexport const CREATE_METHOD_DEFAULTS: MethodDefaults = Object.freeze({\n\tretryableStatuses: Object.freeze([429] as const),\n\tretryableTransportCodes: Object.freeze([] as const),\n});\n\n/** Kind of HTTP method the merge is being performed for. */\nexport type MethodKind = \"create\" | \"idempotent\";\n\n/**\n * Options for {@link mergeConfig}.\n *\n * @template T - Concrete `RetryResolvable` subtype being merged.\n */\ninterface MergeConfigOptions<T> {\n\t/** Method-level defaults (e.g. {@link CREATE_METHOD_DEFAULTS}). */\n\treadonly methodDefaults: Partial<T>;\n\t/** Whether the method is a create or idempotent operation. */\n\treadonly methodKind: MethodKind;\n\t/** Optional per-request overrides; always win when provided. */\n\treadonly requestOptions?: Partial<T>;\n}\n\n/**\n * Options for {@link computeRetryWaitMs}.\n */\ninterface ComputeRetryWaitMsOptions {\n\t/** Zero-indexed retry attempt number. */\n\treadonly attempt: number;\n\t/** Fallback delay function when no server hint is available. */\n\treadonly retryDelay: (attempt: number) => number;\n}\n\n/**\n * Default exponential backoff: 1s → 2s → 4s → 8s → 16s → 30s (capped).\n *\n * @example\n *\n * ```ts\n * import { defaultRetryDelay } from \"./retry\";\n *\n * expect(defaultRetryDelay(0)).toBe(1000);\n * expect(defaultRetryDelay(4)).toBe(16_000);\n * expect(defaultRetryDelay(10)).toBe(30_000);\n * ```\n *\n * @param attempt - Zero-indexed retry attempt number.\n * @returns Wait duration in milliseconds.\n */\nexport function defaultRetryDelay(attempt: number): number {\n\treturn Math.min(1000 * 2 ** attempt, 30_000);\n}\n\n/**\n * Computes how long to wait before the next retry. Prefers the server's\n * suggested delay when the error is a {@link RateLimitError} with a positive\n * `retryAfterSeconds`; otherwise falls through to `retryDelay(attempt)`.\n *\n * @example\n *\n * ```ts\n * import { RateLimitError } from \"../../errors/rate-limit.ts\";\n * import { computeRetryWaitMs, defaultRetryDelay } from \"./retry\";\n *\n * const error = new RateLimitError(\"slow down\", { retryAfterSeconds: 3 });\n *\n * expect(computeRetryWaitMs(error, { attempt: 0, retryDelay: defaultRetryDelay })).toBe(\n * 3000,\n * );\n * ```\n *\n * @example\n *\n * ```ts\n * import { ApiError } from \"../../errors/api-error.ts\";\n * import { computeRetryWaitMs, defaultRetryDelay } from \"./retry\";\n *\n * const error = new ApiError(\"server error\", { statusCode: 503 });\n *\n * expect(computeRetryWaitMs(error, { attempt: 2, retryDelay: defaultRetryDelay })).toBe(\n * 4000,\n * );\n * ```\n *\n * @param error - The error returned by the failing request.\n * @param options - Retry attempt index and fallback delay function.\n * @returns Wait duration in milliseconds before the next attempt.\n */\nexport function computeRetryWaitMs(\n\terror: ApiError | NetworkError | RateLimitError,\n\toptions: ComputeRetryWaitMsOptions,\n): number {\n\tif (error instanceof RateLimitError && error.retryAfterSeconds > 0) {\n\t\treturn error.retryAfterSeconds * 1000;\n\t}\n\n\treturn options.retryDelay(options.attempt);\n}\n\n/**\n * Decides whether a failed request is eligible for retry. {@link RateLimitError}\n * (checked against 429) and {@link ApiError} (checked against its `statusCode`)\n * are retryable when their status is in `retryableStatuses`. A\n * {@link NetworkError} is retryable when its transport code\n * ({@link findErrorCode}) is in `retryableTransportCodes`. This is how\n * transient connection resets recover. All other failures return `false`.\n *\n * @example\n *\n * ```ts\n * import { RateLimitError } from \"../../errors/rate-limit.ts\";\n * import { shouldRetry } from \"./retry\";\n *\n * const error = new RateLimitError(\"\", { retryAfterSeconds: 1 });\n *\n * expect(shouldRetry(error, { retryableStatuses: [429], retryableTransportCodes: [] })).toBe(\n * true,\n * );\n * ```\n *\n * @example\n *\n * ```ts\n * import { NetworkError } from \"../../errors/network-error.ts\";\n * import { shouldRetry } from \"./retry\";\n *\n * const reset = Object.assign(new Error(\"read ECONNRESET\"), { code: \"ECONNRESET\" });\n * const error = new NetworkError(\"Network request failed\", { cause: reset });\n *\n * expect(\n * shouldRetry(error, { retryableStatuses: [], retryableTransportCodes: [\"ECONNRESET\"] }),\n * ).toBe(true);\n * ```\n *\n * @param error - The error returned by the failing request.\n * @param config - Object carrying the retry-eligible status and transport-code lists.\n * @returns `true` if the error should be retried, `false` otherwise.\n */\nexport function shouldRetry(\n\terror: unknown,\n\tconfig: {\n\t\treadonly retryableStatuses: ReadonlyArray<number>;\n\t\treadonly retryableTransportCodes: ReadonlyArray<string>;\n\t},\n): error is ApiError | NetworkError | RateLimitError {\n\tif (error instanceof RateLimitError) {\n\t\treturn config.retryableStatuses.includes(429);\n\t}\n\n\tif (error instanceof ApiError) {\n\t\treturn config.retryableStatuses.includes(error.statusCode);\n\t}\n\n\tif (error instanceof NetworkError) {\n\t\tconst code = findErrorCode(error);\n\t\treturn code !== undefined && config.retryableTransportCodes.includes(code);\n\t}\n\n\treturn false;\n}\n\n/**\n * Resolves the effective config for a single request by shallow-merging the\n * client config, method defaults, and per-request options. Precedence depends\n * on `methodKind`:\n *\n * - `\"create\"`: method defaults override client config, so client-level\n * settings cannot silently relax create-method safety. Only explicit\n * per-request `requestOptions` can.\n * - `\"idempotent\"`: client config overrides method defaults, so consumers\n * can loosen or tighten retry policy globally. `requestOptions` still wins\n * when provided.\n *\n * Array-valued fields like `retryableStatuses` are *replaced*, not extended.\n *\n * @template T - Concrete `RetryResolvable` subtype being merged.\n *\n * @example\n *\n * ```ts\n * import {\n * CREATE_METHOD_DEFAULTS,\n * defaultRetryDelay,\n * mergeConfig,\n * type RetryResolvable,\n * } from \"./retry\";\n *\n * const clientConfig: RetryResolvable = {\n * apiKey: \"k\",\n * baseUrl: \"https://apis.roblox.com\",\n * maxRetries: 3,\n * retryableStatuses: [429, 500],\n * retryableTransportCodes: [],\n * retryDelay: defaultRetryDelay,\n * timeout: 30_000,\n * };\n *\n * const merged = mergeConfig(clientConfig, {\n * methodDefaults: CREATE_METHOD_DEFAULTS,\n * methodKind: \"create\",\n * });\n *\n * expect(merged.retryableStatuses).toStrictEqual([429]);\n * ```\n *\n * @example\n *\n * ```ts\n * import {\n * defaultRetryDelay,\n * IDEMPOTENT_METHOD_DEFAULTS,\n * mergeConfig,\n * type RetryResolvable,\n * } from \"./retry\";\n *\n * const clientConfig: RetryResolvable = {\n * apiKey: \"k\",\n * baseUrl: \"https://apis.roblox.com\",\n * maxRetries: 3,\n * retryableStatuses: [429],\n * retryableTransportCodes: [],\n * retryDelay: defaultRetryDelay,\n * timeout: 30_000,\n * };\n *\n * const merged = mergeConfig(clientConfig, {\n * methodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n * methodKind: \"idempotent\",\n * requestOptions: { timeout: 10_000 },\n * });\n *\n * expect(merged.retryableStatuses).toStrictEqual([429]);\n * expect(merged.timeout).toBe(10_000);\n * ```\n *\n * @param clientConfig - Config frozen at client construction.\n * @param options - Method defaults, method kind, and optional per-request overrides.\n * @returns A new merged config object. Inputs are not mutated.\n */\nexport function mergeConfig<T extends RetryResolvable>(\n\tclientConfig: T,\n\toptions: MergeConfigOptions<T>,\n): T {\n\tconst { methodDefaults, methodKind, requestOptions } = options;\n\n\tswitch (methodKind) {\n\t\tcase \"create\": {\n\t\t\treturn { ...clientConfig, ...methodDefaults, ...requestOptions };\n\t\t}\n\t\tcase \"idempotent\": {\n\t\t\treturn { ...methodDefaults, ...clientConfig, ...requestOptions };\n\t\t}\n\t\tdefault: {\n\t\t\tconst exhaustive: never = methodKind;\n\t\t\tthrow new Error(`Unexpected methodKind: ${String(exhaustive)}`);\n\t\t}\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AA2CA,IAAa,kBAAb,cAAqC,SAAS;CAC7C,OAAwC;CACxC;CACA;;;;;;;;CASA,YAAY,SAAiB,SAAiC;AAC7D,QAAM,SAAS,QAAQ;AACvB,OAAK,eAAe,QAAQ;AAC5B,OAAK,iBAAiB,QAAQ;;;;;;;;;;;ACpDhC,MAAM,YAAY;;;;;;;;;;;;;;;;;;;;;;;;AAyBlB,SAAgB,cAAc,OAAoC;CACjE,IAAI,UAAmB;AACvB,MAAK,IAAI,QAAQ,GAAG,QAAQ,aAAa,mBAAmB,OAAO,SAAS,GAAG;EAC9E,MAAM,OAAO,SAAS,QAAQ;AAC9B,MAAI,SAAS,KAAA,EACZ,QAAO;AAGR,YAAU,QAAQ;;;AAMpB,SAAS,SAAS,OAAkC;CACnD,MAAM,OAAO,QAAQ,IAAI,OAAO,OAAO;AACvC,QAAO,OAAO,SAAS,WAAW,OAAO,KAAA;;;;;;;;;;ACN1C,MAAa,4BAAmD,OAAO,OAAO;CAC7E;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;;;;;;AAYF,MAAa,6BAA6C,OAAO,OAAO;CACvE,mBAAmB,OAAO,OAAO;EAAC;EAAK;EAAK;EAAK;EAAK;EAAI,CAAU;CACpE,yBAAyB;CACzB,CAAC;;;;;;;AAQF,MAAa,yBAAyC,OAAO,OAAO;CACnE,mBAAmB,OAAO,OAAO,CAAC,IAAI,CAAU;CAChD,yBAAyB,OAAO,OAAO,EAAE,CAAU;CACnD,CAAC;;;;;;;;;;;;;;;;;AA6CF,SAAgB,kBAAkB,SAAyB;AAC1D,QAAO,KAAK,IAAI,MAAO,KAAK,SAAS,IAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsC7C,SAAgB,mBACf,OACA,SACS;AACT,KAAI,iBAAiB,kBAAkB,MAAM,oBAAoB,EAChE,QAAO,MAAM,oBAAoB;AAGlC,QAAO,QAAQ,WAAW,QAAQ,QAAQ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0C3C,SAAgB,YACf,OACA,QAIoD;AACpD,KAAI,iBAAiB,eACpB,QAAO,OAAO,kBAAkB,SAAS,IAAI;AAG9C,KAAI,iBAAiB,SACpB,QAAO,OAAO,kBAAkB,SAAS,MAAM,WAAW;AAG3D,KAAI,iBAAiB,cAAc;EAClC,MAAM,OAAO,cAAc,MAAM;AACjC,SAAO,SAAS,KAAA,KAAa,OAAO,wBAAwB,SAAS,KAAK;;AAG3E,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiFR,SAAgB,YACf,cACA,SACI;CACJ,MAAM,EAAE,gBAAgB,YAAY,mBAAmB;AAEvD,SAAQ,YAAR;EACC,KAAK,SACJ,QAAO;GAAE,GAAG;GAAc,GAAG;GAAgB,GAAG;GAAgB;EAEjE,KAAK,aACJ,QAAO;GAAE,GAAG;GAAgB,GAAG;GAAc,GAAG;GAAgB;EAEjE,QAEC,OAAM,IAAI,MAAM,0BAA0B,OADhB,WACkC,GAAG"}
@@ -0,0 +1,163 @@
1
+ import { d as OpenCloudError } from "./types-rzs1NB-j.mjs";
2
+
3
+ //#region src/errors/api-error.d.ts
4
+ /**
5
+ * Options for constructing an {@link ApiError}.
6
+ */
7
+ interface ApiErrorOptions extends ErrorOptions {
8
+ /** Optional machine-readable error code from the API. */
9
+ code?: string | undefined;
10
+ /** Parsed response body, when present. */
11
+ details?: JSONValue | undefined;
12
+ /** HTTP status code from the API response. */
13
+ statusCode: number;
14
+ }
15
+ /**
16
+ * Thrown when the Roblox Open Cloud API returns a non-2xx response
17
+ * that is not a rate limit (429).
18
+ *
19
+ * @example
20
+ *
21
+ * ```ts
22
+ * import { ApiError } from "@bedrock-rbx/ocale";
23
+ *
24
+ * const error = new ApiError("HTTP 404: Pass not found (code NotFound)", {
25
+ * code: "NotFound",
26
+ * details: { errorCode: "NotFound", message: "Pass not found" },
27
+ * statusCode: 404,
28
+ * });
29
+ *
30
+ * expect(error).toBeInstanceOf(ApiError);
31
+ * expect(error.statusCode).toBe(404);
32
+ * expect(error.code).toBe("NotFound");
33
+ * expect(error.details).toEqual({
34
+ * errorCode: "NotFound",
35
+ * message: "Pass not found",
36
+ * });
37
+ * ```
38
+ */
39
+ declare class ApiError extends OpenCloudError {
40
+ readonly code: string | undefined;
41
+ readonly details: JSONValue | undefined;
42
+ override readonly name: string;
43
+ readonly statusCode: number;
44
+ /**
45
+ * Creates a new ApiError.
46
+ *
47
+ * @param message - Human-readable error description.
48
+ * @param options - Error options including status code, optional error
49
+ * code, and the parsed response body when present.
50
+ */
51
+ constructor(message: string, options: ApiErrorOptions);
52
+ }
53
+ //#endregion
54
+ //#region src/errors/network-error.d.ts
55
+ /**
56
+ * Options for constructing a {@link NetworkError}.
57
+ */
58
+ interface NetworkErrorOptions extends ErrorOptions {
59
+ /** HTTP method of the request that failed. */
60
+ method?: string | undefined;
61
+ /** Fully-qualified URL of the request that failed. */
62
+ url?: string | undefined;
63
+ }
64
+ /**
65
+ * Thrown when a network-level failure prevents the request from reaching
66
+ * the Roblox Open Cloud API (e.g., DNS resolution failure, connection reset).
67
+ * The `method` and `url` name the failing call so a transport failure that
68
+ * survives every retry can be diagnosed; the underlying transport error is
69
+ * carried on `cause`.
70
+ */
71
+ declare class NetworkError extends OpenCloudError {
72
+ readonly method: string | undefined;
73
+ override readonly name: string;
74
+ readonly url: string | undefined;
75
+ /**
76
+ * Creates a new NetworkError.
77
+ *
78
+ * @param message - Human-readable error description.
79
+ * @param options - Error options including the optional `cause` and the
80
+ * `method` / `url` of the request that failed.
81
+ */
82
+ constructor(message: string, options?: NetworkErrorOptions);
83
+ }
84
+ //#endregion
85
+ //#region src/errors/rate-limit.d.ts
86
+ /**
87
+ * Options for constructing a {@link RateLimitError}.
88
+ */
89
+ interface RateLimitErrorOptions extends ErrorOptions {
90
+ /** Seconds to wait before retrying the request. */
91
+ retryAfterSeconds: number;
92
+ }
93
+ /**
94
+ * Thrown when the Roblox Open Cloud API returns a 429 Too Many Requests response.
95
+ * Contains the server-suggested retry delay.
96
+ *
97
+ * @example
98
+ *
99
+ * ```ts
100
+ * import { RateLimitError } from "@bedrock-rbx/ocale";
101
+ *
102
+ * const error = new RateLimitError("Too many requests", {
103
+ * retryAfterSeconds: 30,
104
+ * });
105
+ *
106
+ * expect(error).toBeInstanceOf(RateLimitError);
107
+ * expect(error.retryAfterSeconds).toBe(30);
108
+ * ```
109
+ */
110
+ declare class RateLimitError extends OpenCloudError {
111
+ override readonly name = "RateLimitError";
112
+ readonly retryAfterSeconds: number;
113
+ /**
114
+ * Creates a new RateLimitError.
115
+ *
116
+ * @param message - Human-readable error description.
117
+ * @param options - Error options including the retry delay.
118
+ */
119
+ constructor(message: string, options: RateLimitErrorOptions);
120
+ }
121
+ //#endregion
122
+ //#region src/internal/http/retry.d.ts
123
+ /**
124
+ * Fully-resolved retry config shape that {@link mergeConfig} and
125
+ * {@link shouldRetry} operate on. Fields are required because this represents
126
+ * the post-defaulting, internal view; callers should supply every field (or
127
+ * resolve them via a test factory / client constructor). The partial,
128
+ * user-facing type lives on client construction options; method defaults and
129
+ * per-request overrides use `Partial<RetryResolvable>`.
130
+ */
131
+ interface RetryResolvable {
132
+ /** Roblox Open Cloud API key. */
133
+ readonly apiKey: string;
134
+ /** Base URL for the Open Cloud API. */
135
+ readonly baseUrl: string;
136
+ /** Maximum retry attempts before giving up. */
137
+ readonly maxRetries: number;
138
+ /** Status codes that are eligible for retry. */
139
+ readonly retryableStatuses: ReadonlyArray<number>;
140
+ /**
141
+ * Node-style transport error codes ({@link findErrorCode}) eligible for
142
+ * retry when surfaced as a {@link NetworkError}. Empty for create
143
+ * operations by default; consumers opt a create in via a per-request
144
+ * override.
145
+ */
146
+ readonly retryableTransportCodes: ReadonlyArray<string>;
147
+ /** Fallback delay function when no server hint is available. */
148
+ readonly retryDelay: (attempt: number) => number;
149
+ /** Per-request timeout in milliseconds. */
150
+ readonly timeout: number;
151
+ }
152
+ /**
153
+ * Transient transport error codes that are safe to retry for idempotent
154
+ * operations. Connection resets, timeouts, and DNS hiccups are recoverable on
155
+ * a retry; a self-aborted request timeout carries no `code` and so is excluded
156
+ * by construction.
157
+ */
158
+ declare const TRANSIENT_TRANSPORT_CODES: ReadonlyArray<string>;
159
+ /** Kind of HTTP method the merge is being performed for. */
160
+ type MethodKind = "create" | "idempotent";
161
+ //#endregion
162
+ export { RateLimitErrorOptions as a, ApiError as c, RateLimitError as i, ApiErrorOptions as l, RetryResolvable as n, NetworkError as o, TRANSIENT_TRANSPORT_CODES as r, NetworkErrorOptions as s, MethodKind as t };
163
+ //# sourceMappingURL=retry-CXnj3gXI.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retry-CXnj3gXI.d.mts","names":[],"sources":["../src/errors/api-error.ts","../src/errors/network-error.ts","../src/errors/rate-limit.ts","../src/internal/http/retry.ts"],"mappings":";;;;;AAKA;UAAiB,eAAA,SAAwB,YAAA;;EAExC,IAAA;;EAEA,OAAA,GAAU,SAAA;;EAEV,UAAA;AAAA;;;AA2BD;;;;;;;;;;;;;;;;;;;;;;cAAa,QAAA,SAAiB,cAAA;EAAA,SACb,IAAA;EAAA,SACA,OAAA,EAAS,SAAA;EAAA,kBACA,IAAA;EAAA,SACT,UAAA;;;;;;ACvBjB;;EDgCC,WAAA,CAAY,OAAA,UAAiB,OAAA,EAAS,eAAA;AAAA;;;;;AA9CvC;UCAiB,mBAAA,SAA4B,YAAA;;EAE5C,MAAA;;EAEA,GAAA;AAAA;;;;;AD6BD;;;cCnBa,YAAA,SAAqB,cAAA;EAAA,SACjB,MAAA;EAAA,kBACS,IAAA;EAAA,SACT,GAAA;EDgBa;;;;;;;ECP7B,WAAA,CAAY,OAAA,UAAiB,OAAA,GAAU,mBAAA;AAAA;;;;;AD1BxC;UEAiB,qBAAA,SAA8B,YAAA;;EAE9C,iBAAA;AAAA;;;;;;;AF+BD;;;;;;;;;;;cEXa,cAAA,SAAuB,cAAA;EAAA,kBACV,IAAA;EAAA,SACT,iBAAA;;;;;;;EAQhB,WAAA,CAAY,OAAA,UAAiB,OAAA,EAAS,qBAAA;AAAA;;;AFhCvC;;;;;;;;AAAA,UGQiB,eAAA;;WAEP,MAAA;EHuBV;EAAA,SGrBU,OAAA;;WAEA,UAAA;;WAEA,iBAAA,EAAmB,aAAA;;;;;;;WAOnB,uBAAA,EAAyB,aAAA;;WAEzB,UAAA,GAAa,OAAA;;WAEb,OAAA;AAAA;;;;;;AF3BV;cEoCa,yBAAA,EAA2B,aAAA;;KAsC5B,UAAA"}
@@ -1,4 +1,5 @@
1
- import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, n as HttpRequest, r as HttpResponse, s as RequestOptions, u as SleepFunc } from "./types-CwtZT1ek.mjs";
1
+ import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, n as HttpRequest, r as HttpResponse, s as RequestOptions, u as SleepFunc } from "./types-rzs1NB-j.mjs";
2
+ import { n as RetryResolvable, t as MethodKind } from "./retry-CXnj3gXI.mjs";
2
3
 
3
4
  //#region src/domains/cloud-v2/memory-store-queues/types.d.ts
4
5
  /**
@@ -308,32 +309,6 @@ interface OperationLimit {
308
309
  readonly operationKey: string;
309
310
  }
310
311
  //#endregion
311
- //#region src/internal/http/retry.d.ts
312
- /**
313
- * Fully-resolved retry config shape that {@link mergeConfig} and
314
- * {@link shouldRetry} operate on. Fields are required because this represents
315
- * the post-defaulting, internal view — callers should supply every field (or
316
- * resolve them via a test factory / client constructor). The partial,
317
- * user-facing type lives on client construction options; method defaults and
318
- * per-request overrides use `Partial<RetryResolvable>`.
319
- */
320
- interface RetryResolvable {
321
- /** Roblox Open Cloud API key. */
322
- readonly apiKey: string;
323
- /** Base URL for the Open Cloud API. */
324
- readonly baseUrl: string;
325
- /** Maximum retry attempts before giving up. */
326
- readonly maxRetries: number;
327
- /** Status codes that are eligible for retry. */
328
- readonly retryableStatuses: ReadonlyArray<number>;
329
- /** Fallback delay function when no server hint is available. */
330
- readonly retryDelay: (attempt: number) => number;
331
- /** Per-request timeout in milliseconds. */
332
- readonly timeout: number;
333
- }
334
- /** Kind of HTTP method the merge is being performed for. */
335
- type MethodKind = "create" | "idempotent";
336
- //#endregion
337
312
  //#region src/internal/resource-client.d.ts
338
313
  /**
339
314
  * Describes a single resource method's shape for dispatch through
@@ -1 +1 @@
1
- {"version":3,"file":"storage.d.mts","names":[],"sources":["../src/domains/cloud-v2/memory-store-queues/types.ts","../src/domains/cloud-v2/memory-store-sorted-maps/types.ts","../src/internal/http/rate-limit-queue.ts","../src/internal/http/retry.ts","../src/internal/resource-client.ts","../src/resources/storage/queues-group.ts","../src/resources/storage/sorted-maps-group.ts","../src/resources/storage/client.ts"],"mappings":"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"}
1
+ {"version":3,"file":"storage.d.mts","names":[],"sources":["../src/domains/cloud-v2/memory-store-queues/types.ts","../src/domains/cloud-v2/memory-store-sorted-maps/types.ts","../src/internal/http/rate-limit-queue.ts","../src/internal/resource-client.ts","../src/resources/storage/queues-group.ts","../src/resources/storage/sorted-maps-group.ts","../src/resources/storage/client.ts"],"mappings":"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"}
package/dist/storage.mjs CHANGED
@@ -1,5 +1,6 @@
1
- import { r as ApiError } from "./rate-limit-D1q2Js-z.mjs";
2
- import { a as IDEMPOTENT_METHOD_DEFAULTS, c as isDateTimeString, i as CREATE_METHOD_DEFAULTS, n as okRequest, r as parseEmptyResponse, s as isRecord, t as ResourceClient } from "./resource-client-D6Efj9fU.mjs";
1
+ import { r as ApiError } from "./rate-limit-nY4BF079.mjs";
2
+ import { n as IDEMPOTENT_METHOD_DEFAULTS, t as CREATE_METHOD_DEFAULTS } from "./retry-BzX29aw_.mjs";
3
+ import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-CG9-BG81.mjs";
3
4
  //#region src/domains/cloud-v2/memory-store-queues/builders.ts
4
5
  /**
5
6
  * Builds a `POST` request for the Open Cloud