@kodelyth/tlon 2026.5.42 → 2026.6.2
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/klaw.plugin.json +203 -3
- package/package.json +19 -6
- package/api.ts +0 -16
- package/channel-plugin-api.ts +0 -1
- package/doctor-contract-api.ts +0 -1
- package/index.ts +0 -16
- package/runtime-api.ts +0 -17
- package/setup-api.ts +0 -2
- package/setup-entry.ts +0 -9
- package/src/account-fields.ts +0 -31
- package/src/channel.message-adapter.test.ts +0 -145
- package/src/channel.runtime.ts +0 -259
- package/src/channel.ts +0 -192
- package/src/config-schema.ts +0 -54
- package/src/core.test.ts +0 -298
- package/src/doctor-contract.ts +0 -9
- package/src/doctor.test.ts +0 -46
- package/src/doctor.ts +0 -10
- package/src/logger-runtime.ts +0 -1
- package/src/monitor/approval-runtime.ts +0 -363
- package/src/monitor/approval.test.ts +0 -33
- package/src/monitor/approval.ts +0 -283
- package/src/monitor/authorization.ts +0 -30
- package/src/monitor/cites.ts +0 -54
- package/src/monitor/discovery.ts +0 -68
- package/src/monitor/history.ts +0 -226
- package/src/monitor/index.ts +0 -1523
- package/src/monitor/media.test.ts +0 -80
- package/src/monitor/media.ts +0 -156
- package/src/monitor/processed-messages.test.ts +0 -58
- package/src/monitor/processed-messages.ts +0 -89
- package/src/monitor/settings-helpers.test.ts +0 -113
- package/src/monitor/settings-helpers.ts +0 -158
- package/src/monitor/utils.ts +0 -402
- package/src/runtime.ts +0 -9
- package/src/security.test.ts +0 -658
- package/src/session-route.ts +0 -40
- package/src/settings.ts +0 -391
- package/src/setup-core.ts +0 -231
- package/src/setup-surface.ts +0 -99
- package/src/targets.ts +0 -102
- package/src/tlon-api.test.ts +0 -572
- package/src/tlon-api.ts +0 -389
- package/src/types.ts +0 -160
- package/src/urbit/auth.ssrf.test.ts +0 -45
- package/src/urbit/auth.ts +0 -48
- package/src/urbit/base-url.test.ts +0 -48
- package/src/urbit/base-url.ts +0 -61
- package/src/urbit/channel-ops.test.ts +0 -36
- package/src/urbit/channel-ops.ts +0 -149
- package/src/urbit/context.ts +0 -50
- package/src/urbit/errors.ts +0 -51
- package/src/urbit/fetch.ts +0 -38
- package/src/urbit/foreigns.ts +0 -49
- package/src/urbit/send.test.ts +0 -83
- package/src/urbit/send.ts +0 -228
- package/src/urbit/sse-client.test.ts +0 -234
- package/src/urbit/sse-client.ts +0 -492
- package/src/urbit/story.ts +0 -332
- package/src/urbit/upload.test.ts +0 -155
- package/src/urbit/upload.ts +0 -60
- package/test-api.ts +0 -1
- package/tsconfig.json +0 -16
package/src/urbit/send.ts
DELETED
|
@@ -1,228 +0,0 @@
|
|
|
1
|
-
import { scot, da } from "@urbit/aura";
|
|
2
|
-
import {
|
|
3
|
-
createMessageReceiptFromOutboundResults,
|
|
4
|
-
type MessageReceiptPartKind,
|
|
5
|
-
} from "klaw/plugin-sdk/channel-message";
|
|
6
|
-
import { markdownToStory, createImageBlock, isImageUrl, type Story } from "./story.js";
|
|
7
|
-
|
|
8
|
-
export type TlonPokeApi = {
|
|
9
|
-
poke: (params: { app: string; mark: string; json: unknown }) => Promise<unknown>;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
type SendTextParams = {
|
|
13
|
-
api: TlonPokeApi;
|
|
14
|
-
fromShip: string;
|
|
15
|
-
toShip: string;
|
|
16
|
-
text: string;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
type SendStoryParams = {
|
|
20
|
-
api: TlonPokeApi;
|
|
21
|
-
fromShip: string;
|
|
22
|
-
toShip: string;
|
|
23
|
-
story: Story;
|
|
24
|
-
kind?: MessageReceiptPartKind;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
function createTlonSendReceipt(params: {
|
|
28
|
-
messageId: string;
|
|
29
|
-
conversationId: string;
|
|
30
|
-
kind: MessageReceiptPartKind;
|
|
31
|
-
}) {
|
|
32
|
-
return createMessageReceiptFromOutboundResults({
|
|
33
|
-
results: [
|
|
34
|
-
{
|
|
35
|
-
channel: "tlon",
|
|
36
|
-
messageId: params.messageId,
|
|
37
|
-
conversationId: params.conversationId,
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
threadId: params.conversationId,
|
|
41
|
-
kind: params.kind,
|
|
42
|
-
});
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export async function sendDm({ api, fromShip, toShip, text }: SendTextParams) {
|
|
46
|
-
const story: Story = markdownToStory(text);
|
|
47
|
-
return sendDmWithStory({ api, fromShip, toShip, story, kind: "text" });
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export async function sendDmWithStory({
|
|
51
|
-
api,
|
|
52
|
-
fromShip,
|
|
53
|
-
toShip,
|
|
54
|
-
story,
|
|
55
|
-
kind = "unknown",
|
|
56
|
-
}: SendStoryParams) {
|
|
57
|
-
const sentAt = Date.now();
|
|
58
|
-
const idUd = scot("ud", da.fromUnix(sentAt));
|
|
59
|
-
const id = `${fromShip}/${idUd}`;
|
|
60
|
-
|
|
61
|
-
const delta = {
|
|
62
|
-
add: {
|
|
63
|
-
memo: {
|
|
64
|
-
content: story,
|
|
65
|
-
author: fromShip,
|
|
66
|
-
sent: sentAt,
|
|
67
|
-
},
|
|
68
|
-
kind: null,
|
|
69
|
-
time: null,
|
|
70
|
-
},
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
const action = {
|
|
74
|
-
ship: toShip,
|
|
75
|
-
diff: { id, delta },
|
|
76
|
-
};
|
|
77
|
-
|
|
78
|
-
await api.poke({
|
|
79
|
-
app: "chat",
|
|
80
|
-
mark: "chat-dm-action",
|
|
81
|
-
json: action,
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
return {
|
|
85
|
-
channel: "tlon",
|
|
86
|
-
messageId: id,
|
|
87
|
-
receipt: createTlonSendReceipt({ messageId: id, conversationId: toShip, kind }),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
type SendGroupParams = {
|
|
92
|
-
api: TlonPokeApi;
|
|
93
|
-
fromShip: string;
|
|
94
|
-
hostShip: string;
|
|
95
|
-
channelName: string;
|
|
96
|
-
text: string;
|
|
97
|
-
replyToId?: string | null;
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
type SendGroupStoryParams = {
|
|
101
|
-
api: TlonPokeApi;
|
|
102
|
-
fromShip: string;
|
|
103
|
-
hostShip: string;
|
|
104
|
-
channelName: string;
|
|
105
|
-
story: Story;
|
|
106
|
-
replyToId?: string | null;
|
|
107
|
-
kind?: MessageReceiptPartKind;
|
|
108
|
-
};
|
|
109
|
-
|
|
110
|
-
export async function sendGroupMessage({
|
|
111
|
-
api,
|
|
112
|
-
fromShip,
|
|
113
|
-
hostShip,
|
|
114
|
-
channelName,
|
|
115
|
-
text,
|
|
116
|
-
replyToId,
|
|
117
|
-
}: SendGroupParams) {
|
|
118
|
-
const story: Story = markdownToStory(text);
|
|
119
|
-
return sendGroupMessageWithStory({
|
|
120
|
-
api,
|
|
121
|
-
fromShip,
|
|
122
|
-
hostShip,
|
|
123
|
-
channelName,
|
|
124
|
-
story,
|
|
125
|
-
replyToId,
|
|
126
|
-
kind: "text",
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export async function sendGroupMessageWithStory({
|
|
131
|
-
api,
|
|
132
|
-
fromShip,
|
|
133
|
-
hostShip,
|
|
134
|
-
channelName,
|
|
135
|
-
story,
|
|
136
|
-
replyToId,
|
|
137
|
-
kind = "unknown",
|
|
138
|
-
}: SendGroupStoryParams) {
|
|
139
|
-
const sentAt = Date.now();
|
|
140
|
-
|
|
141
|
-
// Format reply ID as @ud (with dots) - required for Tlon to recognize thread replies
|
|
142
|
-
let formattedReplyId = replyToId;
|
|
143
|
-
if (replyToId && /^\d+$/.test(replyToId)) {
|
|
144
|
-
try {
|
|
145
|
-
// scot('ud', n) formats a number as @ud with dots
|
|
146
|
-
formattedReplyId = scot("ud", BigInt(replyToId));
|
|
147
|
-
} catch {
|
|
148
|
-
// Fall back to raw ID if formatting fails
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
const action = {
|
|
153
|
-
channel: {
|
|
154
|
-
nest: `chat/${hostShip}/${channelName}`,
|
|
155
|
-
action: formattedReplyId
|
|
156
|
-
? {
|
|
157
|
-
// Thread reply - needs post wrapper around reply action
|
|
158
|
-
// ReplyActionAdd takes Memo: {content, author, sent} - no kind/blob/meta
|
|
159
|
-
post: {
|
|
160
|
-
reply: {
|
|
161
|
-
id: formattedReplyId,
|
|
162
|
-
action: {
|
|
163
|
-
add: {
|
|
164
|
-
content: story,
|
|
165
|
-
author: fromShip,
|
|
166
|
-
sent: sentAt,
|
|
167
|
-
},
|
|
168
|
-
},
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
}
|
|
172
|
-
: {
|
|
173
|
-
// Regular post
|
|
174
|
-
post: {
|
|
175
|
-
add: {
|
|
176
|
-
content: story,
|
|
177
|
-
author: fromShip,
|
|
178
|
-
sent: sentAt,
|
|
179
|
-
kind: "/chat",
|
|
180
|
-
blob: null,
|
|
181
|
-
meta: null,
|
|
182
|
-
},
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
},
|
|
186
|
-
};
|
|
187
|
-
|
|
188
|
-
await api.poke({
|
|
189
|
-
app: "channels",
|
|
190
|
-
mark: "channel-action-1",
|
|
191
|
-
json: action,
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
const messageId = `${fromShip}/${sentAt}`;
|
|
195
|
-
return {
|
|
196
|
-
channel: "tlon",
|
|
197
|
-
messageId,
|
|
198
|
-
receipt: createTlonSendReceipt({
|
|
199
|
-
messageId,
|
|
200
|
-
conversationId: `${hostShip}/${channelName}`,
|
|
201
|
-
kind,
|
|
202
|
-
}),
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/**
|
|
207
|
-
* Build a story with text and optional media (image)
|
|
208
|
-
*/
|
|
209
|
-
export function buildMediaStory(text: string | undefined, mediaUrl: string | undefined): Story {
|
|
210
|
-
const story: Story = [];
|
|
211
|
-
const cleanText = text?.trim() ?? "";
|
|
212
|
-
const cleanUrl = mediaUrl?.trim() ?? "";
|
|
213
|
-
|
|
214
|
-
// Add text content if present
|
|
215
|
-
if (cleanText) {
|
|
216
|
-
story.push(...markdownToStory(cleanText));
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Add image block if URL looks like an image
|
|
220
|
-
if (cleanUrl && isImageUrl(cleanUrl)) {
|
|
221
|
-
story.push(createImageBlock(cleanUrl, ""));
|
|
222
|
-
} else if (cleanUrl) {
|
|
223
|
-
// For non-image URLs, add as a link
|
|
224
|
-
story.push({ inline: [{ link: { href: cleanUrl, content: cleanUrl } }] });
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
return story.length > 0 ? story : [{ inline: [""] }];
|
|
228
|
-
}
|
|
@@ -1,234 +0,0 @@
|
|
|
1
|
-
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
-
import { urbitFetch } from "./fetch.js";
|
|
3
|
-
import { UrbitSSEClient } from "./sse-client.js";
|
|
4
|
-
|
|
5
|
-
// Mock urbitFetch to avoid real network calls
|
|
6
|
-
vi.mock("./fetch.js", () => ({
|
|
7
|
-
urbitFetch: vi.fn(),
|
|
8
|
-
}));
|
|
9
|
-
|
|
10
|
-
// Mock channel-ops to avoid real channel operations
|
|
11
|
-
vi.mock("./channel-ops.js", () => ({
|
|
12
|
-
ensureUrbitChannelOpen: vi.fn().mockResolvedValue(undefined),
|
|
13
|
-
pokeUrbitChannel: vi.fn().mockResolvedValue(undefined),
|
|
14
|
-
scryUrbitPath: vi.fn().mockResolvedValue({}),
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
function requireFirstMockCall(calls: readonly unknown[][], label: string): unknown[] {
|
|
18
|
-
const call = calls.at(0);
|
|
19
|
-
if (!call) {
|
|
20
|
-
throw new Error(`Expected ${label} call`);
|
|
21
|
-
}
|
|
22
|
-
return call;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
describe("UrbitSSEClient", () => {
|
|
26
|
-
beforeEach(() => {
|
|
27
|
-
vi.clearAllMocks();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
afterEach(() => {
|
|
31
|
-
vi.restoreAllMocks();
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe("subscribe", () => {
|
|
35
|
-
it("sends subscriptions added after connect", async () => {
|
|
36
|
-
const mockUrbitFetch = vi.mocked(urbitFetch);
|
|
37
|
-
mockUrbitFetch.mockResolvedValue({
|
|
38
|
-
response: { ok: true, status: 200 } as unknown as Response,
|
|
39
|
-
finalUrl: "https://example.com",
|
|
40
|
-
release: vi.fn().mockResolvedValue(undefined),
|
|
41
|
-
});
|
|
42
|
-
|
|
43
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
44
|
-
// Simulate connected state
|
|
45
|
-
(client as { isConnected: boolean }).isConnected = true;
|
|
46
|
-
|
|
47
|
-
await client.subscribe({
|
|
48
|
-
app: "chat",
|
|
49
|
-
path: "/dm/~zod",
|
|
50
|
-
event: () => {},
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
expect(mockUrbitFetch).toHaveBeenCalledTimes(1);
|
|
54
|
-
const callArgs = requireFirstMockCall(mockUrbitFetch.mock.calls, "urbit fetch")[0] as
|
|
55
|
-
| Parameters<typeof urbitFetch>[0]
|
|
56
|
-
| undefined;
|
|
57
|
-
if (!callArgs) {
|
|
58
|
-
throw new Error("Expected urbit fetch arguments");
|
|
59
|
-
}
|
|
60
|
-
expect(callArgs.path).toContain("/~/channel/");
|
|
61
|
-
expect(callArgs.init?.method).toBe("PUT");
|
|
62
|
-
|
|
63
|
-
const body = JSON.parse(callArgs.init?.body as string);
|
|
64
|
-
expect(body).toHaveLength(1);
|
|
65
|
-
expect(body[0]).toEqual({
|
|
66
|
-
id: 1,
|
|
67
|
-
action: "subscribe",
|
|
68
|
-
ship: "example",
|
|
69
|
-
app: "chat",
|
|
70
|
-
path: "/dm/~zod",
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
it("queues subscriptions before connect", async () => {
|
|
75
|
-
const mockUrbitFetch = vi.mocked(urbitFetch);
|
|
76
|
-
|
|
77
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
78
|
-
// Not connected yet
|
|
79
|
-
|
|
80
|
-
await client.subscribe({
|
|
81
|
-
app: "chat",
|
|
82
|
-
path: "/dm/~zod",
|
|
83
|
-
event: () => {},
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
// Should not call urbitFetch since not connected
|
|
87
|
-
expect(mockUrbitFetch).not.toHaveBeenCalled();
|
|
88
|
-
// But subscription should be queued
|
|
89
|
-
expect(client.subscriptions).toHaveLength(1);
|
|
90
|
-
expect(client.subscriptions[0]).toEqual({
|
|
91
|
-
id: 1,
|
|
92
|
-
action: "subscribe",
|
|
93
|
-
ship: "example",
|
|
94
|
-
app: "chat",
|
|
95
|
-
path: "/dm/~zod",
|
|
96
|
-
});
|
|
97
|
-
});
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
describe("updateCookie", () => {
|
|
101
|
-
it("normalizes cookie when updating", () => {
|
|
102
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
103
|
-
|
|
104
|
-
// Cookie with extra parts that should be stripped
|
|
105
|
-
client.updateCookie("urbauth-~zod=456; Path=/; HttpOnly");
|
|
106
|
-
|
|
107
|
-
expect(client.cookie).toBe("urbauth-~zod=456");
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
it("handles simple cookie values", () => {
|
|
111
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
112
|
-
|
|
113
|
-
client.updateCookie("urbauth-~zod=newvalue");
|
|
114
|
-
|
|
115
|
-
expect(client.cookie).toBe("urbauth-~zod=newvalue");
|
|
116
|
-
});
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
describe("reconnection", () => {
|
|
120
|
-
it("has autoReconnect enabled by default", () => {
|
|
121
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
122
|
-
expect(client.autoReconnect).toBe(true);
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("can disable autoReconnect via options", () => {
|
|
126
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123", {
|
|
127
|
-
autoReconnect: false,
|
|
128
|
-
});
|
|
129
|
-
expect(client.autoReconnect).toBe(false);
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("stores onReconnect callback", () => {
|
|
133
|
-
const onReconnect = vi.fn();
|
|
134
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123", {
|
|
135
|
-
onReconnect,
|
|
136
|
-
});
|
|
137
|
-
expect(client.onReconnect).toBe(onReconnect);
|
|
138
|
-
});
|
|
139
|
-
|
|
140
|
-
it("resets reconnect attempts on successful connect", async () => {
|
|
141
|
-
const mockUrbitFetch = vi.mocked(urbitFetch);
|
|
142
|
-
|
|
143
|
-
// Mock a response that returns a readable stream
|
|
144
|
-
const mockStream = new ReadableStream({
|
|
145
|
-
start(controller) {
|
|
146
|
-
controller.close();
|
|
147
|
-
},
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
mockUrbitFetch.mockResolvedValue({
|
|
151
|
-
response: {
|
|
152
|
-
ok: true,
|
|
153
|
-
status: 200,
|
|
154
|
-
body: mockStream,
|
|
155
|
-
} as unknown as Response,
|
|
156
|
-
finalUrl: "https://example.com",
|
|
157
|
-
release: vi.fn().mockResolvedValue(undefined),
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123", {
|
|
161
|
-
autoReconnect: false, // Disable to prevent reconnect loop
|
|
162
|
-
});
|
|
163
|
-
client.reconnectAttempts = 5;
|
|
164
|
-
|
|
165
|
-
await client.connect();
|
|
166
|
-
|
|
167
|
-
expect(client.reconnectAttempts).toBe(0);
|
|
168
|
-
});
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
describe("event acking", () => {
|
|
172
|
-
it("logs malformed SSE JSON with an owned parser error", () => {
|
|
173
|
-
const logger = { error: vi.fn() };
|
|
174
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123", {
|
|
175
|
-
logger,
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
client.processEvent("id: 1\ndata: {not json");
|
|
179
|
-
|
|
180
|
-
expect(logger.error).toHaveBeenCalledWith(
|
|
181
|
-
"Error parsing SSE event: Error: Tlon Urbit SSE event was malformed JSON",
|
|
182
|
-
);
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
it("tracks lastHeardEventId and ackThreshold", () => {
|
|
186
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
187
|
-
|
|
188
|
-
// Access private properties for testing
|
|
189
|
-
const lastHeardEventId = (client as unknown as { lastHeardEventId: number }).lastHeardEventId;
|
|
190
|
-
const ackThreshold = (client as unknown as { ackThreshold: number }).ackThreshold;
|
|
191
|
-
|
|
192
|
-
expect(lastHeardEventId).toBe(-1);
|
|
193
|
-
expect(ackThreshold).toBeGreaterThan(0);
|
|
194
|
-
});
|
|
195
|
-
});
|
|
196
|
-
|
|
197
|
-
describe("constructor", () => {
|
|
198
|
-
it("generates unique channel ID", () => {
|
|
199
|
-
const client1 = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
200
|
-
const client2 = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
201
|
-
|
|
202
|
-
expect(client1.channelId).not.toBe(client2.channelId);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it("normalizes cookie in constructor", () => {
|
|
206
|
-
const client = new UrbitSSEClient(
|
|
207
|
-
"https://example.com",
|
|
208
|
-
"urbauth-~zod=123; Path=/; HttpOnly",
|
|
209
|
-
);
|
|
210
|
-
|
|
211
|
-
expect(client.cookie).toBe("urbauth-~zod=123");
|
|
212
|
-
});
|
|
213
|
-
|
|
214
|
-
it("sets default reconnection parameters", () => {
|
|
215
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123");
|
|
216
|
-
|
|
217
|
-
expect(client.maxReconnectAttempts).toBe(10);
|
|
218
|
-
expect(client.reconnectDelay).toBe(1000);
|
|
219
|
-
expect(client.maxReconnectDelay).toBe(30000);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it("allows overriding reconnection parameters", () => {
|
|
223
|
-
const client = new UrbitSSEClient("https://example.com", "urbauth-~zod=123", {
|
|
224
|
-
maxReconnectAttempts: 5,
|
|
225
|
-
reconnectDelay: 500,
|
|
226
|
-
maxReconnectDelay: 10000,
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
expect(client.maxReconnectAttempts).toBe(5);
|
|
230
|
-
expect(client.reconnectDelay).toBe(500);
|
|
231
|
-
expect(client.maxReconnectDelay).toBe(10000);
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
});
|