@bedrock-rbx/ocale 0.1.0-beta.6 → 0.1.0-beta.8

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 (49) hide show
  1. package/dist/badges.d.mts +2 -2
  2. package/dist/badges.mjs +1 -2
  3. package/dist/badges.mjs.map +1 -1
  4. package/dist/{data.generated-DdwXMiv9.d.mts → data.generated-Cb6g6asv.d.mts} +1 -1
  5. package/dist/{data.generated-DdwXMiv9.d.mts.map → data.generated-Cb6g6asv.d.mts.map} +1 -1
  6. package/dist/developer-products.d.mts +2 -2
  7. package/dist/developer-products.mjs +2 -3
  8. package/dist/developer-products.mjs.map +1 -1
  9. package/dist/game-passes.d.mts +2 -2
  10. package/dist/game-passes.mjs +2 -3
  11. package/dist/game-passes.mjs.map +1 -1
  12. package/dist/index.d.mts +2 -2
  13. package/dist/locales.d.mts +1 -1
  14. package/dist/luau-execution.d.mts +2 -2
  15. package/dist/luau-execution.mjs +2 -2
  16. package/dist/places.d.mts +2 -2
  17. package/dist/places.mjs +3 -4
  18. package/dist/places.mjs.map +1 -1
  19. package/dist/{polling-DDKKpz6Z.d.mts → polling-BMrYajok.d.mts} +6 -6
  20. package/dist/{polling-DDKKpz6Z.d.mts.map → polling-BMrYajok.d.mts.map} +1 -1
  21. package/dist/{polling-helpers-DJqtcrCQ.mjs → polling-helpers-CS00apdU.mjs} +29 -15
  22. package/dist/polling-helpers-CS00apdU.mjs.map +1 -0
  23. package/dist/{price-information-XyhlYrn8.mjs → price-information-DIrvwCmd.mjs} +2 -2
  24. package/dist/{price-information-XyhlYrn8.mjs.map → price-information-DIrvwCmd.mjs.map} +1 -1
  25. package/dist/{rate-limit-BHAddFXO.d.mts → rate-limit-BYuizHoD.d.mts} +2 -2
  26. package/dist/{rate-limit-BHAddFXO.d.mts.map → rate-limit-BYuizHoD.d.mts.map} +1 -1
  27. package/dist/{resource-client-D7HKNrOp.mjs → resource-client-D6Efj9fU.mjs} +18 -2
  28. package/dist/resource-client-D6Efj9fU.mjs.map +1 -0
  29. package/dist/{signatures-9rpsTjPL.mjs → signatures-B5Fojgn0.mjs} +1 -1
  30. package/dist/{signatures-9rpsTjPL.mjs.map → signatures-B5Fojgn0.mjs.map} +1 -1
  31. package/dist/storage.d.mts +1 -1
  32. package/dist/storage.mjs +1 -2
  33. package/dist/storage.mjs.map +1 -1
  34. package/dist/testing.d.mts +218 -3
  35. package/dist/testing.d.mts.map +1 -1
  36. package/dist/testing.mjs +92 -2
  37. package/dist/testing.mjs.map +1 -1
  38. package/dist/{types-BOhSh9ug.d.mts → types-CwtZT1ek.d.mts} +1 -1
  39. package/dist/{types-BOhSh9ug.d.mts.map → types-CwtZT1ek.d.mts.map} +1 -1
  40. package/dist/universes.d.mts +3 -3
  41. package/dist/universes.mjs +1 -2
  42. package/dist/universes.mjs.map +1 -1
  43. package/dist/{wire-BeIO-d1x.d.mts → wire-CeL6W_V7.d.mts} +1 -1
  44. package/dist/{wire-BeIO-d1x.d.mts.map → wire-CeL6W_V7.d.mts.map} +1 -1
  45. package/package.json +1 -1
  46. package/dist/is-date-time-string-DL6l9mo6.mjs +0 -19
  47. package/dist/is-date-time-string-DL6l9mo6.mjs.map +0 -1
  48. package/dist/polling-helpers-DJqtcrCQ.mjs.map +0 -1
  49. package/dist/resource-client-D7HKNrOp.mjs.map +0 -1
package/dist/testing.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  import { n as NetworkError, r as ApiError, t as RateLimitError } from "./rate-limit-D1q2Js-z.mjs";
2
- import { n as RBXL_SIGNATURE, t as RBXLX_SIGNATURE } from "./signatures-9rpsTjPL.mjs";
2
+ import { n as RBXL_SIGNATURE, t as RBXLX_SIGNATURE } from "./signatures-B5Fojgn0.mjs";
3
3
  //#region tests/helpers/badges.ts
4
4
  /**
5
5
  * Builds a minimally-valid {@link BadgeResponseV2Wire} body. Pass an
@@ -278,6 +278,96 @@ function validThumbnailUploadBody(overrides = {}) {
278
278
  };
279
279
  }
280
280
  //#endregion
281
+ //#region tests/helpers/luau-execution-task-binary-inputs.ts
282
+ /**
283
+ * Builds a minimally-valid {@link LuauExecutionTaskBinaryInputWire} body
284
+ * for tests. Pass an `overrides` object to tweak fields without re-stating
285
+ * the defaults.
286
+ *
287
+ * @param overrides - Fields to override on the default body.
288
+ * @returns A valid wire body with the overrides applied.
289
+ */
290
+ function validBinaryInputBody(overrides = {}) {
291
+ return {
292
+ path: "universes/123/luau-execution-session-task-binary-inputs/abc",
293
+ uploadUri: "https://storage.example.com/upload?token=xyz",
294
+ ...overrides
295
+ };
296
+ }
297
+ //#endregion
298
+ //#region tests/helpers/luau-execution-task-logs.ts
299
+ /**
300
+ * Builds a minimally-valid {@link ListLogsResponseWire} body containing
301
+ * one chunk with one structured message. Pass an `overrides` object to
302
+ * tweak fields without re-stating the defaults.
303
+ *
304
+ * @param overrides - Fields to override on the default body.
305
+ * @returns A valid wire body with the overrides applied.
306
+ */
307
+ function validLogPageBody(overrides = {}) {
308
+ return {
309
+ luauExecutionSessionTaskLogs: [{ structuredMessages: [{
310
+ createTime: "2026-01-01T00:00:00Z",
311
+ message: "Hello from Luau",
312
+ messageType: "OUTPUT"
313
+ }] }],
314
+ ...overrides
315
+ };
316
+ }
317
+ //#endregion
318
+ //#region tests/helpers/luau-execution-tasks.ts
319
+ /**
320
+ * Builds a minimally-valid {@link LuauExecutionTaskWire} body for an
321
+ * in-progress task. Pass an `overrides` object to tweak fields without
322
+ * re-stating the defaults.
323
+ *
324
+ * @param overrides - Fields to override on the default body.
325
+ * @returns A valid wire body with the overrides applied.
326
+ */
327
+ function validInProgressTaskBody(overrides = {}) {
328
+ return {
329
+ createTime: "2026-01-01T00:00:00Z",
330
+ path: "universes/123/places/456/luau-execution-session-tasks/task-1",
331
+ state: "QUEUED",
332
+ updateTime: "2026-01-01T00:00:30Z",
333
+ user: "user-1",
334
+ ...overrides
335
+ };
336
+ }
337
+ //#endregion
338
+ //#region tests/helpers/memory-store-queues.ts
339
+ /**
340
+ * Builds a minimally-valid {@link MemoryStoreQueueItemWire} body. Pass
341
+ * an `overrides` object to tweak fields without re-stating the defaults.
342
+ *
343
+ * @param overrides - Fields to override on the default body.
344
+ * @returns A valid wire body with the overrides applied.
345
+ */
346
+ function validQueueItemBody(overrides = {}) {
347
+ return {
348
+ data: "hello",
349
+ expireTime: "2026-06-21T15:08:58.4806559Z",
350
+ path: "cloud/v2/universes/123/memory-store/queues/test-queue/items/abc123",
351
+ priority: 1,
352
+ ...overrides
353
+ };
354
+ }
355
+ /**
356
+ * Builds a minimally-valid {@link ReadQueueItemsResponseWire} body
357
+ * carrying a single default queue item. Pass an `overrides` object to
358
+ * change the read identifier or supply a different items array.
359
+ *
360
+ * @param overrides - Fields to override on the default body.
361
+ * @returns A valid dequeue response body with the overrides applied.
362
+ */
363
+ function validDequeueBody(overrides = {}) {
364
+ return {
365
+ id: "1a354bd5b8fe457f8e51232f8dbfe6d0",
366
+ queueItems: [validQueueItemBody()],
367
+ ...overrides
368
+ };
369
+ }
370
+ //#endregion
281
371
  //#region tests/helpers/places.ts
