Skip to content

Commit 42f20a9

Browse files
Added Javascript reference to open cloud datastore doc (#916)
## Changes Adds JavaScript examples to the existing markdown documentation, providing alternative code implementations alongside the original Python examples for the user inventory and leaderboard functionalities. **Update 12.19.24** Made collapsible sections for JavaScript and Python code. Python code is open by default since it's the main code on the docs. ## Checks By submitting your pull request for review, you agree to the following: - [x] This contribution was created in whole or in part by me, and I have the right to submit it under the terms of this repository's open source licenses. - [x] I understand and agree that this contribution and a record of it are public, maintained indefinitely, and may be redistributed under the terms of this repository's open source licenses. - [x] To the best of my knowledge, all proposed changes are accurate. --------- Co-authored-by: Jermaine Cheng <[email protected]>
1 parent 01bffc6 commit 42f20a9

File tree

1 file changed

+204
-0
lines changed

1 file changed

+204
-0
lines changed

content/en-us/cloud/open-cloud/usage-data-stores.md

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,9 @@ When [creating an API Key](./api-keys.md) for this example, make sure you perfor
7878

7979
#### Add scripts for the user inventory support portal
8080

81+
<details open>
82+
<summary>Click for Python Example</summary>
83+
8184
After creating the API key with permissions required for the example app, you need to add Python scripts to perform app functionalities. The `data_stores_methods.py` file shows how to define [`List Entries`](../../reference/cloud/datastores-api/v1.json#list-entries), [`Get Entry`](../../reference/cloud/datastores-api/v1.json#get-entry), and [`Increment Entry`](../../reference/cloud/datastores-api/v1.json#increment-entry) methods. The `update_inventory` file uses the defined methods to list a subset of user inventories, increase the virtual currency for each user, and update the data.
8285

8386
```python title='data_stores_methods.py'
@@ -186,6 +189,102 @@ To test, set the `API_KEY` environment variable and run `update_inventory` file:
186189
export API_KEY=... \
187190
python update_inventory
188191
```
192+
193+
</details>
194+
195+
<details>
196+
<summary>Click for JavaScript Example</summary>
197+
198+
After creating the API key with the required permissions for the example app, you need to add JavaScript code to perform app functionalities. The `data_stores_methods.js` file shows how to define [`List Entries`](../../reference/cloud/datastores-api/v1.json#list-entries), [`Get Entry`](../../reference/cloud/datastores-api/v1.json#get-entry), and [`Increment Entry`](../../reference/cloud/datastores-api/v1.json#increment-entry) methods. The `update_inventory.js` file uses the defined methods to list a subset of user inventories, increase the virtual currency for each user, and update the data.
199+
200+
```javascript title='dataStoresMethods.js'
201+
const fetch = require('node-fetch');
202+
203+
class DataStores {
204+
constructor() {
205+
this._baseUrl = "https://apis.roblox.com/datastores/v1/universes/{universeId}";
206+
this._apiKey = process.env.API_KEY;
207+
this._universeId = "UNIVERSE_ID";
208+
this.ATTR_HDR = 'Roblox-entry-Attributes';
209+
this.USER_ID_HDR = 'Roblox-entry-UserIds';
210+
this._objectsUrl = `${this._baseUrl}${this._universeId}/standard-datastores/datastore/entries/entry`;
211+
this._incrementUrl = `${this._objectsUrl}/increment`;
212+
this._listObjectsUrl = `${this._baseUrl}${this._universeId}/standard-datastores/datastore/entries`;
213+
}
214+
215+
async _getHeaders() {
216+
return { 'x-api-key': this._apiKey };
217+
}
218+
219+
async getEntry(datastore, objectKey, scope = null) {
220+
const url = `${this._objectsUrl}?datastoreName=${datastore}&entryKey=${objectKey}&scope=${scope || ''}`;
221+
const response = await fetch(url, { headers: await this._getHeaders() });
222+
const data = await response.json();
223+
return data;
224+
}
225+
226+
async listEntries(datastore, scope = null, prefix = "", limit = 100) {
227+
const url = `${this._listObjectsUrl}?datastoreName=${datastore}&scope=${scope}&prefix=${prefix}&limit=${limit}`;
228+
const response = await fetch(url, { headers: await this._getHeaders() });
229+
const data = await response.json();
230+
return data;
231+
}
232+
233+
async incrementEntry(datastore, objectKey, incrementBy, scope = null) {
234+
const url = `${this._incrementUrl}?datastoreName=${datastore}&entryKey=${objectKey}&incrementBy=${incrementBy}&scope=${scope || ''}`;
235+
const response = await fetch(url, { method: 'POST', headers: await this._getHeaders() });
236+
const data = await response.json();
237+
return data;
238+
}
239+
}
240+
241+
module.exports = DataStores;
242+
```
243+
244+
```javascript title='updateInventory.js'
245+
const DataStores = require('./dataStoresMethods');
246+
const dataStoresApi = new DataStores();
247+
248+
// Set up
249+
const datastoreName = "Inventory";
250+
251+
// List keys for a subset of users
252+
dataStoresApi.listEntries(datastoreName)
253+
.then(keys => {
254+
console.log(keys);
255+
});
256+
257+
// Read inventory for each user
258+
for (let x = 0; x < 5; x++) {
259+
const updatedObjectKey = `User_${x + 1}`;
260+
dataStoresApi.getEntry(datastoreName, updatedObjectKey)
261+
.then(value => {
262+
console.log(`${updatedObjectKey} has ${value.gems} gems in their inventory`);
263+
});
264+
}
265+
266+
// Update the currency of each user by 10
267+
for (let x = 0; x < 5; x++) {
268+
const updatedObjectKey = `User_${x + 1}`;
269+
dataStoresApi.incrementEntry(datastoreName, updatedObjectKey, 10)
270+
.then(value => {
271+
console.log(`${updatedObjectKey} now has ${value.robux} robux in their inventory`);
272+
});
273+
}
274+
```
275+
276+
To test, set the `API_KEY` environment variable and run the JavaScript file:
277+
278+
```bash
279+
export API_KEY=... \
280+
node updateInventory.js
281+
```
282+
283+
</details>
284+
285+
### External Persistent Leaderboard
286+
287+
=======
189288

190289
### External persistent leaderboard
191290

@@ -219,6 +318,9 @@ When [creating an API Key](./api-keys.md) for this example, make sure you perfor
219318

220319
#### Add scripts for the leaderboard
221320

321+
<details open>
322+
<summary>Click for Python Example</summary>
323+
222324
After creating the API key with permissions required for the example app, you need to add Python scripts to perform app functionalities.
223325

224326
The `ordered_data_stores.py` file shows how to define [`List`](../../reference/cloud/datastores-api/ordered-v1.json#list), [`Create`](../../reference/cloud/datastores-api/ordered-v1.json#create), [`Update`](../../reference/cloud/datastores-api/ordered-v1.json#update) and [`Increment`](../../reference/cloud/datastores-api/ordered-v1.json#increment) methods. The `leaderboard` file uses the defined methods to create entries of users in ordered data stores, display scores, increment scores of winning users, and update the leaderboard. The `leaderboard` file also imports a `config` JSON file for configuring the Universe ID, API domain, and your API key.
@@ -308,3 +410,105 @@ python leaderboard
308410
```
309411

310412
After completing testing, you can publish or embed the leaderboard to websites outside of Roblox for more reach.
413+
414+
</details>
415+
416+
<details>
417+
<summary>Click for JavaScript Example</summary>
418+
419+
After creating the API key with the required permissions for the example app, you need to add JavaScript code to perform app functionalities.
420+
421+
The `ordered_data_stores.js` file shows how to define [`List`](../../reference/cloud/datastores-api/ordered-v1.json#list), [`Create`](../../reference/cloud/datastores-api/ordered-v1.json#create), [`Update`](../../reference/cloud/datastores-api/ordered-v1.json#update), and [`Increment`](../../reference/cloud/datastores-api/ordered-v1.json#increment) methods. The `leaderboard.js` file uses the defined methods to create entries of users in ordered data stores, display scores, increment scores of winning users, and update the leaderboard. The `leaderboard.js` file also imports a `config.json` file for configuring the Universe ID, API domain, and your API key.
422+
423+
```javascript title='ordered_data_stores.js'
424+
const axios = require('axios');
425+
const fs = require('fs');
426+
427+
class DataStores {
428+
constructor(configFile) {
429+
this._config = JSON.parse(fs.readFileSync(configFile, 'utf-8'));
430+
}
431+
432+
_H() {
433+
return { 'x-api-key': this._config.api_key, 'Content-Type': 'application/json' };
434+
}
435+
436+
async list(datastore, scope, pageSize = 10, orderBy = "", filter = "", exclusiveStartKey = "") {
437+
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries`;
438+
const response = await axios.get(url, {
439+
headers: this._H(),
440+
params: { "max_page_size": pageSize, "order_by": orderBy, "filter": filter, "page_token": exclusiveStartKey }
441+
});
442+
return response.data;
443+
}
444+
445+
async create(datastore, scope, entry, data) {
446+
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries`;
447+
const payload = JSON.stringify({ "value": 11 });
448+
const response = await axios.post(url, payload, {
449+
headers: this._H(),
450+
params: { "id": entry }
451+
});
452+
return response.data;
453+
}
454+
455+
async increment(datastore, scope, entry, incrementBy) {
456+
const url = `${this._config.api_key_url}universes/${this._config.universe_id}/orderedDataStores/${datastore}/scopes/${scope}/entries/${entry}:increment`;
457+
const payload = JSON.stringify({ "amount": incrementBy });
458+
const response = await axios.post(url, payload, { headers: this._H() });
459+
return response.data;
460+
}
461+
}
462+
```
463+
464+
```javascript title='leaderboard.js'
465+
const leaderboardEndpoints = require('./ordered_data_stores');
466+
467+
const datastores = new leaderboardEndpoints.DataStores('config.json');
468+
469+
// Variables
470+
const orderedDataStore = 'PlayerScores';
471+
const scope = 'global';
472+
const entryNames = ['Ragdoll', 'Balinese', 'Tabby', 'Siamese'];
473+
474+
// Create an entry and give each new player 50 points for joining the game
475+
entryNames.forEach(async (name) => {
476+
await datastores.create(orderedDataStore, scope, name, 50);
477+
});
478+
479+
// Display the players' scores
480+
datastores.list(orderedDataStore, scope).then((playerScores) => {
481+
console.log(playerScores);
482+
});
483+
484+
// Increment the first player's score for winning the game
485+
datastores.increment(orderedDataStore, scope, entryNames[0], 100);
486+
487+
// Increment all the players' scores for participating in the game
488+
entryNames.forEach(async (name) => {
489+
await datastores.increment(orderedDataStore, scope, name, 10);
490+
});
491+
492+
// Display the updated leaderboard
493+
datastores.list(orderedDataStore, scope).then((updatedPlayerScores) => {
494+
console.log(updatedPlayerScores);
495+
});
496+
```
497+
498+
```json title='config'
499+
{
500+
"universe_id": "",
501+
"api_key_url": "https://apis.roblox.com/datastores/ordered-v1/",
502+
"api_key": ""
503+
}
504+
```
505+
506+
To test, set the `API_KEY` environment variable and run the `leaderboard.js` file:
507+
508+
```bash
509+
export API_KEY=... \
510+
node leaderboard.js
511+
```
512+
513+
After completing testing, you can publish or embed the leaderboard to websites outside of Roblox for more reach.
514+
</details>

0 commit comments

Comments
 (0)