Arcadible SDK
Each build of a game on Arcadible has its own origin, so its browser storage starts empty with every update. Saves made through the Arcadible SDK are kept by the play page instead, on the player's device, so they carry over. The SDK is optional, and saves are all it does.
Install
npm install @arcadible/sdk
Use the package in a game with a build step, such as a Vite project. It also exports ArcadibleError, Codes, and the TypeScript types.
A game without a build step includes the hosted script instead, which Arcadible serves from every build's own origin, as arc serve does locally. Add it as a plain <script> tag, without async, defer, or type="module", before your own scripts, so the global arcadible exists when they run:
<script src="/arcadible/sdk/v1.js"></script>
<script type="module" src="./main.js"></script>
- Under another server, the hosted script's path isn't found, and
window.arcadibleisundefined. The package works anywhere. - A page has one
arcadibleobject: a game that includes both shares it. The hosted script is always the latest version ofv1; the package is the version you installed. Both work with every play page.
Save and load
import { arcadible } from "@arcadible/sdk";
// at startup: once the saves have loaded, the player's progress, or a new game.
await arcadible.ready;
const saved = await arcadible.saves.read("progress");
const progress = saved ? JSON.parse(saved) : { level: 1 };
// at a checkpoint:
await arcadible.saves.write("progress", JSON.stringify(progress));
A save is a name holding one string. arcadible.ready settles once the game's saves have loaded, and never fails; calls made before it wait for it, and from then on readSync, listSync, and infoSync answer at once from memory, for reads during play. Every call that fails rejects (or, for the sync calls, throws) with an ArcadibleError, whose code says what to do. arcadible.saves.where says who can read the saves back: every version of the game, only this build, or only until the page closes.
Off Arcadible, such as on your dev server, the package works on its own, with the same rules and limits: saves are kept on the page's own origin, arcadible.saves.where is "build", and arcadible.build is null. How to use saves well, across versions and tabs, is in Saves.
Modules
| Module | Description |
|---|---|
arcadible.saves | Write, read, list, and remove the game's saves, and where they're kept |
arcadible
interface Arcadible {
readonly ready: Promise<{ build: Build | null }>;
readonly build: Build | null | undefined;
readonly version: string;
readonly saves: Saves;
}
type Build = { version: string; channel: string };
| Property | Value |
|---|---|
arcadible.ready | Settles once, when the play page has answered and the game's saves have loaded, or after 10 seconds if they haven't. It never rejects, and resolves with build, and only that. |
arcadible.build | Which build is running, once ready has settled: information, for comparing with a save's version. null when nobody says, such as off Arcadible, and undefined before ready. |
arcadible.version | The SDK's own version, for bug reports. |
arcadible.saves | The game's saves, and who can read them back. See arcadible.saves. |
const { build } = await arcadible.ready;
// { version: "1.2.0", channel: "production" } on Arcadible, null off it
build.versionis the version you deployed, fromarcadible.tomlorpackage.json.build.channelisproductionorstaging, andlocalunderarc serve. It's a string, and other values may be added.- Standing alone, off Arcadible and outside
arc serve,readydoesn't wait for a play page on a page that isn't in a frame, and waits about a second in one that no play page answers. See Locally. - What the SDK logs starts with
Arcadible SDK:, as a warning when saves won't be kept as they should (they're late, in memory, or the game stands alone in a frame), and as an error only for a bug.
Codes
Every call that fails rejects, or throws, with an ArcadibleError. Act on its code, which the package also exports as Codes (Codes.Full is "full"). Its message is for people, and can change.
class ArcadibleError extends Error {
readonly code: Code; // one of the codes below
}
try {
await arcadible.saves.write("progress", JSON.stringify(progress));
} catch (err) {
if (err.code === "full") showStorageFullMessage();
else if (!["invalid", "too_large", "too_many"].includes(err.code)) {
retryLater();
}
}
| Code | Means | Retry | What to do |
|---|---|---|---|
invalid | A name or a save that breaks the rules | No | Fix the name, or serialize the save to a well-formed string |
too_many | A new save past the most a game can keep | No | Remove a save, or combine saves |
too_large | The game's saves would be larger than they can be together | No | Save less |
full | The device has no room left | No | Tell the player. It works again once they free space |
busy | Too many calls waiting at once | Yes | Wait for some to finish |
timeout | No answer within 10 seconds. A write may still have been kept | Yes | Try again |
unavailable | The saves can't be reached right now | Yes | Try again |
not_ready | A sync call before ready | No | Wait for arcadible.ready |
unsupported | A call the play page doesn't know | No | Carry on without it |
New codes may be added. Treat a code you don't know as unavailable, which the example does by retrying any code that isn't final for a write.