@phreshos/client 0.1.51 → 0.1.52

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.
@@ -0,0 +1,3 @@
1
+ import type { ClientMemory, HandleAddress } from "@phreshos/core";
2
+ /** The System, not this browser document, owns the values and ordering. */
3
+ export default function clientMemory(target: HandleAddress | null): ClientMemory;
@@ -0,0 +1,57 @@
1
+ import wire from "./wire.js";
2
+ /** The System, not this browser document, owns the values and ordering. */
3
+ export default function clientMemory(target) {
4
+ const snapshots = new Map();
5
+ const address = () => target ? Promise.resolve(target) : wire.identity().then(({ process, reference }) => ({ identity: process, reference }));
6
+ const ask = async (operation, key, value, expected) => {
7
+ const [result] = await wire.request(["client-memory", await address(), operation, key, value, expected]);
8
+ return result;
9
+ };
10
+ return {
11
+ async get(key) {
12
+ const snapshot = await ask("snapshot", key);
13
+ snapshots.set(key, snapshot);
14
+ return snapshot.value;
15
+ },
16
+ async set(key, value) { snapshots.set(key, await ask("set", key, value)); },
17
+ async update(key, updater) {
18
+ let snapshot = snapshots.get(key) ?? await ask("snapshot", key);
19
+ for (;;) {
20
+ const next = updater(snapshot.value);
21
+ const result = await ask("compareAndSet", key, next, snapshot);
22
+ snapshots.set(key, result.snapshot);
23
+ if (result.changed)
24
+ return result.snapshot.value;
25
+ if (result.snapshot.run !== snapshot.run)
26
+ throw new Error("The Client run changed during the update");
27
+ snapshot = result.snapshot;
28
+ }
29
+ },
30
+ async delete(key) { const deleted = await ask("delete", key); snapshots.delete(key); return deleted; },
31
+ async entries() { return await ask("entries"); },
32
+ subscribe(key, subscriber) {
33
+ let active = true;
34
+ let stop;
35
+ let latest;
36
+ void address().then(value => {
37
+ if (!active)
38
+ return;
39
+ // Register first; an older snapshot response cannot overtake a newer event.
40
+ stop = wire.on("host-client-memory", key, (identity, snapshot) => {
41
+ if (identity !== value.identity || !active)
42
+ return;
43
+ deliver(snapshot);
44
+ }, value.identity);
45
+ void ask("snapshot", key).then(snapshot => deliver(snapshot)).catch(() => undefined);
46
+ }).catch(() => undefined);
47
+ const deliver = (snapshot) => {
48
+ if (!active || (latest && (latest.run !== snapshot.run || latest.revision > snapshot.revision)))
49
+ return;
50
+ latest = snapshot;
51
+ snapshots.set(key, snapshot);
52
+ subscriber(snapshot.value);
53
+ };
54
+ return () => { active = false; stop?.(); };
55
+ }
56
+ };
57
+ }
package/dist/context.js CHANGED
@@ -2,6 +2,7 @@ import Deadline from "./deadline.js";
2
2
  import { ClientEndpoint, ServerEndpoint, ServerTrafficHandle, TrafficHandle, endpointLifecycle, endpointEvents, process, program, visibleEndpoint, presentation, window as windowHandle, } from "./domain.js";
3
3
  import Events from "./events.js";
4
4
  import wire from "./wire.js";
5
+ import clientMemory from "./client-memory.js";
5
6
  import { contextPermissions } from "./permissions.js";
6
7
  class ContextServerHandle extends ServerEndpoint {
7
8
  owner;
@@ -68,6 +69,7 @@ class ContextClientHandle extends ClientEndpoint {
68
69
  traffic = new TrafficHandle(null, "client");
69
70
  lifecycle = endpointLifecycle(currentAddress, "client");
70
71
  window = windowHandle(currentAddress);
72
+ memory = clientMemory(null);
71
73
  constructor(owner) {
72
74
  super();
73
75
  this.owner = owner;
@@ -95,6 +97,7 @@ contextClient = new ContextClientHandle(owner);
95
97
  class ClientContext extends Events {
96
98
  server = contextServer;
97
99
  window = contextClient.window;
100
+ memory = contextClient.memory;
98
101
  presentation = presentation(currentAddress);
99
102
  permissions = contextPermissions();
100
103
  constructor() {
package/dist/domain.js CHANGED
@@ -6,6 +6,7 @@ import { area, programLogs, sql, store } from "./storage.js";
6
6
  import startup from "./startup.js";
7
7
  import { programPermissions } from "./permissions.js";
8
8
  import wire from "./wire.js";
9
+ import clientMemory from "./client-memory.js";
9
10
  const handles = new HandleRegistry();
10
11
  class ProgramHandle extends CoreProgram {
11
12
  subscribe;
@@ -79,10 +80,10 @@ class ProgramHandle extends CoreProgram {
79
80
  const answer = await wire.request(["program-processes", this.address]);
80
81
  return answer[0].map(record => process(record));
81
82
  }
82
- async firstProcess() {
83
+ async oldestProcess() {
83
84
  return chronological(await this.processes())[0] ?? null;
84
85
  }
85
- async lastProcess() {
86
+ async newestProcess() {
86
87
  return chronological(await this.processes()).at(-1) ?? null;
87
88
  }
88
89
  async findProcess(identityOrName) {
@@ -285,12 +286,14 @@ class ClientEndpointHandle extends CoreClientEndpoint {
285
286
  traffic;
286
287
  lifecycle;
287
288
  window;
289
+ memory;
288
290
  constructor(owner) {
289
291
  super();
290
292
  this.owner = owner;
291
293
  this.traffic = new TrafficHandle(owner.address, "client");
292
294
  this.lifecycle = endpointLifecycle(() => Promise.resolve(owner.address), "client");
293
295
  this.window = window(async () => owner.address);
296
+ this.memory = clientMemory(owner.address);
294
297
  const events = endpointEvents(owner.address, "client");
295
298
  this.subscribe = events.subscribe;
296
299
  this.wait = events.wait;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@phreshos/client",
3
- "version": "0.1.51",
3
+ "version": "0.1.52",
4
4
  "description": "The SDK used by a Program's client endpoint.",
5
5
  "type": "module",
6
6
  "main": "dist/main.js",
@@ -46,13 +46,13 @@
46
46
  "test": "vitest run --project default"
47
47
  },
48
48
  "peerDependencies": {
49
- "@phreshos/core": "^0.1.60"
49
+ "@phreshos/core": "^0.1.62"
50
50
  },
51
51
  "dependencies": {
52
52
  "@the-link/messagepack": "^0.1.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@phreshos/core": "^0.1.60",
55
+ "@phreshos/core": "^0.1.62",
56
56
  "typescript": "^6.0.3",
57
57
  "vitest": "^4.1.10"
58
58
  }