api-ape 2.1.0 → 2.2.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.
Files changed (87) hide show
  1. package/README.md +184 -195
  2. package/client/README.md +37 -30
  3. package/client/browser.js +4 -14
  4. package/client/connectSocket.js +167 -42
  5. package/client/index.js +171 -0
  6. package/client/transports/streaming.js +3 -16
  7. package/dist/ape.js +2 -1049
  8. package/dist/ape.js.map +7 -0
  9. package/dist/api-ape.min.js +2 -0
  10. package/dist/api-ape.min.js.map +7 -0
  11. package/index.d.ts +67 -23
  12. package/package.json +27 -8
  13. package/server/README.md +52 -11
  14. package/server/lib/broadcast.js +25 -8
  15. package/server/lib/bun.js +122 -0
  16. package/server/lib/longPolling.js +28 -23
  17. package/server/lib/main.js +372 -46
  18. package/server/lib/wiring.js +19 -12
  19. package/server/lib/ws/adapters/bun.js +225 -0
  20. package/server/lib/ws/adapters/deno.js +186 -0
  21. package/server/lib/ws/frames.js +217 -0
  22. package/server/lib/ws/index.js +15 -0
  23. package/server/lib/ws/server.js +109 -0
  24. package/server/lib/ws/socket.js +222 -0
  25. package/server/lib/wsProvider.js +135 -0
  26. package/server/socket/receive.js +14 -1
  27. package/server/socket/send.js +6 -6
  28. package/server/utils/parseUserAgent.js +286 -0
  29. package/example/Bun/README.md +0 -74
  30. package/example/Bun/api/message.ts +0 -11
  31. package/example/Bun/index.html +0 -76
  32. package/example/Bun/package.json +0 -9
  33. package/example/Bun/server.ts +0 -59
  34. package/example/Bun/styles.css +0 -128
  35. package/example/ExpressJs/README.md +0 -95
  36. package/example/ExpressJs/api/message.js +0 -11
  37. package/example/ExpressJs/backend.js +0 -39
  38. package/example/ExpressJs/index.html +0 -88
  39. package/example/ExpressJs/package-lock.json +0 -834
  40. package/example/ExpressJs/package.json +0 -10
  41. package/example/ExpressJs/styles.css +0 -128
  42. package/example/NextJs/.dockerignore +0 -29
  43. package/example/NextJs/Dockerfile +0 -52
  44. package/example/NextJs/Dockerfile.dev +0 -27
  45. package/example/NextJs/README.md +0 -113
  46. package/example/NextJs/ape/client.js +0 -66
  47. package/example/NextJs/ape/embed.js +0 -12
  48. package/example/NextJs/ape/index.js +0 -23
  49. package/example/NextJs/ape/logic/chat.js +0 -62
  50. package/example/NextJs/ape/onConnect.js +0 -69
  51. package/example/NextJs/ape/onDisconnect.js +0 -13
  52. package/example/NextJs/ape/onError.js +0 -9
  53. package/example/NextJs/ape/onReceive.js +0 -15
  54. package/example/NextJs/ape/onSend.js +0 -15
  55. package/example/NextJs/api/message.js +0 -44
  56. package/example/NextJs/docker-compose.yml +0 -22
  57. package/example/NextJs/next-env.d.ts +0 -5
  58. package/example/NextJs/next.config.js +0 -8
  59. package/example/NextJs/package-lock.json +0 -6400
  60. package/example/NextJs/package.json +0 -24
  61. package/example/NextJs/pages/Info.tsx +0 -153
  62. package/example/NextJs/pages/_app.tsx +0 -6
  63. package/example/NextJs/pages/index.tsx +0 -275
  64. package/example/NextJs/public/favicon.ico +0 -0
  65. package/example/NextJs/public/vercel.svg +0 -4
  66. package/example/NextJs/server.js +0 -36
  67. package/example/NextJs/styles/Chat.module.css +0 -448
  68. package/example/NextJs/styles/Home.module.css +0 -129
  69. package/example/NextJs/styles/globals.css +0 -26
  70. package/example/NextJs/tsconfig.json +0 -20
  71. package/example/README.md +0 -117
  72. package/example/Vite/README.md +0 -68
  73. package/example/Vite/ape/client.ts +0 -66
  74. package/example/Vite/ape/onConnect.ts +0 -52
  75. package/example/Vite/api/message.ts +0 -57
  76. package/example/Vite/index.html +0 -16
  77. package/example/Vite/package.json +0 -19
  78. package/example/Vite/server.ts +0 -62
  79. package/example/Vite/src/App.vue +0 -170
  80. package/example/Vite/src/components/Info.vue +0 -352
  81. package/example/Vite/src/main.ts +0 -5
  82. package/example/Vite/src/style.css +0 -200
  83. package/example/Vite/src/vite-env.d.ts +0 -7
  84. package/example/Vite/vite.config.ts +0 -20
  85. package/todo.md +0 -85
  86. package/utils/jss.test.js +0 -261
  87. package/utils/messageHash.test.js +0 -56
