@shumoku/core 0.2.4 → 0.2.13

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.
@@ -1,661 +1,661 @@
1
- /**
2
- * Shumoku Data Models
3
- * Network diagram support with Mermaid-like syntax
4
- */
5
-
6
- // ============================================
7
- // Node Types
8
- // ============================================
9
-
10
- export type NodeShape =
11
- | 'rect' // Rectangle [text]
12
- | 'rounded' // Rounded rectangle (text)
13
- | 'circle' // Circle ((text))
14
- | 'diamond' // Diamond {text}
15
- | 'hexagon' // Hexagon {{text}}
16
- | 'cylinder' // Database cylinder [(text)]
17
- | 'stadium' // Stadium/pill shape ([text])
18
- | 'trapezoid' // Trapezoid [/text/]
19
-
20
- export interface NodeStyle {
21
- fill?: string
22
- stroke?: string
23
- strokeWidth?: number
24
- strokeDasharray?: string
25
- textColor?: string
26
- fontSize?: number
27
- fontWeight?: 'normal' | 'bold'
28
- opacity?: number
29
- }
30
-
31
- export interface Node {
32
- id: string
33
-
34
- /**
35
- * Display label - can be single line or multiple lines
36
- * Supports basic HTML: <b>, <i>, <br/>
37
- */
38
- label: string | string[]
39
-
40
- /**
41
- * Node shape
42
- */
43
- shape: NodeShape
44
-
45
- /**
46
- * Device type (for default styling/icons)
47
- */
48
- type?: DeviceType
49
-
50
- /**
51
- * Parent subgraph ID
52
- */
53
- parent?: string
54
-
55
- /**
56
- * Rank/layer for horizontal alignment
57
- * Nodes with the same rank value will be placed on the same horizontal level
58
- */
59
- rank?: number | string
60
-
61
- /**
62
- * Custom style
63
- */
64
- style?: NodeStyle
65
-
66
- /**
67
- * Additional metadata
68
- */
69
- metadata?: Record<string, unknown>
70
-
71
- /**
72
- * Vendor name for vendor-specific icons (e.g., 'aws', 'azure', 'gcp', 'yamaha')
73
- */
74
- vendor?: string
75
-
76
- /**
77
- * Service name within the vendor (e.g., 'ec2', 'vpc', 'lambda')
78
- * Used for cloud providers like AWS
79
- */
80
- service?: string
81
-
82
- /**
83
- * Model name for hardware vendors (e.g., 'rtx3510', 'ex4400')
84
- * Alternative to service for equipment vendors
85
- */
86
- model?: string
87
-
88
- /**
89
- * Resource type within the service (e.g., 'instance', 'nat-gateway')
90
- */
91
- resource?: string
92
- }
93
-
94
- // ============================================
95
- // Link Types
96
- // ============================================
97
-
98
- export type LinkType =
99
- | 'solid' // Normal line -->
100
- | 'dashed' // Dashed line -.->
101
- | 'thick' // Thick line ==>
102
- | 'double' // Double line o==o
103
- | 'invisible' // No line (for layout only)
104
-
105
- export type ArrowType =
106
- | 'none' // No arrow ---
107
- | 'forward' // Arrow at target -->
108
- | 'back' // Arrow at source <--
109
- | 'both' // Arrows at both <-->
110
-
111
- export interface LinkStyle {
112
- stroke?: string
113
- strokeWidth?: number
114
- strokeDasharray?: string
115
- opacity?: number
116
- /** Minimum length for this link (controls node spacing for HA pairs) */
117
- minLength?: number
118
- }
119
-
120
- /**
121
- * Link endpoint with optional port/IP details
122
- */
123
- export interface LinkEndpoint {
124
- node: string
125
- port?: string
126
- ip?: string // e.g., "10.57.0.1/30"
127
- /**
128
- * Pin reference for hierarchical connections (e.g., "subgraph-id:pin-id")
129
- * When set, this endpoint connects to a subgraph's boundary pin
130
- */
131
- pin?: string
132
- }
133
-
134
- /**
135
- * Link bandwidth/speed type
136
- * Controls line thickness for visual distinction
137
- */
138
- export type LinkBandwidth = '1G' | '10G' | '25G' | '40G' | '100G'
139
-
140
- export interface Link {
141
- id?: string
142
-
143
- /**
144
- * Source endpoint - can be simple node ID or detailed endpoint
145
- */
146
- from: string | LinkEndpoint
147
-
148
- /**
149
- * Target endpoint - can be simple node ID or detailed endpoint
150
- */
151
- to: string | LinkEndpoint
152
-
153
- /**
154
- * Link label - can be multiple lines (displayed at center)
155
- */
156
- label?: string | string[]
157
-
158
- /**
159
- * Link type
160
- */
161
- type?: LinkType
162
-
163
- /**
164
- * Arrow direction
165
- */
166
- arrow?: ArrowType
167
-
168
- /**
169
- * Bandwidth/speed - affects line thickness
170
- * 1G: thin, 10G: normal, 25G: medium, 40G: thick, 100G: extra thick
171
- */
172
- bandwidth?: LinkBandwidth
173
-
174
- /**
175
- * Redundancy/clustering type - nodes connected with this will be placed on the same layer
176
- * ha: High Availability (VRRP, HSRP, GLBP, keepalive)
177
- * vc: Virtual Chassis (Juniper)
178
- * vss: Virtual Switching System (Cisco)
179
- * vpc: Virtual Port Channel (Cisco Nexus)
180
- * mlag: Multi-Chassis Link Aggregation
181
- * stack: Stacking
182
- */
183
- redundancy?: 'ha' | 'vc' | 'vss' | 'vpc' | 'mlag' | 'stack'
184
-
185
- /**
186
- * VLANs carried on this link
187
- * Single VLAN for access ports, multiple for trunk ports
188
- */
189
- vlan?: number[]
190
-
191
- /**
192
- * Custom style
193
- */
194
- style?: LinkStyle
195
-
196
- /**
197
- * Custom metadata for extensions
198
- */
199
- metadata?: Record<string, unknown>
200
- }
201
-
202
- /**
203
- * Helper to get node ID from endpoint
204
- */
205
- export function getNodeId(endpoint: string | LinkEndpoint): string {
206
- return typeof endpoint === 'string' ? endpoint : endpoint.node
207
- }
208
-
209
- // ============================================
210
- // Subgraph Types
211
- // ============================================
212
-
213
- export type LayoutDirection = 'TB' | 'BT' | 'LR' | 'RL'
214
-
215
- export interface SubgraphStyle {
216
- fill?: string
217
- stroke?: string
218
- strokeWidth?: number
219
- strokeDasharray?: string
220
- labelPosition?: 'top' | 'bottom' | 'left' | 'right'
221
- labelFontSize?: number
222
- /** Padding inside this subgraph (like CSS padding) */
223
- padding?: number
224
- /** Horizontal spacing between nodes in this subgraph */
225
- nodeSpacing?: number
226
- /** Vertical spacing between layers in this subgraph */
227
- rankSpacing?: number
228
- }
229
-
230
- /**
231
- * Pin for hierarchical boundary connections (KiCad-style sheet pins)
232
- * Maps internal device:port to external connection point
233
- */
234
- export interface Pin {
235
- /**
236
- * Unique identifier for the pin
237
- */
238
- id: string
239
-
240
- /**
241
- * Display label for the pin (e.g., "Office接続")
242
- */
243
- label?: string
244
-
245
- /**
246
- * Internal device reference (which device this pin connects to)
247
- */
248
- device?: string
249
-
250
- /**
251
- * Internal port reference (which port on the device)
252
- */
253
- port?: string
254
-
255
- /**
256
- * Direction hint for layout (incoming/outgoing)
257
- */
258
- direction?: 'in' | 'out' | 'bidirectional'
259
-
260
- /**
261
- * Visual position on the subgraph boundary
262
- */
263
- position?: 'top' | 'bottom' | 'left' | 'right'
264
- }
265
-
266
- export interface Subgraph {
267
- id: string
268
-
269
- /**
270
- * Display label
271
- */
272
- label: string
273
-
274
- /**
275
- * Child subgraph IDs
276
- */
277
- children?: string[]
278
-
279
- /**
280
- * Parent subgraph ID (for nested subgraphs)
281
- */
282
- parent?: string
283
-
284
- /**
285
- * Layout direction within this subgraph
286
- */
287
- direction?: LayoutDirection
288
-
289
- /**
290
- * Custom style
291
- */
292
- style?: SubgraphStyle
293
-
294
- /**
295
- * Vendor name for vendor-specific icons (e.g., 'aws', 'azure', 'gcp', 'yamaha')
296
- */
297
- vendor?: string
298
-
299
- /**
300
- * Service name within the vendor (e.g., 'ec2', 'vpc', 'lambda')
301
- * Used for cloud providers like AWS
302
- */
303
- service?: string
304
-
305
- /**
306
- * Model name for hardware vendors (e.g., 'rtx3510', 'ex4400')
307
- * Alternative to service for equipment vendors
308
- */
309
- model?: string
310
-
311
- /**
312
- * Resource type within the service (e.g., 'instance', 'nat-gateway')
313
- */
314
- resource?: string
315
-
316
- /**
317
- * File reference for external sheet definition (KiCad-style hierarchy)
318
- */
319
- file?: string
320
-
321
- /**
322
- * Pins for boundary connections (hierarchical sheets)
323
- * Defines connection points between this subgraph and parent/siblings
324
- */
325
- pins?: Pin[]
326
- }
327
-
328
- // ============================================
329
- // Canvas/Sheet Size Types
330
- // ============================================
331
-
332
- /**
333
- * Standard paper size presets
334
- */
335
- export type PaperSize =
336
- | 'A0'
337
- | 'A1'
338
- | 'A2'
339
- | 'A3'
340
- | 'A4'
341
- | 'B0'
342
- | 'B1'
343
- | 'B2'
344
- | 'B3'
345
- | 'B4'
346
- | 'letter'
347
- | 'legal'
348
- | 'tabloid'
349
-
350
- /**
351
- * Paper orientation
352
- */
353
- export type PaperOrientation = 'portrait' | 'landscape'
354
-
355
- /**
356
- * Paper size dimensions in mm
357
- */
358
- export const PAPER_SIZES: Record<PaperSize, { width: number; height: number }> = {
359
- A0: { width: 841, height: 1189 },
360
- A1: { width: 594, height: 841 },
361
- A2: { width: 420, height: 594 },
362
- A3: { width: 297, height: 420 },
363
- A4: { width: 210, height: 297 },
364
- B0: { width: 1000, height: 1414 },
365
- B1: { width: 707, height: 1000 },
366
- B2: { width: 500, height: 707 },
367
- B3: { width: 353, height: 500 },
368
- B4: { width: 250, height: 353 },
369
- letter: { width: 216, height: 279 },
370
- legal: { width: 216, height: 356 },
371
- tabloid: { width: 279, height: 432 },
372
- }
373
-
374
- /**
375
- * Canvas/sheet size settings
376
- */
377
- export interface CanvasSettings {
378
- /**
379
- * Paper size preset (A0, A1, A2, A3, A4, etc.)
380
- */
381
- preset?: PaperSize
382
-
383
- /**
384
- * Paper orientation (portrait or landscape)
385
- * Only used with preset
386
- */
387
- orientation?: PaperOrientation
388
-
389
- /**
390
- * Custom width in pixels
391
- * Takes precedence over preset
392
- */
393
- width?: number
394
-
395
- /**
396
- * Custom height in pixels
397
- * Takes precedence over preset
398
- */
399
- height?: number
400
-
401
- /**
402
- * DPI for print output (default: 96 for screen, 300 for print)
403
- */
404
- dpi?: number
405
-
406
- /**
407
- * Fit content to canvas with padding
408
- * If true, scales content to fit within canvas
409
- */
410
- fit?: boolean
411
-
412
- /**
413
- * Padding around content when fit is true (in pixels)
414
- */
415
- padding?: number
416
- }
417
-
418
- /**
419
- * Convert paper size to pixels at given DPI
420
- */
421
- export function paperSizeToPixels(
422
- size: PaperSize,
423
- orientation: PaperOrientation = 'portrait',
424
- dpi = 96,
425
- ): { width: number; height: number } {
426
- const dimensions = PAPER_SIZES[size]
427
- const mmToInch = 1 / 25.4
428
-
429
- let width = Math.round(dimensions.width * mmToInch * dpi)
430
- let height = Math.round(dimensions.height * mmToInch * dpi)
431
-
432
- if (orientation === 'landscape') {
433
- ;[width, height] = [height, width]
434
- }
435
-
436
- return { width, height }
437
- }
438
-
439
- // ============================================
440
- // Graph Types
441
- // ============================================
442
-
443
- /**
444
- * Theme type for diagram appearance
445
- */
446
- export type ThemeType = 'light' | 'dark'
447
-
448
- export interface LegendSettings {
449
- /**
450
- * Show legend in the diagram
451
- */
452
- enabled?: boolean
453
-
454
- /**
455
- * Legend position
456
- */
457
- position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
458
-
459
- /**
460
- * Show device type icons
461
- */
462
- showDeviceTypes?: boolean
463
-
464
- /**
465
- * Show bandwidth indicators
466
- */
467
- showBandwidth?: boolean
468
-
469
- /**
470
- * Show cable/link types
471
- */
472
- showCableTypes?: boolean
473
-
474
- /**
475
- * Show VLAN colors
476
- */
477
- showVlans?: boolean
478
- }
479
-
480
- export interface GraphSettings {
481
- /**
482
- * Default layout direction
483
- */
484
- direction?: LayoutDirection
485
-
486
- /**
487
- * Theme for diagram appearance (light or dark)
488
- */
489
- theme?: ThemeType
490
-
491
- /**
492
- * Node spacing
493
- */
494
- nodeSpacing?: number
495
-
496
- /**
497
- * Rank spacing (between layers)
498
- */
499
- rankSpacing?: number
500
-
501
- /**
502
- * Subgraph padding
503
- */
504
- subgraphPadding?: number
505
-
506
- /**
507
- * Canvas/sheet size settings
508
- */
509
- canvas?: CanvasSettings
510
-
511
- /**
512
- * Legend configuration
513
- */
514
- legend?: boolean | LegendSettings
515
- }
516
-
517
- export interface NetworkGraph {
518
- version: string
519
- name?: string
520
- description?: string
521
-
522
- /**
523
- * All nodes (flat list)
524
- */
525
- nodes: Node[]
526
-
527
- /**
528
- * All links
529
- */
530
- links: Link[]
531
-
532
- /**
533
- * Subgraph definitions
534
- */
535
- subgraphs?: Subgraph[]
536
-
537
- /**
538
- * Global settings
539
- */
540
- settings?: GraphSettings
541
-
542
- /**
543
- * Top-level pins (for child sheets in hierarchical diagrams)
544
- * Defines connection points exposed to parent sheet
545
- */
546
- pins?: Pin[]
547
- }
548
-
549
- /**
550
- * Hierarchical network graph with resolved sheet references
551
- * Used when loading multi-file hierarchical diagrams
552
- */
553
- export interface HierarchicalNetworkGraph extends NetworkGraph {
554
- /**
555
- * Map of sheet ID to their resolved NetworkGraph
556
- */
557
- sheets?: Map<string, NetworkGraph>
558
-
559
- /**
560
- * Parent sheet ID (if this is a child sheet)
561
- */
562
- parentSheet?: string
563
-
564
- /**
565
- * Breadcrumb path from root (e.g., ['root', 'server-room'])
566
- */
567
- breadcrumb?: string[]
568
- }
569
-
570
- // ============================================
571
- // Device Types (for default styling)
572
- // ============================================
573
-
574
- export enum DeviceType {
575
- Router = 'router',
576
- L3Switch = 'l3-switch',
577
- L2Switch = 'l2-switch',
578
- Firewall = 'firewall',
579
- LoadBalancer = 'load-balancer',
580
- Server = 'server',
581
- AccessPoint = 'access-point',
582
- Cloud = 'cloud',
583
- Internet = 'internet',
584
- VPN = 'vpn',
585
- Database = 'database',
586
- Generic = 'generic',
587
- }
588
-
589
- // ============================================
590
- // Layout Result Types
591
- // ============================================
592
-
593
- export interface Position {
594
- x: number
595
- y: number
596
- }
597
-
598
- export interface Size {
599
- width: number
600
- height: number
601
- }
602
-
603
- export interface Bounds {
604
- x: number
605
- y: number
606
- width: number
607
- height: number
608
- }
609
-
610
- /**
611
- * Port position on a node edge
612
- */
613
- export interface LayoutPort {
614
- id: string
615
- /** Port name (e.g., "eth0", "Gi0/1") */
616
- label: string
617
- /** Position relative to node center */
618
- position: Position
619
- /** Port box size */
620
- size: Size
621
- /** Which side of the node (for rendering) */
622
- side: 'top' | 'bottom' | 'left' | 'right'
623
- }
624
-
625
- export interface LayoutNode {
626
- id: string
627
- position: Position
628
- size: Size
629
- node: Node
630
- /** Ports on this node */
631
- ports?: Map<string, LayoutPort>
632
- }
633
-
634
- export interface LayoutLink {
635
- id: string
636
- from: string // Node ID
637
- to: string // Node ID
638
- fromEndpoint: LinkEndpoint // Full endpoint info
639
- toEndpoint: LinkEndpoint // Full endpoint info
640
- points: Position[]
641
- link: Link
642
- }
643
-
644
- export interface LayoutSubgraph {
645
- id: string
646
- bounds: Bounds
647
- subgraph: Subgraph
648
- /** Boundary ports for hierarchical connections */
649
- ports?: Map<string, LayoutPort>
650
- }
651
-
652
- export interface LayoutResult {
653
- nodes: Map<string, LayoutNode>
654
- links: Map<string, LayoutLink>
655
- subgraphs: Map<string, LayoutSubgraph>
656
- bounds: Bounds
657
- metadata?: {
658
- algorithm: string
659
- duration: number
660
- }
661
- }
1
+ /**
2
+ * Shumoku Data Models
3
+ * Network diagram support with Mermaid-like syntax
4
+ */
5
+
6
+ // ============================================
7
+ // Node Types
8
+ // ============================================
9
+
10
+ export type NodeShape =
11
+ | 'rect' // Rectangle [text]
12
+ | 'rounded' // Rounded rectangle (text)
13
+ | 'circle' // Circle ((text))
14
+ | 'diamond' // Diamond {text}
15
+ | 'hexagon' // Hexagon {{text}}
16
+ | 'cylinder' // Database cylinder [(text)]
17
+ | 'stadium' // Stadium/pill shape ([text])
18
+ | 'trapezoid' // Trapezoid [/text/]
19
+
20
+ export interface NodeStyle {
21
+ fill?: string
22
+ stroke?: string
23
+ strokeWidth?: number
24
+ strokeDasharray?: string
25
+ textColor?: string
26
+ fontSize?: number
27
+ fontWeight?: 'normal' | 'bold'
28
+ opacity?: number
29
+ }
30
+
31
+ export interface Node {
32
+ id: string
33
+
34
+ /**
35
+ * Display label - can be single line or multiple lines
36
+ * Supports basic HTML: <b>, <i>, <br/>
37
+ */
38
+ label: string | string[]
39
+
40
+ /**
41
+ * Node shape
42
+ */
43
+ shape: NodeShape
44
+
45
+ /**
46
+ * Device type (for default styling/icons)
47
+ */
48
+ type?: DeviceType
49
+
50
+ /**
51
+ * Parent subgraph ID
52
+ */
53
+ parent?: string
54
+
55
+ /**
56
+ * Rank/layer for horizontal alignment
57
+ * Nodes with the same rank value will be placed on the same horizontal level
58
+ */
59
+ rank?: number | string
60
+
61
+ /**
62
+ * Custom style
63
+ */
64
+ style?: NodeStyle
65
+
66
+ /**
67
+ * Additional metadata
68
+ */
69
+ metadata?: Record<string, unknown>
70
+
71
+ /**
72
+ * Vendor name for vendor-specific icons (e.g., 'aws', 'azure', 'gcp', 'yamaha')
73
+ */
74
+ vendor?: string
75
+
76
+ /**
77
+ * Service name within the vendor (e.g., 'ec2', 'vpc', 'lambda')
78
+ * Used for cloud providers like AWS
79
+ */
80
+ service?: string
81
+
82
+ /**
83
+ * Model name for hardware vendors (e.g., 'rtx3510', 'ex4400')
84
+ * Alternative to service for equipment vendors
85
+ */
86
+ model?: string
87
+
88
+ /**
89
+ * Resource type within the service (e.g., 'instance', 'nat-gateway')
90
+ */
91
+ resource?: string
92
+ }
93
+
94
+ // ============================================
95
+ // Link Types
96
+ // ============================================
97
+
98
+ export type LinkType =
99
+ | 'solid' // Normal line -->
100
+ | 'dashed' // Dashed line -.->
101
+ | 'thick' // Thick line ==>
102
+ | 'double' // Double line o==o
103
+ | 'invisible' // No line (for layout only)
104
+
105
+ export type ArrowType =
106
+ | 'none' // No arrow ---
107
+ | 'forward' // Arrow at target -->
108
+ | 'back' // Arrow at source <--
109
+ | 'both' // Arrows at both <-->
110
+
111
+ export interface LinkStyle {
112
+ stroke?: string
113
+ strokeWidth?: number
114
+ strokeDasharray?: string
115
+ opacity?: number
116
+ /** Minimum length for this link (controls node spacing for HA pairs) */
117
+ minLength?: number
118
+ }
119
+
120
+ /**
121
+ * Link endpoint with optional port/IP details
122
+ */
123
+ export interface LinkEndpoint {
124
+ node: string
125
+ port?: string
126
+ ip?: string // e.g., "10.57.0.1/30"
127
+ /**
128
+ * Pin reference for hierarchical connections (e.g., "subgraph-id:pin-id")
129
+ * When set, this endpoint connects to a subgraph's boundary pin
130
+ */
131
+ pin?: string
132
+ }
133
+
134
+ /**
135
+ * Link bandwidth/speed type
136
+ * Controls line thickness for visual distinction
137
+ */
138
+ export type LinkBandwidth = '1G' | '10G' | '25G' | '40G' | '100G'
139
+
140
+ export interface Link {
141
+ id?: string
142
+
143
+ /**
144
+ * Source endpoint - can be simple node ID or detailed endpoint
145
+ */
146
+ from: string | LinkEndpoint
147
+
148
+ /**
149
+ * Target endpoint - can be simple node ID or detailed endpoint
150
+ */
151
+ to: string | LinkEndpoint
152
+
153
+ /**
154
+ * Link label - can be multiple lines (displayed at center)
155
+ */
156
+ label?: string | string[]
157
+
158
+ /**
159
+ * Link type
160
+ */
161
+ type?: LinkType
162
+
163
+ /**
164
+ * Arrow direction
165
+ */
166
+ arrow?: ArrowType
167
+
168
+ /**
169
+ * Bandwidth/speed - affects line thickness
170
+ * 1G: thin, 10G: normal, 25G: medium, 40G: thick, 100G: extra thick
171
+ */
172
+ bandwidth?: LinkBandwidth
173
+
174
+ /**
175
+ * Redundancy/clustering type - nodes connected with this will be placed on the same layer
176
+ * ha: High Availability (VRRP, HSRP, GLBP, keepalive)
177
+ * vc: Virtual Chassis (Juniper)
178
+ * vss: Virtual Switching System (Cisco)
179
+ * vpc: Virtual Port Channel (Cisco Nexus)
180
+ * mlag: Multi-Chassis Link Aggregation
181
+ * stack: Stacking
182
+ */
183
+ redundancy?: 'ha' | 'vc' | 'vss' | 'vpc' | 'mlag' | 'stack'
184
+
185
+ /**
186
+ * VLANs carried on this link
187
+ * Single VLAN for access ports, multiple for trunk ports
188
+ */
189
+ vlan?: number[]
190
+
191
+ /**
192
+ * Custom style
193
+ */
194
+ style?: LinkStyle
195
+
196
+ /**
197
+ * Custom metadata for extensions
198
+ */
199
+ metadata?: Record<string, unknown>
200
+ }
201
+
202
+ /**
203
+ * Helper to get node ID from endpoint
204
+ */
205
+ export function getNodeId(endpoint: string | LinkEndpoint): string {
206
+ return typeof endpoint === 'string' ? endpoint : endpoint.node
207
+ }
208
+
209
+ // ============================================
210
+ // Subgraph Types
211
+ // ============================================
212
+
213
+ export type LayoutDirection = 'TB' | 'BT' | 'LR' | 'RL'
214
+
215
+ export interface SubgraphStyle {
216
+ fill?: string
217
+ stroke?: string
218
+ strokeWidth?: number
219
+ strokeDasharray?: string
220
+ labelPosition?: 'top' | 'bottom' | 'left' | 'right'
221
+ labelFontSize?: number
222
+ /** Padding inside this subgraph (like CSS padding) */
223
+ padding?: number
224
+ /** Horizontal spacing between nodes in this subgraph */
225
+ nodeSpacing?: number
226
+ /** Vertical spacing between layers in this subgraph */
227
+ rankSpacing?: number
228
+ }
229
+
230
+ /**
231
+ * Pin for hierarchical boundary connections (KiCad-style sheet pins)
232
+ * Maps internal device:port to external connection point
233
+ */
234
+ export interface Pin {
235
+ /**
236
+ * Unique identifier for the pin
237
+ */
238
+ id: string
239
+
240
+ /**
241
+ * Display label for the pin (e.g., "Office接続")
242
+ */
243
+ label?: string
244
+
245
+ /**
246
+ * Internal device reference (which device this pin connects to)
247
+ */
248
+ device?: string
249
+
250
+ /**
251
+ * Internal port reference (which port on the device)
252
+ */
253
+ port?: string
254
+
255
+ /**
256
+ * Direction hint for layout (incoming/outgoing)
257
+ */
258
+ direction?: 'in' | 'out' | 'bidirectional'
259
+
260
+ /**
261
+ * Visual position on the subgraph boundary
262
+ */
263
+ position?: 'top' | 'bottom' | 'left' | 'right'
264
+ }
265
+
266
+ export interface Subgraph {
267
+ id: string
268
+
269
+ /**
270
+ * Display label
271
+ */
272
+ label: string
273
+
274
+ /**
275
+ * Child subgraph IDs
276
+ */
277
+ children?: string[]
278
+
279
+ /**
280
+ * Parent subgraph ID (for nested subgraphs)
281
+ */
282
+ parent?: string
283
+
284
+ /**
285
+ * Layout direction within this subgraph
286
+ */
287
+ direction?: LayoutDirection
288
+
289
+ /**
290
+ * Custom style
291
+ */
292
+ style?: SubgraphStyle
293
+
294
+ /**
295
+ * Vendor name for vendor-specific icons (e.g., 'aws', 'azure', 'gcp', 'yamaha')
296
+ */
297
+ vendor?: string
298
+
299
+ /**
300
+ * Service name within the vendor (e.g., 'ec2', 'vpc', 'lambda')
301
+ * Used for cloud providers like AWS
302
+ */
303
+ service?: string
304
+
305
+ /**
306
+ * Model name for hardware vendors (e.g., 'rtx3510', 'ex4400')
307
+ * Alternative to service for equipment vendors
308
+ */
309
+ model?: string
310
+
311
+ /**
312
+ * Resource type within the service (e.g., 'instance', 'nat-gateway')
313
+ */
314
+ resource?: string
315
+
316
+ /**
317
+ * File reference for external sheet definition (KiCad-style hierarchy)
318
+ */
319
+ file?: string
320
+
321
+ /**
322
+ * Pins for boundary connections (hierarchical sheets)
323
+ * Defines connection points between this subgraph and parent/siblings
324
+ */
325
+ pins?: Pin[]
326
+ }
327
+
328
+ // ============================================
329
+ // Canvas/Sheet Size Types
330
+ // ============================================
331
+
332
+ /**
333
+ * Standard paper size presets
334
+ */
335
+ export type PaperSize =
336
+ | 'A0'
337
+ | 'A1'
338
+ | 'A2'
339
+ | 'A3'
340
+ | 'A4'
341
+ | 'B0'
342
+ | 'B1'
343
+ | 'B2'
344
+ | 'B3'
345
+ | 'B4'
346
+ | 'letter'
347
+ | 'legal'
348
+ | 'tabloid'
349
+
350
+ /**
351
+ * Paper orientation
352
+ */
353
+ export type PaperOrientation = 'portrait' | 'landscape'
354
+
355
+ /**
356
+ * Paper size dimensions in mm
357
+ */
358
+ export const PAPER_SIZES: Record<PaperSize, { width: number; height: number }> = {
359
+ A0: { width: 841, height: 1189 },
360
+ A1: { width: 594, height: 841 },
361
+ A2: { width: 420, height: 594 },
362
+ A3: { width: 297, height: 420 },
363
+ A4: { width: 210, height: 297 },
364
+ B0: { width: 1000, height: 1414 },
365
+ B1: { width: 707, height: 1000 },
366
+ B2: { width: 500, height: 707 },
367
+ B3: { width: 353, height: 500 },
368
+ B4: { width: 250, height: 353 },
369
+ letter: { width: 216, height: 279 },
370
+ legal: { width: 216, height: 356 },
371
+ tabloid: { width: 279, height: 432 },
372
+ }
373
+
374
+ /**
375
+ * Canvas/sheet size settings
376
+ */
377
+ export interface CanvasSettings {
378
+ /**
379
+ * Paper size preset (A0, A1, A2, A3, A4, etc.)
380
+ */
381
+ preset?: PaperSize
382
+
383
+ /**
384
+ * Paper orientation (portrait or landscape)
385
+ * Only used with preset
386
+ */
387
+ orientation?: PaperOrientation
388
+
389
+ /**
390
+ * Custom width in pixels
391
+ * Takes precedence over preset
392
+ */
393
+ width?: number
394
+
395
+ /**
396
+ * Custom height in pixels
397
+ * Takes precedence over preset
398
+ */
399
+ height?: number
400
+
401
+ /**
402
+ * DPI for print output (default: 96 for screen, 300 for print)
403
+ */
404
+ dpi?: number
405
+
406
+ /**
407
+ * Fit content to canvas with padding
408
+ * If true, scales content to fit within canvas
409
+ */
410
+ fit?: boolean
411
+
412
+ /**
413
+ * Padding around content when fit is true (in pixels)
414
+ */
415
+ padding?: number
416
+ }
417
+
418
+ /**
419
+ * Convert paper size to pixels at given DPI
420
+ */
421
+ export function paperSizeToPixels(
422
+ size: PaperSize,
423
+ orientation: PaperOrientation = 'portrait',
424
+ dpi = 96,
425
+ ): { width: number; height: number } {
426
+ const dimensions = PAPER_SIZES[size]
427
+ const mmToInch = 1 / 25.4
428
+
429
+ let width = Math.round(dimensions.width * mmToInch * dpi)
430
+ let height = Math.round(dimensions.height * mmToInch * dpi)
431
+
432
+ if (orientation === 'landscape') {
433
+ ;[width, height] = [height, width]
434
+ }
435
+
436
+ return { width, height }
437
+ }
438
+
439
+ // ============================================
440
+ // Graph Types
441
+ // ============================================
442
+
443
+ /**
444
+ * Theme type for diagram appearance
445
+ */
446
+ export type ThemeType = 'light' | 'dark'
447
+
448
+ export interface LegendSettings {
449
+ /**
450
+ * Show legend in the diagram
451
+ */
452
+ enabled?: boolean
453
+
454
+ /**
455
+ * Legend position
456
+ */
457
+ position?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'
458
+
459
+ /**
460
+ * Show device type icons
461
+ */
462
+ showDeviceTypes?: boolean
463
+
464
+ /**
465
+ * Show bandwidth indicators
466
+ */
467
+ showBandwidth?: boolean
468
+
469
+ /**
470
+ * Show cable/link types
471
+ */
472
+ showCableTypes?: boolean
473
+
474
+ /**
475
+ * Show VLAN colors
476
+ */
477
+ showVlans?: boolean
478
+ }
479
+
480
+ export interface GraphSettings {
481
+ /**
482
+ * Default layout direction
483
+ */
484
+ direction?: LayoutDirection
485
+
486
+ /**
487
+ * Theme for diagram appearance (light or dark)
488
+ */
489
+ theme?: ThemeType
490
+
491
+ /**
492
+ * Node spacing
493
+ */
494
+ nodeSpacing?: number
495
+
496
+ /**
497
+ * Rank spacing (between layers)
498
+ */
499
+ rankSpacing?: number
500
+
501
+ /**
502
+ * Subgraph padding
503
+ */
504
+ subgraphPadding?: number
505
+
506
+ /**
507
+ * Canvas/sheet size settings
508
+ */
509
+ canvas?: CanvasSettings
510
+
511
+ /**
512
+ * Legend configuration
513
+ */
514
+ legend?: boolean | LegendSettings
515
+ }
516
+
517
+ export interface NetworkGraph {
518
+ version: string
519
+ name?: string
520
+ description?: string
521
+
522
+ /**
523
+ * All nodes (flat list)
524
+ */
525
+ nodes: Node[]
526
+
527
+ /**
528
+ * All links
529
+ */
530
+ links: Link[]
531
+
532
+ /**
533
+ * Subgraph definitions
534
+ */
535
+ subgraphs?: Subgraph[]
536
+
537
+ /**
538
+ * Global settings
539
+ */
540
+ settings?: GraphSettings
541
+
542
+ /**
543
+ * Top-level pins (for child sheets in hierarchical diagrams)
544
+ * Defines connection points exposed to parent sheet
545
+ */
546
+ pins?: Pin[]
547
+ }
548
+
549
+ /**
550
+ * Hierarchical network graph with resolved sheet references
551
+ * Used when loading multi-file hierarchical diagrams
552
+ */
553
+ export interface HierarchicalNetworkGraph extends NetworkGraph {
554
+ /**
555
+ * Map of sheet ID to their resolved NetworkGraph
556
+ */
557
+ sheets?: Map<string, NetworkGraph>
558
+
559
+ /**
560
+ * Parent sheet ID (if this is a child sheet)
561
+ */
562
+ parentSheet?: string
563
+
564
+ /**
565
+ * Breadcrumb path from root (e.g., ['root', 'server-room'])
566
+ */
567
+ breadcrumb?: string[]
568
+ }
569
+
570
+ // ============================================
571
+ // Device Types (for default styling)
572
+ // ============================================
573
+
574
+ export enum DeviceType {
575
+ Router = 'router',
576
+ L3Switch = 'l3-switch',
577
+ L2Switch = 'l2-switch',
578
+ Firewall = 'firewall',
579
+ LoadBalancer = 'load-balancer',
580
+ Server = 'server',
581
+ AccessPoint = 'access-point',
582
+ Cloud = 'cloud',
583
+ Internet = 'internet',
584
+ VPN = 'vpn',
585
+ Database = 'database',
586
+ Generic = 'generic',
587
+ }
588
+
589
+ // ============================================
590
+ // Layout Result Types
591
+ // ============================================
592
+
593
+ export interface Position {
594
+ x: number
595
+ y: number
596
+ }
597
+
598
+ export interface Size {
599
+ width: number
600
+ height: number
601
+ }
602
+
603
+ export interface Bounds {
604
+ x: number
605
+ y: number
606
+ width: number
607
+ height: number
608
+ }
609
+
610
+ /**
611
+ * Port position on a node edge
612
+ */
613
+ export interface LayoutPort {
614
+ id: string
615
+ /** Port name (e.g., "eth0", "Gi0/1") */
616
+ label: string
617
+ /** Position relative to node center */
618
+ position: Position
619
+ /** Port box size */
620
+ size: Size
621
+ /** Which side of the node (for rendering) */
622
+ side: 'top' | 'bottom' | 'left' | 'right'
623
+ }
624
+
625
+ export interface LayoutNode {
626
+ id: string
627
+ position: Position
628
+ size: Size
629
+ node: Node
630
+ /** Ports on this node */
631
+ ports?: Map<string, LayoutPort>
632
+ }
633
+
634
+ export interface LayoutLink {
635
+ id: string
636
+ from: string // Node ID
637
+ to: string // Node ID
638
+ fromEndpoint: LinkEndpoint // Full endpoint info
639
+ toEndpoint: LinkEndpoint // Full endpoint info
640
+ points: Position[]
641
+ link: Link
642
+ }
643
+
644
+ export interface LayoutSubgraph {
645
+ id: string
646
+ bounds: Bounds
647
+ subgraph: Subgraph
648
+ /** Boundary ports for hierarchical connections */
649
+ ports?: Map<string, LayoutPort>
650
+ }
651
+
652
+ export interface LayoutResult {
653
+ nodes: Map<string, LayoutNode>
654
+ links: Map<string, LayoutLink>
655
+ subgraphs: Map<string, LayoutSubgraph>
656
+ bounds: Bounds
657
+ metadata?: {
658
+ algorithm: string
659
+ duration: number
660
+ }
661
+ }