termbeam 1.15.1 → 1.16.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 (66) hide show
  1. package/README.md +2 -0
  2. package/package.json +2 -1
  3. package/public/assets/{_basePickBy-DDga1sgN.js → _basePickBy-CYR9pyOe.js} +1 -1
  4. package/public/assets/{_baseUniq-CKfoLvLE.js → _baseUniq-DeFSIx-P.js} +1 -1
  5. package/public/assets/{arc-DbSCVdo8.js → arc-CUEX1fu7.js} +1 -1
  6. package/public/assets/{architectureDiagram-2XIMDMQ5-Ce5knFNR.js → architectureDiagram-2XIMDMQ5-BHhXPzZJ.js} +1 -1
  7. package/public/assets/{blockDiagram-WCTKOSBZ-DJiZx7DH.js → blockDiagram-WCTKOSBZ-RsOwF2Ow.js} +1 -1
  8. package/public/assets/{c4Diagram-IC4MRINW-kOHNvx7n.js → c4Diagram-IC4MRINW-B7KKaZ1J.js} +1 -1
  9. package/public/assets/channel-CBJEzKmm.js +1 -0
  10. package/public/assets/{chunk-4BX2VUAB-DxmUWf39.js → chunk-4BX2VUAB-DOUcZxxl.js} +1 -1
  11. package/public/assets/{chunk-55IACEB6-BdvL648G.js → chunk-55IACEB6-bPgkuqF0.js} +1 -1
  12. package/public/assets/{chunk-FMBD7UC4-Bp3FkcH2.js → chunk-FMBD7UC4-BWT_ExWr.js} +1 -1
  13. package/public/assets/{chunk-JSJVCQXG-DOtbuVd2.js → chunk-JSJVCQXG-Df0AgfkZ.js} +1 -1
  14. package/public/assets/{chunk-KX2RTZJC-b_RAN48_.js → chunk-KX2RTZJC-DnYuhgK5.js} +1 -1
  15. package/public/assets/{chunk-NQ4KR5QH-CKHEKES_.js → chunk-NQ4KR5QH-Dge50UUS.js} +1 -1
  16. package/public/assets/{chunk-QZHKN3VN-Ce3Cy8iK.js → chunk-QZHKN3VN-BT0knyhA.js} +1 -1
  17. package/public/assets/{chunk-WL4C6EOR-CYlFnkd_.js → chunk-WL4C6EOR-DutXGT-d.js} +1 -1
  18. package/public/assets/classDiagram-VBA2DB6C-C-rOD9EU.js +1 -0
  19. package/public/assets/classDiagram-v2-RAHNMMFH-C-rOD9EU.js +1 -0
  20. package/public/assets/clone-DIyhZC23.js +1 -0
  21. package/public/assets/{cose-bilkent-S5V4N54A-Curtohg5.js → cose-bilkent-S5V4N54A-doAicD_V.js} +1 -1
  22. package/public/assets/{dagre-KLK3FWXG-CuZNu96V.js → dagre-KLK3FWXG-O4cFm_hK.js} +1 -1
  23. package/public/assets/{diagram-E7M64L7V-CunKBx6l.js → diagram-E7M64L7V-BifAzLVq.js} +1 -1
  24. package/public/assets/{diagram-IFDJBPK2-BN7aHVm4.js → diagram-IFDJBPK2-BfnxORJG.js} +1 -1
  25. package/public/assets/{diagram-P4PSJMXO-B4lVLdoW.js → diagram-P4PSJMXO-DTr1JYXb.js} +1 -1
  26. package/public/assets/{erDiagram-INFDFZHY-EenQr3uP.js → erDiagram-INFDFZHY-l1N_y881.js} +1 -1
  27. package/public/assets/{flowDiagram-PKNHOUZH-CvFkNm_6.js → flowDiagram-PKNHOUZH-CLGWYVco.js} +1 -1
  28. package/public/assets/{ganttDiagram-A5KZAMGK-DY9bVz9l.js → ganttDiagram-A5KZAMGK-9ERk2sFV.js} +1 -1
  29. package/public/assets/{gitGraphDiagram-K3NZZRJ6-BAd-taYp.js → gitGraphDiagram-K3NZZRJ6-BxK3Z85E.js} +1 -1
  30. package/public/assets/{graph-B5Mupk4w.js → graph-PwJPsvsO.js} +1 -1
  31. package/public/assets/index-0a9Qn-A1.js +394 -0
  32. package/public/assets/index-Z_lybSmO.css +32 -0
  33. package/public/assets/{infoDiagram-LFFYTUFH-vhp46Ys0.js → infoDiagram-LFFYTUFH-DygGOypU.js} +1 -1
  34. package/public/assets/{ishikawaDiagram-PHBUUO56-GppOId5G.js → ishikawaDiagram-PHBUUO56-CySga9vu.js} +1 -1
  35. package/public/assets/{journeyDiagram-4ABVD52K-Bf8IH4_E.js → journeyDiagram-4ABVD52K-ZIZNkXyJ.js} +1 -1
  36. package/public/assets/{kanban-definition-K7BYSVSG-CsV7UppO.js → kanban-definition-K7BYSVSG-IxWUQjiQ.js} +1 -1
  37. package/public/assets/{layout-TFe_JtAk.js → layout-DbFs-9Gp.js} +1 -1
  38. package/public/assets/{linear-jRuCITkz.js → linear-F1crC_h8.js} +1 -1
  39. package/public/assets/{mindmap-definition-YRQLILUH-Drqk-jqT.js → mindmap-definition-YRQLILUH-BwXWnIOB.js} +1 -1
  40. package/public/assets/{pieDiagram-SKSYHLDU-zhtwIYVW.js → pieDiagram-SKSYHLDU-CTKX_qGt.js} +1 -1
  41. package/public/assets/{quadrantDiagram-337W2JSQ-CgighrLO.js → quadrantDiagram-337W2JSQ-C9hYwyla.js} +1 -1
  42. package/public/assets/{requirementDiagram-Z7DCOOCP-Blze02a-.js → requirementDiagram-Z7DCOOCP-eOJ_I7lS.js} +1 -1
  43. package/public/assets/{sankeyDiagram-WA2Y5GQK-DP2pOuJP.js → sankeyDiagram-WA2Y5GQK-CNYzy0Z-.js} +1 -1
  44. package/public/assets/{sequenceDiagram-2WXFIKYE-2ZQZVVEw.js → sequenceDiagram-2WXFIKYE-ChHor0a9.js} +1 -1
  45. package/public/assets/{stateDiagram-RAJIS63D-CxBDjO6s.js → stateDiagram-RAJIS63D-CF2B1sp8.js} +1 -1
  46. package/public/assets/stateDiagram-v2-FVOUBMTO-Doxped-1.js +1 -0
  47. package/public/assets/{timeline-definition-YZTLITO2-Du6zdjZw.js → timeline-definition-YZTLITO2-H72vBjMX.js} +1 -1
  48. package/public/assets/{treemap-KZPCXAKY-Duew5oqq.js → treemap-KZPCXAKY-CWEZDi_m.js} +1 -1
  49. package/public/assets/{vennDiagram-LZ73GAT5-D9zfCBm9.js → vennDiagram-LZ73GAT5-BEqSLv2W.js} +1 -1
  50. package/public/assets/{xychartDiagram-JWTSCODW-BJuwWw4_.js → xychartDiagram-JWTSCODW-enJM4ByX.js} +1 -1
  51. package/public/index.html +2 -2
  52. package/public/sw.js +2 -2
  53. package/src/server/index.js +22 -3
  54. package/src/server/push.js +118 -0
  55. package/src/server/routes.js +227 -1
  56. package/src/server/sessions.js +144 -0
  57. package/src/server/websocket.js +21 -2
  58. package/src/utils/git.js +338 -1
  59. package/src/utils/vapid.js +45 -0
  60. package/public/assets/channel-Ccb6hGZz.js +0 -1
  61. package/public/assets/classDiagram-VBA2DB6C-BIrAPXFF.js +0 -1
  62. package/public/assets/classDiagram-v2-RAHNMMFH-BIrAPXFF.js +0 -1
  63. package/public/assets/clone-D5RGMzJC.js +0 -1
  64. package/public/assets/index-BEOqWnh5.js +0 -391
  65. package/public/assets/index-D_1GL6a5.css +0 -32
  66. package/public/assets/stateDiagram-v2-FVOUBMTO-3AffBMDC.js +0 -1
