@arcadible/sdk 1.1.0 → 1.2.0

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.
@@ -1,8 +1,9 @@
1
1
  // Saves, the page's side: it answers a game's saves requests from its
2
2
  // backend, enforces the limits, and stamps each save with the game's
3
- // version. Its first message on each channel is the game's saves.
3
+ // version. Its first message on each channel is the game's saves, and who
4
+ // can read them back.
4
5
  // [import]
5
- import { ArcadibleError, Codes, utf8Size } from "../bus/protocol.js";
6
+ import { ArcadibleError, Codes, log, utf8Size } from "../bus/protocol.js";
6
7
  import { checkName, checkWrite, } from "./rules.js";
7
8
  // [function]
8
9
  function toSave(record) {
@@ -23,6 +24,11 @@ function nameOf(params) {
23
24
  return params["name"];
24
25
  }
25
26
  // [function]
27
+ // what a write or remove is about, so they keep their order (bus/server.ts).
28
+ function saveKey(params) {
29
+ return String(params["name"]);
30
+ }
31
+ // [function]
26
32
  // the device is out of room: retrying won't help until the player frees
27
33
  // some. Anything else is the bus's `unavailable`.
28
34
  function storageError(err) {
@@ -33,7 +39,7 @@ function storageError(err) {
33
39
  }
34
40
  // [function]
35
41
  export function savesServer(options) {
36
- const { backend, now, scope, version } = options;
42
+ const { backend, now, scope, version, where } = options;
37
43
  const source = sourceId();
38
44
  // a write, checked against the game's saves in the same step as it's kept.
39
45
  const write = async function (params) {
@@ -57,11 +63,18 @@ export function savesServer(options) {
57
63
  return change?.record ? toSave(change.record).info : null;
58
64
  };
59
65
  const load = async function () {
66
+ // when the saves were last opened is bookkeeping: a device too full to
67
+ // keep it still loads them.
60
68
  const [list] = await Promise.all([
61
69
  backend.list(scope),
62
- backend.touch(scope, now().toISOString()),
70
+ backend.touch(scope, now().toISOString()).catch((err) => {
71
+ log("warn", "the saves' last use couldn't be kept.", err);
72
+ }),
63
73
  ]);
64
- return { status: backend.status(), items: list.map(toSave) };
74
+ return {
75
+ where: backend.status() === "memory" ? "memory" : where,
76
+ items: list.map(toSave),
77
+ };
65
78
  };
66
79
  return (context) => {
67
80
  // another tab (later, another device) changed a save: tell the game,
@@ -89,11 +102,18 @@ export function savesServer(options) {
89
102
  "saves.list": {
90
103
  run: async () => (await backend.list(scope)).map((record) => record.name).sort(),
91
104
  },
92
- "saves.write": { run: write, coalesce: (p) => String(p["name"]) },
105
+ "saves.write": { run: write, key: saveKey, coalesce: true },
93
106
  // the removal's revision, or null when there was nothing to remove.
94
107
  "saves.remove": {
108
+ key: saveKey,
95
109
  run: async (params) => {
96
- const change = await backend.change(scope, nameOf(params), () => null, source);
110
+ // a removal writes too (the game's change counter), so a full
111
+ // device refuses it the same way.
112
+ const change = await backend
113
+ .change(scope, nameOf(params), () => null, source)
114
+ .catch((err) => {
115
+ throw storageError(err);
116
+ });
97
117
  return change?.revision ?? null;
98
118
  },
99
119
  },
@@ -103,15 +123,11 @@ export function savesServer(options) {
103
123
  send("saves.load", await load());
104
124
  }
105
125
  catch (err) {
106
- console.error("arcadible: the game's saves couldn't load:", err);
126
+ log("warn", "the game's saves couldn't load.", err);
107
127
  const error = err instanceof ArcadibleError
108
128
  ? err.toJSON()
109
129
  : { code: Codes.Unavailable, message: "Saves couldn't load." };
110
- send("saves.load", {
111
- status: "ephemeral",
112
- items: [],
113
- error,
114
- });
130
+ send("saves.load", { items: [], error });
115
131
  }
116
132
  },
117
133
  close: unsubscribe,
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "1.1.0";
1
+ export declare const VERSION = "1.2.0";
package/dist/version.js CHANGED
@@ -1,3 +1,3 @@
1
1
  // The client's version, sent in its hello and shown as `arcadible.version`,
2
2
  // for bug reports. It matches package.json (test/unit/protocol.test.ts).
3
- export const VERSION = "1.1.0";
3
+ export const VERSION = "1.2.0";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "author": "Offst, Inc.",
3
- "description": "The Arcadible SDK: how a game talks to Arcadible, over a bus between the game and the play page, starting with saves that survive updates.",
3
+ "description": "The Arcadible SDK: saves that carry over between a game's versions on Arcadible.",
4
4
  "devDependencies": {
5
5
  "@playwright/test": "1.63.0",
6
6
  "@types/node": "^25.0.3",
@@ -43,5 +43,5 @@
43
43
  ],
44
44
  "type": "module",
45
45
  "types": "./dist/index.d.ts",
46
- "version": "1.1.0"
46
+ "version": "1.2.0"
47
47
  }