@graphty/graphty-element 2.0.0 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/README.md +3 -3
  2. package/dist/ai.js +4 -4
  3. package/dist/catalog.js +5 -5
  4. package/dist/chunks/{AiManager-D22fxCNb.js → AiManager-DWwQiBQu.js} +5 -5
  5. package/dist/chunks/{Algorithm-BhwPK-aS.js → Algorithm-RQ629NLb.js} +210 -92
  6. package/dist/chunks/{DataSource-7S-7S3M1.js → DataSource-DEg3igzS.js} +3 -3
  7. package/dist/chunks/{GraphSession-DwlThkoy.js → GraphSession-CtqyVNsw.js} +2518 -2239
  8. package/dist/chunks/{GraphtyError-B3eKs4yg.js → GraphtyError-BwcnblTH.js} +10 -8
  9. package/dist/chunks/GraphtyLogger-5KEttFUo.js +752 -0
  10. package/dist/chunks/{NodeStyle-CS7dj20m.js → NodeStyle-Cup9O1lu.js} +2 -1
  11. package/dist/chunks/{VoiceInputAdapter-BrCQEMf0.js → VoiceInputAdapter-mD0x3z7t.js} +1 -1
  12. package/dist/chunks/{XRPivotCameraController-BE1pfwMC.js → XRPivotCameraController-Clil9NhV.js} +2 -2
  13. package/dist/chunks/{cameras-D5LX3ttm.js → cameras-DFXNYBze.js} +2 -2
  14. package/dist/chunks/{capability-check-MH9salUj.js → capability-check-dXwQ_z5B.js} +1 -1
  15. package/dist/chunks/{detect-5cVtGFHg.js → detect-CqN0mC6u.js} +3 -3
  16. package/dist/chunks/{format-detection-Bos-Q387.js → format-detection-C8vbCSlS.js} +1 -1
  17. package/dist/chunks/{index-CqZp3iwq.js → index-2VIpMJZP.js} +1576 -1211
  18. package/dist/chunks/{paletteRegistry-BSjlD98O.js → paletteRegistry-NrWOKT-A.js} +17 -17
  19. package/dist/chunks/{registry-DU-e49Y2.js → registry-CSba5QGJ.js} +1 -1
  20. package/dist/chunks/{scales-DPUY-fFk.js → scales-BUS7NWy2.js} +2206 -1357
  21. package/dist/custom-elements.json +1 -1
  22. package/dist/extend.js +26 -27
  23. package/dist/graphty-catalog.json +7 -4
  24. package/dist/graphty.bundle.js +36288 -34368
  25. package/dist/graphty.js +66 -64
  26. package/dist/index.d.ts +1 -1
  27. package/dist/logging.js +2 -2
  28. package/dist/schema.js +1 -1
  29. package/dist/session.d.ts +2 -1
  30. package/dist/session.js +37 -33
  31. package/dist/src/Edge.d.ts +1 -1
  32. package/dist/src/Graph.d.ts +41 -7
  33. package/dist/src/Node.d.ts +1 -1
  34. package/dist/src/acceleration/AccelerationController.d.ts +27 -0
  35. package/dist/src/acceleration/index.d.ts +1 -1
  36. package/dist/src/acceleration/narrow.d.ts +56 -0
  37. package/dist/src/acceleration/types.d.ts +88 -7
  38. package/dist/src/algorithms/Algorithm.d.ts +96 -2
  39. package/dist/src/algorithms/BFSAlgorithm.d.ts +9 -0
  40. package/dist/src/algorithms/DijkstraAlgorithm.d.ts +2 -8
  41. package/dist/src/algorithms/PageRankAlgorithm.d.ts +8 -0
  42. package/dist/src/algorithms/utils/graphUtils.d.ts +13 -0
  43. package/dist/src/cameras/OrbitCameraController.d.ts +1 -0
  44. package/dist/src/catalog/layouts.d.ts +13 -1
  45. package/dist/src/config/GraphBehavior.d.ts +13 -0
  46. package/dist/src/config/GraphStyle.d.ts +1 -1
  47. package/dist/src/config/StyleTemplate.d.ts +4 -0
  48. package/dist/src/data/CSVDataSource.d.ts +1 -0
  49. package/dist/src/data/csv-variant-detection.d.ts +11 -0
  50. package/dist/src/errors/codes.d.ts +14 -1
  51. package/dist/src/events.d.ts +17 -4
  52. package/dist/src/graphty-element.d.ts +48 -3
  53. package/dist/src/layout/ForceAtlas2LayoutEngine.d.ts +28 -45
  54. package/dist/src/layout/LayoutEngine.d.ts +7 -7
  55. package/dist/src/layout/SimulationLayoutEngine.d.ts +458 -0
  56. package/dist/src/layout/SpringElectricalLayoutEngine.d.ts +32 -0
  57. package/dist/src/layout/SpringLayoutEngine.d.ts +22 -32
  58. package/dist/src/managers/EventManager.d.ts +7 -0
  59. package/dist/src/managers/GraphContext.d.ts +6 -0
  60. package/dist/src/managers/LayoutManager.d.ts +98 -4
  61. package/dist/src/managers/RenderManager.d.ts +7 -0
  62. package/dist/src/managers/UpdateManager.d.ts +1 -1
  63. package/dist/src/session/catalog.d.ts +2 -2
  64. package/dist/src/session/query.d.ts +83 -0
  65. package/dist/src/session/runs/types.d.ts +10 -4
  66. package/dist/src/session/selection/targets.d.ts +20 -3
  67. package/dist/src/session/styles/StylesApi.d.ts +18 -0
  68. package/dist/src/session/styles/legend.d.ts +9 -0
  69. package/dist/src/session/styles/predicate.d.ts +11 -0
  70. package/dist/src/session/styles/sources.d.ts +16 -0
  71. package/dist/src/session/types.d.ts +38 -2
  72. package/dist/src/testing/fakeAccelerator.d.ts +323 -0
  73. package/dist/webgpu.d.ts +23 -1
  74. package/dist/webgpu.js +70 -32
  75. package/package.json +15 -11
  76. package/dist/chunks/GraphtyLogger-DoYeIghs.js +0 -609
  77. package/dist/chunks/types-Dwm9waL2.js +0 -7