package/src/utils/git.js CHANGED
@@ -125,4 +125,341 @@ function parseStatus(output, ahead, behind) {
125
125
  return { clean, modified, staged, untracked, ahead: ahead || 0, behind: behind || 0, summary };
126
126
  }
127
127
 
128
- module.exports = { getGitInfo, parseRemoteUrl, parseStatus };
128
+ // --- Extended git utilities (async, using execFile for security) ---
129
+
130
+ const GIT_TIMEOUT = 5000;
131
+ const MAX_DIFF_BUFFER = 1024 * 1024; // 1 MB
132
+ const MAX_BLAME_BUFFER = 2 * 1024 * 1024; // 2 MB
133
+ const MAX_LOG_BUFFER = 1024 * 1024; // 1 MB
134
+
135
+ async function gitAsync(args, cwd, options = {}) {
136
+ return new Promise((resolve, reject) => {
137
+ require('child_process').execFile(
138
+ 'git',
139
+ args,
140
+ {
141
+ cwd,
142
+ timeout: options.timeout || GIT_TIMEOUT,
143
+ maxBuffer: options.maxBuffer || MAX_DIFF_BUFFER,
144
+ },
145
+ (err, stdout) => {
146
+ if (err) return reject(err);
147
+ resolve(stdout);
148
+ },
149
+ );
150
+ });
151
+ }
152
+
153
+ async function getDetailedStatus(cwd) {
154
+ try {
155
+ await gitAsync(['rev-parse', '--is-inside-work-tree'], cwd);
156
+ } catch {
157
+ return { isGitRepo: false };
158
+ }
159
+
160
+ const result = {
161
+ branch: null,
162
+ ahead: 0,
163
+ behind: 0,
164
+ staged: [],
165
+ modified: [],
166
+ untracked: [],
167
+ isGitRepo: true,
168
+ };
169
+
170
+ try {
171
+ const raw = await gitAsync(['status', '--porcelain=v1', '-b'], cwd);
172
+ const lines = raw.split('\n').filter(Boolean);
173
+
174
+ for (const line of lines) {
175
+ // Branch header line
176
+ if (line.startsWith('## ')) {
177
+ const branchInfo = line.slice(3);
178
+ const trackMatch = branchInfo.match(/^(.+?)(?:\.\.\.(.+?))?(?:\s+\[(.+)\])?$/);
179
+ if (trackMatch) {
180
+ result.branch = trackMatch[1];
181
+ const tracking = trackMatch[3];
182
+ if (tracking) {
183
+ const aheadMatch = tracking.match(/ahead (\d+)/);
184
+ const behindMatch = tracking.match(/behind (\d+)/);
185
+ if (aheadMatch) result.ahead = parseInt(aheadMatch[1], 10);
186
+ if (behindMatch) result.behind = parseInt(behindMatch[1], 10);
187
+ }
188
+ }
189
+ continue;
190
+ }
191
+
192
+ const index = line[0];
193
+ const working = line[1];
194
+ const filePart = line.slice(3);
195
+
196
+ // Untracked
197
+ if (index === '?' && working === '?') {
198
+ result.untracked.push(filePart);
199
+ continue;
200
+ }
201
+
202
+ // Staged changes (index column)
203
+ if (index !== ' ' && index !== '?') {
204
+ const entry = { path: filePart, status: index, oldPath: null };
205
+ if (index === 'R' || index === 'C') {
206
+ const parts = filePart.split(' -> ');
207
+ if (parts.length === 2) {
208
+ entry.oldPath = parts[0];
209
+ entry.path = parts[1];
210
+ }
211
+ }
212
+ result.staged.push(entry);
213
+ }
214
+
215
+ // Working tree changes (working column)
216
+ if (working !== ' ' && working !== '?') {
217
+ result.modified.push({ path: filePart, status: working, oldPath: null });
218
+ }
219
+ }
220
+ } catch (err) {
221
+ log.warn(`getDetailedStatus failed: ${err.message}`);
222
+ }
223
+
224
+ return result;
225
+ }
226
+
227
+ async function parseDiffOutput(raw, filePath) {
228
+ const result = {
229
+ file: filePath,
230
+ hunks: [],
231
+ additions: 0,
232
+ deletions: 0,
233
+ isBinary: false,
234
+ };
235
+
236
+ if (!raw.trim()) return result;
237
+
238
+ // Binary file detection — only check the diff header (lines before the first hunk).
239
+ // Content lines (prefixed with +/-/ ) may contain "Binary files ... differ" as text.
240
+ const firstHunkIdx = raw.indexOf('\n@@');
241
+ const header = firstHunkIdx >= 0 ? raw.slice(0, firstHunkIdx) : raw;
242
+ if (header.includes('Binary files') && header.includes('differ')) {
243
+ result.isBinary = true;
244
+ return result;
245
+ }
246
+
247
+ // Parse unified diff into hunks
248
+ const lines = raw.split('\n');
249
+ let currentHunk = null;
250
+ let oldLine = 0;
251
+ let newLine = 0;
252
+
253
+ for (const line of lines) {
254
+ // Hunk header
255
+ const hunkMatch = line.match(/^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
256
+ if (hunkMatch) {
257
+ currentHunk = {
258
+ header: line.match(/^@@.*@@/)[0],
259
+ oldStart: parseInt(hunkMatch[1], 10),
260
+ oldLines: parseInt(hunkMatch[2] ?? '1', 10),
261
+ newStart: parseInt(hunkMatch[3], 10),
262
+ newLines: parseInt(hunkMatch[4] ?? '1', 10),
263
+ lines: [],
264
+ };
265
+ result.hunks.push(currentHunk);
266
+ oldLine = currentHunk.oldStart;
267
+ newLine = currentHunk.newStart;
268
+ continue;
269
+ }
270
+
271
+ if (!currentHunk) continue;
272
+
273
+ if (line.startsWith('+')) {
274
+ currentHunk.lines.push({
275
+ type: 'add',
276
+ content: line.slice(1),
277
+ oldLine: null,
278
+ newLine: newLine++,
279
+ });
280
+ result.additions++;
281
+ } else if (line.startsWith('-')) {
282
+ currentHunk.lines.push({
283
+ type: 'remove',
284
+ content: line.slice(1),
285
+ oldLine: oldLine++,
286
+ newLine: null,
287
+ });
288
+ result.deletions++;
289
+ } else if (line.startsWith(' ')) {
290
+ currentHunk.lines.push({
291
+ type: 'context',
292
+ content: line.slice(1),
293
+ oldLine: oldLine++,
294
+ newLine: newLine++,
295
+ });
296
+ }
297
+ // Skip diff header lines (diff --git, index, ---, +++)
298
+ }
299
+
300
+ return result;
301
+ }
302
+
303
+ async function getFileDiff(cwd, filePath, options = {}) {
304
+ const { staged = false, untracked = false, context = 3 } = options;
305
+
306
+ try {
307
+ // Untracked files: use --no-index to diff against the null device
308
+ const nullDevice = process.platform === 'win32' ? 'NUL' : '/dev/null';
309
+ if (untracked) {
310
+ const raw = await new Promise((resolve, reject) => {
311
+ require('child_process').execFile(
312
+ 'git',
313
+ ['diff', '--no-index', '--no-color', `--unified=${context}`, '--', nullDevice, filePath],
314
+ {
315
+ cwd,
316
+ timeout: GIT_TIMEOUT,
317
+ maxBuffer: MAX_DIFF_BUFFER,
318
+ },
319
+ (err, stdout) => {
320
+ // git diff --no-index exits with 1 when files differ — that's expected
321
+ if (err && err.code !== 1) return reject(err);
322
+ resolve(stdout || '');
323
+ },
324
+ );
325
+ });
326
+ return parseDiffOutput(raw, filePath);
327
+ }
328
+
329
+ const args = ['diff', `--unified=${context}`, '--no-color'];
330
+ if (staged) args.push('--cached');
331
+ args.push('--', filePath);
332
+
333
+ const raw = await gitAsync(args, cwd, { maxBuffer: MAX_DIFF_BUFFER });
334
+ return parseDiffOutput(raw, filePath);
335
+ } catch (err) {
336
+ // Empty diff or git error
337
+ if (err.code !== 1) {
338
+ log.warn(`getFileDiff failed: ${err.message}`);
339
+ }
340
+ }
341
+
342
+ return {
343
+ file: filePath,
344
+ hunks: [],
345
+ additions: 0,
346
+ deletions: 0,
347
+ isBinary: false,
348
+ };
349
+ }
350
+
351
+ async function getFileBlame(cwd, filePath) {
352
+ const result = { file: filePath, lines: [] };
353
+
354
+ try {
355
+ const raw = await gitAsync(['blame', '--porcelain', '--', filePath], cwd, {
356
+ maxBuffer: MAX_BLAME_BUFFER,
357
+ });
358
+
359
+ const rawLines = raw.split('\n');
360
+ let currentCommit = null;
361
+ let currentLine = null;
362
+ const commitInfo = {}; // cache commit metadata
363
+
364
+ for (let i = 0; i < rawLines.length; i++) {
365
+ const line = rawLines[i];
366
+
367
+ // Commit line: <40-char-hash> <orig-line> <final-line> [<num-lines>]
368
+ const commitMatch = line.match(/^([0-9a-f]{40})\s+(\d+)\s+(\d+)(?:\s+(\d+))?$/);
369
+ if (commitMatch) {
370
+ currentCommit = commitMatch[1];
371
+ currentLine = parseInt(commitMatch[3], 10);
372
+
373
+ if (!commitInfo[currentCommit]) {
374
+ commitInfo[currentCommit] = {
375
+ author: null,
376
+ date: null,
377
+ summary: null,
378
+ };
379
+ }
380
+ continue;
381
+ }
382
+
383
+ // Metadata lines
384
+ if (currentCommit && line.startsWith('author ')) {
385
+ commitInfo[currentCommit].author = line.slice(7);
386
+ } else if (currentCommit && line.startsWith('author-time ')) {
387
+ const timestamp = parseInt(line.slice(12), 10);
388
+ commitInfo[currentCommit].date = new Date(timestamp * 1000).toISOString();
389
+ } else if (currentCommit && line.startsWith('summary ')) {
390
+ commitInfo[currentCommit].summary = line.slice(8);
391
+ } else if (currentCommit && line.startsWith('\t')) {
392
+ // Content line
393
+ const info = commitInfo[currentCommit];
394
+ const isUncommitted = currentCommit === '0000000000000000000000000000000000000000';
395
+ result.lines.push({
396
+ line: currentLine,
397
+ content: line.slice(1),
398
+ commit: isUncommitted ? null : currentCommit.slice(0, 7),
399
+ author: isUncommitted ? 'Not Committed Yet' : info.author || 'Unknown',
400
+ date: isUncommitted ? null : info.date || null,
401
+ summary: isUncommitted ? 'Uncommitted changes' : info.summary || '',
402
+ });
403
+ }
404
+ }
405
+ } catch (err) {
406
+ log.warn(`getFileBlame failed: ${err.message}`);
407
+ }
408
+
409
+ return result;
410
+ }
411
+
412
+ const LOG_SEPARATOR = '---GIT_LOG_SEP---';
413
+ const LOG_FIELD_SEP = '---GIT_FIELD_SEP---';
414
+ const LOG_FORMAT = [
415
+ '%H', // hash
416
+ '%h', // short hash
417
+ '%an', // author name
418
+ '%ae', // author email
419
+ '%aI', // author date ISO
420
+ '%s', // subject
421
+ '%b', // body
422
+ ].join(LOG_FIELD_SEP);
423
+
424
+ async function getGitLog(cwd, options = {}) {
425
+ const limit = Math.min(Math.max(parseInt(options.limit, 10) || 20, 1), 100);
426
+ const result = { commits: [] };
427
+
428
+ try {
429
+ const args = ['log', `--format=${LOG_SEPARATOR}${LOG_FORMAT}`, `-n`, String(limit)];
430
+ if (options.file) {
431
+ args.push('--follow', '--', options.file);
432
+ }
433
+
434
+ const raw = await gitAsync(args, cwd, { maxBuffer: MAX_LOG_BUFFER });
435
+
436
+ const entries = raw.split(LOG_SEPARATOR).filter((e) => e.trim());
437
+ for (const entry of entries) {
438
+ const fields = entry.trim().split(LOG_FIELD_SEP);
439
+ if (fields.length < 6) continue;
440
+ result.commits.push({
441
+ hash: fields[0],
442
+ shortHash: fields[1],
443
+ author: fields[2],
444
+ email: fields[3],
445
+ date: fields[4],
446
+ subject: fields[5],
447
+ body: (fields[6] || '').trim(),
448
+ });
449
+ }
450
+ } catch (err) {
451
+ log.warn(`getGitLog failed: ${err.message}`);
452
+ }
453
+
454
+ return result;
455
+ }
456
+
457
+ module.exports = {
458
+ getGitInfo,
459
+ parseRemoteUrl,
460
+ parseStatus,
461
+ getDetailedStatus,
462
+ getFileDiff,
463
+ getFileBlame,
464
+ getGitLog,
465
+ };
@@ -0,0 +1,45 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const webpush = require('web-push');
4
+ const log = require('./logger');
5
+
6
+ /**
7
+ * Load existing VAPID keys from configDir/vapid.json or generate new ones.
8
+ * Keys are persisted so they survive server restarts.
9
+ * @param {string} configDir - Directory to store vapid.json
10
+ * @returns {{ publicKey: string, privateKey: string, subject: string }}
11
+ */
12
+ function getOrCreateVapidKeys(configDir) {
13
+ const vapidPath = path.join(configDir, 'vapid.json');
14
+ const subject = 'https://termbeam.dev';
15
+
16
+ try {
17
+ const raw = fs.readFileSync(vapidPath, 'utf8');
18
+ const keys = JSON.parse(raw);
19
+ if (keys.publicKey && keys.privateKey) {
20
+ log.debug('Loaded existing VAPID keys');
21
+ return { publicKey: keys.publicKey, privateKey: keys.privateKey, subject };
22
+ }
23
+ } catch {
24
+ // File doesn't exist or is invalid — generate new keys
25
+ }
26
+
27
+ log.info('Generating new VAPID keys');
28
+ const keys = webpush.generateVAPIDKeys();
29
+
30
+ try {
31
+ fs.mkdirSync(configDir, { recursive: true });
32
+ fs.writeFileSync(
33
+ vapidPath,
34
+ JSON.stringify({ publicKey: keys.publicKey, privateKey: keys.privateKey }, null, 2),
35
+ { mode: 0o600 },
36
+ );
37
+ log.debug(`VAPID keys saved to ${vapidPath}`);
38
+ } catch (err) {
39
+ log.warn(`Could not save VAPID keys to ${vapidPath}: ${err.message}`);
40
+ }
41
+
42
+ return { publicKey: keys.publicKey, privateKey: keys.privateKey, subject };
43
+ }
44
+
45
+ module.exports = { getOrCreateVapidKeys };
@@ -1 +0,0 @@
1
- import{aq as o,ar as n}from"./index-BEOqWnh5.js";const t=(r,a)=>o.lang.round(n.parse(r)[a]);export{t as c};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-WL4C6EOR-CYlFnkd_.js";import{_ as i}from"./index-BEOqWnh5.js";import"./chunk-FMBD7UC4-Bp3FkcH2.js";import"./chunk-JSJVCQXG-DOtbuVd2.js";import"./chunk-55IACEB6-BdvL648G.js";import"./chunk-KX2RTZJC-b_RAN48_.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{s as a,c as s,a as e,C as t}from"./chunk-WL4C6EOR-CYlFnkd_.js";import{_ as i}from"./index-BEOqWnh5.js";import"./chunk-FMBD7UC4-Bp3FkcH2.js";import"./chunk-JSJVCQXG-DOtbuVd2.js";import"./chunk-55IACEB6-BdvL648G.js";import"./chunk-KX2RTZJC-b_RAN48_.js";var u={parser:e,get db(){return new t},renderer:s,styles:a,init:i(r=>{r.class||(r.class={}),r.class.arrowMarkerAbsolute=r.arrowMarkerAbsolute},"init")};export{u as diagram};
@@ -1 +0,0 @@
1
- import{b as r}from"./_baseUniq-CKfoLvLE.js";var e=4;function a(o){return r(o,e)}export{a as c};