void 0.7.3 → 0.7.5

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.
Files changed (34) hide show
  1. package/dist/{better-auth-shared-APuDaPqW.mjs → better-auth-shared-CjnJZFC0.mjs} +51 -5
  2. package/dist/cli/cli.mjs +8 -8
  3. package/dist/{db-ClNu7vYQ.mjs → db-RqxhOT2E.mjs} +1 -1
  4. package/dist/{deploy-BkjqNk9U.mjs → deploy-CRIz77mw.mjs} +243 -56
  5. package/dist/index.mjs +56 -22
  6. package/dist/{init-CPny6w9D.mjs → init-FMZ29UZW.mjs} +2 -2
  7. package/dist/pages/client.d.mts +4 -3
  8. package/dist/pages/client.mjs +18 -6
  9. package/dist/pages/protocol.d.mts +1 -1
  10. package/dist/pages/protocol.mjs +5 -0
  11. package/dist/{plugin-inference-oZ6Ybu2_.mjs → plugin-inference-CCtRkt9O.mjs} +41 -12
  12. package/dist/{prepare-DKkx-2Kt.mjs → prepare-PqAbhLte.mjs} +2 -2
  13. package/dist/{preset-DFvePt0l.mjs → preset-jKn1hQwP.mjs} +1 -1
  14. package/dist/{protocol-CK4OFwfR.d.mts → protocol-DxGzKEz2.d.mts} +1 -0
  15. package/dist/runtime/better-auth-pg.mjs +1 -1
  16. package/dist/runtime/better-auth.mjs +1 -1
  17. package/dist/runtime/live-client.d.mts +34 -0
  18. package/dist/runtime/live-client.mjs +283 -0
  19. package/dist/runtime/live-server.d.mts +13 -0
  20. package/dist/runtime/live-server.mjs +417 -0
  21. package/dist/runtime/live.d.mts +107 -0
  22. package/dist/runtime/live.mjs +409 -0
  23. package/dist/runtime/migration-handler.mjs +34 -1
  24. package/dist/runtime/sse-client.d.mts +22 -0
  25. package/dist/runtime/sse-client.mjs +36 -0
  26. package/dist/runtime/sse.d.mts +35 -0
  27. package/dist/runtime/sse.mjs +172 -0
  28. package/dist/{scan-C6HMEIdW.mjs → scan-QtRTdh94.mjs} +1 -1
  29. package/package.json +27 -2
  30. package/skills/void/docs/guide/live.md +230 -0
  31. package/skills/void/docs/guide/pages-routing/overview.md +11 -0
  32. package/skills/void/docs/guide/sse.md +187 -0
  33. package/skills/void/docs/index.md +12 -15
  34. package/skills/void/docs/reference/api.md +12 -4