package/dist/ape.js CHANGED
@@ -1,1049 +1,2 @@
1
- (() => {
2
- var __create = Object.create;
3
- var __defProp = Object.defineProperty;
4
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
- var __getOwnPropNames = Object.getOwnPropertyNames;
6
- var __getProtoOf = Object.getPrototypeOf;
7
- var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __commonJS = (cb, mod) => function __require() {
9
- return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
- };
11
- var __copyProps = (to, from, except, desc) => {
12
- if (from && typeof from === "object" || typeof from === "function") {
13
- for (let key of __getOwnPropNames(from))
14
- if (!__hasOwnProp.call(to, key) && key !== except)
15
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
- }
17
- return to;
18
- };
19
- var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
20
- // If the importer is in node compatibility mode or this is not an ESM
21
- // file that has been converted to a CommonJS file using a Babel-
22
- // compatible transform (i.e. "__esModule" has not been set), then set
23
- // "default" to the CommonJS "module.exports" for node compatibility.
24
- isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
25
- mod
26
- ));
27
-
28
- // utils/messageHash.js
29
- var require_messageHash = __commonJS({
30
- "utils/messageHash.js"(exports, module) {
31
- var alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
32
- function toBase32(n) {
33
- const remainder = Math.floor(n / 32);
34
- const current = n % 32;
35
- if (0 === remainder) {
36
- return alphabet[current];
37
- }
38
- return toBase32(remainder) + alphabet[current];
39
- }
40
- function jenkinsOneAtATimeHash(keyString) {
41
- var hash = 0;
42
- for (var charIndex = 0; charIndex < keyString.length; ++charIndex) {
43
- hash += keyString.charCodeAt(charIndex);
44
- hash += hash << 10;
45
- hash ^= hash >> 6;
46
- }
47
- hash += hash << 3;
48
- hash ^= hash >> 11;
49
- return (hash + (hash << 15) & 4294967295) >>> 0;
50
- }
51
- function messageHash2(messageSt) {
52
- return toBase32(jenkinsOneAtATimeHash(messageSt));
53
- }
54
- module.exports = messageHash2;
55
- }
56
- });
57
-
58
- // utils/jss.js
59
- var require_jss = __commonJS({
60
- "utils/jss.js"(exports, module) {
61
- function encode(obj) {
62
- const tagLookup = {
63
- "[object RegExp]": "R",
64
- "[object Date]": "D",
65
- "[object Error]": "E",
66
- "[object Undefined]": "U",
67
- "[object Map]": "M",
68
- "[object Set]": "S"
69
- };
70
- const visited = /* @__PURE__ */ new WeakMap();
71
- function encodeValue(value, path = "") {
72
- const type = typeof value;
73
- const tag = tagLookup[Object.prototype.toString.call(value)];
74
- if (tag !== void 0) {
75
- if ("D" === tag) return [tag, value.valueOf()];
76
- if ("E" === tag) return [tag, [value.name, value.message, value.stack]];
77
- if ("R" === tag) return [tag, value.toString()];
78
- if ("U" === tag) return [tag, null];
79
- if ("S" === tag) return [tag, Array.from(value)];
80
- if ("M" === tag) return [tag, Object.fromEntries(value)];
81
- return [tag, JSON.stringify(value)];
82
- } else if (type === "object" && value !== null) {
83
- if (visitedEncode.has(value)) {
84
- return ["P", visitedEncode.get(value)];
85
- }
86
- visitedEncode.set(value, path);
87
- const isArray = Array.isArray(value);
88
- const keys2 = isArray ? Array.from(Array(value.length).keys()) : Object.keys(value);
89
- const result2 = isArray ? [] : {};
90
- const typesFound = [];
91
- for (let i = 0; i < keys2.length; i++) {
92
- const key = keys2[i];
93
- const [t, v] = encodeValue(value[key], key);
94
- if (isArray) {
95
- typesFound.push(t);
96
- result2.push(v);
97
- } else if (value[key] !== void 0) {
98
- result2[key + (t ? `<!${t}>` : "")] = v;
99
- }
100
- }
101
- visited.delete(value);
102
- if (isArray && typesFound.find((t) => !!t)) {
103
- return [`[${typesFound.join()}]`, result2];
104
- }
105
- return ["", result2];
106
- } else {
107
- return ["", value];
108
- }
109
- }
110
- let keys = [];
111
- if (Array.isArray(obj)) {
112
- keys = Array.from(Array(obj.length).keys());
113
- } else {
114
- keys = Object.keys(obj);
115
- }
116
- const visitedEncode = /* @__PURE__ */ new WeakMap();
117
- visitedEncode.set(obj, []);
118
- function encodeValueWithVisited(value, path = []) {
119
- const type = typeof value;
120
- const tag = tagLookup[Object.prototype.toString.call(value)];
121
- if (tag !== void 0) {
122
- if ("D" === tag) return [tag, value.valueOf()];
123
- if ("E" === tag) return [tag, [value.name, value.message, value.stack]];
124
- if ("R" === tag) return [tag, value.toString()];
125
- if ("U" === tag) return [tag, null];
126
- if ("S" === tag) return [tag, Array.from(value)];
127
- if ("M" === tag) return [tag, Object.fromEntries(value)];
128
- return [tag, JSON.stringify(value)];
129
- } else if (type === "object" && value !== null) {
130
- if (visitedEncode.has(value)) {
131
- return ["P", visitedEncode.get(value)];
132
- }
133
- visitedEncode.set(value, path);
134
- const isArray = Array.isArray(value);
135
- const objKeys = isArray ? Array.from(Array(value.length).keys()) : Object.keys(value);
136
- const result2 = isArray ? [] : {};
137
- const typesFound = [];
138
- for (let i = 0; i < objKeys.length; i++) {
139
- const key = objKeys[i];
140
- const [t, v] = encodeValueWithVisited(value[key], [...path, key]);
141
- if (isArray) {
142
- typesFound.push(t);
143
- result2.push(v);
144
- } else if (value[key] !== void 0) {
145
- result2[key + (t ? `<!${t}>` : "")] = v;
146
- }
147
- }
148
- if (isArray && typesFound.find((t) => !!t)) {
149
- return [`[${typesFound.join()}]`, result2];
150
- }
151
- return ["", result2];
152
- } else {
153
- return ["", value];
154
- }
155
- }
156
- const result = {};
157
- for (let i = 0; i < keys.length; i++) {
158
- const key = keys[i];
159
- if (obj[key] !== void 0) {
160
- const [t, v] = encodeValueWithVisited(obj[key], [key]);
161
- result[key + (t ? `<!${t}>` : "")] = v;
162
- }
163
- }
164
- return result;
165
- }
166
- function stringify(obj) {
167
- return JSON.stringify(encode(obj));
168
- }
169
- function parse(encoded) {
170
- return decode(JSON.parse(encoded));
171
- }
172
- function decode(data) {
173
- const result = {};
174
- const pointers2Res = [];
175
- const tagLookup = {
176
- R: (s) => new RegExp(s),
177
- D: (n) => new Date(n),
178
- P: function(sourceToPointAt, replaceAtThisPlace) {
179
- pointers2Res.push([sourceToPointAt, replaceAtThisPlace]);
180
- return null;
181
- },
182
- E: ([name, message, stack]) => {
183
- let err;
184
- try {
185
- err = new global[name](message);
186
- if (err instanceof Error) err.stack = stack;
187
- else throw {};
188
- } catch (e) {
189
- err = new Error(message);
190
- err.name = name;
191
- err.stack = stack;
192
- }
193
- return err;
194
- },
195
- U: () => void 0,
196
- S: (a) => new Set(a),
197
- M: (o) => new Map(Object.entries(o))
198
- };
199
- const visited = /* @__PURE__ */ new Map();
200
- function decodeValue(name, tag, val) {
201
- const currentPath = Array.isArray(this) ? this : [];
202
- if (tag in tagLookup) {
203
- return tagLookup[tag](val, currentPath);
204
- } else if (Array.isArray(val)) {
205
- if (tag && tag.startsWith("[")) {
206
- const typeTags = tag.slice(1, -1).split(",");
207
- const res = [];
208
- for (let i = 0; i < val.length; i++) {
209
- const itemPath = [...currentPath, i];
210
- const decodedValue = decodeValue.call(
211
- itemPath,
212
- i.toString(),
213
- typeTags[i],
214
- val[i]
215
- );
216
- res.push(decodedValue);
217
- }
218
- return res;
219
- } else {
220
- const res = [];
221
- for (let i = 0; i < val.length; i++) {
222
- const decodedValue = decodeValue.call([...currentPath, i], "", "", val[i]);
223
- res.push(decodedValue);
224
- }
225
- return res;
226
- }
227
- } else if ("object" === typeof val && val !== null) {
228
- if (visited.has(val)) {
229
- return visited.get(val);
230
- }
231
- visited.set(val, {});
232
- const res = {};
233
- for (const key in val) {
234
- const [nam, t] = parseKeyWithTags(key);
235
- const decodedValue = decodeValue.call(
236
- [...currentPath, nam],
237
- nam,
238
- t,
239
- val[key]
240
- );
241
- res[nam] = decodedValue;
242
- }
243
- visited.set(val, res);
244
- return res;
245
- } else {
246
- return val;
247
- }
248
- }
249
- function parseKeyWithTags(key) {
250
- const match = key.match(/(.+)(<!(.)>)/);
251
- if (match) {
252
- return [match[1], match[3]];
253
- }
254
- const multiMatch = key.match(/(.+)(<!!(.+)>)/);
255
- if (multiMatch) {
256
- return [multiMatch[1], multiMatch[3]];
257
- }
258
- const arrayMatch = key.match(/(.+)(<!\[(.*)>)/);
259
- if (arrayMatch) {
260
- return [arrayMatch[1], "[" + arrayMatch[3]];
261
- }
262
- return [key, void 0];
263
- }
264
- for (const key in data) {
265
- const [name, tag] = parseKeyWithTags(key);
266
- result[name] = decodeValue.call([name], name, tag, data[key]);
267
- }
268
- pointers2Res.forEach(changeAttributeReference.bind(null, result));
269
- return result;
270
- }
271
- function changeAttributeReference(obj, [refPath, attrPath]) {
272
- const refKeys = refPath || [];
273
- const attrKeys = attrPath || [];
274
- let ref = obj;
275
- for (let i = 0; i < refKeys.length; i++) {
276
- ref = ref[refKeys[i]];
277
- }
278
- let attr = obj;
279
- for (let i = 0; i < attrKeys.length - 1; i++) {
280
- attr = attr[attrKeys[i]];
281
- }
282
- attr[attrKeys[attrKeys.length - 1]] = ref;
283
- return obj;
284
- }
285
- module.exports = { parse, stringify, encode, decode };
286
- }
287
- });
288
-
289
- // client/connectSocket.js
290
- var import_messageHash = __toESM(require_messageHash());
291
- var import_jss2 = __toESM(require_jss());
292
-
293
- // client/transports/streaming.js
294
- var import_jss = __toESM(require_jss());
295
- var configuredPort = null;
296
- var configuredHost = null;
297
- function configure(opts = {}) {
298
- if (opts.port) configuredPort = opts.port;
299
- if (opts.host) configuredHost = opts.host;
300
- }
301
- function getPollUrl() {
302
- const hostname = configuredHost || window.location.hostname;
303
- const localServers = ["localhost", "127.0.0.1", "[::1]"];
304
- const isLocal = localServers.includes(hostname);
305
- const isHttps = window.location.protocol === "https:";
306
- const defaultPort = isLocal ? 9010 : window.location.port || (isHttps ? 443 : 80);
307
- const port2 = configuredPort || defaultPort;
308
- const protocol = isHttps ? "https" : "http";
309
- const portSuffix = isLocal || port2 !== 80 && port2 !== 443 ? `:${port2}` : "";
310
- return `${protocol}://${hostname}${portSuffix}/api/ape/poll`;
311
- }
312
- function parseStreamBuffer(buffer) {
313
- const messages = [];
314
- let start = -1;
315
- let depth = 0;
316
- let inString = false;
317
- let escaped = false;
318
- for (let i = 0; i < buffer.length; i++) {
319
- const char = buffer[i];
320
- if (escaped) {
321
- escaped = false;
322
- continue;
323
- }
324
- if (char === "\\" && inString) {
325
- escaped = true;
326
- continue;
327
- }
328
- if (char === '"') {
329
- inString = !inString;
330
- continue;
331
- }
332
- if (inString) continue;
333
- if (char === "{") {
334
- if (depth === 0) {
335
- start = i;
336
- }
337
- depth++;
338
- } else if (char === "}") {
339
- depth--;
340
- if (depth === 0 && start !== -1) {
341
- const jsonStr = buffer.slice(start, i + 1);
342
- try {
343
- messages.push(import_jss.default.parse(jsonStr));
344
- } catch (e) {
345
- console.error("\u{1F98D} Failed to parse stream message:", e);
346
- }
347
- start = -1;
348
- }
349
- }
350
- }
351
- const remaining = start !== -1 ? buffer.slice(start) : "";
352
- return { messages, remaining };
353
- }
354
- function createStreamingTransport() {
355
- let isActive = false;
356
- let abortController = null;
357
- let streamBuffer = "";
358
- let reconnectTimer = null;
359
- let onMessage = () => {
360
- };
361
- let onOpen = () => {
362
- };
363
- let onClose = () => {
364
- };
365
- let onError = () => {
366
- };
367
- async function connect2() {
368
- if (isActive) return;
369
- isActive = true;
370
- abortController = new AbortController();
371
- try {
372
- const response = await fetch(getPollUrl(), {
373
- method: "GET",
374
- credentials: "include",
375
- signal: abortController.signal,
376
- headers: {
377
- "Accept": "application/json"
378
- }
379
- });
380
- if (!response.ok) {
381
- throw new Error(`Stream connect failed: ${response.status}`);
382
- }
383
- onOpen();
384
- const reader = response.body.getReader();
385
- const decoder = new TextDecoder();
386
- async function read() {
387
- while (isActive) {
388
- try {
389
- const { done, value } = await reader.read();
390
- if (done) {
391
- scheduleReconnect();
392
- return;
393
- }
394
- streamBuffer += decoder.decode(value, { stream: true });
395
- const { messages, remaining } = parseStreamBuffer(streamBuffer);
396
- streamBuffer = remaining;
397
- for (const msg of messages) {
398
- if (msg.type === "__heartbeat__") continue;
399
- onMessage(msg);
400
- }
401
- } catch (readErr) {
402
- if (readErr.name === "AbortError") return;
403
- console.error("\u{1F98D} Stream read error:", readErr);
404
- scheduleReconnect();
405
- return;
406
- }
407
- }
408
- }
409
- read();
410
- } catch (err) {
411
- if (err.name === "AbortError") return;
412
- console.error("\u{1F98D} Stream connection error:", err);
413
- onError(err);
414
- scheduleReconnect();
415
- }
416
- }
417
- function scheduleReconnect() {
418
- if (!isActive) return;
419
- if (reconnectTimer) {
420
- clearTimeout(reconnectTimer);
421
- }
422
- reconnectTimer = setTimeout(() => {
423
- if (isActive) {
424
- connect2();
425
- }
426
- }, 500);
427
- }
428
- async function send(type, data, createdAt) {
429
- const payload = {
430
- type,
431
- data,
432
- createdAt: new Date(createdAt)
433
- };
434
- const response = await fetch(getPollUrl(), {
435
- method: "POST",
436
- credentials: "include",
437
- headers: {
438
- "Content-Type": "application/json"
439
- },
440
- body: import_jss.default.stringify(payload)
441
- });
442
- if (!response.ok) {
443
- const error = await response.json().catch(() => ({ error: "Unknown error" }));
444
- throw new Error(error.error || `Request failed: ${response.status}`);
445
- }
446
- const result = import_jss.default.parse(await response.text());
447
- return result.data;
448
- }
449
- function close() {
450
- isActive = false;
451
- if (reconnectTimer) {
452
- clearTimeout(reconnectTimer);
453
- reconnectTimer = null;
454
- }
455
- if (abortController) {
456
- abortController.abort();
457
- abortController = null;
458
- }
459
- streamBuffer = "";
460
- onClose();
461
- }
462
- return {
463
- connect: connect2,
464
- send,
465
- close,
466
- isConnected: () => isActive,
467
- set onMessage(fn) {
468
- onMessage = fn;
469
- },
470
- set onOpen(fn) {
471
- onOpen = fn;
472
- },
473
- set onClose(fn) {
474
- onClose = fn;
475
- },
476
- set onError(fn) {
477
- onError = fn;
478
- }
479
- };
480
- }
481
-
482
- // client/connectSocket.js
483
- var connect;
484
- var ConnectionState = {
485
- Disconnected: "disconnected",
486
- Connecting: "connecting",
487
- Connected: "connected",
488
- Closing: "closing"
489
- };
490
- var connectionState = ConnectionState.Disconnected;
491
- var connectionChangeListeners = [];
492
- function notifyConnectionChange(newState) {
493
- if (connectionState !== newState) {
494
- connectionState = newState;
495
- connectionChangeListeners.forEach((fn) => fn(newState));
496
- }
497
- }
498
- var configuredPort2 = null;
499
- var configuredHost2 = null;
500
- var configuredTransport = "auto";
501
- var currentTransport = null;
502
- var streamingTransport = null;
503
- var wsRetryTimer = null;
504
- var WS_FALLBACK_TIMEOUT = 4e3;
505
- var WS_RETRY_INTERVAL = 3e4;
506
- function configure2(opts = {}) {
507
- if (opts.port) {
508
- configuredPort2 = opts.port;
509
- configure({ port: opts.port });
510
- }
511
- if (opts.host) {
512
- configuredHost2 = opts.host;
513
- configure({ host: opts.host });
514
- }
515
- if (opts.transport) {
516
- configuredTransport = opts.transport;
517
- }
518
- }
519
- function getSocketUrl() {
520
- const hostname = configuredHost2 || window.location.hostname;
521
- const localServers = ["localhost", "127.0.0.1", "[::1]"];
522
- const isLocal = localServers.includes(hostname);
523
- const isHttps = window.location.protocol === "https:";
524
- const defaultPort = isLocal ? 9010 : window.location.port || (isHttps ? 443 : 80);
525
- const port2 = configuredPort2 || defaultPort;
526
- const protocol = isHttps ? "wss" : "ws";
527
- const portSuffix = isLocal || port2 !== 80 && port2 !== 443 ? `:${port2}` : "";
528
- return `${protocol}://${hostname}${portSuffix}/api/ape`;
529
- }
530
- var reconnect = false;
531
- var connentTimeout = 5e3;
532
- var totalRequestTimeout = 1e4;
533
- var joinKey = "/";
534
- var reservedKeys = /* @__PURE__ */ new Set(["on", "onConnectionChange", "configure", "getTransport"]);
535
- var handler = {
536
- get(fn, key) {
537
- if (reservedKeys.has(key)) {
538
- return fn[key];
539
- }
540
- const wrapperFn = function(a, b) {
541
- let path = joinKey + key, body;
542
- if (2 === arguments.length) {
543
- path += a;
544
- body = b;
545
- } else {
546
- body = a;
547
- }
548
- return fn(path, body);
549
- };
550
- return new Proxy(wrapperFn, handler);
551
- }
552
- // END get
553
- };
554
- function wrap(api) {
555
- return new Proxy(api, handler);
556
- }
557
- var __socket = false;
558
- var ready = false;
559
- var wsSend = false;
560
- var waitingOn = {};
561
- var aWaitingSend = [];
562
- var reciverOnAr = [];
563
- var ofTypesOb = {};
564
- function switchToStreaming() {
565
- console.log("\u{1F98D} Switching to HTTP streaming transport");
566
- currentTransport = "polling";
567
- if (!streamingTransport) {
568
- streamingTransport = createStreamingTransport();
569
- streamingTransport.onMessage = async (msg) => {
570
- const { err, type, data } = msg;
571
- if (ofTypesOb[type]) {
572
- ofTypesOb[type].forEach((worker) => worker({ err, type, data }));
573
- }
574
- reciverOnAr.forEach((worker) => worker({ err, type, data }));
575
- };
576
- streamingTransport.onOpen = () => {
577
- ready = true;
578
- notifyConnectionChange(ConnectionState.Connected);
579
- console.log("\u{1F98D} HTTP streaming connected");
580
- aWaitingSend.forEach(({ type, data, next, err, waiting, createdAt, timer }) => {
581
- clearTimeout(timer);
582
- const resultPromise = streamingSend(type, data, createdAt);
583
- if (waiting) {
584
- resultPromise.then(next).catch(err);
585
- }
586
- });
587
- aWaitingSend = [];
588
- startWsRetry();
589
- };
590
- streamingTransport.onClose = () => {
591
- ready = false;
592
- notifyConnectionChange(ConnectionState.Disconnected);
593
- };
594
- streamingTransport.onError = (err) => {
595
- console.error("\u{1F98D} Streaming error:", err);
596
- };
597
- }
598
- streamingTransport.connect();
599
- }
600
- function streamingSend(type, data, createdAt) {
601
- return streamingTransport.send(type, data, createdAt);
602
- }
603
- function startWsRetry() {
604
- if (wsRetryTimer) return;
605
- if (currentTransport !== "polling") return;
606
- if (configuredTransport === "polling") return;
607
- wsRetryTimer = setInterval(() => {
608
- if (currentTransport !== "polling") {
609
- clearInterval(wsRetryTimer);
610
- wsRetryTimer = null;
611
- return;
612
- }
613
- console.log("\u{1F98D} Attempting WebSocket reconnection...");
614
- tryWebSocket(true);
615
- }, WS_RETRY_INTERVAL);
616
- }
617
- function tryWebSocket(isRetry = false) {
618
- const ws = new WebSocket(getSocketUrl());
619
- let fallbackTimer = null;
620
- if (!isRetry && configuredTransport === "auto") {
621
- fallbackTimer = setTimeout(() => {
622
- if (ws.readyState !== WebSocket.OPEN) {
623
- console.log("\u{1F98D} WebSocket timeout, falling back to HTTP streaming");
624
- ws.close();
625
- switchToStreaming();
626
- }
627
- }, WS_FALLBACK_TIMEOUT);
628
- }
629
- ws.onopen = () => {
630
- if (fallbackTimer) clearTimeout(fallbackTimer);
631
- if (isRetry && currentTransport === "polling") {
632
- console.log("\u{1F98D} WebSocket reconnected, switching from HTTP streaming");
633
- if (streamingTransport) {
634
- streamingTransport.close();
635
- }
636
- if (wsRetryTimer) {
637
- clearInterval(wsRetryTimer);
638
- wsRetryTimer = null;
639
- }
640
- }
641
- currentTransport = "websocket";
642
- __socket = ws;
643
- ready = true;
644
- notifyConnectionChange(ConnectionState.Connected);
645
- aWaitingSend.forEach(({ type, data, next, err, waiting, createdAt, timer }) => {
646
- clearTimeout(timer);
647
- const resultPromise = wsSend(type, data, createdAt);
648
- if (waiting) {
649
- resultPromise.then(next).catch(err);
650
- }
651
- });
652
- aWaitingSend = [];
653
- };
654
- ws.onmessage = async function(event) {
655
- const { err, type, queryId, data } = import_jss2.default.parse(event.data);
656
- if (queryId) {
657
- if (waitingOn[queryId]) {
658
- if (data && !err) {
659
- try {
660
- const hydratedData = await fetchLinkedResources(data);
661
- waitingOn[queryId](err, hydratedData);
662
- } catch (fetchErr) {
663
- waitingOn[queryId](fetchErr, null);
664
- }
665
- } else {
666
- waitingOn[queryId](err, data);
667
- }
668
- delete waitingOn[queryId];
669
- } else {
670
- console.error(`\u{1F98D} No matching queryId: ${queryId}`);
671
- }
672
- return;
673
- }
674
- let processedData = data;
675
- if (data && !err) {
676
- try {
677
- processedData = await fetchLinkedResources(data);
678
- } catch (fetchErr) {
679
- console.error(`\u{1F98D} Failed to hydrate broadcast data:`, fetchErr);
680
- }
681
- }
682
- if (ofTypesOb[type]) {
683
- ofTypesOb[type].forEach((worker) => worker({ err, type, data: processedData }));
684
- }
685
- reciverOnAr.forEach((worker) => worker({ err, type, data: processedData }));
686
- };
687
- ws.onerror = function(err) {
688
- if (fallbackTimer) clearTimeout(fallbackTimer);
689
- console.error("socket ERROR:", err);
690
- if (!isRetry && configuredTransport === "auto" && !ready) {
691
- switchToStreaming();
692
- }
693
- };
694
- ws.onclose = function(event) {
695
- if (fallbackTimer) clearTimeout(fallbackTimer);
696
- console.warn("socket disconnect:", event);
697
- __socket = false;
698
- ready = false;
699
- if (currentTransport === "websocket") {
700
- notifyConnectionChange(ConnectionState.Disconnected);
701
- setTimeout(() => reconnect && connectSocket(), 500);
702
- }
703
- };
704
- }
705
- function findLinkedResources(obj, path = "") {
706
- const resources = [];
707
- if (obj === null || obj === void 0 || typeof obj !== "object") {
708
- return resources;
709
- }
710
- if (Array.isArray(obj)) {
711
- for (let i = 0; i < obj.length; i++) {
712
- resources.push(...findLinkedResources(obj[i], path ? `${path}.${i}` : String(i)));
713
- }
714
- return resources;
715
- }
716
- for (const key of Object.keys(obj)) {
717
- if (key.endsWith("<!L>")) {
718
- const cleanKey = key.slice(0, -4);
719
- const hash = obj[key];
720
- resources.push({
721
- path: path ? `${path}.${cleanKey}` : cleanKey,
722
- hash,
723
- originalKey: key
724
- });
725
- } else {
726
- resources.push(...findLinkedResources(obj[key], path ? `${path}.${key}` : key));
727
- }
728
- }
729
- return resources;
730
- }
731
- function setValueAtPath(obj, path, value) {
732
- const parts = path.split(".");
733
- let current = obj;
734
- for (let i = 0; i < parts.length - 1; i++) {
735
- current = current[parts[i]];
736
- }
737
- current[parts[parts.length - 1]] = value;
738
- }
739
- function cleanLinkedKeys(obj) {
740
- if (obj === null || obj === void 0 || typeof obj !== "object") {
741
- return obj;
742
- }
743
- if (Array.isArray(obj)) {
744
- return obj.map(cleanLinkedKeys);
745
- }
746
- const cleaned = {};
747
- for (const key of Object.keys(obj)) {
748
- if (key.endsWith("<!L>")) {
749
- const cleanKey = key.slice(0, -4);
750
- cleaned[cleanKey] = obj[key];
751
- } else {
752
- cleaned[key] = cleanLinkedKeys(obj[key]);
753
- }
754
- }
755
- return cleaned;
756
- }
757
- async function fetchLinkedResources(data, hostId) {
758
- const resources = findLinkedResources(data);
759
- if (resources.length === 0) {
760
- return data;
761
- }
762
- console.log(`\u{1F98D} Fetching ${resources.length} binary resource(s)`);
763
- const cleanedData = cleanLinkedKeys(data);
764
- const hostname = configuredHost2 || window.location.hostname;
765
- const isLocal = ["localhost", "127.0.0.1", "[::1]"].includes(hostname);
766
- const isHttps = window.location.protocol === "https:";
767
- const defaultPort = isLocal ? 9010 : window.location.port || (isHttps ? 443 : 80);
768
- const port2 = configuredPort2 || defaultPort;
769
- const protocol = isHttps ? "https" : "http";
770
- const portSuffix = isLocal || port2 !== 80 && port2 !== 443 ? `:${port2}` : "";
771
- const baseUrl = `${protocol}://${hostname}${portSuffix}`;
772
- await Promise.all(resources.map(async ({ path, hash }) => {
773
- try {
774
- const response = await fetch(`${baseUrl}/api/ape/data/${hash}`, {
775
- credentials: "include",
776
- headers: {
777
- "X-Ape-Host-Id": hostId || ""
778
- }
779
- });
780
- if (!response.ok) {
781
- throw new Error(`Failed to fetch binary resource: ${response.status}`);
782
- }
783
- const arrayBuffer = await response.arrayBuffer();
784
- setValueAtPath(cleanedData, path, arrayBuffer);
785
- } catch (err) {
786
- console.error(`\u{1F98D} Failed to fetch binary resource at ${path}:`, err);
787
- setValueAtPath(cleanedData, path, null);
788
- }
789
- }));
790
- return cleanedData;
791
- }
792
- function connectSocket() {
793
- if (__socket && __socket.readyState !== WebSocket.CLOSED) {
794
- return buildClientInterface();
795
- }
796
- if (currentTransport === "polling" && streamingTransport?.isConnected()) {
797
- return buildClientInterface();
798
- }
799
- notifyConnectionChange(ConnectionState.Connecting);
800
- if (configuredTransport === "polling") {
801
- switchToStreaming();
802
- } else {
803
- tryWebSocket(false);
804
- }
805
- return buildClientInterface();
806
- }
807
- function isBinaryData(value) {
808
- if (value === null || value === void 0) return false;
809
- return value instanceof ArrayBuffer || ArrayBuffer.isView(value) || typeof Blob !== "undefined" && value instanceof Blob;
810
- }
811
- function getBinaryTag(value) {
812
- if (typeof Blob !== "undefined" && value instanceof Blob) return "B";
813
- return "A";
814
- }
815
- function generateUploadHash(path) {
816
- let hash = 0;
817
- for (let i = 0; i < path.length; i++) {
818
- const char = path.charCodeAt(i);
819
- hash = (hash << 5) - hash + char;
820
- hash = hash & hash;
821
- }
822
- return Math.abs(hash).toString(36);
823
- }
824
- function processBinaryForUpload(data, path = "") {
825
- if (data === null || data === void 0) {
826
- return { processedData: data, uploads: [] };
827
- }
828
- if (isBinaryData(data)) {
829
- const tag = getBinaryTag(data);
830
- const hash = generateUploadHash(path || "root");
831
- return {
832
- processedData: { [`__ape_upload__`]: hash },
833
- uploads: [{ path, hash, data, tag }]
834
- };
835
- }
836
- if (Array.isArray(data)) {
837
- const processedArray = [];
838
- const allUploads = [];
839
- for (let i = 0; i < data.length; i++) {
840
- const itemPath = path ? `${path}.${i}` : String(i);
841
- const { processedData, uploads } = processBinaryForUpload(data[i], itemPath);
842
- processedArray.push(processedData);
843
- allUploads.push(...uploads);
844
- }
845
- return { processedData: processedArray, uploads: allUploads };
846
- }
847
- if (typeof data === "object") {
848
- const processedObj = {};
849
- const allUploads = [];
850
- for (const key of Object.keys(data)) {
851
- const itemPath = path ? `${path}.${key}` : key;
852
- const { processedData, uploads } = processBinaryForUpload(data[key], itemPath);
853
- if (uploads.length > 0 && processedData?.__ape_upload__) {
854
- const tag = uploads[uploads.length - 1].tag;
855
- processedObj[`${key}<!${tag}>`] = processedData.__ape_upload__;
856
- } else {
857
- processedObj[key] = processedData;
858
- }
859
- allUploads.push(...uploads);
860
- }
861
- return { processedData: processedObj, uploads: allUploads };
862
- }
863
- return { processedData: data, uploads: [] };
864
- }
865
- async function uploadBinaryData(queryId, uploads) {
866
- if (uploads.length === 0) return;
867
- const hostname = configuredHost2 || window.location.hostname;
868
- const isLocal = ["localhost", "127.0.0.1", "[::1]"].includes(hostname);
869
- const isHttps = window.location.protocol === "https:";
870
- const defaultPort = isLocal ? 9010 : window.location.port || (isHttps ? 443 : 80);
871
- const port2 = configuredPort2 || defaultPort;
872
- const protocol = isHttps ? "https" : "http";
873
- const portSuffix = isLocal || port2 !== 80 && port2 !== 443 ? `:${port2}` : "";
874
- const baseUrl = `${protocol}://${hostname}${portSuffix}`;
875
- console.log(`\u{1F98D} Uploading ${uploads.length} binary file(s)`);
876
- await Promise.all(uploads.map(async ({ hash, data }) => {
877
- try {
878
- const response = await fetch(`${baseUrl}/api/ape/data/${queryId}/${hash}`, {
879
- method: "PUT",
880
- credentials: "include",
881
- headers: {
882
- "Content-Type": "application/octet-stream"
883
- },
884
- body: data
885
- });
886
- if (!response.ok) {
887
- throw new Error(`Upload failed: ${response.status}`);
888
- }
889
- } catch (err) {
890
- console.error(`\u{1F98D} Failed to upload binary at ${hash}:`, err);
891
- throw err;
892
- }
893
- }));
894
- }
895
- wsSend = function(type, data, createdAt, dirctCall) {
896
- let rej, promiseIsLive = false;
897
- const timeLetForReqToBeMade = createdAt + totalRequestTimeout - Date.now();
898
- const timer = setTimeout(() => {
899
- if (promiseIsLive) {
900
- rej(new Error("Request Timedout for :" + type));
901
- }
902
- }, timeLetForReqToBeMade);
903
- const { processedData, uploads } = processBinaryForUpload(data);
904
- const payload = {
905
- type,
906
- data: processedData,
907
- //referer:window.location.href,
908
- createdAt: new Date(createdAt),
909
- requestedAt: dirctCall ? void 0 : /* @__PURE__ */ new Date()
910
- };
911
- const message = import_jss2.default.stringify(payload);
912
- const queryId = (0, import_messageHash.default)(message);
913
- const replyPromise = new Promise((resolve, reject) => {
914
- rej = reject;
915
- waitingOn[queryId] = (err2, result) => {
916
- clearTimeout(timer);
917
- replyPromise.then = next.bind(replyPromise);
918
- if (err2) {
919
- reject(err2);
920
- } else {
921
- resolve(result);
922
- }
923
- };
924
- __socket.send(message);
925
- if (uploads.length > 0) {
926
- uploadBinaryData(queryId, uploads).catch((err2) => {
927
- console.error("\u{1F98D} Binary upload failed:", err2);
928
- });
929
- }
930
- });
931
- const next = replyPromise.then;
932
- replyPromise.then = (worker) => {
933
- promiseIsLive = true;
934
- replyPromise.then = next.bind(replyPromise);
935
- replyPromise.catch = err.bind(replyPromise);
936
- return next.call(replyPromise, worker);
937
- };
938
- const err = replyPromise.catch;
939
- replyPromise.catch = (worker) => {
940
- promiseIsLive = true;
941
- replyPromise.catch = err.bind(replyPromise);
942
- replyPromise.then = next.bind(replyPromise);
943
- return err.call(replyPromise, worker);
944
- };
945
- return replyPromise;
946
- };
947
- var sender = (type, data) => {
948
- if ("string" !== typeof type) {
949
- throw new Error("Missing Path vaule");
950
- }
951
- const createdAt = Date.now();
952
- if (ready) {
953
- return wsSend(type, data, createdAt, true);
954
- }
955
- const timeLetForReqToBeMade = createdAt + connentTimeout - Date.now();
956
- const timer = setTimeout(() => {
957
- const errMessage = "Request not sent for :" + type;
958
- if (payload.waiting) {
959
- payload.err(new Error(errMessage));
960
- } else {
961
- throw new Error(errMessage);
962
- }
963
- }, timeLetForReqToBeMade);
964
- const payload = { type, data, next: void 0, err: void 0, waiting: false, createdAt, timer };
965
- const waitingOnOpen = new Promise((res, er) => {
966
- payload.next = res;
967
- payload.err = er;
968
- });
969
- const waitingOnOpenThen = waitingOnOpen.then;
970
- const waitingOnOpenCatch = waitingOnOpen.catch;
971
- waitingOnOpen.then = (worker) => {
972
- payload.waiting = true;
973
- waitingOnOpen.then = waitingOnOpenThen.bind(waitingOnOpen);
974
- waitingOnOpen.catch = waitingOnOpenCatch.bind(waitingOnOpen);
975
- return waitingOnOpenThen.call(waitingOnOpen, worker);
976
- };
977
- waitingOnOpen.catch = (worker) => {
978
- payload.waiting = true;
979
- waitingOnOpen.catch = waitingOnOpenCatch.bind(waitingOnOpen);
980
- waitingOnOpen.then = waitingOnOpenThen.bind(waitingOnOpen);
981
- return waitingOnOpenCatch.call(waitingOnOpen, worker);
982
- };
983
- aWaitingSend.push(payload);
984
- if (!__socket) {
985
- connectSocket();
986
- }
987
- return waitingOnOpen;
988
- };
989
- function buildClientInterface() {
990
- return {
991
- sender: wrap(sender),
992
- setOnReciver: (onTypeStFn, handlerFn) => {
993
- if ("string" === typeof onTypeStFn) {
994
- ofTypesOb[onTypeStFn] = [handlerFn];
995
- } else {
996
- if (!reciverOnAr.includes(onTypeStFn)) {
997
- reciverOnAr.push(onTypeStFn);
998
- }
999
- }
1000
- },
1001
- onConnectionChange: (handler2) => {
1002
- connectionChangeListeners.push(handler2);
1003
- handler2(connectionState);
1004
- return () => {
1005
- const idx = connectionChangeListeners.indexOf(handler2);
1006
- if (idx > -1) connectionChangeListeners.splice(idx, 1);
1007
- };
1008
- },
1009
- // Expose current transport type
1010
- getTransport: () => currentTransport
1011
- };
1012
- }
1013
- connectSocket.autoReconnect = () => reconnect = true;
1014
- connectSocket.configure = configure2;
1015
- connectSocket.ConnectionState = ConnectionState;
1016
- connect = connectSocket;
1017
- var connectSocket_default = connect;
1018
-
1019
- // client/browser.js
1020
- var port = window.location.port || (window.location.protocol === "https:" ? 443 : 80);
1021
- connectSocket_default.configure({ port: parseInt(port, 10) });
1022
- var { sender: sender2, setOnReciver, onConnectionChange, getTransport } = connectSocket_default();
1023
- connectSocket_default.autoReconnect();
1024
- window.ape = sender2;
1025
- Object.defineProperty(window.ape, "on", {
1026
- value: setOnReciver,
1027
- writable: false,
1028
- enumerable: false,
1029
- configurable: false
1030
- });
1031
- Object.defineProperty(window.ape, "onConnectionChange", {
1032
- value: onConnectionChange,
1033
- writable: false,
1034
- enumerable: false,
1035
- configurable: false
1036
- });
1037
- Object.defineProperty(window.ape, "configure", {
1038
- value: connectSocket_default.configure,
1039
- writable: false,
1040
- enumerable: false,
1041
- configurable: false
1042
- });
1043
- Object.defineProperty(window.ape, "getTransport", {
1044
- value: getTransport,
1045
- writable: false,
1046
- enumerable: false,
1047
- configurable: false
1048
- });
1049
- })();
1
+ (()=>{var ge=Object.create;var Q=Object.defineProperty;var we=Object.getOwnPropertyDescriptor;var ye=Object.getOwnPropertyNames;var me=Object.getPrototypeOf,be=Object.prototype.hasOwnProperty;var Z=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports);var Te=(e,t,n,o)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of ye(t))!be.call(e,s)&&s!==n&&Q(e,s,{get:()=>t[s],enumerable:!(o=we(t,s))||o.enumerable});return e};var j=(e,t,n)=>(n=e!=null?ge(me(e)):{},Te(t||!e||!e.__esModule?Q(n,"default",{value:e,enumerable:!0}):n,e));var te=Z((ve,ee)=>{var z="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function v(e){let t=Math.floor(e/32),n=e%32;return t===0?z[n]:v(t)+z[n]}function Se(e){for(var t=0,n=0;n<e.length;++n)t+=e.charCodeAt(n),t+=t<<10,t^=t>>6;return t+=t<<3,t^=t>>11,(t+(t<<15)&4294967295)>>>0}function ke(e){return v(Se(e))}ee.exports=ke});var H=Z((et,re)=>{function ne(e){let t={"[object RegExp]":"R","[object Date]":"D","[object Error]":"E","[object Undefined]":"U","[object Map]":"M","[object Set]":"S"},n=new WeakMap;function o(r,a=""){let p=typeof r,f=t[Object.prototype.toString.call(r)];if(f!==void 0)return f==="D"?[f,r.valueOf()]:f==="E"?[f,[r.name,r.message,r.stack]]:f==="R"?[f,r.toString()]:f==="U"?[f,null]:f==="S"?[f,Array.from(r)]:f==="M"?[f,Object.fromEntries(r)]:[f,JSON.stringify(r)];if(p==="object"&&r!==null){if(i.has(r))return["P",i.get(r)];i.set(r,a);let d=Array.isArray(r),u=d?Array.from(Array(r.length).keys()):Object.keys(r),g=d?[]:{},w=[];for(let h=0;h<u.length;h++){let m=u[h],[y,S]=o(r[m],m);d?(w.push(y),g.push(S)):r[m]!==void 0&&(g[m+(y?`<!${y}>`:"")]=S)}return n.delete(r),d&&w.find(h=>!!h)?[`[${w.join()}]`,g]:["",g]}else return["",r]}let s=[];Array.isArray(e)?s=Array.from(Array(e.length).keys()):s=Object.keys(e);let i=new WeakMap;i.set(e,[]);function l(r,a=[]){let p=typeof r,f=t[Object.prototype.toString.call(r)];if(f!==void 0)return f==="D"?[f,r.valueOf()]:f==="E"?[f,[r.name,r.message,r.stack]]:f==="R"?[f,r.toString()]:f==="U"?[f,null]:f==="S"?[f,Array.from(r)]:f==="M"?[f,Object.fromEntries(r)]:[f,JSON.stringify(r)];if(p==="object"&&r!==null){if(i.has(r))return["P",i.get(r)];i.set(r,a);let d=Array.isArray(r),u=d?Array.from(Array(r.length).keys()):Object.keys(r),g=d?[]:{},w=[];for(let h=0;h<u.length;h++){let m=u[h],[y,S]=l(r[m],[...a,m]);d?(w.push(y),g.push(S)):r[m]!==void 0&&(g[m+(y?`<!${y}>`:"")]=S)}return d&&w.find(h=>!!h)?[`[${w.join()}]`,g]:["",g]}else return["",r]}let c={};for(let r=0;r<s.length;r++){let a=s[r];if(e[a]!==void 0){let[p,f]=l(e[a],[a]);c[a+(p?`<!${p}>`:"")]=f}}return c}function Ae(e){return JSON.stringify(ne(e))}function Ee(e){return oe(JSON.parse(e))}function oe(e){let t={},n=[],o={R:c=>new RegExp(c),D:c=>new Date(c),P:function(c,r){return n.push([c,r]),null},E:([c,r,a])=>{let p;try{if(p=new global[c](r),p instanceof Error)p.stack=a;else throw{}}catch{p=new Error(r),p.name=c,p.stack=a}return p},U:()=>{},S:c=>new Set(c),M:c=>new Map(Object.entries(c))},s=new Map;function i(c,r,a){let p=Array.isArray(this)?this:[];if(r in o)return o[r](a,p);if(Array.isArray(a))if(r&&r.startsWith("[")){let f=r.slice(1,-1).split(","),d=[];for(let u=0;u<a.length;u++){let g=[...p,u],w=i.call(g,u.toString(),f[u],a[u]);d.push(w)}return d}else{let f=[];for(let d=0;d<a.length;d++){let u=i.call([...p,d],"","",a[d]);f.push(u)}return f}else if(typeof a=="object"&&a!==null){if(s.has(a))return s.get(a);s.set(a,{});let f={};for(let d in a){let[u,g]=l(d),w=i.call([...p,u],u,g,a[d]);f[u]=w}return s.set(a,f),f}else return a}function l(c){let r=c.match(/(.+)(<!(.)>)/);if(r)return[r[1],r[3]];let a=c.match(/(.+)(<!!(.+)>)/);if(a)return[a[1],a[3]];let p=c.match(/(.+)(<!\[(.*)>)/);return p?[p[1],"["+p[3]]:[c,void 0]}for(let c in e){let[r,a]=l(c);t[r]=i.call([r],r,a,e[c])}return n.forEach($e.bind(null,t)),t}function $e(e,[t,n]){let o=t||[],s=n||[],i=e;for(let c=0;c<o.length;c++)i=i[o[c]];let l=e;for(let c=0;c<s.length-1;c++)l=l[s[c]];return l[s[s.length-1]]=i,e}re.exports={parse:Ee,stringify:Ae,encode:ne,decode:oe}});var le=j(te()),q=j(H());var _=j(H());function se(){let e=window.location.hostname,n=["localhost","127.0.0.1","[::1]"].includes(e),o=window.location.protocol==="https:",s=n?9010:window.location.port||(o?443:80),i=o?"https":"http",l=n||s!==80&&s!==443?`:${s}`:"";return`${i}://${e}${l}/api/ape/poll`}function Oe(e){let t=[],n=-1,o=0,s=!1,i=!1;for(let c=0;c<e.length;c++){let r=e[c];if(i){i=!1;continue}if(r==="\\"&&s){i=!0;continue}if(r==='"'){s=!s;continue}if(!s){if(r==="{")o===0&&(n=c),o++;else if(r==="}"&&(o--,o===0&&n!==-1)){let a=e.slice(n,c+1);try{t.push(_.default.parse(a))}catch(p){console.error("\u{1F98D} Failed to parse stream message:",p)}n=-1}}}let l=n!==-1?e.slice(n):"";return{messages:t,remaining:l}}function ie(){let e=!1,t=null,n="",o=null,s=()=>{},i=()=>{},l=()=>{},c=()=>{};async function r(){if(!e){e=!0,t=new AbortController;try{let d=await fetch(se(),{method:"GET",credentials:"include",signal:t.signal,headers:{Accept:"application/json"}});if(!d.ok)throw new Error(`Stream connect failed: ${d.status}`);i();let u=d.body.getReader(),g=new TextDecoder;async function w(){for(;e;)try{let{done:h,value:m}=await u.read();if(h){a();return}n+=g.decode(m,{stream:!0});let{messages:y,remaining:S}=Oe(n);n=S;for(let Y of y)Y.type!=="__heartbeat__"&&s(Y)}catch(h){if(h.name==="AbortError")return;console.error("\u{1F98D} Stream read error:",h),a();return}}w()}catch(d){if(d.name==="AbortError")return;console.error("\u{1F98D} Stream connection error:",d),c(d),a()}}}function a(){e&&(o&&clearTimeout(o),o=setTimeout(()=>{e&&r()},500))}async function p(d,u,g){let w={type:d,data:u,createdAt:new Date(g)},h=await fetch(se(),{method:"POST",credentials:"include",headers:{"Content-Type":"application/json"},body:_.default.stringify(w)});if(!h.ok){let y=await h.json().catch(()=>({error:"Unknown error"}));throw new Error(y.error||`Request failed: ${h.status}`)}return _.default.parse(await h.text()).data}function f(){e=!1,o&&(clearTimeout(o),o=null),t&&(t.abort(),t=null),n="",l()}return{connect:r,send:p,close:f,isConnected:()=>e,set onMessage(d){s=d},set onOpen(d){i=d},set onClose(d){l=d},set onError(d){c=d}}}var fe,b={Offline:"offline",Walled:"walled",Disconnected:"disconnected",Connecting:"connecting",Connected:"connected",Closing:"closing"},W=typeof navigator<"u"&&!navigator.onLine?b.Offline:b.Disconnected,B=[];function k(e){W!==e&&(W=e,B.forEach(t=>t(e)))}var U="auto",A=null,T=null,E=null,V=null,Ce=4e3,ue=3e4,Pe=3e3,De=6e4;function L(){return typeof window>"u"?!1:["localhost","127.0.0.1","[::1]"].includes(window.location.hostname)}function Re(){let e=window.location.hostname,n=["localhost","127.0.0.1","[::1]"].includes(e),o=window.location.protocol==="https:",s=n?9010:window.location.port||(o?443:80),i=o?"https":"http",l=n||s!==80&&s!==443?`:${s}`:"";return`${i}://${e}${l}/api/ape/ping`}async function _e(){try{let e=new AbortController,t=setTimeout(()=>e.abort(),Pe),n=await fetch(Re(),{cache:"no-store",signal:e.signal});if(clearTimeout(t),!n.ok)return L()&&console.error("\u{1F98D} [DEV] Ping failed: HTTP",n.status),"walled";let o=await n.json();if(o?.ok!==!0)return L()&&console.error("\u{1F98D} [DEV] Ping failed: invalid response",o),"walled";if(typeof o.ts=="number"){let s=Date.now(),i=Math.abs(s-o.ts);if(i>De)return L()&&console.error("\u{1F98D} [DEV] Ping failed: timestamp too old/stale (skew:",i,"ms)"),"walled"}return"ok"}catch(e){return L()&&console.error("\u{1F98D} [DEV] Ping failed:",e.message||e),"walled"}}function Le(){typeof window>"u"||(window.addEventListener("online",()=>{console.log("\u{1F98D} Browser went online, checking network..."),G()}),window.addEventListener("offline",()=>{console.log("\u{1F98D} Browser went offline"),k(b.Offline)}))}typeof window<"u"&&Le();function Me(){let e=window.location.hostname,n=["localhost","127.0.0.1","[::1]"].includes(e),o=window.location.protocol==="https:",s=n?9010:window.location.port||(o?443:80),i=o?"wss":"ws",l=n||s!==80&&s!==443?`:${s}`:"";return`${i}://${e}${l}/api/ape`}var de=!1,Be=5e3,We=1e4,Ue="/",xe=new Set(["on","onConnectionChange","getTransport"]),pe={get(e,t){if(xe.has(t))return e[t];let n=function(o,s){let i=Ue+t,l;return arguments.length===2?(i+=o,l=s):l=o,e(i,l)};return new Proxy(n,pe)}};function je(e){return new Proxy(e,pe)}var C=!1,O=!1,J=!1,$={};var P=[],x=[],D={};function K(){console.log("\u{1F98D} Switching to HTTP streaming transport"),A="polling",T||(T=ie(),T.onMessage=async e=>{let{err:t,type:n,data:o}=e;D[n]&&D[n].forEach(s=>s({err:t,type:n,data:o})),x.forEach(s=>s({err:t,type:n,data:o}))},T.onOpen=()=>{O=!0,k(b.Connected),console.log("\u{1F98D} HTTP streaming connected"),P.forEach(({type:e,data:t,next:n,err:o,waiting:s,createdAt:i,timer:l})=>{clearTimeout(l);let c=He(e,t,i);s&&c.then(n).catch(o)}),P=[],Ve()},T.onClose=()=>{O=!1,k(b.Disconnected)},T.onError=e=>{console.error("\u{1F98D} Streaming error:",e)}),T.connect()}function He(e,t,n){return T.send(e,t,n)}function Ve(){E||A==="polling"&&U!=="polling"&&(E=setInterval(()=>{if(A!=="polling"){clearInterval(E),E=null;return}console.log("\u{1F98D} Attempting WebSocket reconnection..."),he(!0)},ue))}function he(e=!1){let t=new WebSocket(Me()),n=null;!e&&U==="auto"&&(n=setTimeout(()=>{t.readyState!==WebSocket.OPEN&&(console.log("\u{1F98D} WebSocket timeout, falling back to HTTP streaming"),t.close(),K())},Ce)),t.onopen=()=>{n&&clearTimeout(n),e&&A==="polling"&&(console.log("\u{1F98D} WebSocket reconnected, switching from HTTP streaming"),T&&T.close(),E&&(clearInterval(E),E=null)),A="websocket",C=t,O=!0,k(b.Connected),P.forEach(({type:o,data:s,next:i,err:l,waiting:c,createdAt:r,timer:a})=>{clearTimeout(a);let p=J(o,s,r);c&&p.then(i).catch(l)}),P=[]},t.onmessage=async function(o){let{err:s,type:i,queryId:l,data:c}=q.default.parse(o.data);if(l){if($[l]){if(c&&!s)try{let a=await ae(c);$[l](s,a)}catch(a){$[l](a,null)}else $[l](s,c);delete $[l]}else console.error(`\u{1F98D} No matching queryId: ${l}`);return}let r=c;if(c&&!s)try{r=await ae(c)}catch(a){console.error("\u{1F98D} Failed to hydrate broadcast data:",a)}D[i]&&D[i].forEach(a=>a({err:s,type:i,data:r})),x.forEach(a=>a({err:s,type:i,data:r}))},t.onerror=function(o){n&&clearTimeout(n),console.error("socket ERROR:",o),!e&&U==="auto"&&!O&&K()},t.onclose=function(o){n&&clearTimeout(n),console.warn("socket disconnect:",o),C=!1,O=!1,A==="websocket"&&(k(b.Disconnected),setTimeout(()=>de&&R(),500))}}function I(e,t=""){let n=[];if(e==null||typeof e!="object")return n;if(Array.isArray(e)){for(let o=0;o<e.length;o++)n.push(...I(e[o],t?`${t}.${o}`:String(o)));return n}for(let o of Object.keys(e))if(o.endsWith("<!L>")){let s=o.slice(0,-4),i=e[o];n.push({path:t?`${t}.${s}`:s,hash:i,originalKey:o})}else n.push(...I(e[o],t?`${t}.${o}`:o));return n}function ce(e,t,n){let o=t.split("."),s=e;for(let i=0;i<o.length-1;i++)s=s[o[i]];s[o[o.length-1]]=n}function F(e){if(e==null||typeof e!="object")return e;if(Array.isArray(e))return e.map(F);let t={};for(let n of Object.keys(e))if(n.endsWith("<!L>")){let o=n.slice(0,-4);t[o]=e[n]}else t[n]=F(e[n]);return t}async function ae(e,t){let n=I(e);if(n.length===0)return e;console.log(`\u{1F98D} Fetching ${n.length} binary resource(s)`);let o=F(e),s=window.location.hostname,i=["localhost","127.0.0.1","[::1]"].includes(s),l=window.location.protocol==="https:",c=i?9010:window.location.port||(l?443:80),r=l?"https":"http",a=i||c!==80&&c!==443?`:${c}`:"",p=`${r}://${s}${a}`;return await Promise.all(n.map(async({path:f,hash:d})=>{try{let u=await fetch(`${p}/api/ape/data/${d}`,{credentials:"include",headers:{"X-Ape-Client-Id":t||""}});if(!u.ok)throw new Error(`Failed to fetch binary resource: ${u.status}`);let g=await u.arrayBuffer();ce(o,f,g)}catch(u){console.error(`\u{1F98D} Failed to fetch binary resource at ${f}:`,u),ce(o,f,null)}})),o}async function G(){if(typeof navigator<"u"&&!navigator.onLine){k(b.Offline);return}if(k(b.Connecting),await _e()==="walled"){k(b.Walled),Ke();return}Ie()}function Ke(){V||(V=setTimeout(()=>{V=null,G()},ue))}function Ie(){U==="polling"?K():he(!1)}function R(){return C&&C.readyState!==WebSocket.CLOSED||A==="polling"&&T?.isConnected()||W===b.Connecting||G(),M()}function Fe(e){return e==null?!1:e instanceof ArrayBuffer||ArrayBuffer.isView(e)||typeof Blob<"u"&&e instanceof Blob}function Ne(e){return typeof Blob<"u"&&e instanceof Blob?"B":"A"}function qe(e){let t=0;for(let n=0;n<e.length;n++){let o=e.charCodeAt(n);t=(t<<5)-t+o,t=t&t}return Math.abs(t).toString(36)}function N(e,t=""){if(e==null)return{processedData:e,uploads:[]};if(Fe(e)){let n=Ne(e),o=qe(t||"root");return{processedData:{__ape_upload__:o},uploads:[{path:t,hash:o,data:e,tag:n}]}}if(Array.isArray(e)){let n=[],o=[];for(let s=0;s<e.length;s++){let i=t?`${t}.${s}`:String(s),{processedData:l,uploads:c}=N(e[s],i);n.push(l),o.push(...c)}return{processedData:n,uploads:o}}if(typeof e=="object"){let n={},o=[];for(let s of Object.keys(e)){let i=t?`${t}.${s}`:s,{processedData:l,uploads:c}=N(e[s],i);if(c.length>0&&l?.__ape_upload__){let r=c[c.length-1].tag;n[`${s}<!${r}>`]=l.__ape_upload__}else n[s]=l;o.push(...c)}return{processedData:n,uploads:o}}return{processedData:e,uploads:[]}}async function Je(e,t){if(t.length===0)return;let n=window.location.hostname,o=["localhost","127.0.0.1","[::1]"].includes(n),s=window.location.protocol==="https:",i=o?9010:window.location.port||(s?443:80),l=s?"https":"http",c=o||i!==80&&i!==443?`:${i}`:"",r=`${l}://${n}${c}`;console.log(`\u{1F98D} Uploading ${t.length} binary file(s)`),await Promise.all(t.map(async({hash:a,data:p})=>{try{let f=await fetch(`${r}/api/ape/data/${e}/${a}`,{method:"PUT",credentials:"include",headers:{"Content-Type":"application/octet-stream"},body:p});if(!f.ok)throw new Error(`Upload failed: ${f.status}`)}catch(f){throw console.error(`\u{1F98D} Failed to upload binary at ${a}:`,f),f}}))}J=function(e,t,n,o){let s,i=!1,l=n+We-Date.now(),c=setTimeout(()=>{i&&s(new Error("Request Timedout for :"+e))},l),{processedData:r,uploads:a}=N(t),p={type:e,data:r,createdAt:new Date(n),requestedAt:o?void 0:new Date},f=q.default.stringify(p),d=(0,le.default)(f),u=new Promise((h,m)=>{s=m,$[d]=(y,S)=>{clearTimeout(c),u.then=g.bind(u),y?m(y):h(S)},C.send(f),a.length>0&&Je(d,a).catch(y=>{console.error("\u{1F98D} Binary upload failed:",y)})}),g=u.then;u.then=h=>(i=!0,u.then=g.bind(u),u.catch=w.bind(u),g.call(u,h));let w=u.catch;return u.catch=h=>(i=!0,u.catch=w.bind(u),u.then=g.bind(u),w.call(u,h)),u};var Ge=(e,t)=>{if(typeof e!="string")throw new Error("Missing Path vaule");let n=Date.now();if(O)return J(e,t,n,!0);let o=n+Be-Date.now(),s=setTimeout(()=>{let a="Request not sent for :"+e;if(i.waiting)i.err(new Error(a));else throw new Error(a)},o),i={type:e,data:t,next:void 0,err:void 0,waiting:!1,createdAt:n,timer:s},l=new Promise((a,p)=>{i.next=a,i.err=p}),c=l.then,r=l.catch;return l.then=a=>(i.waiting=!0,l.then=c.bind(l),l.catch=r.bind(l),c.call(l,a)),l.catch=a=>(i.waiting=!0,l.catch=r.bind(l),l.then=c.bind(l),r.call(l,a)),P.push(i),C||R(),l};function M(){return{sender:je(Ge),setOnReciver:(e,t)=>{typeof e=="string"?D[e]=[t]:x.includes(e)||x.push(e)},onConnectionChange:e=>(B.push(e),e(W),()=>{let t=B.indexOf(e);t>-1&&B.splice(t,1)}),getTransport:()=>A}}R.autoReconnect=()=>de=!0;R.ConnectionState=b;fe=R;var X=fe;var{sender:Xe,setOnReciver:Ye,onConnectionChange:Qe,getTransport:Ze}=X();X.autoReconnect();window.api=Xe;Object.defineProperty(window.api,"on",{value:Ye,writable:!1,enumerable:!1,configurable:!1});Object.defineProperty(window.api,"onConnectionChange",{value:Qe,writable:!1,enumerable:!1,configurable:!1});Object.defineProperty(window.api,"getTransport",{value:Ze,writable:!1,enumerable:!1,configurable:!1});})();
2
+ //# sourceMappingURL=ape.js.map