@macula-io/ts 0.13.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.
@@ -0,0 +1,133 @@
1
+ // Loads the compiled N-API addon (addon/binding.cc) and re-exports its
2
+ // typed functions. Unlike the koffi-era version of this file, there is
3
+ // no runtime signature declaration here -- the addon's C++ glue already
4
+ // knows its own shapes, throws real JS errors on failure (no more
5
+ // manual errOut-array/checkErr dance), and is a single self-contained
6
+ // .node file (cabi/'s Go code is statically linked in via
7
+ // -buildmode=c-archive, not loaded separately at runtime).
8
+ //
9
+ // node-gyp-build picks, at require time, whichever of these exists:
10
+ // build/Release/*.node (a local dev build via `npm run build:addon:dev`)
11
+ // or prebuilds/<platform>-<arch>/*.node (baked in by `npm run
12
+ // build:prebuilds` / prebuildify, and published as part of the npm
13
+ // package) -- this is the whole point: a consumer installing this
14
+ // package from npm never runs a compiler or fetches anything, because
15
+ // the matching prebuild is already sitting in the downloaded tarball.
16
+ import { createRequire } from "node:module";
17
+ import { fileURLToPath } from "node:url";
18
+ import { dirname, join } from "node:path";
19
+ const require = createRequire(import.meta.url);
20
+ const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
21
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
22
+ const addon = require("node-gyp-build")(repoRoot);
23
+ export const native = {
24
+ identityGenerate() {
25
+ return addon.identityGenerate();
26
+ },
27
+ identityFromSeedBytes(seed32) {
28
+ if (seed32.length !== 32) {
29
+ throw new Error(`macula-ts: seed must be exactly 32 bytes, got ${seed32.length}`);
30
+ }
31
+ return addon.identityFromSeedBytes(seed32);
32
+ },
33
+ identityNodeId(handle) {
34
+ return addon.identityNodeId(handle);
35
+ },
36
+ identityPrivateBytes(handle) {
37
+ return addon.identityPrivateBytes(handle);
38
+ },
39
+ identityFree(handle) {
40
+ addon.identityFree(handle);
41
+ },
42
+ identitySign(handle, data) {
43
+ return addon.identitySign(handle, data);
44
+ },
45
+ sessionConnect(host, port, identityHandle) {
46
+ return addon.sessionConnect(host, port, identityHandle);
47
+ },
48
+ sessionRemoteAddr(handle) {
49
+ return addon.sessionRemoteAddr(handle);
50
+ },
51
+ sessionStationNodeId(handle) {
52
+ return addon.sessionStationNodeId(handle);
53
+ },
54
+ sessionClose(handle, identityHandle, reason) {
55
+ return addon.sessionClose(handle, identityHandle, reason);
56
+ },
57
+ sessionCall(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs) {
58
+ return addon.sessionCall(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs);
59
+ },
60
+ ucanMint(identityHandle, issuer, audience, capabilitiesJson, expiresAt, notBefore, nonce, factsJson, proofsJson) {
61
+ return addon.ucanMint(identityHandle, issuer, audience, capabilitiesJson, expiresAt, notBefore, nonce, factsJson, proofsJson);
62
+ },
63
+ ucanDecode(token) {
64
+ return addon.ucanDecode(token);
65
+ },
66
+ sessionCallWithUcan(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs, ucanToken) {
67
+ return addon.sessionCallWithUcan(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs, ucanToken);
68
+ },
69
+ sessionAdvertise(sessionHandle, identityHandle, realm, procedure) {
70
+ return addon.sessionAdvertise(sessionHandle, identityHandle, realm, procedure);
71
+ },
72
+ sessionUnadvertise(sessionHandle, identityHandle, realm, procedure) {
73
+ return addon.sessionUnadvertise(sessionHandle, identityHandle, realm, procedure);
74
+ },
75
+ serveWaitForCall(sessionHandle, identityHandle, realm, procedure, timeoutMs) {
76
+ return addon.serveWaitForCall(sessionHandle, identityHandle, realm, procedure, timeoutMs);
77
+ },
78
+ pendingCallProcedure(pendingHandle) {
79
+ return addon.pendingCallProcedure(pendingHandle);
80
+ },
81
+ pendingCallPayloadJson(pendingHandle) {
82
+ return addon.pendingCallPayloadJson(pendingHandle);
83
+ },
84
+ pendingCallReplyResult(pendingHandle, resultJson) {
85
+ return addon.pendingCallReplyResult(pendingHandle, resultJson);
86
+ },
87
+ pendingCallReplyError(pendingHandle, detail) {
88
+ return addon.pendingCallReplyError(pendingHandle, detail);
89
+ },
90
+ dhtFindRecordsByType(sessionHandle, identityHandle, recordType) {
91
+ return addon.dhtFindRecordsByType(sessionHandle, identityHandle, recordType);
92
+ },
93
+ dhtFindRecords(sessionHandle, identityHandle, key32) {
94
+ return addon.dhtFindRecords(sessionHandle, identityHandle, key32);
95
+ },
96
+ dhtFindRecord(sessionHandle, identityHandle, key32) {
97
+ return addon.dhtFindRecord(sessionHandle, identityHandle, key32);
98
+ },
99
+ dhtPutProcedureAdvertisement(sessionHandle, identityHandle, realm, procedure, servingStation32, ttlMs) {
100
+ return addon.dhtPutProcedureAdvertisement(sessionHandle, identityHandle, realm, procedure, servingStation32, ttlMs);
101
+ },
102
+ dhtPutContentAnnouncement(sessionHandle, identityHandle, mcid34, endpoint, ttlMs) {
103
+ return addon.dhtPutContentAnnouncement(sessionHandle, identityHandle, mcid34, endpoint, ttlMs);
104
+ },
105
+ sessionPublish(sessionHandle, identityHandle, realm, topic, payloadJson, ttlMs) {
106
+ return addon.sessionPublish(sessionHandle, identityHandle, realm, topic, payloadJson, ttlMs);
107
+ },
108
+ sessionSubscribeStart(sessionHandle, identityHandle, realm, topic, onEvent) {
109
+ return addon.sessionSubscribeStart(sessionHandle, identityHandle, realm, topic, onEvent);
110
+ },
111
+ sessionSubscribeStop(subscriptionHandle) {
112
+ return addon.sessionSubscribeStop(subscriptionHandle);
113
+ },
114
+ contentPut(sessionHandle, identityHandle, data, name) {
115
+ return addon.contentPut(sessionHandle, identityHandle, data, name);
116
+ },
117
+ contentGet(sessionHandle, identityHandle, mcidHex) {
118
+ return addon.contentGet(sessionHandle, identityHandle, mcidHex);
119
+ },
120
+ directdialResolve(sessionHandle, identityHandle, realm, procedure) {
121
+ return addon.directdialResolve(sessionHandle, identityHandle, realm, procedure);
122
+ },
123
+ directdialCall(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs) {
124
+ return addon.directdialCall(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs);
125
+ },
126
+ directdialCallWithUcan(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs, ucanToken) {
127
+ return addon.directdialCallWithUcan(sessionHandle, identityHandle, procedure, realm, payloadJson, timeoutMs, ucanToken);
128
+ },
129
+ directdialAdvertise(sessionHandle, identityHandle, realm, procedure, ttlMs) {
130
+ return addon.directdialAdvertise(sessionHandle, identityHandle, realm, procedure, ttlMs);
131
+ },
132
+ };
133
+ //# sourceMappingURL=binding.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"binding.js","sourceRoot":"","sources":["../src/binding.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /** Thrown by Session.getContent() when the station reports the content
2
+ * isn't known to it (macula-go's content.ErrNotFound) -- an expected,
3
+ * routine outcome for a transfer mechanism with no durability
4
+ * guarantee, not a transport failure. Unlike DhtRecord's findRecord()
5
+ * (which resolves `null` for its own equivalent "not found" case),
6
+ * getContent() throws instead: its whole contract is "hand back the
7
+ * bytes or fail", and there is no sensible non-throwing value to return
8
+ * in place of the `Uint8Array` a caller asked for. */
9
+ export declare class ContentNotFoundError extends Error {
10
+ /** The mcid that produced this error, hex-encoded (the same string
11
+ * that was passed to getContent()). */
12
+ readonly mcid: string;
13
+ constructor(mcid: string);
14
+ }
@@ -0,0 +1,45 @@
1
+ // Content transfer -- macula-go's content package (Put/Get), thin
2
+ // CALL/RESULT wrappers to reserved `_content.*` procedures sent on
3
+ // their OWN dedicated QUIC stream (Session.OpenDedicatedStream on the
4
+ // Go side), NOT the shared control stream call()/serve()/the DHT
5
+ // methods/subscribe() all read from -- see cabi/content.go's own doc
6
+ // for why Session.putContent()/getContent() (session.ts) are, unlike
7
+ // those, never subject to Session's same-Session exclusivity guard, and
8
+ // why two concurrent putContent()/getContent() calls on one Session
9
+ // don't race each other either (each gets its own fresh dedicated
10
+ // stream).
11
+ //
12
+ // IMPORTANT: this is a one-time TRANSFER mechanism, not durable object
13
+ // storage. A station may forget content after serving it, there is no
14
+ // "list what's stored here" operation, and there is no "delete"
15
+ // operation -- putContent()/getContent() hand a blob to a peer once,
16
+ // they do not give you a key-value store. Do not build anything on this
17
+ // SDK that assumes content survives indefinitely, or that a station is
18
+ // obligated to keep serving something it once accepted.
19
+ //
20
+ // mcid crosses the FFI boundary as a lowercase hex string (68 hex
21
+ // chars = 34 bytes: <<Version:8, Codec:8, Hash:32/binary>>, macula-go's
22
+ // manifest.Mcid) -- the same "raw byte identifier -> hex string"
23
+ // convention DhtRecord's key/version/signature already use (dht.ts),
24
+ // deliberately NOT rpc.ts's own "0x"-prefixed convention for bytes
25
+ // embedded *inside* a JSON payload -- an mcid stands on its own here,
26
+ // it isn't a payload field.
27
+ /** Thrown by Session.getContent() when the station reports the content
28
+ * isn't known to it (macula-go's content.ErrNotFound) -- an expected,
29
+ * routine outcome for a transfer mechanism with no durability
30
+ * guarantee, not a transport failure. Unlike DhtRecord's findRecord()
31
+ * (which resolves `null` for its own equivalent "not found" case),
32
+ * getContent() throws instead: its whole contract is "hand back the
33
+ * bytes or fail", and there is no sensible non-throwing value to return
34
+ * in place of the `Uint8Array` a caller asked for. */
35
+ export class ContentNotFoundError extends Error {
36
+ /** The mcid that produced this error, hex-encoded (the same string
37
+ * that was passed to getContent()). */
38
+ mcid;
39
+ constructor(mcid) {
40
+ super(`macula-ts: no content found for mcid ${mcid}`);
41
+ this.name = "ContentNotFoundError";
42
+ this.mcid = mcid;
43
+ }
44
+ }
45
+ //# sourceMappingURL=content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.ts"],"names":[],"mappings":"AAAA,kEAAkE;AAClE,mEAAmE;AACnE,sEAAsE;AACtE,iEAAiE;AACjE,qEAAqE;AACrE,qEAAqE;AACrE,wEAAwE;AACxE,oEAAoE;AACpE,kEAAkE;AAClE,WAAW;AACX,EAAE;AACF,uEAAuE;AACvE,sEAAsE;AACtE,gEAAgE;AAChE,qEAAqE;AACrE,wEAAwE;AACxE,uEAAuE;AACvE,wDAAwD;AACxD,EAAE;AACF,kEAAkE;AAClE,wEAAwE;AACxE,iEAAiE;AACjE,qEAAqE;AACrE,mEAAmE;AACnE,sEAAsE;AACtE,4BAA4B;AAE5B;;;;;;;sDAOsD;AACtD,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IAC7C;2CACuC;IAC9B,IAAI,CAAS;IAEtB,YAAY,IAAY;QACtB,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;QACtD,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;QACnC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
package/dist/dht.d.ts ADDED
@@ -0,0 +1,54 @@
1
+ import type { JsonValue } from "./rpc.js";
2
+ /** Record type tags -- macula-go's dht.Type* constants (dht/record.go).
3
+ * There is no client-side constructor for StationEndpoint in macula-go
4
+ * (stations publish those themselves, not clients) -- it's listed here
5
+ * because Session.findRecord/findRecords/findRecordsByType can still
6
+ * return one, not because a Session.putRecord* method can build one. */
7
+ export declare enum DhtRecordType {
8
+ ProcedureAdvertisement = 6,
9
+ ContentAnnouncement = 17,
10
+ StationEndpoint = 18
11
+ }
12
+ /** A signed, TTL'd DHT record envelope -- mirrors macula-go's dht.Record
13
+ * (dht/record.go). `key`/`version`/`signature` are raw bytes with no
14
+ * native JSON shape, so they cross the FFI boundary as lowercase hex
15
+ * strings -- deliberately NOT rpc.ts's own "0x"-prefixed convention for
16
+ * bytes embedded inside a payload (see cabi/dht.go's own doc for why:
17
+ * these three fields never go through jsonToCbor/cborToJSON at all,
18
+ * wirevalue.go's "0x"-hex convention is specifically for bytes found
19
+ * *inside* a cbor.Value payload, which these aren't). `payload` DID go
20
+ * through that conversion (it's the record's own cbor.Value map) and
21
+ * follows rpc.ts's JsonValue rules exactly like a CALL payload does --
22
+ * no boolean, embedded bytes as "0x"-prefixed hex. Note that a
23
+ * procedure_advertisement/content_announcement's own advertiser_node/
24
+ * serving_station/announcer_node/mcid payload fields are themselves raw
25
+ * bytes on the wire (CBOR byte strings) but surface here as the SAME
26
+ * "0x"-prefixed hex JsonValue strings cborToJSON gives any embedded
27
+ * bytes -- consistent with every other payload field this SDK decodes,
28
+ * just called out since they look similar to this record's own
29
+ * top-level key/version/signature while following the other convention.
30
+ *
31
+ * This SDK does not verify a record's signature or check its expiry on
32
+ * the caller's behalf (matching macula-go's own FindRecord/FindRecords/
33
+ * FindRecordsByType, which say the same in their own doc comments) --
34
+ * a caller that needs to trust a record's payload must check both
35
+ * itself (against `key`, `signature`, and `expiresAt`) before relying
36
+ * on it. */
37
+ export interface DhtRecord {
38
+ readonly type: DhtRecordType | number;
39
+ /** Hex-encoded, 32 bytes: the envelope signer's Ed25519 public key. */
40
+ readonly key: string;
41
+ /** Hex-encoded, 16 bytes: a UUIDv7. */
42
+ readonly version: string;
43
+ /** Milliseconds since epoch. */
44
+ readonly createdAt: number;
45
+ /** Milliseconds since epoch. */
46
+ readonly expiresAt: number;
47
+ readonly payload: JsonValue;
48
+ /** Hex-encoded, 64 bytes. */
49
+ readonly signature: string;
50
+ }
51
+ /** Default TTL for a record built by Session.putProcedureAdvertisement()/
52
+ * putContentAnnouncement() when the caller doesn't specify one --
53
+ * matches macula-go's dht.DefaultTTL (48h). */
54
+ export declare const DHT_DEFAULT_TTL_MS: number;
package/dist/dht.js ADDED
@@ -0,0 +1,25 @@
1
+ // DHT record shapes -- macula-go's dht package (FindRecord/FindRecords/
2
+ // FindRecordsByType/PutRecord), thin CALL wrappers to the mesh's own
3
+ // reserved `_dht.*` procedures under the DHT's own all-zero realm
4
+ // (threaded internally by macula-go's dht package, never passed from
5
+ // here -- see cabi/dht.go). Session (session.ts) is the actual FFI
6
+ // entry point for these, matching call()/serve()'s own shape (a
7
+ // Session-bound method, using that Session's own retained Identity to
8
+ // sign); this file holds the shapes both directions share, the same
9
+ // split rpc.ts has for call()/serve().
10
+ /** Record type tags -- macula-go's dht.Type* constants (dht/record.go).
11
+ * There is no client-side constructor for StationEndpoint in macula-go
12
+ * (stations publish those themselves, not clients) -- it's listed here
13
+ * because Session.findRecord/findRecords/findRecordsByType can still
14
+ * return one, not because a Session.putRecord* method can build one. */
15
+ export var DhtRecordType;
16
+ (function (DhtRecordType) {
17
+ DhtRecordType[DhtRecordType["ProcedureAdvertisement"] = 6] = "ProcedureAdvertisement";
18
+ DhtRecordType[DhtRecordType["ContentAnnouncement"] = 17] = "ContentAnnouncement";
19
+ DhtRecordType[DhtRecordType["StationEndpoint"] = 18] = "StationEndpoint";
20
+ })(DhtRecordType || (DhtRecordType = {}));
21
+ /** Default TTL for a record built by Session.putProcedureAdvertisement()/
22
+ * putContentAnnouncement() when the caller doesn't specify one --
23
+ * matches macula-go's dht.DefaultTTL (48h). */
24
+ export const DHT_DEFAULT_TTL_MS = 48 * 60 * 60 * 1000;
25
+ //# sourceMappingURL=dht.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dht.js","sourceRoot":"","sources":["../src/dht.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,qEAAqE;AACrE,kEAAkE;AAClE,qEAAqE;AACrE,mEAAmE;AACnE,gEAAgE;AAChE,sEAAsE;AACtE,oEAAoE;AACpE,uCAAuC;AAIvC;;;;wEAIwE;AACxE,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,qFAA6B,CAAA;IAC7B,gFAA0B,CAAA;IAC1B,wEAAsB,CAAA;AACxB,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AA0CD;;+CAE+C;AAC/C,MAAM,CAAC,MAAM,kBAAkB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC"}
@@ -0,0 +1,79 @@
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 };
@@ -0,0 +1,76 @@
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
@@ -0,0 +1 @@
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,OAAoC,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"}
@@ -0,0 +1,43 @@
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
+ }
@@ -0,0 +1,83 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,8 @@
1
+ export { Identity } from "./identity.js";
2
+ export { Session, type CallOptions } from "./session.js";
3
+ export { MaculaCallError, type JsonValue, type Bolt4ErrorInfo } from "./rpc.js";
4
+ export { DhtRecordType, DHT_DEFAULT_TTL_MS, type DhtRecord } from "./dht.js";
5
+ export type { PublishOptions, PubsubEvent } from "./pubsub.js";
6
+ export { ContentNotFoundError } from "./content.js";
7
+ export { Ucan, type UcanCapability, type UcanFactValue, type UcanMintOptions } from "./ucan.js";
8
+ export { keepAdvertisedDirect, KEEP_ADVERTISED_DIRECT_INTERVAL_MS, type DirectDialTarget, type AdvertiseDirectOptions, type KeepAdvertisedDirectOptions, } from "./directdial.js";
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { Identity } from "./identity.js";
2
+ export { Session } from "./session.js";
3
+ export { MaculaCallError } from "./rpc.js";
4
+ export { DhtRecordType, DHT_DEFAULT_TTL_MS } from "./dht.js";
5
+ export { ContentNotFoundError } from "./content.js";
6
+ export { Ucan } from "./ucan.js";
7
+ export { keepAdvertisedDirect, KEEP_ADVERTISED_DIRECT_INTERVAL_MS, } from "./directdial.js";
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,OAAO,EAAoB,MAAM,cAAc,CAAC;AACzD,OAAO,EAAE,eAAe,EAAuC,MAAM,UAAU,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,kBAAkB,EAAkB,MAAM,UAAU,CAAC;AAE7E,OAAO,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,EAAE,IAAI,EAAiE,MAAM,WAAW,CAAC;AAChG,OAAO,EACL,oBAAoB,EACpB,kCAAkC,GAInC,MAAM,iBAAiB,CAAC"}