@@ -0,0 +1,417 @@
1
+ import { eventStream } from "./sse.mjs";
2
+ import { __getLiveBindingName } from "./live.mjs";
3
+ //#region src/runtime/live-server.ts
4
+ const GENERATION_KEY = "connection:generation";
5
+ const TOPIC_PRUNE_ALARM_DELAY_MS = 6e4;
6
+ const textEncoder = new TextEncoder();
7
+ function createLiveDurableObject() {
8
+ class VoidLiveStreamDurableObject {
9
+ connection = null;
10
+ publishChain = Promise.resolve();
11
+ constructor(state, env) {
12
+ this.state = state;
13
+ this.env = env;
14
+ }
15
+ async fetch(request) {
16
+ const { pathname } = new URL(request.url);
17
+ if (request.method !== "POST") return new Response("Method Not Allowed", { status: 405 });
18
+ if (pathname === "/connect") return this.connect(await request.json());
19
+ if (pathname === "/control") return this.control(await request.json());
20
+ if (pathname === "/deliver") return this.deliver(await request.json());
21
+ if (pathname === "/check") return this.check(await request.json());
22
+ if (pathname === "/register") return this.register(await request.json());
23
+ if (pathname === "/unregister") return this.unregister(await request.json());
24
+ if (pathname === "/publish") return this.enqueuePublish(request);
25
+ return new Response("Not Found", { status: 404 });
26
+ }
27
+ async alarm() {
28
+ await this.pruneAllSubscribers();
29
+ }
30
+ enqueuePublish(request) {
31
+ const run = this.publishChain.catch(() => {}).then(async () => {
32
+ return this.publish(await request.json());
33
+ });
34
+ this.publishChain = run.then(() => {}, () => {});
35
+ return run;
36
+ }
37
+ async connect(message) {
38
+ const previous = this.connection;
39
+ if (previous) {
40
+ const active = [...previous.subscriptions.values()].filter((sub) => sub.active);
41
+ for (const subscription of previous.subscriptions.values()) subscription.active = false;
42
+ await previous.stream.close().catch(() => {});
43
+ await Promise.all(active.map((sub) => this.unregisterTopic(message.streamId, message.connectionId, sub)));
44
+ }
45
+ const generation = (await this.state.storage.get(GENERATION_KEY) ?? 0) + 1;
46
+ await this.state.storage.put(GENERATION_KEY, generation);
47
+ return eventStream(async (stream) => {
48
+ const subscriptions = previous?.owner === message.owner ? previous.subscriptions : /* @__PURE__ */ new Map();
49
+ for (const subscription of subscriptions.values()) subscription.active = false;
50
+ this.connection = {
51
+ stream,
52
+ owner: message.owner,
53
+ generation,
54
+ subscriptions,
55
+ writeChain: Promise.resolve(),
56
+ queued: 0,
57
+ limits: message.limits
58
+ };
59
+ await stream.comment("connected");
60
+ await stream.closed;
61
+ if (this.connection?.generation === generation) {
62
+ const active = [...this.connection.subscriptions.values()].filter((sub) => sub.active);
63
+ this.connection = null;
64
+ await Promise.all(active.map((sub) => this.unregisterTopic(message.streamId, message.connectionId, sub)));
65
+ }
66
+ }, { keepAlive: {
67
+ intervalMs: 15e3,
68
+ comment: "keep-alive"
69
+ } });
70
+ }
71
+ async control(message) {
72
+ const connection = this.connection;
73
+ if (!connection) return controlBatchError("CONNECTION_NOT_FOUND", "live: connection is not open.", 404);
74
+ if (connection.owner !== message.owner) return controlBatchError("OWNER_MISMATCH", "live: connection owner mismatch.", 403);
75
+ const results = [];
76
+ for (const operation of message.operations) {
77
+ if (operation.kind === "unsubscribe") {
78
+ const existing = connection.subscriptions.get(operation.id);
79
+ if (existing) {
80
+ existing.active = false;
81
+ await this.unregisterTopic(message.streamId, message.connectionId, existing);
82
+ connection.subscriptions.delete(operation.id);
83
+ }
84
+ results.push({
85
+ ok: true,
86
+ kind: "unsubscribe",
87
+ id: operation.id
88
+ });
89
+ continue;
90
+ }
91
+ if (!connection.subscriptions.has(operation.id) && activeSubscriptionCount(connection) >= message.limits.maxSubscriptionsPerConnection) {
92
+ results.push({
93
+ ok: false,
94
+ kind: "subscribe",
95
+ id: operation.id,
96
+ error: {
97
+ code: "SUBSCRIPTION_LIMIT",
98
+ message: "live: subscription limit reached."
99
+ }
100
+ });
101
+ continue;
102
+ }
103
+ const topicKey = await topicDigest(message.streamId, operation.topic);
104
+ const existing = connection.subscriptions.get(operation.id);
105
+ const revision = (existing?.revision ?? 0) + 1;
106
+ const row = {
107
+ streamId: message.streamId,
108
+ topic: operation.topic,
109
+ topicKey,
110
+ connectionId: message.connectionId,
111
+ subscriptionId: operation.id,
112
+ generation: connection.generation,
113
+ revision,
114
+ lastSeenAt: Date.now()
115
+ };
116
+ const response = await this.topicStub(message.streamId, topicKey).fetch(internalUrl("/register"), {
117
+ method: "POST",
118
+ body: JSON.stringify({
119
+ ...row,
120
+ limits: message.limits
121
+ })
122
+ });
123
+ if (!response.ok) {
124
+ results.push({
125
+ ok: false,
126
+ kind: "subscribe",
127
+ id: operation.id,
128
+ error: response.status === 409 ? {
129
+ code: "TOPIC_FULL",
130
+ message: "live: topic subscription limit reached."
131
+ } : {
132
+ code: "INTERNAL_ERROR",
133
+ message: await response.text()
134
+ }
135
+ });
136
+ continue;
137
+ }
138
+ if (existing) {
139
+ existing.active = false;
140
+ await this.unregisterTopic(message.streamId, message.connectionId, existing).catch(() => {});
141
+ }
142
+ connection.subscriptions.set(operation.id, {
143
+ id: operation.id,
144
+ topic: operation.topic,
145
+ topicKey,
146
+ generation: connection.generation,
147
+ revision,
148
+ active: true
149
+ });
150
+ results.push({
151
+ ok: true,
152
+ kind: "subscribe",
153
+ id: operation.id,
154
+ topic: operation.topic
155
+ });
156
+ }
157
+ return Response.json({
158
+ accepted: true,
159
+ connectionId: message.connectionId,
160
+ results
161
+ });
162
+ }
163
+ async deliver(message) {
164
+ const connection = this.connection;
165
+ if (!connection) return new Response("connection missing", { status: 410 });
166
+ let delivered = 0;
167
+ const stale = [];
168
+ for (const [index, row] of message.subscriptions.entries()) {
169
+ if (isStaleSubscriber(row, connection)) {
170
+ stale.push(index);
171
+ continue;
172
+ }
173
+ if (connection.queued >= connection.limits.maxQueuedEventsPerConnection) {
174
+ await connection.stream.close().catch(() => {});
175
+ this.connection = null;
176
+ return new Response("connection queue full", { status: 410 });
177
+ }
178
+ const event = {
179
+ subscriptionId: row.subscriptionId,
180
+ topic: message.topic,
181
+ ...message.type !== void 0 && { type: message.type },
182
+ ...message.eventId !== void 0 && { eventId: message.eventId },
183
+ data: message.data
184
+ };
185
+ if (encodedLiveEventSize(event) > connection.limits.maxEncodedEventSize) return payloadTooLargeResponse(connection.limits.maxEncodedEventSize);
186
+ connection.queued++;
187
+ const activeConnection = connection;
188
+ connection.writeChain = connection.writeChain.catch(() => {}).then(() => connection.stream.send({
189
+ event: "message",
190
+ data: event
191
+ })).catch(() => {
192
+ if (this.connection === activeConnection) this.connection = null;
193
+ connection.stream.close().catch(() => {});
194
+ }).finally(() => {
195
+ connection.queued--;
196
+ });
197
+ delivered++;
198
+ }
199
+ return Response.json({
200
+ delivered,
201
+ stale
202
+ });
203
+ }
204
+ check(message) {
205
+ const connection = this.connection;
206
+ if (!connection) return new Response("connection missing", { status: 410 });
207
+ const stale = [];
208
+ for (const [index, row] of message.subscriptions.entries()) if (isStaleSubscriber(row, connection)) stale.push(index);
209
+ return Response.json({ stale });
210
+ }
211
+ async register(row) {
212
+ const prefix = subscriberPrefix(row.streamId, row.topicKey);
213
+ const current = await this.state.storage.list({ prefix });
214
+ const deletedKeys = /* @__PURE__ */ new Set();
215
+ for (const [key, value] of current) {
216
+ if (value.connectionId === row.connectionId && value.generation < row.generation) {
217
+ deletedKeys.add(key);
218
+ continue;
219
+ }
220
+ if (value.connectionId === row.connectionId && value.subscriptionId === row.subscriptionId) deletedKeys.add(key);
221
+ }
222
+ let activeRows = [...current].filter(([key]) => !deletedKeys.has(key));
223
+ if (activeRows.length >= row.limits.maxSubscriptionsPerTopic) {
224
+ for (const key of await this.findStaleSubscriberKeys(activeRows, row.limits)) deletedKeys.add(key);
225
+ activeRows = activeRows.filter(([key]) => !deletedKeys.has(key));
226
+ }
227
+ if (activeRows.length >= row.limits.maxSubscriptionsPerTopic) return new Response("topic full", { status: 409 });
228
+ if (deletedKeys.size > 0) await this.state.storage.delete([...deletedKeys]);
229
+ await this.state.storage.put(subscriberKey(row), withoutLimits(row));
230
+ await this.schedulePruneAlarm();
231
+ return Response.json({ ok: true });
232
+ }
233
+ async unregister(row) {
234
+ if (!row.streamId || !row.topicKey) return Response.json({ ok: true });
235
+ const key = row.connectionId && row.subscriptionId && row.generation != null && row.revision != null ? subscriberKey(row) : void 0;
236
+ if (key) await this.state.storage.delete(key);
237
+ return Response.json({ ok: true });
238
+ }
239
+ async publish(message) {
240
+ const rows = await this.state.storage.list({ prefix: subscriberPrefix(message.streamId, message.topicKey) });
241
+ const grouped = /* @__PURE__ */ new Map();
242
+ for (const [key, row] of rows) {
243
+ const list = grouped.get(row.connectionId) ?? [];
244
+ list.push({
245
+ key,
246
+ row
247
+ });
248
+ grouped.set(row.connectionId, list);
249
+ }
250
+ for (const { row } of [...grouped.values()].flat()) if (encodedLiveEventSize({
251
+ subscriptionId: row.subscriptionId,
252
+ topic: message.topic,
253
+ ...message.type !== void 0 && { type: message.type },
254
+ ...message.eventId !== void 0 && { eventId: message.eventId },
255
+ data: message.data
256
+ }) > message.limits.maxEncodedEventSize) return payloadTooLargeResponse(message.limits.maxEncodedEventSize);
257
+ for (const [connectionId, items] of grouped) {
258
+ const response = await fetchWithTimeout(this.connectionStub(message.streamId, connectionId), internalUrl("/deliver"), {
259
+ method: "POST",
260
+ body: JSON.stringify({
261
+ streamId: message.streamId,
262
+ topic: message.topic,
263
+ data: message.data,
264
+ type: message.type,
265
+ eventId: message.eventId,
266
+ subscriptions: items.map((item) => item.row)
267
+ })
268
+ }, message.limits.deliveryAttemptTimeoutMs);
269
+ if (!response || response.status === 410 || response.status === 404) {
270
+ await this.state.storage.delete(items.map((item) => item.key));
271
+ continue;
272
+ }
273
+ if (response.status === 413) return response;
274
+ if (response.ok) {
275
+ const staleKeys = (await response.json().catch(() => null))?.stale.map((index) => items[index]?.key).filter((key) => typeof key === "string");
276
+ if (staleKeys?.length) await this.state.storage.delete(staleKeys);
277
+ }
278
+ }
279
+ return Response.json({ ok: true });
280
+ }
281
+ async pruneAllSubscribers() {
282
+ const rows = await this.state.storage.list({ prefix: "sub:" });
283
+ const staleKeys = await this.findStaleSubscriberKeys([...rows], { deliveryAttemptTimeoutMs: 1500 });
284
+ if (staleKeys.length > 0) await this.state.storage.delete(staleKeys);
285
+ if (rows.size > staleKeys.length) await this.schedulePruneAlarm();
286
+ }
287
+ async findStaleSubscriberKeys(entries, limits) {
288
+ const grouped = /* @__PURE__ */ new Map();
289
+ for (const [key, row] of entries) {
290
+ const list = grouped.get(row.connectionId) ?? [];
291
+ list.push({
292
+ key,
293
+ row
294
+ });
295
+ grouped.set(row.connectionId, list);
296
+ }
297
+ const staleKeys = [];
298
+ for (const [connectionId, items] of grouped) {
299
+ const response = await fetchWithTimeout(this.connectionStub(items[0].row.streamId, connectionId), internalUrl("/check"), {
300
+ method: "POST",
301
+ body: JSON.stringify({ subscriptions: items.map((item) => item.row) })
302
+ }, limits.deliveryAttemptTimeoutMs);
303
+ if (!response || response.status === 410 || response.status === 404) {
304
+ staleKeys.push(...items.map((item) => item.key));
305
+ continue;
306
+ }
307
+ if (response.ok) {
308
+ const result = await response.json().catch(() => null);
309
+ for (const index of result?.stale ?? []) {
310
+ const key = items[index]?.key;
311
+ if (key) staleKeys.push(key);
312
+ }
313
+ }
314
+ }
315
+ return staleKeys;
316
+ }
317
+ async schedulePruneAlarm() {
318
+ await this.state.storage.setAlarm?.(Date.now() + TOPIC_PRUNE_ALARM_DELAY_MS);
319
+ }
320
+ topicStub(streamId, topicKey) {
321
+ const binding = this.env[__getLiveBindingName()];
322
+ return binding.get(binding.idFromName(topicInstanceName(streamId, topicKey)));
323
+ }
324
+ connectionStub(streamId, connectionId) {
325
+ const binding = this.env[__getLiveBindingName()];
326
+ return binding.get(binding.idFromName(connectionInstanceName(streamId, connectionId)));
327
+ }
328
+ unregisterTopic(streamId, connectionId, subscription) {
329
+ return this.topicStub(streamId, subscription.topicKey).fetch(internalUrl("/unregister"), {
330
+ method: "POST",
331
+ body: JSON.stringify({
332
+ streamId,
333
+ topic: subscription.topic,
334
+ topicKey: subscription.topicKey,
335
+ connectionId,
336
+ subscriptionId: subscription.id,
337
+ revision: subscription.revision,
338
+ generation: subscription.generation
339
+ })
340
+ });
341
+ }
342
+ }
343
+ return VoidLiveStreamDurableObject;
344
+ }
345
+ function controlBatchError(code, message, status) {
346
+ return Response.json({
347
+ accepted: false,
348
+ error: {
349
+ code,
350
+ message
351
+ }
352
+ }, { status });
353
+ }
354
+ function activeSubscriptionCount(connection) {
355
+ let count = 0;
356
+ for (const subscription of connection.subscriptions.values()) if (subscription.active) count++;
357
+ return count;
358
+ }
359
+ function isStaleSubscriber(row, connection) {
360
+ if (row.generation !== connection.generation) return true;
361
+ const subscription = connection.subscriptions.get(row.subscriptionId);
362
+ return !subscription || !subscription.active || subscription.revision !== row.revision;
363
+ }
364
+ function encodedLiveEventSize(event) {
365
+ return textEncoder.encode(JSON.stringify(event)).byteLength;
366
+ }
367
+ function payloadTooLargeResponse(maxEncodedEventSize) {
368
+ return Response.json({
369
+ accepted: false,
370
+ error: {
371
+ code: "PAYLOAD_TOO_LARGE",
372
+ message: `live: encoded event exceeds ${maxEncodedEventSize} bytes.`
373
+ }
374
+ }, { status: 413 });
375
+ }
376
+ async function fetchWithTimeout(stub, input, init, timeoutMs) {
377
+ const fetchPromise = stub.fetch(input, init);
378
+ fetchPromise.catch(() => {});
379
+ let timeout;
380
+ const timeoutPromise = new Promise((resolve) => {
381
+ timeout = setTimeout(() => resolve(null), Math.max(1, timeoutMs));
382
+ });
383
+ try {
384
+ return await Promise.race([fetchPromise, timeoutPromise]);
385
+ } catch {
386
+ return null;
387
+ } finally {
388
+ if (timeout) clearTimeout(timeout);
389
+ }
390
+ }
391
+ function withoutLimits(row) {
392
+ const { limits: _limits, ...rest } = row;
393
+ return rest;
394
+ }
395
+ function subscriberPrefix(streamId, topicKey) {
396
+ return `sub:${streamId}:${topicKey}:`;
397
+ }
398
+ function subscriberKey(row) {
399
+ return `${subscriberPrefix(row.streamId, row.topicKey)}${row.connectionId}:${row.subscriptionId}:${row.generation}:${row.revision}`;
400
+ }
401
+ async function topicDigest(streamId, topic) {
402
+ const bytes = new TextEncoder().encode(`${streamId}\u0000${topic}`);
403
+ const digest = await crypto.subtle.digest("SHA-256", bytes);
404
+ const binary = String.fromCharCode(...new Uint8Array(digest));
405
+ return btoa(binary).replaceAll("+", "-").replaceAll("/", "_").replace(/=+$/, "");
406
+ }
407
+ function connectionInstanceName(streamId, connectionId) {
408
+ return `live:${streamId}:connection:${connectionId}`;
409
+ }
410
+ function topicInstanceName(streamId, topicKey) {
411
+ return `live:${streamId}:topic:${topicKey}`;
412
+ }
413
+ function internalUrl(path) {
414
+ return `https://void.live${path}`;
415
+ }
416
+ //#endregion
417
+ export { createLiveDurableObject };
@@ -0,0 +1,107 @@
1
+ /// <reference types="@cloudflare/workers-types" />
2
+ import { r as AuthUser } from "../auth-DrfOTMmr.mjs";
3
+ import { i as CloudEnv, n as CloudContext } from "../handler-dKQWyF-G.mjs";
4
+
5
+ //#region src/runtime/live.d.ts
6
+ type MaybePromise<T> = T | Promise<T>;
7
+ type LiveControlRequest = {
8
+ connectionId: string;
9
+ operations: Array<LiveControlOperation>;
10
+ };
11
+ type LiveControlOperation = {
12
+ kind: "subscribe";
13
+ id: string;
14
+ topic: string;
15
+ lastEventId?: string;
16
+ } | {
17
+ kind: "unsubscribe";
18
+ id: string;
19
+ };
20
+ type LiveControlErrorCode = "BAD_REQUEST" | "CONNECTION_CLOSED" | "CONNECTION_NOT_FOUND" | "FORBIDDEN" | "INVALID_SUBSCRIPTION_ID" | "INVALID_TOPIC" | "OWNER_MISMATCH" | "SUBSCRIPTION_LIMIT" | "TOPIC_FULL" | "PAYLOAD_TOO_LARGE" | "INTERNAL_ERROR";
21
+ type LiveControlError = {
22
+ code: LiveControlErrorCode;
23
+ message: string;
24
+ };
25
+ type LiveControlOperationResult = {
26
+ ok: true;
27
+ kind: "subscribe" | "unsubscribe";
28
+ id: string;
29
+ topic?: string;
30
+ } | {
31
+ ok: false;
32
+ kind: "subscribe" | "unsubscribe";
33
+ id: string;
34
+ error: LiveControlError;
35
+ };
36
+ type LiveControlResponse = {
37
+ accepted: true;
38
+ connectionId: string;
39
+ results: Array<LiveControlOperationResult>;
40
+ } | {
41
+ accepted: false;
42
+ error: LiveControlError;
43
+ };
44
+ type LiveClientEvent<Data = unknown> = {
45
+ subscriptionId: string;
46
+ topic: string;
47
+ type?: string;
48
+ eventId?: string;
49
+ data: Data;
50
+ };
51
+ type LivePublishOptions = {
52
+ type?: string;
53
+ eventId?: string;
54
+ };
55
+ type LiveConnectOptions = {
56
+ owner?: string | null;
57
+ user?: unknown;
58
+ };
59
+ type LiveControlOptions = LiveConnectOptions;
60
+ type LiveHookContext = {
61
+ request: Request;
62
+ env: CloudEnv["Bindings"];
63
+ user: AuthUser | unknown | null;
64
+ owner: string | null;
65
+ };
66
+ type LiveConnectHookContext = LiveHookContext & {
67
+ connection: {
68
+ id: string;
69
+ };
70
+ };
71
+ type LiveSubscribeHookContext = LiveHookContext & {
72
+ connection: {
73
+ id: string;
74
+ };
75
+ subscription: {
76
+ id: string;
77
+ };
78
+ topic: string;
79
+ lastEventId?: string;
80
+ };
81
+ type LiveStreamOptions = {
82
+ id: string;
83
+ allowAnonymousControl?: boolean;
84
+ identifyConnection?: (ctx: LiveHookContext) => MaybePromise<string | null | undefined>;
85
+ onConnect?: (ctx: LiveConnectHookContext) => MaybePromise<Response | void>;
86
+ onSubscribe?: (ctx: LiveSubscribeHookContext) => MaybePromise<Response | void>;
87
+ limits?: Partial<LiveLimits>;
88
+ };
89
+ type LiveLimits = {
90
+ maxSubscriptionsPerConnection: number;
91
+ maxSubscriptionsPerTopic: number;
92
+ maxOperationsPerControlRequest: number;
93
+ maxQueuedEventsPerConnection: number;
94
+ maxEncodedEventSize: number;
95
+ deliveryAttemptTimeoutMs: number;
96
+ };
97
+ type LiveStream = {
98
+ connect(ctx: CloudContext, options?: LiveConnectOptions): Promise<Response>;
99
+ control(ctx: CloudContext, options?: LiveControlOptions): Promise<Response>;
100
+ publish(topic: string, data: unknown, options?: LivePublishOptions): Promise<void>;
101
+ withEnv(env: unknown): Pick<LiveStream, "publish">;
102
+ };
103
+ declare function __setLiveBindingName(name: string): void;
104
+ declare function __getLiveBindingName(): string;
105
+ declare function defineLiveStream(options: LiveStreamOptions): LiveStream;
106
+ //#endregion
107
+ export { LiveClientEvent, LiveConnectHookContext, LiveConnectOptions, LiveControlError, LiveControlErrorCode, LiveControlOperation, LiveControlOperationResult, LiveControlOptions, LiveControlRequest, LiveControlResponse, LiveHookContext, LiveLimits, LivePublishOptions, LiveStream, LiveStreamOptions, LiveSubscribeHookContext, __getLiveBindingName, __setLiveBindingName, defineLiveStream };