@macula-io/ts 0.18.0 → 0.20.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,79 +0,0 @@
1
- import type { CallOptions, Session } from "./session.js";
2
- /** What Session.resolveDirect() resolves with: `procedure`'s
3
- * currently-advertised serving station and its dialable host/port
4
- * (macula-go's `directdial.Resolve`). */
5
- export interface DirectDialTarget {
6
- /** Hex-encoded, 32 bytes: the resolved station's NodeID (Ed25519
7
- * public key) -- the SAME identity Session.callDirect()/
8
- * callDirectWithUcan() pin the one-hop dial against internally before
9
- * trusting it. */
10
- readonly station: string;
11
- readonly host: string;
12
- readonly port: number;
13
- }
14
- /** Options for Session.advertiseDirect(). */
15
- export interface AdvertiseDirectOptions {
16
- /** Same 64-character hex realm convention as CallOptions.realm --
17
- * MUST match whatever realm resolveDirect()/callDirect()/
18
- * callDirectWithUcan() (or the Erlang/Rust/Go equivalent) resolve
19
- * under, or the two sides derive a different discovery URI and resolve
20
- * comes back exactly as if this was never called at all (see
21
- * directdial.go's own DiscoveryURI note). Omitted means the all-zero
22
- * realm, this SDK's sole default before this option existed. */
23
- realm?: string;
24
- /** Milliseconds. Defaults to DHT_DEFAULT_TTL_MS (48h) -- matches
25
- * macula-go's own dht.DefaultTTL, applied Go-side for ttlMs<=0 (not
26
- * duplicated as a second default here; this SDK's default is threaded
27
- * through explicitly instead, matching putProcedureAdvertisement's own
28
- * convention). */
29
- ttlMs?: number;
30
- }
31
- /** How long keepAdvertisedDirect() waits between re-advertise ticks, in
32
- * milliseconds, when opts.intervalMs is left unset. This is a real
33
- * production margin against AdvertiseDirectOptions' own 48h default TTL
34
- * actually expiring between ticks -- not chosen to match macula-go's own
35
- * KeepAdvertisedDirect live-test interval (1s there, only to keep that
36
- * particular test fast). A caller passing a much shorter `ttlMs` should
37
- * pass a correspondingly shorter `intervalMs` too; this constant does not
38
- * scale itself to `opts.ttlMs`. */
39
- export declare const KEEP_ADVERTISED_DIRECT_INTERVAL_MS: number;
40
- /** Options for keepAdvertisedDirect(). */
41
- export interface KeepAdvertisedDirectOptions extends AdvertiseDirectOptions {
42
- /** Milliseconds between re-advertise ticks. Defaults to
43
- * KEEP_ADVERTISED_DIRECT_INTERVAL_MS. */
44
- intervalMs?: number;
45
- /** Called with a tick's own thrown error when a re-advertise tick
46
- * fails -- a network blip, a genuinely dead session, etc. Matches
47
- * macula-go's own KeepAdvertisedDirect: a failed tick is reported, not
48
- * fatal -- this loop tries again at the next interval regardless, and
49
- * cannot detect or repair a dead Session on its own (a separate, larger
50
- * concern this does not attempt to solve). Omit to drop the error
51
- * silently. */
52
- onError?: (err: unknown) => void;
53
- }
54
- /** Re-advertises `procedure` as direct-dial-reachable on `session` (via
55
- * `session.advertiseDirect()`) immediately, then again every
56
- * `opts.intervalMs`, until the returned `stop()` is called -- macula-go's
57
- * own `KeepAdvertisedDirect` free function, ported here as a standalone
58
- * helper rather than a Session method for the identical reason
59
- * macula-go's own is a free function taking a `*connection.Session`
60
- * rather than a method on one: a station's registration for a procedure
61
- * does not survive the connection that sent it being replaced, so a
62
- * long-lived provider needs to call `AdvertiseDirect` again on its own
63
- * schedule, and it is this function's CALLER's job to decide WHICH
64
- * Session that runs on. See `Session.advertiseDirect()`'s own doc for why
65
- * that must NOT be a Session with an active `serve()` on it
66
- * (`advertiseDirect()`'s own `PutRecord` CALL would race `serve()`'s own
67
- * reads of the same shared control stream): a long-lived provider that
68
- * also serves `procedure` needs a SEPARATE Session (and identity -- this
69
- * fleet enforces one connection per identity, kicking whichever connects
70
- * second) for that, passed here instead of the serving Session.
71
- *
72
- * The returned `stop()` is synchronous -- unlike `Session.serve()`'s own
73
- * async `stop()`, there is no pending tick to wait out and no unadvertise
74
- * step: `advertiseDirect()`'s own DHT record simply expires on its own
75
- * TTL once ticks stop, matching macula-go's own `KeepAdvertisedDirect`,
76
- * which has no corresponding "undo" either. Calling `stop()` more than
77
- * once is a no-op. */
78
- export declare function keepAdvertisedDirect(session: Session, procedure: string, opts?: KeepAdvertisedDirectOptions): () => void;
79
- export type { CallOptions };
@@ -1,76 +0,0 @@
1
- // Direct-dial: caller-side resolve+one-hop-call and provider-side
2
- // advertise-direct, built on macula-go's directdial package (see
3
- // cabi/directdial.go's own doc for the trust model -- every candidate
4
- // procedure_advertisement must carry a valid signature before its
5
- // serving_station is trusted at all, the resolved station_endpoint must
6
- // be signed by the station itself, and after the one-hop dial -- which
7
- // trusts neither the TLS certificate nor nothing -- the freshly connected
8
- // peer's own HELLO-proven identity is checked against the exact pubkey
9
- // the signed DHT chain resolved, application-layer pinning instead of
10
- // relying on the dial's own TLS -- and for why AdvertiseDirect publishes
11
- // BOTH a plain ADVERTISE and a signed procedure_advertisement DHT record:
12
- // skipping the plain ADVERTISE lets resolve+dial complete cleanly against
13
- // a station with nothing registered to route the CALL to, a real bug
14
- // macula-go fixed live 2026-08-30). The actual FFI plumbing lives on
15
- // Session (session.ts's resolveDirect/callDirect/callDirectWithUcan/
16
- // advertiseDirect), matching this SDK's own call()/serve() split; this
17
- // file holds the shapes those share, plus keepAdvertisedDirect -- a
18
- // standalone helper mirroring macula-go's own free-function
19
- // KeepAdvertisedDirect, not a Session method (see its own doc for why).
20
- /** How long keepAdvertisedDirect() waits between re-advertise ticks, in
21
- * milliseconds, when opts.intervalMs is left unset. This is a real
22
- * production margin against AdvertiseDirectOptions' own 48h default TTL
23
- * actually expiring between ticks -- not chosen to match macula-go's own
24
- * KeepAdvertisedDirect live-test interval (1s there, only to keep that
25
- * particular test fast). A caller passing a much shorter `ttlMs` should
26
- * pass a correspondingly shorter `intervalMs` too; this constant does not
27
- * scale itself to `opts.ttlMs`. */
28
- export const KEEP_ADVERTISED_DIRECT_INTERVAL_MS = 15 * 60 * 1000;
29
- /** Re-advertises `procedure` as direct-dial-reachable on `session` (via
30
- * `session.advertiseDirect()`) immediately, then again every
31
- * `opts.intervalMs`, until the returned `stop()` is called -- macula-go's
32
- * own `KeepAdvertisedDirect` free function, ported here as a standalone
33
- * helper rather than a Session method for the identical reason
34
- * macula-go's own is a free function taking a `*connection.Session`
35
- * rather than a method on one: a station's registration for a procedure
36
- * does not survive the connection that sent it being replaced, so a
37
- * long-lived provider needs to call `AdvertiseDirect` again on its own
38
- * schedule, and it is this function's CALLER's job to decide WHICH
39
- * Session that runs on. See `Session.advertiseDirect()`'s own doc for why
40
- * that must NOT be a Session with an active `serve()` on it
41
- * (`advertiseDirect()`'s own `PutRecord` CALL would race `serve()`'s own
42
- * reads of the same shared control stream): a long-lived provider that
43
- * also serves `procedure` needs a SEPARATE Session (and identity -- this
44
- * fleet enforces one connection per identity, kicking whichever connects
45
- * second) for that, passed here instead of the serving Session.
46
- *
47
- * The returned `stop()` is synchronous -- unlike `Session.serve()`'s own
48
- * async `stop()`, there is no pending tick to wait out and no unadvertise
49
- * step: `advertiseDirect()`'s own DHT record simply expires on its own
50
- * TTL once ticks stop, matching macula-go's own `KeepAdvertisedDirect`,
51
- * which has no corresponding "undo" either. Calling `stop()` more than
52
- * once is a no-op. */
53
- export function keepAdvertisedDirect(session, procedure, opts = {}) {
54
- const intervalMs = opts.intervalMs ?? KEEP_ADVERTISED_DIRECT_INTERVAL_MS;
55
- let stopped = false;
56
- const tick = () => {
57
- session.advertiseDirect(procedure, { realm: opts.realm, ttlMs: opts.ttlMs }).catch((err) => {
58
- opts.onError?.(err);
59
- });
60
- };
61
- tick();
62
- const timer = setInterval(tick, intervalMs);
63
- // Node keeps the event loop alive for a pending timer by default --
64
- // unref() so a program that starts this loop with nothing else keeping
65
- // it running (no active serve()/subscribe()/etc. elsewhere) can still
66
- // exit on its own; a real, still-open Session doing other work keeps
67
- // the process alive on its own merits regardless, unaffected by this.
68
- timer.unref?.();
69
- return () => {
70
- if (stopped)
71
- return;
72
- stopped = true;
73
- clearInterval(timer);
74
- };
75
- }
76
- //# sourceMappingURL=directdial.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"directdial.js","sourceRoot":"","sources":["../src/directdial.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,iEAAiE;AACjE,sEAAsE;AACtE,kEAAkE;AAClE,wEAAwE;AACxE,uEAAuE;AACvE,0EAA0E;AAC1E,uEAAuE;AACvE,sEAAsE;AACtE,yEAAyE;AACzE,0EAA0E;AAC1E,0EAA0E;AAC1E,qEAAqE;AACrE,qEAAqE;AACrE,qEAAqE;AACrE,uEAAuE;AACvE,oEAAoE;AACpE,4DAA4D;AAC5D,wEAAwE;AAmCxE;;;;;;;mCAOmC;AACnC,MAAM,CAAC,MAAM,kCAAkC,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAiBjE;;;;;;;;;;;;;;;;;;;;;;;sBAuBsB;AACtB,MAAM,UAAU,oBAAoB,CAAC,OAAgB,EAAE,SAAiB,EAAE,IAAI,GAAgC,EAAE;IAC9G,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,IAAI,kCAAkC,CAAC;IACzE,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,OAAO,CAAC,eAAe,CAAC,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YAClG,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,IAAI,EAAE,CAAC;IACP,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC5C,oEAAoE;IACpE,uEAAuE;IACvE,sEAAsE;IACtE,qEAAqE;IACrE,sEAAsE;IACtE,KAAK,CAAC,KAAK,EAAE,EAAE,CAAC;IAEhB,OAAO,GAAS,EAAE;QAChB,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,aAAa,CAAC,KAAK,CAAC,CAAC;IACvB,CAAC,CAAC;AACJ,CAAC"}
@@ -1,43 +0,0 @@
1
- import { type Handle } from "./binding.js";
2
- export declare class Identity {
3
- #private;
4
- private constructor();
5
- /** Mints a fresh identity, grinding an Ed25519 keypair until its
6
- * NodeID's SHA-256 has the required S/Kademlia puzzle difficulty
7
- * (macula-go's DefaultPuzzleDifficulty = 8 leading zero bits). This
8
- * is real work done on the Go side -- not instant, not mocked. */
9
- static generate(): Identity;
10
- /** Reconstructs an identity from a previously-saved 32-byte Ed25519
11
- * seed. Deterministic: does not re-grind the puzzle (a seed that
12
- * already satisfied it at generation time still does). */
13
- static fromSeedBytes(seed32: Uint8Array): Identity;
14
- /** The 32-byte Ed25519 public key this identity is known by on the
15
- * wire (CONNECT/HELLO's node_id field). */
16
- get nodeId(): Uint8Array;
17
- /** The 32-byte Ed25519 seed -- persist this (e.g. to a 0600 file)
18
- * to reconstruct the identity later via fromSeedBytes. Treat as a
19
- * private key: anyone with this seed can sign as this identity. */
20
- get privateSeedBytes(): Uint8Array;
21
- /** Signs data with this identity's private key (Ed25519, via
22
- * macula-go's identity.KeyPair.Sign -- a direct ed25519.Sign wrapper)
23
- * and returns the raw 64-byte signature. This is a generic signing
24
- * primitive: no application-specific message format is baked in
25
- * here or on the Go side -- data is signed exactly as given, byte
26
- * for byte. A caller that needs a particular byte-layout convention
27
- * (e.g. an ownership-proof format binding this signature to some
28
- * other value) builds those bytes itself and passes the result in;
29
- * that convention is the caller's concern, not this method's.
30
- * Deterministic: signing the same data twice with the same identity
31
- * produces the same signature (Ed25519 has no per-signature nonce
32
- * randomness the way ECDSA does). */
33
- sign(data: Uint8Array): Uint8Array;
34
- /** Frees the Go-side handle. Safe to call more than once. */
35
- dispose(): void;
36
- /** The raw native handle, for Session.connect/close only -- they need
37
- * it to establish/close a connection under this identity. JS private
38
- * fields (#handle) are genuinely inaccessible from outside this
39
- * class body, even to other code in this package, so this method is
40
- * how Session and Identity cooperate across the FFI boundary. Not
41
- * part of the intended public API. */
42
- handleForFfi(): Handle;
43
- }
package/dist/identity.js DELETED
@@ -1,83 +0,0 @@
1
- // Public identity API -- the one real capability this walking
2
- // skeleton proves end-to-end: minting a Macula peer identity (an
3
- // Ed25519 keypair, S/Kademlia puzzle-hardened) via macula-go's own
4
- // identity.Generate(), reached through cabi/'s FFI boundary rather
5
- // than reimplemented here.
6
- //
7
- // An Identity wraps a Go-side handle. It is a disposable, freeable
8
- // resource: call dispose() when done with it (or let the process
9
- // exit -- the Go side doesn't leak across a process lifetime, but a
10
- // long-running host process minting many identities should dispose
11
- // each one). There is no finalizer/GC integration in this skeleton;
12
- // forgetting to call dispose() leaks the Go-side handle for the life
13
- // of the process, exactly as macula-php's identical handle-based
14
- // design does.
15
- import { native } from "./binding.js";
16
- export class Identity {
17
- #handle;
18
- constructor(handle) {
19
- this.#handle = handle;
20
- }
21
- /** Mints a fresh identity, grinding an Ed25519 keypair until its
22
- * NodeID's SHA-256 has the required S/Kademlia puzzle difficulty
23
- * (macula-go's DefaultPuzzleDifficulty = 8 leading zero bits). This
24
- * is real work done on the Go side -- not instant, not mocked. */
25
- static generate() {
26
- return new Identity(native.identityGenerate());
27
- }
28
- /** Reconstructs an identity from a previously-saved 32-byte Ed25519
29
- * seed. Deterministic: does not re-grind the puzzle (a seed that
30
- * already satisfied it at generation time still does). */
31
- static fromSeedBytes(seed32) {
32
- return new Identity(native.identityFromSeedBytes(seed32));
33
- }
34
- #requireHandle() {
35
- if (this.#handle === null) {
36
- throw new Error("macula-ts: Identity used after dispose()");
37
- }
38
- return this.#handle;
39
- }
40
- /** The 32-byte Ed25519 public key this identity is known by on the
41
- * wire (CONNECT/HELLO's node_id field). */
42
- get nodeId() {
43
- return native.identityNodeId(this.#requireHandle());
44
- }
45
- /** The 32-byte Ed25519 seed -- persist this (e.g. to a 0600 file)
46
- * to reconstruct the identity later via fromSeedBytes. Treat as a
47
- * private key: anyone with this seed can sign as this identity. */
48
- get privateSeedBytes() {
49
- return native.identityPrivateBytes(this.#requireHandle());
50
- }
51
- /** Signs data with this identity's private key (Ed25519, via
52
- * macula-go's identity.KeyPair.Sign -- a direct ed25519.Sign wrapper)
53
- * and returns the raw 64-byte signature. This is a generic signing
54
- * primitive: no application-specific message format is baked in
55
- * here or on the Go side -- data is signed exactly as given, byte
56
- * for byte. A caller that needs a particular byte-layout convention
57
- * (e.g. an ownership-proof format binding this signature to some
58
- * other value) builds those bytes itself and passes the result in;
59
- * that convention is the caller's concern, not this method's.
60
- * Deterministic: signing the same data twice with the same identity
61
- * produces the same signature (Ed25519 has no per-signature nonce
62
- * randomness the way ECDSA does). */
63
- sign(data) {
64
- return native.identitySign(this.#requireHandle(), data);
65
- }
66
- /** Frees the Go-side handle. Safe to call more than once. */
67
- dispose() {
68
- if (this.#handle !== null) {
69
- native.identityFree(this.#handle);
70
- this.#handle = null;
71
- }
72
- }
73
- /** The raw native handle, for Session.connect/close only -- they need
74
- * it to establish/close a connection under this identity. JS private
75
- * fields (#handle) are genuinely inaccessible from outside this
76
- * class body, even to other code in this package, so this method is
77
- * how Session and Identity cooperate across the FFI boundary. Not
78
- * part of the intended public API. */
79
- handleForFfi() {
80
- return this.#requireHandle();
81
- }
82
- }
83
- //# sourceMappingURL=identity.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"identity.js","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,8DAA8D;AAC9D,iEAAiE;AACjE,mEAAmE;AACnE,mEAAmE;AACnE,2BAA2B;AAC3B,EAAE;AACF,mEAAmE;AACnE,iEAAiE;AACjE,oEAAoE;AACpE,mEAAmE;AACnE,oEAAoE;AACpE,qEAAqE;AACrE,iEAAiE;AACjE,eAAe;AACf,OAAO,EAAE,MAAM,EAAe,MAAM,cAAc,CAAC;AAEnD,MAAM,OAAO,QAAQ;IACnB,OAAO,CAAgB;IAEvB,YAAoB,MAAc;QAChC,IAAI,CAAC,OAAO,GAAG,MAAM,CAAC;IACxB,CAAC;IAED;;;sEAGkE;IAClE,MAAM,CAAC,QAAQ;QACb,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;IACjD,CAAC;IAED;;8DAE0D;IAC1D,MAAM,CAAC,aAAa,CAAC,MAAkB;QACrC,OAAO,IAAI,QAAQ,CAAC,MAAM,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC;IAED,cAAc;QACZ,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;QAC9D,CAAC;QACD,OAAO,IAAI,CAAC,OAAO,CAAC;IACtB,CAAC;IAED;+CAC2C;IAC3C,IAAI,MAAM;QACR,OAAO,MAAM,CAAC,cAAc,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IACtD,CAAC;IAED;;uEAEmE;IACnE,IAAI,gBAAgB;QAClB,OAAO,MAAM,CAAC,oBAAoB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IAC5D,CAAC;IAED;;;;;;;;;;;yCAWqC;IACrC,IAAI,CAAC,IAAgB;QACnB,OAAO,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,cAAc,EAAE,EAAE,IAAI,CAAC,CAAC;IAC1D,CAAC;IAED,6DAA6D;IAC7D,OAAO;QACL,IAAI,IAAI,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC1B,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAClC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACtB,CAAC;IACH,CAAC;IAED;;;;;0CAKsC;IACtC,YAAY;QACV,OAAO,IAAI,CAAC,cAAc,EAAE,CAAC;IAC/B,CAAC;CACF"}
package/dist/pubsub.d.ts DELETED
@@ -1,60 +0,0 @@
1
- import type { BytesOutput, JsonValue } from "./rpc.js";
2
- /** Options for Session.publish(). */
3
- export interface PublishOptions {
4
- /** How many milliseconds from now this event should live -- a
5
- * DURATION, not a timestamp (matches every other ttlMs in this SDK,
6
- * e.g. dht.ts's DHT_DEFAULT_TTL_MS) -- PublishSpec's own `ttl_ms`
7
- * (frame/pubsub.go) is computed from this. Omitted means no TTL, not
8
- * zero or an invented default -- macula-go's Publish has no fallback
9
- * of its own for this field, unlike the DHT puts' TTL. */
10
- ttlMs?: number;
11
- /** The realm this PUBLISH is scoped to, as a 64-character hex string
12
- * (32 bytes) -- see session.ts's CallOptions.realm for the full
13
- * convention this shares. Omitted means the all-zero realm. Realm is
14
- * an exact-match routing key: a subscribe() only ever receives this
15
- * event if its own realm matches exactly, not a prefix or default
16
- * fallback. */
17
- realm?: string;
18
- }
19
- /** Options for Session.subscribe(). */
20
- export interface SubscribeOptions {
21
- /** The realm this SUBSCRIBE listens on -- see PublishOptions.realm's
22
- * own doc for the format and exact-match semantics. Omitted means the
23
- * all-zero realm. Must match the realm a publisher actually used, or
24
- * nothing published under a different realm is ever delivered here. */
25
- realm?: string;
26
- /** How bytes in each event's payload reach the handler: "hex" (the
27
- * default) or "tagged" -- see rpc.ts's BytesOutput. */
28
- bytes?: BytesOutput;
29
- /** Called at most once, only if this subscription's background
30
- * reader exits on its own -- the underlying session/connection died,
31
- * or some other transport error ended the read loop -- rather than
32
- * via the stop() subscribe() returned being called. See
33
- * Session.subscribe()'s own doc for the full story (a real bug this
34
- * SDK had and fixed: without this signal, such a subscription went
35
- * silent forever and left the Session unable to close cleanly).
36
- * Optional: even without a handler here, the subscription still
37
- * tears itself down automatically and correctly the moment this
38
- * happens -- this is purely a notification hook for a caller who
39
- * wants to know why events stopped arriving. */
40
- onClosed?: (error: Error) => void;
41
- }
42
- /** One delivered EVENT -- macula-go's frame.EventInfo, minus `Realm`
43
- * (the delivering EVENT's own realm is not surfaced back per-event here
44
- * -- a caller already knows it, since subscribe()'s own `realm` option
45
- * is what selected which realm's events reach this handler at all) and
46
- * `DeliveredVia` (a routing/telemetry detail, not part of this SDK's
47
- * scope yet). `payload`
48
- * follows rpc.ts's JsonValue rules exactly like a CALL payload does --
49
- * no boolean, embedded bytes as "0x"-prefixed hex by default or as
50
- * `{"$bytes": base64}` when subscribe() asked for `bytes: "tagged"`
51
- * (see cabi/wirevalue.go).
52
- * `publisher` is the raw 32-byte Ed25519 public key of whoever published
53
- * this event -- NOT verified against the frame's own signature by this
54
- * SDK, matching findRecord/findRecords/findRecordsByType's identical
55
- * "does not verify" posture (dht.ts). */
56
- export interface PubsubEvent {
57
- readonly payload: JsonValue;
58
- readonly publisher: Uint8Array;
59
- readonly seq: number;
60
- }
package/dist/pubsub.js DELETED
@@ -1,8 +0,0 @@
1
- // Pubsub shapes -- macula-go's connection.Session.Publish/Subscribe/
2
- // Unsubscribe and frame.EventInfo (frame/pubsub.go, connection/
3
- // connection.go, connection/subscriber.go). Session (session.ts) is the
4
- // actual FFI entry point (publish()/subscribe()), matching call()/
5
- // serve()/the DHT methods' own shape -- this file holds the shapes that
6
- // side needs, the same split rpc.ts/dht.ts already have.
7
- export {};
8
- //# sourceMappingURL=pubsub.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pubsub.js","sourceRoot":"","sources":["../src/pubsub.ts"],"names":[],"mappings":"AAAA,qEAAqE;AACrE,gEAAgE;AAChE,wEAAwE;AACxE,mEAAmE;AACnE,wEAAwE;AACxE,yDAAyD"}
package/dist/rpc.d.ts DELETED
@@ -1,86 +0,0 @@
1
- /** A CALL/RESULT payload, restricted to what macula's wire CBOR can
2
- * actually represent (cbor.Value's Kind enum: UInt/NegInt/Bytes/Text/
3
- * List/Map/Null/Float -- no bool, no undefined). There is deliberately
4
- * no `boolean` in this union: encode true/false as 1/0 yourself, the
5
- * same rule this project's macula MCP server and macula-cli's own
6
- * wirevalue package both enforce -- a JS boolean silently reaching the
7
- * wire is exactly the mistake this type exists to make impossible at
8
- * compile time.
9
- *
10
- * Bytes have no native JSON shape either. Going IN, write them as an
11
- * object whose ONLY key is "$bytes", holding standard padded base64
12
- * (RFC 4648 section 4): `{"$bytes": "AQID"}` is the three bytes 01 02 03.
13
- * Any other value under that sole key is rejected, an object with more
14
- * keys stays an ordinary map, and a plain string is always text, even
15
- * one that looks like hex -- so the sole-key "$bytes" object is
16
- * reserved. Coming OUT, bytes are a "0x"-prefixed lowercase hex string
17
- * by default, or that same tagged object when the call, serve() or
18
- * subscribe() asked for `bytes: "tagged"` (see BytesOutput), which lets
19
- * a returned value be sent straight back. See cabi/wirevalue.go. */
20
- export type JsonValue = string | number | null | JsonValue[] | {
21
- [key: string]: JsonValue;
22
- };
23
- /** How bytes in a RESULT, an inbound CALL or an EVENT payload reach
24
- * JavaScript: "hex" (the default) as a "0x"-prefixed lowercase hex
25
- * string, "tagged" as `{"$bytes": "<base64>"}`, the same form a payload
26
- * uses going IN. The choice is made on the Go side, per call, serve()
27
- * or subscribe(), because only Go still knows which values were bytes:
28
- * once rendered as hex, bytes and a text value that looks like "0x..."
29
- * can no longer be told apart. */
30
- export type BytesOutput = "hex" | "tagged";
31
- /** BytesOutput as the integer cabi's bytesOutput takes. An unknown value
32
- * (reachable from plain JavaScript) throws instead of silently falling
33
- * back to hex. Internal to the FFI boundary. */
34
- export declare function bytesModeFor(bytes: BytesOutput | undefined): number;
35
- /** The BOLT#4 fields a failed CALL carries -- see bolt4/bolt4.go's own
36
- * 17-code table (UnknownNextPeer, TemporaryRelayFailure, Unauthorized,
37
- * ...). `retryable` is bolt4.Code.IsRetryable()'s verdict, computed
38
- * Go-side from `code` (cabi/rpc.go), not re-derived here. */
39
- export interface Bolt4ErrorInfo {
40
- readonly code: number;
41
- readonly name: string;
42
- readonly retryable: boolean;
43
- readonly detail: string | null;
44
- }
45
- /** Thrown by Session.call() when the provider (or a relay in between)
46
- * answered with a real BOLT#4 ERROR frame instead of a RESULT -- e.g.
47
- * calling a procedure nobody has advertised comes back
48
- * unknown_next_peer; a provider handler that threw comes back
49
- * unknown_error (macula-go's connection/serve.go maps every handler
50
- * error to that one code, matching macula_station_link.erl's own
51
- * handle_inbound_call/2); a provider handler that panicked (recovered)
52
- * comes back temporary_relay_failure. Distinct from a plain
53
- * Error/rejection out of call() itself, which means this CALL never
54
- * got a wire-level answer at all (a local timeout, a dead connection,
55
- * a payload macula's CBOR can't represent). */
56
- export declare class MaculaCallError extends Error {
57
- readonly code: number;
58
- readonly bolt4Name: string;
59
- readonly retryable: boolean;
60
- readonly detail: string | null;
61
- constructor(info: Bolt4ErrorInfo);
62
- }
63
- /** The JSON envelope cabi/rpc.go's macula_session_call returns --
64
- * internal to the FFI boundary, not part of the public API. Kept in
65
- * sync BY HAND with cabi/rpc.go's callEnvelope/callEnvelopeError Go
66
- * structs; there is no shared schema generating either side. */
67
- export type CallEnvelope = {
68
- ok: true;
69
- payload: JsonValue;
70
- } | {
71
- ok: false;
72
- bolt4: Bolt4ErrorInfo;
73
- };
74
- /** How long Session.call() waits for a RESULT/ERROR before giving up,
75
- * in milliseconds -- also becomes the wire's own `deadline_ms` (now +
76
- * this), matching macula-go's own examples/quickstart/main.go, which
77
- * derives both from one duration rather than treating the local wait
78
- * and the wire deadline as independent numbers. */
79
- export declare const DEFAULT_CALL_TIMEOUT_MS = 30000;
80
- /** How long one Session.serve() poll tick blocks waiting for the next
81
- * inbound CALL before checking whether stop() was requested --
82
- * mirrors macula-go's own servePollInterval (connection/serve_loop.go),
83
- * the exact tick length its ServeForever uses internally for the same
84
- * "poll with a bounded per-tick wait, check for cancellation between
85
- * ticks" shape. */
86
- export declare const SERVE_POLL_MS = 2000;
package/dist/rpc.js DELETED
@@ -1,57 +0,0 @@
1
- // Unary RPC -- the caller and provider roles built on top of a
2
- // handshaked Session's control stream, via macula-go's own
3
- // Session.Call (caller) and Session.Advertise + Session.ServeOneCall
4
- // (provider) -- see connection/connection.go and connection/serve.go.
5
- // The actual FFI plumbing lives on Session (session.ts); this file
6
- // holds the shapes both directions share: the JSON-only payload model
7
- // and the structured BOLT#4 error macula-go's own bolt4 package
8
- // defines (bolt4/bolt4.go, 17 codes).
9
- /** BytesOutput as the integer cabi's bytesOutput takes. An unknown value
10
- * (reachable from plain JavaScript) throws instead of silently falling
11
- * back to hex. Internal to the FFI boundary. */
12
- export function bytesModeFor(bytes) {
13
- if (bytes === undefined || bytes === "hex")
14
- return 0;
15
- if (bytes === "tagged")
16
- return 1;
17
- throw new Error(`macula-ts: bytes must be "hex" or "tagged", got ${JSON.stringify(bytes)}`);
18
- }
19
- /** Thrown by Session.call() when the provider (or a relay in between)
20
- * answered with a real BOLT#4 ERROR frame instead of a RESULT -- e.g.
21
- * calling a procedure nobody has advertised comes back
22
- * unknown_next_peer; a provider handler that threw comes back
23
- * unknown_error (macula-go's connection/serve.go maps every handler
24
- * error to that one code, matching macula_station_link.erl's own
25
- * handle_inbound_call/2); a provider handler that panicked (recovered)
26
- * comes back temporary_relay_failure. Distinct from a plain
27
- * Error/rejection out of call() itself, which means this CALL never
28
- * got a wire-level answer at all (a local timeout, a dead connection,
29
- * a payload macula's CBOR can't represent). */
30
- export class MaculaCallError extends Error {
31
- code;
32
- bolt4Name;
33
- retryable;
34
- detail;
35
- constructor(info) {
36
- super(`macula-ts: CALL failed: ${info.name} (bolt4 code ${info.code})${info.detail ? `: ${info.detail}` : ""}`);
37
- this.name = "MaculaCallError";
38
- this.code = info.code;
39
- this.bolt4Name = info.name;
40
- this.retryable = info.retryable;
41
- this.detail = info.detail;
42
- }
43
- }
44
- /** How long Session.call() waits for a RESULT/ERROR before giving up,
45
- * in milliseconds -- also becomes the wire's own `deadline_ms` (now +
46
- * this), matching macula-go's own examples/quickstart/main.go, which
47
- * derives both from one duration rather than treating the local wait
48
- * and the wire deadline as independent numbers. */
49
- export const DEFAULT_CALL_TIMEOUT_MS = 30_000;
50
- /** How long one Session.serve() poll tick blocks waiting for the next
51
- * inbound CALL before checking whether stop() was requested --
52
- * mirrors macula-go's own servePollInterval (connection/serve_loop.go),
53
- * the exact tick length its ServeForever uses internally for the same
54
- * "poll with a bounded per-tick wait, check for cancellation between
55
- * ticks" shape. */
56
- export const SERVE_POLL_MS = 2_000;
57
- //# sourceMappingURL=rpc.js.map
package/dist/rpc.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"rpc.js","sourceRoot":"","sources":["../src/rpc.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,2DAA2D;AAC3D,qEAAqE;AACrE,sEAAsE;AACtE,mEAAmE;AACnE,sEAAsE;AACtE,gEAAgE;AAChE,sCAAsC;AAgCtC;;gDAEgD;AAChD,MAAM,UAAU,YAAY,CAAC,KAA8B;IACzD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,QAAQ;QAAE,OAAO,CAAC,CAAC;IACjC,MAAM,IAAI,KAAK,CAAC,mDAAmD,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC9F,CAAC;AAaD;;;;;;;;;;+CAU+C;AAC/C,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAC/B,IAAI,CAAS;IACb,SAAS,CAAS;IAClB,SAAS,CAAU;IACnB,MAAM,CAAgB;IAE/B,YAAY,IAAoB;QAC9B,KAAK,CAAC,2BAA2B,IAAI,CAAC,IAAI,gBAAgB,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAChH,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC;QAC3B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IAC5B,CAAC;CACF;AAQD;;;;mDAImD;AACnD,MAAM,CAAC,MAAM,uBAAuB,GAAG,MAAM,CAAC;AAE9C;;;;;mBAKmB;AACnB,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC"}