@mauroandre/velojs 0.0.59 → 0.0.61

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/dist/channels.js CHANGED
@@ -1,431 +1,606 @@
1
- import { DEFAULT_HEARTBEAT_MS as H } from "./events.js";
2
- import { trace as P, spanRecorder as W, byteLength as le } from "./telemetry.js";
3
- const F = "snapshot", Q = "slice", ce = "error", ue = "close", B = 50, K = 3e5;
4
- let f = {}, R = B, N = K, O = H, Y = !0;
5
- function je(e, t) {
6
- f = e ? { ...e } : {}, R = t?.coalesceMs ?? B, N = t?.idleMs ?? K, O = t?.heartbeatMs ?? H, Y = t?.logEmits ?? !0, X(), S.clear();
7
- }
8
- function Ae() {
9
- return f;
10
- }
11
- function ke() {
12
- return Object.keys(f);
13
- }
14
- const d = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Map(), b = /* @__PURE__ */ new Map();
15
- function de(e, t, n) {
16
- const o = D(e, t), r = b.get(o);
17
- if (r) {
18
- n && r.gestures.push(n);
1
+ import { DEFAULT_HEARTBEAT_MS as se } from "./events.js";
2
+ import { trace as F, byteLength as H, spanRecorder as ie } from "./telemetry.js";
3
+ const X = "snapshot", ae = "slice", Se = "error", le = "close", ce = 50, ue = 3e5;
4
+ let g = {}, Z = ce, L = ue, N = se, fe = !0;
5
+ function Pe(e, t) {
6
+ g = e ? { ...e } : {}, Z = t?.coalesceMs ?? ce, L = t?.idleMs ?? ue, N = t?.heartbeatMs ?? se, fe = t?.logEmits ?? !0, de(), O.clear(), G.clear();
7
+ }
8
+ function qe() {
9
+ return g;
10
+ }
11
+ function ze() {
12
+ return Object.keys(g);
13
+ }
14
+ const S = /* @__PURE__ */ new Map(), O = /* @__PURE__ */ new Map(), I = /* @__PURE__ */ new Map();
15
+ function Ee(e, t, r) {
16
+ const n = ee(e, t), o = I.get(n);
17
+ if (o) {
18
+ r && o.gestures.push(r);
19
19
  return;
20
20
  }
21
21
  const s = {
22
22
  timer: void 0,
23
23
  channel: e,
24
24
  partition: t,
25
- gestures: n ? [n] : []
26
- }, i = setTimeout(() => {
27
- b.delete(o), fe(s);
28
- }, R), c = i.unref;
29
- typeof c == "function" && c.call(i), s.timer = i, b.set(o, s);
30
- }
31
- async function fe(e) {
32
- const t = W(), n = await te(e.channel, e.partition, t);
33
- for (const o of e.gestures)
34
- o.addSpans(t.spans), o.end({ status: "ok", connections: n });
35
- }
36
- function X() {
37
- for (const e of b.values()) clearTimeout(e.timer);
38
- b.clear();
39
- }
40
- function Ce() {
25
+ gestures: r ? [r] : []
26
+ }, a = setTimeout(() => {
27
+ I.delete(n), Ae(s);
28
+ }, Z), u = a.unref;
29
+ typeof u == "function" && u.call(a), s.timer = a, I.set(n, s);
30
+ }
31
+ async function Ae(e) {
32
+ const t = ie(), r = await ve(e.channel, e.partition, t);
33
+ for (const n of e.gestures)
34
+ n.addSpans(t.spans), n.end({ status: "ok", connections: r });
35
+ }
36
+ function de() {
37
+ for (const e of I.values()) clearTimeout(e.timer);
38
+ I.clear();
39
+ }
40
+ function Le() {
41
41
  const e = [];
42
42
  let t = 0;
43
- for (const [o, r] of d) {
44
- const s = [];
45
- for (const [i, c] of r) {
46
- const p = /* @__PURE__ */ new Map();
47
- for (const a of c) {
48
- const u = p.get(a.moduleId) ?? { count: 0, last: void 0 };
49
- u.count += 1, a.lastDeliveryAt !== void 0 && (u.last === void 0 || a.lastDeliveryAt > u.last) && (u.last = a.lastDeliveryAt), p.set(a.moduleId, u);
43
+ const r = /* @__PURE__ */ new Map();
44
+ for (const [o, s] of S) {
45
+ const a = [];
46
+ for (const [u, v] of s) {
47
+ const l = /* @__PURE__ */ new Map();
48
+ for (const i of v) {
49
+ const f = l.get(i.moduleId) ?? { count: 0, last: void 0 };
50
+ if (f.count += 1, i.lastDeliveryAt !== void 0 && (f.last === void 0 || i.lastDeliveryAt > f.last) && (f.last = i.lastDeliveryAt), l.set(i.moduleId, f), i.kind === "live" && i.liveId) {
51
+ let h = r.get(i.liveId);
52
+ if (h || (h = {
53
+ moduleId: i.moduleId,
54
+ action: i.actionName ?? "(anonymous)",
55
+ channels: [],
56
+ args: i.args ? { ...i.args } : null,
57
+ lastDeliveryAt: null
58
+ }, r.set(i.liveId, h)), h.channels.push({ channel: o, partition: u }), i.lastDeliveryAt !== void 0) {
59
+ const w = new Date(i.lastDeliveryAt).toISOString();
60
+ (h.lastDeliveryAt === null || w > h.lastDeliveryAt) && (h.lastDeliveryAt = w);
61
+ }
62
+ } else i.kind !== "live" && (t += 1);
50
63
  }
51
- for (const [a, u] of p)
52
- s.push({
53
- moduleId: a,
54
- partition: i,
55
- connections: u.count,
56
- lastDeliveryAt: u.last === void 0 ? null : new Date(u.last).toISOString()
64
+ for (const [i, f] of l)
65
+ a.push({
66
+ moduleId: i,
67
+ partition: u,
68
+ connections: f.count,
69
+ lastDeliveryAt: f.last === void 0 ? null : new Date(f.last).toISOString()
57
70
  });
58
71
  }
59
72
  e.push({
60
73
  channel: o,
61
- groups: s,
62
- connections: U(r)
63
- }), t += U(r);
74
+ groups: a,
75
+ connections: be(s)
76
+ });
64
77
  }
78
+ t += r.size;
65
79
  const n = [];
66
- for (const o of b.values())
80
+ for (const o of I.values())
67
81
  n.push({ channel: o.channel, partition: o.partition });
68
- return { channels: e, openCoalesceWindows: n, totalConnections: t };
82
+ return {
83
+ channels: e,
84
+ openCoalesceWindows: n,
85
+ liveActions: [...r.values()],
86
+ totalConnections: t
87
+ };
69
88
  }
70
- function U(e) {
89
+ function be(e) {
71
90
  let t = 0;
72
- for (const n of e.values()) t += n.size;
91
+ for (const r of e.values()) t += r.size;
73
92
  return t;
74
93
  }
75
- function D(e, t) {
94
+ function ee(e, t) {
76
95
  return `${e}\0${t}`;
77
96
  }
78
97
  function pe(e) {
79
- let t = d.get(e.channel);
80
- t || (t = /* @__PURE__ */ new Map(), d.set(e.channel, t));
81
- let n = t.get(e.partition);
82
- n || (n = /* @__PURE__ */ new Set(), t.set(e.partition, n));
83
- const o = n.size === 0;
84
- return n.add(e), o;
85
- }
86
- function V(e) {
87
- const t = d.get(e.channel), n = t?.get(e.partition);
88
- if (!t || !n) return !1;
89
- n.delete(e);
90
- const o = n.size === 0;
91
- return o && t.delete(e.partition), t.size === 0 && d.delete(e.channel), o;
92
- }
93
- function Z(e, t, n) {
94
- const o = D(e, t), r = f[e]?.onGroupOpen, s = (async () => {
95
- if (typeof r == "function")
98
+ let t = S.get(e.channel);
99
+ t || (t = /* @__PURE__ */ new Map(), S.set(e.channel, t));
100
+ let r = t.get(e.partition);
101
+ r || (r = /* @__PURE__ */ new Set(), t.set(e.partition, r));
102
+ const n = r.size === 0;
103
+ return r.add(e), n;
104
+ }
105
+ function ne(e) {
106
+ const t = S.get(e.channel), r = t?.get(e.partition);
107
+ if (!t || !r) return !1;
108
+ r.delete(e);
109
+ const n = r.size === 0;
110
+ return n && t.delete(e.partition), t.size === 0 && S.delete(e.channel), n;
111
+ }
112
+ const G = /* @__PURE__ */ new Map();
113
+ function te(e, t, r) {
114
+ const n = ee(e, t), o = g[e]?.onGroupOpen;
115
+ G.set(n, r);
116
+ const s = (async () => {
117
+ if (typeof o == "function")
96
118
  try {
97
- await r({ partition: t, params: n });
98
- } catch (i) {
119
+ await o({ partition: t, params: r.params, args: r.args });
120
+ } catch (a) {
99
121
  console.error(
100
122
  `[velojs] channel "${e}" onGroupOpen failed for partition "${t}":`,
101
- i
123
+ a
102
124
  );
103
125
  }
104
126
  })();
105
- return S.set(o, s), s.then(() => {
106
- S.get(o) === s && S.delete(o);
127
+ return O.set(n, s), s.then(() => {
128
+ O.get(n) === s && O.delete(n);
107
129
  }), s;
108
130
  }
109
- async function me(e) {
110
- const t = D(e.channel, e.partition), n = S.get(t);
111
- n && await n;
112
- const o = d.get(e.channel)?.get(e.partition);
113
- if (!o || !o.has(e) || o.size > 1) {
114
- V(e);
131
+ async function he(e) {
132
+ const t = ee(e.channel, e.partition), r = O.get(t);
133
+ r && await r;
134
+ const n = S.get(e.channel)?.get(e.partition);
135
+ if (!n || !n.has(e) || n.size > 1) {
136
+ ne(e);
115
137
  return;
116
138
  }
117
- const r = f[e.channel]?.onGroupClose;
118
- if (typeof r == "function")
139
+ const o = g[e.channel]?.onGroupClose, s = G.get(t) ?? { params: e.params };
140
+ if (typeof o == "function")
119
141
  try {
120
- await r({ partition: e.partition });
121
- } catch (c) {
142
+ await o({ partition: e.partition, args: s.args });
143
+ } catch (v) {
122
144
  console.error(
123
145
  `[velojs] channel "${e.channel}" onGroupClose failed for partition "${e.partition}":`,
124
- c
146
+ v
125
147
  );
126
148
  }
127
- V(e);
128
- const s = d.get(e.channel)?.get(e.partition), i = s ? [...s][0] : void 0;
129
- i && await Z(e.channel, e.partition, i.params);
149
+ ne(e);
150
+ const a = S.get(e.channel)?.get(e.partition), u = a ? [...a][0] : void 0;
151
+ u ? await te(e.channel, e.partition, {
152
+ params: u.params,
153
+ args: u.args
154
+ }) : G.delete(t);
130
155
  }
131
- function Te() {
132
- d.clear(), S.clear(), X();
156
+ function Ne() {
157
+ S.clear(), O.clear(), G.clear(), de();
133
158
  }
134
- async function T(e, t) {
135
- const n = e.scope;
136
- return typeof n != "function" ? "all" : await n(t);
159
+ async function x(e, t) {
160
+ const r = e.scope;
161
+ return typeof r != "function" ? "all" : await r(t);
137
162
  }
138
- function he(e, t) {
163
+ function ye(e, t) {
139
164
  return e.get(t);
140
165
  }
141
- async function ee(e, t) {
142
- const n = d.get(e)?.get(t);
143
- if (!n || n.size === 0) return null;
144
- const o = f[e], r = [];
145
- for (const s of [...n]) {
146
- let i;
166
+ async function me(e, t) {
167
+ const r = S.get(e)?.get(t);
168
+ if (!r || r.size === 0) return null;
169
+ const n = g[e], o = [];
170
+ for (const s of [...r]) {
171
+ let a;
147
172
  try {
148
- i = await T(o, {
149
- user: s.principal,
150
- params: s.params
151
- });
152
- } catch (c) {
153
- console.error(`[velojs] channel "${e}" scope threw on emit:`, c), i = null;
173
+ a = await x(n, je(s));
174
+ } catch (u) {
175
+ console.error(`[velojs] channel "${e}" scope threw on emit:`, u), a = null;
154
176
  }
155
- if (i == null || i !== t) {
177
+ if (a == null || a !== t) {
156
178
  await s.terminate();
157
179
  continue;
158
180
  }
159
- r.push(s);
181
+ o.push(s);
160
182
  }
161
- return r.length > 0 ? r : null;
162
- }
163
- async function te(e, t, n) {
164
- const o = await ee(e, t);
165
- return o ? (await Promise.all(
166
- o.map(async (r) => {
167
- const s = n.span(`loader:${r.moduleId}`), i = await ne(r);
168
- s.end(i);
183
+ return o.length > 0 ? o : null;
184
+ }
185
+ function je(e) {
186
+ return e.kind === "live" ? { user: e.principal, args: e.args } : { user: e.principal, params: e.params };
187
+ }
188
+ async function ve(e, t, r) {
189
+ const n = await me(e, t);
190
+ return n ? (await Promise.all(
191
+ n.map(async (o) => {
192
+ const s = r.span(ke(o)), a = await re(o);
193
+ s.end(a);
169
194
  })
170
- ), o.length) : 0;
195
+ ), n.length) : 0;
171
196
  }
172
- async function ne(e) {
173
- let t;
174
- try {
175
- t = await e.loader({
197
+ function ke(e) {
198
+ return e.kind === "live" ? `action:${e.moduleId}/${e.actionName ?? "anonymous"}` : `loader:${e.moduleId}`;
199
+ }
200
+ async function Te(e) {
201
+ if (e.kind === "live") {
202
+ if (typeof e.action != "function")
203
+ throw new Error("[velojs] live action connection has no action");
204
+ return e.action({
205
+ body: e.args ?? {},
176
206
  params: e.params,
177
207
  query: e.query,
178
208
  c: e.c
179
209
  });
180
- } catch (n) {
210
+ }
211
+ if (typeof e.loader != "function")
212
+ throw new Error("[velojs] channel connection has no loader");
213
+ return e.loader({ params: e.params, query: e.query, c: e.c });
214
+ }
215
+ async function re(e) {
216
+ let t;
217
+ try {
218
+ t = await Te(e);
219
+ } catch (r) {
181
220
  return await e.send(
182
- ce,
221
+ Se,
183
222
  JSON.stringify({
184
- message: n instanceof Error ? n.message : String(n)
223
+ message: r instanceof Error ? r.message : String(r)
185
224
  })
186
225
  ), "error";
187
226
  }
188
- return t instanceof Response || await e.send(F, JSON.stringify(t ?? null)), "ok";
227
+ return t instanceof Response || await e.send(X, JSON.stringify(t ?? null)), "ok";
189
228
  }
190
- function _e(e, t, n, o) {
191
- return typeof e == "string" ? ye(e, t ?? {}) : we(e, t, n, o);
229
+ function Ge(e, t, r, n) {
230
+ return typeof e == "string" ? De(e, t ?? {}) : Ce(e, t, r, n);
192
231
  }
193
- async function ye(e, t) {
194
- const n = f[e];
195
- if (!n)
232
+ async function De(e, t) {
233
+ const r = g[e];
234
+ if (!r)
196
235
  throw new Error(
197
236
  `[velojs] emit("${e}"): this channel has no entry in app/channels.ts. Add one — a typo or a renamed channel would otherwise be a silent no-op.`
198
237
  );
199
- const o = await T(n, t), r = o == null ? 0 : d.get(e)?.get(o)?.size ?? 0;
200
- oe(e, o, "invalidate", r);
201
- const s = P("emit", {
238
+ const n = await x(r, t), o = n == null ? 0 : S.get(e)?.get(n)?.size ?? 0;
239
+ ge(e, n, "invalidate", o);
240
+ const s = F("emit", {
202
241
  channel: e,
203
- partition: o ?? null,
242
+ partition: n ?? null,
204
243
  mode: "invalidate",
205
- connections: r
244
+ connections: o
206
245
  });
207
- if (o == null) {
246
+ if (n == null) {
208
247
  s.end({ status: "ok", connections: 0 });
209
248
  return;
210
249
  }
211
- if (r === 0) {
250
+ if (o === 0) {
212
251
  s.end({ status: "ok", connections: 0 });
213
252
  return;
214
253
  }
215
- if (R <= 0) {
216
- const i = W(), c = await te(e, o, i);
217
- s.addSpans(i.spans), s.end({ status: "ok", connections: c });
254
+ if (Z <= 0) {
255
+ const a = ie(), u = await ve(e, n, a);
256
+ s.addSpans(a.spans), s.end({ status: "ok", connections: u });
218
257
  return;
219
258
  }
220
- de(e, o, s);
259
+ Ee(e, n, s);
221
260
  }
222
- async function we(e, t, n, o) {
223
- const r = e?.metadata?.moduleId;
224
- if (!r)
261
+ async function Ce(e, t, r, n) {
262
+ const o = e?.metadata?.moduleId;
263
+ if (!o)
225
264
  throw new Error(
226
265
  `[velojs] emit(module, "${t}", …): the module has no metadata.moduleId — pass the imported route module (the Vite plugin injects its metadata), the same object the route tree uses.`
227
266
  );
228
267
  const s = e.channels;
229
268
  if (!Array.isArray(s) || !s.includes(t))
230
269
  throw new Error(
231
- `[velojs] emit(module, "${t}", …): module "${r}" does not declare channel "${t}" — add it to the module's \`channels\` export, or use emit("${t}", ctx) for the invalidation mode.`
270
+ `[velojs] emit(module, "${t}", …): module "${o}" does not declare channel "${t}" — add it to the module's \`channels\` export, or use emit("${t}", ctx) for the invalidation mode.`
232
271
  );
233
272
  if (typeof e.loader != "function")
234
273
  throw new Error(
235
- `[velojs] emit(module, "${t}", …): module "${r}" has no \`loader\` — there is no data shape to slice.`
274
+ `[velojs] emit(module, "${t}", …): module "${o}" has no \`loader\` — there is no data shape to slice.`
236
275
  );
237
- const i = f[t];
238
- if (!i)
276
+ const a = g[t];
277
+ if (!a)
239
278
  throw new Error(
240
279
  `[velojs] emit(module, "${t}", …): this channel has no entry in app/channels.ts. Add one — a typo or a renamed channel would otherwise be a silent no-op.`
241
280
  );
242
- if (o === null || typeof o != "object" || Array.isArray(o))
281
+ if (n === null || typeof n != "object" || Array.isArray(n))
243
282
  throw new Error(
244
- `[velojs] emit(module, "${t}", …): the slice must be the object of changed keys — got ${o === null ? "null" : Array.isArray(o) ? "an array" : typeof o}.`
283
+ `[velojs] emit(module, "${t}", …): the slice must be the object of changed keys — got ${n === null ? "null" : Array.isArray(n) ? "an array" : typeof n}.`
245
284
  );
246
- const c = await T(i, n), p = c == null ? void 0 : d.get(t)?.get(c), a = p?.size ?? 0;
247
- oe(t, c, "slice", a);
248
- const u = P("emit", {
285
+ const u = await x(a, r), v = u == null ? void 0 : S.get(t)?.get(u), l = v?.size ?? 0;
286
+ ge(t, u, "slice", l);
287
+ const i = F("emit", {
249
288
  channel: t,
250
- partition: c ?? null,
289
+ partition: u ?? null,
251
290
  mode: "slice",
252
- connections: a
291
+ connections: l
253
292
  });
254
- if (c == null) {
255
- u.end({ status: "ok", connections: 0 });
293
+ if (u == null) {
294
+ i.end({ status: "ok", connections: 0 });
256
295
  return;
257
296
  }
258
- if (!p || a === 0) {
259
- u.end({ status: "ok", connections: 0 });
297
+ if (!v || l === 0) {
298
+ i.end({ status: "ok", connections: 0 });
260
299
  return;
261
300
  }
262
- const m = await ee(t, c);
263
- if (!m) {
264
- u.end({ status: "ok", connections: 0 });
301
+ const f = await me(t, u);
302
+ if (!f) {
303
+ i.end({ status: "ok", connections: 0 });
265
304
  return;
266
305
  }
267
- const y = m.filter((E) => E.moduleId === r);
268
- if (y.length === 0) {
269
- u.end({ status: "ok", connections: 0 });
306
+ const h = f.filter(
307
+ (E) => E.moduleId === o && E.kind !== "live"
308
+ );
309
+ if (h.length === 0) {
310
+ i.end({ status: "ok", connections: 0 });
270
311
  return;
271
312
  }
272
- const j = JSON.stringify(o);
273
- await Promise.all(y.map((E) => E.send(Q, j))), u.end({ status: "ok", connections: y.length });
313
+ const w = JSON.stringify(n);
314
+ await Promise.all(h.map((E) => E.send(ae, w))), i.end({ status: "ok", connections: h.length });
274
315
  }
275
- function oe(e, t, n, o) {
276
- if (!Y) return;
277
- const r = typeof t == "string" ? `"${t}"` : "null";
316
+ function ge(e, t, r, n) {
317
+ if (!fe) return;
318
+ const o = typeof t == "string" ? `"${t}"` : "null";
278
319
  console.log(
279
- `[velojs] emit kind=${n} channel="${e}" partition=${r} connections=${o} at=${(/* @__PURE__ */ new Date()).toISOString()}`
320
+ `[velojs] emit kind=${r} channel="${e}" partition=${o} connections=${n} at=${(/* @__PURE__ */ new Date()).toISOString()}`
280
321
  );
281
322
  }
282
- function ge(e, t) {
283
- let n = Promise.resolve();
284
- return (o) => (n = n.then(() => t(o)).then(() => {
285
- }).catch((r) => {
323
+ function we(e, t) {
324
+ let r = Promise.resolve();
325
+ return (n) => (r = r.then(() => t(n)).then(() => {
326
+ }).catch((o) => {
286
327
  console.warn(
287
328
  `[velojs] channel "${e}": SSE write failed — the snapshot did not reach the client:`,
288
- r
329
+ o
289
330
  );
290
- }), n);
331
+ }), r);
291
332
  }
292
- const C = "_route";
293
- function ve(e) {
333
+ const W = "_route";
334
+ function _e(e) {
294
335
  return e ? e.split("/").filter((t) => t.startsWith(":")).map((t) => t.slice(1)) : [];
295
336
  }
296
- function Ee(e, t) {
337
+ function Oe(e, t) {
297
338
  if (e == null || e === "")
298
339
  return { params: {}, error: null };
299
- let n;
340
+ let r;
300
341
  try {
301
- n = JSON.parse(e);
342
+ r = JSON.parse(e);
302
343
  } catch {
303
- return { params: {}, error: `the ?${C}= payload is not valid JSON` };
344
+ return { params: {}, error: `the ?${W}= payload is not valid JSON` };
304
345
  }
305
- if (n === null || typeof n != "object" || Array.isArray(n))
346
+ if (r === null || typeof r != "object" || Array.isArray(r))
306
347
  return {
307
348
  params: {},
308
- error: `the ?${C}= payload must be an object of route params`
349
+ error: `the ?${W}= payload must be an object of route params`
309
350
  };
310
- const o = {};
311
- for (const [r, s] of Object.entries(n)) {
312
- if (!t.includes(r)) {
313
- const i = t.length > 0 ? t.join(", ") : "none";
351
+ const n = {};
352
+ for (const [o, s] of Object.entries(r)) {
353
+ if (!t.includes(o)) {
354
+ const a = t.length > 0 ? t.join(", ") : "none";
314
355
  return {
315
356
  params: {},
316
- error: `route param "${r}" is not declared by the module's path (declared: ${i})`
357
+ error: `route param "${o}" is not declared by the module's path (declared: ${a})`
317
358
  };
318
359
  }
319
360
  if (typeof s != "string")
320
- return { params: {}, error: `route param "${r}" must be a URL string` };
321
- o[r] = s;
361
+ return { params: {}, error: `route param "${o}" must be a URL string` };
362
+ n[o] = s;
322
363
  }
323
- return { params: o, error: null };
364
+ return { params: n, error: null };
324
365
  }
325
- function Me(e, t, n, o, r, s) {
326
- if (typeof o.loader != "function")
366
+ function xe(e, t, r, n, o, s) {
367
+ if (typeof n.loader != "function")
327
368
  throw new Error(
328
- `[velojs] module "${r}" declares \`channels\` without a \`loader\` — there is nothing to synchronize. Add a loader or remove the export.`
369
+ `[velojs] module "${o}" declares \`channels\` without a \`loader\` — there is nothing to synchronize. Add a loader or remove the export.`
329
370
  );
330
- if (!f[n])
371
+ if (!g[r])
331
372
  throw new Error(
332
- `[velojs] module "${r}" declares channel "${n}" with no entry in app/channels.ts — add the partition resolver for "${n}".`
373
+ `[velojs] module "${o}" declares channel "${r}" with no entry in app/channels.ts — add the partition resolver for "${r}".`
333
374
  );
334
- const i = o.loader, c = ve(o.metadata?.fullPath), p = async (a) => {
335
- const u = f[n], m = P("channel-connect", { route: t, module: r, channel: n }), y = Ee(
336
- a.req.query(C),
337
- c
375
+ const a = n.loader, u = _e(n.metadata?.fullPath), v = async (l) => {
376
+ const i = g[r], f = F("channel-connect", { route: t, module: o, channel: r }), h = Oe(
377
+ l.req.query(W),
378
+ u
338
379
  );
339
- if (y.error)
340
- return console.error(`[velojs] channel "${n}": rejecting subscription — ${y.error}`), m.end({ status: "error" }), a.json({ error: "invalid-route-params", message: y.error }, 400);
341
- const j = y.params, E = he(a, "user");
342
- let A;
380
+ if (h.error)
381
+ return console.error(`[velojs] channel "${r}": rejecting subscription — ${h.error}`), f.end({ status: "error" }), l.json({ error: "invalid-route-params", message: h.error }, 400);
382
+ const w = h.params, E = ye(l, "user");
383
+ let T;
343
384
  try {
344
- A = await T(u, { user: E, params: j });
345
- } catch (w) {
346
- return console.error(`[velojs] channel "${n}" scope threw:`, w), m.end({ status: "error" }), a.json({ error: "forbidden" }, 403);
385
+ T = await x(i, { user: E, params: w });
386
+ } catch (p) {
387
+ return console.error(`[velojs] channel "${r}" scope threw:`, p), f.end({ status: "error" }), l.json({ error: "forbidden" }, 403);
347
388
  }
348
- if (A == null)
349
- return m.end({ status: "error" }), a.json({ error: "forbidden" }, 403);
350
- const { streamSSE: re } = await import("hono/streaming"), I = {};
351
- for (const [w, h] of Object.entries(a.req.query()))
352
- w !== C && (I[w] = h);
353
- const k = await re(a, async (w) => {
354
- let h = !1, L = () => {
389
+ if (T == null)
390
+ return f.end({ status: "error" }), l.json({ error: "forbidden" }, 403);
391
+ const { streamSSE: Y } = await import("hono/streaming"), R = {};
392
+ for (const [p, y] of Object.entries(l.req.query()))
393
+ p !== W && (R[p] = y);
394
+ const b = await Y(l, async (p) => {
395
+ let y = !1, j = () => {
355
396
  };
356
- const se = new Promise((l) => {
357
- L = l;
358
- }), _ = ge(
359
- n,
360
- (l) => typeof l == "string" ? w.write(l) : w.writeSSE(l)
361
- ), g = {
362
- channel: n,
363
- partition: A,
364
- moduleId: r,
397
+ const P = new Promise((d) => {
398
+ j = d;
399
+ }), D = we(
400
+ r,
401
+ (d) => typeof d == "string" ? p.write(d) : p.writeSSE(d)
402
+ ), A = {
403
+ channel: r,
404
+ partition: T,
405
+ moduleId: o,
365
406
  principal: E,
366
- loader: i,
367
- c: a,
368
- params: j,
369
- query: I,
370
- telemetry: m,
371
- send: (l, M) => h ? Promise.resolve() : l === F || l === Q ? (g.telemetry?.enabled && g.telemetry.delivery(le(M)), _({ event: l, data: M }).then(() => {
372
- h || (g.lastDeliveryAt = Date.now(), x());
373
- })) : _({ event: l, data: M }),
374
- terminate: (l) => q(l)
375
- }, G = () => {
376
- h || (h = !0, v !== null && clearTimeout(v), $ !== null && clearInterval($), L(), g.telemetry?.close(), me(g));
377
- }, q = async (l = "partition") => {
378
- h || (await g.send(ue, JSON.stringify({ reason: l })), G());
379
- };
380
- let v = null;
381
- const x = () => {
382
- if (N <= 0 || h) return;
383
- v !== null && clearTimeout(v), v = setTimeout(() => {
384
- v = null, q("idle");
385
- }, N);
386
- const l = v.unref;
387
- typeof l == "function" && l.call(v);
407
+ loader: a,
408
+ c: l,
409
+ params: w,
410
+ query: R,
411
+ telemetry: f,
412
+ send: (d, c) => y ? Promise.resolve() : d === X || d === ae ? (A.telemetry?.enabled && A.telemetry.delivery(H(c)), D({ event: d, data: c }).then(() => {
413
+ y || (A.lastDeliveryAt = Date.now(), z());
414
+ })) : D({ event: d, data: c }),
415
+ terminate: (d) => q(d)
416
+ }, C = () => {
417
+ y || (y = !0, $ !== null && clearTimeout($), m !== null && clearInterval(m), j(), A.telemetry?.close(), he(A));
418
+ }, q = async (d = "partition") => {
419
+ y || (await A.send(le, JSON.stringify({ reason: d })), C());
388
420
  };
389
421
  let $ = null;
390
- O > 0 && ($ = setInterval(() => {
391
- h || _(`: ping
422
+ const z = () => {
423
+ if (L <= 0 || y) return;
424
+ $ !== null && clearTimeout($), $ = setTimeout(() => {
425
+ $ = null, q("idle");
426
+ }, L);
427
+ const d = $.unref;
428
+ typeof d == "function" && d.call($);
429
+ };
430
+ let m = null;
431
+ N > 0 && (m = setInterval(() => {
432
+ y || D(`: ping
392
433
 
393
434
  `);
394
- }, O));
395
- const ie = pe(g);
396
- if (w.onAbort(G), x(), $ !== null) {
397
- const l = $.unref;
398
- typeof l == "function" && l.call($);
435
+ }, N));
436
+ const J = pe(A);
437
+ if (p.onAbort(C), z(), m !== null) {
438
+ const d = m.unref;
439
+ typeof d == "function" && d.call(m);
399
440
  }
400
- ie && await Z(n, A, j);
401
- const ae = m.span("snapshot"), J = await ne(g);
402
- ae.end(J), m.end({ status: J }), await se;
403
- }), z = new Headers(k.headers);
404
- return z.set("Cache-Control", "no-store"), new Response(k.body, {
405
- status: k.status,
406
- statusText: k.statusText,
407
- headers: z
441
+ J && await te(r, T, { params: w });
442
+ const k = f.span("snapshot"), V = await re(A);
443
+ k.end(V), f.end({ status: V }), await P;
444
+ }), M = new Headers(b.headers);
445
+ return M.set("Cache-Control", "no-store"), new Response(b.body, {
446
+ status: b.status,
447
+ statusText: b.statusText,
448
+ headers: M
449
+ });
450
+ };
451
+ s.length > 0 ? e.on(["GET"], [t], ...s, v) : e.on(["GET"], [t], v);
452
+ }
453
+ const Q = "_args", K = 4096;
454
+ function Ie(e) {
455
+ if (e == null || e === "")
456
+ return { args: {}, error: null };
457
+ let t;
458
+ try {
459
+ t = JSON.parse(e);
460
+ } catch {
461
+ return { args: {}, error: `the ?${Q}= payload is not valid JSON` };
462
+ }
463
+ return t === null || typeof t != "object" || Array.isArray(t) ? {
464
+ args: {},
465
+ error: `the ?${Q}= payload must be an object of the action's arguments`
466
+ } : { args: t, error: null };
467
+ }
468
+ let oe = 0;
469
+ function Je(e, t, r, n, o, s, a) {
470
+ const u = o[`action_${r}`];
471
+ if (typeof u != "function")
472
+ throw new Error(
473
+ `[velojs] module "${s}" declares liveActions.${r} but has no \`export const action_${r}\` — there is nothing to synchronize. Add the action or remove the entry.`
474
+ );
475
+ for (const l of n)
476
+ if (!g[l])
477
+ throw new Error(
478
+ `[velojs] module "${s}" liveActions.${r} declares channel "${l}" with no entry in app/channels.ts — add the partition resolver for "${l}".`
479
+ );
480
+ const v = async (l) => {
481
+ const i = F("live-action-connect", { route: t, module: s, name: r }), f = Ie(l.req.query(Q));
482
+ if (f.error)
483
+ return console.error(
484
+ `[velojs] live action "${s}/${r}": rejecting subscription — ` + f.error
485
+ ), i.end({ status: "error" }), l.json({ error: "invalid-args", message: f.error }, 400);
486
+ const h = f.args, w = JSON.stringify(h);
487
+ if (H(w) > K) {
488
+ const p = `[velojs] live action "${s}/${r}": the serialized args are ${H(w)} bytes — the limit is ${K}. Pass less data (an id, not the document) — the args are the tab's address.`;
489
+ return console.error(p), i.end({ status: "error" }), l.json(
490
+ { error: "args-too-large", message: p, limit: K },
491
+ 400
492
+ );
493
+ }
494
+ const E = ye(l, "user"), T = [];
495
+ for (const p of n) {
496
+ const y = g[p];
497
+ let j;
498
+ try {
499
+ j = await x(y, { user: E, args: h });
500
+ } catch (P) {
501
+ return console.error(`[velojs] channel "${p}" scope threw:`, P), i.end({ status: "error" }), l.json({ error: "forbidden" }, 403);
502
+ }
503
+ if (j == null)
504
+ return i.end({ status: "error" }), l.json({ error: "forbidden" }, 403);
505
+ T.push({ channel: p, partition: j });
506
+ }
507
+ const { streamSSE: Y } = await import("hono/streaming"), R = {};
508
+ for (const [p, y] of Object.entries(l.req.query()))
509
+ p !== Q && (R[p] = y);
510
+ const b = await Y(l, async (p) => {
511
+ let y = !1, j = () => {
512
+ };
513
+ const P = new Promise((c) => {
514
+ j = c;
515
+ }), D = we(
516
+ `${s}/${r}`,
517
+ (c) => typeof c == "string" ? p.write(c) : p.writeSSE(c)
518
+ );
519
+ oe += 1;
520
+ const A = `live-${oe}`, C = T.map(({ channel: c, partition: _ }) => ({
521
+ channel: c,
522
+ partition: _,
523
+ moduleId: s,
524
+ kind: "live",
525
+ principal: E,
526
+ action: u,
527
+ actionName: r,
528
+ args: h,
529
+ liveId: A,
530
+ c: l,
531
+ params: {},
532
+ query: R,
533
+ telemetry: i,
534
+ send: (U, B) => q(U, B),
535
+ terminate: (U) => z(U)
536
+ })), q = (c, _) => y ? Promise.resolve() : c === X ? (i.enabled && i.delivery(H(_)), D({ event: c, data: _ }).then(() => {
537
+ if (y) return;
538
+ const B = Date.now();
539
+ for (const $e of C) $e.lastDeliveryAt = B;
540
+ J();
541
+ })) : D({ event: c, data: _ }), $ = () => {
542
+ if (!y) {
543
+ y = !0, m !== null && clearTimeout(m), k !== null && clearInterval(k), j(), i.close();
544
+ for (const c of C) he(c);
545
+ }
546
+ }, z = async (c = "partition") => {
547
+ y || (await q(le, JSON.stringify({ reason: c })), $());
548
+ };
549
+ let m = null;
550
+ const J = () => {
551
+ if (L <= 0 || y) return;
552
+ m !== null && clearTimeout(m), m = setTimeout(() => {
553
+ m = null, z("idle");
554
+ }, L);
555
+ const c = m.unref;
556
+ typeof c == "function" && c.call(m);
557
+ };
558
+ let k = null;
559
+ if (N > 0 && (k = setInterval(() => {
560
+ y || D(`: ping
561
+
562
+ `);
563
+ }, N)), p.onAbort($), J(), k !== null) {
564
+ const c = k.unref;
565
+ typeof c == "function" && c.call(k);
566
+ }
567
+ for (const c of C)
568
+ pe(c) && await te(c.channel, c.partition, {
569
+ params: {},
570
+ args: h
571
+ });
572
+ const V = i.span("snapshot"), d = await re(C[0]);
573
+ V.end(d), i.end({ status: d }), await P;
574
+ }), M = new Headers(b.headers);
575
+ return M.set("Cache-Control", "no-store"), new Response(b.body, {
576
+ status: b.status,
577
+ statusText: b.statusText,
578
+ headers: M
408
579
  });
409
580
  };
410
- s.length > 0 ? e.on(["GET"], [t], ...s, p) : e.on(["GET"], [t], p);
581
+ a.length > 0 ? e.on(["GET"], [t], ...a, v) : e.on(["GET"], [t], v);
411
582
  }
412
583
  export {
413
- ue as CHANNEL_CLOSE_EVENT,
414
- ce as CHANNEL_ERROR_EVENT,
415
- B as DEFAULT_COALESCE_MS,
416
- K as DEFAULT_IDLE_MS,
417
- C as ROUTE_PARAMS_QUERY,
418
- Q as SLICE_EVENT,
419
- F as SNAPSHOT_EVENT,
420
- Te as __resetChannels,
421
- ke as channelNames,
422
- ge as createChannelWriteChain,
423
- ve as declaredRouteParams,
424
- _e as emit,
425
- Ae as getChannelMap,
426
- Ce as inspectChannels,
427
- Ee as parseRouteParamsQuery,
428
- ne as pushSnapshot,
429
- Me as registerChannelRoute,
430
- je as registerChannels
584
+ le as CHANNEL_CLOSE_EVENT,
585
+ Se as CHANNEL_ERROR_EVENT,
586
+ ce as DEFAULT_COALESCE_MS,
587
+ ue as DEFAULT_IDLE_MS,
588
+ K as LIVE_ARGS_MAX_BYTES,
589
+ Q as LIVE_ARGS_QUERY,
590
+ W as ROUTE_PARAMS_QUERY,
591
+ ae as SLICE_EVENT,
592
+ X as SNAPSHOT_EVENT,
593
+ Ne as __resetChannels,
594
+ ze as channelNames,
595
+ we as createChannelWriteChain,
596
+ _e as declaredRouteParams,
597
+ Ge as emit,
598
+ qe as getChannelMap,
599
+ Le as inspectChannels,
600
+ Ie as parseLiveArgsQuery,
601
+ Oe as parseRouteParamsQuery,
602
+ re as pushSnapshot,
603
+ xe as registerChannelRoute,
604
+ Pe as registerChannels,
605
+ Je as registerLiveActionRoute
431
606
  };