@takodotid/circuit 0.19.0 → 0.20.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 (49) hide show
  1. package/README.md +2 -2
  2. package/dist/chunks/index-jtzfw679.js +936 -0
  3. package/dist/chunks/{index-dczpxzzm.js → index-xm9nma2t.js} +20 -1
  4. package/dist/chunks/server-5shmsmse.js +246 -0
  5. package/dist/cli/index.js +544 -487
  6. package/dist/index.js +1 -1
  7. package/dist/presets/index.js +1 -1
  8. package/dist/types/adapters/devices/derive.d.ts +2 -0
  9. package/dist/types/core/across.d.ts +4 -0
  10. package/dist/types/core/addr.d.ts +10 -0
  11. package/dist/types/core/addresses.d.ts +46 -0
  12. package/dist/types/core/files.d.ts +6 -0
  13. package/dist/types/core/graph.d.ts +31 -1
  14. package/dist/types/core/schema-docs.d.ts +16 -0
  15. package/package.json +1 -1
  16. package/src/adapters/devices/derive.ts +32 -0
  17. package/src/adapters/devices/raisecom-ros/index.ts +23 -3
  18. package/src/adapters/devices/routeros/index.ts +10 -0
  19. package/src/adapters/devices/vrp/index.ts +10 -1
  20. package/src/cli/graph.ts +1 -15
  21. package/src/cli/index.ts +154 -20
  22. package/src/cli/rename.ts +129 -0
  23. package/src/core/across.ts +322 -0
  24. package/src/core/addr.ts +29 -0
  25. package/src/core/addresses.ts +316 -0
  26. package/src/core/files.ts +30 -0
  27. package/src/core/graph.ts +27 -6
  28. package/src/core/schema-docs.ts +166 -0
  29. package/src/core/validate.ts +2 -52
  30. package/src/studio/data.ts +255 -0
  31. package/src/studio/git.ts +119 -0
  32. package/src/studio/public/app.js +147 -0
  33. package/src/studio/public/compare.js +243 -0
  34. package/src/studio/public/diff.js +97 -0
  35. package/src/studio/public/dom.js +108 -0
  36. package/src/studio/public/evaluate.js +648 -0
  37. package/src/studio/public/export.js +122 -0
  38. package/src/studio/public/favicon.svg +6 -0
  39. package/src/studio/public/graph.js +914 -0
  40. package/src/studio/public/index.html +67 -0
  41. package/src/studio/public/net.js +128 -0
  42. package/src/studio/public/style.css +693 -0
  43. package/src/studio/public/tables.js +1223 -0
  44. package/src/studio/public/tools.js +578 -0
  45. package/src/studio/server.ts +218 -0
  46. package/templates/project/AGENTS.md +2 -0
  47. package/dist/chunks/studio-femhydvd.js +0 -764
  48. package/src/cli/studio-page.ts +0 -876
  49. package/src/cli/studio.ts +0 -126