282
372
  /**
283
373
  * Returns a fresh, minimal `.rbxl`-formatted body whose magic bytes
@@ -362,6 +452,6 @@ function validUniverseBody(overrides = {}) {
362
452
  };
363
453
  }
364
454
  //#endregion
365
- export { FakeHttpClientError, createFakeHttpClient, createFakeSend, createFakeSleep, rbxlBody, rbxlxBody, validBadgeBody, validDeveloperProductBody, validGamePassBody, validIconListBody, validLocalizedIcon, validPlaceBody, validPublishResponseBody, validThumbnailUploadBody, validUniverseBody };
455
+ export { FakeHttpClientError, createFakeHttpClient, createFakeSend, createFakeSleep, rbxlBody, rbxlxBody, validBadgeBody, validBinaryInputBody, validDequeueBody, validDeveloperProductBody, validGamePassBody, validIconListBody, validInProgressTaskBody, validLocalizedIcon, validLogPageBody, validPlaceBody, validPublishResponseBody, validQueueItemBody, validThumbnailUploadBody, validUniverseBody };
366
456
 
367
457
  //# sourceMappingURL=testing.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"testing.mjs","names":[],"sources":["../tests/helpers/badges.ts","../tests/helpers/developer-products.ts","../tests/helpers/fake-http-client.ts","../tests/helpers/fake-send.ts","../tests/helpers/fake-sleep.ts","../tests/helpers/game-icon.ts","../tests/helpers/game-passes.ts","../tests/helpers/game-thumbnails.ts","../tests/helpers/places.ts","../tests/helpers/universes.ts"],"sourcesContent":["import type { BadgeResponseV2Wire } from \"#src/domains/badges/badges/wire\";\n\n/**\n * Builds a minimally-valid {@link BadgeResponseV2Wire} body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validBadgeBody(overrides: Partial<BadgeResponseV2Wire> = {}): BadgeResponseV2Wire {\n\treturn {\n\t\tid: 12_345,\n\t\tname: \"First Goal\",\n\t\tawarder: { id: 222, name: \"Lobby\", type: 1 },\n\t\tcreated: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"Awarded on first login.\",\n\t\tdisplayDescription: \"Awarded on first login.\",\n\t\tdisplayIconImageId: 67_890,\n\t\tdisplayName: \"First Goal\",\n\t\tenabled: true,\n\t\ticonImageId: 67_890,\n\t\tstatistics: { awardedCount: 100, pastDayAwardedCount: 5, winRatePercentage: 42.5 },\n\t\tupdated: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n","import type { DeveloperProductConfigV2 } from \"#src/domains/developer-products/products/wire\";\n\n/**\n * Builds a minimally-valid {@link DeveloperProductConfigV2} wire body. Pass\n * an `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validDeveloperProductBody(\n\toverrides: Partial<DeveloperProductConfigV2> = {},\n): DeveloperProductConfigV2 {\n\treturn {\n\t\tname: \"Gem Pack\",\n\t\tcreatedTimestamp: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A premium gem pack\",\n\t\ticonImageAssetId: 67_890,\n\t\tisForSale: true,\n\t\tisImmutable: false,\n\t\tpriceInformation: { defaultPriceInRobux: 100, enabledFeatures: [] },\n\t\tproductId: 12_345,\n\t\tstorePageEnabled: true,\n\t\tuniverseId: 999,\n\t\tupdatedTimestamp: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n","import { ApiError } from \"#src/errors/api-error\";\nimport type { OpenCloudError } from \"#src/errors/base\";\nimport { NetworkError } from \"#src/errors/network-error\";\nimport { RateLimitError } from \"#src/errors/rate-limit\";\nimport type {\n\tHttpClient,\n\tHttpRequest,\n\tHttpResponse,\n\tRequestConfig,\n} from \"#src/internal/http/types\";\nimport type { Result } from \"#src/types\";\n\n/**\n * A request captured by {@link FakeHttpClient} for later assertion.\n */\nexport interface CapturedRequest {\n\t/** The per-request config passed alongside the request. */\n\treadonly config: RequestConfig;\n\t/** The request passed to {@link HttpClient.request}. */\n\treadonly request: HttpRequest;\n}\n\n/**\n * A fluent fake for the {@link HttpClient} boundary. Mocks are queued in\n * FIFO order and consumed by each `request()` call. Records every\n * request and config for later assertion. Throws\n * {@link FakeHttpClientError} if the queue is empty when `request()` is\n * called — surfaces missing mocks as test setup bugs instead of silently\n * repeating the last response.\n */\nexport interface FakeHttpClient extends HttpClient {\n\t/** Queues an {@link ApiError} with the given status code and optional message/code. */\n\tmockApiError(options: { code?: string; message?: string; statusCode: number }): this;\n\t/** Queues an error Result with the given error instance. */\n\tmockError(error: OpenCloudError): this;\n\t/** Queues a {@link NetworkError}. Preserves `cause` when provided. */\n\tmockNetworkError(options?: { cause?: unknown; message?: string }): this;\n\t/** Queues a {@link RateLimitError} with the given retry hint. */\n\tmockRateLimit(options: { message?: string; retryAfterSeconds: number }): this;\n\t/** Queues a successful {@link HttpResponse}. Body defaults to `{}`; headers default to `{}`. */\n\tmockResponse(options: {\n\t\tbody?: unknown;\n\t\theaders?: Readonly<Record<string, string>>;\n\t\tstatus: number;\n\t}): this;\n\t/** Number of queued mocks that have not yet been consumed. */\n\treadonly pendingMocks: number;\n\t/** Chronological log of every `(request, config)` pair the fake received. */\n\treadonly requests: ReadonlyArray<CapturedRequest>;\n}\n\ntype ErrorResult = Result<HttpResponse, OpenCloudError> & { success: false };\n\ninterface FakeState {\n\treadonly captured: Array<CapturedRequest>;\n\tconsumed: number;\n\treadonly queue: Array<Result<HttpResponse, OpenCloudError>>;\n}\n\n/**\n * Thrown when {@link FakeHttpClient.request} is called but no mock has\n * been queued. The message names the method, url, and consumed count to\n * aid debugging of missing `.mockResponse`/`.mockError` setup.\n */\nexport class FakeHttpClientError extends Error {\n\tpublic override readonly name: string = \"FakeHttpClientError\";\n}\n\n/**\n * Creates a fluent {@link FakeHttpClient} that sits at the\n * {@link HttpClient} seam. Use for integration tests where you need to\n * assert per-request config (apiKey, baseUrl) flows through to HTTP.\n *\n * @returns A fresh fake with an empty mock queue.\n */\nexport function createFakeHttpClient(): FakeHttpClient {\n\tconst state: FakeState = { captured: [], consumed: 0, queue: [] };\n\tfunction enqueue(result: Result<HttpResponse, OpenCloudError>): FakeHttpClient {\n\t\tstate.queue.push(result);\n\t\treturn fake;\n\t}\n\n\tconst fake: FakeHttpClient = {\n\t\tmockApiError: (options) => enqueue(errorResult(buildApiError(options))),\n\t\tmockError: (error) => enqueue(errorResult(error)),\n\t\tmockNetworkError: (options) => enqueue(errorResult(buildNetworkError(options))),\n\t\tmockRateLimit: (options) => enqueue(errorResult(buildRateLimitError(options))),\n\t\tmockResponse: (options) => enqueue(successResult(options)),\n\t\tget pendingMocks() {\n\t\t\treturn state.queue.length;\n\t\t},\n\t\trequest: async (request, config) => handleRequest({ config, request, state }),\n\t\tget requests() {\n\t\t\treturn state.captured;\n\t\t},\n\t};\n\n\treturn fake;\n}\n\nfunction consumeNextMock(\n\tstate: FakeState,\n\trequest: HttpRequest,\n): Result<HttpResponse, OpenCloudError> {\n\tconst next = state.queue.shift();\n\tif (next === undefined) {\n\t\tthrow new FakeHttpClientError(\n\t\t\t`FakeHttpClient: no mock queued for ${request.method} ${request.url} (consumed ${String(state.consumed)}, pending 0)`,\n\t\t);\n\t}\n\n\tstate.consumed += 1;\n\treturn next;\n}\n\nasync function handleRequest(options: {\n\treadonly config: RequestConfig;\n\treadonly request: HttpRequest;\n\treadonly state: FakeState;\n}): Promise<Result<HttpResponse, OpenCloudError>> {\n\tconst { config, request, state } = options;\n\tstate.captured.push({ config, request });\n\treturn consumeNextMock(state, request);\n}\n\nfunction successResult(options: {\n\tbody?: unknown;\n\theaders?: Readonly<Record<string, string>>;\n\tstatus: number;\n}): Result<HttpResponse, OpenCloudError> {\n\treturn {\n\t\tdata: {\n\t\t\tbody: options.body ?? {},\n\t\t\theaders: options.headers ?? {},\n\t\t\tstatus: options.status,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction errorResult(err: OpenCloudError): ErrorResult {\n\treturn { err, success: false };\n}\n\nfunction buildApiError(options: { code?: string; message?: string; statusCode: number }): ApiError {\n\tconst message = options.message ?? \"API error\";\n\tif (options.code === undefined) {\n\t\treturn new ApiError(message, { statusCode: options.statusCode });\n\t}\n\n\treturn new ApiError(message, { code: options.code, statusCode: options.statusCode });\n}\n\nfunction buildNetworkError(\n\toptions: undefined | { cause?: unknown; message?: string },\n): NetworkError {\n\tconst message = options?.message ?? \"Network error\";\n\tif (options?.cause === undefined) {\n\t\treturn new NetworkError(message);\n\t}\n\n\treturn new NetworkError(message, { cause: options.cause });\n}\n\nfunction buildRateLimitError(options: {\n\tmessage?: string;\n\tretryAfterSeconds: number;\n}): RateLimitError {\n\treturn new RateLimitError(options.message ?? \"Rate limited\", {\n\t\tretryAfterSeconds: options.retryAfterSeconds,\n\t});\n}\n","import type { OpenCloudError } from \"#src/errors/base\";\nimport type { HttpRequest, HttpResponse } from \"#src/internal/http/types\";\nimport type { Result } from \"#src/types\";\n\n/**\n * The `send` callback shape consumed by `executeWithRetry`. A plain\n * transport function — no `RequestConfig`, no queueing, no retries.\n */\nexport type SendFunc = (request: HttpRequest) => Promise<Result<HttpResponse, OpenCloudError>>;\n\n/**\n * A scripted fake for the `send` callback. Replays responses in order\n * and records every request it receives.\n */\nexport interface FakeSend {\n\t/** Chronological log of every request the fake received. */\n\treadonly requests: ReadonlyArray<HttpRequest>;\n\t/** The scripted send callback. */\n\treadonly send: SendFunc;\n}\n\n/**\n * Creates a scripted fake for the `send` callback. Each call returns the\n * next queued response; exhausting the queue throws, which surfaces test\n * setup mistakes instead of silently repeating the last response.\n *\n * @param options - The scripted responses to replay, in order.\n * @returns A `send` callback plus a `requests` log.\n * @rejects {Error} When a call is made after all scripted responses are consumed.\n */\nexport function createFakeSend(options: {\n\treadonly responses: ReadonlyArray<Result<HttpResponse, OpenCloudError>>;\n}): FakeSend {\n\tconst requests: Array<HttpRequest> = [];\n\tlet index = 0;\n\n\tasync function send(request: HttpRequest): Promise<Result<HttpResponse, OpenCloudError>> {\n\t\trequests.push(request);\n\t\tconst response = options.responses[index];\n\t\tindex += 1;\n\n\t\tif (response === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`createFakeSend exhausted: ${String(index)} calls made, only ${String(options.responses.length)} responses scripted`,\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\treturn { requests, send };\n}\n","import type { SleepFunc } from \"#src/internal/utils/sleep\";\n\n/**\n * A directly-callable sleep double that records its wait arguments without\n * delaying. Assignable to {@link SleepFunc}.\n */\nexport interface FakeSleep extends SleepFunc {\n\t/** Chronological log of every `ms` value the fake was called with. */\n\treadonly waits: ReadonlyArray<number>;\n}\n\n/**\n * Creates a {@link FakeSleep} that resolves immediately and records every\n * `ms` value it was called with.\n *\n * @returns A callable sleep function with a `waits` log attached.\n */\nexport function createFakeSleep(): FakeSleep {\n\tconst waits: Array<number> = [];\n\n\tasync function sleep(ms: number): Promise<void> {\n\t\twaits.push(ms);\n\t}\n\n\tconst fake: FakeSleep = Object.assign(sleep, {\n\t\tget waits(): ReadonlyArray<number> {\n\t\t\treturn waits;\n\t\t},\n\t});\n\n\treturn fake;\n}\n","import type {\n\tGameIconListWire,\n\tGetGameIconResponseWire,\n} from \"#src/domains/game-internationalization/game-icon/wire\";\n\n/**\n * Builds a minimally-valid {@link GetGameIconResponseWire} entry. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant.\n *\n * @param overrides - Fields to override on the default entry.\n * @returns A valid localized-icon entry with the overrides applied.\n */\nexport function validLocalizedIcon(\n\toverrides: Partial<GetGameIconResponseWire> = {},\n): GetGameIconResponseWire {\n\treturn {\n\t\timageId: \"12345\",\n\t\timageUrl: \"https://t1.rbxcdn.com/icon/12345\",\n\t\tlanguageCode: \"en_us\",\n\t\tstate: \"Approved\",\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid {@link GameIconListWire} body containing a single\n * default localized icon.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validIconListBody(overrides: Partial<GameIconListWire> = {}): GameIconListWire {\n\treturn {\n\t\tdata: [validLocalizedIcon()],\n\t\t...overrides,\n\t};\n}\n","import type { GamePassConfigV2 } from \"#src/domains/game-passes/game-passes/wire\";\n\n/**\n * Test-only wire shape for the list response. Mirrors the OpenAPI\n * schema, which marks `nextPageToken` as required and nullable, so\n * fixtures can carry the literal JSON `null` the API sends on the last\n * page without leaking `null` into the production wire type (which\n * exposes a post-normalization view of `string | undefined`).\n */\ninterface ListGamePassesWireBody {\n\treadonly gamePasses: ReadonlyArray<GamePassConfigV2>;\n\n\treadonly nextPageToken: null | string;\n}\n\n/**\n * Builds a minimally-valid {@link GamePassConfigV2} wire body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant — useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validGamePassBody(overrides: Partial<GamePassConfigV2> = {}): GamePassConfigV2 {\n\treturn {\n\t\tname: \"Epic Pass\",\n\t\tcreatedTimestamp: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"Unlocks epic stuff\",\n\t\tgamePassId: 12_345,\n\t\ticonAssetId: 67_890,\n\t\tisForSale: true,\n\t\tpriceInformation: { defaultPriceInRobux: 100, enabledFeatures: [] },\n\t\tupdatedTimestamp: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid wire body for the \"list game passes\" endpoint.\n * By default the page contains one game pass and `nextPageToken` is the\n * literal JSON `null` the API sends on the last page; `overrides` let\n * parser and integration tests tweak the items array or the cursor\n * without rebuilding the whole shape.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied. `nextPageToken`\n * defaults to the wire's literal `null`, which the response parser\n * normalizes to `undefined` at the boundary.\n */\nexport function validListGamePassesBody(\n\toverrides: Partial<ListGamePassesWireBody> = {},\n): ListGamePassesWireBody {\n\treturn {\n\t\tgamePasses: [validGamePassBody()],\n\t\t// eslint-disable-next-line unicorn/no-null -- API sends null on the last page; parser normalizes to undefined.\n\t\tnextPageToken: null,\n\t\t...overrides,\n\t};\n}\n","import type { GameThumbnailUploadWire } from \"#src/domains/game-internationalization/game-thumbnails/wire\";\n\n/**\n * Builds a minimally-valid {@link GameThumbnailUploadWire} body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validThumbnailUploadBody(\n\toverrides: Partial<GameThumbnailUploadWire> = {},\n): GameThumbnailUploadWire {\n\treturn { mediaAssetId: \"67890\", ...overrides };\n}\n","import type { PlaceWire } from \"#src/domains/cloud-v2/places/wire\";\nimport { RBXL_SIGNATURE, RBXLX_SIGNATURE } from \"#src/domains/universes/places/signatures\";\nimport type { PlaceVersionWire } from \"#src/domains/universes/places/wire\";\n\n/**\n * Returns a fresh, minimal `.rbxl`-formatted body whose magic bytes\n * match {@link RBXL_SIGNATURE}. Useful when integration tests don't\n * care about the file's contents past the signature.\n *\n * @returns A 14-byte rbxl body matching the binary signature.\n */\nexport function rbxlBody(): Uint8Array<ArrayBuffer> {\n\treturn new Uint8Array(RBXL_SIGNATURE);\n}\n\n/**\n * Returns a fresh, minimal `.rbxlx`-formatted body whose magic bytes\n * match {@link RBXLX_SIGNATURE}. Useful when integration tests don't\n * care about the file's contents past the signature.\n *\n * @returns An 8-byte rbxlx body matching the XML signature.\n */\nexport function rbxlxBody(): Uint8Array<ArrayBuffer> {\n\treturn new Uint8Array(RBXLX_SIGNATURE);\n}\n\n/**\n * Builds a minimally-valid {@link PlaceVersionWire} body. Pass an\n * `overrides` object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validPublishResponseBody(\n\toverrides: Partial<PlaceVersionWire> = {},\n): PlaceVersionWire {\n\treturn {\n\t\tversionNumber: 1,\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid {@link PlaceWire} body. Pass an `overrides`\n * object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validPlaceBody(overrides: Partial<PlaceWire> = {}): PlaceWire {\n\treturn {\n\t\tcreateTime: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A sample place.\",\n\t\tdisplayName: \"Test Place\",\n\t\tpath: \"universes/123/places/456\",\n\t\troot: true,\n\t\tserverSize: 30,\n\t\tuniverseRuntimeCreation: false,\n\t\tupdateTime: \"2024-11-02T17:08:21.500Z\",\n\t\t...overrides,\n\t};\n}\n","import type { UniverseWire } from \"#src/domains/cloud-v2/universes/wire\";\n\n/**\n * Builds a minimally-valid {@link UniverseWire} body. Pass an\n * `overrides` object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validUniverseBody(overrides: Partial<UniverseWire> = {}): UniverseWire {\n\treturn {\n\t\tageRating: \"AGE_RATING_13_PLUS\",\n\t\tconsoleEnabled: false,\n\t\tcreateTime: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A sample universe for tests.\",\n\t\tdesktopEnabled: true,\n\t\tdisplayName: \"Test Universe\",\n\t\tmobileEnabled: true,\n\t\tpath: \"universes/12345\",\n\t\trootPlace: \"universes/12345/places/98765\",\n\t\ttabletEnabled: true,\n\t\tupdateTime: \"2024-11-02T17:08:21.500Z\",\n\t\tuser: \"users/7777\",\n\t\tvisibility: \"PUBLIC\",\n\t\tvoiceChatEnabled: false,\n\t\tvrEnabled: false,\n\t\t...overrides,\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"testing.mjs","names":[],"sources":["../tests/helpers/badges.ts","../tests/helpers/developer-products.ts","../tests/helpers/fake-http-client.ts","../tests/helpers/fake-send.ts","../tests/helpers/fake-sleep.ts","../tests/helpers/game-icon.ts","../tests/helpers/game-passes.ts","../tests/helpers/game-thumbnails.ts","../tests/helpers/luau-execution-task-binary-inputs.ts","../tests/helpers/luau-execution-task-logs.ts","../tests/helpers/luau-execution-tasks.ts","../tests/helpers/memory-store-queues.ts","../tests/helpers/places.ts","../tests/helpers/universes.ts"],"sourcesContent":["import type { BadgeResponseV2Wire } from \"#src/domains/badges/badges/wire\";\n\n/**\n * Builds a minimally-valid {@link BadgeResponseV2Wire} body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validBadgeBody(overrides: Partial<BadgeResponseV2Wire> = {}): BadgeResponseV2Wire {\n\treturn {\n\t\tid: 12_345,\n\t\tname: \"First Goal\",\n\t\tawarder: { id: 222, name: \"Lobby\", type: 1 },\n\t\tcreated: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"Awarded on first login.\",\n\t\tdisplayDescription: \"Awarded on first login.\",\n\t\tdisplayIconImageId: 67_890,\n\t\tdisplayName: \"First Goal\",\n\t\tenabled: true,\n\t\ticonImageId: 67_890,\n\t\tstatistics: { awardedCount: 100, pastDayAwardedCount: 5, winRatePercentage: 42.5 },\n\t\tupdated: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n","import type { DeveloperProductConfigV2 } from \"#src/domains/developer-products/products/wire\";\n\n/**\n * Builds a minimally-valid {@link DeveloperProductConfigV2} wire body. Pass\n * an `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validDeveloperProductBody(\n\toverrides: Partial<DeveloperProductConfigV2> = {},\n): DeveloperProductConfigV2 {\n\treturn {\n\t\tname: \"Gem Pack\",\n\t\tcreatedTimestamp: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A premium gem pack\",\n\t\ticonImageAssetId: 67_890,\n\t\tisForSale: true,\n\t\tisImmutable: false,\n\t\tpriceInformation: { defaultPriceInRobux: 100, enabledFeatures: [] },\n\t\tproductId: 12_345,\n\t\tstorePageEnabled: true,\n\t\tuniverseId: 999,\n\t\tupdatedTimestamp: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n","import { ApiError } from \"#src/errors/api-error\";\nimport type { OpenCloudError } from \"#src/errors/base\";\nimport { NetworkError } from \"#src/errors/network-error\";\nimport { RateLimitError } from \"#src/errors/rate-limit\";\nimport type {\n\tHttpClient,\n\tHttpRequest,\n\tHttpResponse,\n\tRequestConfig,\n} from \"#src/internal/http/types\";\nimport type { Result } from \"#src/types\";\n\n/**\n * A request captured by {@link FakeHttpClient} for later assertion.\n */\nexport interface CapturedRequest {\n\t/** The per-request config passed alongside the request. */\n\treadonly config: RequestConfig;\n\t/** The request passed to {@link HttpClient.request}. */\n\treadonly request: HttpRequest;\n}\n\n/**\n * A fluent fake for the {@link HttpClient} boundary. Mocks are queued in\n * FIFO order and consumed by each `request()` call. Records every\n * request and config for later assertion. Throws\n * {@link FakeHttpClientError} if the queue is empty when `request()` is\n * called — surfaces missing mocks as test setup bugs instead of silently\n * repeating the last response.\n */\nexport interface FakeHttpClient extends HttpClient {\n\t/** Queues an {@link ApiError} with the given status code and optional message/code. */\n\tmockApiError(options: { code?: string; message?: string; statusCode: number }): this;\n\t/** Queues an error Result with the given error instance. */\n\tmockError(error: OpenCloudError): this;\n\t/** Queues a {@link NetworkError}. Preserves `cause` when provided. */\n\tmockNetworkError(options?: { cause?: unknown; message?: string }): this;\n\t/** Queues a {@link RateLimitError} with the given retry hint. */\n\tmockRateLimit(options: { message?: string; retryAfterSeconds: number }): this;\n\t/** Queues a successful {@link HttpResponse}. Body defaults to `{}`; headers default to `{}`. */\n\tmockResponse(options: {\n\t\tbody?: unknown;\n\t\theaders?: Readonly<Record<string, string>>;\n\t\tstatus: number;\n\t}): this;\n\t/** Number of queued mocks that have not yet been consumed. */\n\treadonly pendingMocks: number;\n\t/** Chronological log of every `(request, config)` pair the fake received. */\n\treadonly requests: ReadonlyArray<CapturedRequest>;\n}\n\ntype ErrorResult = Result<HttpResponse, OpenCloudError> & { success: false };\n\ninterface FakeState {\n\treadonly captured: Array<CapturedRequest>;\n\tconsumed: number;\n\treadonly queue: Array<Result<HttpResponse, OpenCloudError>>;\n}\n\n/**\n * Thrown when {@link FakeHttpClient.request} is called but no mock has\n * been queued. The message names the method, url, and consumed count to\n * aid debugging of missing `.mockResponse`/`.mockError` setup.\n */\nexport class FakeHttpClientError extends Error {\n\tpublic override readonly name: string = \"FakeHttpClientError\";\n}\n\n/**\n * Creates a fluent {@link FakeHttpClient} that sits at the\n * {@link HttpClient} seam. Use for integration tests where you need to\n * assert per-request config (apiKey, baseUrl) flows through to HTTP.\n *\n * @returns A fresh fake with an empty mock queue.\n */\nexport function createFakeHttpClient(): FakeHttpClient {\n\tconst state: FakeState = { captured: [], consumed: 0, queue: [] };\n\tfunction enqueue(result: Result<HttpResponse, OpenCloudError>): FakeHttpClient {\n\t\tstate.queue.push(result);\n\t\treturn fake;\n\t}\n\n\tconst fake: FakeHttpClient = {\n\t\tmockApiError: (options) => enqueue(errorResult(buildApiError(options))),\n\t\tmockError: (error) => enqueue(errorResult(error)),\n\t\tmockNetworkError: (options) => enqueue(errorResult(buildNetworkError(options))),\n\t\tmockRateLimit: (options) => enqueue(errorResult(buildRateLimitError(options))),\n\t\tmockResponse: (options) => enqueue(successResult(options)),\n\t\tget pendingMocks() {\n\t\t\treturn state.queue.length;\n\t\t},\n\t\trequest: async (request, config) => handleRequest({ config, request, state }),\n\t\tget requests() {\n\t\t\treturn state.captured;\n\t\t},\n\t};\n\n\treturn fake;\n}\n\nfunction consumeNextMock(\n\tstate: FakeState,\n\trequest: HttpRequest,\n): Result<HttpResponse, OpenCloudError> {\n\tconst next = state.queue.shift();\n\tif (next === undefined) {\n\t\tthrow new FakeHttpClientError(\n\t\t\t`FakeHttpClient: no mock queued for ${request.method} ${request.url} (consumed ${String(state.consumed)}, pending 0)`,\n\t\t);\n\t}\n\n\tstate.consumed += 1;\n\treturn next;\n}\n\nasync function handleRequest(options: {\n\treadonly config: RequestConfig;\n\treadonly request: HttpRequest;\n\treadonly state: FakeState;\n}): Promise<Result<HttpResponse, OpenCloudError>> {\n\tconst { config, request, state } = options;\n\tstate.captured.push({ config, request });\n\treturn consumeNextMock(state, request);\n}\n\nfunction successResult(options: {\n\tbody?: unknown;\n\theaders?: Readonly<Record<string, string>>;\n\tstatus: number;\n}): Result<HttpResponse, OpenCloudError> {\n\treturn {\n\t\tdata: {\n\t\t\tbody: options.body ?? {},\n\t\t\theaders: options.headers ?? {},\n\t\t\tstatus: options.status,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction errorResult(err: OpenCloudError): ErrorResult {\n\treturn { err, success: false };\n}\n\nfunction buildApiError(options: { code?: string; message?: string; statusCode: number }): ApiError {\n\tconst message = options.message ?? \"API error\";\n\tif (options.code === undefined) {\n\t\treturn new ApiError(message, { statusCode: options.statusCode });\n\t}\n\n\treturn new ApiError(message, { code: options.code, statusCode: options.statusCode });\n}\n\nfunction buildNetworkError(\n\toptions: undefined | { cause?: unknown; message?: string },\n): NetworkError {\n\tconst message = options?.message ?? \"Network error\";\n\tif (options?.cause === undefined) {\n\t\treturn new NetworkError(message);\n\t}\n\n\treturn new NetworkError(message, { cause: options.cause });\n}\n\nfunction buildRateLimitError(options: {\n\tmessage?: string;\n\tretryAfterSeconds: number;\n}): RateLimitError {\n\treturn new RateLimitError(options.message ?? \"Rate limited\", {\n\t\tretryAfterSeconds: options.retryAfterSeconds,\n\t});\n}\n","import type { OpenCloudError } from \"#src/errors/base\";\nimport type { HttpRequest, HttpResponse } from \"#src/internal/http/types\";\nimport type { Result } from \"#src/types\";\n\n/**\n * The `send` callback shape consumed by `executeWithRetry`. A plain\n * transport function — no `RequestConfig`, no queueing, no retries.\n */\nexport type SendFunc = (request: HttpRequest) => Promise<Result<HttpResponse, OpenCloudError>>;\n\n/**\n * A scripted fake for the `send` callback. Replays responses in order\n * and records every request it receives.\n */\nexport interface FakeSend {\n\t/** Chronological log of every request the fake received. */\n\treadonly requests: ReadonlyArray<HttpRequest>;\n\t/** The scripted send callback. */\n\treadonly send: SendFunc;\n}\n\n/**\n * Creates a scripted fake for the `send` callback. Each call returns the\n * next queued response; exhausting the queue throws, which surfaces test\n * setup mistakes instead of silently repeating the last response.\n *\n * @param options - The scripted responses to replay, in order.\n * @returns A `send` callback plus a `requests` log.\n * @rejects {Error} When a call is made after all scripted responses are consumed.\n */\nexport function createFakeSend(options: {\n\treadonly responses: ReadonlyArray<Result<HttpResponse, OpenCloudError>>;\n}): FakeSend {\n\tconst requests: Array<HttpRequest> = [];\n\tlet index = 0;\n\n\tasync function send(request: HttpRequest): Promise<Result<HttpResponse, OpenCloudError>> {\n\t\trequests.push(request);\n\t\tconst response = options.responses[index];\n\t\tindex += 1;\n\n\t\tif (response === undefined) {\n\t\t\tthrow new Error(\n\t\t\t\t`createFakeSend exhausted: ${String(index)} calls made, only ${String(options.responses.length)} responses scripted`,\n\t\t\t);\n\t\t}\n\n\t\treturn response;\n\t}\n\n\treturn { requests, send };\n}\n","import type { SleepFunc } from \"#src/internal/utils/sleep\";\n\n/**\n * A directly-callable sleep double that records its wait arguments without\n * delaying. Assignable to {@link SleepFunc}.\n */\nexport interface FakeSleep extends SleepFunc {\n\t/** Chronological log of every `ms` value the fake was called with. */\n\treadonly waits: ReadonlyArray<number>;\n}\n\n/**\n * Creates a {@link FakeSleep} that resolves immediately and records every\n * `ms` value it was called with.\n *\n * @returns A callable sleep function with a `waits` log attached.\n */\nexport function createFakeSleep(): FakeSleep {\n\tconst waits: Array<number> = [];\n\n\tasync function sleep(ms: number): Promise<void> {\n\t\twaits.push(ms);\n\t}\n\n\tconst fake: FakeSleep = Object.assign(sleep, {\n\t\tget waits(): ReadonlyArray<number> {\n\t\t\treturn waits;\n\t\t},\n\t});\n\n\treturn fake;\n}\n","import type {\n\tGameIconListWire,\n\tGetGameIconResponseWire,\n} from \"#src/domains/game-internationalization/game-icon/wire\";\n\n/**\n * Builds a minimally-valid {@link GetGameIconResponseWire} entry. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant.\n *\n * @param overrides - Fields to override on the default entry.\n * @returns A valid localized-icon entry with the overrides applied.\n */\nexport function validLocalizedIcon(\n\toverrides: Partial<GetGameIconResponseWire> = {},\n): GetGameIconResponseWire {\n\treturn {\n\t\timageId: \"12345\",\n\t\timageUrl: \"https://t1.rbxcdn.com/icon/12345\",\n\t\tlanguageCode: \"en_us\",\n\t\tstate: \"Approved\",\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid {@link GameIconListWire} body containing a single\n * default localized icon.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validIconListBody(overrides: Partial<GameIconListWire> = {}): GameIconListWire {\n\treturn {\n\t\tdata: [validLocalizedIcon()],\n\t\t...overrides,\n\t};\n}\n","import type { GamePassConfigV2 } from \"#src/domains/game-passes/game-passes/wire\";\n\n/**\n * Test-only wire shape for the list response. Mirrors the OpenAPI\n * schema, which marks `nextPageToken` as required and nullable, so\n * fixtures can carry the literal JSON `null` the API sends on the last\n * page without leaking `null` into the production wire type (which\n * exposes a post-normalization view of `string | undefined`).\n */\ninterface ListGamePassesWireBody {\n\treadonly gamePasses: ReadonlyArray<GamePassConfigV2>;\n\n\treadonly nextPageToken: null | string;\n}\n\n/**\n * Builds a minimally-valid {@link GamePassConfigV2} wire body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant — useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validGamePassBody(overrides: Partial<GamePassConfigV2> = {}): GamePassConfigV2 {\n\treturn {\n\t\tname: \"Epic Pass\",\n\t\tcreatedTimestamp: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"Unlocks epic stuff\",\n\t\tgamePassId: 12_345,\n\t\ticonAssetId: 67_890,\n\t\tisForSale: true,\n\t\tpriceInformation: { defaultPriceInRobux: 100, enabledFeatures: [] },\n\t\tupdatedTimestamp: \"2024-03-20T14:45:00.000Z\",\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid wire body for the \"list game passes\" endpoint.\n * By default the page contains one game pass and `nextPageToken` is the\n * literal JSON `null` the API sends on the last page; `overrides` let\n * parser and integration tests tweak the items array or the cursor\n * without rebuilding the whole shape.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied. `nextPageToken`\n * defaults to the wire's literal `null`, which the response parser\n * normalizes to `undefined` at the boundary.\n */\nexport function validListGamePassesBody(\n\toverrides: Partial<ListGamePassesWireBody> = {},\n): ListGamePassesWireBody {\n\treturn {\n\t\tgamePasses: [validGamePassBody()],\n\t\t// eslint-disable-next-line unicorn/no-null -- API sends null on the last page; parser normalizes to undefined.\n\t\tnextPageToken: null,\n\t\t...overrides,\n\t};\n}\n","import type { GameThumbnailUploadWire } from \"#src/domains/game-internationalization/game-thumbnails/wire\";\n\n/**\n * Builds a minimally-valid {@link GameThumbnailUploadWire} body. Pass an\n * `overrides` object to tweak individual fields while keeping everything\n * else schema-compliant; useful for parser and integration tests that\n * only care about one field at a time.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validThumbnailUploadBody(\n\toverrides: Partial<GameThumbnailUploadWire> = {},\n): GameThumbnailUploadWire {\n\treturn { mediaAssetId: \"67890\", ...overrides };\n}\n","import type { LuauExecutionTaskBinaryInputWire } from \"#src/domains/cloud-v2/luau-execution-task-binary-inputs/wire\";\n\n/**\n * Builds a minimally-valid {@link LuauExecutionTaskBinaryInputWire} body\n * for tests. Pass an `overrides` object to tweak fields without re-stating\n * the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validBinaryInputBody(\n\toverrides: Partial<LuauExecutionTaskBinaryInputWire> = {},\n): LuauExecutionTaskBinaryInputWire {\n\treturn {\n\t\tpath: \"universes/123/luau-execution-session-task-binary-inputs/abc\",\n\t\tuploadUri: \"https://storage.example.com/upload?token=xyz\",\n\t\t...overrides,\n\t};\n}\n","import type { ListLogsResponseWire } from \"#src/domains/cloud-v2/luau-execution-task-logs/wire\";\n\n/**\n * Builds a minimally-valid {@link ListLogsResponseWire} body containing\n * one chunk with one structured message. Pass an `overrides` object to\n * tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validLogPageBody(\n\toverrides: Partial<ListLogsResponseWire> = {},\n): ListLogsResponseWire {\n\treturn {\n\t\tluauExecutionSessionTaskLogs: [\n\t\t\t{\n\t\t\t\tstructuredMessages: [\n\t\t\t\t\t{\n\t\t\t\t\t\tcreateTime: \"2026-01-01T00:00:00Z\",\n\t\t\t\t\t\tmessage: \"Hello from Luau\",\n\t\t\t\t\t\tmessageType: \"OUTPUT\",\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t\t...overrides,\n\t};\n}\n","import type { LuauExecutionTaskWire } from \"#src/domains/cloud-v2/luau-execution-tasks/wire\";\n\n/**\n * Builds a minimally-valid {@link LuauExecutionTaskWire} body for an\n * in-progress task. Pass an `overrides` object to tweak fields without\n * re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validInProgressTaskBody(\n\toverrides: Partial<LuauExecutionTaskWire> = {},\n): LuauExecutionTaskWire {\n\treturn {\n\t\tcreateTime: \"2026-01-01T00:00:00Z\",\n\t\tpath: \"universes/123/places/456/luau-execution-session-tasks/task-1\",\n\t\tstate: \"QUEUED\",\n\t\tupdateTime: \"2026-01-01T00:00:30Z\",\n\t\tuser: \"user-1\",\n\t\t...overrides,\n\t};\n}\n","import type {\n\tMemoryStoreQueueItemWire,\n\tReadQueueItemsResponseWire,\n} from \"#src/domains/cloud-v2/memory-store-queues/wire\";\n\n/**\n * Builds a minimally-valid {@link MemoryStoreQueueItemWire} body. Pass\n * an `overrides` object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validQueueItemBody(\n\toverrides: Partial<MemoryStoreQueueItemWire> = {},\n): MemoryStoreQueueItemWire {\n\treturn {\n\t\tdata: \"hello\",\n\t\texpireTime: \"2026-06-21T15:08:58.4806559Z\",\n\t\tpath: \"cloud/v2/universes/123/memory-store/queues/test-queue/items/abc123\",\n\t\tpriority: 1,\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid {@link ReadQueueItemsResponseWire} body\n * carrying a single default queue item. Pass an `overrides` object to\n * change the read identifier or supply a different items array.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid dequeue response body with the overrides applied.\n */\nexport function validDequeueBody(\n\toverrides: Partial<ReadQueueItemsResponseWire> = {},\n): ReadQueueItemsResponseWire {\n\treturn {\n\t\tid: \"1a354bd5b8fe457f8e51232f8dbfe6d0\",\n\t\tqueueItems: [validQueueItemBody()],\n\t\t...overrides,\n\t};\n}\n","import type { PlaceWire } from \"#src/domains/cloud-v2/places/wire\";\nimport { RBXL_SIGNATURE, RBXLX_SIGNATURE } from \"#src/domains/universes/places/signatures\";\nimport type { PlaceVersionWire } from \"#src/domains/universes/places/wire\";\n\n/**\n * Returns a fresh, minimal `.rbxl`-formatted body whose magic bytes\n * match {@link RBXL_SIGNATURE}. Useful when integration tests don't\n * care about the file's contents past the signature.\n *\n * @returns A 14-byte rbxl body matching the binary signature.\n */\nexport function rbxlBody(): Uint8Array<ArrayBuffer> {\n\treturn new Uint8Array(RBXL_SIGNATURE);\n}\n\n/**\n * Returns a fresh, minimal `.rbxlx`-formatted body whose magic bytes\n * match {@link RBXLX_SIGNATURE}. Useful when integration tests don't\n * care about the file's contents past the signature.\n *\n * @returns An 8-byte rbxlx body matching the XML signature.\n */\nexport function rbxlxBody(): Uint8Array<ArrayBuffer> {\n\treturn new Uint8Array(RBXLX_SIGNATURE);\n}\n\n/**\n * Builds a minimally-valid {@link PlaceVersionWire} body. Pass an\n * `overrides` object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validPublishResponseBody(\n\toverrides: Partial<PlaceVersionWire> = {},\n): PlaceVersionWire {\n\treturn {\n\t\tversionNumber: 1,\n\t\t...overrides,\n\t};\n}\n\n/**\n * Builds a minimally-valid {@link PlaceWire} body. Pass an `overrides`\n * object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validPlaceBody(overrides: Partial<PlaceWire> = {}): PlaceWire {\n\treturn {\n\t\tcreateTime: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A sample place.\",\n\t\tdisplayName: \"Test Place\",\n\t\tpath: \"universes/123/places/456\",\n\t\troot: true,\n\t\tserverSize: 30,\n\t\tuniverseRuntimeCreation: false,\n\t\tupdateTime: \"2024-11-02T17:08:21.500Z\",\n\t\t...overrides,\n\t};\n}\n","import type { UniverseWire } from \"#src/domains/cloud-v2/universes/wire\";\n\n/**\n * Builds a minimally-valid {@link UniverseWire} body. Pass an\n * `overrides` object to tweak fields without re-stating the defaults.\n *\n * @param overrides - Fields to override on the default body.\n * @returns A valid wire body with the overrides applied.\n */\nexport function validUniverseBody(overrides: Partial<UniverseWire> = {}): UniverseWire {\n\treturn {\n\t\tageRating: \"AGE_RATING_13_PLUS\",\n\t\tconsoleEnabled: false,\n\t\tcreateTime: \"2024-01-15T10:30:00.000Z\",\n\t\tdescription: \"A sample universe for tests.\",\n\t\tdesktopEnabled: true,\n\t\tdisplayName: \"Test Universe\",\n\t\tmobileEnabled: true,\n\t\tpath: \"universes/12345\",\n\t\trootPlace: \"universes/12345/places/98765\",\n\t\ttabletEnabled: true,\n\t\tupdateTime: \"2024-11-02T17:08:21.500Z\",\n\t\tuser: \"users/7777\",\n\t\tvisibility: \"PUBLIC\",\n\t\tvoiceChatEnabled: false,\n\t\tvrEnabled: false,\n\t\t...overrides,\n\t};\n}\n"],"mappings":"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"}
