@fairfox/polly 0.3.8 → 0.4.1

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.
@@ -2001,6 +2001,7 @@ class ArchitectureAnalyzer {
2001
2001
  const adrs = extractADRs(this.options.projectRoot);
2002
2002
  const repository = this.extractRepositoryInfo();
2003
2003
  return {
2004
+ projectRoot: this.options.projectRoot,
2004
2005
  system: systemInfo,
2005
2006
  manifest,
2006
2007
  projectConfig,
@@ -2056,6 +2057,93 @@ async function analyzeArchitecture(options) {
2056
2057
  return analyzer.analyze();
2057
2058
  }
2058
2059
 
2060
+ // vendor/visualize/src/types/structurizr.ts
2061
+ var DEFAULT_COLORS = {
2062
+ messageHandler: "#1168bd",
2063
+ queryHandler: "#51cf66",
2064
+ commandHandler: "#ff922b",
2065
+ authHandler: "#ff6b6b",
2066
+ subscribeHandler: "#845ef7",
2067
+ service: "#95a5a6",
2068
+ repository: "#74b9ff",
2069
+ database: "#0984e3",
2070
+ externalSystem: "#e17055",
2071
+ container: "#6c5ce7",
2072
+ deployment: "#00b894",
2073
+ textLight: "#ffffff",
2074
+ textDark: "#2d3436",
2075
+ relationship: "#707070"
2076
+ };
2077
+ var DEFAULT_ELEMENT_STYLES = {
2078
+ "Message Handler": {
2079
+ shape: "Hexagon",
2080
+ background: DEFAULT_COLORS.messageHandler,
2081
+ color: DEFAULT_COLORS.textLight,
2082
+ fontSize: 14
2083
+ },
2084
+ Query: {
2085
+ background: DEFAULT_COLORS.queryHandler,
2086
+ color: DEFAULT_COLORS.textDark
2087
+ },
2088
+ Command: {
2089
+ background: DEFAULT_COLORS.commandHandler,
2090
+ color: DEFAULT_COLORS.textDark
2091
+ },
2092
+ Authentication: {
2093
+ background: DEFAULT_COLORS.authHandler,
2094
+ color: DEFAULT_COLORS.textLight
2095
+ },
2096
+ Subscribe: {
2097
+ background: DEFAULT_COLORS.subscribeHandler,
2098
+ color: DEFAULT_COLORS.textLight
2099
+ },
2100
+ Service: {
2101
+ shape: "RoundedBox",
2102
+ background: DEFAULT_COLORS.service,
2103
+ color: DEFAULT_COLORS.textLight
2104
+ },
2105
+ Repository: {
2106
+ shape: "Cylinder",
2107
+ background: DEFAULT_COLORS.repository,
2108
+ color: DEFAULT_COLORS.textDark
2109
+ },
2110
+ Database: {
2111
+ shape: "Cylinder",
2112
+ background: DEFAULT_COLORS.database,
2113
+ color: DEFAULT_COLORS.textLight
2114
+ },
2115
+ "External System": {
2116
+ background: DEFAULT_COLORS.externalSystem,
2117
+ color: DEFAULT_COLORS.textLight
2118
+ },
2119
+ Container: {
2120
+ background: DEFAULT_COLORS.container,
2121
+ color: DEFAULT_COLORS.textLight
2122
+ }
2123
+ };
2124
+ var DEFAULT_RELATIONSHIP_STYLES = {
2125
+ Relationship: {
2126
+ routing: "Orthogonal",
2127
+ thickness: 2,
2128
+ color: DEFAULT_COLORS.relationship,
2129
+ fontSize: 12
2130
+ },
2131
+ Sync: {
2132
+ style: "Solid",
2133
+ thickness: 2
2134
+ },
2135
+ Async: {
2136
+ style: "Dashed",
2137
+ thickness: 2
2138
+ },
2139
+ Database: {
2140
+ style: "Solid",
2141
+ thickness: 3,
2142
+ color: DEFAULT_COLORS.database
2143
+ }
2144
+ };
2145
+ var DEFAULT_THEME = "https://static.structurizr.com/themes/default/theme.json";
2146
+
2059
2147
  // vendor/visualize/src/codegen/structurizr.ts
2060
2148
  class StructurizrDSLGenerator {
2061
2149
  analysis;
@@ -2066,8 +2154,25 @@ class StructurizrDSLGenerator {
2066
2154
  includeDynamicDiagrams: true,
2067
2155
  includeComponentDiagrams: true,
2068
2156
  componentDiagramContexts: ["background"],
2069
- theme: "https://static.structurizr.com/themes/default",
2070
- ...options
2157
+ includeDefaultStyles: true,
2158
+ relationships: [],
2159
+ properties: {},
2160
+ groups: [],
2161
+ dynamicDiagrams: [],
2162
+ perspectives: {},
2163
+ deploymentNodes: [],
2164
+ ...options,
2165
+ styles: {
2166
+ theme: options.styles?.theme || DEFAULT_THEME,
2167
+ elements: {
2168
+ ...DEFAULT_ELEMENT_STYLES,
2169
+ ...options.styles?.elements
2170
+ },
2171
+ relationships: {
2172
+ ...DEFAULT_RELATIONSHIP_STYLES,
2173
+ ...options.styles?.relationships
2174
+ }
2175
+ }
2071
2176
  };
2072
2177
  }
2073
2178
  generate() {
@@ -2100,6 +2205,9 @@ class StructurizrDSLGenerator {
2100
2205
  parts.push(this.generatePeople());
2101
2206
  parts.push(this.generateExternalSystems());
2102
2207
  parts.push(this.generateMainSystem());
2208
+ if (this.options.deploymentNodes && this.options.deploymentNodes.length > 0) {
2209
+ parts.push(this.generateDeploymentEnvironments());
2210
+ }
2103
2211
  parts.push(" }");
2104
2212
  return parts.join(`
2105
2213
 
@@ -2155,6 +2263,7 @@ class StructurizrDSLGenerator {
2155
2263
  }
2156
2264
  generateComponents(contextType, contextInfo) {
2157
2265
  const parts = [];
2266
+ const componentDefs = [];
2158
2267
  const handlersByType = new Map;
2159
2268
  for (const handler of contextInfo.handlers) {
2160
2269
  if (!handlersByType.has(handler.messageType)) {
@@ -2166,11 +2275,22 @@ class StructurizrDSLGenerator {
2166
2275
  const componentName = this.toComponentName(messageType);
2167
2276
  const description = this.generateComponentDescription(messageType, handlers[0]);
2168
2277
  const tags = this.getComponentTags(messageType, handlers[0]);
2169
- parts.push(` ${this.toId(componentName)} = component "${componentName}" "${description}" {`);
2170
- if (tags.length > 0) {
2171
- parts.push(` tags "${tags.join('" "')}"`);
2278
+ const properties = this.getComponentProperties(messageType, handlers[0], contextType);
2279
+ componentDefs.push({
2280
+ id: this.toId(componentName),
2281
+ name: componentName,
2282
+ description,
2283
+ tags,
2284
+ properties,
2285
+ messageType
2286
+ });
2287
+ }
2288
+ if (this.options.groups && this.options.groups.length > 0) {
2289
+ parts.push(...this.generateGroupedComponents(componentDefs, this.options.groups));
2290
+ } else {
2291
+ for (const comp of componentDefs) {
2292
+ parts.push(this.generateComponentDefinition(comp, " "));
2172
2293
  }
2173
- parts.push(` }`);
2174
2294
  }
2175
2295
  if (contextInfo.components) {
2176
2296
  for (const comp of contextInfo.components) {
@@ -2241,6 +2361,44 @@ class StructurizrDSLGenerator {
2241
2361
  }
2242
2362
  return tags;
2243
2363
  }
2364
+ getComponentProperties(messageType, handler, contextType) {
2365
+ const properties = {};
2366
+ if (handler.location) {
2367
+ const relativePath = handler.location.file.replace(this.analysis.projectRoot + "/", "");
2368
+ properties["Source"] = `${relativePath}:${handler.location.line}`;
2369
+ }
2370
+ const technologies = ["TypeScript"];
2371
+ if (handler.location?.file.includes("ws") || contextType === "server") {
2372
+ technologies.push("WebSocket");
2373
+ }
2374
+ if (handler.location?.file.includes("socket.io")) {
2375
+ technologies.push("Socket.IO");
2376
+ }
2377
+ if (handler.location?.file.includes("elysia")) {
2378
+ technologies.push("Elysia");
2379
+ }
2380
+ properties["Technology"] = technologies.join(", ");
2381
+ const type = messageType.toLowerCase();
2382
+ let pattern = "Message Handler";
2383
+ if (type.includes("query") || type.includes("get") || type.includes("fetch") || type.includes("load")) {
2384
+ pattern = "Query Handler";
2385
+ properties["Message Type"] = "Query";
2386
+ } else if (type.includes("command") || type.includes("add") || type.includes("create") || type.includes("update") || type.includes("delete") || type.includes("remove")) {
2387
+ pattern = "Command Handler";
2388
+ properties["Message Type"] = "Command";
2389
+ } else if (type.includes("auth") || type.includes("login") || type.includes("logout")) {
2390
+ pattern = "Authentication Handler";
2391
+ properties["Message Type"] = "Authentication";
2392
+ } else if (type.includes("subscribe") || type.includes("watch") || type.includes("listen")) {
2393
+ pattern = "Subscription Handler";
2394
+ properties["Message Type"] = "Subscription";
2395
+ }
2396
+ properties["Pattern"] = pattern;
2397
+ if (this.options.properties && this.options.properties[messageType]) {
2398
+ Object.assign(properties, this.options.properties[messageType]);
2399
+ }
2400
+ return properties;
2401
+ }
2244
2402
  generateComponentRelationships(contextType, contextInfo) {
2245
2403
  const parts = [];
2246
2404
  const handlersByType = new Map;
@@ -2271,6 +2429,21 @@ class StructurizrDSLGenerator {
2271
2429
  }
2272
2430
  }
2273
2431
  }
2432
+ if (this.options.relationships && this.options.relationships.length > 0) {
2433
+ for (const rel of this.options.relationships) {
2434
+ const fromId = this.toId(rel.from);
2435
+ const toId = this.toId(rel.to);
2436
+ const description = this.escape(rel.description);
2437
+ parts.push(` ${fromId} -> ${toId} "${description}" {`);
2438
+ if (rel.technology) {
2439
+ parts.push(` technology "${this.escape(rel.technology)}"`);
2440
+ }
2441
+ if (rel.tags && rel.tags.length > 0) {
2442
+ parts.push(` tags "${rel.tags.join('" "')}"`);
2443
+ }
2444
+ parts.push(` }`);
2445
+ }
2446
+ }
2274
2447
  const stateHandlers = [];
2275
2448
  const queryHandlers = [];
2276
2449
  for (const [messageType, handlers] of handlersByType) {
@@ -2339,6 +2512,9 @@ class StructurizrDSLGenerator {
2339
2512
  if (this.options.includeDynamicDiagrams) {
2340
2513
  parts.push(this.generateDynamicViews());
2341
2514
  }
2515
+ if (this.options.deploymentNodes && this.options.deploymentNodes.length > 0) {
2516
+ parts.push(this.generateDeploymentViews());
2517
+ }
2342
2518
  parts.push(this.generateStyles());
2343
2519
  parts.push(" }");
2344
2520
  if (this.analysis.adrs && this.analysis.adrs.adrs.length > 0) {
@@ -2387,6 +2563,11 @@ class StructurizrDSLGenerator {
2387
2563
  }
2388
2564
  generateDynamicViews() {
2389
2565
  const parts = [];
2566
+ if (this.options.dynamicDiagrams && this.options.dynamicDiagrams.length > 0) {
2567
+ for (const diagram of this.options.dynamicDiagrams) {
2568
+ parts.push(this.generateUserDynamicDiagram(diagram));
2569
+ }
2570
+ }
2390
2571
  const flowsByDomain = new Map;
2391
2572
  for (const flow of this.analysis.messageFlows) {
2392
2573
  const messageType = flow.messageType.toLowerCase();
@@ -2413,6 +2594,20 @@ class StructurizrDSLGenerator {
2413
2594
  }
2414
2595
  return parts.join(`
2415
2596
 
2597
+ `);
2598
+ }
2599
+ generateUserDynamicDiagram(diagram) {
2600
+ const parts = [];
2601
+ parts.push(` dynamic ${diagram.scope || "extension"} "${this.escape(diagram.title)}" "${this.escape(diagram.description || "")}" {`);
2602
+ for (const step of diagram.steps) {
2603
+ const from = step.from;
2604
+ const to = step.to;
2605
+ const description = this.escape(step.description);
2606
+ parts.push(` ${from} -> ${to} "${description}"`);
2607
+ }
2608
+ parts.push(" autoLayout lr");
2609
+ parts.push(" }");
2610
+ return parts.join(`
2416
2611
  `);
2417
2612
  }
2418
2613
  generateDynamicView(flowName, flows, domain) {
@@ -2475,27 +2670,176 @@ class StructurizrDSLGenerator {
2475
2670
  return "Clear items";
2476
2671
  return messageType;
2477
2672
  }
2673
+ generateDeploymentEnvironments() {
2674
+ const parts = [];
2675
+ const nodesByEnvironment = new Map;
2676
+ for (const node of this.options.deploymentNodes || []) {
2677
+ const env = node.tags?.find((tag) => tag.toLowerCase().includes("environment:"))?.split(":")[1] || "Production";
2678
+ if (!nodesByEnvironment.has(env)) {
2679
+ nodesByEnvironment.set(env, []);
2680
+ }
2681
+ nodesByEnvironment.get(env).push(node);
2682
+ }
2683
+ for (const [envName, nodes] of nodesByEnvironment) {
2684
+ parts.push(` deploymentEnvironment "${envName}" {`);
2685
+ for (const node of nodes) {
2686
+ parts.push(this.generateDeploymentNode(node, " "));
2687
+ }
2688
+ parts.push(" }");
2689
+ }
2690
+ return parts.join(`
2691
+ `);
2692
+ }
2693
+ generateDeploymentNode(node, indent) {
2694
+ const parts = [];
2695
+ const description = node.description ? ` "${this.escape(node.description)}"` : "";
2696
+ const technology = node.technology ? ` "${this.escape(node.technology)}"` : "";
2697
+ parts.push(`${indent}deploymentNode "${this.escape(node.name)}"${description}${technology} {`);
2698
+ if (node.tags && node.tags.length > 0) {
2699
+ const filteredTags = node.tags.filter((tag) => !tag.toLowerCase().includes("environment:"));
2700
+ if (filteredTags.length > 0) {
2701
+ parts.push(`${indent} tags "${filteredTags.join('" "')}"`);
2702
+ }
2703
+ }
2704
+ if (node.properties && Object.keys(node.properties).length > 0) {
2705
+ parts.push(`${indent} properties {`);
2706
+ for (const [key, value] of Object.entries(node.properties)) {
2707
+ parts.push(`${indent} "${this.escape(key)}" "${this.escape(value)}"`);
2708
+ }
2709
+ parts.push(`${indent} }`);
2710
+ }
2711
+ if (node.children && node.children.length > 0) {
2712
+ for (const child of node.children) {
2713
+ parts.push(this.generateDeploymentNode(child, indent + " "));
2714
+ }
2715
+ }
2716
+ if (node.containerInstances && node.containerInstances.length > 0) {
2717
+ for (const containerInstance of node.containerInstances) {
2718
+ const instancesStr = containerInstance.instances && containerInstance.instances > 1 ? ` ${containerInstance.instances}` : "";
2719
+ parts.push(`${indent} containerInstance extension.${containerInstance.container}${instancesStr}`);
2720
+ }
2721
+ } else if (!node.children || node.children.length === 0) {
2722
+ const contexts = Object.keys(this.analysis.contexts);
2723
+ if (contexts.length > 0) {
2724
+ for (const contextType of contexts) {
2725
+ parts.push(`${indent} containerInstance extension.${contextType}`);
2726
+ }
2727
+ }
2728
+ }
2729
+ parts.push(`${indent}}`);
2730
+ return parts.join(`
2731
+ `);
2732
+ }
2733
+ generateDeploymentViews() {
2734
+ const parts = [];
2735
+ const nodesByEnvironment = new Map;
2736
+ for (const node of this.options.deploymentNodes || []) {
2737
+ const env = node.tags?.find((tag) => tag.toLowerCase().includes("environment:"))?.split(":")[1] || "Production";
2738
+ if (!nodesByEnvironment.has(env)) {
2739
+ nodesByEnvironment.set(env, []);
2740
+ }
2741
+ nodesByEnvironment.get(env).push(node);
2742
+ }
2743
+ for (const [envName] of nodesByEnvironment) {
2744
+ const description = `${envName} environment deployment architecture`;
2745
+ parts.push(` deployment extension "${envName}" "${description}" {`);
2746
+ parts.push(" include *");
2747
+ parts.push(" autoLayout lr");
2748
+ parts.push(" }");
2749
+ }
2750
+ return parts.join(`
2751
+
2752
+ `);
2753
+ }
2478
2754
  generateStyles() {
2479
2755
  const parts = [];
2480
2756
  parts.push(" styles {");
2481
- const contextStyles = {
2482
- background: "#2E7D32",
2483
- content: "#F57C00",
2484
- popup: "#1976D2",
2485
- devtools: "#7B1FA2",
2486
- options: "#0288D1",
2487
- ...this.options.styles
2488
- };
2489
- for (const [context, color] of Object.entries(contextStyles)) {
2490
- if (this.analysis.contexts[context]) {
2491
- parts.push(` element "extension.${context}" {`);
2492
- parts.push(` background ${color}`);
2493
- parts.push(` color #ffffff`);
2494
- parts.push(" }");
2757
+ if (this.options.includeDefaultStyles && this.options.styles?.elements) {
2758
+ for (const [tag, style] of Object.entries(this.options.styles.elements)) {
2759
+ parts.push(this.generateElementStyle(tag, style));
2495
2760
  }
2496
2761
  }
2762
+ if (this.options.includeDefaultStyles && this.options.styles?.relationships) {
2763
+ for (const [tag, style] of Object.entries(this.options.styles.relationships)) {
2764
+ parts.push(this.generateRelationshipStyle(tag, style));
2765
+ }
2766
+ }
2767
+ if (this.options.styles?.theme) {
2768
+ parts.push(` theme ${this.options.styles.theme}`);
2769
+ }
2497
2770
  parts.push(" }");
2498
2771
  return parts.join(`
2772
+ `);
2773
+ }
2774
+ generateElementStyle(tag, style) {
2775
+ const parts = [];
2776
+ parts.push(` element "${tag}" {`);
2777
+ if (style.shape) {
2778
+ parts.push(` shape ${style.shape}`);
2779
+ }
2780
+ if (style.icon) {
2781
+ parts.push(` icon ${style.icon}`);
2782
+ }
2783
+ if (style.width) {
2784
+ parts.push(` width ${style.width}`);
2785
+ }
2786
+ if (style.height) {
2787
+ parts.push(` height ${style.height}`);
2788
+ }
2789
+ if (style.background) {
2790
+ parts.push(` background ${style.background}`);
2791
+ }
2792
+ if (style.color) {
2793
+ parts.push(` color ${style.color}`);
2794
+ }
2795
+ if (style.fontSize) {
2796
+ parts.push(` fontSize ${style.fontSize}`);
2797
+ }
2798
+ if (style.border) {
2799
+ parts.push(` border ${style.border}`);
2800
+ }
2801
+ if (style.opacity !== undefined) {
2802
+ parts.push(` opacity ${style.opacity}`);
2803
+ }
2804
+ if (style.metadata !== undefined) {
2805
+ parts.push(` metadata ${style.metadata}`);
2806
+ }
2807
+ if (style.description !== undefined) {
2808
+ parts.push(` description ${style.description}`);
2809
+ }
2810
+ parts.push(" }");
2811
+ return parts.join(`
2812
+ `);
2813
+ }
2814
+ generateRelationshipStyle(tag, style) {
2815
+ const parts = [];
2816
+ parts.push(` relationship "${tag}" {`);
2817
+ if (style.thickness) {
2818
+ parts.push(` thickness ${style.thickness}`);
2819
+ }
2820
+ if (style.color) {
2821
+ parts.push(` color ${style.color}`);
2822
+ }
2823
+ if (style.style) {
2824
+ parts.push(` style ${style.style}`);
2825
+ }
2826
+ if (style.routing) {
2827
+ parts.push(` routing ${style.routing}`);
2828
+ }
2829
+ if (style.fontSize) {
2830
+ parts.push(` fontSize ${style.fontSize}`);
2831
+ }
2832
+ if (style.width) {
2833
+ parts.push(` width ${style.width}`);
2834
+ }
2835
+ if (style.position) {
2836
+ parts.push(` position ${style.position}`);
2837
+ }
2838
+ if (style.opacity !== undefined) {
2839
+ parts.push(` opacity ${style.opacity}`);
2840
+ }
2841
+ parts.push(" }");
2842
+ return parts.join(`
2499
2843
  `);
2500
2844
  }
2501
2845
  getContextTechnology(contextType) {
@@ -2521,6 +2865,54 @@ class StructurizrDSLGenerator {
2521
2865
  capitalize(str) {
2522
2866
  return str.charAt(0).toUpperCase() + str.slice(1);
2523
2867
  }
2868
+ generateComponentDefinition(comp, indent) {
2869
+ const parts = [];
2870
+ parts.push(`${indent}${comp.id} = component "${comp.name}" "${this.escape(comp.description)}" {`);
2871
+ if (comp.tags.length > 0) {
2872
+ parts.push(`${indent} tags "${comp.tags.join('" "')}"`);
2873
+ }
2874
+ if (comp.properties && Object.keys(comp.properties).length > 0) {
2875
+ parts.push(`${indent} properties {`);
2876
+ for (const [key, value] of Object.entries(comp.properties)) {
2877
+ if (value) {
2878
+ parts.push(`${indent} "${key}" "${this.escape(value)}"`);
2879
+ }
2880
+ }
2881
+ parts.push(`${indent} }`);
2882
+ }
2883
+ if (this.options.perspectives && this.options.perspectives[comp.id]) {
2884
+ const perspectives = this.options.perspectives[comp.id];
2885
+ parts.push(`${indent} perspectives {`);
2886
+ for (const perspective of perspectives) {
2887
+ parts.push(`${indent} "${this.escape(perspective.name)}" "${this.escape(perspective.description)}"`);
2888
+ }
2889
+ parts.push(`${indent} }`);
2890
+ }
2891
+ parts.push(`${indent}}`);
2892
+ return parts.join(`
2893
+ `);
2894
+ }
2895
+ generateGroupedComponents(componentDefs, groups) {
2896
+ const parts = [];
2897
+ const assignedComponents = new Set;
2898
+ for (const group of groups) {
2899
+ const groupComponents = componentDefs.filter((comp) => group.components.includes(comp.id));
2900
+ if (groupComponents.length === 0)
2901
+ continue;
2902
+ parts.push(` group "${this.escape(group.name)}" {`);
2903
+ for (const comp of groupComponents) {
2904
+ parts.push(this.generateComponentDefinition(comp, " "));
2905
+ assignedComponents.add(comp.id);
2906
+ }
2907
+ parts.push(` }`);
2908
+ parts.push("");
2909
+ }
2910
+ const ungroupedComponents = componentDefs.filter((comp) => !assignedComponents.has(comp.id));
2911
+ for (const comp of ungroupedComponents) {
2912
+ parts.push(this.generateComponentDefinition(comp, " "));
2913
+ }
2914
+ return parts;
2915
+ }
2524
2916
  escape(str) {
2525
2917
  return str.replace(/"/g, "\\\"");
2526
2918
  }
@@ -3007,4 +3399,4 @@ Stack trace:`, COLORS.gray));
3007
3399
  process.exit(1);
3008
3400
  });
3009
3401
 
3010
- //# debugId=78733C0D94700D7D64756E2164756E21
3402
+ //# debugId=85D3947587AAAF0E64756E2164756E21