@@ -0,0 +1,693 @@
1
+ /* Circuit Studio's look, the documentation site's own: Inter for text, Newsreader for headings, terracotta for the brand, and VitePress's neutrals. Colors are tokens, redefined for a dark screen; then the page, the tables and the graph. */
2
+ :root {
3
+ --bg: #f6f6f7;
4
+ --surface: #ffffff;
5
+ --line: #e2e2e3;
6
+ --text: #3c3c43;
7
+ --muted: #67676c;
8
+ --edge: #929295;
9
+ --accent: #a8432b;
10
+ --accent-strong: #b4492f;
11
+ --on-accent: #ffffff;
12
+ --error: #b8272c;
13
+ --error-strong: #b8272c;
14
+ --warning: #915930;
15
+ --warning-strong: #9f6a00;
16
+ --ok: #18794e;
17
+ --segment: rgba(180, 73, 47, 0.08);
18
+ --font: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
19
+ --serif: "Newsreader", "Iowan Old Style", "Palatino Linotype", Georgia, serif;
20
+ --mono: ui-monospace, "Menlo", "Monaco", "Consolas", "Liberation Mono", "Courier New", monospace;
21
+ }
22
+ @media (prefers-color-scheme: dark) {
23
+ :root {
24
+ --bg: #161618;
25
+ --surface: #1b1b1f;
26
+ --line: #2e2e32;
27
+ --text: #dfdfd6;
28
+ --muted: #98989f;
29
+ --edge: #6a6a71;
30
+ --accent: #e8866b;
31
+ --accent-strong: #b4492f;
32
+ --error: #f66f81;
33
+ --error-strong: #b62a3c;
34
+ --warning: #f9b44e;
35
+ --warning-strong: #a46a0a;
36
+ --ok: #3dd68c;
37
+ --segment: rgba(232, 134, 107, 0.12);
38
+ }
39
+ }
40
+ * {
41
+ box-sizing: border-box;
42
+ }
43
+ html,
44
+ body {
45
+ margin: 0;
46
+ height: 100%;
47
+ background: var(--bg);
48
+ color: var(--text);
49
+ font: 14px/1.45 var(--font);
50
+ }
51
+ body {
52
+ display: flex;
53
+ flex-direction: column;
54
+ }
55
+ button {
56
+ font: inherit;
57
+ color: inherit;
58
+ background: var(--surface);
59
+ border: 1px solid var(--line);
60
+ border-radius: 6px;
61
+ padding: 4px 10px;
62
+ cursor: pointer;
63
+ }
64
+ button:hover {
65
+ border-color: var(--accent);
66
+ }
67
+ button[aria-pressed="true"] {
68
+ background: var(--accent-strong);
69
+ border-color: var(--accent-strong);
70
+ color: var(--on-accent);
71
+ }
72
+ header {
73
+ display: flex;
74
+ flex-wrap: wrap;
75
+ align-items: center;
76
+ gap: 8px 16px;
77
+ padding: 10px 16px;
78
+ background: var(--surface);
79
+ border-bottom: 1px solid var(--line);
80
+ }
81
+ /* The wordmark is Circuit's own; Studio is set apart from it, as the part of Circuit this is. */
82
+ header .brand {
83
+ display: flex;
84
+ align-items: baseline;
85
+ gap: 8px;
86
+ }
87
+ header .wordmark {
88
+ font-family: var(--serif);
89
+ font-size: 22px;
90
+ font-weight: 400;
91
+ letter-spacing: -0.01em;
92
+ }
93
+ header .product {
94
+ font-size: 13px;
95
+ font-weight: 500;
96
+ color: var(--accent);
97
+ padding-left: 8px;
98
+ border-left: 1px solid var(--line);
99
+ }
100
+ code {
101
+ font-family: var(--mono);
102
+ font-size: 0.92em;
103
+ }
104
+ nav,
105
+ .actions {
106
+ display: flex;
107
+ flex-wrap: wrap;
108
+ gap: 6px;
109
+ }
110
+ .count {
111
+ opacity: 0.7;
112
+ margin-left: 4px;
113
+ font-size: 12px;
114
+ }
115
+ header input[type="search"] {
116
+ font: inherit;
117
+ color: inherit;
118
+ background: var(--bg);
119
+ border: 1px solid var(--line);
120
+ border-radius: 6px;
121
+ padding: 4px 10px;
122
+ width: 220px;
123
+ max-width: 100%;
124
+ }
125
+ header input[type="search"]:focus {
126
+ outline: 2px solid var(--accent);
127
+ outline-offset: -1px;
128
+ }
129
+ a {
130
+ color: var(--accent);
131
+ cursor: pointer;
132
+ text-decoration: none;
133
+ }
134
+ a:hover {
135
+ text-decoration: underline;
136
+ }
137
+ .muted {
138
+ color: var(--muted);
139
+ }
140
+ header .summary {
141
+ color: var(--muted);
142
+ font-size: 13px;
143
+ }
144
+ header .live {
145
+ margin-left: auto;
146
+ color: var(--muted);
147
+ font-size: 12px;
148
+ }
149
+ header .live::before {
150
+ content: "";
151
+ display: inline-block;
152
+ width: 8px;
153
+ height: 8px;
154
+ border-radius: 50%;
155
+ background: var(--warning);
156
+ margin-right: 6px;
157
+ }
158
+ header .live.on::before {
159
+ background: var(--ok);
160
+ }
161
+ .banner {
162
+ margin: 0;
163
+ padding: 10px 16px;
164
+ background: var(--error-strong);
165
+ color: var(--on-accent);
166
+ white-space: pre-wrap;
167
+ font: 12px/1.4 var(--mono);
168
+ max-height: 30vh;
169
+ overflow: auto;
170
+ }
171
+ main {
172
+ flex: 1;
173
+ display: flex;
174
+ flex-direction: column;
175
+ min-height: 0;
176
+ }
177
+ .view {
178
+ flex: 1;
179
+ display: flex;
180
+ flex-direction: column;
181
+ min-height: 0;
182
+ }
183
+ .view[hidden] {
184
+ display: none;
185
+ }
186
+ .toolbar {
187
+ display: flex;
188
+ flex-wrap: wrap;
189
+ align-items: center;
190
+ gap: 8px 16px;
191
+ padding: 8px 16px;
192
+ background: var(--surface);
193
+ border-bottom: 1px solid var(--line);
194
+ }
195
+ .stage {
196
+ flex: 1;
197
+ display: flex;
198
+ min-height: 0;
199
+ }
200
+ .tables {
201
+ flex: 1;
202
+ overflow: auto;
203
+ padding: 16px 24px 48px;
204
+ }
205
+ .tables h2 {
206
+ font-family: var(--serif);
207
+ font-size: 30px;
208
+ font-weight: 400;
209
+ letter-spacing: -0.01em;
210
+ line-height: 1.25;
211
+ margin: 4px 0 8px;
212
+ display: flex;
213
+ align-items: center;
214
+ flex-wrap: wrap;
215
+ gap: 8px;
216
+ }
217
+ .tables h3 {
218
+ font-size: 14px;
219
+ margin: 24px 0 8px;
220
+ }
221
+ .tables h4 {
222
+ font-size: 13px;
223
+ margin: 16px 0 6px;
224
+ font-family: var(--mono);
225
+ font-weight: 600;
226
+ }
227
+ .tables p {
228
+ margin: 4px 0 8px;
229
+ }
230
+ .tables .crumbs {
231
+ margin: 0;
232
+ font-size: 13px;
233
+ }
234
+ .tables .tabs {
235
+ margin: 14px 0 6px;
236
+ }
237
+ .tables .findings {
238
+ list-style: none;
239
+ padding: 0;
240
+ margin: 0;
241
+ }
242
+ .tables .findings li {
243
+ padding: 3px 0;
244
+ }
245
+ table.data {
246
+ border-collapse: separate;
247
+ border-spacing: 0;
248
+ width: 100%;
249
+ font-size: 13px;
250
+ background: var(--surface);
251
+ border: 1px solid var(--line);
252
+ border-radius: 8px;
253
+ }
254
+ table.data th,
255
+ table.data td {
256
+ text-align: left;
257
+ padding: 6px 10px;
258
+ border-bottom: 1px solid var(--line);
259
+ vertical-align: top;
260
+ overflow-wrap: break-word;
261
+ }
262
+ table.data tr:last-child > td,
263
+ table.data tr:last-child > th {
264
+ border-bottom: 0;
265
+ }
266
+ table.data thead th {
267
+ color: var(--muted);
268
+ font-weight: 600;
269
+ font-size: 12px;
270
+ white-space: nowrap;
271
+ }
272
+ table.data th[title] {
273
+ cursor: help;
274
+ text-decoration: underline dotted;
275
+ text-underline-offset: 3px;
276
+ }
277
+ table.data tr.muted td {
278
+ color: var(--muted);
279
+ }
280
+ table.settings {
281
+ width: auto;
282
+ min-width: min(560px, 100%);
283
+ }
284
+ table.settings > tbody > tr > th {
285
+ width: 1%;
286
+ white-space: nowrap;
287
+ color: var(--muted);
288
+ font-weight: 500;
289
+ }
290
+ table.data table.data {
291
+ margin: 0;
292
+ }
293
+ pre.code {
294
+ margin: 0;
295
+ font: 12px/1.5 var(--mono);
296
+ background: var(--surface);
297
+ border: 1px solid var(--line);
298
+ border-radius: 8px;
299
+ padding: 12px;
300
+ overflow: auto;
301
+ white-space: pre;
302
+ }
303
+ svg.canvas {
304
+ flex: 1;
305
+ min-width: 0;
306
+ height: 100%;
307
+ cursor: grab;
308
+ touch-action: none;
309
+ user-select: none;
310
+ }
311
+ svg.canvas.panning {
312
+ cursor: grabbing;
313
+ }
314
+ aside {
315
+ width: 340px;
316
+ overflow: auto;
317
+ padding: 14px 16px;
318
+ background: var(--surface);
319
+ border-left: 1px solid var(--line);
320
+ }
321
+ aside h2 {
322
+ font-family: var(--serif);
323
+ font-size: 21px;
324
+ font-weight: 400;
325
+ margin: 0 0 4px;
326
+ overflow-wrap: anywhere;
327
+ }
328
+ aside h3 {
329
+ font-size: 13px;
330
+ font-weight: 600;
331
+ color: var(--muted);
332
+ margin: 18px 0 6px;
333
+ }
334
+ aside ul {
335
+ list-style: none;
336
+ margin: 0;
337
+ padding: 0;
338
+ }
339
+ aside li {
340
+ padding: 3px 0;
341
+ overflow-wrap: anywhere;
342
+ }
343
+ aside .kind {
344
+ color: var(--muted);
345
+ font-size: 12px;
346
+ }
347
+ aside pre {
348
+ margin: 0;
349
+ font: 12px/1.45 var(--mono);
350
+ white-space: pre-wrap;
351
+ overflow-wrap: anywhere;
352
+ background: var(--bg);
353
+ padding: 8px;
354
+ border-radius: 6px;
355
+ }
356
+ .badge {
357
+ display: inline-block;
358
+ font-size: 11px;
359
+ font-weight: 600;
360
+ padding: 0 6px;
361
+ border-radius: 4px;
362
+ margin-right: 6px;
363
+ color: var(--on-accent);
364
+ font-family: var(--font);
365
+ }
366
+ .badge.error {
367
+ background: var(--error-strong);
368
+ }
369
+ .badge.warning {
370
+ background: var(--warning-strong);
371
+ }
372
+ .chips {
373
+ display: flex;
374
+ flex-wrap: wrap;
375
+ gap: 6px;
376
+ }
377
+ .chips button {
378
+ padding: 2px 8px;
379
+ font-size: 12px;
380
+ }
381
+ .legend li {
382
+ display: flex;
383
+ align-items: center;
384
+ gap: 8px;
385
+ }
386
+ .legend svg {
387
+ flex: none;
388
+ }
389
+ .edge path {
390
+ fill: none;
391
+ stroke: var(--edge);
392
+ stroke-width: 1.6;
393
+ }
394
+ .edge.one-sided path:not(.hit) {
395
+ stroke: var(--warning);
396
+ stroke-dasharray: 6 4;
397
+ }
398
+ .edge text {
399
+ font-size: 11px;
400
+ fill: var(--muted);
401
+ paint-order: stroke;
402
+ stroke: var(--bg);
403
+ stroke-width: 4px;
404
+ stroke-linejoin: round;
405
+ }
406
+ .edge .hit {
407
+ stroke: transparent;
408
+ stroke-width: 12;
409
+ cursor: pointer;
410
+ }
411
+ .edge.selected path:not(.hit),
412
+ .edge.lit path:not(.hit) {
413
+ stroke: var(--accent);
414
+ stroke-width: 2.6;
415
+ }
416
+ .edge.selected text,
417
+ .edge.lit text {
418
+ fill: var(--text);
419
+ }
420
+ .node {
421
+ cursor: pointer;
422
+ }
423
+ .node rect {
424
+ fill: var(--surface);
425
+ stroke: var(--line);
426
+ stroke-width: 1.5;
427
+ }
428
+ .node.segment rect {
429
+ fill: var(--segment);
430
+ }
431
+ .node.outside rect {
432
+ stroke-dasharray: 5 3;
433
+ }
434
+ .node.error rect {
435
+ stroke: var(--error);
436
+ stroke-width: 3;
437
+ }
438
+ .node.warning rect {
439
+ stroke: var(--warning);
440
+ stroke-width: 3;
441
+ }
442
+ .node.selected rect {
443
+ stroke: var(--accent);
444
+ stroke-width: 3;
445
+ }
446
+ .node text {
447
+ fill: var(--text);
448
+ font-size: 12px;
449
+ text-anchor: middle;
450
+ dominant-baseline: central;
451
+ pointer-events: none;
452
+ }
453
+ .node text.name {
454
+ font-weight: 600;
455
+ font-size: 13px;
456
+ }
457
+ .node text.sub {
458
+ fill: var(--muted);
459
+ font-size: 11px;
460
+ }
461
+ .node.segment text,
462
+ .node.outside text {
463
+ font-family: var(--mono);
464
+ font-size: 11px;
465
+ }
466
+ .dim {
467
+ opacity: 0.18;
468
+ }
469
+ svg.far .edge text {
470
+ display: none;
471
+ }
472
+ @media (max-width: 760px) {
473
+ .stage {
474
+ flex-direction: column;
475
+ }
476
+ aside {
477
+ width: auto;
478
+ height: 40%;
479
+ border-left: 0;
480
+ border-top: 1px solid var(--line);
481
+ }
482
+ .tables {
483
+ padding: 12px 16px 40px;
484
+ }
485
+ header input[type="search"] {
486
+ width: 100%;
487
+ }
488
+ }
489
+
490
+ /* A table that can be saved, with its action above it. */
491
+ .table-actions {
492
+ margin: 0 0 6px;
493
+ font-size: 13px;
494
+ text-align: right;
495
+ }
496
+
497
+ /* The row a port's square points to. */
498
+ tr.flash td {
499
+ background: var(--segment);
500
+ transition: background 0.4s;
501
+ }
502
+
503
+ /* A device's front panel: a square per port, by speed. */
504
+ .faceplate {
505
+ display: flex;
506
+ flex-wrap: wrap;
507
+ gap: 12px 24px;
508
+ padding: 12px;
509
+ margin: 8px 0;
510
+ background: var(--surface);
511
+ border: 1px solid var(--line);
512
+ border-radius: 8px;
513
+ }
514
+ .faceplate .speed {
515
+ display: flex;
516
+ align-items: center;
517
+ gap: 10px;
518
+ }
519
+ .faceplate .speed-name {
520
+ font-family: var(--mono);
521
+ font-size: 12px;
522
+ color: var(--muted);
523
+ min-width: 36px;
524
+ }
525
+ .faceplate .ports {
526
+ display: grid;
527
+ grid-template-rows: repeat(2, auto);
528
+ grid-auto-flow: column;
529
+ gap: 4px;
530
+ }
531
+ .port {
532
+ position: relative;
533
+ display: inline-block;
534
+ width: 28px;
535
+ height: 24px;
536
+ padding: 0;
537
+ font: 500 11px var(--font);
538
+ border-radius: 4px;
539
+ border: 1px solid var(--line);
540
+ background: var(--surface);
541
+ color: var(--text);
542
+ }
543
+ .port.shut {
544
+ border-style: dashed;
545
+ color: var(--muted);
546
+ background: var(--bg);
547
+ }
548
+ .port.access {
549
+ background: var(--segment);
550
+ border-color: var(--accent);
551
+ }
552
+ .port.trunk {
553
+ background: var(--accent-strong);
554
+ border-color: var(--accent-strong);
555
+ color: var(--on-accent);
556
+ }
557
+ .port.routed {
558
+ border: 2px solid var(--text);
559
+ }
560
+ .port.lag {
561
+ border: 2px solid var(--accent);
562
+ }
563
+ .port.linked::after {
564
+ content: "";
565
+ position: absolute;
566
+ top: 2px;
567
+ right: 2px;
568
+ width: 5px;
569
+ height: 5px;
570
+ border-radius: 50%;
571
+ background: var(--ok);
572
+ }
573
+ .faceplate-legend {
574
+ display: flex;
575
+ flex-wrap: wrap;
576
+ gap: 6px 16px;
577
+ list-style: none;
578
+ padding: 0;
579
+ margin: 0 0 12px;
580
+ font-size: 12px;
581
+ color: var(--muted);
582
+ }
583
+ .faceplate-legend li {
584
+ display: flex;
585
+ align-items: center;
586
+ gap: 6px;
587
+ }
588
+ .faceplate-legend .port {
589
+ width: 18px;
590
+ height: 14px;
591
+ }
592
+
593
+ /* A line diff: removed lines, added lines, and runs of the same folded away. */
594
+ pre.diff .removed,
595
+ p .removed {
596
+ color: var(--error);
597
+ }
598
+ pre.diff .added,
599
+ p .added {
600
+ color: var(--ok);
601
+ }
602
+ pre.diff .fold {
603
+ display: block;
604
+ color: var(--muted);
605
+ font-style: italic;
606
+ margin: 4px 0;
607
+ }
608
+
609
+ /* The tools' forms: a field per line on a narrow screen, several side by side on a wide one. */
610
+ .tool-form {
611
+ display: flex;
612
+ flex-wrap: wrap;
613
+ align-items: flex-end;
614
+ gap: 12px 16px;
615
+ margin: 12px 0 16px;
616
+ padding: 14px;
617
+ background: var(--surface);
618
+ border: 1px solid var(--line);
619
+ border-radius: 8px;
620
+ }
621
+ .field {
622
+ display: flex;
623
+ flex-direction: column;
624
+ gap: 4px;
625
+ font-size: 13px;
626
+ color: var(--muted);
627
+ }
628
+ .field input[type="text"],
629
+ .field select {
630
+ font: inherit;
631
+ color: var(--text);
632
+ background: var(--bg);
633
+ border: 1px solid var(--line);
634
+ border-radius: 6px;
635
+ padding: 5px 8px;
636
+ min-width: 150px;
637
+ }
638
+ .field small {
639
+ font-size: 11px;
640
+ }
641
+ .flags {
642
+ display: flex;
643
+ flex-wrap: wrap;
644
+ gap: 4px 12px;
645
+ color: var(--text);
646
+ }
647
+ .flag {
648
+ display: flex;
649
+ align-items: center;
650
+ gap: 4px;
651
+ }
652
+ button.primary {
653
+ background: var(--accent-strong);
654
+ border-color: var(--accent-strong);
655
+ color: var(--on-accent);
656
+ }
657
+ .verdict {
658
+ font-weight: 600;
659
+ }
660
+ .verdict.accept {
661
+ color: var(--ok);
662
+ }
663
+ .verdict.drop,
664
+ .verdict.reject {
665
+ color: var(--error);
666
+ }
667
+ .verdict.unknown {
668
+ color: var(--warning);
669
+ }
670
+
671
+ /* A comparison on the graph: what is new, and what is gone. */
672
+ .edge.added path:not(.hit) {
673
+ stroke: var(--ok);
674
+ stroke-width: 2.6;
675
+ }
676
+ .edge.gone path:not(.hit) {
677
+ stroke: var(--error);
678
+ stroke-dasharray: 6 4;
679
+ }
680
+ .added {
681
+ color: var(--ok);
682
+ }
683
+ .removed {
684
+ color: var(--error);
685
+ }
686
+ details.change {
687
+ margin: 6px 0;
688
+ }
689
+ details.change summary {
690
+ cursor: pointer;
691
+ font-weight: 600;
692
+ padding: 4px 0;
693
+ }