@@ -211,4 +211,4 @@ type RequestOptions = Partial<Pick<OpenCloudClientOptions, "apiKey" | "baseUrl"
211
211
  type HttpRequestBody = FormData | Record<string, unknown> | Uint8Array<ArrayBuffer> | undefined;
212
212
  //#endregion
213
213
  export { OpenCloudHooks as a, Page as c, OpenCloudError as d, OpenCloudClientOptions as i, Result as l, HttpRequest as n, RequestConfig as o, HttpResponse as r, RequestOptions as s, HttpClient as t, SleepFunc as u };
214
- //# sourceMappingURL=types-BOhSh9ug.d.mts.map
214
+ //# sourceMappingURL=types-CwtZT1ek.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-BOhSh9ug.d.mts","names":[],"sources":["../src/errors/base.ts","../src/internal/utils/sleep.ts","../src/types.ts","../src/client/types.ts"],"mappings":";;AAMA;;;;;cAAa,cAAA,SAAuB,KAAA;EAAA,kBACV,IAAA;AAAA;;;;KCNd,SAAA,IAAa,EAAA,aAAe,OAAA;;;;ADKxC;;;;;;;;ACLA;;;;;;;;ACiCA;;;;;;;;;;;;;;;;;KAAY,MAAA,QAAc,KAAA;EAAW,IAAA,EAAM,CAAA;EAAG,OAAA;AAAA;EAAoB,GAAA,EAAK,CAAA;EAAG,OAAA;AAAA;;;;;;;ACzB1E;;;;;;;;;;;;;;;;;AAkBA;;;UDmCiB,IAAA;;WAEP,KAAA,EAAO,aAAA,CAAc,CAAA;;WAErB,aAAA;AAAA;;;;;;UCzDO,WAAA;;WAEP,IAAA,GAAO,eAAA;EFVL;;;;;EAAA,SEgBF,OAAA,GAAU,QAAA,CAAS,MAAA;;WAEnB,MAAA;EDeE;EAAA,SCbF,GAAA;AAAA;;;;UAMO,YAAA;;;;;;WAMP,IAAA;;WAEA,OAAA,EAAS,QAAA,CAAS,MAAA;;WAElB,MAAA;AAAA;ADyBV;;;AAAA,UCnBiB,aAAA;;WAEP,MAAA;;WAEA,OAAA;;WAEA,OAAA;AAAA;;;;AAxCV;UA+CiB,UAAA;;EAEhB,OAAA,CACC,OAAA,EAAS,WAAA,EACT,MAAA,EAAQ,aAAA,GACN,OAAA,CAAQ,MAAA,CAAO,YAAA,EAAc,cAAA;AAAA;;;;;UAOhB,cAAA;;WAEP,WAAA,IAAe,MAAA;;WAEf,SAAA,IAAa,OAAA,EAAS,WAAA;;WAEtB,OAAA,IAAW,OAAA,UAAiB,KAAA,EAAO,cAAA;AAAA;AA/C7C;;;;AAAA,UAsDiB,sBAAA;;WAEP,MAAA;;WAEA,OAAA;;WAEA,KAAA,GAAQ,cAAA;EA5ClB;;;;;;;EAAA,SAoDU,UAAA,GAAa,UAAA;EA9Cb;EAAA,SAgDA,UAAA;EAzCO;;;;;EAAA,SA+CP,iBAAA,GAAoB,aAAA;;WAEpB,UAAA,IAAc,OAAA;;;;;;;WAOd,KAAA,GAAQ,SAAA;;WAER,OAAA;AAAA;;;;AA9CV;;KAsDY,cAAA,GAAiB,OAAA,CAC5B,IAAA,CACC,sBAAA;;;;;;;;;;;;KAgBG,eAAA,GAAkB,QAAA,GAAW,MAAA,oBAA0B,UAAA,CAAW,WAAA"}
1
+ {"version":3,"file":"types-CwtZT1ek.d.mts","names":[],"sources":["../src/errors/base.ts","../src/internal/utils/sleep.ts","../src/types.ts","../src/client/types.ts"],"mappings":";;AAMA;;;;;cAAa,cAAA,SAAuB,KAAA;EAAA,kBACV,IAAA;AAAA;;;;KCNd,SAAA,IAAa,EAAA,aAAe,OAAA;;;;ADKxC;;;;;;;;ACLA;;;;;;;;ACiCA;;;;;;;;;;;;;;;;;KAAY,MAAA,QAAc,KAAA;EAAW,IAAA,EAAM,CAAA;EAAG,OAAA;AAAA;EAAoB,GAAA,EAAK,CAAA;EAAG,OAAA;AAAA;;;;;;;ACzB1E;;;;;;;;;;;;;;;;;AAkBA;;;UDmCiB,IAAA;;WAEP,KAAA,EAAO,aAAA,CAAc,CAAA;;WAErB,aAAA;AAAA;;;;;;UCzDO,WAAA;;WAEP,IAAA,GAAO,eAAA;EFVL;;;;;EAAA,SEgBF,OAAA,GAAU,QAAA,CAAS,MAAA;;WAEnB,MAAA;EDeE;EAAA,SCbF,GAAA;AAAA;;;;UAMO,YAAA;;;;;;WAMP,IAAA;;WAEA,OAAA,EAAS,QAAA,CAAS,MAAA;;WAElB,MAAA;AAAA;ADyBV;;;AAAA,UCnBiB,aAAA;;WAEP,MAAA;;WAEA,OAAA;;WAEA,OAAA;AAAA;;;;AAxCV;UA+CiB,UAAA;;EAEhB,OAAA,CACC,OAAA,EAAS,WAAA,EACT,MAAA,EAAQ,aAAA,GACN,OAAA,CAAQ,MAAA,CAAO,YAAA,EAAc,cAAA;AAAA;;;;;UAOhB,cAAA;;WAEP,WAAA,IAAe,MAAA;;WAEf,SAAA,IAAa,OAAA,EAAS,WAAA;;WAEtB,OAAA,IAAW,OAAA,UAAiB,KAAA,EAAO,cAAA;AAAA;AA/C7C;;;;AAAA,UAsDiB,sBAAA;;WAEP,MAAA;;WAEA,OAAA;;WAEA,KAAA,GAAQ,cAAA;EA5ClB;;;;;;;EAAA,SAoDU,UAAA,GAAa,UAAA;EA9Cb;EAAA,SAgDA,UAAA;EAzCO;;;;;EAAA,SA+CP,iBAAA,GAAoB,aAAA;;WAEpB,UAAA,IAAc,OAAA;;;;;;;WAOd,KAAA,GAAQ,SAAA;;WAER,OAAA;AAAA;;;;AA9CV;;KAsDY,cAAA,GAAiB,OAAA,CAC5B,IAAA,CACC,sBAAA;;;;;;;;;;;;KAgBG,eAAA,GAAkB,QAAA,GAAW,MAAA,oBAA0B,UAAA,CAAW,WAAA"}
@@ -1,6 +1,6 @@
1
- import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, s as RequestOptions } from "./types-BOhSh9ug.mjs";
2
- import { i as RobloxLocale, r as RobloxLanguageCode } from "./data.generated-DdwXMiv9.mjs";
3
- import { n as GameIconState } from "./wire-BeIO-d1x.mjs";
1
+ import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, s as RequestOptions } from "./types-CwtZT1ek.mjs";
2
+ import { i as RobloxLocale, r as RobloxLanguageCode } from "./data.generated-Cb6g6asv.mjs";
3
+ import { n as GameIconState } from "./wire-CeL6W_V7.mjs";
4
4
 
