@estiva-app/protocol 0.1.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,57 @@
1
+ /**
2
+ * `@estiva-app/protocol` — the Estiva wire format, once.
3
+ *
4
+ * ## What is in here, and what is deliberately not
5
+ *
6
+ * **In:** the bytes. Event construction, the NIP-01 id preimage, NIP-19 `naddr`,
7
+ * NIP-98 HTTP auth, Schnorr signing, and the two relay clients (the HTTP bridge
8
+ * and the live socket). Everything whose correctness the *relay* judges.
9
+ *
10
+ * **Not in: the fold, or anything that interprets events.** How an app turns a
11
+ * stream of events into current truth is where apps are supposed to differ —
12
+ * `estiva-docs/decisions/0001` §8, and the README of this repo. Ship folds
13
+ * issues, Peek folds conversations, and neither should inherit the other's
14
+ * opinion. `foldFolder`, `foldResolution` and the projection all stay in their
15
+ * apps, and each app's conformance fixture stays with it.
16
+ *
17
+ * That line is the one thing to hold when adding to this package. "Both apps
18
+ * need it" is not the test; "the relay would notice if we disagreed" is.
19
+ *
20
+ * ## Why one implementation, when the suite's whole claim is independence
21
+ *
22
+ * SPEC §10 used to say the duplication *was* the architecture: three apps each
23
+ * implementing NIP-01 serialization is what makes "apps sharing no code work on
24
+ * the same data" a real statement. That argument was right about the *claim* and
25
+ * wrong about the *mechanism*, and the third copy is what settled it.
26
+ *
27
+ * A second hand-written event-id hash is not a demonstration of independence, it
28
+ * is a divergence the relay notices and we do not. It had already happened:
29
+ * Peek's `buildMessage` emitted `a` tags and Ship's could not, so the same
30
+ * logical message produced different bytes depending on which app sent it — and
31
+ * nothing failed, because each copy was self-consistent. `diff -r` between two
32
+ * vendored trees was the only thing holding the other two together, and it is a
33
+ * check somebody has to remember to run.
34
+ *
35
+ * What makes the interop claim true is that the apps share **no interpretation
36
+ * and no database** — which is still exactly the case. They now agree on the
37
+ * wire format on purpose rather than by coincidence.
38
+ *
39
+ * ## A MAJOR here is a protocol event, not a TypeScript event
40
+ *
41
+ * A change to the bytes an app publishes — id computation, serialization order,
42
+ * tag semantics, signature input — is a MAJOR even when the TypeScript signature
43
+ * is identical (ADR 0002 §4b). Every release note answers the wire question
44
+ * explicitly, including when the answer is "unchanged".
45
+ */
46
+ /** Bumped by hand with the version in package.json — `test/version.test.ts`
47
+ * pins the two together. It exists so "the upgrade reached the app" can be
48
+ * checked by grepping a built bundle rather than by trusting a lockfile. */
49
+ export declare const PROTOCOL_VERSION = "0.1.0";
50
+ export { type NostrTag, type UnsignedEvent, type SignedEvent, type Profile, type ThreadRef, type ChannelVisibility, type ChannelKind, type MemberRole, type Label, type ResolutionAction, KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE, computeEventId, toNostrSeconds, canonicalChannelName, threadTags, addr, relayAuthUrl, buildProfile, parseProfile, buildCreateChannel, buildDeleteChannel, buildEditChannelMetadata, buildAddMember, buildReaction, buildDeletion, buildMessage, buildResolution, buildFile, buildComponent, buildHighlight, buildUnsignedRelayAuthEvent, } from './events.js';
51
+ export { type AddressPointer, convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
52
+ export { type AuthEventArgs, TIMESTAMP_TOLERANCE_SECS, normalizeUrl, buildUnsignedAuthEvent, base64, authorizationHeaderFor, authorizationHeader, } from './nip98.js';
53
+ export { type Signer, type SignerKind, publicKeyFromSecret, signEvent, secretKeySigner, } from './sign.js';
54
+ export { type PublishResult, type QueryResult, type RelayHeaders, type RelayOptions, type FetchLike, parsePublishResponse, parseQueryResponse, Relay, } from './bridge.js';
55
+ export { type RelayState, type SocketLike, type RelayCredential, type LiveRelayOptions, type Subscription, type LiveRelay, toWebSocketUrl, parseFrame, createLiveRelay, } from './live.js';
56
+ export { type ChannelEventHandler, type ChannelSubscription, type ChannelSubscriptions, createChannelSubscriptions, } from './subscriptions.js';
57
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,eAAO,MAAM,gBAAgB,UAAU,CAAA;AAEvC,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,KAAK,EACV,KAAK,gBAAgB,EAErB,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB,EAEjB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY,EAEZ,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,cAAc,EACnB,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,aAAa,EAClB,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EACL,KAAK,MAAM,EACX,KAAK,UAAU,EACf,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,YAAY,EACjB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EACL,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EACL,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
package/dist/index.js ADDED
@@ -0,0 +1,63 @@
1
+ /**
2
+ * `@estiva-app/protocol` — the Estiva wire format, once.
3
+ *
4
+ * ## What is in here, and what is deliberately not
5
+ *
6
+ * **In:** the bytes. Event construction, the NIP-01 id preimage, NIP-19 `naddr`,
7
+ * NIP-98 HTTP auth, Schnorr signing, and the two relay clients (the HTTP bridge
8
+ * and the live socket). Everything whose correctness the *relay* judges.
9
+ *
10
+ * **Not in: the fold, or anything that interprets events.** How an app turns a
11
+ * stream of events into current truth is where apps are supposed to differ —
12
+ * `estiva-docs/decisions/0001` §8, and the README of this repo. Ship folds
13
+ * issues, Peek folds conversations, and neither should inherit the other's
14
+ * opinion. `foldFolder`, `foldResolution` and the projection all stay in their
15
+ * apps, and each app's conformance fixture stays with it.
16
+ *
17
+ * That line is the one thing to hold when adding to this package. "Both apps
18
+ * need it" is not the test; "the relay would notice if we disagreed" is.
19
+ *
20
+ * ## Why one implementation, when the suite's whole claim is independence
21
+ *
22
+ * SPEC §10 used to say the duplication *was* the architecture: three apps each
23
+ * implementing NIP-01 serialization is what makes "apps sharing no code work on
24
+ * the same data" a real statement. That argument was right about the *claim* and
25
+ * wrong about the *mechanism*, and the third copy is what settled it.
26
+ *
27
+ * A second hand-written event-id hash is not a demonstration of independence, it
28
+ * is a divergence the relay notices and we do not. It had already happened:
29
+ * Peek's `buildMessage` emitted `a` tags and Ship's could not, so the same
30
+ * logical message produced different bytes depending on which app sent it — and
31
+ * nothing failed, because each copy was self-consistent. `diff -r` between two
32
+ * vendored trees was the only thing holding the other two together, and it is a
33
+ * check somebody has to remember to run.
34
+ *
35
+ * What makes the interop claim true is that the apps share **no interpretation
36
+ * and no database** — which is still exactly the case. They now agree on the
37
+ * wire format on purpose rather than by coincidence.
38
+ *
39
+ * ## A MAJOR here is a protocol event, not a TypeScript event
40
+ *
41
+ * A change to the bytes an app publishes — id computation, serialization order,
42
+ * tag semantics, signature input — is a MAJOR even when the TypeScript signature
43
+ * is identical (ADR 0002 §4b). Every release note answers the wire question
44
+ * explicitly, including when the answer is "unchanged".
45
+ */
46
+ /** Bumped by hand with the version in package.json — `test/version.test.ts`
47
+ * pins the two together. It exists so "the upgrade reached the app" can be
48
+ * checked by grepping a built bundle rather than by trusting a lockfile. */
49
+ export const PROTOCOL_VERSION = '0.1.0';
50
+ export {
51
+ // constants
52
+ KIND, MAX_EMOJI_CHARS, MAX_MESSAGE_BYTES, MAX_MENTIONS, MAX_RATIONALE_BYTES, RELAY_AUTH_TOLERANCE_SECS, ASSERTION_SUBTYPE,
53
+ // the id preimage and the pieces that feed it
54
+ computeEventId, toNostrSeconds, canonicalChannelName, threadTags, addr, relayAuthUrl,
55
+ // builders
56
+ buildProfile, parseProfile, buildCreateChannel, buildDeleteChannel, buildEditChannelMetadata, buildAddMember, buildReaction, buildDeletion, buildMessage, buildResolution, buildFile, buildComponent, buildHighlight, buildUnsignedRelayAuthEvent, } from './events.js';
57
+ export { convertBits, bech32Encode, bech32Decode, encodeNaddr, decodeNaddr, pointerToAddress, addressToPointer, addrToNaddr, naddrToAddr, referenceToPointer, NADDR_RE, findNaddrs, stripNaddrs, } from './nip19.js';
58
+ export { TIMESTAMP_TOLERANCE_SECS, normalizeUrl, buildUnsignedAuthEvent, base64, authorizationHeaderFor, authorizationHeader, } from './nip98.js';
59
+ export { publicKeyFromSecret, signEvent, secretKeySigner, } from './sign.js';
60
+ export { parsePublishResponse, parseQueryResponse, Relay, } from './bridge.js';
61
+ export { toWebSocketUrl, parseFrame, createLiveRelay, } from './live.js';
62
+ export { createChannelSubscriptions, } from './subscriptions.js';
63
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH;;4EAE4E;AAC5E,MAAM,CAAC,MAAM,gBAAgB,GAAG,OAAO,CAAA;AAEvC,OAAO;AAYL,YAAY;AACZ,IAAI,EACJ,eAAe,EACf,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,yBAAyB,EACzB,iBAAiB;AACjB,8CAA8C;AAC9C,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,UAAU,EACV,IAAI,EACJ,YAAY;AACZ,WAAW;AACX,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,EACd,aAAa,EACb,aAAa,EACb,YAAY,EACZ,eAAe,EACf,SAAS,EACT,cAAc,EACd,cAAc,EACd,2BAA2B,GAC5B,MAAM,aAAa,CAAA;AAEpB,OAAO,EAEL,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,WAAW,EACX,gBAAgB,EAChB,gBAAgB,EAChB,WAAW,EACX,WAAW,EACX,kBAAkB,EAClB,QAAQ,EACR,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAA;AAEnB,OAAO,EAEL,wBAAwB,EACxB,YAAY,EACZ,sBAAsB,EACtB,MAAM,EACN,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,YAAY,CAAA;AAEnB,OAAO,EAGL,mBAAmB,EACnB,SAAS,EACT,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAML,oBAAoB,EACpB,kBAAkB,EAClB,KAAK,GACN,MAAM,aAAa,CAAA;AAEpB,OAAO,EAOL,cAAc,EACd,UAAU,EACV,eAAe,GAChB,MAAM,WAAW,CAAA;AAElB,OAAO,EAIL,0BAA0B,GAC3B,MAAM,oBAAoB,CAAA"}
package/dist/live.d.ts ADDED
@@ -0,0 +1,205 @@
1
+ /**
2
+ * One live relay socket, with NIP-42 AUTH and reconnect (PEE-5).
3
+ *
4
+ * A WebSocket that stays open, authenticates as the viewer, and keeps
5
+ * subscriptions alive across disconnects. Nothing is *interpreted* here: this
6
+ * delivers frames, and folding them into state is the consuming app's business.
7
+ *
8
+ * The socket belongs in the **client**, not in a backend: a request-scoped
9
+ * server runtime cannot hold one, and more importantly the viewer's own
10
+ * credential is the only thing that can see the viewer's channels. Buzz gates
11
+ * reads per channel (`is_member_cached`), so a service identity would need
12
+ * membership in every conversation — a product decision, not an implementation
13
+ * detail.
14
+ *
15
+ * **This was built inside Peek** (PEE-5, PEE-6) because Gate 2 had not happened
16
+ * when it was due, and it was Peek-only for two days. SHA-3 is the ticket that
17
+ * owed the move; `subscriptions.ts` beside this file is PEE-6's half.
18
+ *
19
+ * No nostr library. Raw `WebSocket` plus `buildUnsignedRelayAuthEvent` is
20
+ * enough, and the tag layout stays in one place.
21
+ *
22
+ * ## Three things the relay does that shape this file
23
+ *
24
+ * All three were read out of `crates/buzz-*` rather than assumed, because each
25
+ * one fails as a healthy-looking socket that delivers nothing.
26
+ *
27
+ * 1. **A second AUTH on an authenticated connection is refused.** `handle_auth`
28
+ * matches on `AuthState::{Pending, Authenticated, Failed}` and answers
29
+ * anything but `Pending` with `OK … false "auth-required: already
30
+ * authenticated"`. So re-authenticating in place is not possible, and
31
+ * {@link LiveRelay} never tries.
32
+ *
33
+ * 2. **A failed AUTH poisons the connection and leaves it open.** Only a *ban*
34
+ * closes the socket; a verification failure sets `AuthState::Failed` and
35
+ * returns. Every later REQ is answered `CLOSED … "auth-required:
36
+ * authenticate before subscribing"`, forever, on a socket whose readyState
37
+ * is OPEN. Treating an AUTH refusal as fatal-for-this-socket and reconnecting
38
+ * is the only way out.
39
+ *
40
+ * 3. **The `relay` tag is bound to the connection's host**, not the deployment
41
+ * URL — see `relayAuthUrl`.
42
+ *
43
+ * ## Token rotation needs nothing here, and that is worth stating
44
+ *
45
+ * PEE-5 asked for re-authentication when the app renews its access token,
46
+ * preferring it to a reconnect. Neither is needed, and the first is impossible
47
+ * (point 1 above).
48
+ *
49
+ * The relay authenticates a **pubkey**, by verifying a Schnorr signature. It
50
+ * never sees the Estiva ID access token and has no idea one exists. Renewal
51
+ * issues a new token for the *same* keypair, so nothing the relay checked has
52
+ * changed and the connection stays valid. The token is needed only to *sign* a
53
+ * fresh 22242, which happens on the next connect.
54
+ *
55
+ * What genuinely does not propagate is offboarding: a person whose Estiva ID
56
+ * access is revoked keeps an already-authenticated socket until it drops. That
57
+ * is the relay's session model — its own ban gate is the control for it — and
58
+ * re-authenticating on a timer would not have fixed it either, since a banned
59
+ * pubkey is caught at connect.
60
+ *
61
+ * ## Never logged, never persisted
62
+ *
63
+ * The AUTH event and the access token appear in no log line. Buzz refuses to
64
+ * store kind:22242 for this reason, and Convex surfaces function arguments in
65
+ * its dashboard logs — which is the entire reason Peek's credential lives in the
66
+ * browser. {@link LiveRelayOptions.log} receives states and reasons, never
67
+ * events or credentials, and this module must keep it that way.
68
+ */
69
+ import { type SignedEvent, type UnsignedEvent } from './events.js';
70
+ /**
71
+ * What the connection is doing, for PEE-9 to render.
72
+ *
73
+ * `failed` is terminal and deliberate: it means repeated *authentication*
74
+ * refusals, which retrying cannot fix — a missing 22242 grant, a clock more
75
+ * than 60s out, a revoked identity. A relay that is merely down stays in
76
+ * `reconnecting` forever, because that one does fix itself.
77
+ */
78
+ export type RelayState = 'connecting' | 'authenticating' | 'live' | 'reconnecting' | 'failed';
79
+ /** Just enough of `WebSocket` to be faked in a test. */
80
+ export interface SocketLike {
81
+ send(data: string): void;
82
+ close(): void;
83
+ onopen: ((this: unknown, ev: unknown) => unknown) | null;
84
+ onmessage: ((this: unknown, ev: {
85
+ data: unknown;
86
+ }) => unknown) | null;
87
+ onclose: ((this: unknown, ev: unknown) => unknown) | null;
88
+ onerror: ((this: unknown, ev: unknown) => unknown) | null;
89
+ }
90
+ /** The credential a connect attempt needs. `null` means "not signed in". */
91
+ export interface RelayCredential {
92
+ accessToken: string;
93
+ pubkey: string;
94
+ }
95
+ export interface LiveRelayOptions {
96
+ /**
97
+ * The relay origin, `https://…` or `wss://…`.
98
+ *
99
+ * Peek reads this from a Convex query rather than a `VITE_` build-time
100
+ * variable, so that the bundle and the backend cannot drift. Where it comes
101
+ * from is the app's decision; that it is one value is not.
102
+ */
103
+ url: string;
104
+ /** Read fresh on every connect, so a reconnect picks up a renewed token. */
105
+ getCredential: () => RelayCredential | null;
106
+ /**
107
+ * Injected so this module does no fetching of its own. Peek passes
108
+ * `signViaEstivaId`; a keyed client passes a `signEvent` wrapper.
109
+ *
110
+ * `expectedPubkey` is not a request — a remote `/sign` signs as the token's
111
+ * subject whatever it is handed, so a mismatch comes back as HTTP 200 with a
112
+ * valid event authored by somebody else. The implementation must check it.
113
+ */
114
+ sign: (unsigned: UnsignedEvent, token: string, expectedPubkey: string) => Promise<SignedEvent>;
115
+ onState?: (state: RelayState) => void;
116
+ /** Never receives event bodies or credentials. */
117
+ log?: (message: string, detail?: Record<string, unknown>) => void;
118
+ /** Test seams. */
119
+ socketFactory?: (url: string) => SocketLike;
120
+ now?: () => number;
121
+ setTimer?: (fn: () => void, ms: number) => unknown;
122
+ clearTimer?: (handle: unknown) => void;
123
+ /** Backoff shape. Exposed so a test does not wait real seconds. */
124
+ backoff?: {
125
+ baseMs: number;
126
+ maxMs: number;
127
+ jitter: () => number;
128
+ };
129
+ /**
130
+ * Prefix for REQ subscription ids. Cosmetic — it appears in the relay's logs
131
+ * and nowhere else — but a relay operator reading two apps' traffic wants to
132
+ * know which is which. Was hardcoded `peek-` while this lived in Peek.
133
+ */
134
+ subscriptionPrefix?: string;
135
+ }
136
+ export interface Subscription {
137
+ /** Idempotent. Sends CLOSE when the socket is live, and forgets it either way. */
138
+ close(): void;
139
+ }
140
+ export interface LiveRelay {
141
+ /**
142
+ * Drop the current socket and connect again now, ignoring any backoff.
143
+ *
144
+ * For the case a socket cannot detect on its own: the network went away and
145
+ * came back without the connection ever closing. A WebSocket whose peer has
146
+ * become unreachable stays `OPEN` until TCP gives up, which can be minutes —
147
+ * and browser devtools' offline mode frequently does not close it at all. The
148
+ * socket therefore reports `live`, delivers nothing, and would never
149
+ * reconnect, because reconnection is driven by `onclose`.
150
+ *
151
+ * `liveTopics` calls this from the browser's own `online`/`offline` events,
152
+ * which are the one authority here that a socket cannot second-guess.
153
+ */
154
+ reconnect(): void;
155
+ /**
156
+ * Subscribe now if the socket is live, and on every future reconnect.
157
+ *
158
+ * Registering before `live` is normal and supported — that is what makes a
159
+ * subscription survive a reconnect rather than being lost with the socket.
160
+ */
161
+ subscribe(filters: Record<string, unknown>[], onEvent: (event: SignedEvent) => void, options?: {
162
+ onEose?: () => void;
163
+ onClosed?: (reason: string) => void;
164
+ }): Subscription;
165
+ state(): RelayState;
166
+ /** Stop for good. Does not reconnect afterwards. */
167
+ close(): void;
168
+ }
169
+ /** `https://` → `wss://`, `http://` → `ws://`; a `ws`-scheme URL is left alone. */
170
+ export declare function toWebSocketUrl(url: string): string;
171
+ /**
172
+ * A relay message, parsed far enough to route.
173
+ *
174
+ * Deliberately tolerant: an unknown verb is ignored rather than throwing, so a
175
+ * relay that grows a frame does not take the socket down with it.
176
+ */
177
+ type RelayFrame = {
178
+ type: 'AUTH';
179
+ challenge: string;
180
+ } | {
181
+ type: 'OK';
182
+ eventId: string;
183
+ accepted: boolean;
184
+ message: string;
185
+ } | {
186
+ type: 'EVENT';
187
+ subId: string;
188
+ event: SignedEvent;
189
+ } | {
190
+ type: 'EOSE';
191
+ subId: string;
192
+ } | {
193
+ type: 'CLOSED';
194
+ subId: string;
195
+ message: string;
196
+ } | {
197
+ type: 'NOTICE';
198
+ message: string;
199
+ } | {
200
+ type: 'OTHER';
201
+ };
202
+ export declare function parseFrame(raw: unknown): RelayFrame;
203
+ export declare function createLiveRelay(options: LiveRelayOptions): LiveRelay;
204
+ export {};
205
+ //# sourceMappingURL=live.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"live.d.ts","sourceRoot":"","sources":["../src/live.ts"],"names":[],"mappings":"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"}