@bedrock-rbx/ocale 0.1.0-beta.9 → 0.1.1
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 +182 -0
- package/dist/badges.d.mts +33 -2
- package/dist/badges.d.mts.map +1 -1
- package/dist/badges.mjs +16 -4
- package/dist/badges.mjs.map +1 -1
- package/dist/{data.generated-Cb6g6asv.d.mts → data.generated-B2ceLfSn.d.mts} +9 -1
- package/dist/data.generated-B2ceLfSn.d.mts.map +1 -0
- package/dist/developer-products.d.mts +38 -2
- package/dist/developer-products.d.mts.map +1 -1
- package/dist/developer-products.mjs +32 -8
- package/dist/developer-products.mjs.map +1 -1
- package/dist/game-passes.d.mts +40 -2
- package/dist/game-passes.d.mts.map +1 -1
- package/dist/game-passes.mjs +30 -6
- package/dist/game-passes.mjs.map +1 -1
- package/dist/index.d.mts +21 -12
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -5
- package/dist/locales.d.mts +1 -1
- package/dist/locales.mjs +2 -0
- package/dist/locales.mjs.map +1 -1
- package/dist/luau-execution.d.mts +22 -3
- package/dist/luau-execution.d.mts.map +1 -1
- package/dist/luau-execution.mjs +29 -13
- package/dist/luau-execution.mjs.map +1 -1
- package/dist/places.d.mts +20 -2
- package/dist/places.d.mts.map +1 -1
- package/dist/places.mjs +34 -14
- package/dist/places.mjs.map +1 -1
- package/dist/{poll-timeout-Dg_QFEqi.mjs → poll-timeout-BfxUWWCZ.mjs} +6 -2
- package/dist/poll-timeout-BfxUWWCZ.mjs.map +1 -0
- package/dist/{polling-helpers-CS00apdU.mjs → polling-helpers-DCw9LyJM.mjs} +225 -78
- package/dist/polling-helpers-DCw9LyJM.mjs.map +1 -0
- package/dist/{polling-BMrYajok.d.mts → polling-rj0dGREg.d.mts} +73 -14
- package/dist/polling-rj0dGREg.d.mts.map +1 -0
- package/dist/{price-information-DIrvwCmd.mjs → price-information-C4gC2CMZ.mjs} +2 -2
- package/dist/{price-information-DIrvwCmd.mjs.map → price-information-C4gC2CMZ.mjs.map} +1 -1
- package/dist/{rate-limit-D1q2Js-z.mjs → rate-limit-Dh2leqaB.mjs} +49 -3
- package/dist/rate-limit-Dh2leqaB.mjs.map +1 -0
- package/dist/resource-client-CIAkS2xQ.mjs +960 -0
- package/dist/resource-client-CIAkS2xQ.mjs.map +1 -0
- package/dist/retry-Bh2nNjBV.d.mts +234 -0
- package/dist/retry-Bh2nNjBV.d.mts.map +1 -0
- package/dist/retry-BvZRZDXs.mjs +380 -0
- package/dist/retry-BvZRZDXs.mjs.map +1 -0
- package/dist/{signatures-B5Fojgn0.mjs → signatures-JF-7Psce.mjs} +1 -1
- package/dist/{signatures-B5Fojgn0.mjs.map → signatures-JF-7Psce.mjs.map} +1 -1
- package/dist/storage.d.mts +30 -27
- package/dist/storage.d.mts.map +1 -1
- package/dist/storage.mjs +46 -31
- package/dist/storage.mjs.map +1 -1
- package/dist/testing.d.mts +24 -9
- package/dist/testing.d.mts.map +1 -1
- package/dist/testing.mjs +2 -2
- package/dist/testing.mjs.map +1 -1
- package/dist/{to-blob-B27VhoRp.mjs → to-blob-RPqMBuft.mjs} +1 -1
- package/dist/{to-blob-B27VhoRp.mjs.map → to-blob-RPqMBuft.mjs.map} +1 -1
- package/dist/{types-CwtZT1ek.d.mts → types-CRiJg5EQ.d.mts} +46 -4
- package/dist/types-CRiJg5EQ.d.mts.map +1 -0
- package/dist/universes.d.mts +47 -5
- package/dist/universes.d.mts.map +1 -1
- package/dist/universes.mjs +31 -15
- package/dist/universes.mjs.map +1 -1
- package/dist/{validation-DkL5KQqz.mjs → validation-xJZRa8tX.mjs} +4 -2
- package/dist/validation-xJZRa8tX.mjs.map +1 -0
- package/dist/{wire-CeL6W_V7.d.mts → wire-D3K-a-UP.d.mts} +3 -1
- package/dist/wire-D3K-a-UP.d.mts.map +1 -0
- package/package.json +6 -5
- package/dist/data.generated-Cb6g6asv.d.mts.map +0 -1
- package/dist/permission-error-DOVtNq3A.mjs +0 -46
- package/dist/permission-error-DOVtNq3A.mjs.map +0 -1
- package/dist/poll-timeout-Dg_QFEqi.mjs.map +0 -1
- package/dist/polling-BMrYajok.d.mts.map +0 -1
- package/dist/polling-helpers-CS00apdU.mjs.map +0 -1
- package/dist/rate-limit-BYuizHoD.d.mts +0 -92
- package/dist/rate-limit-BYuizHoD.d.mts.map +0 -1
- package/dist/rate-limit-D1q2Js-z.mjs.map +0 -1
- package/dist/resource-client-D6Efj9fU.mjs +0 -732
- package/dist/resource-client-D6Efj9fU.mjs.map +0 -1
- package/dist/types-CwtZT1ek.d.mts.map +0 -1
- package/dist/validation-DkL5KQqz.mjs.map +0 -1
- package/dist/wire-CeL6W_V7.d.mts.map +0 -1
package/README.md
ADDED
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
# @bedrock-rbx/ocale
|
|
2
|
+
|
|
3
|
+
Zero-dependency TypeScript SDK for Roblox Open Cloud.
|
|
4
|
+
|
|
5
|
+
[](https://npmx.dev/package/@bedrock-rbx/ocale)
|
|
6
|
+
[](https://github.com/christopher-buss/bedrock/blob/main/LICENSE)
|
|
7
|
+
[](https://github.com/christopher-buss/bedrock/actions/workflows/ci.yaml)
|
|
8
|
+
|
|
9
|
+
> **Status: 0.1, pre-1.0.** The public API is stabilizing; breaking changes may
|
|
10
|
+
> land in minor releases until 1.0.
|
|
11
|
+
|
|
12
|
+
## What is `@bedrock-rbx/ocale`?
|
|
13
|
+
|
|
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.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
pnpm add @bedrock-rbx/ocale
|
|
40
|
+
# or: npm install @bedrock-rbx/ocale
|
|
41
|
+
# or: bun add @bedrock-rbx/ocale
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
**Runtime:** Node >= 24.12 or Bun >= 1.3.
|
|
45
|
+
|
|
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).
|
|
51
|
+
|
|
52
|
+
## Quick start
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { GamePassesClient } from "@bedrock-rbx/ocale/game-passes";
|
|
56
|
+
|
|
57
|
+
const client = new GamePassesClient({ apiKey: "your-open-cloud-api-key" });
|
|
58
|
+
|
|
59
|
+
const result = await client.get({
|
|
60
|
+
gamePassId: "9876543210",
|
|
61
|
+
universeId: "1234567890", // from your experience URL in Creator Hub
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
console.error(`Open Cloud call failed: ${result.err.message}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(`${result.data.name} (${result.data.id})`);
|
|
70
|
+
```
|
|
71
|
+
|
|
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.
|
|
76
|
+
|
|
77
|
+
## Available clients
|
|
78
|
+
|
|
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.
|
|
101
|
+
|
|
102
|
+
## Rate limiting and retries
|
|
103
|
+
|
|
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.
|
|
107
|
+
|
|
108
|
+
Retry behavior is idempotency-aware:
|
|
109
|
+
|
|
110
|
+
| Method kind | 429 (rate limit) | 5xx (server error) |
|
|
111
|
+
| ----------- | ---------------- | ------------------ |
|
|
112
|
+
| Create | Retry | Do not retry |
|
|
113
|
+
| Read / List | Retry | Retry |
|
|
114
|
+
| Update | Retry | Retry |
|
|
115
|
+
| Delete | Retry | Retry |
|
|
116
|
+
|
|
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.
|
|
121
|
+
|
|
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).
|
|
125
|
+
|
|
126
|
+
Observability hooks (`onRequest`, `onRetry`, `onRateLimit`) accept callbacks on
|
|
127
|
+
the client constructor for logging, metrics, or tracing integration.
|
|
128
|
+
|
|
129
|
+
## Per-request configuration overrides
|
|
130
|
+
|
|
131
|
+
Client-level config is frozen on construction. Every method accepts an optional
|
|
132
|
+
second `RequestOptions` argument that overrides config for a single call:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
const client = new GamePassesClient({ apiKey: "main-key" });
|
|
136
|
+
|
|
137
|
+
const result = await client.create(parameters, {
|
|
138
|
+
apiKey: "asset-upload-key", // different key for moderation safety
|
|
139
|
+
timeout: 60_000,
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
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.
|
|
146
|
+
|
|
147
|
+
## Testing helpers
|
|
148
|
+
|
|
149
|
+
A `@bedrock-rbx/ocale/testing` subpath exports the same fakes the SDK's own
|
|
150
|
+
integration tests use:
|
|
151
|
+
|
|
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.
|
|
157
|
+
- `createFakeSleep(...)` for deterministic retry and rate-limit timing.
|
|
158
|
+
- `valid*Body` fixtures (`validGamePassBody`, `validPlaceBody`,
|
|
159
|
+
`validUniverseBody`, and similar) for synthesising realistic response
|
|
160
|
+
payloads.
|
|
161
|
+
|
|
162
|
+
Pass the fake into any client via the `httpClient` and `sleep` parameters on
|
|
163
|
+
`OpenCloudClientOptions` and assert against the captured requests.
|
|
164
|
+
|
|
165
|
+
## Status, docs, and contributing
|
|
166
|
+
|
|
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).
|
|
169
|
+
|
|
170
|
+
- [Documentation site](https://bedrock-livid.vercel.app/) (work in progress)
|
|
171
|
+
- [Source repository](https://github.com/christopher-buss/bedrock/tree/main/packages/open-cloud)
|
|
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)
|
|
176
|
+
- [Contributing guide](https://github.com/christopher-buss/bedrock/blob/main/CONTRIBUTING.md)
|
|
177
|
+
- [Security policy](https://github.com/christopher-buss/bedrock/blob/main/SECURITY.md)
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
[MIT](https://github.com/christopher-buss/bedrock/blob/main/LICENSE) (c)
|
|
182
|
+
Christopher Buss.
|
package/dist/badges.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, s as RequestOptions } from "./types-
|
|
2
|
-
import { i as RobloxLocale, r as RobloxLanguageCode } from "./data.generated-
|
|
1
|
+
import { d as OpenCloudError, i as OpenCloudClientOptions, l as Result, s as RequestOptions } from "./types-CRiJg5EQ.mjs";
|
|
2
|
+
import { i as RobloxLocale, r as RobloxLanguageCode } from "./data.generated-B2ceLfSn.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/domains/badges/badges/types.d.ts
|
|
5
5
|
/**
|
|
@@ -7,11 +7,15 @@ import { i as RobloxLocale, r as RobloxLanguageCode } from "./data.generated-Cb6
|
|
|
7
7
|
* `Place`, so the wire enum carries a single value; the public type
|
|
8
8
|
* preserves the string label so future awarder kinds can be added
|
|
9
9
|
* without a breaking change.
|
|
10
|
+
*
|
|
11
|
+
* @since 0.1.0
|
|
10
12
|
*/
|
|
11
13
|
type BadgeAwarderType = "Place";
|
|
12
14
|
/**
|
|
13
15
|
* The entity that awards a badge. Always a place at present; the
|
|
14
16
|
* `id` is the awarding place's ID and `name` its display name.
|
|
17
|
+
*
|
|
18
|
+
* @since 0.1.0
|
|
15
19
|
*/
|
|
16
20
|
interface BadgeAwarder {
|
|
17
21
|
/** Stringified ID of the awarding entity. */
|
|
@@ -23,6 +27,8 @@ interface BadgeAwarder {
|
|
|
23
27
|
}
|
|
24
28
|
/**
|
|
25
29
|
* Award statistics for a badge.
|
|
30
|
+
*
|
|
31
|
+
* @since 0.1.0
|
|
26
32
|
*/
|
|
27
33
|
interface BadgeStatistics {
|
|
28
34
|
/** Total number of times the badge has been awarded. */
|
|
@@ -34,10 +40,14 @@ interface BadgeStatistics {
|
|
|
34
40
|
}
|
|
35
41
|
/**
|
|
36
42
|
* Source of funds for the Robux fee charged on badge creation.
|
|
43
|
+
*
|
|
44
|
+
* @since 0.1.0
|
|
37
45
|
*/
|
|
38
46
|
type BadgePaymentSource = "Group" | "User";
|
|
39
47
|
/**
|
|
40
48
|
* Parameters for creating a new badge under a universe.
|
|
49
|
+
*
|
|
50
|
+
* @since 0.1.0
|
|
41
51
|
*/
|
|
42
52
|
interface CreateBadgeParameters {
|
|
43
53
|
/** Display name of the new badge. */
|
|
@@ -59,6 +69,8 @@ interface CreateBadgeParameters {
|
|
|
59
69
|
* Parameters for partially updating an existing badge. Every field
|
|
60
70
|
* except the identifier is optional; omitted fields are not included
|
|
61
71
|
* in the JSON body so the server leaves their current values untouched.
|
|
72
|
+
*
|
|
73
|
+
* @since 0.1.0
|
|
62
74
|
*/
|
|
63
75
|
interface UpdateBadgeParameters {
|
|
64
76
|
/** Optional new source-language display name. */
|
|
@@ -74,6 +86,8 @@ interface UpdateBadgeParameters {
|
|
|
74
86
|
* A Roblox badge as exposed to SDK consumers. Fields use DX-friendly
|
|
75
87
|
* names and types (stringified IDs, `Date` timestamps) rather than the
|
|
76
88
|
* raw wire representation.
|
|
89
|
+
*
|
|
90
|
+
* @since 0.1.0
|
|
77
91
|
*/
|
|
78
92
|
interface Badge {
|
|
79
93
|
/** Stringified badge ID. The API returns an int64; always use this. */
|
|
@@ -108,6 +122,8 @@ interface Badge {
|
|
|
108
122
|
* against a badge. A subsequent upload for the same `(badgeId, languageCode)`
|
|
109
123
|
* pair replaces the existing icon for that locale. Source-language icons
|
|
110
124
|
* are managed through `BadgesClient.uploadIcon`.
|
|
125
|
+
*
|
|
126
|
+
* @since 0.1.0
|
|
111
127
|
*/
|
|
112
128
|
interface UploadBadgeIconLocalizationParameters {
|
|
113
129
|
/** Stringified ID of the badge whose icon is being uploaded. */
|
|
@@ -128,6 +144,8 @@ interface UploadBadgeIconLocalizationParameters {
|
|
|
128
144
|
* against a badge. Both `name` and `description` are optional; fields omitted
|
|
129
145
|
* from the call are not included in the JSON body so the server leaves the
|
|
130
146
|
* existing value for that locale untouched.
|
|
147
|
+
*
|
|
148
|
+
* @since 0.1.0
|
|
131
149
|
*/
|
|
132
150
|
interface UpdateBadgeNameDescriptionParameters {
|
|
133
151
|
/** Replacement display name for the supplied locale. */
|
|
@@ -151,6 +169,8 @@ interface UpdateBadgeNameDescriptionParameters {
|
|
|
151
169
|
* replaces the existing source icon; per-locale icon overlays live
|
|
152
170
|
* under a separate `legacy-game-internationalization` endpoint and
|
|
153
171
|
* are managed through `BadgesClient.localization.uploadIcon`.
|
|
172
|
+
*
|
|
173
|
+
* @since 0.1.0
|
|
154
174
|
*/
|
|
155
175
|
interface UploadBadgeIconParameters {
|
|
156
176
|
/** Stringified ID of the badge whose icon is being uploaded. */
|
|
@@ -182,6 +202,9 @@ interface BadgeLocalizationHandle {
|
|
|
182
202
|
* upload cannot be created if the server fails mid-write. Source-language
|
|
183
203
|
* icons remain on {@link BadgesClient.uploadIcon}.
|
|
184
204
|
*
|
|
205
|
+
* No default request timeout applies to this upload; pass `options.timeout`
|
|
206
|
+
* to set a per-call deadline.
|
|
207
|
+
*
|
|
185
208
|
* @param parameters - Badge and language identifiers plus the image bytes
|
|
186
209
|
* to upload.
|
|
187
210
|
* @param options - Optional per-request overrides.
|
|
@@ -201,6 +224,8 @@ interface BadgeLocalizationHandle {
|
|
|
201
224
|
* callers handle failure explicitly; no thrown {@link OpenCloudError}
|
|
202
225
|
* ever escapes the client.
|
|
203
226
|
*
|
|
227
|
+
* @since 0.1.0
|
|
228
|
+
*
|
|
204
229
|
* @example
|
|
205
230
|
*
|
|
206
231
|
* ```ts
|
|
@@ -232,6 +257,9 @@ declare class BadgesClient {
|
|
|
232
257
|
/**
|
|
233
258
|
* Creates a new badge under the supplied universe.
|
|
234
259
|
*
|
|
260
|
+
* No default request timeout applies to this upload; pass `options.timeout`
|
|
261
|
+
* to set a per-call deadline.
|
|
262
|
+
*
|
|
235
263
|
* @param parameters - Creation fields including the universe, name, and
|
|
236
264
|
* icon image.
|
|
237
265
|
* @param options - Optional per-request overrides.
|
|
@@ -257,6 +285,9 @@ declare class BadgesClient {
|
|
|
257
285
|
* existing source icon. Does not retry on 5xx so a duplicate icon
|
|
258
286
|
* upload cannot be created if the server fails mid-write.
|
|
259
287
|
*
|
|
288
|
+
* No default request timeout applies to this upload; pass `options.timeout`
|
|
289
|
+
* to set a per-call deadline.
|
|
290
|
+
*
|
|
260
291
|
* @param parameters - Identifier plus the image bytes to upload.
|
|
261
292
|
* @param options - Optional per-request overrides.
|
|
262
293
|
* @returns A success {@link Result} with no payload, or the
|
package/dist/badges.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badges.d.mts","names":[],"sources":["../src/domains/badges/badges/types.ts","../src/domains/game-internationalization/badge-icon/types.ts","../src/domains/game-internationalization/badge-name-description/types.ts","../src/domains/publish/badge-icon/types.ts","../src/resources/badges/client.ts"],"mappings":";;;;;;;;
|
|
1
|
+
{"version":3,"file":"badges.d.mts","names":[],"sources":["../src/domains/badges/badges/types.ts","../src/domains/game-internationalization/badge-icon/types.ts","../src/domains/game-internationalization/badge-name-description/types.ts","../src/domains/publish/badge-icon/types.ts","../src/resources/badges/client.ts"],"mappings":";;;;;;;;AAQA;;;;KAAY,gBAAA;AAQZ;;;;;;AAAA,UAAiB,YAAA;;WAEP,EAAA;EAIM;EAAA,SAFN,IAAA;EAUO;EAAA,SARP,IAAA,EAAM,gBAAA;AAAA;;;;;AAcN;UANO,eAAA;EAcL;EAAA,SAZF,YAAA;EAYE;EAAA,SAVF,mBAAA;EAiBV;EAAA,SAfU,iBAAA;AAAA;;;;;;KAQE,kBAAA;;;;;;UAOK,qBAAA;;WAEP,IAAA;;WAEA,WAAA;EAUA;EAAA,SARA,YAAA;EAkBO;EAAA,SAhBP,IAAA,EAAM,IAAA,GAAO,UAAA;EAgBN;EAAA,SAdP,QAAA;;WAEA,aAAA,GAAgB,kBAAA;;WAEhB,UAAA;AAAA;AA4BV;;;;;;;AAAA,UAlBiB,qBAAA;EA0CI;EAAA,SAxCX,IAAA;;WAEA,OAAA;;WAEA,WAAA;;WAEA,OAAA;AAAA;;;;;;;;UAUO,KAAA;EAwBI;EAAA,SAtBX,EAAA;;WAEA,IAAA;;WAEA,OAAA,EAAS,YAAA;ECzFF;EAAA,SD2FP,SAAA,EAAW,IAAA;;WAEX,WAAA;;WAEA,kBAAA;ECrFmC;EAAA,SDuFnC,kBAAA;;WAEA,WAAA;;WAEA,OAAA;;WAEA,WAAA;;WAEA,UAAA,EAAY,eAAA;EC/FuB;EAAA,SDiGnC,SAAA,EAAW,IAAA;AAAA;;;;;;AA7GrB;;;;AAAY;UCEK,qCAAA;EDMA;EAAA,SCJP,OAAA;EDUM;EAAA,SCRN,KAAA,EAAO,IAAA,GAAO,UAAA;;;;;ADQR;WCFN,YAAA,EAAc,kBAAA,GAAqB,YAAA;AAAA;;;;;;ADZ7C;;;;AAAY;UEEK,oCAAA;EFMA;EAAA,SEJP,IAAA;EFUM;EAAA,SERN,OAAA;;WAEA,WAAA;;;AFMM;AAQhB;;WERU,YAAA,EAAc,kBAAA,GAAqB,YAAA;AAAA;;;;;;;AFd7C;;;;AAAY;UGCK,yBAAA;EHOA;EAAA,SGLP,OAAA;EHWM;EAAA,SGTN,IAAA,EAAM,IAAA,GAAO,UAAA;AAAA;;;UC0Eb,uBAAA;EJ/EE;AAQZ;;;;;;;;;AAMgB;AAQhB;;EIuEC,qBAAA,GACC,UAAA,EAAY,oCAAA,EACZ,OAAA,GAAU,cAAA,KACN,OAAA,CAAQ,MAAA,YAAkB,cAAA;EJ1Ef;;;;;AAMP;AAQV;;;;AAAY;AAOZ;;;;;EIsEC,UAAA,GACC,UAAA,EAAY,qCAAA,EACZ,OAAA,GAAU,cAAA,KACN,OAAA,CAAQ,MAAA,YAAkB,cAAA;AAAA;;;;;;;;;;;;;AJ3DtB;AAUV;;;;;;;;;cI0Ea,YAAA;EAAA;EJxDI;;;;;;;;;EAAA,SIoEA,YAAA,EAAc,uBAAA;;;;;;;EAQ9B,WAAA,CAAY,OAAA,EAAS,sBAAA;;;;;;;;;AJpDD;;;;EIqEpB,MAAA,CACC,UAAA,EAAY,qBAAA,EACZ,OAAA,GAAU,cAAA,GACR,OAAA,CAAQ,MAAA,CAAO,KAAA,EAAO,cAAA;EHnLT;;;;;;;;;;;EGkMhB,MAAA,CACC,UAAA,EAAY,qBAAA,EACZ,OAAA,GAAU,cAAA,GACR,OAAA,CAAQ,MAAA,YAAkB,cAAA;;;;;AH3Le;;;;ACV7C;;;;;;EEuNC,UAAA,CACC,UAAA,EAAY,yBAAA,EACZ,OAAA,GAAU,cAAA,GACR,OAAA,CAAQ,MAAA,YAAkB,cAAA;AAAA"}
|
package/dist/badges.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { r as ApiError } from "./rate-limit-
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
1
|
+
import { r as ApiError } from "./rate-limit-Dh2leqaB.mjs";
|
|
2
|
+
import { n as IDEMPOTENT_METHOD_DEFAULTS, t as CREATE_METHOD_DEFAULTS } from "./retry-BvZRZDXs.mjs";
|
|
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-CIAkS2xQ.mjs";
|
|
4
5
|
//#region src/domains/badges/badges/builders.ts
|
|
5
6
|
/**
|
|
6
7
|
* Builds a `POST` request for the legacy "create badge" endpoint.
|
|
@@ -98,7 +99,10 @@ const UPDATE_REQUIRED_SCOPES = Object.freeze(["legacy-universe.badge:write"]);
|
|
|
98
99
|
function parseBadgeResponse(response) {
|
|
99
100
|
const { body, status: statusCode } = response;
|
|
100
101
|
if (!isBadgeResponseV2Wire(body)) return {
|
|
101
|
-
err: new ApiError("Malformed badge response", {
|
|
102
|
+
err: new ApiError("Malformed badge response", {
|
|
103
|
+
details: body,
|
|
104
|
+
statusCode
|
|
105
|
+
}),
|
|
102
106
|
success: false
|
|
103
107
|
};
|
|
104
108
|
return {
|
|
@@ -308,6 +312,8 @@ const UPLOAD_LOCALIZED_ICON_SPEC = makeSpec({
|
|
|
308
312
|
* callers handle failure explicitly; no thrown {@link OpenCloudError}
|
|
309
313
|
* ever escapes the client.
|
|
310
314
|
*
|
|
315
|
+
* @since 0.1.0
|
|
316
|
+
*
|
|
311
317
|
* @example
|
|
312
318
|
*
|
|
313
319
|
* ```ts
|
|
@@ -342,6 +348,9 @@ var BadgesClient = class {
|
|
|
342
348
|
/**
|
|
343
349
|
* Creates a new badge under the supplied universe.
|
|
344
350
|
*
|
|
351
|
+
* No default request timeout applies to this upload; pass `options.timeout`
|
|
352
|
+
* to set a per-call deadline.
|
|
353
|
+
*
|
|
345
354
|
* @param parameters - Creation fields including the universe, name, and
|
|
346
355
|
* icon image.
|
|
347
356
|
* @param options - Optional per-request overrides.
|
|
@@ -379,6 +388,9 @@ var BadgesClient = class {
|
|
|
379
388
|
* existing source icon. Does not retry on 5xx so a duplicate icon
|
|
380
389
|
* upload cannot be created if the server fails mid-write.
|
|
381
390
|
*
|
|
391
|
+
* No default request timeout applies to this upload; pass `options.timeout`
|
|
392
|
+
* to set a per-call deadline.
|
|
393
|
+
*
|
|
382
394
|
* @param parameters - Identifier plus the image bytes to upload.
|
|
383
395
|
* @param options - Optional per-request overrides.
|
|
384
396
|
* @returns A success {@link Result} with no payload, or the
|
package/dist/badges.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"badges.mjs","names":["buildUpdateRequest","buildUploadIconRequest","buildUpdateRequest","buildLocaleNameDescRequest","buildLocaleUploadIconRequest","#inner"],"sources":["../src/domains/badges/badges/builders.ts","../src/domains/badges/badges/operations.ts","../src/domains/badges/badges/parsers.ts","../src/domains/game-internationalization/badge-icon/builders.ts","../src/domains/game-internationalization/badge-name-description/builders.ts","../src/domains/game-internationalization/badge-name-description/operations.ts","../src/domains/publish/badge-icon/builders.ts","../src/domains/publish/badge-icon/operations.ts","../src/resources/badges/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { BadgePaymentSource, CreateBadgeParameters, UpdateBadgeParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the legacy \"create badge\" endpoint.\n *\n * @param parameters - Fields describing the new badge; optional values\n * omitted here are left off the multipart payload entirely.\n * @returns A pure {@link HttpRequest} describing the create call.\n */\nexport function buildCreateRequest(parameters: CreateBadgeParameters): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"name\", parameters.name);\n\tbody.append(\"files\", toBlob(parameters.icon));\n\tif (parameters.description !== undefined) {\n\t\tbody.append(\"description\", parameters.description);\n\t}\n\n\tif (parameters.isActive !== undefined) {\n\t\tbody.append(\"isActive\", String(parameters.isActive));\n\t}\n\n\tif (parameters.expectedCost !== undefined) {\n\t\tbody.append(\"expectedCost\", String(parameters.expectedCost));\n\t}\n\n\tif (parameters.paymentSource !== undefined) {\n\t\tbody.append(\"paymentSourceType\", toPaymentSourceWire(parameters.paymentSource));\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-badges/v1/universes/${parameters.universeId}/badges`,\n\t};\n}\n\n/**\n * Builds a `PATCH` request for the legacy \"update badge\" endpoint. Every\n * field on `parameters` except the identifier is optional; omitted fields\n * are not appended to the JSON body so the server leaves them unchanged.\n *\n * @param parameters - Identifier plus fields to update.\n * @returns A pure {@link HttpRequest} describing the update call.\n */\nexport function buildUpdateRequest(parameters: UpdateBadgeParameters): HttpRequest {\n\tconst body: Record<string, boolean | string> = {};\n\tif (parameters.name !== undefined) {\n\t\tbody[\"name\"] = parameters.name;\n\t}\n\n\tif (parameters.description !== undefined) {\n\t\tbody[\"description\"] = parameters.description;\n\t}\n\n\tif (parameters.enabled !== undefined) {\n\t\tbody[\"enabled\"] = parameters.enabled;\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"PATCH\",\n\t\turl: `/legacy-badges/v1/badges/${parameters.badgeId}`,\n\t};\n}\n\nfunction toPaymentSourceWire(source: BadgePaymentSource): \"1\" | \"2\" {\n\treturn source === \"User\" ? \"1\" : \"2\";\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for creating a badge, sourced from\n * `x-roblox-rate-limits` on the legacy badges create operation in the\n * vendored OpenAPI schema (100 per minute, per API key owner).\n */\nexport const CREATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.create\",\n});\n\n/**\n * Per-second request ceiling for updating a badge, sourced from\n * `x-roblox-rate-limits` on the legacy badges update operation in the\n * vendored OpenAPI schema. Keyed independently from\n * {@link CREATE_OPERATION_LIMIT} so create and update do not share a\n * queue, since Roblox does not document the per-minute quota as shared\n * between the POST and PATCH endpoints.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.update\",\n});\n\n/**\n * Scopes the API key or OAuth token must carry to create a badge,\n * sourced from `x-roblox-scopes` on the legacy badges create operation\n * in the vendored OpenAPI schema. The trailing\n * `:manage-and-spend-robux` reflects that badge creation may charge a\n * Robux fee.\n */\nexport const CREATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe.badge:manage-and-spend-robux\",\n]);\n\n/**\n * Scopes the API key or OAuth token must carry to update a badge,\n * sourced from `x-roblox-scopes` on the legacy badges update operation\n * in the vendored OpenAPI schema.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe.badge: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 { Badge, BadgeAwarder, BadgeStatistics } from \"./types.ts\";\nimport type { BadgeAwarderWire, BadgeResponseV2Wire, BadgeStatisticsWire } from \"./wire.ts\";\n\n/**\n * Parses a successful Badges API response into the public `Badge` shape,\n * returning a `Result` so callers can handle malformed payloads without\n * exceptions.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * The status code is included on the returned `ApiError` when validation\n * fails; the headers are available for future parsers that need them.\n * @returns A success result wrapping the converted `Badge`, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseBadgeResponse(response: HttpResponse): Result<Badge, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isBadgeResponseV2Wire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed badge response\", { statusCode }),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tid: String(body.id),\n\t\t\tname: body.name,\n\t\t\tawarder: copyAwarder(body.awarder),\n\t\t\tcreatedAt: new Date(body.created),\n\t\t\tdescription: body.description,\n\t\t\tdisplayDescription: body.displayDescription,\n\t\t\tdisplayIconImageId:\n\t\t\t\tbody.displayIconImageId === 0 ? undefined : String(body.displayIconImageId),\n\t\t\tdisplayName: body.displayName,\n\t\t\tenabled: body.enabled,\n\t\t\ticonImageId: body.iconImageId === 0 ? undefined : String(body.iconImageId),\n\t\t\tstatistics: copyStatistics(body.statistics),\n\t\t\tupdatedAt: new Date(body.updated),\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction copyAwarder(awarder: BadgeAwarderWire): BadgeAwarder {\n\treturn { id: String(awarder.id), name: awarder.name, type: \"Place\" };\n}\n\nfunction copyStatistics(statistics: BadgeStatisticsWire): BadgeStatistics {\n\treturn {\n\t\tawardedCount: statistics.awardedCount,\n\t\tpastDayAwardedCount: statistics.pastDayAwardedCount,\n\t\twinRatePercentage: statistics.winRatePercentage,\n\t};\n}\n\nfunction hasRequiredPrimitiveFields(body: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof body[\"id\"] === \"number\" &&\n\t\ttypeof body[\"name\"] === \"string\" &&\n\t\ttypeof body[\"description\"] === \"string\" &&\n\t\ttypeof body[\"displayName\"] === \"string\" &&\n\t\ttypeof body[\"displayDescription\"] === \"string\" &&\n\t\ttypeof body[\"enabled\"] === \"boolean\" &&\n\t\ttypeof body[\"iconImageId\"] === \"number\" &&\n\t\ttypeof body[\"displayIconImageId\"] === \"number\" &&\n\t\tisDateTimeString(body[\"created\"]) &&\n\t\tisDateTimeString(body[\"updated\"])\n\t);\n}\n\nfunction isBadgeAwarderWire(value: unknown): value is BadgeAwarderWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"id\"] === \"number\" && typeof value[\"name\"] === \"string\" && value[\"type\"] === 1\n\t);\n}\n\nfunction isBadgeStatisticsWire(value: unknown): value is BadgeStatisticsWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"awardedCount\"] === \"number\" &&\n\t\ttypeof value[\"pastDayAwardedCount\"] === \"number\" &&\n\t\ttypeof value[\"winRatePercentage\"] === \"number\"\n\t);\n}\n\nfunction isBadgeResponseV2Wire(body: unknown): body is BadgeResponseV2Wire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\tif (!hasRequiredPrimitiveFields(body)) {\n\t\treturn false;\n\t}\n\n\tif (!isBadgeAwarderWire(body[\"awarder\"])) {\n\t\treturn false;\n\t}\n\n\tif (!isBadgeStatisticsWire(body[\"statistics\"])) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { UploadBadgeIconLocalizationParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the localized \"upload badge icon\" endpoint. A\n * successful upload replaces any existing icon for the same\n * `(badgeId, languageCode)` pair.\n *\n * @param parameters - Badge and language identifiers plus the image bytes\n * to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(\n\tparameters: UploadBadgeIconLocalizationParameters,\n): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"Files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-game-internationalization/v1/badges/${parameters.badgeId}/icons/language-codes/${parameters.languageCode}`,\n\t};\n}\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport type { UpdateBadgeNameDescriptionParameters } from \"./types.ts\";\n\n/**\n * Builds a `PATCH` request for the localized \"update badge name/description\"\n * endpoint. Either `name`, `description`, or both may be supplied; omitted\n * fields are not included in the JSON body so the server leaves the existing\n * value for that locale untouched.\n *\n * @param parameters - Badge and language identifiers plus the optional\n * replacement values.\n * @returns A pure {@link HttpRequest} describing the update call.\n */\nexport function buildUpdateRequest(parameters: UpdateBadgeNameDescriptionParameters): HttpRequest {\n\tconst body: Record<string, string> = {};\n\tif (parameters.name !== undefined) {\n\t\tbody[\"name\"] = parameters.name;\n\t}\n\n\tif (parameters.description !== undefined) {\n\t\tbody[\"description\"] = parameters.description;\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"PATCH\",\n\t\turl: `/legacy-game-internationalization/v1/badges/${parameters.badgeId}/name-description/language-codes/${parameters.languageCode}`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every badge localization Operation. The\n * legacy `gameinternationalization` service caps each API key at 100\n * requests per minute *shared across the entire service* (see the\n * `x-roblox-rate-limits` extension on every operation in the vendored\n * Open Cloud spec), so all badge localization methods queue against the\n * same operation key.\n */\nexport const LOCALIZATION_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badge-localization\",\n});\n\n/**\n * Scopes required for every badge localization operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` badge\n * endpoints in the vendored OpenAPI schema.\n */\nexport const LOCALIZATION_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-badge:manage\",\n]);\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { UploadBadgeIconParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the legacy \"upload badge icon\" endpoint. A\n * successful upload replaces any existing source-language icon on the\n * badge.\n *\n * @param parameters - Badge identifier plus the image bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(parameters: UploadBadgeIconParameters): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"Files\", toBlob(parameters.icon));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-publish/v1/badges/${parameters.badgeId}/icon`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for uploading a badge icon, sourced from\n * `x-roblox-rate-limits` on the legacy badge icon upload operation in\n * the vendored OpenAPI schema (100 per minute, per API key owner). Keyed\n * separately from the badges create and update buckets because Roblox\n * does not document the legacy-publish quota as shared with the\n * legacy-badges quota.\n */\nexport const UPLOAD_ICON_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.upload-icon\",\n});\n\n/**\n * Scopes the API key or OAuth token must carry to upload a badge icon,\n * sourced from `x-roblox-scopes` on the legacy badge icon upload\n * operation in the vendored OpenAPI schema.\n */\nexport const UPLOAD_ICON_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-badge:manage\",\n]);\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildCreateRequest, buildUpdateRequest } from \"../../domains/badges/badges/builders.ts\";\nimport {\n\tCREATE_OPERATION_LIMIT,\n\tCREATE_REQUIRED_SCOPES,\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/badges/badges/operations.ts\";\nimport { parseBadgeResponse } from \"../../domains/badges/badges/parsers.ts\";\nimport type {\n\tBadge,\n\tCreateBadgeParameters,\n\tUpdateBadgeParameters,\n} from \"../../domains/badges/badges/types.ts\";\nimport { buildUploadIconRequest as buildLocaleUploadIconRequest } from \"../../domains/game-internationalization/badge-icon/builders.ts\";\nimport type { UploadBadgeIconLocalizationParameters } from \"../../domains/game-internationalization/badge-icon/types.ts\";\nimport { buildUpdateRequest as buildLocaleNameDescRequest } from \"../../domains/game-internationalization/badge-name-description/builders.ts\";\nimport {\n\tLOCALIZATION_OPERATION_LIMIT,\n\tLOCALIZATION_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/badge-name-description/operations.ts\";\nimport type { UpdateBadgeNameDescriptionParameters } from \"../../domains/game-internationalization/badge-name-description/types.ts\";\nimport { buildUploadIconRequest } from \"../../domains/publish/badge-icon/builders.ts\";\nimport {\n\tUPLOAD_ICON_OPERATION_LIMIT,\n\tUPLOAD_ICON_REQUIRED_SCOPES,\n} from \"../../domains/publish/badge-icon/operations.ts\";\nimport type { UploadBadgeIconParameters } from \"../../domains/publish/badge-icon/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS, IDEMPOTENT_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport {\n\tokRequest,\n\tparseEmptyResponse,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\n\nfunction makeSpec<P, R>(spec: ResourceMethodSpec<P, R>): ResourceMethodSpec<P, R> {\n\treturn Object.freeze(spec);\n}\n\nconst CREATE_SPEC = makeSpec<CreateBadgeParameters, Badge>({\n\tbuildRequest: (parameters) => okRequest(buildCreateRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: CREATE_OPERATION_LIMIT,\n\tparse: parseBadgeResponse,\n\trequiredScopes: CREATE_REQUIRED_SCOPES,\n});\n\nconst UPDATE_SPEC = makeSpec<UpdateBadgeParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildUpdateRequest(parameters)),\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\nconst UPLOAD_ICON_SPEC = makeSpec<UploadBadgeIconParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildUploadIconRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: UPLOAD_ICON_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: UPLOAD_ICON_REQUIRED_SCOPES,\n});\n\nconst UPDATE_NAME_DESCRIPTION_SPEC = makeSpec<UpdateBadgeNameDescriptionParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildLocaleNameDescRequest(parameters)),\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: LOCALIZATION_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: LOCALIZATION_REQUIRED_SCOPES,\n});\n\nconst UPLOAD_LOCALIZED_ICON_SPEC = makeSpec<UploadBadgeIconLocalizationParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildLocaleUploadIconRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: LOCALIZATION_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: LOCALIZATION_REQUIRED_SCOPES,\n});\n\ninterface BadgeLocalizationHandle {\n\t/**\n\t * Updates the per-locale display name and/or description registered against\n\t * a badge. Either `name`, `description`, or both may be supplied; omitted\n\t * fields are not forwarded so the server leaves the existing value for\n\t * that locale untouched. Mirrors the upstream `200 OK` echo body as\n\t * `undefined` data.\n\t *\n\t * @param parameters - Badge and language identifiers plus the optional\n\t * replacement values.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tupdateNameDescription: (\n\t\tparameters: UpdateBadgeNameDescriptionParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Uploads or replaces the per-locale icon for a badge. A subsequent\n\t * upload for the same `(badgeId, languageCode)` pair replaces the\n\t * existing icon for that locale. Does not retry on 5xx so a duplicate\n\t * upload cannot be created if the server fails mid-write. Source-language\n\t * icons remain on {@link BadgesClient.uploadIcon}.\n\t *\n\t * @param parameters - Badge and language identifiers plus the image bytes\n\t * to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tuploadIcon: (\n\t\tparameters: UploadBadgeIconLocalizationParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud Badges API. Covers programmatic\n * badge creation under a universe, partial updates of badge configuration\n * (`name`, `description`, `enabled`), and source-language icon uploads.\n *\n * Wires the request builders, the injected\n * {@link OpenCloudClientOptions.httpClient}, and response parsers into a\n * single ergonomic surface. Every method returns a {@link Result} so\n * callers handle failure explicitly; no thrown {@link OpenCloudError}\n * ever escapes the client.\n *\n * @example\n *\n * ```ts\n * import { BadgesClient } from \"@bedrock-rbx/ocale/badges\";\n *\n * const client = new BadgesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(BadgesClient);\n * ```\n */\nexport class BadgesClient {\n\treadonly #inner: ResourceClient;\n\n\t/**\n\t * Operation Group exposing per-locale localization Operations\n\t * (`updateNameDescription`, `uploadIcon`) backed by the\n\t * `legacy-game-internationalization` domain. Source-language values\n\t * remain on {@link BadgesClient.update} and\n\t * {@link BadgesClient.uploadIcon}; methods on this group set per-locale\n\t * overlays on top. Shares the parent client's HTTP, rate-limit, and\n\t * retry plumbing.\n\t */\n\tpublic readonly localization: BadgeLocalizationHandle;\n\n\t/**\n\t * Creates a new {@link BadgesClient}. 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.localization = createLocalizationHandle(this.#inner);\n\t}\n\n\t/**\n\t * Creates a new badge under the supplied universe.\n\t *\n\t * @param parameters - Creation fields including the universe, name, and\n\t * icon image.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed {@link Badge} or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async create(\n\t\tparameters: CreateBadgeParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Badge, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: CREATE_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a badge's configuration. Mirrors the upstream\n\t * `200 OK` empty response: a successful update yields `undefined`\n\t * data. Only fields explicitly provided are forwarded to the server,\n\t * so omitted fields keep their current values.\n\t *\n\t * @param parameters - Identifier plus the fields to update.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdateBadgeParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<undefined, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n\n\t/**\n\t * Uploads or replaces the source-language icon registered against a\n\t * badge. A subsequent upload for the same badge replaces the\n\t * existing source icon. Does not retry on 5xx so a duplicate icon\n\t * upload cannot be created if the server fails mid-write.\n\t *\n\t * @param parameters - Identifier plus the image bytes to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async uploadIcon(\n\t\tparameters: UploadBadgeIconParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<undefined, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPLOAD_ICON_SPEC });\n\t}\n}\n\nfunction createLocalizationHandle(inner: ResourceClient): BadgeLocalizationHandle {\n\treturn {\n\t\tasync updateNameDescription(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: UPDATE_NAME_DESCRIPTION_SPEC });\n\t\t},\n\t\tasync uploadIcon(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: UPLOAD_LOCALIZED_ICON_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"badges.mjs","names":["buildUpdateRequest","buildUploadIconRequest","buildUpdateRequest","buildLocaleNameDescRequest","buildLocaleUploadIconRequest","#inner"],"sources":["../src/domains/badges/badges/builders.ts","../src/domains/badges/badges/operations.ts","../src/domains/badges/badges/parsers.ts","../src/domains/game-internationalization/badge-icon/builders.ts","../src/domains/game-internationalization/badge-name-description/builders.ts","../src/domains/game-internationalization/badge-name-description/operations.ts","../src/domains/publish/badge-icon/builders.ts","../src/domains/publish/badge-icon/operations.ts","../src/resources/badges/client.ts"],"sourcesContent":["import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { BadgePaymentSource, CreateBadgeParameters, UpdateBadgeParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the legacy \"create badge\" endpoint.\n *\n * @param parameters - Fields describing the new badge; optional values\n * omitted here are left off the multipart payload entirely.\n * @returns A pure {@link HttpRequest} describing the create call.\n */\nexport function buildCreateRequest(parameters: CreateBadgeParameters): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"name\", parameters.name);\n\tbody.append(\"files\", toBlob(parameters.icon));\n\tif (parameters.description !== undefined) {\n\t\tbody.append(\"description\", parameters.description);\n\t}\n\n\tif (parameters.isActive !== undefined) {\n\t\tbody.append(\"isActive\", String(parameters.isActive));\n\t}\n\n\tif (parameters.expectedCost !== undefined) {\n\t\tbody.append(\"expectedCost\", String(parameters.expectedCost));\n\t}\n\n\tif (parameters.paymentSource !== undefined) {\n\t\tbody.append(\"paymentSourceType\", toPaymentSourceWire(parameters.paymentSource));\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-badges/v1/universes/${parameters.universeId}/badges`,\n\t};\n}\n\n/**\n * Builds a `PATCH` request for the legacy \"update badge\" endpoint. Every\n * field on `parameters` except the identifier is optional; omitted fields\n * are not appended to the JSON body so the server leaves them unchanged.\n *\n * @param parameters - Identifier plus fields to update.\n * @returns A pure {@link HttpRequest} describing the update call.\n */\nexport function buildUpdateRequest(parameters: UpdateBadgeParameters): HttpRequest {\n\tconst body: Record<string, boolean | string> = {};\n\tif (parameters.name !== undefined) {\n\t\tbody[\"name\"] = parameters.name;\n\t}\n\n\tif (parameters.description !== undefined) {\n\t\tbody[\"description\"] = parameters.description;\n\t}\n\n\tif (parameters.enabled !== undefined) {\n\t\tbody[\"enabled\"] = parameters.enabled;\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"PATCH\",\n\t\turl: `/legacy-badges/v1/badges/${parameters.badgeId}`,\n\t};\n}\n\nfunction toPaymentSourceWire(source: BadgePaymentSource): \"1\" | \"2\" {\n\treturn source === \"User\" ? \"1\" : \"2\";\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for creating a badge, sourced from\n * `x-roblox-rate-limits` on the legacy badges create operation in the\n * vendored OpenAPI schema (100 per minute, per API key owner).\n */\nexport const CREATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.create\",\n});\n\n/**\n * Per-second request ceiling for updating a badge, sourced from\n * `x-roblox-rate-limits` on the legacy badges update operation in the\n * vendored OpenAPI schema. Keyed independently from\n * {@link CREATE_OPERATION_LIMIT} so create and update do not share a\n * queue, since Roblox does not document the per-minute quota as shared\n * between the POST and PATCH endpoints.\n */\nexport const UPDATE_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.update\",\n});\n\n/**\n * Scopes the API key or OAuth token must carry to create a badge,\n * sourced from `x-roblox-scopes` on the legacy badges create operation\n * in the vendored OpenAPI schema. The trailing\n * `:manage-and-spend-robux` reflects that badge creation may charge a\n * Robux fee.\n */\nexport const CREATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe.badge:manage-and-spend-robux\",\n]);\n\n/**\n * Scopes the API key or OAuth token must carry to update a badge,\n * sourced from `x-roblox-scopes` on the legacy badges update operation\n * in the vendored OpenAPI schema.\n */\nexport const UPDATE_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-universe.badge: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 { Badge, BadgeAwarder, BadgeStatistics } from \"./types.ts\";\nimport type { BadgeAwarderWire, BadgeResponseV2Wire, BadgeStatisticsWire } from \"./wire.ts\";\n\n/**\n * Parses a successful Badges API response into the public `Badge` shape,\n * returning a `Result` so callers can handle malformed payloads without\n * exceptions.\n *\n * @param response - The full {@link HttpResponse} from the Open Cloud API.\n * The status code is included on the returned `ApiError` when validation\n * fails; the headers are available for future parsers that need them.\n * @returns A success result wrapping the converted `Badge`, or an\n * `ApiError` when the body does not match the wire schema.\n */\nexport function parseBadgeResponse(response: HttpResponse): Result<Badge, ApiError> {\n\tconst { body, status: statusCode } = response;\n\n\tif (!isBadgeResponseV2Wire(body)) {\n\t\treturn {\n\t\t\terr: new ApiError(\"Malformed badge response\", {\n\t\t\t\tdetails: body as JSONValue | undefined,\n\t\t\t\tstatusCode,\n\t\t\t}),\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tid: String(body.id),\n\t\t\tname: body.name,\n\t\t\tawarder: copyAwarder(body.awarder),\n\t\t\tcreatedAt: new Date(body.created),\n\t\t\tdescription: body.description,\n\t\t\tdisplayDescription: body.displayDescription,\n\t\t\tdisplayIconImageId:\n\t\t\t\tbody.displayIconImageId === 0 ? undefined : String(body.displayIconImageId),\n\t\t\tdisplayName: body.displayName,\n\t\t\tenabled: body.enabled,\n\t\t\ticonImageId: body.iconImageId === 0 ? undefined : String(body.iconImageId),\n\t\t\tstatistics: copyStatistics(body.statistics),\n\t\t\tupdatedAt: new Date(body.updated),\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction copyAwarder(awarder: BadgeAwarderWire): BadgeAwarder {\n\treturn { id: String(awarder.id), name: awarder.name, type: \"Place\" };\n}\n\nfunction copyStatistics(statistics: BadgeStatisticsWire): BadgeStatistics {\n\treturn {\n\t\tawardedCount: statistics.awardedCount,\n\t\tpastDayAwardedCount: statistics.pastDayAwardedCount,\n\t\twinRatePercentage: statistics.winRatePercentage,\n\t};\n}\n\nfunction hasRequiredPrimitiveFields(body: Record<string, unknown>): boolean {\n\treturn (\n\t\ttypeof body[\"id\"] === \"number\" &&\n\t\ttypeof body[\"name\"] === \"string\" &&\n\t\ttypeof body[\"description\"] === \"string\" &&\n\t\ttypeof body[\"displayName\"] === \"string\" &&\n\t\ttypeof body[\"displayDescription\"] === \"string\" &&\n\t\ttypeof body[\"enabled\"] === \"boolean\" &&\n\t\ttypeof body[\"iconImageId\"] === \"number\" &&\n\t\ttypeof body[\"displayIconImageId\"] === \"number\" &&\n\t\tisDateTimeString(body[\"created\"]) &&\n\t\tisDateTimeString(body[\"updated\"])\n\t);\n}\n\nfunction isBadgeAwarderWire(value: unknown): value is BadgeAwarderWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"id\"] === \"number\" && typeof value[\"name\"] === \"string\" && value[\"type\"] === 1\n\t);\n}\n\nfunction isBadgeStatisticsWire(value: unknown): value is BadgeStatisticsWire {\n\tif (!isRecord(value)) {\n\t\treturn false;\n\t}\n\n\treturn (\n\t\ttypeof value[\"awardedCount\"] === \"number\" &&\n\t\ttypeof value[\"pastDayAwardedCount\"] === \"number\" &&\n\t\ttypeof value[\"winRatePercentage\"] === \"number\"\n\t);\n}\n\nfunction isBadgeResponseV2Wire(body: unknown): body is BadgeResponseV2Wire {\n\tif (!isRecord(body)) {\n\t\treturn false;\n\t}\n\n\tif (!hasRequiredPrimitiveFields(body)) {\n\t\treturn false;\n\t}\n\n\tif (!isBadgeAwarderWire(body[\"awarder\"])) {\n\t\treturn false;\n\t}\n\n\tif (!isBadgeStatisticsWire(body[\"statistics\"])) {\n\t\treturn false;\n\t}\n\n\treturn true;\n}\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { UploadBadgeIconLocalizationParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the localized \"upload badge icon\" endpoint. A\n * successful upload replaces any existing icon for the same\n * `(badgeId, languageCode)` pair.\n *\n * @param parameters - Badge and language identifiers plus the image bytes\n * to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(\n\tparameters: UploadBadgeIconLocalizationParameters,\n): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"Files\", toBlob(parameters.image));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-game-internationalization/v1/badges/${parameters.badgeId}/icons/language-codes/${parameters.languageCode}`,\n\t};\n}\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport type { UpdateBadgeNameDescriptionParameters } from \"./types.ts\";\n\n/**\n * Builds a `PATCH` request for the localized \"update badge name/description\"\n * endpoint. Either `name`, `description`, or both may be supplied; omitted\n * fields are not included in the JSON body so the server leaves the existing\n * value for that locale untouched.\n *\n * @param parameters - Badge and language identifiers plus the optional\n * replacement values.\n * @returns A pure {@link HttpRequest} describing the update call.\n */\nexport function buildUpdateRequest(parameters: UpdateBadgeNameDescriptionParameters): HttpRequest {\n\tconst body: Record<string, string> = {};\n\tif (parameters.name !== undefined) {\n\t\tbody[\"name\"] = parameters.name;\n\t}\n\n\tif (parameters.description !== undefined) {\n\t\tbody[\"description\"] = parameters.description;\n\t}\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"PATCH\",\n\t\turl: `/legacy-game-internationalization/v1/badges/${parameters.badgeId}/name-description/language-codes/${parameters.languageCode}`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for every badge localization Operation. The\n * legacy `gameinternationalization` service caps each API key at 100\n * requests per minute *shared across the entire service* (see the\n * `x-roblox-rate-limits` extension on every operation in the vendored\n * Open Cloud spec), so all badge localization methods queue against the\n * same operation key.\n */\nexport const LOCALIZATION_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badge-localization\",\n});\n\n/**\n * Scopes required for every badge localization operation, sourced from\n * `x-roblox-scopes` on the legacy `gameinternationalization` badge\n * endpoints in the vendored OpenAPI schema.\n */\nexport const LOCALIZATION_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-badge:manage\",\n]);\n","import type { HttpRequest } from \"../../../internal/http/types.ts\";\nimport { toBlob } from \"../../../internal/utils/to-blob.ts\";\nimport type { UploadBadgeIconParameters } from \"./types.ts\";\n\n/**\n * Builds a `POST` request for the legacy \"upload badge icon\" endpoint. A\n * successful upload replaces any existing source-language icon on the\n * badge.\n *\n * @param parameters - Badge identifier plus the image bytes to upload.\n * @returns A pure {@link HttpRequest} describing the upload call.\n */\nexport function buildUploadIconRequest(parameters: UploadBadgeIconParameters): HttpRequest {\n\tconst body = new FormData();\n\tbody.append(\"Files\", toBlob(parameters.icon));\n\n\treturn {\n\t\tbody,\n\t\tmethod: \"POST\",\n\t\turl: `/legacy-publish/v1/badges/${parameters.badgeId}/icon`,\n\t};\n}\n","import type { OperationLimit } from \"../../../internal/http/rate-limit-queue.ts\";\n\n/**\n * Per-second request ceiling for uploading a badge icon, sourced from\n * `x-roblox-rate-limits` on the legacy badge icon upload operation in\n * the vendored OpenAPI schema (100 per minute, per API key owner). Keyed\n * separately from the badges create and update buckets because Roblox\n * does not document the legacy-publish quota as shared with the\n * legacy-badges quota.\n */\nexport const UPLOAD_ICON_OPERATION_LIMIT: OperationLimit = Object.freeze({\n\tmaxPerSecond: 100 / 60,\n\toperationKey: \"badges.upload-icon\",\n});\n\n/**\n * Scopes the API key or OAuth token must carry to upload a badge icon,\n * sourced from `x-roblox-scopes` on the legacy badge icon upload\n * operation in the vendored OpenAPI schema.\n */\nexport const UPLOAD_ICON_REQUIRED_SCOPES: ReadonlyArray<string> = Object.freeze([\n\t\"legacy-badge:manage\",\n]);\n","import type { OpenCloudClientOptions, RequestOptions } from \"../../client/types.ts\";\nimport { buildCreateRequest, buildUpdateRequest } from \"../../domains/badges/badges/builders.ts\";\nimport {\n\tCREATE_OPERATION_LIMIT,\n\tCREATE_REQUIRED_SCOPES,\n\tUPDATE_OPERATION_LIMIT,\n\tUPDATE_REQUIRED_SCOPES,\n} from \"../../domains/badges/badges/operations.ts\";\nimport { parseBadgeResponse } from \"../../domains/badges/badges/parsers.ts\";\nimport type {\n\tBadge,\n\tCreateBadgeParameters,\n\tUpdateBadgeParameters,\n} from \"../../domains/badges/badges/types.ts\";\nimport { buildUploadIconRequest as buildLocaleUploadIconRequest } from \"../../domains/game-internationalization/badge-icon/builders.ts\";\nimport type { UploadBadgeIconLocalizationParameters } from \"../../domains/game-internationalization/badge-icon/types.ts\";\nimport { buildUpdateRequest as buildLocaleNameDescRequest } from \"../../domains/game-internationalization/badge-name-description/builders.ts\";\nimport {\n\tLOCALIZATION_OPERATION_LIMIT,\n\tLOCALIZATION_REQUIRED_SCOPES,\n} from \"../../domains/game-internationalization/badge-name-description/operations.ts\";\nimport type { UpdateBadgeNameDescriptionParameters } from \"../../domains/game-internationalization/badge-name-description/types.ts\";\nimport { buildUploadIconRequest } from \"../../domains/publish/badge-icon/builders.ts\";\nimport {\n\tUPLOAD_ICON_OPERATION_LIMIT,\n\tUPLOAD_ICON_REQUIRED_SCOPES,\n} from \"../../domains/publish/badge-icon/operations.ts\";\nimport type { UploadBadgeIconParameters } from \"../../domains/publish/badge-icon/types.ts\";\nimport type { OpenCloudError } from \"../../errors/base.ts\";\nimport { CREATE_METHOD_DEFAULTS, IDEMPOTENT_METHOD_DEFAULTS } from \"../../internal/http/retry.ts\";\nimport {\n\tokRequest,\n\tparseEmptyResponse,\n\tResourceClient,\n\ttype ResourceMethodSpec,\n} from \"../../internal/resource-client.ts\";\nimport type { Result } from \"../../types.ts\";\n\nfunction makeSpec<P, R>(spec: ResourceMethodSpec<P, R>): ResourceMethodSpec<P, R> {\n\treturn Object.freeze(spec);\n}\n\nconst CREATE_SPEC = makeSpec<CreateBadgeParameters, Badge>({\n\tbuildRequest: (parameters) => okRequest(buildCreateRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: CREATE_OPERATION_LIMIT,\n\tparse: parseBadgeResponse,\n\trequiredScopes: CREATE_REQUIRED_SCOPES,\n});\n\nconst UPDATE_SPEC = makeSpec<UpdateBadgeParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildUpdateRequest(parameters)),\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: UPDATE_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: UPDATE_REQUIRED_SCOPES,\n});\n\nconst UPLOAD_ICON_SPEC = makeSpec<UploadBadgeIconParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildUploadIconRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: UPLOAD_ICON_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: UPLOAD_ICON_REQUIRED_SCOPES,\n});\n\nconst UPDATE_NAME_DESCRIPTION_SPEC = makeSpec<UpdateBadgeNameDescriptionParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildLocaleNameDescRequest(parameters)),\n\tmethodDefaults: IDEMPOTENT_METHOD_DEFAULTS,\n\tmethodKind: \"idempotent\",\n\toperationLimit: LOCALIZATION_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: LOCALIZATION_REQUIRED_SCOPES,\n});\n\nconst UPLOAD_LOCALIZED_ICON_SPEC = makeSpec<UploadBadgeIconLocalizationParameters, undefined>({\n\tbuildRequest: (parameters) => okRequest(buildLocaleUploadIconRequest(parameters)),\n\tmethodDefaults: CREATE_METHOD_DEFAULTS,\n\tmethodKind: \"create\",\n\toperationLimit: LOCALIZATION_OPERATION_LIMIT,\n\tparse: parseEmptyResponse,\n\trequiredScopes: LOCALIZATION_REQUIRED_SCOPES,\n});\n\ninterface BadgeLocalizationHandle {\n\t/**\n\t * Updates the per-locale display name and/or description registered against\n\t * a badge. Either `name`, `description`, or both may be supplied; omitted\n\t * fields are not forwarded so the server leaves the existing value for\n\t * that locale untouched. Mirrors the upstream `200 OK` echo body as\n\t * `undefined` data.\n\t *\n\t * @param parameters - Badge and language identifiers plus the optional\n\t * replacement values.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tupdateNameDescription: (\n\t\tparameters: UpdateBadgeNameDescriptionParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n\t/**\n\t * Uploads or replaces the per-locale icon for a badge. A subsequent\n\t * upload for the same `(badgeId, languageCode)` pair replaces the\n\t * existing icon for that locale. Does not retry on 5xx so a duplicate\n\t * upload cannot be created if the server fails mid-write. Source-language\n\t * icons remain on {@link BadgesClient.uploadIcon}.\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 - Badge and language identifiers plus the image bytes\n\t * to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tuploadIcon: (\n\t\tparameters: UploadBadgeIconLocalizationParameters,\n\t\toptions?: RequestOptions,\n\t) => Promise<Result<undefined, OpenCloudError>>;\n}\n\n/**\n * Public client for the Roblox Open Cloud Badges API. Covers programmatic\n * badge creation under a universe, partial updates of badge configuration\n * (`name`, `description`, `enabled`), and source-language icon uploads.\n *\n * Wires the request builders, the injected\n * {@link OpenCloudClientOptions.httpClient}, and response parsers into a\n * single ergonomic surface. Every method returns a {@link Result} so\n * callers handle failure explicitly; no thrown {@link OpenCloudError}\n * ever escapes the client.\n *\n * @since 0.1.0\n *\n * @example\n *\n * ```ts\n * import { BadgesClient } from \"@bedrock-rbx/ocale/badges\";\n *\n * const client = new BadgesClient({ apiKey: \"your-key\" });\n * expect(client).toBeInstanceOf(BadgesClient);\n * ```\n */\nexport class BadgesClient {\n\treadonly #inner: ResourceClient;\n\n\t/**\n\t * Operation Group exposing per-locale localization Operations\n\t * (`updateNameDescription`, `uploadIcon`) backed by the\n\t * `legacy-game-internationalization` domain. Source-language values\n\t * remain on {@link BadgesClient.update} and\n\t * {@link BadgesClient.uploadIcon}; methods on this group set per-locale\n\t * overlays on top. Shares the parent client's HTTP, rate-limit, and\n\t * retry plumbing.\n\t */\n\tpublic readonly localization: BadgeLocalizationHandle;\n\n\t/**\n\t * Creates a new {@link BadgesClient}. 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.localization = createLocalizationHandle(this.#inner);\n\t}\n\n\t/**\n\t * Creates a new badge under the supplied universe.\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 - Creation fields including the universe, name, and\n\t * icon image.\n\t * @param options - Optional per-request overrides.\n\t * @returns A {@link Result} wrapping the parsed {@link Badge} or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async create(\n\t\tparameters: CreateBadgeParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<Badge, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: CREATE_SPEC });\n\t}\n\n\t/**\n\t * Partially updates a badge's configuration. Mirrors the upstream\n\t * `200 OK` empty response: a successful update yields `undefined`\n\t * data. Only fields explicitly provided are forwarded to the server,\n\t * so omitted fields keep their current values.\n\t *\n\t * @param parameters - Identifier plus the fields to update.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async update(\n\t\tparameters: UpdateBadgeParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<undefined, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPDATE_SPEC });\n\t}\n\n\t/**\n\t * Uploads or replaces the source-language icon registered against a\n\t * badge. A subsequent upload for the same badge replaces the\n\t * existing source icon. Does not retry on 5xx so a duplicate icon\n\t * upload cannot be created if the server fails mid-write.\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 - Identifier plus the image bytes to upload.\n\t * @param options - Optional per-request overrides.\n\t * @returns A success {@link Result} with no payload, or the\n\t * {@link OpenCloudError} that caused the request to fail.\n\t */\n\tpublic async uploadIcon(\n\t\tparameters: UploadBadgeIconParameters,\n\t\toptions?: RequestOptions,\n\t): Promise<Result<undefined, OpenCloudError>> {\n\t\treturn this.#inner.execute({ options, parameters, spec: UPLOAD_ICON_SPEC });\n\t}\n}\n\nfunction createLocalizationHandle(inner: ResourceClient): BadgeLocalizationHandle {\n\treturn {\n\t\tasync updateNameDescription(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: UPDATE_NAME_DESCRIPTION_SPEC });\n\t\t},\n\t\tasync uploadIcon(parameters, options) {\n\t\t\treturn inner.execute({ options, parameters, spec: UPLOAD_LOCALIZED_ICON_SPEC });\n\t\t},\n\t};\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
//#region src/locales/data.generated.d.ts
|
|
2
2
|
/**
|
|
3
3
|
* One row in the vendored Roblox creator-locale list.
|
|
4
|
+
*
|
|
5
|
+
* @since 0.1.0
|
|
4
6
|
*/
|
|
5
7
|
interface RobloxCreatorLocale {
|
|
6
8
|
readonly locale: string;
|
|
@@ -16,6 +18,8 @@ interface RobloxCreatorLocale {
|
|
|
16
18
|
* Vendored snapshot of
|
|
17
19
|
* `https://locale.roblox.com/v1/locales/supported-locales-for-creators`.
|
|
18
20
|
* Refreshed by `pnpm --filter @bedrock-rbx/ocale refresh-locales`.
|
|
21
|
+
*
|
|
22
|
+
* @since 0.1.0
|
|
19
23
|
*/
|
|
20
24
|
declare const ROBLOX_CREATOR_LOCALES: readonly [{
|
|
21
25
|
readonly locale: "ar_001";
|
|
@@ -472,14 +476,18 @@ declare const ROBLOX_CREATOR_LOCALES: readonly [{
|
|
|
472
476
|
* Roblox locale wire form (e.g. `en_us`, `pt_br`, `ar_001`). Used by
|
|
473
477
|
* the legacy game-internationalization endpoints when
|
|
474
478
|
* `languageCodeType` is `Locale`.
|
|
479
|
+
*
|
|
480
|
+
* @since 0.1.0
|
|
475
481
|
*/
|
|
476
482
|
type RobloxLocale = (typeof ROBLOX_CREATOR_LOCALES)[number]["locale"];
|
|
477
483
|
/**
|
|
478
484
|
* Roblox language wire form (e.g. `en`, `fil`, `zh-hans`). Used by
|
|
479
485
|
* the legacy game-internationalization endpoints when
|
|
480
486
|
* `languageCodeType` is `Language`.
|
|
487
|
+
*
|
|
488
|
+
* @since 0.1.0
|
|
481
489
|
*/
|
|
482
490
|
type RobloxLanguageCode = (typeof ROBLOX_CREATOR_LOCALES)[number]["languageCode"];
|
|
483
491
|
//#endregion
|
|
484
492
|
export { RobloxLocale as i, RobloxCreatorLocale as n, RobloxLanguageCode as r, ROBLOX_CREATOR_LOCALES as t };
|
|
485
|
-
//# sourceMappingURL=data.generated-
|
|
493
|
+
//# sourceMappingURL=data.generated-B2ceLfSn.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"data.generated-B2ceLfSn.d.mts","names":[],"sources":["../src/locales/data.generated.ts"],"mappings":"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"}
|