5
5
  //#region src/domains/cloud-v2/universes/types.d.ts
6
6
  /**
@@ -1,8 +1,7 @@
1
1
  import { r as ApiError } from "./rate-limit-D1q2Js-z.mjs";
2
2
  import { t as ValidationError } from "./validation-DkL5KQqz.mjs";
3
3
  import { t as toBlob } from "./to-blob-B27VhoRp.mjs";
4
- import { t as isDateTimeString } from "./is-date-time-string-DL6l9mo6.mjs";
5
- import { a as IDEMPOTENT_METHOD_DEFAULTS, i as CREATE_METHOD_DEFAULTS, n as okRequest, r as parseEmptyResponse, s as isRecord, t as ResourceClient } from "./resource-client-D7HKNrOp.mjs";
4
+ 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";
6
5
  //#region src/domains/cloud-v2/universes/builders.ts
7
6
  /**
8
7
  * Dodges `unicorn/no-null` while still emitting a literal `null` onto
@@ -1 +1 @@
1
- {"version":3,"file":"universes.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/universes/builders.ts","../src/domains/cloud-v2/universes/operations.ts","../src/domains/cloud-v2/universes/parsers.ts","../src/domains/game-internationalization/game-icon/builders.ts","../src/domains/game-internationalization/game-icon/operations.ts","../src/domains/game-internationalization/game-icon/parsers.ts","../src/domains/game-internationalization/game-thumbnails/builders.ts","../src/domains/game-internationalization/game-thumbnails/operations.ts","../src/domains/game-internationalization/game-thumbnails/parsers.ts","../src/resources/universes/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport type { OpenCloudError } from \"../../../errors/base.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport { okRequest } from \"../../../internal/resource-client.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { GetUniverseParameters, UpdateUniverseParameters } from \"./types.ts\";\n\n/**\n * Dodges `unicorn/no-null` while still emitting a literal `null` onto\n * the wire, which the Open Cloud `Cloud_UpdateUniverse` endpoint\n * requires to clear a nullable field (for example disabling private\n * servers or removing a social link).\n */\nconst NULL_SENTINEL = JSON.parse(\"null\");\n\n/**\n * Builds a `GET` request for the Open Cloud \"get universe\" endpoint.\n *\n * @param parameters - The universe identifier.\n * @returns A success result wrapping the request; the builder cannot fail.\n */\nexport function buildGetRequest(\n\tparameters: GetUniverseParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest({\n\t\tmethod: \"GET\",\n\t\turl: `/cloud/v2/universes/${parameters.universeId}`,\n\t});\n}\n\n/**\n * Builds a `PATCH` request for the Open Cloud \"update universe\"\n * endpoint. Derives the `updateMask` query string from the keys\n * present on `parameters` and emits a JSON body containing those same\n * fields, translating `undefined` values to JSON `null` so Roblox\n * clears the corresponding server-side value.\n *\n * @param parameters - The universe identifier plus the fields to update.\n * @returns A success result wrapping the request, or a\n * {@link ValidationError} when no updatable fields were supplied.\n */\nexport function buildUpdateRequest(\n\tparameters: UpdateUniverseParameters,\n): Result<HttpRequest, ValidationError> {\n\tconst fieldKeys = extractUpdateFieldKeys(parameters);\n\n\tif (fieldKeys.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"Update must include at least one field\", {\n\t\t\t\tcode: \"empty_update\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\tconst body: Record<string, unknown> = {};\n\tfor (const key of fieldKeys) {\n\t\tbody[key] = bodyValueFor(parameters, key);\n\t}\n\n\tconst updateMask = fieldKeys.join(\",\");\n\treturn {\n\t\tdata: {\n\t\t\tbody,\n\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\tmethod: \"PATCH\",\n\t\t\turl: `/cloud/v2/universes/${parameters.universeId}?updateMask=${updateMask}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction extractUpdateFieldKeys(parameters: UpdateUniverseParameters): ReadonlyArray<string> {\n\treturn Object.keys(parameters).filter((key) => key !== \"universeId\");\n}\n\nfunction bodyValueFor(parameters: UpdateUniverseParameters, key: string): unknown {\n\tconst value = Reflect.get(parameters, key);\n\treturn value === undefined ? NULL_SENTINEL : value;\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst PER_MINUTE = 100;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for reading a universe, from the Open\n * Cloud OpenAPI schema (100 requests per minute per API key owner).\n */\nexport const GET_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"universes.get\",\n});\n\n/**\n * Per-second request ceiling for updating a universe, from the Open\n * Cloud OpenAPI schema (100 requests per minute per API key owner).\n * Keyed independently from {@link GET_OPERATION_LIMIT} so reads and\n * updates do not share a queue; upstream quota accounting is not\n * documented as shared and the conservative default is fewer\n * cross-method contention surprises.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"universes.update\",\n});\n\n/**\n * Scopes required to update a universe, sourced from `x-roblox-scopes`\n * on the `Cloud_UpdateUniverse` operation in the vendored OpenAPI schema.\n * `Cloud_GetUniverse` declares no scope, so the GET method intentionally\n * does not declare `requiredScopes` and a 401/403 there surfaces as a\n * generic ApiError.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\"universe:write\"]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isDateTimeString } from \"../../../internal/utils/is-date-time-string.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type {\n\tSocialLink,\n\tUniverse,\n\tUniverseAgeRating,\n\tUniverseOwner,\n\tUniverseVisibility,\n} from \"./types.ts\";\nimport type { AgeRatingWire, SocialLinkWire, UniverseWire, VisibilityWire } from \"./wire.ts\";\n\nconst VISIBILITY_MAP: Readonly<Record<VisibilityWire, UniverseVisibility>> = {\n\tPRIVATE: \"private\",\n\tPUBLIC: \"public\",\n\tVISIBILITY_UNSPECIFIED: \"unspecified\",\n};\n\nconst AGE_RATING_MAP: Readonly<Record<AgeRatingWire, UniverseAgeRating>> = {\n\tAGE_RATING_9_PLUS: \"9Plus\",\n\tAGE_RATING_13_PLUS: \"13Plus\",\n\tAGE_RATING_17_PLUS: \"17Plus\",\n\tAGE_RATING_ALL: \"all\",\n\tAGE_RATING_UNSPECIFIED: \"unspecified\",\n};\n\nconst MALFORMED_MESSAGE = \"Malformed universe response\";\n\ninterface ToUniverseArgs {\n\treadonly id: string;\n\treadonly body: UniverseWire;\n\treadonly owner: UniverseOwner;\n}\n\n/**\n * Parses a successful Open Cloud `Universe` response body into the\n * public {@link Universe} shape.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link Universe}, or\n * an {@link ApiError} when the body does not match the wire schema.\n */\nexport function parseUniverseResponse(response: HttpResponse): Result<Universe, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isUniverseWire(body)) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tconst ownerResult = resolveOwner(body);\n\tif (!ownerResult.success) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tconst idMatch = /^universes\\/(\\d+)$/.exec(body.path);\n\tconst id = idMatch?.[1];\n\tif (id === undefined) {\n\t\treturn malformed(statusCode);\n\t}\n\n\treturn { data: toUniverse({ id, body, owner: ownerResult.data }), success: true };\n}\n\nfunction malformed(statusCode: number): Result<Universe, ApiError> {\n\treturn {\n\t\terr: new ApiError(MALFORMED_MESSAGE, { statusCode }),\n\t\tsuccess: false,\n\t};\n}\n\nfunction extractRootPlaceId(rootPlace: string | undefined): string | undefined {\n\tif (rootPlace === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst match = /\\/places\\/(\\d+)$/.exec(rootPlace);\n\treturn match?.[1];\n}\n\nfunction toSocialLink(wire: SocialLinkWire | undefined): SocialLink | undefined {\n\tif (wire === undefined) {\n\t\treturn undefined;\n\t}\n\n\treturn { title: wire.title, uri: wire.uri };\n}\n\nfunction toUniverse(args: ToUniverseArgs): Universe {\n\tconst { id, body, owner } = args;\n\treturn {\n\t\tid,\n\t\tageRating: AGE_RATING_MAP[body.ageRating],\n\t\tconsoleEnabled: body.consoleEnabled ?? false,\n\t\tcreatedAt: new Date(body.createTime),\n\t\tdescription: body.description,\n\t\tdesktopEnabled: body.desktopEnabled ?? false,\n\t\tdiscordSocialLink: toSocialLink(body.discordSocialLink),\n\t\tdisplayName: body.displayName,\n\t\tfacebookSocialLink: toSocialLink(body.facebookSocialLink),\n\t\tguildedSocialLink: toSocialLink(body.guildedSocialLink),\n\t\tmobileEnabled: body.mobileEnabled ?? false,\n\t\towner,\n\t\tprivateServerPriceRobux: body.privateServerPriceRobux ?? undefined,\n\t\trobloxGroupSocialLink: toSocialLink(body.robloxGroupSocialLink),\n\t\trootPlaceId: extractRootPlaceId(body.rootPlace),\n\t\ttabletEnabled: body.tabletEnabled ?? false,\n\t\ttwitchSocialLink: toSocialLink(body.twitchSocialLink),\n\t\ttwitterSocialLink: toSocialLink(body.twitterSocialLink),\n\t\tupdatedAt: new Date(body.updateTime),\n\t\tvisibility: VISIBILITY_MAP[body.visibility],\n\t\tvoiceChatEnabled: body.voiceChatEnabled ?? false,\n\t\tvrEnabled: body.vrEnabled ?? false,\n\t\tyoutubeSocialLink: toSocialLink(body.youtubeSocialLink),\n\t};\n}\n\nfunction isVisibilityWire(value: unknown): value is VisibilityWire {\n\treturn value === \"PRIVATE\" || value === \"PUBLIC\" || value === \"VISIBILITY_UNSPECIFIED\";\n}\n\nfunction isAgeRatingWire(value: unknown): value is AgeRatingWire {\n\treturn (\n\t\tvalue === \"AGE_RATING_13_PLUS\" ||\n\t\tvalue === \"AGE_RATING_17_PLUS\" ||\n\t\tvalue === \"AGE_RATING_9_PLUS\" ||\n\t\tvalue === \"AGE_RATING_ALL\" ||\n\t\tvalue === \"AGE_RATING_UNSPECIFIED\"\n\t);\n}\n\nfunction hasValidRequiredFields(body: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof body[\"path\"] === \"string\" &&\n\t\tisDateTimeString(body[\"createTime\"]) &&\n\t\tisDateTimeString(body[\"updateTime\"]) &&\n\t\ttypeof body[\"displayName\"] === \"string\" &&\n\t\ttypeof body[\"description\"] === \"string\" &&\n\t\tisVisibilityWire(body[\"visibility\"]) &&\n\t\tisAgeRatingWire(body[\"ageRating\"])\n\t);\n}\n\nfunction isSocialLinkWire(value: unknown): value is SocialLinkWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn typeof value[\"title\"] === \"string\" && typeof value[\"uri\"] === \"string\";\n}\n\nfunction isOptionalSocialLink(value: unknown): boolean {\n\treturn value === undefined || value === null || isSocialLinkWire(value);\n}\n\nfunction isOptionalBoolean(value: unknown): boolean {\n\treturn value === undefined || value === null || typeof value === \"boolean\";\n}\n\nfunction hasValidOptionalFields(body: Record<string, unknown>): boolean {\n\tconst priceField = body[\"privateServerPriceRobux\"] ?? undefined;\n\tif (priceField !== undefined && typeof priceField !== \"number\") {\n\t\treturn false;\n\t}\n\n\tconst rootPlace = body[\"rootPlace\"] ?? undefined;\n\tif (rootPlace !== undefined && typeof rootPlace !== \"string\") {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tisOptionalBoolean(body[\"voiceChatEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"desktopEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"mobileEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"tabletEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"consoleEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"vrEnabled\"]) &&\n\t\tisOptionalSocialLink(body[\"facebookSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"twitterSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"youtubeSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"twitchSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"discordSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"robloxGroupSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"guildedSocialLink\"])\n\t);\n}\n\nfunction isUniverseWire(body: unknown): body is UniverseWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\treturn hasValidRequiredFields(body) && hasValidOptionalFields(body);\n}\n\nfunction extractOwnerId(resourcePath: string): string | undefined {\n\tconst match = /^(?:users|groups)\\/(\\d+)$/.exec(resourcePath);\n\treturn match?.[1];\n}\n\nfunction resolveOwner(body: UniverseWire): Result<UniverseOwner, undefined> {\n\tif (typeof body.user === \"string\") {\n\t\tconst id = extractOwnerId(body.user);\n\t\tif (id !== undefined) {\n\t\t\treturn { data: { id, kind: \"user\" }, success: true };\n\t\t}\n\t}\n\n\tif (typeof body.group === \"string\") {\n\t\tconst id = extractOwnerId(body.group);\n\t\tif (id !== undefined) {\n\t\t\treturn { data: { id, kind: \"group\" }, success: true };\n\t\t}\n\t}\n\n\treturn { err: undefined, success: false };\n}\n","// The legacy `{gameId}` URL segment is in fact the universe ID; the public API\n// takes `universeId` and substitutes it into the path.\n\nimport type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type {\n\tDeleteExperienceIconParameters,\n\tListExperienceIconsParameters,\n\tUploadExperienceIconParameters,\n} from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the localized \"upload experience icon\"\n * endpoint. A successful upload replaces any existing icon for the same\n * `(universeId, languageCode)` pair.\n *\n * @param parameters - Universe and language identifiers plus the image\n * bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(parameters: UploadExperienceIconParameters): HttpRequest {\n\tconst body = new FormData();\n\t// The legacy game-icon endpoint reads the upload from `request.files`.\n\tbody.append(\"request.files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}/language-codes/${parameters.languageCode}`,\n\t};\n}\n\n/**\n * Builds a `DELETE` request for the localized \"delete experience icon\"\n * endpoint. Removing the source-language icon is rejected server-side;\n * deleting the icon for a non-source language clears that translation.\n *\n * @param parameters - Universe and language identifiers of the icon to\n * delete.\n * @returns A pure {@link HttpRequest} describing the delete call.\n */\nexport function buildDeleteIconRequest(parameters: DeleteExperienceIconParameters): HttpRequest {\n\treturn {\n\t\tmethod: \"DELETE\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}/language-codes/${parameters.languageCode}`,\n\t};\n}\n\n/**\n * Builds a `GET` request for the \"list experience icons\" endpoint. The\n * server returns one entry per locale that has an icon registered.\n *\n * @param parameters - Universe identifier whose icons to list.\n * @returns A pure {@link HttpRequest} describing the list call.\n */\nexport function buildListIconsRequest(parameters: ListExperienceIconsParameters): HttpRequest {\n\treturn {\n\t\tmethod: \"GET\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every game-icon Operation bound on\n * `UniversesClient.icon`. The legacy `gameinternationalization` service caps\n * each API key at 100 requests per minute *shared across the entire service*\n * (see the `x-roblox-rate-limits` extension on every operation in the\n * vendored Open Cloud spec), so all methods queue against the same operation\n * key.\n */\nexport const ICON_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"experience-icon\",\n});\n\n/**\n * Scopes required for every game-icon operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` icon\n * endpoints in the vendored OpenAPI schema.\n */\nexport const ICON_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe:manage\",\n]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { ExperienceIcon } from \"./types.ts\";\nimport type { GameIconListWire, GameIconState, GetGameIconResponseWire } from \"./wire.ts\";\n\n/**\n * Parses a successful icon-list response into a public array of\n * {@link ExperienceIcon} entries.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the converted icon list, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseIconListResponse(\n\tresponse: HttpResponse,\n): Result<ReadonlyArray<ExperienceIcon>, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isGameIconListWire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed icon list response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: body.data.map(toExperienceIcon),\n\t\tsuccess: true,\n\t};\n}\n\nfunction isGameIconState(value: unknown): value is GameIconState {\n\treturn (\n\t\tvalue === \"Approved\" ||\n\t\tvalue === \"Error\" ||\n\t\tvalue === \"PendingReview\" ||\n\t\tvalue === \"Rejected\" ||\n\t\tvalue === \"UnAvailable\"\n\t);\n}\n\nfunction isGetGameIconResponseWire(value: unknown): value is GetGameIconResponseWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"imageId\"] === \"string\" &&\n\t\ttypeof value[\"imageUrl\"] === \"string\" &&\n\t\ttypeof value[\"languageCode\"] === \"string\" &&\n\t\tisGameIconState(value[\"state\"])\n\t);\n}\n\nfunction isGameIconListWire(body: unknown): body is GameIconListWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\tconst { data } = body;\n\tif (!Array.isArray(data)) {\n\t\treturn false;\n\t}\n\n\treturn data.every(isGetGameIconResponseWire);\n}\n\nfunction toExperienceIcon(wire: GetGameIconResponseWire): ExperienceIcon {\n\treturn {\n\t\timageId: wire.imageId,\n\t\timageUrl: wire.imageUrl,\n\t\tlanguageCode: wire.languageCode,\n\t\tstate: wire.state,\n\t};\n}\n","import { ValidationError } from \"../../../errors/validation.ts\";\nimport type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type {\n\tDeleteExperienceThumbnailParameters,\n\tReorderExperienceThumbnailsParameters,\n\tUploadExperienceThumbnailParameters,\n} from \"./types.ts\";\n\ntype ParsedIdsResult = Result<ReadonlyArray<number>, ValidationError>;\n\n/**\n * Builds a `POST` request for the localized \"upload experience thumbnail\"\n * endpoint. Each successful upload appends a new entry to the carousel.\n *\n * @param parameters - Universe and language identifiers plus the image\n * bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadThumbnailRequest(\n\tparameters: UploadExperienceThumbnailParameters,\n): HttpRequest {\n\tconst body = new FormData();\n\t// The legacy game-thumbnails endpoint reads the upload from\n\t// `gameThumbnailRequest.files`, distinct from game-icon's `request.files`.\n\tbody.append(\"gameThumbnailRequest.files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\t// The `{gameId}` URL segment in this legacy path is in fact the\n\t\t// universe ID; the package surfaces only `universeId`.\n\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${parameters.universeId}/language-codes/${parameters.languageCode}/image`,\n\t};\n}\n\n/**\n * Builds a `DELETE` request for the \"delete experience thumbnail\" endpoint.\n *\n * @param parameters - Universe, language, and image identifiers of the\n * thumbnail to delete.\n * @returns A pure {@link HttpRequest} describing the delete call.\n */\nexport function buildDeleteThumbnailRequest(\n\tparameters: DeleteExperienceThumbnailParameters,\n): HttpRequest {\n\treturn {\n\t\tmethod: \"DELETE\",\n\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${parameters.universeId}/language-codes/${parameters.languageCode}/images/${parameters.imageId}`,\n\t};\n}\n\n/**\n * Builds a `POST` request for the \"reorder experience thumbnails\" endpoint.\n * Validates each supplied image ID at the wire boundary so a typo cannot\n * silently serialize as JSON `null` and corrupt the request.\n *\n * @param parameters - Universe, language, and the desired display order.\n * @returns A success result wrapping the request, or a\n * {@link ValidationError} when `orderedImageIds` is empty or any ID is not\n * a positive integer within the safe-integer range.\n */\nexport function buildReorderThumbnailsRequest(\n\tparameters: ReorderExperienceThumbnailsParameters,\n): Result<HttpRequest, ValidationError> {\n\tconst { languageCode, orderedImageIds, universeId } = parameters;\n\n\tconst idsResult = parseOrderedImageIds(orderedImageIds);\n\tif (!idsResult.success) {\n\t\treturn idsResult;\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tbody: { mediaAssetIds: idsResult.data },\n\t\t\tmethod: \"POST\",\n\t\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${universeId}/language-codes/${languageCode}/images/order`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction parseImageId(value: string): number | undefined {\n\tif (!/^[1-9]\\d*$/.test(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst parsed = Number(value);\n\tif (!Number.isSafeInteger(parsed)) {\n\t\treturn undefined;\n\t}\n\n\treturn parsed;\n}\n\nfunction appendParsedId(accumulator: ParsedIdsResult, id: string): ParsedIdsResult {\n\tif (!accumulator.success) {\n\t\treturn accumulator;\n\t}\n\n\tconst parsed = parseImageId(id);\n\tif (parsed === undefined) {\n\t\treturn {\n\t\t\terr: new ValidationError(\n\t\t\t\t`orderedImageIds entry ${JSON.stringify(id)} is not a positive integer ID`,\n\t\t\t\t{ code: \"invalid_image_id\" },\n\t\t\t),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn { data: [...accumulator.data, parsed], success: true };\n}\n\nfunction parseOrderedImageIds(orderedImageIds: ReadonlyArray<string>): ParsedIdsResult {\n\tif (orderedImageIds.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"orderedImageIds must contain at least one image ID\", {\n\t\t\t\tcode: \"empty_image_ids\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn orderedImageIds.reduce<ParsedIdsResult>(appendParsedId, { data: [], success: true });\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every game-thumbnails Operation bound on\n * `UniversesClient.thumbnails`. The legacy `gameinternationalization`\n * service caps each API key at 100 requests per minute *shared across the\n * entire service* (see the `x-roblox-rate-limits` extension on every\n * operation in the vendored Open Cloud spec), so all methods queue against\n * the same operation key.\n */\nexport const THUMBNAILS_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"experience-thumbnails\",\n});\n\n/**\n * Scopes required for every game-thumbnails operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` thumbnail\n * endpoints in the vendored OpenAPI schema.\n */\nexport const THUMBNAILS_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe:manage\",\n]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { UploadedExperienceThumbnail } from \"./types.ts\";\nimport type { GameThumbnailUploadWire } from \"./wire.ts\";\n\n/**\n * Parses a successful thumbnail-upload response into the public\n * {@link UploadedExperienceThumbnail} shape, returning a {@link Result}\n * so callers can handle malformed payloads without exceptions.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the converted upload, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseThumbnailUploadResponse(\n\tresponse: HttpResponse,\n): Result<UploadedExperienceThumbnail, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isGameThumbnailUploadWire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed thumbnail upload response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: { mediaAssetId: body.mediaAssetId },\n\t\tsuccess: true,\n\t};\n}\n\nfunction isGameThumbnailUploadWire(body: unknown): body is GameThumbnailUploadWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\treturn typeof body[\"mediaAssetId\"] === \"string\";\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildGetRequest, buildUpdateRequest } from \"../../domains/cloud-v2/universes/builders.ts\";\nimport {\n\tGET_OPERATION_LIMIT,\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/universes/operations.ts\";\nimport { parseUniverseResponse } from \"../../domains/cloud-v2/universes/parsers.ts\";\nimport type {\n\tGetUniverseParameters,\n\tUniverse,\n\tUpdateUniverseParameters,\n} from \"../../domains/cloud-v2/universes/types.ts\";\nimport {\n\tbuildDeleteIconRequest,\n\tbuildListIconsRequest,\n\tbuildUploadIconRequest,\n} from \"../../domains/game-internationalization/game-icon/builders.ts\";\nimport {\n\tICON_OPERATION_LIMIT,\n\tICON_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/game-icon/operations.ts\";\nimport { parseIconListResponse } from \"../../domains/game-internationalization/game-icon/parsers.ts\";\nimport type {\n\tDeleteExperienceIconParameters,\n\tExperienceIcon,\n\tListExperienceIconsParameters,\n\tUploadExperienceIconParameters,\n} from \"../../domains/game-internationalization/game-icon/types.ts\";\nimport {\n\tbuildDeleteThumbnailRequest,\n\tbuildReorderThumbnailsRequest,\n\tbuildUploadThumbnailRequest,\n} from \"../../domains/game-internationalization/game-thumbnails/builders.ts\";\nimport {\n\tTHUMBNAILS_OPERATION_LIMIT,\n\tTHUMBNAILS_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/game-thumbnails/operations.ts\";\nimport { parseThumbnailUploadResponse } from \"../../domains/game-internationalization/game-thumbnails/parsers.ts\";\nimport type {\n\tDeleteExperienceThumbnailParameters,\n\tReorderExperienceThumbnailsParameters,\n\tUploadedExperienceThumbnail,\n\tUploadExperienceThumbnailParameters,\n} from \"../../domains/game-internationalization/game-thumbnails/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS, IDEMPOTENT_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport type { HttpRequest } from \"../../internal/http/types.ts\";\nimport {\n\tokRequest,\n\tparseEmptyResponse,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\n\nconst GET_SPEC: ResourceMethodSpec<GetUniverseParameters, Universe> = Object.freeze({\n\tbuildRequest: buildGetRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: GET_OPERATION_LIMIT,\n\tparse: parseUniverseResponse,\n});\n\nconst UPDATE_SPEC: ResourceMethodSpec<UpdateUniverseParameters, Universe> = Object.freeze({\n\tbuildRequest: buildUpdateRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parseUniverseResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\nfunction buildIconUploadOkRequest(\n\tparameters: UploadExperienceIconParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildUploadIconRequest(parameters));\n}\n\nfunction buildIconDeleteOkRequest(\n\tparameters: DeleteExperienceIconParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildDeleteIconRequest(parameters));\n}\n\nfunction buildIconListOkRequest(\n\tparameters: ListExperienceIconsParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildListIconsRequest(parameters));\n}\n\nconst ICON_UPLOAD_SPEC: ResourceMethodSpec<UploadExperienceIconParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildIconUploadOkRequest,\n\t\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\t\tmethodKind: \"create\",\n\t\toperationLimit: ICON_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: ICON_REQUIRED_SCOPES,\n\t});\n\nconst ICON_DELETE_SPEC: ResourceMethodSpec<DeleteExperienceIconParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildIconDeleteOkRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: ICON_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: ICON_REQUIRED_SCOPES,\n\t});\n\nconst ICON_LIST_SPEC: ResourceMethodSpec<\n\tListExperienceIconsParameters,\n\tReadonlyArray<ExperienceIcon>\n> = Object.freeze({\n\tbuildRequest: buildIconListOkRequest,\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: ICON_OPERATION_LIMIT,\n\tparse: parseIconListResponse,\n\trequiredScopes: ICON_REQUIRED_SCOPES,\n});\n\nfunction buildThumbnailUploadOkRequest(\n\tparameters: UploadExperienceThumbnailParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildUploadThumbnailRequest(parameters));\n}\n\nfunction buildThumbnailDeleteOkRequest(\n\tparameters: DeleteExperienceThumbnailParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildDeleteThumbnailRequest(parameters));\n}\n\nconst THUMBNAIL_UPLOAD_SPEC: ResourceMethodSpec<\n\tUploadExperienceThumbnailParameters,\n\tUploadedExperienceThumbnail\n> = Object.freeze({\n\tbuildRequest: buildThumbnailUploadOkRequest,\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\tparse: parseThumbnailUploadResponse,\n\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n});\n\nconst THUMBNAIL_DELETE_SPEC: ResourceMethodSpec<DeleteExperienceThumbnailParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildThumbnailDeleteOkRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n\t});\n\nconst THUMBNAIL_REORDER_SPEC: ResourceMethodSpec<ReorderExperienceThumbnailsParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildReorderThumbnailsRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n\t});\n\ninterface UniverseIconHandle {\n\t/**\n\t * Deletes the localized icon registered against a universe for a given\n\t * language. Removing the source-language icon is rejected server-side;\n\t * consumers must replace it via {@link UniverseIconHandle.upload}\n\t * instead.\n\t *\n\t * @param parameters - Universe and language identifiers of the icon to\n\t * delete.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tdelete: (\n\t\tparameters: DeleteExperienceIconParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Lists every localized icon registered against an experience. The\n\t * server returns one entry per locale that has an icon registered.\n\t *\n\t * @param parameters - Universe identifier whose icons to list.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed array of\n\t * {@link ExperienceIcon} entries or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tlist: (\n\t\tparameters: ListExperienceIconsParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<ReadonlyArray<ExperienceIcon>, OpenCloudError>>;\n\t/**\n\t * Uploads or replaces the localized icon for an experience. A\n\t * subsequent upload for the same `(universeId, languageCode)` pair\n\t * replaces the existing icon for that locale.\n\t *\n\t * @param parameters - Universe and language identifiers plus the image\n\t * bytes to upload.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tupload: (\n\t\tparameters: UploadExperienceIconParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n}\n\ninterface UniverseThumbnailsHandle {\n\t/**\n\t * Deletes a single thumbnail by media asset ID. Idempotent: deleting an\n\t * already-removed thumbnail surfaces the server's 404 unchanged.\n\t *\n\t * @param parameters - Universe, language, and image identifiers of the\n\t * thumbnail to delete.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tdelete: (\n\t\tparameters: DeleteExperienceThumbnailParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Reorders the localized thumbnail carousel. The supplied\n\t * `orderedImageIds` describes the desired display order from first to\n\t * last. Image IDs must be positive integers within the safe-integer\n\t * range; invalid input is rejected with a {@link OpenCloudError} of\n\t * kind `ValidationError` before any HTTP round-trip.\n\t *\n\t * @param parameters - Universe, language, and the desired display order.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\treorder: (\n\t\tparameters: ReorderExperienceThumbnailsParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Uploads a new thumbnail and appends it to the localized carousel. Use\n\t * {@link UniverseThumbnailsHandle.reorder} after multiple uploads to\n\t * set the display order.\n\t *\n\t * @param parameters - Universe and language identifiers plus the image\n\t * bytes to upload.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed\n\t * {@link UploadedExperienceThumbnail} or the {@link OpenCloudError}\n\t * that caused the request to fail.\n\t */\n\tupload: (\n\t\tparameters: UploadExperienceThumbnailParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<UploadedExperienceThumbnail, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud `Universe` resource. Wires\n * the request builders, the injected\n * {@link OpenCloudClientOptions.httpClient}, and the response parser\n * into a single ergonomic surface. Every method returns a\n * {@link Result} so callers handle failure explicitly; no thrown\n * {@link OpenCloudError} ever escapes the client.\n *\n * Partial updates use a Google-style `updateMask` query string derived\n * from the keys present on the update parameters. Setting a clearable\n * field (`privateServerPriceRobux` or any social link) to `undefined`\n * sends JSON `null` for that field so the server clears the\n * corresponding value.\n *\n * Localized experience-icon and experience-thumbnail Operations are\n * bound on the {@link UniversesClient.icon} and\n * {@link UniversesClient.thumbnails} Operation Groups so callers reach\n * for one client per universe.\n *\n * @example\n *\n * ```ts\n * import { UniversesClient } from \"@bedrock-rbx/ocale/universes\";\n *\n * const client = new UniversesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(UniversesClient);\n * ```\n */\nexport class UniversesClient {\n\treadonly #inner: ResourceClient;\n\n\t/**\n\t * Operation Group exposing the localized experience-icon\n\t * Operations (`upload`, `delete`, `list`) backed by the\n\t * `legacy-game-internationalization` domain. Shares the parent\n\t * client's HTTP, rate-limit, and retry plumbing.\n\t */\n\tpublic readonly icon: UniverseIconHandle;\n\t/**\n\t * Operation Group exposing the localized experience-thumbnail\n\t * Operations (`upload`, `delete`, `reorder`) backed by the\n\t * `legacy-game-internationalization` domain. No list-thumbnails\n\t * endpoint is bridged; consumers must track uploaded\n\t * `mediaAssetId`s in their own state store to reconcile against\n\t * the existing carousel. Shares the parent client's HTTP,\n\t * rate-limit, and retry plumbing.\n\t */\n\tpublic readonly thumbnails: UniverseThumbnailsHandle;\n\n\t/**\n\t * Creates a new {@link UniversesClient}. Configuration is frozen\n\t * on construction; per-request overrides are accepted on each\n\t * method.\n\t *\n\t * @param options - Client-level configuration including the API key.\n\t */\n\tconstructor(options: OpenCloudClientOptions) {\n\t\tthis.#inner = new ResourceClient(options);\n\t\tthis.icon = createIconHandle(this.#inner);\n\t\tthis.thumbnails = createThumbnailsHandle(this.#inner);\n\t}\n\n\t/**\n\t * Fetches the current configuration of a universe.\n\t *\n\t * @param parameters - The universe identifier.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed {@link Universe}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async get(\n\t\tparameters: GetUniverseParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Universe, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: GET_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a universe's configuration. The fields\n\t * supplied on `parameters` (excluding `universeId`) are forwarded\n\t * to the server via a Google-style `updateMask`; unmentioned\n\t * fields are left untouched.\n\t *\n\t * @param parameters - The universe identifier and the fields to\n\t * update. At least one updatable field must be supplied.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed {@link Universe}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdateUniverseParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Universe, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n}\n\nfunction createIconHandle(inner: ResourceClient): UniverseIconHandle {\n\treturn {\n\t\tasync delete(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_DELETE_SPEC });\n\t\t},\n\t\tasync list(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_LIST_SPEC });\n\t\t},\n\t\tasync upload(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_UPLOAD_SPEC });\n\t\t},\n\t};\n}\n\nfunction createThumbnailsHandle(inner: ResourceClient): UniverseThumbnailsHandle {\n\treturn {\n\t\tasync delete(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_DELETE_SPEC });\n\t\t},\n\t\tasync reorder(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_REORDER_SPEC });\n\t\t},\n\t\tasync upload(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_UPLOAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"universes.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/universes/builders.ts","../src/domains/cloud-v2/universes/operations.ts","../src/domains/cloud-v2/universes/parsers.ts","../src/domains/game-internationalization/game-icon/builders.ts","../src/domains/game-internationalization/game-icon/operations.ts","../src/domains/game-internationalization/game-icon/parsers.ts","../src/domains/game-internationalization/game-thumbnails/builders.ts","../src/domains/game-internationalization/game-thumbnails/operations.ts","../src/domains/game-internationalization/game-thumbnails/parsers.ts","../src/resources/universes/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport type { OpenCloudError } from \"../../../errors/base.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport { okRequest } from \"../../../internal/resource-client.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { GetUniverseParameters, UpdateUniverseParameters } from \"./types.ts\";\n\n/**\n * Dodges `unicorn/no-null` while still emitting a literal `null` onto\n * the wire, which the Open Cloud `Cloud_UpdateUniverse` endpoint\n * requires to clear a nullable field (for example disabling private\n * servers or removing a social link).\n */\nconst NULL_SENTINEL = JSON.parse(\"null\");\n\n/**\n * Builds a `GET` request for the Open Cloud \"get universe\" endpoint.\n *\n * @param parameters - The universe identifier.\n * @returns A success result wrapping the request; the builder cannot fail.\n */\nexport function buildGetRequest(\n\tparameters: GetUniverseParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest({\n\t\tmethod: \"GET\",\n\t\turl: `/cloud/v2/universes/${parameters.universeId}`,\n\t});\n}\n\n/**\n * Builds a `PATCH` request for the Open Cloud \"update universe\"\n * endpoint. Derives the `updateMask` query string from the keys\n * present on `parameters` and emits a JSON body containing those same\n * fields, translating `undefined` values to JSON `null` so Roblox\n * clears the corresponding server-side value.\n *\n * @param parameters - The universe identifier plus the fields to update.\n * @returns A success result wrapping the request, or a\n * {@link ValidationError} when no updatable fields were supplied.\n */\nexport function buildUpdateRequest(\n\tparameters: UpdateUniverseParameters,\n): Result<HttpRequest, ValidationError> {\n\tconst fieldKeys = extractUpdateFieldKeys(parameters);\n\n\tif (fieldKeys.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"Update must include at least one field\", {\n\t\t\t\tcode: \"empty_update\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\tconst body: Record<string, unknown> = {};\n\tfor (const key of fieldKeys) {\n\t\tbody[key] = bodyValueFor(parameters, key);\n\t}\n\n\tconst updateMask = fieldKeys.join(\",\");\n\treturn {\n\t\tdata: {\n\t\t\tbody,\n\t\t\theaders: { \"content-type\": \"application/json\" },\n\t\t\tmethod: \"PATCH\",\n\t\t\turl: `/cloud/v2/universes/${parameters.universeId}?updateMask=${updateMask}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction extractUpdateFieldKeys(parameters: UpdateUniverseParameters): ReadonlyArray<string> {\n\treturn Object.keys(parameters).filter((key) => key !== \"universeId\");\n}\n\nfunction bodyValueFor(parameters: UpdateUniverseParameters, key: string): unknown {\n\tconst value = Reflect.get(parameters, key);\n\treturn value === undefined ? NULL_SENTINEL : value;\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst PER_MINUTE = 100;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for reading a universe, from the Open\n * Cloud OpenAPI schema (100 requests per minute per API key owner).\n */\nexport const GET_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"universes.get\",\n});\n\n/**\n * Per-second request ceiling for updating a universe, from the Open\n * Cloud OpenAPI schema (100 requests per minute per API key owner).\n * Keyed independently from {@link GET_OPERATION_LIMIT} so reads and\n * updates do not share a queue; upstream quota accounting is not\n * documented as shared and the conservative default is fewer\n * cross-method contention surprises.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"universes.update\",\n});\n\n/**\n * Scopes required to update a universe, sourced from `x-roblox-scopes`\n * on the `Cloud_UpdateUniverse` operation in the vendored OpenAPI schema.\n * `Cloud_GetUniverse` declares no scope, so the GET method intentionally\n * does not declare `requiredScopes` and a 401/403 there surfaces as a\n * generic ApiError.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\"universe:write\"]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isDateTimeString } from \"../../../internal/utils/is-date-time-string.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type {\n\tSocialLink,\n\tUniverse,\n\tUniverseAgeRating,\n\tUniverseOwner,\n\tUniverseVisibility,\n} from \"./types.ts\";\nimport type { AgeRatingWire, SocialLinkWire, UniverseWire, VisibilityWire } from \"./wire.ts\";\n\nconst VISIBILITY_MAP: Readonly<Record<VisibilityWire, UniverseVisibility>> = {\n\tPRIVATE: \"private\",\n\tPUBLIC: \"public\",\n\tVISIBILITY_UNSPECIFIED: \"unspecified\",\n};\n\nconst AGE_RATING_MAP: Readonly<Record<AgeRatingWire, UniverseAgeRating>> = {\n\tAGE_RATING_9_PLUS: \"9Plus\",\n\tAGE_RATING_13_PLUS: \"13Plus\",\n\tAGE_RATING_17_PLUS: \"17Plus\",\n\tAGE_RATING_ALL: \"all\",\n\tAGE_RATING_UNSPECIFIED: \"unspecified\",\n};\n\nconst MALFORMED_MESSAGE = \"Malformed universe response\";\n\ninterface ToUniverseArgs {\n\treadonly id: string;\n\treadonly body: UniverseWire;\n\treadonly owner: UniverseOwner;\n}\n\n/**\n * Parses a successful Open Cloud `Universe` response body into the\n * public {@link Universe} shape.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link Universe}, or\n * an {@link ApiError} when the body does not match the wire schema.\n */\nexport function parseUniverseResponse(response: HttpResponse): Result<Universe, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isUniverseWire(body)) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tconst ownerResult = resolveOwner(body);\n\tif (!ownerResult.success) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tconst idMatch = /^universes\\/(\\d+)$/.exec(body.path);\n\tconst id = idMatch?.[1];\n\tif (id === undefined) {\n\t\treturn malformed(statusCode);\n\t}\n\n\treturn { data: toUniverse({ id, body, owner: ownerResult.data }), success: true };\n}\n\nfunction malformed(statusCode: number): Result<Universe, ApiError> {\n\treturn {\n\t\terr: new ApiError(MALFORMED_MESSAGE, { statusCode }),\n\t\tsuccess: false,\n\t};\n}\n\nfunction extractRootPlaceId(rootPlace: string | undefined): string | undefined {\n\tif (rootPlace === undefined) {\n\t\treturn undefined;\n\t}\n\n\tconst match = /\\/places\\/(\\d+)$/.exec(rootPlace);\n\treturn match?.[1];\n}\n\nfunction toSocialLink(wire: SocialLinkWire | undefined): SocialLink | undefined {\n\tif (wire === undefined) {\n\t\treturn undefined;\n\t}\n\n\treturn { title: wire.title, uri: wire.uri };\n}\n\nfunction toUniverse(args: ToUniverseArgs): Universe {\n\tconst { id, body, owner } = args;\n\treturn {\n\t\tid,\n\t\tageRating: AGE_RATING_MAP[body.ageRating],\n\t\tconsoleEnabled: body.consoleEnabled ?? false,\n\t\tcreatedAt: new Date(body.createTime),\n\t\tdescription: body.description,\n\t\tdesktopEnabled: body.desktopEnabled ?? false,\n\t\tdiscordSocialLink: toSocialLink(body.discordSocialLink),\n\t\tdisplayName: body.displayName,\n\t\tfacebookSocialLink: toSocialLink(body.facebookSocialLink),\n\t\tguildedSocialLink: toSocialLink(body.guildedSocialLink),\n\t\tmobileEnabled: body.mobileEnabled ?? false,\n\t\towner,\n\t\tprivateServerPriceRobux: body.privateServerPriceRobux ?? undefined,\n\t\trobloxGroupSocialLink: toSocialLink(body.robloxGroupSocialLink),\n\t\trootPlaceId: extractRootPlaceId(body.rootPlace),\n\t\ttabletEnabled: body.tabletEnabled ?? false,\n\t\ttwitchSocialLink: toSocialLink(body.twitchSocialLink),\n\t\ttwitterSocialLink: toSocialLink(body.twitterSocialLink),\n\t\tupdatedAt: new Date(body.updateTime),\n\t\tvisibility: VISIBILITY_MAP[body.visibility],\n\t\tvoiceChatEnabled: body.voiceChatEnabled ?? false,\n\t\tvrEnabled: body.vrEnabled ?? false,\n\t\tyoutubeSocialLink: toSocialLink(body.youtubeSocialLink),\n\t};\n}\n\nfunction isVisibilityWire(value: unknown): value is VisibilityWire {\n\treturn value === \"PRIVATE\" || value === \"PUBLIC\" || value === \"VISIBILITY_UNSPECIFIED\";\n}\n\nfunction isAgeRatingWire(value: unknown): value is AgeRatingWire {\n\treturn (\n\t\tvalue === \"AGE_RATING_13_PLUS\" ||\n\t\tvalue === \"AGE_RATING_17_PLUS\" ||\n\t\tvalue === \"AGE_RATING_9_PLUS\" ||\n\t\tvalue === \"AGE_RATING_ALL\" ||\n\t\tvalue === \"AGE_RATING_UNSPECIFIED\"\n\t);\n}\n\nfunction hasValidRequiredFields(body: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof body[\"path\"] === \"string\" &&\n\t\tisDateTimeString(body[\"createTime\"]) &&\n\t\tisDateTimeString(body[\"updateTime\"]) &&\n\t\ttypeof body[\"displayName\"] === \"string\" &&\n\t\ttypeof body[\"description\"] === \"string\" &&\n\t\tisVisibilityWire(body[\"visibility\"]) &&\n\t\tisAgeRatingWire(body[\"ageRating\"])\n\t);\n}\n\nfunction isSocialLinkWire(value: unknown): value is SocialLinkWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn typeof value[\"title\"] === \"string\" && typeof value[\"uri\"] === \"string\";\n}\n\nfunction isOptionalSocialLink(value: unknown): boolean {\n\treturn value === undefined || value === null || isSocialLinkWire(value);\n}\n\nfunction isOptionalBoolean(value: unknown): boolean {\n\treturn value === undefined || value === null || typeof value === \"boolean\";\n}\n\nfunction hasValidOptionalFields(body: Record<string, unknown>): boolean {\n\tconst priceField = body[\"privateServerPriceRobux\"] ?? undefined;\n\tif (priceField !== undefined && typeof priceField !== \"number\") {\n\t\treturn false;\n\t}\n\n\tconst rootPlace = body[\"rootPlace\"] ?? undefined;\n\tif (rootPlace !== undefined && typeof rootPlace !== \"string\") {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\tisOptionalBoolean(body[\"voiceChatEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"desktopEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"mobileEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"tabletEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"consoleEnabled\"]) &&\n\t\tisOptionalBoolean(body[\"vrEnabled\"]) &&\n\t\tisOptionalSocialLink(body[\"facebookSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"twitterSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"youtubeSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"twitchSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"discordSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"robloxGroupSocialLink\"]) &&\n\t\tisOptionalSocialLink(body[\"guildedSocialLink\"])\n\t);\n}\n\nfunction isUniverseWire(body: unknown): body is UniverseWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\treturn hasValidRequiredFields(body) && hasValidOptionalFields(body);\n}\n\nfunction extractOwnerId(resourcePath: string): string | undefined {\n\tconst match = /^(?:users|groups)\\/(\\d+)$/.exec(resourcePath);\n\treturn match?.[1];\n}\n\nfunction resolveOwner(body: UniverseWire): Result<UniverseOwner, undefined> {\n\tif (typeof body.user === \"string\") {\n\t\tconst id = extractOwnerId(body.user);\n\t\tif (id !== undefined) {\n\t\t\treturn { data: { id, kind: \"user\" }, success: true };\n\t\t}\n\t}\n\n\tif (typeof body.group === \"string\") {\n\t\tconst id = extractOwnerId(body.group);\n\t\tif (id !== undefined) {\n\t\t\treturn { data: { id, kind: \"group\" }, success: true };\n\t\t}\n\t}\n\n\treturn { err: undefined, success: false };\n}\n","// The legacy `{gameId}` URL segment is in fact the universe ID; the public API\n// takes `universeId` and substitutes it into the path.\n\nimport type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type {\n\tDeleteExperienceIconParameters,\n\tListExperienceIconsParameters,\n\tUploadExperienceIconParameters,\n} from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the localized \"upload experience icon\"\n * endpoint. A successful upload replaces any existing icon for the same\n * `(universeId, languageCode)` pair.\n *\n * @param parameters - Universe and language identifiers plus the image\n * bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(parameters: UploadExperienceIconParameters): HttpRequest {\n\tconst body = new FormData();\n\t// The legacy game-icon endpoint reads the upload from `request.files`.\n\tbody.append(\"request.files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}/language-codes/${parameters.languageCode}`,\n\t};\n}\n\n/**\n * Builds a `DELETE` request for the localized \"delete experience icon\"\n * endpoint. Removing the source-language icon is rejected server-side;\n * deleting the icon for a non-source language clears that translation.\n *\n * @param parameters - Universe and language identifiers of the icon to\n * delete.\n * @returns A pure {@link HttpRequest} describing the delete call.\n */\nexport function buildDeleteIconRequest(parameters: DeleteExperienceIconParameters): HttpRequest {\n\treturn {\n\t\tmethod: \"DELETE\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}/language-codes/${parameters.languageCode}`,\n\t};\n}\n\n/**\n * Builds a `GET` request for the \"list experience icons\" endpoint. The\n * server returns one entry per locale that has an icon registered.\n *\n * @param parameters - Universe identifier whose icons to list.\n * @returns A pure {@link HttpRequest} describing the list call.\n */\nexport function buildListIconsRequest(parameters: ListExperienceIconsParameters): HttpRequest {\n\treturn {\n\t\tmethod: \"GET\",\n\t\turl: `/legacy-game-internationalization/v1/game-icon/games/${parameters.universeId}`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every game-icon Operation bound on\n * `UniversesClient.icon`. The legacy `gameinternationalization` service caps\n * each API key at 100 requests per minute *shared across the entire service*\n * (see the `x-roblox-rate-limits` extension on every operation in the\n * vendored Open Cloud spec), so all methods queue against the same operation\n * key.\n */\nexport const ICON_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"experience-icon\",\n});\n\n/**\n * Scopes required for every game-icon operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` icon\n * endpoints in the vendored OpenAPI schema.\n */\nexport const ICON_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe:manage\",\n]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { ExperienceIcon } from \"./types.ts\";\nimport type { GameIconListWire, GameIconState, GetGameIconResponseWire } from \"./wire.ts\";\n\n/**\n * Parses a successful icon-list response into a public array of\n * {@link ExperienceIcon} entries.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the converted icon list, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseIconListResponse(\n\tresponse: HttpResponse,\n): Result<ReadonlyArray<ExperienceIcon>, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isGameIconListWire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed icon list response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: body.data.map(toExperienceIcon),\n\t\tsuccess: true,\n\t};\n}\n\nfunction isGameIconState(value: unknown): value is GameIconState {\n\treturn (\n\t\tvalue === \"Approved\" ||\n\t\tvalue === \"Error\" ||\n\t\tvalue === \"PendingReview\" ||\n\t\tvalue === \"Rejected\" ||\n\t\tvalue === \"UnAvailable\"\n\t);\n}\n\nfunction isGetGameIconResponseWire(value: unknown): value is GetGameIconResponseWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"imageId\"] === \"string\" &&\n\t\ttypeof value[\"imageUrl\"] === \"string\" &&\n\t\ttypeof value[\"languageCode\"] === \"string\" &&\n\t\tisGameIconState(value[\"state\"])\n\t);\n}\n\nfunction isGameIconListWire(body: unknown): body is GameIconListWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\tconst { data } = body;\n\tif (!Array.isArray(data)) {\n\t\treturn false;\n\t}\n\n\treturn data.every(isGetGameIconResponseWire);\n}\n\nfunction toExperienceIcon(wire: GetGameIconResponseWire): ExperienceIcon {\n\treturn {\n\t\timageId: wire.imageId,\n\t\timageUrl: wire.imageUrl,\n\t\tlanguageCode: wire.languageCode,\n\t\tstate: wire.state,\n\t};\n}\n","import { ValidationError } from \"../../../errors/validation.ts\";\nimport type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type {\n\tDeleteExperienceThumbnailParameters,\n\tReorderExperienceThumbnailsParameters,\n\tUploadExperienceThumbnailParameters,\n} from \"./types.ts\";\n\ntype ParsedIdsResult = Result<ReadonlyArray<number>, ValidationError>;\n\n/**\n * Builds a `POST` request for the localized \"upload experience thumbnail\"\n * endpoint. Each successful upload appends a new entry to the carousel.\n *\n * @param parameters - Universe and language identifiers plus the image\n * bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadThumbnailRequest(\n\tparameters: UploadExperienceThumbnailParameters,\n): HttpRequest {\n\tconst body = new FormData();\n\t// The legacy game-thumbnails endpoint reads the upload from\n\t// `gameThumbnailRequest.files`, distinct from game-icon's `request.files`.\n\tbody.append(\"gameThumbnailRequest.files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\t// The `{gameId}` URL segment in this legacy path is in fact the\n\t\t// universe ID; the package surfaces only `universeId`.\n\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${parameters.universeId}/language-codes/${parameters.languageCode}/image`,\n\t};\n}\n\n/**\n * Builds a `DELETE` request for the \"delete experience thumbnail\" endpoint.\n *\n * @param parameters - Universe, language, and image identifiers of the\n * thumbnail to delete.\n * @returns A pure {@link HttpRequest} describing the delete call.\n */\nexport function buildDeleteThumbnailRequest(\n\tparameters: DeleteExperienceThumbnailParameters,\n): HttpRequest {\n\treturn {\n\t\tmethod: \"DELETE\",\n\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${parameters.universeId}/language-codes/${parameters.languageCode}/images/${parameters.imageId}`,\n\t};\n}\n\n/**\n * Builds a `POST` request for the \"reorder experience thumbnails\" endpoint.\n * Validates each supplied image ID at the wire boundary so a typo cannot\n * silently serialize as JSON `null` and corrupt the request.\n *\n * @param parameters - Universe, language, and the desired display order.\n * @returns A success result wrapping the request, or a\n * {@link ValidationError} when `orderedImageIds` is empty or any ID is not\n * a positive integer within the safe-integer range.\n */\nexport function buildReorderThumbnailsRequest(\n\tparameters: ReorderExperienceThumbnailsParameters,\n): Result<HttpRequest, ValidationError> {\n\tconst { languageCode, orderedImageIds, universeId } = parameters;\n\n\tconst idsResult = parseOrderedImageIds(orderedImageIds);\n\tif (!idsResult.success) {\n\t\treturn idsResult;\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tbody: { mediaAssetIds: idsResult.data },\n\t\t\tmethod: \"POST\",\n\t\t\turl: `/legacy-game-internationalization/v1/game-thumbnails/games/${universeId}/language-codes/${languageCode}/images/order`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction parseImageId(value: string): number | undefined {\n\tif (!/^[1-9]\\d*$/.test(value)) {\n\t\treturn undefined;\n\t}\n\n\tconst parsed = Number(value);\n\tif (!Number.isSafeInteger(parsed)) {\n\t\treturn undefined;\n\t}\n\n\treturn parsed;\n}\n\nfunction appendParsedId(accumulator: ParsedIdsResult, id: string): ParsedIdsResult {\n\tif (!accumulator.success) {\n\t\treturn accumulator;\n\t}\n\n\tconst parsed = parseImageId(id);\n\tif (parsed === undefined) {\n\t\treturn {\n\t\t\terr: new ValidationError(\n\t\t\t\t`orderedImageIds entry ${JSON.stringify(id)} is not a positive integer ID`,\n\t\t\t\t{ code: \"invalid_image_id\" },\n\t\t\t),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn { data: [...accumulator.data, parsed], success: true };\n}\n\nfunction parseOrderedImageIds(orderedImageIds: ReadonlyArray<string>): ParsedIdsResult {\n\tif (orderedImageIds.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"orderedImageIds must contain at least one image ID\", {\n\t\t\t\tcode: \"empty_image_ids\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn orderedImageIds.reduce<ParsedIdsResult>(appendParsedId, { data: [], success: true });\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every game-thumbnails Operation bound on\n * `UniversesClient.thumbnails`. The legacy `gameinternationalization`\n * service caps each API key at 100 requests per minute *shared across the\n * entire service* (see the `x-roblox-rate-limits` extension on every\n * operation in the vendored Open Cloud spec), so all methods queue against\n * the same operation key.\n */\nexport const THUMBNAILS_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"experience-thumbnails\",\n});\n\n/**\n * Scopes required for every game-thumbnails operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` thumbnail\n * endpoints in the vendored OpenAPI schema.\n */\nexport const THUMBNAILS_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe:manage\",\n]);\n","import type { HttpResponse } from \"../../../client/types.ts\";\nimport { ApiError } from \"../../../errors/api-error.ts\";\nimport { isRecord } from \"../../../internal/utils/is-record.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { UploadedExperienceThumbnail } from \"./types.ts\";\nimport type { GameThumbnailUploadWire } from \"./wire.ts\";\n\n/**\n * Parses a successful thumbnail-upload response into the public\n * {@link UploadedExperienceThumbnail} shape, returning a {@link Result}\n * so callers can handle malformed payloads without exceptions.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the converted upload, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseThumbnailUploadResponse(\n\tresponse: HttpResponse,\n): Result<UploadedExperienceThumbnail, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isGameThumbnailUploadWire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed thumbnail upload response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: { mediaAssetId: body.mediaAssetId },\n\t\tsuccess: true,\n\t};\n}\n\nfunction isGameThumbnailUploadWire(body: unknown): body is GameThumbnailUploadWire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\treturn typeof body[\"mediaAssetId\"] === \"string\";\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildGetRequest, buildUpdateRequest } from \"../../domains/cloud-v2/universes/builders.ts\";\nimport {\n\tGET_OPERATION_LIMIT,\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/universes/operations.ts\";\nimport { parseUniverseResponse } from \"../../domains/cloud-v2/universes/parsers.ts\";\nimport type {\n\tGetUniverseParameters,\n\tUniverse,\n\tUpdateUniverseParameters,\n} from \"../../domains/cloud-v2/universes/types.ts\";\nimport {\n\tbuildDeleteIconRequest,\n\tbuildListIconsRequest,\n\tbuildUploadIconRequest,\n} from \"../../domains/game-internationalization/game-icon/builders.ts\";\nimport {\n\tICON_OPERATION_LIMIT,\n\tICON_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/game-icon/operations.ts\";\nimport { parseIconListResponse } from \"../../domains/game-internationalization/game-icon/parsers.ts\";\nimport type {\n\tDeleteExperienceIconParameters,\n\tExperienceIcon,\n\tListExperienceIconsParameters,\n\tUploadExperienceIconParameters,\n} from \"../../domains/game-internationalization/game-icon/types.ts\";\nimport {\n\tbuildDeleteThumbnailRequest,\n\tbuildReorderThumbnailsRequest,\n\tbuildUploadThumbnailRequest,\n} from \"../../domains/game-internationalization/game-thumbnails/builders.ts\";\nimport {\n\tTHUMBNAILS_OPERATION_LIMIT,\n\tTHUMBNAILS_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/game-thumbnails/operations.ts\";\nimport { parseThumbnailUploadResponse } from \"../../domains/game-internationalization/game-thumbnails/parsers.ts\";\nimport type {\n\tDeleteExperienceThumbnailParameters,\n\tReorderExperienceThumbnailsParameters,\n\tUploadedExperienceThumbnail,\n\tUploadExperienceThumbnailParameters,\n} from \"../../domains/game-internationalization/game-thumbnails/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS, IDEMPOTENT_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport type { HttpRequest } from \"../../internal/http/types.ts\";\nimport {\n\tokRequest,\n\tparseEmptyResponse,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\n\nconst GET_SPEC: ResourceMethodSpec<GetUniverseParameters, Universe> = Object.freeze({\n\tbuildRequest: buildGetRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: GET_OPERATION_LIMIT,\n\tparse: parseUniverseResponse,\n});\n\nconst UPDATE_SPEC: ResourceMethodSpec<UpdateUniverseParameters, Universe> = Object.freeze({\n\tbuildRequest: buildUpdateRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parseUniverseResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\nfunction buildIconUploadOkRequest(\n\tparameters: UploadExperienceIconParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildUploadIconRequest(parameters));\n}\n\nfunction buildIconDeleteOkRequest(\n\tparameters: DeleteExperienceIconParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildDeleteIconRequest(parameters));\n}\n\nfunction buildIconListOkRequest(\n\tparameters: ListExperienceIconsParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildListIconsRequest(parameters));\n}\n\nconst ICON_UPLOAD_SPEC: ResourceMethodSpec<UploadExperienceIconParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildIconUploadOkRequest,\n\t\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\t\tmethodKind: \"create\",\n\t\toperationLimit: ICON_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: ICON_REQUIRED_SCOPES,\n\t});\n\nconst ICON_DELETE_SPEC: ResourceMethodSpec<DeleteExperienceIconParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildIconDeleteOkRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: ICON_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: ICON_REQUIRED_SCOPES,\n\t});\n\nconst ICON_LIST_SPEC: ResourceMethodSpec<\n\tListExperienceIconsParameters,\n\tReadonlyArray<ExperienceIcon>\n> = Object.freeze({\n\tbuildRequest: buildIconListOkRequest,\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: ICON_OPERATION_LIMIT,\n\tparse: parseIconListResponse,\n\trequiredScopes: ICON_REQUIRED_SCOPES,\n});\n\nfunction buildThumbnailUploadOkRequest(\n\tparameters: UploadExperienceThumbnailParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildUploadThumbnailRequest(parameters));\n}\n\nfunction buildThumbnailDeleteOkRequest(\n\tparameters: DeleteExperienceThumbnailParameters,\n): Result<HttpRequest, OpenCloudError> {\n\treturn okRequest(buildDeleteThumbnailRequest(parameters));\n}\n\nconst THUMBNAIL_UPLOAD_SPEC: ResourceMethodSpec<\n\tUploadExperienceThumbnailParameters,\n\tUploadedExperienceThumbnail\n> = Object.freeze({\n\tbuildRequest: buildThumbnailUploadOkRequest,\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\tparse: parseThumbnailUploadResponse,\n\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n});\n\nconst THUMBNAIL_DELETE_SPEC: ResourceMethodSpec<DeleteExperienceThumbnailParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildThumbnailDeleteOkRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n\t});\n\nconst THUMBNAIL_REORDER_SPEC: ResourceMethodSpec<ReorderExperienceThumbnailsParameters, undefined> =\n\tObject.freeze({\n\t\tbuildRequest: buildReorderThumbnailsRequest,\n\t\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\t\tmethodKind: \"idempotent\",\n\t\toperationLimit: THUMBNAILS_OPERATION_LIMIT,\n\t\tparse: parseEmptyResponse,\n\t\trequiredScopes: THUMBNAILS_REQUIRED_SCOPES,\n\t});\n\ninterface UniverseIconHandle {\n\t/**\n\t * Deletes the localized icon registered against a universe for a given\n\t * language. Removing the source-language icon is rejected server-side;\n\t * consumers must replace it via {@link UniverseIconHandle.upload}\n\t * instead.\n\t *\n\t * @param parameters - Universe and language identifiers of the icon to\n\t * delete.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tdelete: (\n\t\tparameters: DeleteExperienceIconParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Lists every localized icon registered against an experience. The\n\t * server returns one entry per locale that has an icon registered.\n\t *\n\t * @param parameters - Universe identifier whose icons to list.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed array of\n\t * {@link ExperienceIcon} entries or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tlist: (\n\t\tparameters: ListExperienceIconsParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<ReadonlyArray<ExperienceIcon>, OpenCloudError>>;\n\t/**\n\t * Uploads or replaces the localized icon for an experience. A\n\t * subsequent upload for the same `(universeId, languageCode)` pair\n\t * replaces the existing icon for that locale.\n\t *\n\t * @param parameters - Universe and language identifiers plus the image\n\t * bytes to upload.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tupload: (\n\t\tparameters: UploadExperienceIconParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n}\n\ninterface UniverseThumbnailsHandle {\n\t/**\n\t * Deletes a single thumbnail by media asset ID. Idempotent: deleting an\n\t * already-removed thumbnail surfaces the server's 404 unchanged.\n\t *\n\t * @param parameters - Universe, language, and image identifiers of the\n\t * thumbnail to delete.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tdelete: (\n\t\tparameters: DeleteExperienceThumbnailParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Reorders the localized thumbnail carousel. The supplied\n\t * `orderedImageIds` describes the desired display order from first to\n\t * last. Image IDs must be positive integers within the safe-integer\n\t * range; invalid input is rejected with a {@link OpenCloudError} of\n\t * kind `ValidationError` before any HTTP round-trip.\n\t *\n\t * @param parameters - Universe, language, and the desired display order.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\treorder: (\n\t\tparameters: ReorderExperienceThumbnailsParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Uploads a new thumbnail and appends it to the localized carousel. Use\n\t * {@link UniverseThumbnailsHandle.reorder} after multiple uploads to\n\t * set the display order.\n\t *\n\t * @param parameters - Universe and language identifiers plus the image\n\t * bytes to upload.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed\n\t * {@link UploadedExperienceThumbnail} or the {@link OpenCloudError}\n\t * that caused the request to fail.\n\t */\n\tupload: (\n\t\tparameters: UploadExperienceThumbnailParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<UploadedExperienceThumbnail, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud `Universe` resource. Wires\n * the request builders, the injected\n * {@link OpenCloudClientOptions.httpClient}, and the response parser\n * into a single ergonomic surface. Every method returns a\n * {@link Result} so callers handle failure explicitly; no thrown\n * {@link OpenCloudError} ever escapes the client.\n *\n * Partial updates use a Google-style `updateMask` query string derived\n * from the keys present on the update parameters. Setting a clearable\n * field (`privateServerPriceRobux` or any social link) to `undefined`\n * sends JSON `null` for that field so the server clears the\n * corresponding value.\n *\n * Localized experience-icon and experience-thumbnail Operations are\n * bound on the {@link UniversesClient.icon} and\n * {@link UniversesClient.thumbnails} Operation Groups so callers reach\n * for one client per universe.\n *\n * @example\n *\n * ```ts\n * import { UniversesClient } from \"@bedrock-rbx/ocale/universes\";\n *\n * const client = new UniversesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(UniversesClient);\n * ```\n */\nexport class UniversesClient {\n\treadonly #inner: ResourceClient;\n\n\t/**\n\t * Operation Group exposing the localized experience-icon\n\t * Operations (`upload`, `delete`, `list`) backed by the\n\t * `legacy-game-internationalization` domain. Shares the parent\n\t * client's HTTP, rate-limit, and retry plumbing.\n\t */\n\tpublic readonly icon: UniverseIconHandle;\n\t/**\n\t * Operation Group exposing the localized experience-thumbnail\n\t * Operations (`upload`, `delete`, `reorder`) backed by the\n\t * `legacy-game-internationalization` domain. No list-thumbnails\n\t * endpoint is bridged; consumers must track uploaded\n\t * `mediaAssetId`s in their own state store to reconcile against\n\t * the existing carousel. Shares the parent client's HTTP,\n\t * rate-limit, and retry plumbing.\n\t */\n\tpublic readonly thumbnails: UniverseThumbnailsHandle;\n\n\t/**\n\t * Creates a new {@link UniversesClient}. Configuration is frozen\n\t * on construction; per-request overrides are accepted on each\n\t * method.\n\t *\n\t * @param options - Client-level configuration including the API key.\n\t */\n\tconstructor(options: OpenCloudClientOptions) {\n\t\tthis.#inner = new ResourceClient(options);\n\t\tthis.icon = createIconHandle(this.#inner);\n\t\tthis.thumbnails = createThumbnailsHandle(this.#inner);\n\t}\n\n\t/**\n\t * Fetches the current configuration of a universe.\n\t *\n\t * @param parameters - The universe identifier.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed {@link Universe}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async get(\n\t\tparameters: GetUniverseParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Universe, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: GET_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a universe's configuration. The fields\n\t * supplied on `parameters` (excluding `universeId`) are forwarded\n\t * to the server via a Google-style `updateMask`; unmentioned\n\t * fields are left untouched.\n\t *\n\t * @param parameters - The universe identifier and the fields to\n\t * update. At least one updatable field must be supplied.\n\t * @param options - Optional per-request overrides (e.g. A different\n\t * {@link OpenCloudClientOptions.apiKey} for this call only).\n\t * @returns A {@link Result} wrapping the parsed {@link Universe}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdateUniverseParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Universe, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n}\n\nfunction createIconHandle(inner: ResourceClient): UniverseIconHandle {\n\treturn {\n\t\tasync delete(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_DELETE_SPEC });\n\t\t},\n\t\tasync list(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_LIST_SPEC });\n\t\t},\n\t\tasync upload(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: ICON_UPLOAD_SPEC });\n\t\t},\n\t};\n}\n\nfunction createThumbnailsHandle(inner: ResourceClient): UniverseThumbnailsHandle {\n\treturn {\n\t\tasync delete(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_DELETE_SPEC });\n\t\t},\n\t\tasync reorder(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_REORDER_SPEC });\n\t\t},\n\t\tasync upload(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: THUMBNAIL_UPLOAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -32,4 +32,4 @@ interface GameIconListWire {
32
32
  }
