### Install OpenCloud with bun Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Install the OpenCloud package using bun. ```sh $ bun add @relatiohq/opencloud ``` -------------------------------- ### Install Dependencies and Build Project Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Install project dependencies using pnpm and then build the project. ```bash pnpm install ``` ```bash pnpm build ``` -------------------------------- ### Install @relatiohq/opencloud Source: https://github.com/relatiocc/opencloud/blob/main/README.md Install the SDK using npm, pnpm, or yarn. ```bash npm install @relatiohq/opencloud # or pnpm add @relatiohq/opencloud # or yarn add @relatiohq/opencloud ``` -------------------------------- ### Install OpenCloud with yarn Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Install the OpenCloud package using yarn. ```sh $ yarn add @relatiohq/opencloud ``` -------------------------------- ### Install OpenCloud with pnpm Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Install the OpenCloud package using pnpm. ```sh $ pnpm add @relatiohq/opencloud ``` -------------------------------- ### Install Relatio OpenCloud SDK Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/index.md Install the SDK using npm. This is the first step to using the Relatio OpenCloud SDK in your project. ```bash npm install @relatiohq/opencloud ``` -------------------------------- ### Install OpenCloud with npm Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Install the OpenCloud package using npm. ```sh $ npm install @relatiohq/opencloud ``` -------------------------------- ### TypeScript Function Example with JSDoc Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Example of a TypeScript function with JSDoc comments, including parameter and return types, and an example usage block. ```typescript /** * Fetches user information by user ID. * * @param userId - The Roblox user ID * @returns User information * @throws {OpenCloudError} If the API request fails * * @example * ```typescript * const user = await client.users.get("123456789"); * console.log(user.displayName); * ``` */ async get(userId: string): Promise { // Implementation } ``` -------------------------------- ### Conventional Commits Usage Examples Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Practical examples of commit messages adhering to the Conventional Commits format. Demonstrates how to structure messages for new features, bug fixes, and documentation updates. ```markdown Examples: ``` feat(users): add getUserInventory method fix(http): handle rate limiting correctly docs: update contributing guidelines ``` ``` -------------------------------- ### Complete Example: Group Operations Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Demonstrates a combination of group operations: fetching group info, listing roles, finding admin members, and checking join requests. ```typescript // Get group information const group = await client.groups.get("123456789"); console.log(`Managing group: ${group.displayName}`); // List all roles const roles = await client.groups.listGroupRoles("123456789"); console.log(`Total roles: ${roles.groupRoles.length}`); // Get admin role const adminRole = roles.groupRoles.find(r => r.displayName === "Admin"); // List members with admin role if (adminRole) { const admins = await client.groups.listGroupMemberships("123456789", { filter: `role == '${adminRole.id}'` }); console.log(`Total admins: ${admins.groupMemberships.length}`); } // Check for pending join requests const requests = await client.groups.listGroupJoinRequests("123456789"); console.log(`Pending requests: ${requests.groupJoinRequests.length}`); ``` -------------------------------- ### Paginate User Inventory Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Handle large user inventories by paginating through items. This example fetches all items by repeatedly requesting pages until no next page token is available. ```typescript let pageToken: string | undefined; let allItems = []; do { const page = await client.users.listInventoryItems("123456789", { maxPageSize: 100, pageToken }); allItems.push(...page.inventoryItems); pageToken = page.nextPageToken; } while (pageToken); console.log(`Total items: ${allItems.length}`); ``` -------------------------------- ### Migrate Getting User Information Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Replace direct fetch calls for user data with the client.users.get method. ```typescript // Before const response = await fetch( `https://apis.roblox.com/cloud/v2/users/${userId}` ); const user = await response.json(); ``` ```typescript // After const user = await client.users.get(userId); ``` -------------------------------- ### Initialize OpenCloud Client and Make API Calls Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Initialize the OpenCloud client with your API key and make basic calls to get user and group information. Ensure your API key is set in the environment variable ROBLOX_API_KEY. ```typescript import { OpenCloud } from "@relatiohq/opencloud"; // Initialize the client with your API key const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY, }); // Get user information const user = await client.users.get("123456789"); console.log(user.displayName); // "John Doe" // Get group details const group = await client.groups.get("987654321"); console.log(group.displayName); // "My Group" ``` -------------------------------- ### Migrate Getting Group Members Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Transition from fetching group memberships directly to using the client.groups.listGroupMemberships method. ```typescript // Before const response = await fetch( `https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships`, { headers: { "x-api-key": apiKey } } ); const data = await response.json(); const members = data.groupMemberships; ``` ```typescript // After const page = await client.groups.listGroupMemberships(groupId); const members = page.groupMemberships; ``` -------------------------------- ### List User Restrictions Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Get all banned users in your universe. ```APIDOC ## List User Restrictions ### Description Get all banned users in your universe. ### Method GET ### Endpoint `/universes/{universeId}/restrictions` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe. ### Response #### Success Response (200) - **userRestrictions** (array) - A list of user restrictions. - **user** (string) - The user ID. - **gameJoinRestriction** (object) - **active** (boolean) - Whether the restriction is active. - **displayReason** (string) - The reason for the restriction displayed to the user. ### Response Example ```json { "userRestrictions": [ { "user": "987654321", "gameJoinRestriction": { "active": true, "displayReason": "Violation of game rules" } } ] } ``` ``` -------------------------------- ### Get User Information Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Retrieve basic user profile information by user ID. ```APIDOC ## Get User Information ### Description Retrieve basic user profile information by user ID. ### Method GET ### Endpoint /users/{userId} ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user to retrieve. ### Response #### Success Response (200) - **displayName** (string) - The display name of the user. - **name** (string) - The username of the user. - **hasVerifiedBadge** (boolean) - Indicates if the user has a verified badge. ``` -------------------------------- ### Batch Operations with Delays Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/rate-limiting.md When processing multiple items, introduce small delays between requests to avoid hitting rate limits. This example fetches multiple user details with a 100ms delay between each. ```typescript const userIds = ["123", "456", "789", "012"]; for (const userId of userIds) { try { const user = await client.users.get(userId); console.log(user.displayName); // Small delay between requests await new Promise(resolve => setTimeout(resolve, 100)); } catch (error) { console.error(`Failed to fetch user ${userId}:`, error); } } ``` -------------------------------- ### Conventional Commits Type Examples Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Examples of commit message types used in Conventional Commits. Common types include 'feat', 'fix', 'docs', 'style', 'refactor', 'test', and 'chore'. ```markdown Types: - `feat`: New feature - `fix`: Bug fix - `docs`: Documentation changes - `style`: Code style changes (formatting, etc.) - `refactor`: Code refactoring - `test`: Test additions or modifications - `chore`: Maintenance tasks ``` -------------------------------- ### Get Universe Information Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Retrieve universe information by its unique ID. ```APIDOC ## Get Universe Information ### Description Retrieve universe information by universe ID. ### Method GET ### Endpoint `/universes/{universeId}` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe to retrieve. ### Response #### Success Response (200) - **displayName** (string) - The display name of the universe. - **voiceChatEnabled** (boolean) - Indicates if voice chat is enabled. - **desktopEnabled** (boolean) - Indicates if desktop access is enabled. - **privateServerPriceRobux** (number) - The price for private servers in Robux. ### Response Example ```json { "displayName": "My Awesome Game", "voiceChatEnabled": false, "desktopEnabled": true, "privateServerPriceRobux": 50 } ``` ``` -------------------------------- ### Get User Information by ID Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Retrieve basic user profile information using their unique user ID. This includes display name, username, and badge status. ```typescript const user = await client.users.get("123456789"); console.log(user.displayName); // "John Doe" console.log(user.name); // "@johndoe" console.log(user.hasVerifiedBadge); ``` -------------------------------- ### Filter User Inventory by Asset Type Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Retrieve specific types of items from a user's inventory by applying filters. Example shows fetching only hats and pants. ```typescript // Get only hats and pants const items = await client.users.listInventoryItems("123456789", { filter: "inventoryItemAssetTypes=HAT,CLASSIC_PANTS" }); ``` -------------------------------- ### Handling 429 Rate Limited Errors Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/error-handling.md This example shows how to catch a RateLimitError when too many requests are made. The SDK's automatic retries are mentioned, and this error is thrown only after all retries fail. ```typescript try { // Making many requests in a loop for (const userId of userIds) { await client.users.get(userId); } } catch (error) { if (error instanceof RateLimitError) { console.error("Rate limit hit!"); // The SDK automatically retries with exponential backoff // This error is thrown only after all retry attempts fail } } ``` -------------------------------- ### Get Specific User Restriction Details Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Check the restriction status and details for a particular user within a universe. This includes ban duration and reason. ```typescript const restriction = await client.universes.getUserRestriction( "123456789", // Universe ID "987654321" // User ID ); console.log(restriction.gameJoinRestriction.duration); console.log(restriction.gameJoinRestriction.displayReason); ``` -------------------------------- ### Get Group Information Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve basic information about a group using its ID. This includes display name, description, owner, member count, and public entry status. ```APIDOC ## Get Group Information ### Description Retrieve basic group information by group ID. ### Method `client.groups.get(groupId)` ### Parameters #### Path Parameters - **groupId** (string) - Required - The unique identifier of the group. ### Response #### Success Response (200) - **displayName** (string) - The display name of the group. - **description** (string) - The description of the group. - **owner** (string) - The user ID of the group owner. - **memberCount** (number) - The current number of members in the group. - **publicEntryAllowed** (boolean) - Indicates if the group allows public entry. ### Request Example ```typescript const group = await client.groups.get("123456789"); console.log(group.displayName); console.log(group.description); console.log(group.owner); console.log(group.memberCount); console.log(group.publicEntryAllowed); ``` ``` -------------------------------- ### Get Group Information Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve basic group details using the group ID. Access properties like display name, description, owner, member count, and public entry status. ```typescript const group = await client.groups.get("123456789"); console.log(group.displayName); // "My Awesome Group" console.log(group.description); console.log(group.owner); // "users/987654321" console.log(group.memberCount); console.log(group.publicEntryAllowed); ``` -------------------------------- ### Initialize and Use OpenCloud Client Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/index.md Initialize the OpenCloud client with your API key and make a request to fetch user information. Ensure you replace 'your-api-key' with your actual API key. ```typescript import { OpenCloud } from "@relatiohq/opencloud"; const client = new OpenCloud({ apiKey: "your-api-key" }); const user = await client.users.get("123456789"); console.log(user.displayName); ``` -------------------------------- ### Running Full Test Suite with pnpm Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Commands to execute all necessary checks before pushing changes. Includes type checking, linting, testing, and building the project. ```bash pnpm typecheck pnpm lint pnpm test pnpm build ``` -------------------------------- ### Run Project Tests Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Execute the project's test suite to ensure all components are functioning correctly. ```bash pnpm test ``` -------------------------------- ### Load API Key from .env File Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/authentication.md Demonstrates how to use a `.env` file and the `dotenv` package to load your API key into environment variables for use with the OpenCloud client. ```typescript import "dotenv/config"; import { OpenCloud } from "@relatiohq/opencloud"; const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY! }); ``` -------------------------------- ### Get Group Shout Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve the current group shout (announcement) for a group. ```APIDOC ## Get Group Shout ### Description Retrieve the current group shout (announcement). ### Method `client.groups.getGroupShout(groupId)` ### Parameters #### Path Parameters - **groupId** (string) - Required - The unique identifier of the group. ### Response #### Success Response (200) - **content** (string) - The content of the shout message. - **poster** (string) - The user ID of the user who posted the shout. - **createTime** (string) - The timestamp when the shout was created. - **updateTime** (string) - The timestamp when the shout was last updated. ### Request Example ```typescript const shout = await client.groups.getGroupShout("123456789"); if (shout.content) { console.log(shout.content); console.log(shout.poster); console.log(shout.createTime); console.log(shout.updateTime); } else { console.log("No active shout"); } ``` ``` -------------------------------- ### Initialize OpenCloud Client with Environment Variable Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/authentication.md Recommended practice for securely managing API keys by loading them from environment variables, preventing hardcoding sensitive credentials. ```typescript const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY! }); ``` -------------------------------- ### Initialize OpenCloud Client with API Key Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/authentication.md Use this method to create an OpenCloud client for server-side applications requiring direct access to Roblox resources using an API key. ```typescript import { OpenCloud } from "@relatiohq/opencloud"; const client = new OpenCloud({ apiKey: "your-api-key-here" }); ``` -------------------------------- ### Get User Restriction Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Check restriction details for a specific user within a universe. ```APIDOC ## Get User Restriction ### Description Check restriction details for a specific user within a universe. ### Method GET ### Endpoint `/universes/{universeId}/restrictions/{userId}` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe. - **userId** (string) - Required - The ID of the user. ### Response #### Success Response (200) - **gameJoinRestriction** (object) - **duration** (string) - The duration of the restriction (e.g., "86400s"). - **displayReason** (string) - The reason for the restriction displayed to the user. ### Response Example ```json { "gameJoinRestriction": { "duration": "86400s", "displayReason": "Violation of game rules" } } ``` ``` -------------------------------- ### Run Project Scripts Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Execute various project scripts using pnpm for building, testing, linting, and documentation generation. ```bash pnpm build # Build the project ``` ```bash pnpm test # Run tests once ``` ```bash pnpm test:watch # Run tests in watch mode ``` ```bash pnpm coverage # Generate test coverage report ``` ```bash pnpm typecheck # Run TypeScript type checking ``` ```bash pnpm lint # Run ESLint ``` ```bash pnpm lint:format # Check code formatting ``` ```bash pnpm format # Format code with Prettier ``` ```bash pnpm docs # Generate documentation ``` ```bash pnpm docs:watch # Generate documentation in watch mode ``` -------------------------------- ### Get Group Role Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve detailed information about a specific role within a group. ```APIDOC ## Get Group Role ### Description Retrieve detailed information about a single role. ### Method `client.groups.getGroupRole(groupId, roleId)` ### Parameters #### Path Parameters - **groupId** (string) - Required - The unique identifier of the group. - **roleId** (string) - Required - The unique identifier of the role. ### Response #### Success Response (200) - **displayName** (string) - The display name of the role. - **description** (string) - The description of the role. - **permissions** (object) - An object detailing the role's permissions. ### Request Example ```typescript const role = await client.groups.getGroupRole("123456789", "12345"); console.log(role.displayName); console.log(role.description); console.log(role.permissions); ``` ``` -------------------------------- ### Generating Documentation with TypeDoc Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Commands for generating project documentation using TypeDoc via pnpm. Use 'pnpm docs' for a one-time generation or 'pnpm docs:watch' to automatically regenerate docs on file changes. ```bash # Generate documentation pnpm docs # Generate documentation in watch mode pnpm docs:watch ``` -------------------------------- ### Get Current Group Shout Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve the latest announcement (shout) for a group. If a shout exists, its content, poster, and timestamps are available. ```typescript const shout = await client.groups.getGroupShout("123456789"); if (shout.content) { console.log(shout.content); // Shout message console.log(shout.poster); // User who posted console.log(shout.createTime); console.log(shout.updateTime); } else { console.log("No active shout"); } ``` -------------------------------- ### Multi-Tenant Server with OAuth2 Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/authentication.md Implement a backend service that handles requests from multiple users by dynamically applying OAuth2 authentication based on the user's access token provided in the request headers. ```typescript import { OpenCloud } from "@relatiohq/opencloud"; import express from "express"; const app = express(); const client = new OpenCloud(); // Shared client, no default auth app.get("/api/my-groups", async (req, res) => { // Get user's access token from request const accessToken = req.headers.authorization?.split(" ")[1]; // Create scoped client for this user const userClient = client.withAuth({ kind: "oauth2", accessToken: accessToken! }); // Make requests on behalf of the user const memberships = await userClient.groups.listGroupMemberships(req.query.userId); res.json(memberships); }); ``` -------------------------------- ### Manual API Call vs. SDK Usage Source: https://github.com/relatiocc/opencloud/blob/main/README.md Compares making raw `fetch` requests to the Roblox Open Cloud API with using the SDK. The SDK simplifies error handling, retries, and provides type safety. ```typescript // Manual fetch with error handling, retries, rate limiting... const response = await fetch( `https://apis.roblox.com/cloud/v2/users/${userId}`, { headers: { "x-api-key": apiKey }, }, ); if (!response.ok) { // Handle errors manually throw new Error(`API error: ${response.status}`); } const data = await response.json(); // No type safety, no automatic retries ``` ```typescript // Type-safe, automatic retries, built-in error handling const user = await client.users.get(userId); // Full TypeScript autocomplete and type checking ``` -------------------------------- ### Get Specific Group Role Details Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve detailed information for a single role within a group using both the group ID and the role ID. ```typescript const role = await client.groups.getGroupRole("123456789", "12345"); console.log(role.displayName); console.log(role.description); console.log(role.permissions); // Role permissions object ``` -------------------------------- ### Enforce Code Style with ESLint and Prettier Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Use pnpm commands to check and fix code formatting and linting issues. ```bash # Check formatting pnpm lint:format # Fix formatting issues pnpm format # Check linting pnpm lint ``` -------------------------------- ### Initialize OpenCloud Client with API Key Source: https://github.com/relatiocc/opencloud/blob/main/README.md Initialize the OpenCloud client using an API key for authentication. This is suitable for server-side applications or when a single API key is used. ```typescript import { OpenCloud } from "@relatiohq/opencloud"; // With API key authentication const client = new OpenCloud({ apiKey: "your-api-key", }); const user = await client.users.get("123456789"); ``` -------------------------------- ### Running Tests with pnpm Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Commands to execute the test suite using pnpm. Use 'pnpm test' for a standard run, 'pnpm test:watch' for continuous testing, and 'pnpm coverage' to generate a test coverage report. ```bash # Run all tests pnpm test # Run tests in watch mode pnpm test:watch # Generate coverage report pnpm coverage ``` -------------------------------- ### Basic Test Structure in Vitest Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Illustrates the Arrange-Act-Assert pattern for writing tests using Vitest. Ensure to import necessary functions from 'vitest'. ```typescript import { describe, it, expect } from "vitest"; describe("Feature Name", () => { it("should do something specific", () => { // Arrange const input = "test"; // Act const result = functionToTest(input); // Assert expect(result).toBe("expected"); }); }); ``` -------------------------------- ### Get Universe Information by ID Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Retrieve detailed information about a specific Roblox universe using its unique ID. This includes display name and voice chat status. ```typescript const universe = await client.universes.get("123456789"); console.log(universe.displayName); console.log(universe.voiceChatEnabled); console.log(universe.desktopEnabled); console.log(universe.privateServerPriceRobux); ``` -------------------------------- ### OpenCloud Project Structure Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Overview of the directory structure for the OpenCloud project, indicating the purpose of key directories. ```tree opencloud/ ├── src/ # Source code │ ├── resources/ # API resource implementations (users, groups, etc.) │ ├── types/ # TypeScript type definitions │ ├── errors.ts # Custom error classes │ ├── http.ts # HTTP client implementation │ └── index.ts # Main entry point ├── test/ # Test files │ ├── _utils.ts # Test utilities │ └── *.test.ts # Test suites ├── docs/ # Generated documentation ├── dist/ # Built output (generated) └── coverage/ # Test coverage reports (generated) ``` -------------------------------- ### Importing SDK Types Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/typescript.md All necessary types, including OpenCloud, User, Group, and InventoryItem, are exported from the main @relatiohq/opencloud package for easy import. ```typescript import { OpenCloud, User, Group, InventoryItem, GroupRole, GroupMembershipItem } from "@relatiohq/opencloud"; ``` -------------------------------- ### Pagination with Max Page Size Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/rate-limiting.md Demonstrates using 'maxPageSize' for efficient pagination. A smaller page size (e.g., 100) is generally preferred over the maximum possible to avoid excessive requests. ```typescript // Good: Reasonable page size const members = await client.groups.listGroupMemberships("123456789", { maxPageSize: 100 }); // Avoid: Requesting maximum items too frequently const members = await client.groups.listGroupMemberships("123456789", { maxPageSize: 1000 }); ``` -------------------------------- ### Refactoring API Calls with SDK Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Compares verbose 'before' code using fetch with the concise 'after' code using the SDK for listing inventory items. ```typescript // Before: Verbose const url = new URL(`https://apis.roblox.com/cloud/v2/users/${userId}/inventory-items`); url.searchParams.set("maxPageSize", "50"); url.searchParams.set("filter", "inventoryItemAssetTypes=HAT"); const response = await fetch(url, { headers: { "x-api-key": apiKey } }); const data = await response.json(); // After: Concise const data = await client.users.listInventoryItems(userId, { maxPageSize: 50, filter: "inventoryItemAssetTypes=HAT" }); ``` -------------------------------- ### Migrate Accepting Join Requests Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Replace POST requests for accepting join requests with the client.groups.acceptGroupJoinRequest method. ```typescript // Before await fetch( `https://apis.roblox.com/cloud/v2/groups/${groupId}/join-requests/${requestId}:accept`, { method: "POST", headers: { "x-api-key": apiKey } } ); ``` ```typescript // After await client.groups.acceptGroupJoinRequest(groupId, requestId); ``` -------------------------------- ### Migrate from Manual API Calls to OpenCloud SDK Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Replace manual fetch calls with the OpenCloud SDK for automatic error handling, retries, and type safety. ```typescript // Manual implementation const response = await fetch( `https://apis.roblox.com/cloud/v2/users/${userId}`, { headers: { "x-api-key": process.env.ROBLOX_API_KEY } } ); if (!response.ok) { const error = await response.json(); throw new Error(`API error: ${response.status} - ${error.message}`); } const user = await response.json(); ``` ```typescript import { OpenCloud } from "@relatiohq/opencloud"; const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY! }); // Automatic error handling, retries, and type safety const user = await client.users.get(userId); ``` -------------------------------- ### Fetch First Page of User Inventory Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/pagination.md Retrieve the initial set of items from a paginated list. Always check the nextPageToken to determine if more data is available. ```typescript // Get first page of user inventory const firstPage = await client.users.listInventoryItems("123456789"); console.log(`Found ${firstPage.inventoryItems.length} items`); console.log(`Has more pages: ${!!firstPage.nextPageToken}`); ``` -------------------------------- ### Migrate Listing Inventory with Pagination Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Update inventory listing logic to use the client.users.listInventoryItems method, which handles pagination internally. ```typescript // Before let allItems = []; let pageToken = undefined; do { const url = new URL(`https://apis.roblox.com/cloud/v2/users/${userId}/inventory-items`); if (pageToken) url.searchParams.set("pageToken", pageToken); const response = await fetch(url, { headers: { "x-api-key": apiKey } }); const data = await response.json(); allItems.push(...data.inventoryItems); pageToken = data.nextPageToken; } while (pageToken); ``` ```typescript // After let allItems = []; let pageToken = undefined; do { const page = await client.users.listInventoryItems(userId, { pageToken }); allItems.push(...page.inventoryItems); pageToken = page.nextPageToken; } while (pageToken); ``` -------------------------------- ### Publish Message Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Send messages to subscribed game servers within a universe. ```APIDOC ## Publish Message ### Description Send messages to subscribed game servers within a universe. ### Method POST ### Endpoint `/universes/{universeId}/publish` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe. #### Request Body - **topic** (string) - Required - The topic to publish the message to. - **message** (string) - Required - The message content, typically JSON stringified. ### Request Example ```json { "topic": "server-announcements", "message": "{\"type\": \"maintenance\", \"scheduledTime\": \"2024-11-15T03:00:00Z\"}" } ``` ### Response #### Success Response (200) - (No specific fields mentioned, implies success status) ### Response Example (No example provided in source) ``` -------------------------------- ### Update Universe Settings Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Update platform availability and other settings for a universe. ```APIDOC ## Update Universe Settings ### Description Update platform availability and other settings for a universe. ### Method PUT ### Endpoint `/universes/{universeId}` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe to update. #### Request Body - **voiceChatEnabled** (boolean) - Optional - Whether to enable voice chat. - **desktopEnabled** (boolean) - Optional - Whether to enable desktop access. - **mobileEnabled** (boolean) - Optional - Whether to enable mobile access. - **privateServerPriceRobux** (number) - Optional - The price for private servers in Robux. ### Request Example ```json { "voiceChatEnabled": true, "desktopEnabled": true, "mobileEnabled": true, "privateServerPriceRobux": 100 } ``` ### Response #### Success Response (200) - (No specific fields mentioned, implies success status) ### Response Example (No example provided in source) ``` -------------------------------- ### Migrate from axios to OpenCloud SDK Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Switch from axios to the OpenCloud SDK to leverage built-in rate limit handling and automatic retries. ```typescript import axios from "axios"; const client = axios.create({ baseURL: "https://apis.roblox.com", headers: { "x-api-key": process.env.ROBLOX_API_KEY } }); try { const response = await client.get(`/cloud/v2/users/${userId}`); const user = response.data; } catch (error) { if (error.response?.status === 429) { // Handle rate limiting manually await new Promise(resolve => setTimeout(resolve, 5000)); // Retry... } throw error; } ``` ```typescript import { OpenCloud } from "@relatiohq/opencloud"; const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY! }); // Built-in rate limit handling and retries const user = await client.users.get(userId); ``` -------------------------------- ### List Group Join Requests with Pagination Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Retrieve pending join requests for a group, supporting pagination with `maxPageSize`. Each request includes user and creation time. ```typescript const requests = await client.groups.listGroupJoinRequests("123456789", { maxPageSize: 50 }); for (const request of requests.groupJoinRequests) { console.log(request.user); // "users/987654321" console.log(request.createTime); } ``` -------------------------------- ### Fetch User Inventory Items Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Retrieve a list of inventory items for a given user, with options to filter by item type and set the maximum page size. ```typescript // Get a user's inventory items const inventory = await client.users.listInventoryItems("123456789", { maxPageSize: 50, filter: "inventoryItemAssetTypes=HAT,CLASSIC_PANTS", }); for (const item of inventory.inventoryItems) { console.log(item.assetDetails.displayName); } ``` -------------------------------- ### List User Inventory Items Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Retrieve all items from a user's inventory. Each item includes display name and asset type. ```typescript // Get all inventory items const inventory = await client.users.listInventoryItems("123456789"); for (const item of inventory.inventoryItems) { console.log(item.assetDetails.displayName); console.log(item.assetDetails.assetType); } ``` -------------------------------- ### Clone OpenCloud Repository Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Clone your forked repository locally and add the upstream remote for tracking changes. ```bash git clone https://github.com/relatiocc/opencloud.git cd opencloud ``` ```bash git remote add upstream https://github.com/relatiocc/opencloud.git ``` -------------------------------- ### Custom Retry Configuration (Aggressive) Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/rate-limiting.md Configure the SDK for more aggressive retries by increasing the number of 'attempts'. ```typescript const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY!, retry: { attempts: 6, // More retry attempts backoff: "exponential" } }); ``` -------------------------------- ### Fetch Second Page of User Inventory Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/pagination.md Fetch the next page of results by passing the nextPageToken obtained from a previous response. This is essential for retrieving all data when it spans multiple pages. ```typescript const firstPage = await client.users.listInventoryItems("123456789"); if (firstPage.nextPageToken) { const secondPage = await client.users.listInventoryItems("123456789", { pageToken: firstPage.nextPageToken }); console.log(`Page 2 has ${secondPage.inventoryItems.length} items`); } ``` -------------------------------- ### List Inventory Items Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md List items in a user's inventory with optional filtering and pagination. ```APIDOC ## List Inventory Items ### Description List items in a user's inventory with optional filtering and pagination. ### Method GET ### Endpoint /users/{userId}/inventory ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user whose inventory to list. #### Query Parameters - **filter** (string) - Optional - Filters items by asset type (e.g., `inventoryItemAssetTypes=HAT,CLASSIC_PANTS`). - **maxPageSize** (integer) - Optional - The maximum number of items to return per page. Defaults to 100. - **pageToken** (string) - Optional - A token to retrieve the next page of results. ### Response #### Success Response (200) - **inventoryItems** (array) - An array of inventory items. - **item.assetDetails.displayName** (string) - The display name of the asset. - **item.assetDetails.assetType** (string) - The type of the asset. - **nextPageToken** (string) - A token to retrieve the next page of results, if available. ``` -------------------------------- ### List Asset Quotas Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md View upload quotas and usage limits for a user. ```APIDOC ## List Asset Quotas ### Description View upload quotas and usage limits for a user. ### Method GET ### Endpoint /users/{userId}/asset-quotas ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user whose asset quotas to check. ### Response #### Success Response (200) - **assetQuotas** (array) - An array of asset quota objects. - **quota.assetType** (string) - The type of asset. - **quota.usage** (integer) - The current usage for the asset type. - **quota.quota** (integer) - The limit for the asset type. - **quota.usageResetTime** (string) - The time when the usage resets. ``` -------------------------------- ### List Group Members with Pagination Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Fetch all members of a group, supporting pagination with `maxPageSize`. Each member object includes user and role information. ```typescript const members = await client.groups.listGroupMemberships("123456789", { maxPageSize: 100 }); for (const member of members.groupMemberships) { console.log(member.user); // "users/987654321" console.log(member.role); // "groups/123456789/roles/12345" } ``` -------------------------------- ### Configuring Automatic Retries Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Illustrates how to configure built-in retry logic for API requests. Specify the number of attempts and the backoff strategy. ```typescript // No manual retry logic needed const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY!, retry: { attempts: 4, backoff: "exponential" } }); ``` -------------------------------- ### API Key Authentication Configuration Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/authentication.md Defines the `AuthConfig` object for API key authentication, which is then passed to the `withAuth` method to configure the client. ```typescript const auth = { kind: "apiKey", apiKey: "your-api-key" }; const client = new OpenCloud().withAuth(auth); ``` -------------------------------- ### Generate User Thumbnail Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/getting-started.md Generate a user thumbnail with specified size, format, and shape. The response contains a URI to the generated image. ```typescript const thumbnail = await client.users.generateThumbnail("123456789", { size: 420, format: "PNG", shape: "ROUND", }); console.log(thumbnail.response.imageUri); ``` -------------------------------- ### Create New Git Branch Source: https://github.com/relatiocc/opencloud/blob/main/CONTRIBUTING.md Use these commands to create a new branch for feature development or bug fixes, following established naming conventions. ```bash git checkout -b feature/your-feature-name # or git checkout -b fix/your-bug-fix ``` -------------------------------- ### Type-Safe Helper Functions Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/typescript.md Create reusable, type-safe helper functions by leveraging SDK types like `User` and `GroupRole` for operations such as fetching users by IDs or finding group roles by name. ```typescript import type { User, Group } from "@relatiohq/opencloud"; async function getUsersByIds(userIds: string[]): Promise { const users: User[] = []; for (const userId of userIds) { const user = await client.users.get(userId); users.push(user); } return users; } async function getGroupRoleByName( groupId: string, roleName: string ): Promise { const roles = await client.groups.listGroupRoles(groupId); return roles.groupRoles.find(role => role.displayName === roleName); } ``` -------------------------------- ### Automatic Retry Configuration Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/rate-limiting.md Configure the SDK with custom retry attempts and backoff strategy. The SDK automatically retries requests when rate limits are encountered. ```typescript const client = new OpenCloud({ apiKey: process.env.ROBLOX_API_KEY!, retry: { attempts: 4, // Number of retry attempts (default: 4) backoff: "exponential" // Exponential backoff strategy (default) } }); // The SDK will automatically retry if rate limited const user = await client.users.get("123456789"); ``` -------------------------------- ### Generate Speech Asset from Text Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Create an AI-generated speech asset from a text string for a universe. This includes basic speech style parameters like voice ID, pitch, and speed. ```typescript const speechAsset = await client.universes.generateSpeechAsset("123456789", { text: "Welcome to the game!", speechStyle: { voiceId: "1", pitch: 1.0, speed: 1.0 } }); if (speechAsset.response.moderationResult.moderationState === "Approved") { console.log(`Asset ID: ${speechAsset.response.assetId}`); } ``` -------------------------------- ### Accept Group Join Request Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md Accept a pending join request for a group. ```APIDOC ## Accept Group Join Request ### Description Accept a join request for the group. ### Method `client.groups.acceptGroupJoinRequest(groupId, requestId)` ### Parameters #### Path Parameters - **groupId** (string) - Required - The unique identifier of the group. - **requestId** (string) - Required - The unique identifier of the join request to accept. ### Request Example ```typescript await client.groups.acceptGroupJoinRequest( "123456789", // Group ID "555555555" // Join request ID ); console.log("Join request accepted"); ``` ``` -------------------------------- ### Generate Thumbnail Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Generate avatar thumbnails with customizable size, format, and shape. ```APIDOC ## Generate Thumbnail ### Description Generate avatar thumbnails with customizable size, format, and shape. ### Method POST ### Endpoint /users/{userId}/thumbnail ### Parameters #### Path Parameters - **userId** (string) - Required - The ID of the user whose thumbnail to generate. #### Query Parameters - **size** (integer) - Optional - The desired size of the thumbnail (e.g., 48, 50, 60, 75, 100, 110, 150, 180, 352, 420, 720). Defaults to 420. - **format** (string) - Optional - The image format (PNG or JPEG). Defaults to PNG. - **shape** (string) - Optional - The shape of the thumbnail (ROUND or SQUARE). Defaults to ROUND. ### Response #### Success Response (200) - **response.imageUri** (string) - The URI of the generated thumbnail image. ``` -------------------------------- ### List Group Join Requests Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/groups.md List pending join requests for a group, with support for pagination and filtering by user. ```APIDOC ## List Group Join Requests ### Description List join requests for a group with pagination support. ### Method `client.groups.listGroupJoinRequests(groupId, options)` ### Parameters #### Path Parameters - **groupId** (string) - Required - The unique identifier of the group. #### Query Parameters - **maxPageSize** (number) - Optional - The maximum number of requests to return per page. - **filter** (string) - Optional - A filter string to narrow down results, e.g., `user == 'user_id'`. ### Response #### Success Response (200) - **groupJoinRequests** (array) - An array of join request objects. - **user** (string) - The user ID of the requester. - **createTime** (string) - The timestamp when the request was created. ### Request Example ```typescript const requests = await client.groups.listGroupJoinRequests("123456789", { maxPageSize: 50 }); for (const request of requests.groupJoinRequests) { console.log(request.user); console.log(request.createTime); } // Filtering Requests const userRequest = await client.groups.listGroupJoinRequests("123456789", { filter: "user == 'users/987654321'" }); ``` ``` -------------------------------- ### Type-Safe Client Configuration Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/typescript.md Configure the OpenCloud client using the `OpenCloudConfig` type for type safety, ensuring correct parameters like apiKey, userAgent, baseUrl, and retry settings. ```typescript import type { OpenCloudConfig } from "@relatiohq/opencloud"; const config: OpenCloudConfig = { apiKey: process.env.ROBLOX_API_KEY!, userAgent: "MyApp/1.0", baseUrl: "https://apis.roblox.com", retry: { attempts: 4, backoff: "exponential" } }; const client = new OpenCloud(config); ``` -------------------------------- ### Check User Asset Quotas Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md View upload quotas and usage limits for a user's assets. Displays asset type, current usage, limit, and when the usage resets. ```typescript const quotas = await client.users.listAssetQuotas("123456789"); for (const quota of quotas.assetQuotas) { console.log(`Asset Type: ${quota.assetType}`); console.log(`Usage: ${quota.usage}`); console.log(`Limit: ${quota.quota}`); console.log(`Resets at: ${quota.usageResetTime}`); } ``` -------------------------------- ### Per-Request Authentication with OAuth2 Source: https://github.com/relatiocc/opencloud/blob/main/README.md Use the `withAuth` method to authenticate individual requests with OAuth2 access tokens. This is ideal for multi-tenant applications where each user has their own token. ```typescript // Create client without default auth const client = new OpenCloud(); // Use different credentials per request const userClient = client.withAuth({ kind: "oauth2", accessToken: "user-access-token", }); const groups = await userClient.groups.listGroupMemberships("123456"); ``` -------------------------------- ### List User Restriction Logs Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/universes.md Track all restriction changes for a universe, with optional filtering. ```APIDOC ## List User Restriction Logs ### Description Track all restriction changes for a universe, with optional filtering. ### Method GET ### Endpoint `/universes/{universeId}/restrictions/logs` ### Parameters #### Path Parameters - **universeId** (string) - Required - The ID of the universe. #### Query Parameters - **filter** (string) - Optional - Filter criteria for the logs (e.g., "user == 'users/987654321'"). ### Response #### Success Response (200) - **logs** (array) - A list of restriction log entries. - **user** (string) - The ID of the user affected. - **moderator** (object) - **robloxUser** (string) - The Roblox username of the moderator. - **displayReason** (string) - The reason for the restriction displayed to the user. ### Response Example ```json { "logs": [ { "user": "987654321", "moderator": { "robloxUser": "AdminUser" }, "displayReason": "Violation of game rules" } ] } ``` ``` -------------------------------- ### Generate Avatar Thumbnails Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/resources/users.md Create customizable avatar thumbnails. Supports PNG and JPEG formats, with options for size and shape (round or square). The default size is 420px. ```typescript const thumbnail = await client.users.generateThumbnail("123456789", { size: 420, // 48, 50, 60, 75, 100, 110, 150, 180, 352, 420, 720 format: "PNG", // PNG, JPEG shape: "ROUND" // ROUND, SQUARE }); console.log(thumbnail.response.imageUri); ``` -------------------------------- ### Automatic Error Handling with SDK Source: https://github.com/relatiocc/opencloud/blob/main/src/docs/guide/migration.md Shows how the SDK provides structured error types for robust error handling. Catch specific errors like RateLimitError and AuthError. ```typescript // SDK provides structured error types import { OpenCloudError, RateLimitError, AuthError } from "@relatiohq/opencloud"; try { const user = await client.users.get("123456789"); } catch (error) { if (error instanceof RateLimitError) { // Handle rate limiting } else if (error instanceof AuthError) { // Handle auth issues } } ```