@@ -0,0 +1,752 @@
1
+ import { G as c } from "./GraphtyError-BwcnblTH.js";
2
+ import { c as $ } from "./types-B7bX5c0K.js";
3
+ function G(e) {
4
+ const t = /* @__PURE__ */ new Map(), r = /* @__PURE__ */ new Set();
5
+ let s = null;
6
+ return {
7
+ register(i, n) {
8
+ const o = e.idOf(i);
9
+ if (typeof o != "string" || o === "")
10
+ throw new c({
11
+ code: "E_BAD_COMMAND",
12
+ message: `a ${e.kind} registration needs an id`,
13
+ source: "registry",
14
+ details: { kind: e.kind, field: "id" }
15
+ });
16
+ if (e.builtInIds().includes(o))
17
+ throw new c({
18
+ code: "E_DUPLICATE_PLUGIN",
19
+ message: `"${o}" is the id of a ${e.kind} the element ships, and a built-in id may not be taken: a saved document that named it yesterday has to mean the same thing today`,
20
+ source: "registry",
21
+ details: { kind: e.kind, name: o, builtIn: !0 }
22
+ });
23
+ const u = t.get(o);
24
+ if (u !== void 0) {
25
+ if (e.implementationOf(u) === e.implementationOf(i))
26
+ return;
27
+ if (n?.strict === !0)
28
+ throw new c({
29
+ code: "E_DUPLICATE_PLUGIN",
30
+ message: `a ${e.kind} named "${o}" is already registered`,
31
+ source: "registry",
32
+ details: { kind: e.kind, name: o }
33
+ });
34
+ r.has(o) || (r.add(o), console.warn(
35
+ `graphty: a second ${e.kind} named "${o}" replaced the first. Register one implementation per name, or pass { strict: true } to make this throw.`
36
+ ));
37
+ }
38
+ t.set(o, i), s = null;
39
+ },
40
+ entries() {
41
+ return Object.freeze([...t.values()]);
42
+ },
43
+ descriptors() {
44
+ return s ??= Object.freeze([...t.values()].map((i) => e.descriptorOf(i))), s;
45
+ },
46
+ byId(i) {
47
+ return t.get(i);
48
+ },
49
+ clearForTesting() {
50
+ t.clear(), r.clear(), s = null;
51
+ }
52
+ };
53
+ }
54
+ const _ = G({
55
+ kind: "sink",
56
+ idOf: (e) => e.descriptor.id,
57
+ descriptorOf: (e) => e.descriptor,
58
+ implementationOf: (e) => e.create,
59
+ builtInIds: () => $
60
+ });
61
+ function Oe(e, t) {
62
+ const r = e.descriptor;
63
+ if (r === void 0 || typeof r != "object")
64
+ throw new c({
65
+ code: "E_BAD_COMMAND",
66
+ message: "registerLogSink takes a registration with a descriptor",
67
+ source: "registry",
68
+ details: { kind: "sink", field: "descriptor" }
69
+ });
70
+ if (typeof e.create != "function")
71
+ throw new c({
72
+ code: "E_BAD_COMMAND",
73
+ message: `the log destination "${String(r.id)}" was registered without a create function`,
74
+ source: "registry",
75
+ details: { kind: "sink", name: String(r.id), field: "create" }
76
+ });
77
+ _.register(e, t);
78
+ }
79
+ function U() {
80
+ return _.descriptors();
81
+ }
82
+ function v(e) {
83
+ return _.byId(e);
84
+ }
85
+ function Te() {
86
+ _.clearForTesting();
87
+ }
88
+ const F = Object.freeze([
89
+ {
90
+ id: "console",
91
+ plainName: "Browser console",
92
+ description: "Writes each record to the developer console, one line per record.",
93
+ options: [
94
+ {
95
+ name: "colors",
96
+ plainName: "Coloured output",
97
+ type: "boolean",
98
+ // TRUE BECAUSE THAT IS WHAT THE ELEMENT ACTUALLY DOES. The console the element
99
+ // attaches reads `format.colors ?? true`, so a descriptor saying false made a
100
+ // settings panel built from this table show "Coloured output: off" while the
101
+ // element was colouring, and `configure({ sinks: [{ use: "console" }] })`
102
+ // silently turned colour off by filling in a default nobody chose.
103
+ default: !0,
104
+ description: "Tint each line by its level."
105
+ }
106
+ ]
107
+ },
108
+ {
109
+ id: "remote",
110
+ plainName: "Remote log server",
111
+ description: "Batches records and posts them to a log server, for a device whose console nobody can see -- a headset, a phone, a kiosk.",
112
+ options: [
113
+ {
114
+ name: "serverUrl",
115
+ plainName: "Server address",
116
+ type: "string",
117
+ description: "Where records are posted, such as http://localhost:9080."
118
+ },
119
+ {
120
+ name: "sessionPrefix",
121
+ plainName: "Session prefix",
122
+ type: "string",
123
+ default: "graphty",
124
+ description: "Prefixes the session id each batch is filed under."
125
+ },
126
+ {
127
+ name: "batchIntervalMs",
128
+ plainName: "Batch interval",
129
+ type: "integer",
130
+ default: 100,
131
+ min: 0,
132
+ description: "How long records are collected before a batch is sent, in milliseconds."
133
+ },
134
+ {
135
+ name: "maxRetries",
136
+ plainName: "Retries",
137
+ type: "integer",
138
+ default: 3,
139
+ min: 0,
140
+ description: "How many times a failed batch is resent before it is dropped."
141
+ },
142
+ {
143
+ name: "retryDelayMs",
144
+ plainName: "Retry delay",
145
+ type: "integer",
146
+ default: 1e3,
147
+ min: 0,
148
+ description: "How long to wait between retries, in milliseconds."
149
+ },
150
+ {
151
+ name: "throttleMs",
152
+ plainName: "Throttle window",
153
+ type: "integer",
154
+ default: 5e3,
155
+ min: 0,
156
+ description: "How long a repeated message is suppressed for, in milliseconds."
157
+ }
158
+ ]
159
+ }
160
+ ]);
161
+ function j(e) {
162
+ return F.find((t) => t.id === e) ?? v(e)?.descriptor;
163
+ }
164
+ const x = 3;
165
+ function B(e, t) {
166
+ let r = Array.from({ length: t.length + 1 }, (s, i) => i);
167
+ for (let s = 1; s <= e.length; s++) {
168
+ const i = [s];
169
+ for (let n = 1; n <= t.length; n++) {
170
+ const o = (r[n - 1] ?? 0) + (e[s - 1] === t[n - 1] ? 0 : 1);
171
+ i[n] = Math.min(o, (r[n] ?? 0) + 1, (i[n - 1] ?? 0) + 1);
172
+ }
173
+ r = i;
174
+ }
175
+ return r[t.length] ?? Math.max(e.length, t.length);
176
+ }
177
+ function W(e, t) {
178
+ return t.map((r) => ({ name: r, distance: B(e.toLowerCase(), r.toLowerCase()) })).filter((r) => r.distance <= x).sort((r, s) => r.distance - s.distance).slice(0, 3).map((r) => r.name);
179
+ }
180
+ function O(e) {
181
+ return typeof e == "number" ? e : void 0;
182
+ }
183
+ function K(e, t, r) {
184
+ const s = { kind: r.kind, id: r.id, option: e.name, value: t };
185
+ if (e.type === "enum" && e.values !== void 0) {
186
+ const i = e.values.map((n) => n.value);
187
+ if (typeof t != "string" || !i.includes(t))
188
+ throw new c({
189
+ code: "E_OPTION_RANGE",
190
+ message: `"${e.name}" accepts ${i.map((n) => `"${n}"`).join(", ")}`,
191
+ source: "config",
192
+ details: { ...s, values: i }
193
+ });
194
+ return;
195
+ }
196
+ if (e.type === "number" || e.type === "integer") {
197
+ if (typeof t != "number" || !Number.isFinite(t))
198
+ throw new c({
199
+ code: "E_OPTION_RANGE",
200
+ message: `"${e.name}" takes a number`,
201
+ source: "config",
202
+ details: s
203
+ });
204
+ if (e.type === "integer" && !Number.isInteger(t))
205
+ throw new c({
206
+ code: "E_OPTION_RANGE",
207
+ message: `"${e.name}" takes a whole number`,
208
+ source: "config",
209
+ details: s
210
+ });
211
+ const i = O(e.min), n = O(e.max);
212
+ if (i !== void 0 && t < i || n !== void 0 && t > n)
213
+ throw new c({
214
+ code: "E_OPTION_RANGE",
215
+ message: `"${e.name}" is limited to ${i ?? "any"} through ${n ?? "any"}`,
216
+ source: "config",
217
+ details: { ...s, min: i, max: n }
218
+ });
219
+ return;
220
+ }
221
+ if (e.type === "boolean" && typeof t != "boolean")
222
+ throw new c({
223
+ code: "E_OPTION_RANGE",
224
+ message: `"${e.name}" takes true or false`,
225
+ source: "config",
226
+ details: s
227
+ });
228
+ }
229
+ function T(e, t, r) {
230
+ const s = new Map(e.map((n) => [n.name, n]));
231
+ for (const n of Object.keys(t))
232
+ if (!s.has(n)) {
233
+ const o = e.map((u) => u.name);
234
+ throw new c({
235
+ code: "E_UNKNOWN_OPTION",
236
+ message: `the ${r.kind} "${r.id}" has no option named "${n}"`,
237
+ source: "config",
238
+ details: {
239
+ kind: r.kind,
240
+ id: r.id,
241
+ option: n,
242
+ available: o,
243
+ candidates: W(n, o)
244
+ }
245
+ });
246
+ }
247
+ const i = {};
248
+ for (const n of e) {
249
+ const o = t[n.name];
250
+ if (o === void 0) {
251
+ n.default !== void 0 && (i[n.name] = n.default);
252
+ continue;
253
+ }
254
+ K(n, o, r), i[n.name] = o;
255
+ }
256
+ return i;
257
+ }
258
+ var l = /* @__PURE__ */ ((e) => (e[e.SILENT = 0] = "SILENT", e[e.ERROR = 1] = "ERROR", e[e.WARN = 2] = "WARN", e[e.INFO = 3] = "INFO", e[e.DEBUG = 4] = "DEBUG", e[e.TRACE = 5] = "TRACE", e))(l || {});
259
+ const H = {
260
+ silent: 0,
261
+ error: 1,
262
+ warn: 2,
263
+ info: 3,
264
+ debug: 4,
265
+ trace: 5
266
+ /* TRACE */
267
+ }, N = {
268
+ 0: "SILENT",
269
+ 1: "ERROR",
270
+ 2: "WARN",
271
+ 3: "INFO",
272
+ 4: "DEBUG",
273
+ 5: "TRACE"
274
+ };
275
+ function be(e) {
276
+ return H[e.toLowerCase()];
277
+ }
278
+ const y = {
279
+ enabled: !1,
280
+ level: l.INFO,
281
+ modules: "*",
282
+ format: {
283
+ timestamp: !0,
284
+ module: !0,
285
+ colors: !0
286
+ }
287
+ };
288
+ let a = { ...y, format: { ...y.format } };
289
+ function z(e) {
290
+ a = {
291
+ enabled: e.enabled ?? a.enabled,
292
+ level: e.level ?? a.level,
293
+ modules: e.modules ?? a.modules,
294
+ moduleLevels: e.moduleLevels ?? a.moduleLevels,
295
+ format: {
296
+ timestamp: e.format?.timestamp ?? a.format.timestamp,
297
+ timestampFormat: e.format?.timestampFormat ?? a.format.timestampFormat,
298
+ module: e.format?.module ?? a.format.module,
299
+ colors: e.format?.colors ?? a.format.colors
300
+ }
301
+ };
302
+ }
303
+ function b(e) {
304
+ const t = a.moduleLevels;
305
+ if (t === void 0)
306
+ return a.level;
307
+ for (let r = e.length - 1; r >= 0; r--) {
308
+ const s = t[e[r]];
309
+ if (s !== void 0)
310
+ return s;
311
+ }
312
+ return a.level;
313
+ }
314
+ function m() {
315
+ return { ...a, format: { ...a.format } };
316
+ }
317
+ function k(e) {
318
+ if (!a.enabled || e.length === 0)
319
+ return !1;
320
+ if (a.modules === "*")
321
+ return !0;
322
+ const t = a.modules;
323
+ for (const r of t)
324
+ if (e.includes(r))
325
+ return !0;
326
+ return !1;
327
+ }
328
+ function ke() {
329
+ a = { ...y, format: { ...y.format } };
330
+ }
331
+ function R(e, t) {
332
+ const { format: r } = m(), s = t?.timestamp ?? r.timestamp, i = t?.module ?? r.module, n = [];
333
+ return s && n.push(`[${e.timestamp.toISOString()}]`), i && n.push(`[${e.category.join(".")}]`), n.push(`[${N[e.level]}]`), n.push(e.message), n.join(" ");
334
+ }
335
+ const I = /* @__PURE__ */ Symbol.for("graphty.lazy");
336
+ function Me(e) {
337
+ let t, r = !1;
338
+ const s = () => (r || (t = e(), r = !0), t);
339
+ return s[I] = !0, s;
340
+ }
341
+ function J(e) {
342
+ return typeof e == "function" && I in e;
343
+ }
344
+ function V(e) {
345
+ const t = {};
346
+ for (const [r, s] of Object.entries(e))
347
+ t[r] = J(s) ? s() : s;
348
+ return t;
349
+ }
350
+ function q(e) {
351
+ switch (e) {
352
+ case l.ERROR:
353
+ return "error";
354
+ case l.WARN:
355
+ return "warn";
356
+ case l.INFO:
357
+ return "info";
358
+ default:
359
+ return "debug";
360
+ }
361
+ }
362
+ function Y(e) {
363
+ const t = { ...e.data };
364
+ return e.error && (t.error = e.error.stack ?? e.error.message), Object.keys(t).length > 0 ? t : void 0;
365
+ }
366
+ function S(e = {}) {
367
+ const t = e.formatter ?? R, r = e.colors ?? !0;
368
+ return {
369
+ name: "console",
370
+ write(s) {
371
+ const i = t(s), n = r ? q(s.level) : "log", o = Y(s);
372
+ o ? console[n](i, o) : console[n](i);
373
+ }
374
+ };
375
+ }
376
+ function M(e) {
377
+ try {
378
+ if (e === "__REMOTE_LOG_PROJECT_MARKER__")
379
+ return typeof __REMOTE_LOG_PROJECT_MARKER__ < "u" ? __REMOTE_LOG_PROJECT_MARKER__ : void 0;
380
+ if (e === "__REMOTE_LOG_WORKTREE_PATH__")
381
+ return typeof __REMOTE_LOG_WORKTREE_PATH__ < "u" ? __REMOTE_LOG_WORKTREE_PATH__ : void 0;
382
+ } catch {
383
+ return;
384
+ }
385
+ }
386
+ const X = 1e3, Z = 3, Q = 1e3, ee = "session", te = 5e3;
387
+ function re(e) {
388
+ const t = Date.now().toString(36), r = Math.random().toString(36).substring(2, 8);
389
+ return `${e}-${t}-${r}`;
390
+ }
391
+ class ne {
392
+ /**
393
+ * Creates a new RemoteLogClient.
394
+ * @param options - Configuration options
395
+ */
396
+ constructor(t) {
397
+ this.pendingLogs = [], this.batchTimer = null, this.isClosed = !1, this.flushPromise = null, this.throttleLastTimes = /* @__PURE__ */ new Map(), this.serverUrl = t.serverUrl, this.sessionId = re(t.sessionPrefix ?? ee), this.batchIntervalMs = t.batchIntervalMs ?? X, this.maxRetries = t.maxRetries ?? Z, this.retryDelayMs = t.retryDelayMs ?? Q, this.throttlePatterns = t.throttlePatterns ?? [], this.timeoutMs = t.timeoutMs ?? te, this.projectMarker = t.projectMarker ?? M("__REMOTE_LOG_PROJECT_MARKER__"), this.worktreePath = t.worktreePath ?? M("__REMOTE_LOG_WORKTREE_PATH__");
398
+ }
399
+ /**
400
+ * Checks if a message should be throttled based on configured patterns.
401
+ * Updates the last time tracking if the message is allowed through.
402
+ * @param message - The message to check
403
+ * @returns true if the message should be dropped (throttled)
404
+ */
405
+ shouldThrottle(t) {
406
+ const r = Date.now();
407
+ for (const { pattern: s, intervalMs: i } of this.throttlePatterns)
408
+ if (s.test(t)) {
409
+ const n = s.source, o = this.throttleLastTimes.get(n) ?? 0;
410
+ return r - o < i ? !0 : (this.throttleLastTimes.set(n, r), !1);
411
+ }
412
+ return !1;
413
+ }
414
+ /**
415
+ * Logs a message at the specified level.
416
+ * @param level - Log level (e.g., "INFO", "DEBUG", "WARN", "ERROR")
417
+ * @param message - The log message
418
+ * @param data - Optional additional data to include
419
+ */
420
+ log(t, r, s) {
421
+ if (this.isClosed || this.shouldThrottle(r))
422
+ return;
423
+ const i = {
424
+ time: (/* @__PURE__ */ new Date()).toISOString(),
425
+ level: t,
426
+ message: r,
427
+ ...s !== void 0 && { data: s }
428
+ };
429
+ this.pendingLogs.push(i), this.scheduleBatchSend();
430
+ }
431
+ /**
432
+ * Schedules a batch send after the configured interval.
433
+ * If a timer is already scheduled, does nothing.
434
+ */
435
+ scheduleBatchSend() {
436
+ this.batchTimer !== null || this.isClosed || (this.batchTimer = setTimeout(() => {
437
+ this.batchTimer = null, this.sendBatch();
438
+ }, this.batchIntervalMs));
439
+ }
440
+ /**
441
+ * Sends the current batch of logs to the server.
442
+ * Uses retry logic with exponential backoff on failure.
443
+ */
444
+ async sendBatch() {
445
+ if (this.pendingLogs.length === 0)
446
+ return;
447
+ const t = this.pendingLogs;
448
+ this.pendingLogs = [], await this.sendWithRetry(t);
449
+ }
450
+ /**
451
+ * Sends logs with retry logic using exponential backoff.
452
+ * @param logs - The log entries to send
453
+ */
454
+ async sendWithRetry(t) {
455
+ let r = null;
456
+ for (let s = 0; s <= this.maxRetries; s++)
457
+ try {
458
+ await this.sendRequest(t);
459
+ return;
460
+ } catch (i) {
461
+ if (r = i instanceof Error ? i : new Error(String(i)), s < this.maxRetries) {
462
+ const n = this.retryDelayMs * Math.pow(2, s);
463
+ await this.sleep(n);
464
+ }
465
+ }
466
+ console.error("[RemoteLogClient] Failed to send logs after retries:", r?.message);
467
+ }
468
+ /**
469
+ * Makes the actual HTTP request to send logs.
470
+ * @param logs - The log entries to send
471
+ * @throws Error if the request fails or times out
472
+ */
473
+ async sendRequest(t) {
474
+ const r = {
475
+ sessionId: this.sessionId,
476
+ logs: t
477
+ };
478
+ this.projectMarker !== void 0 && (r.projectMarker = this.projectMarker), this.worktreePath !== void 0 && (r.worktreePath = this.worktreePath);
479
+ const s = new AbortController(), i = setTimeout(() => {
480
+ s.abort();
481
+ }, this.timeoutMs);
482
+ try {
483
+ const n = await fetch(`${this.serverUrl}/log`, {
484
+ method: "POST",
485
+ headers: {
486
+ "Content-Type": "application/json"
487
+ },
488
+ body: JSON.stringify(r),
489
+ signal: s.signal
490
+ });
491
+ if (!n.ok)
492
+ throw new Error(`HTTP ${n.status}: ${n.statusText}`);
493
+ } finally {
494
+ clearTimeout(i);
495
+ }
496
+ }
497
+ /**
498
+ * Helper to sleep for the specified duration.
499
+ * @param ms - Milliseconds to sleep
500
+ * @returns A promise that resolves after the specified time
501
+ */
502
+ sleep(t) {
503
+ return new Promise((r) => setTimeout(r, t));
504
+ }
505
+ /**
506
+ * Immediately flushes all pending logs to the server.
507
+ * Useful before page unload or when immediate delivery is needed.
508
+ */
509
+ async flush() {
510
+ this.batchTimer !== null && (clearTimeout(this.batchTimer), this.batchTimer = null), this.flushPromise !== null && await this.flushPromise, this.pendingLogs.length > 0 && (this.flushPromise = this.sendBatch(), await this.flushPromise, this.flushPromise = null);
511
+ }
512
+ /**
513
+ * Closes the client, flushing any pending logs and stopping the batch timer.
514
+ * After calling close(), no more logs will be accepted.
515
+ */
516
+ async close() {
517
+ this.isClosed || (this.isClosed = !0, await this.flush());
518
+ }
519
+ }
520
+ function se(e) {
521
+ const t = [R(e, { timestamp: !1, module: !0 })];
522
+ if (e.data && Object.keys(e.data).length > 0)
523
+ try {
524
+ t.push(JSON.stringify(e.data));
525
+ } catch {
526
+ t.push("[non-serializable data]");
527
+ }
528
+ return e.error && (t.push(`
529
+ Error: ${e.error.message}`), e.error.stack && t.push(`
530
+ ${e.error.stack}`)), t.join(" ");
531
+ }
532
+ function L(e) {
533
+ const t = e.serverUrl.replace(/\/$/, ""), r = e.sessionPrefix ?? "graphty", s = e.batchIntervalMs ?? 100, i = e.maxRetries ?? 3, n = e.retryDelayMs ?? 1e3, o = e.throttleMs ?? 5e3, u = e.throttlePatterns?.map((f) => ({
534
+ pattern: f,
535
+ intervalMs: o
536
+ })), h = new ne({
537
+ serverUrl: t,
538
+ sessionPrefix: r,
539
+ batchIntervalMs: s,
540
+ maxRetries: i,
541
+ retryDelayMs: n,
542
+ throttlePatterns: u
543
+ });
544
+ return {
545
+ name: "remote",
546
+ write(f) {
547
+ const D = se(f), C = N[f.level];
548
+ h.log(C, D, f.data);
549
+ },
550
+ async flush() {
551
+ await h.flush();
552
+ },
553
+ /*
554
+ * The client holds a batch timer, and before `dispose` existed nothing ever stopped it:
555
+ * removing this destination left it posting to a server the page had stopped listening
556
+ * to. `close` sends what is buffered first, so records already accepted are not lost.
557
+ */
558
+ async dispose() {
559
+ await h.close();
560
+ }
561
+ };
562
+ }
563
+ const E = /* @__PURE__ */ new Map(), d = /* @__PURE__ */ new Map();
564
+ let w;
565
+ function ie(e) {
566
+ return e.join(".");
567
+ }
568
+ function A(e) {
569
+ if (e.dispose)
570
+ try {
571
+ const t = e.dispose();
572
+ t instanceof Promise && t.catch((r) => {
573
+ console.error(`[GraphtyLogger] Error disposing sink "${e.name}":`, r);
574
+ });
575
+ } catch (t) {
576
+ console.error(`[GraphtyLogger] Error disposing sink "${e.name}":`, t);
577
+ }
578
+ }
579
+ function oe(e, t) {
580
+ return e.level !== void 0 && t.level > e.level ? !1 : e.categories !== void 0 && e.categories.length > 0 ? e.categories.some((r) => t.category.includes(r)) : !0;
581
+ }
582
+ function ae(e) {
583
+ e.data && Object.freeze(e.data), Object.freeze(e);
584
+ for (const t of d.values())
585
+ if (oe(t, e))
586
+ try {
587
+ t.write(e);
588
+ } catch (r) {
589
+ console.error(`[GraphtyLogger] Error in sink "${t.name}":`, r);
590
+ }
591
+ }
592
+ function le(e) {
593
+ const t = (i, n, o, u) => {
594
+ if (!m().enabled || !k(e) || i > b(e))
595
+ return;
596
+ const f = o ? V(o) : void 0;
597
+ ae({
598
+ timestamp: /* @__PURE__ */ new Date(),
599
+ level: i,
600
+ category: e,
601
+ message: n,
602
+ data: f,
603
+ error: u
604
+ });
605
+ }, r = (i) => (n, o) => {
606
+ t(i, n, o);
607
+ }, s = (i) => m().enabled && k(e) && b(e) >= i;
608
+ return {
609
+ trace: r(l.TRACE),
610
+ debug: r(l.DEBUG),
611
+ info: r(l.INFO),
612
+ warn: r(l.WARN),
613
+ error: (i, n, o) => {
614
+ t(l.ERROR, i, o, n);
615
+ },
616
+ isTraceEnabled: () => s(l.TRACE),
617
+ isDebugEnabled: () => s(l.DEBUG)
618
+ };
619
+ }
620
+ function ce(e) {
621
+ return S({ colors: e.colors === !0 });
622
+ }
623
+ function g(e) {
624
+ return typeof e == "number" ? e : void 0;
625
+ }
626
+ function ue(e) {
627
+ return L({
628
+ serverUrl: typeof e.serverUrl == "string" ? e.serverUrl : "",
629
+ sessionPrefix: typeof e.sessionPrefix == "string" ? e.sessionPrefix : void 0,
630
+ batchIntervalMs: g(e.batchIntervalMs),
631
+ maxRetries: g(e.maxRetries),
632
+ retryDelayMs: g(e.retryDelayMs),
633
+ throttleMs: g(e.throttleMs)
634
+ });
635
+ }
636
+ const P = /* @__PURE__ */ new Map([
637
+ ["console", ce],
638
+ ["remote", ue]
639
+ ]);
640
+ function fe() {
641
+ return [...P.keys(), ...U().map((e) => e.id)];
642
+ }
643
+ function de(e) {
644
+ throw new c({
645
+ code: "E_UNKNOWN_SINK",
646
+ message: `nothing is registered as the log destination "${e}". Register it with registerLogSink before naming it in a configuration.`,
647
+ source: "config",
648
+ details: { kind: "sink", name: e, available: fe() }
649
+ });
650
+ }
651
+ function me(e) {
652
+ const t = e.use, r = e.options ?? {}, s = v(t);
653
+ if (s)
654
+ return s.create(T(s.descriptor.options, r, { kind: "sink", id: t }));
655
+ const i = P.get(t), n = j(t);
656
+ return (!i || !n) && de(t), i(T(n.options, r, { kind: "sink", id: t }));
657
+ }
658
+ function p(e) {
659
+ const t = d.get(e.name);
660
+ t && t !== e && A(t), d.set(e.name, e);
661
+ }
662
+ function he(e) {
663
+ z(e), p(S({ colors: m().format.colors ?? !0 }));
664
+ const { remoteLogUrl: t } = e;
665
+ t && t !== w && (w = t, p(L({ serverUrl: t })));
666
+ for (const r of e.sinks ?? [])
667
+ p("write" in r ? r : me(r));
668
+ return E.clear(), Promise.resolve();
669
+ }
670
+ function ge(e) {
671
+ const t = d.get(e);
672
+ return t ? (d.delete(e), A(t), e === "remote" && (w = void 0), !0) : !1;
673
+ }
674
+ function pe() {
675
+ return Array.from(d.values());
676
+ }
677
+ async function ye() {
678
+ const e = [];
679
+ for (const t of d.values())
680
+ t.flush && e.push(
681
+ t.flush().catch((r) => {
682
+ console.error(`[GraphtyLogger] Error flushing sink "${t.name}":`, r);
683
+ })
684
+ );
685
+ await Promise.all(e);
686
+ }
687
+ function _e(e) {
688
+ const t = ie(e), r = E.get(t);
689
+ if (r)
690
+ return r;
691
+ const s = le(e);
692
+ return E.set(t, s), s;
693
+ }
694
+ function Ee() {
695
+ return m().enabled;
696
+ }
697
+ const ve = {
698
+ /**
699
+ * Configure the logging system.
700
+ */
701
+ configure: he,
702
+ /**
703
+ * Get a logger for the specified category.
704
+ */
705
+ getLogger: _e,
706
+ /**
707
+ * Check if logging is enabled.
708
+ */
709
+ isEnabled: Ee,
710
+ /**
711
+ * Add a custom sink to the logger.
712
+ */
713
+ addSink: p,
714
+ /**
715
+ * Remove a sink by name.
716
+ */
717
+ removeSink: ge,
718
+ /**
719
+ * Get all registered sinks.
720
+ */
721
+ getSinks: pe,
722
+ /**
723
+ * Flush all sinks that support flushing.
724
+ */
725
+ flush: ye,
726
+ /**
727
+ * Render a record the way the element renders its own console line.
728
+ */
729
+ formatRecord: R
730
+ };
731
+ export {
732
+ ve as G,
733
+ F as L,
734
+ U as a,
735
+ T as b,
736
+ Te as c,
737
+ l as d,
738
+ H as e,
739
+ N as f,
740
+ z as g,
741
+ S as h,
742
+ L as i,
743
+ R as j,
744
+ m as k,
745
+ j as l,
746
+ k as m,
747
+ Me as n,
748
+ ke as o,
749
+ be as p,
750
+ G as q,
751
+ Oe as r
752
+ };