33
33
  //#endregion
34
34
  export { GameIconState as n, GetGameIconResponseWire as r, GameIconListWire as t };
35
- //# sourceMappingURL=wire-BeIO-d1x.d.mts.map
35
+ //# sourceMappingURL=wire-CeL6W_V7.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"wire-BeIO-d1x.d.mts","names":[],"sources":["../src/domains/game-internationalization/game-icon/wire.ts"],"mappings":";;AAGA;;KAAY,aAAA;;;AAOZ;;;UAAiB,uBAAA;;WAEP,OAAA;;WAEA,QAAA;;;;AAeV;;WATU,YAAA;EAWM;EAAA,SATN,KAAA,EAAO,aAAA;AAAA;;;;;UAOA,gBAAA;;WAEP,IAAA,EAAM,aAAA,CAAc,uBAAA;AAAA"}
1
+ {"version":3,"file":"wire-CeL6W_V7.d.mts","names":[],"sources":["../src/domains/game-internationalization/game-icon/wire.ts"],"mappings":";;AAGA;;KAAY,aAAA;;;AAOZ;;;UAAiB,uBAAA;;WAEP,OAAA;;WAEA,QAAA;;;;AAeV;;WATU,YAAA;EAWM;EAAA,SATN,KAAA,EAAO,aAAA;AAAA;;;;;UAOA,gBAAA;;WAEP,IAAA,EAAM,aAAA,CAAc,uBAAA;AAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bedrock-rbx/ocale",
3
- "version": "0.1.0-beta.6",
3
+ "version": "0.1.0-beta.8",
4
4
  "description": "Roblox Open Cloud API client",
5
5
  "keywords": [
6
6
  "api",
@@ -1,19 +0,0 @@
1
- //#region src/internal/utils/is-date-time-string.ts
2
- /**
3
- * Narrows `value` to a string that parses to a real {@link Date} via the
4
- * `Date(string)` constructor. Used by resource parsers to gate
5
- * `format: date-time` wire fields before handing them to `new Date(...)`,
6
- * which silently produces an `Invalid Date` for invalid input.
7
- *
8
- * @param value - The unknown wire value to validate.
9
- * @returns `true` when `value` is a string and `new Date(value).getTime()`
10
- * is not `NaN`.
11
- */
12
- function isDateTimeString(value) {
13
- if (typeof value !== "string") return false;
14
- return !Number.isNaN(new Date(value).getTime());
15
- }
16
- //#endregion
17
- export { isDateTimeString as t };
18
-
19
- //# sourceMappingURL=is-date-time-string-DL6l9mo6.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"is-date-time-string-DL6l9mo6.mjs","names":[],"sources":["../src/internal/utils/is-date-time-string.ts"],"sourcesContent":["/**\n * Narrows `value` to a string that parses to a real {@link Date} via the\n * `Date(string)` constructor. Used by resource parsers to gate\n * `format: date-time` wire fields before handing them to `new Date(...)`,\n * which silently produces an `Invalid Date` for invalid input.\n *\n * @param value - The unknown wire value to validate.\n * @returns `true` when `value` is a string and `new Date(value).getTime()`\n * is not `NaN`.\n */\nexport function isDateTimeString(value: unknown): value is string {\n\tif (typeof value !== \"string\") {\n\t\treturn false;\n\t}\n\n\treturn !Number.isNaN(new Date(value).getTime());\n}\n"],"mappings":";;;;;;;;;;;AAUA,SAAgB,iBAAiB,OAAiC;AACjE,KAAI,OAAO,UAAU,SACpB,QAAO;AAGR,QAAO,CAAC,OAAO,MAAM,IAAI,KAAK,MAAM,CAAC,SAAS,CAAC"}