@quo-systems/quo 0.2.1 → 0.2.3

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.
package/SPEC.md CHANGED
@@ -851,10 +851,14 @@ One ward is one runtime and one language, and every being in it shares both.
851
851
  A harbor that wants two languages starts two wards at least. Under
852
852
  `src/being/`, `src/ward/`, `src/harbor/` and `src/conformance/` no runtime is
853
853
  named. The whole
854
- platform surface is the language plus six globals -- `crypto`, `TextEncoder`,
855
- `TextDecoder`, `structuredClone`, `setTimeout`, `atob` -- and that list is a
856
- promise, not an accident: `test/terrain.test.ts` fails the build both when a
857
- file names a platform and when it reaches for a global outside the list.
854
+ platform surface is the language plus ten globals. Six are the ward's own:
855
+ `crypto`, `TextEncoder`, `TextDecoder`, `structuredClone`, `setTimeout` and
856
+ `atob`. Four more came with the harbor, and are the whole of what a reach
857
+ costs: `fetch` and `WebSocket`, the two kinds of reach; `DataView`, the frame
858
+ id on a socket; and `clearTimeout`, the dialer's reconnect called off. That
859
+ list is a promise, not an accident: `test/terrain.test.ts` fails the build
860
+ both when a file names a platform and when it reaches for a global outside
861
+ the list, and when the list names one the tree has stopped using.
858
862
 
859
863
  The package exports raw TypeScript, extension and all, on every specifier, so
860
864
  Node loads it directly and every other terrain reaches a ward through a
@@ -891,7 +895,8 @@ partition
891
895
  bind key -> her bind table
892
896
  standings id -> { ward, heir | null, current, next, seq } her keys for a standing
893
897
  occupants id -> heir pk
894
- knocks <ward>:<heir> | public:<ward> -> { current, next, spoke, seq } before take
898
+ knocks <ward>:<heir> | public:<ward> -> { current, next, spoke, sent, seq } before take
899
+ spoke: bytes came back once. sent: bytes went out once, answered or not
895
900
  answered <ward>:<heir> | public:<ward> -> true knocked and answered
896
901
  minted the last eight pks her side minted
897
902
  heirs heir pk -> { being, id, current, announced, fresh, mark, spent } the door's view of every occupant
@@ -1185,8 +1190,7 @@ way waits out the ceiling before asking again, because a suite does not
1185
1190
  become speakable by asking sooner. Its wait returns to the first second
1186
1191
  where the far side announced and was taken, and not where the line merely
1187
1192
  opened: a listener that opens and then refuses would otherwise be dialed at
1188
- a fixed two seconds for good, which is what the lab measured before the
1189
- code was read. Absent is this suite,
1193
+ a fixed two seconds for good. Absent is this suite,
1190
1194
  because a caller older than the header is this one. Present and different is
1191
1195
  refused as it is written: the number is compared as it was sent, so a suite
1192
1196
  is one spelling and not a family of them.
@@ -1234,7 +1238,12 @@ is reachable through it without waiting for that line to fall; the listener's
1234
1238
  bound, dialed again
1235
1239
  with a wait that doubles from a second to thirty when the line drops, and
1236
1240
  while it is dialed it is one of the harbor's fallbacks, where a pk nobody
1237
- here knows is sent. Fallbacks are a list and a pk is tried down it in
1241
+ here knows is sent. A device that slept, a phone in a pocket, comes back
1242
+ with that wait frozen and, often, its socket closed under it by the system
1243
+ without a word, so the dialer takes one call from the device, `wake`: a
1244
+ line in hand is made to announce, and a dead one closes under the word and
1245
+ is dialed again; a line that is down is dialed now, the wait called off; a
1246
+ dial in flight is left alone. Fallbacks are a list and a pk is tried down it in
1238
1247
  order: a harbor may dial more than one listener, and a rendezvous is a
1239
1248
  listener and nothing more, so a ward is never reachable through one place
1240
1249
  by anything but its own choice. A line that drops takes only its own place
@@ -1436,8 +1445,8 @@ alone, one JavaScript file and one declaration file per source file with
1436
1445
  every relative import rewritten, and the exports map points there, types
1437
1446
  beside default. The
1438
1447
  build runs before every gate and every publish and is never tracked;
1439
- nothing under `test/` or `dock/` imports it except through the package
1440
- name, which is how a consumer does. `test/package.test.ts` is the one
1448
+ nothing in this repository imports it except through the package name,
1449
+ which is how a consumer does. `test/package.test.ts` is the one
1441
1450
  suite that meets the package as a stranger: it packs the tarball,
1442
1451
  installs it into an empty folder, and imports every entry point under
