Browser; server clients
Scores and rankings
@silicon-jungle/inkwell-sdk/leaderboardsNamed boards, policies, ranking queries and creator-side score management.
Exact source · npm package · Reference version 0.0.8
API at a glance
leaderboards.board(name): Leaderboardleaderboards.find(name): Promise<Leaderboard | null>leaderboards.findOrCreate(definition): Promise<Leaderboard>leaderboards.list(offset?)board.get(), getEntryCount(), list(query?), aroundMe(options?), getMyEntry(), submit(input)context.leaderboards.define(definition)serverBoard.submitFor(username, input), queryFor(username, query?)serverBoard.update(definition), deleteEntry(username), reset(), delete()Leaderboard, ServerLeaderboard, createLeaderboards(request?), createServerLeaderboards(request)
Scores and details are signed int32. keepBest and forceUpdate have different replacement semantics; details are not arbitrary JSON or replay files.
Catalog offsets are zero-based. Ranked start is one-based; follow nextStart or nextOffset until null. Friends-only policies restrict client query scopes.
Use serverWritesOnly for backend-controlled score submission. It controls the writer, not whether a creator’s game logic is cheat-proof.
All exported symbols
LeaderboardLeaderboardDefinitionLeaderboardEntryLeaderboardInfoLeaderboardQueryLeaderboardResultScoreResultScoreSubmissionServerLeaderboardcreateLeaderboardscreateServerLeaderboardsleaderboards
Exact TypeScript API
Generated from the SDK source, including input options, return values, public types and overloads. Relative imports below are links between SDK source modules, not additional package subpaths. Only the entrypoints listed in the reference index are supported import paths.
import { type GameServiceRequest } from "./game-services.js";
export type LeaderboardDefinition = {
name: string;
communityName?: string | null;
sort?: "ascending" | "descending";
display?: "numeric" | "seconds" | "milliseconds";
serverWritesOnly?: boolean;
friendsReadsOnly?: boolean;
enabled?: boolean;
};
export type LeaderboardInfo = Required<LeaderboardDefinition> & {
createdAt: string;
updatedAt: string;
};
export type LeaderboardEntry = {
username: string;
avatarUrl: string | null;
score: number;
details: number[];
rank: number;
updatedAt: string;
};
export type LeaderboardResult = {
board: LeaderboardInfo;
total: number;
entries: LeaderboardEntry[];
nextStart: number | null;
};
export type ScoreSubmission = {
score: number;
details?: number[];
method?: "keepBest" | "forceUpdate";
};
export type ScoreResult = {
score: number;
updated: boolean;
scoreChanged: boolean;
previousRank: number | null;
rank: number;
};
export type LeaderboardQuery = {
scope?: "global" | "friends" | "around" | "users";
start?: number;
limit?: number;
before?: number;
after?: number;
usernames?: string[];
};
export declare class Leaderboard {
readonly name: string;
protected readonly request: GameServiceRequest;
constructor(name: string, request?: GameServiceRequest);
get(): Promise<{
board: LeaderboardInfo;
}>;
getEntryCount(): Promise<number>;
list(query?: LeaderboardQuery): Promise<LeaderboardResult>;
aroundMe(options?: {
before?: number;
after?: number;
}): Promise<LeaderboardResult>;
getMyEntry(): Promise<LeaderboardEntry>;
submit(input: ScoreSubmission): Promise<ScoreResult>;
}
export declare class ServerLeaderboard extends Leaderboard {
submitFor(username: string, input: ScoreSubmission): Promise<ScoreResult>;
queryFor(username: string, query?: LeaderboardQuery): Promise<LeaderboardResult>;
update(definition: Omit<LeaderboardDefinition, "name">): Promise<{
board: LeaderboardInfo;
}>;
reset(): Promise<{
success: true;
}>;
deleteEntry(username: string): Promise<{
success: true;
}>;
delete(): Promise<{
success: true;
}>;
}
export declare function createLeaderboards(request?: GameServiceRequest): Readonly<{
board: (name: string) => Leaderboard;
find(name: string): Promise<Leaderboard | null>;
findOrCreate(definition: Pick<LeaderboardDefinition, "name" | "sort" | "display">): Promise<Leaderboard>;
list: (offset?: number) => Promise<{
boards: LeaderboardInfo[];
nextOffset: number | null;
}>;
}>;
export declare function createServerLeaderboards(request: GameServiceRequest): Readonly<{
board: (name: string) => ServerLeaderboard;
find(name: string): Promise<ServerLeaderboard | null>;
findOrCreate(definition: LeaderboardDefinition): Promise<ServerLeaderboard>;
define: (definition: LeaderboardDefinition) => Promise<{
board: LeaderboardInfo;
}>;
list: (offset?: number) => Promise<{
boards: LeaderboardInfo[];
nextOffset: number | null;
}>;
}>;
export declare const leaderboards: Readonly<{
board: (name: string) => Leaderboard;
find(name: string): Promise<Leaderboard | null>;
findOrCreate(definition: Pick<LeaderboardDefinition, "name" | "sort" | "display">): Promise<Leaderboard>;
list: (offset?: number) => Promise<{
boards: LeaderboardInfo[];
nextOffset: number | null;
}>;
}>;
Supporting internal type declarations
These clarify types referenced by the generated signatures; do not import these internal paths directly.
game-services.d.ts
export declare class GameServiceError extends Error {
readonly status: number;
readonly code: string;
constructor(message: string, status?: number, code?: string);
}
export type GameServiceRequest = <T>(service: string, request: Record<string, unknown>) => Promise<T>;
export declare const requestGameService: GameServiceRequest;
/** Server-only adapter. Credentials must never be bundled into browser games. */
export declare function createGameServiceRequest(options: {
baseUrl: string;
token: string;
fetch?: typeof fetch;
}): GameServiceRequest;
protocol.d.ts
export declare const SDK_SOURCE: "inkwell-sdk";
export declare const SDK_VERSION: 1;
export type InkwellMessageType = "ready" | "loading.progress" | "loading.error" | "session.complete" | "analytics.track" | "assets.progress" | "player.get" | "presence.get" | "performance.sample" | "backend.connect" | "backend.fetch";
export type InkwellMessage = {
source: typeof SDK_SOURCE;
version: typeof SDK_VERSION;
type: InkwellMessageType;
payload?: Record<string, unknown>;
sentAt: number;
};
export declare function parentOrigin(): string | null;
export declare function requestId(): string;
export declare function emit(type: InkwellMessageType, payload?: Record<string, unknown>): boolean;