What did this do?
backend.json
file in your directory with some default
settings.module.json
config here.What did this do?
modules/my_leaderboard
and updated
backend.json
to include the module. The important files we’ll look at are
modules/my_leaderboard/db/schema.prisma
, modules/my_leaderboard/scripts/
,
and modules/my_leaderboard/tests/
.modules/my_leaderboard/db/schema.prisma
file to look like this:
What's going on here?
model Scores
creates a new table that will store all of the scores on the leadboardid
is the unique identifier for each score.
String
is the type of the column@id
indicates that this is the primary key of the table@default(uuid())
indicates that this column will be automatically set to a UUID when a new row is created@db.Uuid
indicates that this is stored as UUID type. UUIDs are universally unique (unlike integers) and take a small amount of storage (unlike strings).createdAt
is the time the score was created
DateTime
is the type of the column@default(now())
indicates that this column will be automatically set to the current time when a new row is created@db.Timestamp
indicates that this is stored as a timestamp type. This is a good way to store dates and times in a database.userId
is the user who submitted the score
String
is the type of the column@db.Uuid
indicates that this is stored as UUID type.score
is the score itself
Int
is the type of the column@@index([score])
creates an index on the score
column.
submit_score
scriptsubmit_score
script that will:
Create script
What did this do?
modules/my_leaderboard/scripts/submit_score.ts
:modules/my_leaderboard/module.json
to include the new script:What's going on here?
import { ScriptContext } from "../module.gen.ts";
imports the ScriptContext
.
module.gen.ts
file is generated by Open Game Backend to provide a type-safe interface for the database (see schema.prisma
), calling other modules, and reading the module config.export interface Request {}
and export interface Response {}
define the input and output of the script.
export async function run(...)
is the main function of the script.
Add dependencies & make public
modules/my_leaderboard/module.json
file to look like this:What did this do?
user
and rate_limit
as dependencies. This will allow us to authenticate the user and rate limit calls to the script.public: true
for the submit_score
script so that anyone can call it.Update request & response
modules/my_leaderboard/scripts/submit_score.ts
and update Request
and Response
to look like this:What did this do?
userToken
and submit a score using score
.Throttle requests
run
function in modules/my_leaderboard/scripts/submit_score.ts
file, add code to throttle requests:What did this do?
rate_limit_exceeded
error will be thrown. See the rate limit docs for more details.Validate user token
What did this do?
Insert score
What did this do?
id
and createdAt
will be automatically set by the database because of the @default
annotations in the schema.Query rank
What did this do?
gt
) the user’s score. This is the user’s rank on the leaderboard.We add 1 to the rank, since the 1st place will have 0 scores greater than it.Full submit_score.ts source code
get_top_scores
scriptCreate script
Make public
modules/my_leaderboard/module.json
and update the get_top_scores
script to be public:Update request & response
modules/my_leaderboard/scripts/get_top_scores.ts
and update Request
and Response
to look like this:What did this do?
count
scores and return an array of Score
objects.Throttle requests
run
function in modules/my_leaderboard/scripts/get_top_scores.ts
file, add code to throttle the requests:Query scores
What did this do?
take
limits the number of scores returned to req.count
.orderBy
orders the scores by score
in descending order.select
limits the columns returned to userId
, createdAt
, and score
.Convert rows
Score
objects:What did this do?
Score
objects we defined in the Response
.We use toISOString
to convert the createdAt
of type Date
into a string.Full get_top_scores.ts source code
Start development server
Migrate database
Success
Create test
e2e
stands for “end to end” test. E2E tests simulate real-world scenarios involving multiple parts of a system. These tend to be comprehensive and catch the most bugs.Write test
modules/my_leaderboard/tests/e2e.ts
to look like this:Run test