1443
1452
  plain Node. `npm pack --dry-run` shows what ships: `dist/`, the four
@@ -1456,11 +1465,6 @@ test/ the suites.
1456
1465
  vectors/ fixed inputs and outputs: the arithmetic, Quo's own framing, the frames on the wire.
1457
1466
  ```
1458
1467
 
1459
- `dock/` sits beside `src` and is not Quo: the beings, screens, model sides
1460
- and real harbors built on it, each folder with its own document. This
1461
- document does not read them, and they may not add a word to it. Its one
1462
- claim on them is that every harbor there passes `src/conformance/` untouched.
1463
-
1464
1468
  The hand to a kit in another language is two things, and they are of two
1465
1469
  kinds. `vectors/` is the byte-level hand: fixed inputs and outputs for
1466
1470
  everything a stranger can observe, the arithmetic, the ward pk, the digest,
@@ -3,6 +3,7 @@ import { Socket } from './reach.ts';
3
3
  export type Dialer = {
4
4
  url: string;
5
5
  socket: Socket | null;
6
+ wake(): void;
6
7
  close(): void;
7
8
  };
8
9
  export declare function dial(harbor: Harbor, url: string): Dialer;
@@ -1,8 +1,9 @@
1
1
  import { REFUSED, Socket } from './reach.js';
2
2
  export function dial(harbor, url) {
3
- const d = { url, socket: null, close: () => { } };
3
+ const d = { url, socket: null, wake: () => { }, close: () => { } };
4
4
  let stopped = false, wait = 1000, timer;
5
5
  const connect = () => {
6
+ timer = undefined; // no wait pending: this is the dial it was waiting for
6
7
  if (stopped)
7
8
  return;
8
9
  const line = new WebSocket(url.replace(/\/$/, '').replace(/^http/, 'ws'));
@@ -41,6 +42,18 @@ export function dial(harbor, url) {
41
42
  say();
42
43
  });
43
44
  };
45
+ d.wake = () => {
46
+ if (stopped)
47
+ return;
48
+ if (d.socket)
49
+ return d.socket.announce([...harbor.doors.keys()]);
50
+ if (timer === undefined)
51
+ return;
52
+ clearTimeout(timer);
53
+ timer = undefined;
54
+ wait = 1000;
55
+ connect();
56
+ };
44
57
  d.close = () => {
45
58
  stopped = true;
46
59
  clearTimeout(timer);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quo-systems/quo",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "description": "Quo: an object asks another object and gets an answer, without knowing where it is. Being, Ward, Harbor.",
5
5
  "keywords": [
6
6
  "quo",
@@ -11,14 +11,21 @@
11
11
  import type { Harbor } from './core.ts';
12
12
  import { REFUSED, Socket, type Line } from './reach.ts';
13
13
 
14
- export type Dialer = { url: string; socket: Socket | null; close(): void };
14
+ // `wake` is the device saying it is back: a phone out of a pocket, a
15
+ // laptop's lid opened. A device that slept comes back with its timer
16
+ // frozen and, often, its socket closed under it by the system without a
17
+ // word. So a line in hand is made to speak, an announce, and a dead one
18
+ // closes under the word and is dialed again; a line that is down is dialed
19
+ // now instead of waiting out the backoff; a dial in flight is left alone.
20
+ export type Dialer = { url: string; socket: Socket | null; wake(): void; close(): void };
15
21
 
16
22
  export function dial(harbor: Harbor, url: string): Dialer {
17
- const d: Dialer = { url, socket: null, close: () => {} };
23
+ const d: Dialer = { url, socket: null, wake: () => {}, close: () => {} };
18
24
  let stopped = false,
19
25
  wait = 1000,
20
26
  timer: ReturnType<typeof setTimeout> | undefined;
21
27
  const connect = () => {
28
+ timer = undefined; // no wait pending: this is the dial it was waiting for
22
29
  if (stopped) return;
23
30
  const line = new WebSocket(url.replace(/\/$/, '').replace(/^http/, 'ws')) as unknown as Line;
24
31
  const s: Socket = new Socket(
@@ -57,6 +64,15 @@ export function dial(harbor: Harbor, url: string): Dialer {
57
64
  say();
58
65
  });
59
66
  };
67
+ d.wake = () => {
68
+ if (stopped) return;
69
+ if (d.socket) return d.socket.announce([...harbor.doors.keys()]);
70
+ if (timer === undefined) return;
71
+ clearTimeout(timer);
72
+ timer = undefined;
73
+ wait = 1000;
74
+ connect();
75
+ };
60
76
  d.close = () => {
61
77
  stopped = true;
62
78
  clearTimeout(timer);