@rtsdk/topia 0.17.7 → 0.17.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -183,11 +183,11 @@ Run `yarn add @rtsdk/topia` or `npm install @rtsdk/topia`
183
183
 
184
184
  Create your instance of Topia and instantiate the factories you need:
185
185
 
186
- ```js
186
+ ```ts
187
187
  dotenv.config();
188
188
  import dotenv from "dotenv";
189
189
 
190
- import { AssetFactory, Topia, DroppedAssetFactory, UserFactory, WorldFactory } from "@rtsdk/topia";
190
+ import { AssetFactory, Topia, DroppedAssetFactory, UserFactory, VisitorFactory, WorldFactory } from "@rtsdk/topia";
191
191
 
192
192
  const config = {
193
193
  apiDomain: process.env.INSTANCE_DOMAIN || "https://api.topia.io/",
@@ -200,31 +200,43 @@ const myTopiaInstance = new Topia(config);
200
200
  const Asset = new AssetFactory(myTopiaInstance);
201
201
  const DroppedAsset = new DroppedAssetFactory(myTopiaInstance);
202
202
  const User = new UserFactory(myTopiaInstance);
203
+ const Visitor = new VisitorFactory(myTopiaInstance);
203
204
  const World = new WorldFactory(myTopiaInstance);
204
205
 
205
- export { Asset, DroppedAsset, myTopiaInstance, User, World };
206
+ export { Asset, DroppedAsset, User, Visitor, World };
206
207
  ```
207
208
 
208
209
  <br/>
209
210
 
210
- Put it to use:
211
+ Put it to use in your controller:
211
212
 
212
- ```js
213
- import { DroppedAsset } from "./pathToAboveCode";
213
+ ```ts
214
+ import { Request, Response } from "express";
215
+ import { DroppedAsset } from "utils/topiaInit.ts";
216
+ import { VisitorInterface } from "@rtsdk/topia";
214
217
 
215
- export const getAssetAndDataObject = async (req) => {
216
- const { assetId, interactiveNonce, interactivePublicKey, urlSlug, visitorId } = req.query;
218
+ export const getDroppedAssetAndVisitor = async (req: Request, res: Response) => {
219
+ try {
220
+ const { assetId, interactiveNonce, interactivePublicKey, urlSlug, visitorId } = req.query;
217
221
 
218
- const droppedAsset = await DroppedAsset.get(assetId, urlSlug, {
219
- credentials: {
222
+ const credentials = {
220
223
  interactiveNonce,
221
224
  interactivePublicKey,
225
+ assetId,
226
+ urlSlug,
222
227
  visitorId,
223
- },
224
- });
228
+ };
229
+
230
+ const droppedAsset = await DroppedAsset.get(assetId, urlSlug, { credentials });
231
+
232
+ await droppedAsset.fetchDataObject();
225
233
 
226
- await droppedAsset.fetchDroppedAssetDataObject();
227
- return droppedAsset;
234
+ const visitor: VisitorInterface = await Visitor.get(visitorId, urlSlug, { credentials });
235
+
236
+ return { droppedAsset, isAdmin: visitor.isAdmin };
237
+ } catch (error) {
238
+ return res.status(error.status || 500).send({ error, success: false });
239
+ }
228
240
  };
229
241
  ```
230
242
 
@@ -237,19 +249,19 @@ There are three types of Data Objects:
237
249
 
238
250
  - **World:** The World data object should be used to store information unique to your app in a given world but not necessarily specific details about an instance or an active game. This information would persist even if the app was removed from the world.
239
251
  - **Example - Update two specific data points:**
240
- ```js
252
+ ```ts
241
253
  await world.updateDataObject({
242
254
  [`keyAssets.${keyAssetId}.itemsCollectedByUser.${profileId}`]: { [dateKey]: { count: 1 }, total: 1 },
243
255
  [`profileMapper.${profileId}`]: username,
244
256
  });
245
257
  ```
246
258
  - **Example - Increment a specific value within the data object by 1:**
247
- ```js
259
+ ```ts
248
260
  await world.incrementDataObjectValue([`keyAssets.${keyAssetId}.totalItemsCollected.count`], 1);
249
261
  ```
250
262
  - **Dropped Asset:** The Dropped Asset data object should only store what is unique to the specific instance of the app in the world such as game state. If the Dropped Asset is deleted, the data object would be lost as well so be sure to only store information here the doesn't need to persist!
251
263
  - **Example - Initialize data object with default data and keyAssetId:**
252
- ```js
264
+ ```ts
253
265
  await droppedAsset.setDataObject(
254
266
  {
255
267
  ...defaultGameData,
@@ -259,7 +271,7 @@ There are three types of Data Objects:
259
271
  );
260
272
  ```
261
273
  - **Example - Update lastInteraction date and playerCount:**
262
- ```js
274
+ ```ts
263
275
  await droppedAsset.updateDataObject({ lastInteraction: new Date(), playerCount: playerCount + 1 });
264
276
  ```
265
277
  - **User:** The User data object should be used to store information unique to a user that is NOT unique to a world or instance (dropped asset) of an app.
@@ -271,7 +283,7 @@ There are three types of Data Objects:
271
283
 
272
284
  All of our data object set, update, and increment methods have an optional lock argument. You can create a lock id using that parameters specific to the action you are taking plus a timestamp so that the lock will expire after a certain amount of time has passed. As an example, TicTacToe allows users to Reset the game board so that they can start a new game but we'd only want the reset to happen once even if the user(s) press the button multiple times. To prevent multiple resets from happening within a 10 second window (stopping the calls from going through and preventing the race condition), we'd lock the object by doing the following:
273
285
 
274
- ```js
286
+ ```ts
275
287
  try {
276
288
  await droppedAsset.updateDataObject(
277
289
  { isResetInProgress: true },
@@ -289,7 +301,7 @@ Using the code above would also allow us to check if `isResetInProgress === true
289
301
  **Turn based locking**
290
302
  Locking data object updates can also be extremely helpful when building a turn based game. As an example, TicTacToe should only allow one user to take a turn at a time. To prevent multiple moves at once we could use the following:
291
303
 
292
- ```js
304
+ ```ts
293
305
  try {
294
306
  const timestamp = new Date(Math.round(new Date().getTime() / 5000) * 5000);
295
307
  const lockId = `${keyAssetId}-${resetCount}-${turnCount}-${timestamp}`;
@@ -301,14 +313,15 @@ try {
301
313
 
302
314
  Once complete be sure to also call `await keyAsset.updateDataObject({ turnCount: turnCount + 1 });` so that the next player is free to take their turn!
303
315
 
304
- **Custom analytics**
316
+ ### Custom Analytics
317
+
305
318
  You can leverage the data object methods for all types to track analytics unique to your Public Key by passing `analytics` as an optional array along with `profileId`, `urlSlug`, and/or `uniqueKey` to all calls that set, update, or increment data objects!
306
319
 
307
320
  **World** and **Dropped Asset** classes will automatically include `urlSlug`. In addition to `analytics` you can also pass `profileId` if you want to track event per user and/or a `uniqueKey` to additionally track uniqueness of the event for all time, per user (if `profileId` is included), and per world.
308
321
 
309
322
  Examples leveraging World data objects calls:
310
323
 
311
- ```js
324
+ ```ts
312
325
  await world.setDataObject({ hello: "world" }, { analytics: [{ analyticName: "resets"} ], lock: { lockId, releaseLock: true });
313
326
 
314
327
  await world.updateDataObject({}, { analytics: [ {analyticName: "matches", uniqueKey: `${playerOneProfileId}-${playerTwoProfileId}`, urlSlug }], });
@@ -320,7 +333,7 @@ await world.incrementDataObjectValue(`keyAssets.${assetId}.completions`, 1, { an
320
333
 
321
334
  Examples leveraging Visitor data objects calls:
322
335
 
323
- ```js
336
+ ```ts
324
337
  await visitor.setDataObject(
325
338
  { hello: "world" },
326
339
  { analytics: [{ analyticName: "starts" }], lock: { lockId, releaseLock: true } },
@@ -370,6 +383,10 @@ We've added a Pull Request template to help make it easier for developers to cla
370
383
 
371
384
  The SDK Stylesheet is already added to every boilerplate. To view documentation and examples please [click here](https://sdk-style.s3.amazonaws.com/example.html).
372
385
 
386
+ ### AI Rules for @rtsdk/topia
387
+
388
+ Always follow the rules outlined in ./ai/rules.md.
389
+
373
390
  ### Developer Documentation
374
391
 
375
392
  We use [TypeDoc](https://typedoc.org/guides/overview) to convert comments in TypeScript source code into rendered HTML documentation. Comments should be simple and concise and include examples where applicable. Please be sure to add or update comments accordingly!
@@ -382,12 +399,15 @@ Example of Class comments:
382
399
 
383
400
  ````ts
384
401
  /**
385
- * @summary
386
402
  * Create an instance of Dropped Asset class with a given dropped asset id, url slug, and optional attributes and session credentials.
387
403
  *
388
- * @usage
404
+ * @example
389
405
  * ```ts
390
- * await new DroppedAsset(topia, "1giFZb0sQ3X27L7uGyQX", "example", { attributes: { text: "" }, credentials: { assetId: "1giFZb0sQ3X27L7uGyQX" } } });
406
+ * import { DroppedAsset } from "utils/topiaInit.ts";
407
+ *
408
+ * const droppedAsset = await DroppedAsset.get(exampleDroppedAssetId, exampleUrlSlug, {
409
+ * credentials: { interactivePublicKey: "examplePublicKey", interactiveNonce: "exampleNonce", assetId: "exampleDroppedAssetId", visitorId: 1, urlSlug: "exampleUrlSlug" }
410
+ * });
391
411
  * ```
392
412
  */
393
413
  ````
@@ -396,17 +416,24 @@ Example of method comments
396
416
 
397
417
  ````ts
398
418
  /**
399
- * @summary
400
- * Sets the data object for a dropped asset.
419
+ * Sets the data object for a dropped asset and assigns the response data to the instance.
401
420
  *
421
+ * @remarks
402
422
  * Optionally, a lock can be provided with this request to ensure only one update happens at a time between all updates that share the same lock id
403
423
  *
404
- * @usage
424
+ * @category Data Objects
425
+ *
426
+ * @example
405
427
  * ```ts
406
- * await droppedAsset.setDroppedAssetDataObject({
407
- * "exampleKey": "exampleValue",
408
- * });
409
- * const { dataObject } = droppedAsset;
428
+ * await droppedAsset.setDataObject(
429
+ * { resetCount: 0 },
430
+ * {
431
+ * analytics: [{ analyticName: "resets"} ],
432
+ * lock: { lockId: `${droppedAssetId}-${resetCount}-${new Date(Math.round(new Date().getTime() / 10000) * 10000)}` },
433
+ * },
434
+ * );
435
+ *
436
+ * const { resetCount } = droppedAsset.dataObject;
410
437
  * ```
411
438
  */
412
439
  ````