@bedrock-rbx/ocale 0.1.0-beta.21 → 0.1.0-beta.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,15 +6,32 @@ Zero-dependency TypeScript SDK for Roblox Open Cloud.
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://github.com/christopher-buss/bedrock/blob/main/LICENSE)
7
7
  [![CI](https://github.com/christopher-buss/bedrock/actions/workflows/ci.yaml/badge.svg)](https://github.com/christopher-buss/bedrock/actions/workflows/ci.yaml)
8
8
 
9
- > **Status: 0.1, pre-1.0.** The public API is stabilizing; breaking changes may land in minor releases until 1.0.
9
+ > **Status: 0.1, pre-1.0.** The public API is stabilizing; breaking changes may
10
+ > land in minor releases until 1.0.
10
11
 
11
12
  ## What is `@bedrock-rbx/ocale`?
12
13
 
13
- A typed HTTP client for [Roblox Open Cloud](https://create.roblox.com/docs/cloud). Each Roblox feature (universes, places, game passes, developer products, badges, storage, Luau execution) is exposed as its own client class with the methods, request types, and response types you would otherwise build by hand against the raw REST endpoints.
14
-
15
- The SDK has zero runtime dependencies and runs on Node >= 24.12 or Bun >= 1.3 using the standard `fetch`, `FormData`, and `TextEncoder` web APIs. Rate-limit queueing and retry handling are built in: requests are queued per-operation against Roblox's published limits, and idempotent calls automatically retry on 429 and 5xx responses without consumer code reaching for `try`/`catch` or `setTimeout`.
16
-
17
- `@bedrock-rbx/ocale` is the foundation that [`@bedrock-rbx/core`](https://github.com/christopher-buss/bedrock/tree/main/packages/bedrock) uses internally to talk to Roblox, and it is publishable as a standalone package for anyone building tooling, scripts, or services that need typed Open Cloud calls without bedrock's full IaC engine. If you already depend on `@bedrock-rbx/core`, ocale is installed transitively; reach for it directly when you need HTTP-level control that core's IaC engine does not expose.
14
+ A typed HTTP client for
15
+ [Roblox Open Cloud](https://create.roblox.com/docs/cloud). Each Roblox feature
16
+ (universes, places, game passes, developer products, badges, storage, Luau
17
+ execution) is exposed as its own client class with the methods, request types,
18
+ and response types you would otherwise build by hand against the raw REST
19
+ endpoints.
20
+
21
+ The SDK has zero runtime dependencies and runs on Node >= 24.12 or Bun >= 1.3
22
+ using the standard `fetch`, `FormData`, and `TextEncoder` web APIs. Rate-limit
23
+ queueing and retry handling are built in: requests are queued per-operation
24
+ against Roblox's published limits, and idempotent calls automatically retry on
25
+ 429 and 5xx responses without consumer code reaching for `try`/`catch` or
26
+ `setTimeout`.
27
+
28
+ `@bedrock-rbx/ocale` is the foundation that
29
+ [`@bedrock-rbx/core`](https://github.com/christopher-buss/bedrock/tree/main/packages/bedrock)
30
+ uses internally to talk to Roblox, and it is publishable as a standalone package
31
+ for anyone building tooling, scripts, or services that need typed Open Cloud
32
+ calls without bedrock's full IaC engine. If you already depend on
33
+ `@bedrock-rbx/core`, ocale is installed transitively; reach for it directly when
34
+ you need HTTP-level control that core's IaC engine does not expose.
18
35
 
19
36
  ## Install
20
37
 
@@ -26,7 +43,11 @@ pnpm add @bedrock-rbx/ocale
26
43
 
27
44
  **Runtime:** Node >= 24.12 or Bun >= 1.3.
28
45
 
29
- **Authentication:** every client takes an `apiKey` at construction. Generate one at [Creator Hub > Credentials > API Keys](https://create.roblox.com/dashboard/credentials) and grant it the scopes for the operations you plan to call (each method's JSDoc lists its required scopes).
46
+ **Authentication:** every client takes an `apiKey` at construction. Generate one
47
+ at
48
+ [Creator Hub > Credentials > API Keys](https://create.roblox.com/dashboard/credentials)
49
+ and grant it the scopes for the operations you plan to call (each method's JSDoc
50
+ lists its required scopes).
30
51
 
31
52
  ## Quick start
32
53
 
@@ -48,49 +69,67 @@ if (!result.success) {
48
69
  console.log(`${result.data.name} (${result.data.id})`);
49
70
  ```
50
71
 
51
- Every method returns `Promise<Result<T, OpenCloudError>>`. `Result` is a discriminated union: `result.success` is `true` with the parsed response on `result.data`, or `false` with a structured error on `result.err`. No exception ever escapes a client method.
72
+ Every method returns `Promise<Result<T, OpenCloudError>>`. `Result` is a
73
+ discriminated union: `result.success` is `true` with the parsed response on
74
+ `result.data`, or `false` with a structured error on `result.err`. No exception
75
+ ever escapes a client method.
52
76
 
53
77
  ## Available clients
54
78
 
55
- Resource clients live on subpaths so unused features tree-shake out of your bundle.
56
-
57
- | Subpath | Client | What it covers |
58
- |---|---|---|
59
- | `@bedrock-rbx/ocale/universes` | `UniversesClient` | Universe metadata, social links, icon and thumbnail uploads. |
60
- | `@bedrock-rbx/ocale/places` | `PlacesClient` | Place metadata, `.rbxl` publishing, Luau execution tasks scoped to a place. |
61
- | `@bedrock-rbx/ocale/game-passes` | `GamePassesClient` | Game pass CRUD, icon upload, localized name and description updates. |
62
- | `@bedrock-rbx/ocale/developer-products` | `DeveloperProductsClient` | Developer product CRUD, icon upload, localized name and description updates. |
63
- | `@bedrock-rbx/ocale/badges` | `BadgesClient` | Badge CRUD and localized icon uploads. |
64
- | `@bedrock-rbx/ocale/storage` | `StorageClient` | Memory stores (sorted maps, queues) for live game state. |
65
- | `@bedrock-rbx/ocale/luau-execution` | `LuauExecutionClient` | Standalone Luau execution tasks with binary inputs and log streaming. |
66
- | `@bedrock-rbx/ocale/locales` | `ROBLOX_CREATOR_LOCALES` (data) | Reference list of locales Roblox supports for localized fields. |
67
-
68
- Additional Open Cloud features (messaging, data stores, OAuth, groups, analytics) are not yet wrapped; they are tracked on the [roadmap](https://github.com/christopher-buss/bedrock/projects).
69
-
70
- The package root (`@bedrock-rbx/ocale`) deliberately re-exports only shared utilities: `Result`, `Page`, `OpenCloudError` and its subclasses (`ApiError`, `RateLimitError`, `NetworkError`, `ValidationError`, and similar), and the `OpenCloudClientOptions` type. Resource clients are not on the root barrel.
79
+ Resource clients live on subpaths so unused features tree-shake out of your
80
+ bundle.
81
+
82
+ | Subpath | Client | What it covers |
83
+ | --------------------------------------- | ------------------------------- | ---------------------------------------------------------------------------- |
84
+ | `@bedrock-rbx/ocale/universes` | `UniversesClient` | Universe metadata, social links, icon and thumbnail uploads. |
85
+ | `@bedrock-rbx/ocale/places` | `PlacesClient` | Place metadata, `.rbxl` publishing, Luau execution tasks scoped to a place. |
86
+ | `@bedrock-rbx/ocale/game-passes` | `GamePassesClient` | Game pass CRUD, icon upload, localized name and description updates. |
87
+ | `@bedrock-rbx/ocale/developer-products` | `DeveloperProductsClient` | Developer product CRUD, icon upload, localized name and description updates. |
88
+ | `@bedrock-rbx/ocale/badges` | `BadgesClient` | Badge CRUD and localized icon uploads. |
89
+ | `@bedrock-rbx/ocale/storage` | `StorageClient` | Memory stores (sorted maps, queues) for live game state. |
90
+ | `@bedrock-rbx/ocale/luau-execution` | `LuauExecutionClient` | Standalone Luau execution tasks with binary inputs and log streaming. |
91
+ | `@bedrock-rbx/ocale/locales` | `ROBLOX_CREATOR_LOCALES` (data) | Reference list of locales Roblox supports for localized fields. |
92
+
93
+ Additional Open Cloud features (messaging, data stores, OAuth, groups,
94
+ analytics) are not yet wrapped; they are tracked on the
95
+ [roadmap](https://github.com/christopher-buss/bedrock/projects).
96
+
97
+ The package root (`@bedrock-rbx/ocale`) deliberately re-exports only shared
98
+ utilities: `Result`, `Page`, `OpenCloudError` and its subclasses (`ApiError`,
99
+ `RateLimitError`, `NetworkError`, `ValidationError`, and similar), and the
100
+ `OpenCloudClientOptions` type. Resource clients are not on the root barrel.
71
101
 
72
102
  ## Rate limiting and retries
73
103
 
74
- The SDK queues every request behind a per-operation rate-limit bucket sourced from Roblox's published OpenAPI schema. You fire calls at whatever rate your code needs; the SDK paces them.
104
+ The SDK queues every request behind a per-operation rate-limit bucket sourced
105
+ from Roblox's published OpenAPI schema. You fire calls at whatever rate your
106
+ code needs; the SDK paces them.
75
107
 
76
108
  Retry behavior is idempotency-aware:
77
109
 
78
110
  | Method kind | 429 (rate limit) | 5xx (server error) |
79
- |---|---|---|
80
- | Create | Retry | Do not retry |
81
- | Read / List | Retry | Retry |
82
- | Update | Retry | Retry |
83
- | Delete | Retry | Retry |
111
+ | ----------- | ---------------- | ------------------ |
112
+ | Create | Retry | Do not retry |
113
+ | Read / List | Retry | Retry |
114
+ | Update | Retry | Retry |
115
+ | Delete | Retry | Retry |
84
116
 
85
- Create operations skip 5xx retries because Roblox does not support idempotency keys and a duplicate retry would silently produce a second resource. If you can detect duplicates externally, opt back into 5xx retry on a per-call basis via `retryableStatuses` on the request options argument.
117
+ Create operations skip 5xx retries because Roblox does not support idempotency
118
+ keys and a duplicate retry would silently produce a second resource. If you can
119
+ detect duplicates externally, opt back into 5xx retry on a per-call basis via
120
+ `retryableStatuses` on the request options argument.
86
121
 
87
- After retry attempts are exhausted, the final failure surfaces on `result.err` as the typed error that caused it (`RateLimitError` for 429s, `ApiError` for 5xx, `NetworkError` for transport-level faults, and so on).
122
+ After retry attempts are exhausted, the final failure surfaces on `result.err`
123
+ as the typed error that caused it (`RateLimitError` for 429s, `ApiError` for
124
+ 5xx, `NetworkError` for transport-level faults, and so on).
88
125
 
89
- Observability hooks (`onRequest`, `onRetry`, `onRateLimit`) accept callbacks on the client constructor for logging, metrics, or tracing integration.
126
+ Observability hooks (`onRequest`, `onRetry`, `onRateLimit`) accept callbacks on
127
+ the client constructor for logging, metrics, or tracing integration.
90
128
 
91
129
  ## Per-request configuration overrides
92
130
 
93
- Client-level config is frozen on construction. Every method accepts an optional second `RequestOptions` argument that overrides config for a single call:
131
+ Client-level config is frozen on construction. Every method accepts an optional
132
+ second `RequestOptions` argument that overrides config for a single call:
94
133
 
95
134
  ```ts
96
135
  const client = new GamePassesClient({ apiKey: "main-key" });
@@ -101,29 +140,43 @@ const result = await client.create(parameters, {
101
140
  });
102
141
  ```
103
142
 
104
- This pattern fits multi-tenant tooling (different API keys per workspace), credential rotation (swap mid-batch), and isolating retry / timeout policies to specific calls.
143
+ This pattern fits multi-tenant tooling (different API keys per workspace),
144
+ credential rotation (swap mid-batch), and isolating retry / timeout policies to
145
+ specific calls.
105
146
 
106
147
  ## Testing helpers
107
148
 
108
- A `@bedrock-rbx/ocale/testing` subpath exports the same fakes the SDK's own integration tests use:
149
+ A `@bedrock-rbx/ocale/testing` subpath exports the same fakes the SDK's own
150
+ integration tests use:
109
151
 
110
- - `createFakeHttpClient(...)` for swapping the HTTP transport with a recorded fake that validates request bodies against the vendored OpenAPI schema.
111
- - `createFakeSend(...)` for a lightweight scripted send-callback fake that records requests and replays responses for single-call tests, without schema validation.
152
+ - `createFakeHttpClient(...)` for swapping the HTTP transport with a recorded
153
+ fake that validates request bodies against the vendored OpenAPI schema.
154
+ - `createFakeSend(...)` for a lightweight scripted send-callback fake that
155
+ records requests and replays responses for single-call tests, without schema
156
+ validation.
112
157
  - `createFakeSleep(...)` for deterministic retry and rate-limit timing.
113
- - `valid*Body` fixtures (`validGamePassBody`, `validPlaceBody`, `validUniverseBody`, and similar) for synthesising realistic response payloads.
158
+ - `valid*Body` fixtures (`validGamePassBody`, `validPlaceBody`,
159
+ `validUniverseBody`, and similar) for synthesising realistic response
160
+ payloads.
114
161
 
115
- Pass the fake into any client via the `httpClient` and `sleep` parameters on `OpenCloudClientOptions` and assert against the captured requests.
162
+ Pass the fake into any client via the `httpClient` and `sleep` parameters on
163
+ `OpenCloudClientOptions` and assert against the captured requests.
116
164
 
117
165
  ## Status, docs, and contributing
118
166
 
119
- This package is pre-1.0 and under active development. Track scope and timing on the [project board](https://github.com/christopher-buss/bedrock/projects).
167
+ This package is pre-1.0 and under active development. Track scope and timing on
168
+ the [project board](https://github.com/christopher-buss/bedrock/projects).
120
169
 
121
170
  - [Documentation site](https://bedrock-livid.vercel.app/) (work in progress)
122
171
  - [Source repository](https://github.com/christopher-buss/bedrock/tree/main/packages/open-cloud)
123
- - [Issues](https://github.com/christopher-buss/bedrock/issues) (maintainer-only; external feedback runs through [Discussions](https://github.com/christopher-buss/bedrock/discussions) as prompt requests)
172
+ - [Issues](https://github.com/christopher-buss/bedrock/issues) (maintainer-only;
173
+ external feedback runs through
174
+ [Discussions](https://github.com/christopher-buss/bedrock/discussions) as
175
+ prompt requests)
124
176
  - [Contributing guide](https://github.com/christopher-buss/bedrock/blob/main/CONTRIBUTING.md)
125
177
  - [Security policy](https://github.com/christopher-buss/bedrock/blob/main/SECURITY.md)
126
178
 
127
179
  ## License
128
180
 
129
- [MIT](https://github.com/christopher-buss/bedrock/blob/main/LICENSE) (c) Christopher Buss.
181
+ [MIT](https://github.com/christopher-buss/bedrock/blob/main/LICENSE) (c)
182
+ Christopher Buss.
package/dist/badges.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { n as IDEMPOTENT_METHOD_DEFAULTS, t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
3
  import { t as toBlob } from "./to-blob-RPqMBuft.mjs";
4
- import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-lE7Tg3BK.mjs";
4
+ import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-QIICmSU8.mjs";
5
5
  //#region src/domains/badges/badges/builders.ts
6
6
  /**
7
7
  * Builds a `POST` request for the legacy "create badge" endpoint.
@@ -1,8 +1,8 @@
1
1
  import { r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { n as IDEMPOTENT_METHOD_DEFAULTS, t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
3
  import { t as toBlob } from "./to-blob-RPqMBuft.mjs";
4
- import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-lE7Tg3BK.mjs";
5
- import { n as isPriceInformationLike, t as copyPriceInformation } from "./price-information-Bu87sPyh.mjs";
4
+ import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-QIICmSU8.mjs";
5
+ import { n as isPriceInformationLike, t as copyPriceInformation } from "./price-information-BK6UhOOz.mjs";
6
6
  //#region src/domains/developer-products/products/builders.ts
7
7
  /**
8
8
  * Builds a `GET` request for the Open Cloud "read developer product"
@@ -1,8 +1,8 @@
1
1
  import { r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { n as IDEMPOTENT_METHOD_DEFAULTS, t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
3
  import { t as toBlob } from "./to-blob-RPqMBuft.mjs";
4
- import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-lE7Tg3BK.mjs";
5
- import { n as isPriceInformationLike, t as copyPriceInformation } from "./price-information-Bu87sPyh.mjs";
4
+ import { a as isDateTimeString, i as isRecord, n as okRequest, r as parseEmptyResponse, t as ResourceClient } from "./resource-client-QIICmSU8.mjs";
5
+ import { n as isPriceInformationLike, t as copyPriceInformation } from "./price-information-BK6UhOOz.mjs";
6
6
  //#region src/domains/game-internationalization/game-pass-icon/builders.ts
7
7
  /**
8
8
  * Builds a `POST` request for the localized "upload game-pass icon"
@@ -1,7 +1,7 @@
1
1
  import { r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
- import { i as isRecord, n as okRequest, t as ResourceClient } from "./resource-client-lE7Tg3BK.mjs";
4
- import { a as withBudgetRequestTimeout, c as SUBMIT_VERSION_SPEC, i as pollUntilDoneCore, l as LIST_LOGS_SPEC, n as submitAndPoll, o as GET_SPEC, r as defaultPollDelay, s as SUBMIT_HEAD_SPEC, t as buildPollDeps } from "./polling-helpers-Cb4j4cq7.mjs";
3
+ import { i as isRecord, n as okRequest, t as ResourceClient } from "./resource-client-QIICmSU8.mjs";
4
+ import { a as withBudgetRequestTimeout, c as SUBMIT_VERSION_SPEC, i as pollUntilDoneCore, l as LIST_LOGS_SPEC, n as submitAndPoll, o as GET_SPEC, r as defaultPollDelay, s as SUBMIT_HEAD_SPEC, t as buildPollDependencies } from "./polling-helpers-BzeCsBFI.mjs";
5
5
  //#region src/domains/cloud-v2/luau-execution-task-binary-inputs/builders.ts
6
6
  /**
7
7
  * Builds a `POST` request for the Open Cloud
@@ -146,7 +146,7 @@ function createTasksHandle(inner) {
146
146
  },
147
147
  async pollUntilDone(ref, options = {}) {
148
148
  const resolved = withBudgetRequestTimeout(options);
149
- return pollUntilDoneCore(buildPollDeps(inner, {
149
+ return pollUntilDoneCore(buildPollDependencies(inner, {
150
150
  options: resolved,
151
151
  ref
152
152
  }), resolved);
@@ -1 +1 @@
1
- {"version":3,"file":"luau-execution.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/luau-execution-task-binary-inputs/builders.ts","../src/domains/cloud-v2/luau-execution-task-binary-inputs/operations.ts","../src/domains/cloud-v2/luau-execution-task-binary-inputs/parsers.ts","../src/resources/luau-execution/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport type { CreateBinaryInputParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the Open Cloud\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` endpoint. The\n * server responds with a presigned `uploadUri` and the resource `path`.\n *\n * @param parameters - Universe identifier and the byte size of the\n * binary to be uploaded.\n * @returns A pure {@link HttpRequest} describing the create call.\n */\nexport function buildCreateBinaryInputRequest(\n\tparameters: CreateBinaryInputParameters,\n): HttpRequest {\n\tconst { size, universeId } = parameters;\n\treturn {\n\t\tbody: { size },\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tmethod: \"POST\",\n\t\turl: `/cloud/v2/universes/${universeId}/luau-execution-session-task-binary-inputs`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst CREATE_PER_MINUTE = 5;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for creating a Luau execution task binary\n * input, sourced from `x-roblox-rate-limits.perApiKeyOwner` on the\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` operation (5 requests\n * per minute per API key owner).\n */\nexport const CREATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: CREATE_PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"luau-execution-task-binary-inputs.create\",\n});\n\n/**\n * Scopes required to create a Luau execution task binary input, sourced\n * from `x-roblox-scopes` on the create operation in the vendored OpenAPI\n * schema.\n */\nexport const CREATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe.place.luau-execution-session:write\",\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 { LuauExecutionTaskBinaryInput } from \"./types.ts\";\n\nconst PATH_PATTERN = /^universes\\/(\\d+)\\/luau-execution-session-task-binary-inputs\\/([^/]+)$/;\n\nconst MALFORMED_MESSAGE = \"Malformed luau-execution-session-task-binary-input response\";\n\n/**\n * Parses a successful Open Cloud\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` response body into\n * the public {@link LuauExecutionTaskBinaryInput}.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed binary input, or an\n * {@link ApiError} when the body does not match the expected shape.\n */\nexport function parseBinaryInputResponse(\n\tresponse: HttpResponse,\n): Result<LuauExecutionTaskBinaryInput, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isRecord(body)) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tif (typeof body[\"path\"] !== \"string\" || !PATH_PATTERN.test(body[\"path\"])) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tif (typeof body[\"uploadUri\"] !== \"string\") {\n\t\treturn malformed(statusCode);\n\t}\n\n\treturn {\n\t\tdata: { path: body[\"path\"], uploadUri: body[\"uploadUri\"] },\n\t\tsuccess: true,\n\t};\n}\n\nfunction malformed(statusCode: number): Result<LuauExecutionTaskBinaryInput, ApiError> {\n\treturn { err: new ApiError(MALFORMED_MESSAGE, { statusCode }), success: false };\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildCreateBinaryInputRequest } from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/builders.ts\";\nimport {\n\tCREATE_OPERATION_LIMIT,\n\tCREATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/operations.ts\";\nimport { parseBinaryInputResponse } from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/parsers.ts\";\nimport type {\n\tCreateBinaryInputParameters,\n\tLuauExecutionTaskBinaryInput,\n} from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/types.ts\";\nimport { LIST_LOGS_SPEC } from \"../../domains/cloud-v2/luau-execution-task-logs/specs.ts\";\nimport type {\n\tListLogsParameters,\n\tLogPage,\n} from \"../../domains/cloud-v2/luau-execution-task-logs/types.ts\";\nimport {\n\tGET_SPEC,\n\tSUBMIT_HEAD_SPEC,\n\tSUBMIT_VERSION_SPEC,\n} from \"../../domains/cloud-v2/luau-execution-tasks/specs.ts\";\nimport type {\n\tGetParameters,\n\tLuauExecutionTask,\n\tLuauExecutionTaskRef,\n\tSubmitAtHeadParameters,\n\tSubmitAtVersionParameters,\n} from \"../../domains/cloud-v2/luau-execution-tasks/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport {\n\tokRequest,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\nimport { buildPollDeps, submitAndPoll } from \"./polling-helpers.ts\";\nimport {\n\tpollUntilDoneCore,\n\ttype PollUntilDoneOptions,\n\twithBudgetRequestTimeout,\n} from \"./polling.ts\";\n\nfunction makeSpec<P, R>(spec: ResourceMethodSpec<P, R>): ResourceMethodSpec<P, R> {\n\treturn Object.freeze(spec);\n}\n\nconst CREATE_BINARY_INPUT_SPEC = makeSpec<\n\tCreateBinaryInputParameters,\n\tLuauExecutionTaskBinaryInput\n>({\n\tbuildRequest: (parameters) => okRequest(buildCreateBinaryInputRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: CREATE_OPERATION_LIMIT,\n\tparse: parseBinaryInputResponse,\n\trequiredScopes: CREATE_REQUIRED_SCOPES,\n});\n\n/**\n * Operation handle for the `binaryInputs` namespace on\n * {@link LuauExecutionClient}. Provides `create` to allocate a presigned\n * upload slot for binary script inputs.\n *\n * @since 0.1.0\n */\nexport interface BinaryInputsHandle {\n\t/**\n\t * Allocates a presigned binary input upload slot. The returned\n\t * `uploadUri` is a presigned `PUT` target; the caller uploads the\n\t * binary data directly and passes `path` to `tasks.submit` as\n\t * `binaryInput`.\n\t *\n\t * @param parameters - Universe identifier and the byte size of the\n\t * binary to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed\n\t * {@link LuauExecutionTaskBinaryInput} or the {@link OpenCloudError}\n\t * that caused the request to fail.\n\t */\n\tcreate(\n\t\tparameters: CreateBinaryInputParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTaskBinaryInput, OpenCloudError>>;\n}\n\n/**\n * Operation handle exposed by {@link LuauExecutionClient} as the\n * `tasks` namespace. Provides `submit` to queue a Luau script, `get`\n * to fetch a task's current state, and `listLogs` to retrieve\n * structured log messages produced by a task.\n *\n * @since 0.1.0\n */\nexport interface TasksHandle {\n\t/**\n\t * Fetches the current state of a previously-submitted Luau\n\t * execution task. Uses idempotent retry semantics for both 429 and\n\t * 5xx.\n\t *\n\t * @param parameters - The task ref plus an optional `view` selector.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tget(\n\t\tparameters: GetParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Lists one page of structured log messages produced by a\n\t * previously-submitted Luau execution task. Messages from multiple\n\t * server-side chunks are flattened into a single ordered array.\n\t * Uses idempotent retry semantics for both 429 and 5xx.\n\t *\n\t * @param parameters - The task ref and optional pagination controls\n\t * (`pageSize`, `pageToken`).\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 LogPage} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tlistLogs(\n\t\tparameters: ListLogsParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LogPage, OpenCloudError>>;\n\t/**\n\t * Polls `tasks.get` with `view=BASIC` on a configurable backoff schedule\n\t * until the task reaches a terminal state, the wall-clock budget is\n\t * exhausted, or the supplied `AbortSignal` fires. Returns the terminal\n\t * task on success.\n\t *\n\t * @param ref - Reference to the task to poll, typically returned by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal {@link LuauExecutionTask},\n\t * or an error if aborted, timed out, or the transport fails.\n\t */\n\tpollUntilDone(\n\t\tref: LuauExecutionTaskRef,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script and polls `tasks.get` with `view=BASIC` until\n\t * the task reaches a terminal state, the wall-clock budget is\n\t * exhausted, or the supplied `AbortSignal` fires. Combines `submit`\n\t * and `pollUntilDone` in one call.\n\t *\n\t * @param parameters - The same input accepted by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal\n\t * {@link LuauExecutionTask}, or an error if submit fails, the task\n\t * is aborted, timed out, or the transport fails.\n\t */\n\trunUntilDone(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script for execution against a place. Dispatches\n\t * to the head-version URL when `versionId` is omitted, or to the\n\t * specific-version URL when one is supplied. Both URL shapes share\n\t * one rate-limit queue and one required-scope set.\n\t *\n\t * @param parameters - The universe and place identifiers, the\n\t * script to run, an optional `versionId`, and any other writable\n\t * submit fields.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tsubmit(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud `LuauExecutionSessionTask`\n * resource. Tasks run a Luau script against a place and surface state,\n * output, or error through the `LuauExecutionTask` discriminated\n * union. Exposes `tasks.submit` for both the head version and a\n * specific place version, `tasks.get` for fetching task state,\n * `tasks.listLogs` for fetching structured log messages, and\n * `binaryInputs.create` for allocating presigned upload slots.\n *\n * @since 0.1.0\n *\n * @example\n *\n * ```ts\n * import { LuauExecutionClient } from \"@bedrock-rbx/ocale/luau-execution\";\n *\n * const client = new LuauExecutionClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(LuauExecutionClient);\n * ```\n */\nexport class LuauExecutionClient {\n\treadonly #inner: ResourceClient;\n\n\tpublic readonly binaryInputs: BinaryInputsHandle;\n\tpublic readonly tasks: TasksHandle;\n\n\t/**\n\t * Creates a new {@link LuauExecutionClient}. 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.binaryInputs = createBinaryInputsHandle(this.#inner);\n\t\tthis.tasks = createTasksHandle(this.#inner);\n\t}\n}\n\nfunction createBinaryInputsHandle(inner: ResourceClient): BinaryInputsHandle {\n\treturn {\n\t\tasync create(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: CREATE_BINARY_INPUT_SPEC });\n\t\t},\n\t};\n}\n\nfunction createTasksHandle(inner: ResourceClient): TasksHandle {\n\treturn {\n\t\tasync get(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: GET_SPEC });\n\t\t},\n\t\tasync listLogs(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: LIST_LOGS_SPEC });\n\t\t},\n\t\tasync pollUntilDone(ref, options = {}) {\n\t\t\tconst resolved = withBudgetRequestTimeout(options);\n\t\t\treturn pollUntilDoneCore(buildPollDeps(inner, { options: resolved, ref }), resolved);\n\t\t},\n\t\tasync runUntilDone(parameters, options = {}) {\n\t\t\treturn submitAndPoll(inner, { options: withBudgetRequestTimeout(options), parameters });\n\t\t},\n\t\tasync submit(parameters, options) {\n\t\t\tif (\"versionId\" in parameters) {\n\t\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_VERSION_SPEC });\n\t\t\t}\n\n\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_HEAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,SAAgB,8BACf,YACc;CACd,MAAM,EAAE,MAAM,eAAe;CAC7B,OAAO;EACN,MAAM,EAAE,KAAK;EACb,SAAS,EAAE,gBAAgB,mBAAmB;EAC9C,QAAQ;EACR,KAAK,uBAAuB,WAAW;CACxC;AACD;;;;;;;ACXA,MAAa,yBAAyC,OAAO,OAAO;CACnE,cAAc,IAAoB;CAClC,cAAc;AACf,CAAC;;;;;;AAOD,MAAa,yBAAgD,OAAO,OAAO,CAC1E,6CACD,CAAC;;;ACjBD,MAAM,eAAe;AAErB,MAAM,oBAAoB;;;;;;;;;;AAW1B,SAAgB,yBACf,UACiD;CACjD,MAAM,EAAE,MAAM,QAAQ,eAAe;CAErC,IAAI,CAAC,SAAS,IAAI,GACjB,OAAO,UAAU,UAAU;CAG5B,IAAI,OAAO,KAAK,YAAY,YAAY,CAAC,aAAa,KAAK,KAAK,OAAO,GACtE,OAAO,UAAU,UAAU;CAG5B,IAAI,OAAO,KAAK,iBAAiB,UAChC,OAAO,UAAU,UAAU;CAG5B,OAAO;EACN,MAAM;GAAE,MAAM,KAAK;GAAS,WAAW,KAAK;EAAa;EACzD,SAAS;CACV;AACD;AAEA,SAAS,UAAU,YAAoE;CACtF,OAAO;EAAE,KAAK,IAAI,SAAS,mBAAmB,EAAE,WAAW,CAAC;EAAG,SAAS;CAAM;AAC/E;;;ACDA,SAAS,SAAe,MAA0D;CACjF,OAAO,OAAO,OAAO,IAAI;AAC1B;AAEA,MAAM,2BAA2B,SAG/B;CACD,eAAe,eAAe,UAAU,8BAA8B,UAAU,CAAC;CACjF,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,OAAO;CACP,gBAAgB;AACjB,CAAC;;;;;;;;;;;;;;;;;;;;;AA+ID,IAAa,sBAAb,MAAiC;CAChC;CAEA;CACA;;;;;;;;CASA,YAAY,SAAiC;EAC5C,KAAKA,SAAS,IAAI,eAAe,OAAO;EACxC,KAAK,eAAe,yBAAyB,KAAKA,MAAM;EACxD,KAAK,QAAQ,kBAAkB,KAAKA,MAAM;CAC3C;AACD;AAEA,SAAS,yBAAyB,OAA2C;CAC5E,OAAO,EACN,MAAM,OAAO,YAAY,SAAS;EACjC,OAAO,MAAM,QAAQ;GAAE;GAAS;GAAY,MAAM;EAAyB,CAAC;CAC7E,EACD;AACD;AAEA,SAAS,kBAAkB,OAAoC;CAC9D,OAAO;EACN,MAAM,IAAI,YAAY,SAAS;GAC9B,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAS,CAAC;EAC7D;EACA,MAAM,SAAS,YAAY,SAAS;GACnC,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAe,CAAC;EACnE;EACA,MAAM,cAAc,KAAK,UAAU,CAAC,GAAG;GACtC,MAAM,WAAW,yBAAyB,OAAO;GACjD,OAAO,kBAAkB,cAAc,OAAO;IAAE,SAAS;IAAU;GAAI,CAAC,GAAG,QAAQ;EACpF;EACA,MAAM,aAAa,YAAY,UAAU,CAAC,GAAG;GAC5C,OAAO,cAAc,OAAO;IAAE,SAAS,yBAAyB,OAAO;IAAG;GAAW,CAAC;EACvF;EACA,MAAM,OAAO,YAAY,SAAS;GACjC,IAAI,eAAe,YAClB,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAoB,CAAC;GAGxE,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAiB,CAAC;EACrE;CACD;AACD"}
1
+ {"version":3,"file":"luau-execution.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/luau-execution-task-binary-inputs/builders.ts","../src/domains/cloud-v2/luau-execution-task-binary-inputs/operations.ts","../src/domains/cloud-v2/luau-execution-task-binary-inputs/parsers.ts","../src/resources/luau-execution/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport type { CreateBinaryInputParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the Open Cloud\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` endpoint. The\n * server responds with a presigned `uploadUri` and the resource `path`.\n *\n * @param parameters - Universe identifier and the byte size of the\n * binary to be uploaded.\n * @returns A pure {@link HttpRequest} describing the create call.\n */\nexport function buildCreateBinaryInputRequest(\n\tparameters: CreateBinaryInputParameters,\n): HttpRequest {\n\tconst { size, universeId } = parameters;\n\treturn {\n\t\tbody: { size },\n\t\theaders: { \"content-type\": \"application/json\" },\n\t\tmethod: \"POST\",\n\t\turl: `/cloud/v2/universes/${universeId}/luau-execution-session-task-binary-inputs`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst CREATE_PER_MINUTE = 5;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for creating a Luau execution task binary\n * input, sourced from `x-roblox-rate-limits.perApiKeyOwner` on the\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` operation (5 requests\n * per minute per API key owner).\n */\nexport const CREATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: CREATE_PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"luau-execution-task-binary-inputs.create\",\n});\n\n/**\n * Scopes required to create a Luau execution task binary input, sourced\n * from `x-roblox-scopes` on the create operation in the vendored OpenAPI\n * schema.\n */\nexport const CREATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe.place.luau-execution-session:write\",\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 { LuauExecutionTaskBinaryInput } from \"./types.ts\";\n\nconst PATH_PATTERN = /^universes\\/(\\d+)\\/luau-execution-session-task-binary-inputs\\/([^/]+)$/;\n\nconst MALFORMED_MESSAGE = \"Malformed luau-execution-session-task-binary-input response\";\n\n/**\n * Parses a successful Open Cloud\n * `Cloud_CreateLuauExecutionSessionTaskBinaryInput` response body into\n * the public {@link LuauExecutionTaskBinaryInput}.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed binary input, or an\n * {@link ApiError} when the body does not match the expected shape.\n */\nexport function parseBinaryInputResponse(\n\tresponse: HttpResponse,\n): Result<LuauExecutionTaskBinaryInput, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isRecord(body)) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tif (typeof body[\"path\"] !== \"string\" || !PATH_PATTERN.test(body[\"path\"])) {\n\t\treturn malformed(statusCode);\n\t}\n\n\tif (typeof body[\"uploadUri\"] !== \"string\") {\n\t\treturn malformed(statusCode);\n\t}\n\n\treturn {\n\t\tdata: { path: body[\"path\"], uploadUri: body[\"uploadUri\"] },\n\t\tsuccess: true,\n\t};\n}\n\nfunction malformed(statusCode: number): Result<LuauExecutionTaskBinaryInput, ApiError> {\n\treturn { err: new ApiError(MALFORMED_MESSAGE, { statusCode }), success: false };\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildCreateBinaryInputRequest } from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/builders.ts\";\nimport {\n\tCREATE_OPERATION_LIMIT,\n\tCREATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/operations.ts\";\nimport { parseBinaryInputResponse } from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/parsers.ts\";\nimport type {\n\tCreateBinaryInputParameters,\n\tLuauExecutionTaskBinaryInput,\n} from \"../../domains/cloud-v2/luau-execution-task-binary-inputs/types.ts\";\nimport { LIST_LOGS_SPEC } from \"../../domains/cloud-v2/luau-execution-task-logs/specs.ts\";\nimport type {\n\tListLogsParameters,\n\tLogPage,\n} from \"../../domains/cloud-v2/luau-execution-task-logs/types.ts\";\nimport {\n\tGET_SPEC,\n\tSUBMIT_HEAD_SPEC,\n\tSUBMIT_VERSION_SPEC,\n} from \"../../domains/cloud-v2/luau-execution-tasks/specs.ts\";\nimport type {\n\tGetParameters,\n\tLuauExecutionTask,\n\tLuauExecutionTaskRef,\n\tSubmitAtHeadParameters,\n\tSubmitAtVersionParameters,\n} from \"../../domains/cloud-v2/luau-execution-tasks/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport {\n\tokRequest,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\nimport { buildPollDependencies, submitAndPoll } from \"./polling-helpers.ts\";\nimport {\n\tpollUntilDoneCore,\n\ttype PollUntilDoneOptions,\n\twithBudgetRequestTimeout,\n} from \"./polling.ts\";\n\nfunction makeSpec<P, R>(spec: ResourceMethodSpec<P, R>): ResourceMethodSpec<P, R> {\n\treturn Object.freeze(spec);\n}\n\nconst CREATE_BINARY_INPUT_SPEC = makeSpec<\n\tCreateBinaryInputParameters,\n\tLuauExecutionTaskBinaryInput\n>({\n\tbuildRequest: (parameters) => okRequest(buildCreateBinaryInputRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: CREATE_OPERATION_LIMIT,\n\tparse: parseBinaryInputResponse,\n\trequiredScopes: CREATE_REQUIRED_SCOPES,\n});\n\n/**\n * Operation handle for the `binaryInputs` namespace on\n * {@link LuauExecutionClient}. Provides `create` to allocate a presigned\n * upload slot for binary script inputs.\n *\n * @since 0.1.0\n */\nexport interface BinaryInputsHandle {\n\t/**\n\t * Allocates a presigned binary input upload slot. The returned\n\t * `uploadUri` is a presigned `PUT` target; the caller uploads the\n\t * binary data directly and passes `path` to `tasks.submit` as\n\t * `binaryInput`.\n\t *\n\t * @param parameters - Universe identifier and the byte size of the\n\t * binary to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed\n\t * {@link LuauExecutionTaskBinaryInput} or the {@link OpenCloudError}\n\t * that caused the request to fail.\n\t */\n\tcreate(\n\t\tparameters: CreateBinaryInputParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTaskBinaryInput, OpenCloudError>>;\n}\n\n/**\n * Operation handle exposed by {@link LuauExecutionClient} as the\n * `tasks` namespace. Provides `submit` to queue a Luau script, `get`\n * to fetch a task's current state, and `listLogs` to retrieve\n * structured log messages produced by a task.\n *\n * @since 0.1.0\n */\nexport interface TasksHandle {\n\t/**\n\t * Fetches the current state of a previously-submitted Luau\n\t * execution task. Uses idempotent retry semantics for both 429 and\n\t * 5xx.\n\t *\n\t * @param parameters - The task ref plus an optional `view` selector.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tget(\n\t\tparameters: GetParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Lists one page of structured log messages produced by a\n\t * previously-submitted Luau execution task. Messages from multiple\n\t * server-side chunks are flattened into a single ordered array.\n\t * Uses idempotent retry semantics for both 429 and 5xx.\n\t *\n\t * @param parameters - The task ref and optional pagination controls\n\t * (`pageSize`, `pageToken`).\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 LogPage} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tlistLogs(\n\t\tparameters: ListLogsParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LogPage, OpenCloudError>>;\n\t/**\n\t * Polls `tasks.get` with `view=BASIC` on a configurable backoff schedule\n\t * until the task reaches a terminal state, the wall-clock budget is\n\t * exhausted, or the supplied `AbortSignal` fires. Returns the terminal\n\t * task on success.\n\t *\n\t * @param ref - Reference to the task to poll, typically returned by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal {@link LuauExecutionTask},\n\t * or an error if aborted, timed out, or the transport fails.\n\t */\n\tpollUntilDone(\n\t\tref: LuauExecutionTaskRef,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script and polls `tasks.get` with `view=BASIC` until\n\t * the task reaches a terminal state, the wall-clock budget is\n\t * exhausted, or the supplied `AbortSignal` fires. Combines `submit`\n\t * and `pollUntilDone` in one call.\n\t *\n\t * @param parameters - The same input accepted by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal\n\t * {@link LuauExecutionTask}, or an error if submit fails, the task\n\t * is aborted, timed out, or the transport fails.\n\t */\n\trunUntilDone(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script for execution against a place. Dispatches\n\t * to the head-version URL when `versionId` is omitted, or to the\n\t * specific-version URL when one is supplied. Both URL shapes share\n\t * one rate-limit queue and one required-scope set.\n\t *\n\t * @param parameters - The universe and place identifiers, the\n\t * script to run, an optional `versionId`, and any other writable\n\t * submit fields.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tsubmit(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud `LuauExecutionSessionTask`\n * resource. Tasks run a Luau script against a place and surface state,\n * output, or error through the `LuauExecutionTask` discriminated\n * union. Exposes `tasks.submit` for both the head version and a\n * specific place version, `tasks.get` for fetching task state,\n * `tasks.listLogs` for fetching structured log messages, and\n * `binaryInputs.create` for allocating presigned upload slots.\n *\n * @since 0.1.0\n *\n * @example\n *\n * ```ts\n * import { LuauExecutionClient } from \"@bedrock-rbx/ocale/luau-execution\";\n *\n * const client = new LuauExecutionClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(LuauExecutionClient);\n * ```\n */\nexport class LuauExecutionClient {\n\treadonly #inner: ResourceClient;\n\n\tpublic readonly binaryInputs: BinaryInputsHandle;\n\tpublic readonly tasks: TasksHandle;\n\n\t/**\n\t * Creates a new {@link LuauExecutionClient}. 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.binaryInputs = createBinaryInputsHandle(this.#inner);\n\t\tthis.tasks = createTasksHandle(this.#inner);\n\t}\n}\n\nfunction createBinaryInputsHandle(inner: ResourceClient): BinaryInputsHandle {\n\treturn {\n\t\tasync create(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: CREATE_BINARY_INPUT_SPEC });\n\t\t},\n\t};\n}\n\nfunction createTasksHandle(inner: ResourceClient): TasksHandle {\n\treturn {\n\t\tasync get(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: GET_SPEC });\n\t\t},\n\t\tasync listLogs(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: LIST_LOGS_SPEC });\n\t\t},\n\t\tasync pollUntilDone(ref, options = {}) {\n\t\t\tconst resolved = withBudgetRequestTimeout(options);\n\t\t\treturn pollUntilDoneCore(\n\t\t\t\tbuildPollDependencies(inner, { options: resolved, ref }),\n\t\t\t\tresolved,\n\t\t\t);\n\t\t},\n\t\tasync runUntilDone(parameters, options = {}) {\n\t\t\treturn submitAndPoll(inner, { options: withBudgetRequestTimeout(options), parameters });\n\t\t},\n\t\tasync submit(parameters, options) {\n\t\t\tif (\"versionId\" in parameters) {\n\t\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_VERSION_SPEC });\n\t\t\t}\n\n\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_HEAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,SAAgB,8BACf,YACc;CACd,MAAM,EAAE,MAAM,eAAe;CAC7B,OAAO;EACN,MAAM,EAAE,KAAK;EACb,SAAS,EAAE,gBAAgB,mBAAmB;EAC9C,QAAQ;EACR,KAAK,uBAAuB,WAAW;CACxC;AACD;;;;;;;ACXA,MAAa,yBAAyC,OAAO,OAAO;CACnE,cAAc,IAAoB;CAClC,cAAc;AACf,CAAC;;;;;;AAOD,MAAa,yBAAgD,OAAO,OAAO,CAC1E,6CACD,CAAC;;;ACjBD,MAAM,eAAe;AAErB,MAAM,oBAAoB;;;;;;;;;;AAW1B,SAAgB,yBACf,UACiD;CACjD,MAAM,EAAE,MAAM,QAAQ,eAAe;CAErC,IAAI,CAAC,SAAS,IAAI,GACjB,OAAO,UAAU,UAAU;CAG5B,IAAI,OAAO,KAAK,YAAY,YAAY,CAAC,aAAa,KAAK,KAAK,OAAO,GACtE,OAAO,UAAU,UAAU;CAG5B,IAAI,OAAO,KAAK,iBAAiB,UAChC,OAAO,UAAU,UAAU;CAG5B,OAAO;EACN,MAAM;GAAE,MAAM,KAAK;GAAS,WAAW,KAAK;EAAa;EACzD,SAAS;CACV;AACD;AAEA,SAAS,UAAU,YAAoE;CACtF,OAAO;EAAE,KAAK,IAAI,SAAS,mBAAmB,EAAE,WAAW,CAAC;EAAG,SAAS;CAAM;AAC/E;;;ACDA,SAAS,SAAe,MAA0D;CACjF,OAAO,OAAO,OAAO,IAAI;AAC1B;AAEA,MAAM,2BAA2B,SAG/B;CACD,eAAe,eAAe,UAAU,8BAA8B,UAAU,CAAC;CACjF,gBAAgB;CAChB,YAAY;CACZ,gBAAgB;CAChB,OAAO;CACP,gBAAgB;AACjB,CAAC;;;;;;;;;;;;;;;;;;;;;AA+ID,IAAa,sBAAb,MAAiC;CAChC;CAEA;CACA;;;;;;;;CASA,YAAY,SAAiC;EAC5C,KAAKA,SAAS,IAAI,eAAe,OAAO;EACxC,KAAK,eAAe,yBAAyB,KAAKA,MAAM;EACxD,KAAK,QAAQ,kBAAkB,KAAKA,MAAM;CAC3C;AACD;AAEA,SAAS,yBAAyB,OAA2C;CAC5E,OAAO,EACN,MAAM,OAAO,YAAY,SAAS;EACjC,OAAO,MAAM,QAAQ;GAAE;GAAS;GAAY,MAAM;EAAyB,CAAC;CAC7E,EACD;AACD;AAEA,SAAS,kBAAkB,OAAoC;CAC9D,OAAO;EACN,MAAM,IAAI,YAAY,SAAS;GAC9B,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAS,CAAC;EAC7D;EACA,MAAM,SAAS,YAAY,SAAS;GACnC,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAe,CAAC;EACnE;EACA,MAAM,cAAc,KAAK,UAAU,CAAC,GAAG;GACtC,MAAM,WAAW,yBAAyB,OAAO;GACjD,OAAO,kBACN,sBAAsB,OAAO;IAAE,SAAS;IAAU;GAAI,CAAC,GACvD,QACD;EACD;EACA,MAAM,aAAa,YAAY,UAAU,CAAC,GAAG;GAC5C,OAAO,cAAc,OAAO;IAAE,SAAS,yBAAyB,OAAO;IAAG;GAAW,CAAC;EACvF;EACA,MAAM,OAAO,YAAY,SAAS;GACjC,IAAI,eAAe,YAClB,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAoB,CAAC;GAGxE,OAAO,MAAM,QAAQ;IAAE;IAAS;IAAY,MAAM;GAAiB,CAAC;EACrE;CACD;AACD"}
package/dist/places.mjs CHANGED
@@ -1,8 +1,8 @@
1
1
  import { r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
3
  import { t as ValidationError } from "./validation-9oU6qNNQ.mjs";
4
- import { a as isDateTimeString, i as isRecord, t as ResourceClient } from "./resource-client-lE7Tg3BK.mjs";
5
- import { c as SUBMIT_VERSION_SPEC, i as pollUntilDoneCore, l as LIST_LOGS_SPEC, n as submitAndPoll, o as GET_SPEC, s as SUBMIT_HEAD_SPEC, t as buildPollDeps } from "./polling-helpers-Cb4j4cq7.mjs";
4
+ import { a as isDateTimeString, i as isRecord, t as ResourceClient } from "./resource-client-QIICmSU8.mjs";
5
+ import { c as SUBMIT_VERSION_SPEC, i as pollUntilDoneCore, l as LIST_LOGS_SPEC, n as submitAndPoll, o as GET_SPEC, s as SUBMIT_HEAD_SPEC, t as buildPollDependencies } from "./polling-helpers-BzeCsBFI.mjs";
6
6
  import { n as RBXL_SIGNATURE, r as matchesSignature, t as RBXLX_SIGNATURE } from "./signatures-JF-7Psce.mjs";
7
7
  //#region src/domains/cloud-v2/places/builders.ts
8
8
  const NON_UPDATABLE_KEYS = new Set(["placeId", "universeId"]);
@@ -60,6 +60,7 @@ const UPDATE_REQUIRED_SCOPES = Object.freeze(["universe.place:write"]);
60
60
  //#endregion
61
61
  //#region src/domains/cloud-v2/places/parsers.ts
62
62
  const MALFORMED_PLACE_MESSAGE = "Malformed place response";
63
+ const PLACE_PATH_PATTERN = /^universes\/(\d+)\/places\/(\d+)$/;
63
64
  /**
64
65
  * Parses a successful Open Cloud `Place` response body into the public
65
66
  * {@link Place} shape.
@@ -71,7 +72,7 @@ const MALFORMED_PLACE_MESSAGE = "Malformed place response";
71
72
  function parsePlaceResponse(response) {
72
73
  const { body, status: statusCode } = response;
73
74
  if (!isPlaceWire(body)) return malformedPlace(statusCode);
74
- const match = /^universes\/(\d+)\/places\/(\d+)$/.exec(body.path);
75
+ const match = PLACE_PATH_PATTERN.exec(body.path);
75
76
  const universeId = match?.[1];
76
77
  const id = match?.[2];
77
78
  if (id === void 0 || universeId === void 0) return malformedPlace(statusCode);
@@ -370,7 +371,7 @@ function createLuauExecutionHandle(inner) {
370
371
  });
371
372
  },
372
373
  async pollUntilDone(ref, options = {}) {
373
- return pollUntilDoneCore(buildPollDeps(inner, {
374
+ return pollUntilDoneCore(buildPollDependencies(inner, {
374
375
  options,
375
376
  ref
376
377
  }), options);
@@ -1 +1 @@
1
- {"version":3,"file":"places.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/places/builders.ts","../src/domains/cloud-v2/places/operations.ts","../src/domains/cloud-v2/places/parsers.ts","../src/domains/universes/places/builders.ts","../src/domains/universes/places/operations.ts","../src/domains/universes/places/parsers.ts","../src/resources/places/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { UpdatePlaceParameters } from \"./types.ts\";\n\nconst NON_UPDATABLE_KEYS: ReadonlySet<string> = new Set([\"placeId\", \"universeId\"]);\n\n/**\n * Builds a `PATCH` request for the Open Cloud \"update place\" endpoint.\n * Derives the `updateMask` query string from the keys present on\n * `parameters` (excluding the identifiers) and emits a JSON body\n * containing those same fields.\n *\n * @param parameters - The universe and place identifiers plus the fields\n * 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: UpdatePlaceParameters,\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 = Object.fromEntries(\n\t\tfieldKeys.map((key): readonly [string, unknown] => [key, Reflect.get(parameters, key)]),\n\t);\n\tconst updateMask = fieldKeys.join(\",\");\n\tconst { placeId, universeId } = parameters;\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/${universeId}/places/${placeId}?updateMask=${updateMask}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction extractUpdateFieldKeys(parameters: UpdatePlaceParameters): ReadonlyArray<string> {\n\treturn Object.keys(parameters).filter((key) => !NON_UPDATABLE_KEYS.has(key));\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst UPDATE_PER_MINUTE = 100;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for updating a place, from the Open Cloud\n * OpenAPI schema (100 requests per minute per API key owner). Keyed\n * independently from the publish operation so publish and update do\n * not share a queue; upstream quota accounting is not documented as\n * shared and the conservative default is fewer cross-method\n * contention surprises.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: UPDATE_PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"places.update\",\n});\n\n/**\n * Scopes required to update a place's metadata, sourced from\n * `x-roblox-scopes` on the `Cloud_UpdatePlace` operation in the vendored\n * OpenAPI schema.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe.place:write\",\n]);\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 { Place } from \"./types.ts\";\nimport type { PlaceWire } from \"./wire.ts\";\n\nconst MALFORMED_PLACE_MESSAGE = \"Malformed place response\";\n\ninterface ToPlaceArgs {\n\treadonly id: string;\n\treadonly body: PlaceWire;\n\treadonly universeId: string;\n}\n\n/**\n * Parses a successful Open Cloud `Place` response body into the public\n * {@link Place} shape.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link Place}, or an\n * {@link ApiError} when the body does not match the wire schema.\n */\nexport function parsePlaceResponse(response: HttpResponse): Result<Place, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isPlaceWire(body)) {\n\t\treturn malformedPlace(statusCode);\n\t}\n\n\tconst match = /^universes\\/(\\d+)\\/places\\/(\\d+)$/.exec(body.path);\n\tconst universeId = match?.[1];\n\tconst id = match?.[2];\n\tif (id === undefined || universeId === undefined) {\n\t\treturn malformedPlace(statusCode);\n\t}\n\n\treturn { data: toPlace({ id, body, universeId }), success: true };\n}\n\nfunction malformedPlace(statusCode: number): Result<Place, ApiError> {\n\treturn {\n\t\terr: new ApiError(MALFORMED_PLACE_MESSAGE, { statusCode }),\n\t\tsuccess: false,\n\t};\n}\n\nfunction toPlace(args: ToPlaceArgs): Place {\n\tconst { id, body, universeId } = args;\n\treturn {\n\t\tid,\n\t\tcreatedAt: new Date(body.createTime),\n\t\tdescription: body.description,\n\t\tdisplayName: body.displayName,\n\t\troot: body.root ?? false,\n\t\tserverSize: body.serverSize ?? undefined,\n\t\tuniverseId,\n\t\tuniverseRuntimeCreation: body.universeRuntimeCreation ?? false,\n\t\tupdatedAt: new Date(body.updateTime),\n\t};\n}\n\nfunction hasValidPlaceRequired(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);\n}\n\nfunction isOptionalBoolean(value: unknown): boolean {\n\treturn value === undefined || value === null || typeof value === \"boolean\";\n}\n\nfunction hasValidPlaceOptional(body: Record<string, unknown>): boolean {\n\tconst serverSize = body[\"serverSize\"] ?? undefined;\n\treturn (\n\t\t(serverSize === undefined || typeof serverSize === \"number\") &&\n\t\tisOptionalBoolean(body[\"root\"]) &&\n\t\tisOptionalBoolean(body[\"universeRuntimeCreation\"])\n\t);\n}\n\nfunction isPlaceWire(body: unknown): body is PlaceWire {\n\treturn isRecord(body) && hasValidPlaceRequired(body) && hasValidPlaceOptional(body);\n}\n","import type { HttpRequest } from \"../../../client/types.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport { matchesSignature, RBXL_SIGNATURE, RBXLX_SIGNATURE } from \"./signatures.ts\";\nimport type { PublishParameters } from \"./types.ts\";\n\n/**\n * Whether a publish call writes a live (`Published`) or draft (`Saved`)\n * version. Surfaces only as the `versionType` query string on the\n * underlying HTTP request.\n */\ntype VersionType = \"Published\" | \"Saved\";\n\nconst CONTENT_TYPE_BY_FORMAT: Readonly<Record<PublishParameters[\"format\"], string>> = {\n\trbxl: \"application/octet-stream\",\n\trbxlx: \"application/xml\",\n};\n\n/**\n * Builds a `POST` request for the Open Cloud \"publish place version\"\n * endpoint. Performs two local validations before producing any\n * {@link HttpRequest}: a non-empty body check and a magic-byte check\n * that the bytes' actual format matches `parameters.format`.\n *\n * @param parameters - Universe and place identifiers, the place file\n * bytes, and the declared `format` of those bytes.\n * @param versionType - `\"Published\"` for `publish()`, `\"Saved\"` for\n * `save()`; baked into the `?versionType=` query string.\n * @returns A success result wrapping the request on success, or a\n * {@link ValidationError} when the body is empty or its magic bytes\n * disagree with `parameters.format`.\n */\nexport function buildPublishRequest(\n\tparameters: PublishParameters,\n\tversionType: VersionType,\n): Result<HttpRequest, ValidationError> {\n\tconst { body, format, placeId, universeId } = parameters;\n\n\tif (body.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"Place body is empty\", { code: \"empty_body\" }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\tconst expectedSignature = format === \"rbxl\" ? RBXL_SIGNATURE : RBXLX_SIGNATURE;\n\tif (!matchesSignature(body, expectedSignature)) {\n\t\treturn {\n\t\t\terr: new ValidationError(`Place body does not match the declared \"${format}\" format`, {\n\t\t\t\tcode: \"format_mismatch\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tbody,\n\t\t\theaders: { \"content-type\": CONTENT_TYPE_BY_FORMAT[format] },\n\t\t\tmethod: \"POST\",\n\t\t\turl: `/universes/v1/${universeId}/places/${placeId}/versions?versionType=${versionType}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for publishing or saving a place version,\n * from the Open Cloud OpenAPI schema (30 requests per minute, expressed\n * here as `0.5` per second). The publish and save methods both reference\n * this constant so that a single per-API-key queue serves both, matching\n * Roblox's server-side accounting which counts both call types against\n * the same per-minute quota.\n */\nexport const PUBLISH_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 0.5,\n\toperationKey: \"places.publishVersion\",\n});\n\n/**\n * Scopes required to publish or save a place version, sourced from\n * `x-roblox-scopes` on the `Places_CreatePlaceVersionApiKey` operation\n * in the vendored OpenAPI schema.\n */\nexport const PUBLISH_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe-places:write\",\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 { PlaceVersion } from \"./types.ts\";\nimport type { PlaceVersionWire } from \"./wire.ts\";\n\n/**\n * Parses a successful publish-version response into the public\n * {@link PlaceVersion} shape. The Roblox endpoint sometimes returns the\n * JSON-shaped body under a `text/plain` `Content-Type`, so the body may\n * arrive either pre-decoded as a JSON object or still in its raw string\n * form; both are accepted here.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link PlaceVersion}, or\n * an {@link ApiError} when the body is malformed or its `versionNumber`\n * field is missing/wrong-typed.\n */\nexport function parsePublishResponse(response: HttpResponse): Result<PlaceVersion, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tconst decodeResult = decodeBody(body, statusCode);\n\tif (!decodeResult.success) {\n\t\treturn decodeResult;\n\t}\n\n\tif (!isPlaceVersionWire(decodeResult.data)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed publish response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: { versionNumber: decodeResult.data.versionNumber },\n\t\tsuccess: true,\n\t};\n}\n\nfunction decodeBody(body: unknown, statusCode: number): Result<unknown, ApiError> {\n\tif (typeof body !== \"string\") {\n\t\treturn { data: body, success: true };\n\t}\n\n\ttry {\n\t\treturn { data: JSON.parse(body), success: true };\n\t} catch {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed publish response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n}\n\nfunction isPlaceVersionWire(value: unknown): value is PlaceVersionWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn typeof value[\"versionNumber\"] === \"number\";\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { LIST_LOGS_SPEC } from \"../../domains/cloud-v2/luau-execution-task-logs/specs.ts\";\nimport type {\n\tListLogsParameters,\n\tLogPage,\n} from \"../../domains/cloud-v2/luau-execution-task-logs/types.ts\";\nimport {\n\tGET_SPEC,\n\tSUBMIT_HEAD_SPEC,\n\tSUBMIT_VERSION_SPEC,\n} from \"../../domains/cloud-v2/luau-execution-tasks/specs.ts\";\nimport type {\n\tGetParameters,\n\tLuauExecutionTask,\n\tLuauExecutionTaskRef,\n\tSubmitAtHeadParameters,\n\tSubmitAtVersionParameters,\n} from \"../../domains/cloud-v2/luau-execution-tasks/types.ts\";\nimport { buildUpdateRequest } from \"../../domains/cloud-v2/places/builders.ts\";\nimport {\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/places/operations.ts\";\nimport { parsePlaceResponse } from \"../../domains/cloud-v2/places/parsers.ts\";\nimport type { Place, UpdatePlaceParameters } from \"../../domains/cloud-v2/places/types.ts\";\nimport { buildPublishRequest } from \"../../domains/universes/places/builders.ts\";\nimport {\n\tPUBLISH_OPERATION_LIMIT,\n\tPUBLISH_REQUIRED_SCOPES,\n} from \"../../domains/universes/places/operations.ts\";\nimport { parsePublishResponse } from \"../../domains/universes/places/parsers.ts\";\nimport type { PlaceVersion, PublishParameters } from \"../../domains/universes/places/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport { ResourceClient, type ResourceMethodSpec } from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\nimport { buildPollDeps, submitAndPoll } from \"../luau-execution/polling-helpers.ts\";\nimport { pollUntilDoneCore, type PollUntilDoneOptions } from \"../luau-execution/polling.ts\";\n\n/**\n * Operation Group exposed by {@link PlacesClient} as the\n * `luauExecution` namespace. Provides `submit` to queue a Luau script,\n * `get` to fetch a task's current state, and `listLogs` to retrieve\n * structured log messages. Shares the same dispatch wiring as the\n * top-level `LuauExecutionClient` exposed at\n * `@bedrock-rbx/ocale/luau-execution`.\n *\n * @since 0.1.0\n */\nexport interface LuauExecutionHandle {\n\t/**\n\t * Fetches the current state of a previously-submitted Luau\n\t * execution task. Uses idempotent retry semantics for both 429 and\n\t * 5xx.\n\t *\n\t * @param parameters - The task ref plus an optional `view` selector.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tget(\n\t\tparameters: GetParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Lists one page of structured log messages produced by a\n\t * previously-submitted Luau execution task. Messages from multiple\n\t * server-side chunks are flattened into a single ordered array.\n\t * Uses idempotent retry semantics for both 429 and 5xx.\n\t *\n\t * @param parameters - The task ref and optional pagination controls\n\t * (`pageSize`, `pageToken`).\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 LogPage} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tlistLogs(\n\t\tparameters: ListLogsParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LogPage, OpenCloudError>>;\n\t/**\n\t * Polls `get` with `view=BASIC` on a configurable backoff schedule until\n\t * the task reaches a terminal state, the wall-clock budget is exhausted,\n\t * or the supplied `AbortSignal` fires. Returns the terminal task on\n\t * success.\n\t *\n\t * @param ref - Reference to the task to poll, typically returned by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal {@link LuauExecutionTask},\n\t * or an error if aborted, timed out, or the transport fails.\n\t */\n\tpollUntilDone(\n\t\tref: LuauExecutionTaskRef,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script and polls `get` with `view=BASIC` until the\n\t * task reaches a terminal state, the wall-clock budget is exhausted,\n\t * or the supplied `AbortSignal` fires. Combines `submit` and\n\t * `pollUntilDone` in one call.\n\t *\n\t * @param parameters - The same input accepted by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal\n\t * {@link LuauExecutionTask}, or an error if submit fails, the task\n\t * is aborted, timed out, or the transport fails.\n\t */\n\trunUntilDone(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script for execution against a place. Dispatches\n\t * to the head-version URL when `versionId` is omitted, or to the\n\t * specific-version URL when one is supplied. Both URL shapes share\n\t * one rate-limit queue and one required-scope set.\n\t *\n\t * @param parameters - The universe and place identifiers, the\n\t * script to run, an optional `versionId`, and any other writable\n\t * submit fields.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tsubmit(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n}\n\nfunction makePublishSpec(\n\tversionType: \"Published\" | \"Saved\",\n): ResourceMethodSpec<PublishParameters, PlaceVersion> {\n\treturn Object.freeze({\n\t\tbuildRequest: (parameters: PublishParameters) =>\n\t\t\tbuildPublishRequest(parameters, versionType),\n\t\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\t\tmethodKind: \"create\",\n\t\toperationLimit: PUBLISH_OPERATION_LIMIT,\n\t\tparse: parsePublishResponse,\n\t\trequiredScopes: PUBLISH_REQUIRED_SCOPES,\n\t});\n}\n\nconst PUBLISH_SPEC = makePublishSpec(\"Published\");\nconst SAVE_SPEC = makePublishSpec(\"Saved\");\n\nconst UPDATE_SPEC: ResourceMethodSpec<UpdatePlaceParameters, Place> = Object.freeze({\n\tbuildRequest: buildUpdateRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parsePlaceResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\n/**\n * Public client for the Roblox Open Cloud `Place` resource. Covers\n * place-version publishing (`publish`, `save`), place-configuration\n * updates (`update`), and the Luau execution Operation Group\n * (`luauExecution.submit`, `luauExecution.get`). Every method returns\n * a {@link Result} so callers handle failure explicitly; no thrown\n * {@link OpenCloudError} ever escapes the client.\n *\n * Publishing or saving a 5xx-failed place version is not retried\n * automatically: Roblox does not support idempotency keys, so a retry\n * could publish a duplicate version unnoticed. Callers that *can* detect\n * duplicates externally may opt back into 5xx retry per-call by passing\n * `retryableStatuses` on the second argument. The `update` method, by\n * contrast, is idempotent and retries both 429 and 5xx automatically.\n *\n * @since 0.1.0\n *\n * @example\n *\n * ```ts\n * import { PlacesClient } from \"@bedrock-rbx/ocale/places\";\n *\n * const client = new PlacesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(PlacesClient);\n * ```\n */\nexport class PlacesClient {\n\treadonly #inner: ResourceClient;\n\n\tpublic readonly luauExecution: LuauExecutionHandle;\n\n\t/**\n\t * Creates a new {@link PlacesClient}. Configuration is frozen on\n\t * construction; per-request overrides are accepted on each 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.luauExecution = createLuauExecutionHandle(this.#inner);\n\t}\n\n\t/**\n\t * Publishes a new live version of a place.\n\t *\n\t * No default request timeout applies to this upload; pass `options.timeout`\n\t * to set a per-call deadline.\n\t *\n\t * @param parameters - Universe and place identifiers, the place file\n\t * bytes, and their declared `format`.\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 PlaceVersion}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async publish(\n\t\tparameters: PublishParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<PlaceVersion, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: PUBLISH_SPEC });\n\t}\n\n\t/**\n\t * Saves a new draft version of a place. Identical to {@link publish}\n\t * except the resulting version is not made live; consumers can list or\n\t * promote it later. Shares a single per-API-key rate-limit queue with\n\t * `publish` because Roblox attributes both calls to the same per-minute\n\t * quota.\n\t *\n\t * No default request timeout applies to this upload; pass `options.timeout`\n\t * to set a per-call deadline.\n\t *\n\t * @param parameters - Universe and place identifiers, the place file\n\t * bytes, and their declared `format`.\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 PlaceVersion}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async save(\n\t\tparameters: PublishParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<PlaceVersion, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: SAVE_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a place's configuration. The fields supplied on\n\t * `parameters` (excluding the identifiers) are forwarded to the\n\t * server via a Google-style `updateMask`; unmentioned fields are\n\t * left untouched. The universe's root place is the canonical place\n\t * to update when changing a universe's description or display name:\n\t * both are derived server-side from the root place.\n\t *\n\t * @param parameters - The universe and place identifiers and the\n\t * fields to update. At least one writable 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 Place} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdatePlaceParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Place, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n}\n\nfunction createLuauExecutionHandle(inner: ResourceClient): LuauExecutionHandle {\n\treturn {\n\t\tasync get(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: GET_SPEC });\n\t\t},\n\t\tasync listLogs(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: LIST_LOGS_SPEC });\n\t\t},\n\t\tasync pollUntilDone(ref, options = {}) {\n\t\t\treturn pollUntilDoneCore(buildPollDeps(inner, { options, ref }), options);\n\t\t},\n\t\tasync runUntilDone(parameters, options = {}) {\n\t\t\treturn submitAndPoll(inner, { options, parameters });\n\t\t},\n\t\tasync submit(parameters, options) {\n\t\t\tif (\"versionId\" in parameters) {\n\t\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_VERSION_SPEC });\n\t\t\t}\n\n\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_HEAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"places.mjs","names":["#inner"],"sources":["../src/domains/cloud-v2/places/builders.ts","../src/domains/cloud-v2/places/operations.ts","../src/domains/cloud-v2/places/parsers.ts","../src/domains/universes/places/builders.ts","../src/domains/universes/places/operations.ts","../src/domains/universes/places/parsers.ts","../src/resources/places/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../client/types.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport type { UpdatePlaceParameters } from \"./types.ts\";\n\nconst NON_UPDATABLE_KEYS: ReadonlySet<string> = new Set([\"placeId\", \"universeId\"]);\n\n/**\n * Builds a `PATCH` request for the Open Cloud \"update place\" endpoint.\n * Derives the `updateMask` query string from the keys present on\n * `parameters` (excluding the identifiers) and emits a JSON body\n * containing those same fields.\n *\n * @param parameters - The universe and place identifiers plus the fields\n * 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: UpdatePlaceParameters,\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 = Object.fromEntries(\n\t\tfieldKeys.map((key): readonly [string, unknown] => [key, Reflect.get(parameters, key)]),\n\t);\n\tconst updateMask = fieldKeys.join(\",\");\n\tconst { placeId, universeId } = parameters;\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/${universeId}/places/${placeId}?updateMask=${updateMask}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction extractUpdateFieldKeys(parameters: UpdatePlaceParameters): ReadonlyArray<string> {\n\treturn Object.keys(parameters).filter((key) => !NON_UPDATABLE_KEYS.has(key));\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\nconst UPDATE_PER_MINUTE = 100;\nconst SECONDS_PER_MINUTE = 60;\n\n/**\n * Per-second request ceiling for updating a place, from the Open Cloud\n * OpenAPI schema (100 requests per minute per API key owner). Keyed\n * independently from the publish operation so publish and update do\n * not share a queue; upstream quota accounting is not documented as\n * shared and the conservative default is fewer cross-method\n * contention surprises.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: UPDATE_PER_MINUTE / SECONDS_PER_MINUTE,\n\toperationKey: \"places.update\",\n});\n\n/**\n * Scopes required to update a place's metadata, sourced from\n * `x-roblox-scopes` on the `Cloud_UpdatePlace` operation in the vendored\n * OpenAPI schema.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe.place:write\",\n]);\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 { Place } from \"./types.ts\";\nimport type { PlaceWire } from \"./wire.ts\";\n\nconst MALFORMED_PLACE_MESSAGE = \"Malformed place response\";\n\nconst PLACE_PATH_PATTERN = /^universes\\/(\\d+)\\/places\\/(\\d+)$/;\n\ninterface ToPlaceArgs {\n\treadonly id: string;\n\treadonly body: PlaceWire;\n\treadonly universeId: string;\n}\n\n/**\n * Parses a successful Open Cloud `Place` response body into the public\n * {@link Place} shape.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link Place}, or an\n * {@link ApiError} when the body does not match the wire schema.\n */\nexport function parsePlaceResponse(response: HttpResponse): Result<Place, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isPlaceWire(body)) {\n\t\treturn malformedPlace(statusCode);\n\t}\n\n\tconst match = PLACE_PATH_PATTERN.exec(body.path);\n\tconst universeId = match?.[1];\n\tconst id = match?.[2];\n\tif (id === undefined || universeId === undefined) {\n\t\treturn malformedPlace(statusCode);\n\t}\n\n\treturn { data: toPlace({ id, body, universeId }), success: true };\n}\n\nfunction malformedPlace(statusCode: number): Result<Place, ApiError> {\n\treturn {\n\t\terr: new ApiError(MALFORMED_PLACE_MESSAGE, { statusCode }),\n\t\tsuccess: false,\n\t};\n}\n\nfunction toPlace(args: ToPlaceArgs): Place {\n\tconst { id, body, universeId } = args;\n\treturn {\n\t\tid,\n\t\tcreatedAt: new Date(body.createTime),\n\t\tdescription: body.description,\n\t\tdisplayName: body.displayName,\n\t\troot: body.root ?? false,\n\t\tserverSize: body.serverSize ?? undefined,\n\t\tuniverseId,\n\t\tuniverseRuntimeCreation: body.universeRuntimeCreation ?? false,\n\t\tupdatedAt: new Date(body.updateTime),\n\t};\n}\n\nfunction hasValidPlaceRequired(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);\n}\n\nfunction isOptionalBoolean(value: unknown): boolean {\n\treturn value === undefined || value === null || typeof value === \"boolean\";\n}\n\nfunction hasValidPlaceOptional(body: Record<string, unknown>): boolean {\n\tconst serverSize = body[\"serverSize\"] ?? undefined;\n\treturn (\n\t\t(serverSize === undefined || typeof serverSize === \"number\") &&\n\t\tisOptionalBoolean(body[\"root\"]) &&\n\t\tisOptionalBoolean(body[\"universeRuntimeCreation\"])\n\t);\n}\n\nfunction isPlaceWire(body: unknown): body is PlaceWire {\n\treturn isRecord(body) && hasValidPlaceRequired(body) && hasValidPlaceOptional(body);\n}\n","import type { HttpRequest } from \"../../../client/types.ts\";\nimport { ValidationError } from \"../../../errors/validation.ts\";\nimport type { Result } from \"../../../types.ts\";\nimport { matchesSignature, RBXL_SIGNATURE, RBXLX_SIGNATURE } from \"./signatures.ts\";\nimport type { PublishParameters } from \"./types.ts\";\n\n/**\n * Whether a publish call writes a live (`Published`) or draft (`Saved`)\n * version. Surfaces only as the `versionType` query string on the\n * underlying HTTP request.\n */\ntype VersionType = \"Published\" | \"Saved\";\n\nconst CONTENT_TYPE_BY_FORMAT: Readonly<Record<PublishParameters[\"format\"], string>> = {\n\trbxl: \"application/octet-stream\",\n\trbxlx: \"application/xml\",\n};\n\n/**\n * Builds a `POST` request for the Open Cloud \"publish place version\"\n * endpoint. Performs two local validations before producing any\n * {@link HttpRequest}: a non-empty body check and a magic-byte check\n * that the bytes' actual format matches `parameters.format`.\n *\n * @param parameters - Universe and place identifiers, the place file\n * bytes, and the declared `format` of those bytes.\n * @param versionType - `\"Published\"` for `publish()`, `\"Saved\"` for\n * `save()`; baked into the `?versionType=` query string.\n * @returns A success result wrapping the request on success, or a\n * {@link ValidationError} when the body is empty or its magic bytes\n * disagree with `parameters.format`.\n */\nexport function buildPublishRequest(\n\tparameters: PublishParameters,\n\tversionType: VersionType,\n): Result<HttpRequest, ValidationError> {\n\tconst { body, format, placeId, universeId } = parameters;\n\n\tif (body.length === 0) {\n\t\treturn {\n\t\t\terr: new ValidationError(\"Place body is empty\", { code: \"empty_body\" }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\tconst expectedSignature = format === \"rbxl\" ? RBXL_SIGNATURE : RBXLX_SIGNATURE;\n\tif (!matchesSignature(body, expectedSignature)) {\n\t\treturn {\n\t\t\terr: new ValidationError(`Place body does not match the declared \"${format}\" format`, {\n\t\t\t\tcode: \"format_mismatch\",\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tbody,\n\t\t\theaders: { \"content-type\": CONTENT_TYPE_BY_FORMAT[format] },\n\t\t\tmethod: \"POST\",\n\t\t\turl: `/universes/v1/${universeId}/places/${placeId}/versions?versionType=${versionType}`,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for publishing or saving a place version,\n * from the Open Cloud OpenAPI schema (30 requests per minute, expressed\n * here as `0.5` per second). The publish and save methods both reference\n * this constant so that a single per-API-key queue serves both, matching\n * Roblox's server-side accounting which counts both call types against\n * the same per-minute quota.\n */\nexport const PUBLISH_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 0.5,\n\toperationKey: \"places.publishVersion\",\n});\n\n/**\n * Scopes required to publish or save a place version, sourced from\n * `x-roblox-scopes` on the `Places_CreatePlaceVersionApiKey` operation\n * in the vendored OpenAPI schema.\n */\nexport const PUBLISH_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"universe-places:write\",\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 { PlaceVersion } from \"./types.ts\";\nimport type { PlaceVersionWire } from \"./wire.ts\";\n\n/**\n * Parses a successful publish-version response into the public\n * {@link PlaceVersion} shape. The Roblox endpoint sometimes returns the\n * JSON-shaped body under a `text/plain` `Content-Type`, so the body may\n * arrive either pre-decoded as a JSON object or still in its raw string\n * form; both are accepted here.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * @returns A success result wrapping the parsed {@link PlaceVersion}, or\n * an {@link ApiError} when the body is malformed or its `versionNumber`\n * field is missing/wrong-typed.\n */\nexport function parsePublishResponse(response: HttpResponse): Result<PlaceVersion, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tconst decodeResult = decodeBody(body, statusCode);\n\tif (!decodeResult.success) {\n\t\treturn decodeResult;\n\t}\n\n\tif (!isPlaceVersionWire(decodeResult.data)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed publish response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: { versionNumber: decodeResult.data.versionNumber },\n\t\tsuccess: true,\n\t};\n}\n\nfunction decodeBody(body: unknown, statusCode: number): Result<unknown, ApiError> {\n\tif (typeof body !== \"string\") {\n\t\treturn { data: body, success: true };\n\t}\n\n\ttry {\n\t\treturn { data: JSON.parse(body), success: true };\n\t} catch {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed publish response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n}\n\nfunction isPlaceVersionWire(value: unknown): value is PlaceVersionWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn typeof value[\"versionNumber\"] === \"number\";\n}\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { LIST_LOGS_SPEC } from \"../../domains/cloud-v2/luau-execution-task-logs/specs.ts\";\nimport type {\n\tListLogsParameters,\n\tLogPage,\n} from \"../../domains/cloud-v2/luau-execution-task-logs/types.ts\";\nimport {\n\tGET_SPEC,\n\tSUBMIT_HEAD_SPEC,\n\tSUBMIT_VERSION_SPEC,\n} from \"../../domains/cloud-v2/luau-execution-tasks/specs.ts\";\nimport type {\n\tGetParameters,\n\tLuauExecutionTask,\n\tLuauExecutionTaskRef,\n\tSubmitAtHeadParameters,\n\tSubmitAtVersionParameters,\n} from \"../../domains/cloud-v2/luau-execution-tasks/types.ts\";\nimport { buildUpdateRequest } from \"../../domains/cloud-v2/places/builders.ts\";\nimport {\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/cloud-v2/places/operations.ts\";\nimport { parsePlaceResponse } from \"../../domains/cloud-v2/places/parsers.ts\";\nimport type { Place, UpdatePlaceParameters } from \"../../domains/cloud-v2/places/types.ts\";\nimport { buildPublishRequest } from \"../../domains/universes/places/builders.ts\";\nimport {\n\tPUBLISH_OPERATION_LIMIT,\n\tPUBLISH_REQUIRED_SCOPES,\n} from \"../../domains/universes/places/operations.ts\";\nimport { parsePublishResponse } from \"../../domains/universes/places/parsers.ts\";\nimport type { PlaceVersion, PublishParameters } from \"../../domains/universes/places/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport { ResourceClient, type ResourceMethodSpec } from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\nimport { buildPollDependencies, submitAndPoll } from \"../luau-execution/polling-helpers.ts\";\nimport { pollUntilDoneCore, type PollUntilDoneOptions } from \"../luau-execution/polling.ts\";\n\n/**\n * Operation Group exposed by {@link PlacesClient} as the\n * `luauExecution` namespace. Provides `submit` to queue a Luau script,\n * `get` to fetch a task's current state, and `listLogs` to retrieve\n * structured log messages. Shares the same dispatch wiring as the\n * top-level `LuauExecutionClient` exposed at\n * `@bedrock-rbx/ocale/luau-execution`.\n *\n * @since 0.1.0\n */\nexport interface LuauExecutionHandle {\n\t/**\n\t * Fetches the current state of a previously-submitted Luau\n\t * execution task. Uses idempotent retry semantics for both 429 and\n\t * 5xx.\n\t *\n\t * @param parameters - The task ref plus an optional `view` selector.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tget(\n\t\tparameters: GetParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Lists one page of structured log messages produced by a\n\t * previously-submitted Luau execution task. Messages from multiple\n\t * server-side chunks are flattened into a single ordered array.\n\t * Uses idempotent retry semantics for both 429 and 5xx.\n\t *\n\t * @param parameters - The task ref and optional pagination controls\n\t * (`pageSize`, `pageToken`).\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 LogPage} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tlistLogs(\n\t\tparameters: ListLogsParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LogPage, OpenCloudError>>;\n\t/**\n\t * Polls `get` with `view=BASIC` on a configurable backoff schedule until\n\t * the task reaches a terminal state, the wall-clock budget is exhausted,\n\t * or the supplied `AbortSignal` fires. Returns the terminal task on\n\t * success.\n\t *\n\t * @param ref - Reference to the task to poll, typically returned by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal {@link LuauExecutionTask},\n\t * or an error if aborted, timed out, or the transport fails.\n\t */\n\tpollUntilDone(\n\t\tref: LuauExecutionTaskRef,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script and polls `get` with `view=BASIC` until the\n\t * task reaches a terminal state, the wall-clock budget is exhausted,\n\t * or the supplied `AbortSignal` fires. Combines `submit` and\n\t * `pollUntilDone` in one call.\n\t *\n\t * @param parameters - The same input accepted by `submit`.\n\t * @param options - Polling and per-request overrides.\n\t * @returns A {@link Result} wrapping the terminal\n\t * {@link LuauExecutionTask}, or an error if submit fails, the task\n\t * is aborted, timed out, or the transport fails.\n\t */\n\trunUntilDone(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: PollUntilDoneOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n\t/**\n\t * Submits a Luau script for execution against a place. Dispatches\n\t * to the head-version URL when `versionId` is omitted, or to the\n\t * specific-version URL when one is supplied. Both URL shapes share\n\t * one rate-limit queue and one required-scope set.\n\t *\n\t * @param parameters - The universe and place identifiers, the\n\t * script to run, an optional `versionId`, and any other writable\n\t * submit fields.\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 LuauExecutionTask} or the {@link OpenCloudError} that\n\t * caused the request to fail.\n\t */\n\tsubmit(\n\t\tparameters: SubmitAtHeadParameters | SubmitAtVersionParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<LuauExecutionTask, OpenCloudError>>;\n}\n\nfunction makePublishSpec(\n\tversionType: \"Published\" | \"Saved\",\n): ResourceMethodSpec<PublishParameters, PlaceVersion> {\n\treturn Object.freeze({\n\t\tbuildRequest: (parameters: PublishParameters) =>\n\t\t\tbuildPublishRequest(parameters, versionType),\n\t\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\t\tmethodKind: \"create\",\n\t\toperationLimit: PUBLISH_OPERATION_LIMIT,\n\t\tparse: parsePublishResponse,\n\t\trequiredScopes: PUBLISH_REQUIRED_SCOPES,\n\t});\n}\n\nconst PUBLISH_SPEC = makePublishSpec(\"Published\");\nconst SAVE_SPEC = makePublishSpec(\"Saved\");\n\nconst UPDATE_SPEC: ResourceMethodSpec<UpdatePlaceParameters, Place> = Object.freeze({\n\tbuildRequest: buildUpdateRequest,\n\tmethodDefaults: {},\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parsePlaceResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\n/**\n * Public client for the Roblox Open Cloud `Place` resource. Covers\n * place-version publishing (`publish`, `save`), place-configuration\n * updates (`update`), and the Luau execution Operation Group\n * (`luauExecution.submit`, `luauExecution.get`). Every method returns\n * a {@link Result} so callers handle failure explicitly; no thrown\n * {@link OpenCloudError} ever escapes the client.\n *\n * Publishing or saving a 5xx-failed place version is not retried\n * automatically: Roblox does not support idempotency keys, so a retry\n * could publish a duplicate version unnoticed. Callers that *can* detect\n * duplicates externally may opt back into 5xx retry per-call by passing\n * `retryableStatuses` on the second argument. The `update` method, by\n * contrast, is idempotent and retries both 429 and 5xx automatically.\n *\n * @since 0.1.0\n *\n * @example\n *\n * ```ts\n * import { PlacesClient } from \"@bedrock-rbx/ocale/places\";\n *\n * const client = new PlacesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(PlacesClient);\n * ```\n */\nexport class PlacesClient {\n\treadonly #inner: ResourceClient;\n\n\tpublic readonly luauExecution: LuauExecutionHandle;\n\n\t/**\n\t * Creates a new {@link PlacesClient}. Configuration is frozen on\n\t * construction; per-request overrides are accepted on each 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.luauExecution = createLuauExecutionHandle(this.#inner);\n\t}\n\n\t/**\n\t * Publishes a new live version of a place.\n\t *\n\t * No default request timeout applies to this upload; pass `options.timeout`\n\t * to set a per-call deadline.\n\t *\n\t * @param parameters - Universe and place identifiers, the place file\n\t * bytes, and their declared `format`.\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 PlaceVersion}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async publish(\n\t\tparameters: PublishParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<PlaceVersion, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: PUBLISH_SPEC });\n\t}\n\n\t/**\n\t * Saves a new draft version of a place. Identical to {@link publish}\n\t * except the resulting version is not made live; consumers can list or\n\t * promote it later. Shares a single per-API-key rate-limit queue with\n\t * `publish` because Roblox attributes both calls to the same per-minute\n\t * quota.\n\t *\n\t * No default request timeout applies to this upload; pass `options.timeout`\n\t * to set a per-call deadline.\n\t *\n\t * @param parameters - Universe and place identifiers, the place file\n\t * bytes, and their declared `format`.\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 PlaceVersion}\n\t * or the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async save(\n\t\tparameters: PublishParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<PlaceVersion, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: SAVE_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a place's configuration. The fields supplied on\n\t * `parameters` (excluding the identifiers) are forwarded to the\n\t * server via a Google-style `updateMask`; unmentioned fields are\n\t * left untouched. The universe's root place is the canonical place\n\t * to update when changing a universe's description or display name:\n\t * both are derived server-side from the root place.\n\t *\n\t * @param parameters - The universe and place identifiers and the\n\t * fields to update. At least one writable 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 Place} or\n\t * the {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdatePlaceParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Place, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n}\n\nfunction createLuauExecutionHandle(inner: ResourceClient): LuauExecutionHandle {\n\treturn {\n\t\tasync get(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: GET_SPEC });\n\t\t},\n\t\tasync listLogs(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: LIST_LOGS_SPEC });\n\t\t},\n\t\tasync pollUntilDone(ref, options = {}) {\n\t\t\treturn pollUntilDoneCore(buildPollDependencies(inner, { options, ref }), options);\n\t\t},\n\t\tasync runUntilDone(parameters, options = {}) {\n\t\t\treturn submitAndPoll(inner, { options, parameters });\n\t\t},\n\t\tasync submit(parameters, options) {\n\t\t\tif (\"versionId\" in parameters) {\n\t\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_VERSION_SPEC });\n\t\t\t}\n\n\t\t\treturn inner.execute({ options, parameters, spec: SUBMIT_HEAD_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
@@ -2,7 +2,7 @@ import { n as NetworkError, r as ApiError } from "./rate-limit-Co9i28qi.mjs";
2
2
  import { c as findErrorCode, n as IDEMPOTENT_METHOD_DEFAULTS, r as TRANSIENT_TRANSPORT_CODES, t as CREATE_METHOD_DEFAULTS } from "./retry-CbHBw60o.mjs";
3
3
  import { n as PollAbortedError, t as PollTimeoutError } from "./poll-timeout-C0nmJzOd.mjs";
4
4
  import { t as ValidationError } from "./validation-9oU6qNNQ.mjs";
5
- import { a as isDateTimeString, i as isRecord, n as okRequest } from "./resource-client-lE7Tg3BK.mjs";
5
+ import { a as isDateTimeString, i as isRecord, n as okRequest } from "./resource-client-QIICmSU8.mjs";
6
6
  //#region src/domains/cloud-v2/luau-execution-task-logs/builders.ts
7
7
  /**
8
8
  * Builds a `GET` request for the Open Cloud "list Luau execution session
@@ -86,11 +86,15 @@ function parseListLogsResponse(response) {
86
86
  const rawToken = body["nextPageToken"] ?? void 0;
87
87
  if (rawToken !== void 0 && typeof rawToken !== "string") return malformed$1(statusCode);
88
88
  const messages = [];
89
- for (const chunk of rawChunks ?? []) for (const wireMessage of chunk.structuredMessages ?? []) messages.push({
90
- createTime: wireMessage.createTime,
91
- message: wireMessage.message,
92
- messageType: wireMessage.messageType
93
- });
89
+ const chunks = rawChunks ?? [];
90
+ for (const chunk of chunks) {
91
+ const wireMessages = chunk.structuredMessages ?? [];
92
+ for (const wireMessage of wireMessages) messages.push({
93
+ createTime: wireMessage.createTime,
94
+ message: wireMessage.message,
95
+ messageType: wireMessage.messageType
96
+ });
97
+ }
94
98
  return {
95
99
  data: {
96
100
  messages,
@@ -562,8 +566,8 @@ async function pollUntilDoneCore(deps, options = {}) {
562
566
  const pollDelay = options.pollDelay ?? defaultPollDelay;
563
567
  const maxFailures = options.maxConsecutivePollFailures ?? 3;
564
568
  const sig = options.signal;
565
- const startedAt = deps.now();
566
569
  if (sig?.aborted === true) return abortedResult(sig);
570
+ const startedAt = deps.now();
567
571
  let state = {
568
572
  consecutiveFailures: 0,
569
573
  lastTask: void 0
@@ -709,8 +713,8 @@ function isTransientTransport(error) {
709
713
  const code = findErrorCode(error);
710
714
  return code !== void 0 && TRANSIENT_TRANSPORT_CODES.includes(code);
711
715
  }
712
- async function fetchOnce(deps, signal) {
713
- const fetchResult = await raceWithAbort(deps.fetch(), signal);
716
+ async function fetchOnce(dependencies, signal) {
717
+ const fetchResult = await raceWithAbort(dependencies.fetch(), signal);
714
718
  if (fetchResult === ABORTED) return { kind: "aborted" };
715
719
  if (!fetchResult.success) return isTransientTransport(fetchResult.err) ? {
716
720
  error: fetchResult.err,
@@ -730,15 +734,15 @@ async function fetchOnce(deps, signal) {
730
734
  //#endregion
731
735
  //#region src/resources/luau-execution/polling-helpers.ts
732
736
  /**
733
- * Builds the {@link PollDeps} bundle used by {@link pollUntilDoneCore},
737
+ * Builds the {@link PollDependencies} bundle used by {@link pollUntilDoneCore},
734
738
  * closing over the supplied {@link ResourceClient}, task ref, and
735
739
  * per-request options so the core loop stays narrow.
736
740
  *
737
741
  * @param inner - The {@link ResourceClient} that issues each `tasks.get` call.
738
742
  * @param args - The polling options and the task ref to fetch on every iteration.
739
- * @returns A {@link PollDeps} bundle wiring `fetch`, `now`, and `sleep`.
743
+ * @returns A {@link PollDependencies} bundle wiring `fetch`, `now`, and `sleep`.
740
744
  */
741
- function buildPollDeps(inner, args) {
745
+ function buildPollDependencies(inner, args) {
742
746
  return {
743
747
  fetch: async () => {
744
748
  return inner.execute({
@@ -776,12 +780,12 @@ async function submitAndPoll(inner, args) {
776
780
  spec: SUBMIT_HEAD_SPEC
777
781
  }));
778
782
  if (!submitResult.success) return submitResult;
779
- return pollUntilDoneCore(buildPollDeps(inner, {
783
+ return pollUntilDoneCore(buildPollDependencies(inner, {
780
784
  options,
781
785
  ref: submitResult.data.ref
782
786
  }), options);
783
787
  }
784
788
  //#endregion
785
- export { withBudgetRequestTimeout as a, SUBMIT_VERSION_SPEC as c, pollUntilDoneCore as i, LIST_LOGS_SPEC as l, submitAndPoll as n, GET_SPEC as o, defaultPollDelay as r, SUBMIT_HEAD_SPEC as s, buildPollDeps as t };
789
+ export { withBudgetRequestTimeout as a, SUBMIT_VERSION_SPEC as c, pollUntilDoneCore as i, LIST_LOGS_SPEC as l, submitAndPoll as n, GET_SPEC as o, defaultPollDelay as r, SUBMIT_HEAD_SPEC as s, buildPollDependencies as t };
786
790
 
787
- //# sourceMappingURL=polling-helpers-Cb4j4cq7.mjs.map
791
+ //# sourceMappingURL=polling-helpers-BzeCsBFI.mjs.map