@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.
- package/dist/fixtures/index.d.ts +13 -0
- package/dist/fixtures/index.d.ts.map +1 -0
- package/dist/fixtures/index.js +553 -0
- package/dist/fixtures/index.js.map +1 -0
- package/dist/hierarchical.d.ts +35 -0
- package/dist/hierarchical.d.ts.map +1 -0
- package/dist/hierarchical.js +173 -0
- package/dist/hierarchical.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/layout/hierarchical.d.ts.map +1 -1
- package/dist/layout/hierarchical.js +20 -14
- package/dist/layout/hierarchical.js.map +1 -1
- package/package.json +1 -1
- package/src/fixtures/index.ts +558 -0
- package/src/hierarchical.ts +240 -0
- package/src/index.test.ts +23 -0
- package/src/index.ts +4 -0
- package/src/layout/hierarchical.ts +1366 -1358
- package/src/models/types.ts +661 -661
- package/dist/renderer/index.d.ts +0 -7
- package/dist/renderer/index.d.ts.map +0 -1
- package/dist/renderer/index.js +0 -6
- package/dist/renderer/index.js.map +0 -1
- package/dist/renderer/svg.d.ts +0 -153
- package/dist/renderer/svg.d.ts.map +0 -1
- package/dist/renderer/svg.js +0 -1170
- package/dist/renderer/svg.js.map +0 -1
- package/dist/renderer/types.d.ts +0 -70
- package/dist/renderer/types.d.ts.map +0 -1
- package/dist/renderer/types.js +0 -6
- package/dist/renderer/types.js.map +0 -1
package/src/models/types.ts
CHANGED
|
@@ -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
|
+
}
|