@fairfox/polly 0.11.0 → 0.12.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.
Files changed (40) hide show
  1. package/dist/src/client/index.d.ts +33 -0
  2. package/dist/src/client/index.js +586 -0
  3. package/dist/src/client/index.js.map +13 -0
  4. package/dist/src/client/wrapper.d.ts +54 -0
  5. package/dist/src/core/clock.d.ts +63 -0
  6. package/dist/src/elysia/index.d.ts +43 -0
  7. package/dist/src/elysia/index.js +241 -0
  8. package/dist/src/elysia/index.js.map +12 -0
  9. package/dist/src/elysia/plugin.d.ts +85 -0
  10. package/dist/src/elysia/tla-generator.d.ts +16 -0
  11. package/dist/src/elysia/types.d.ts +137 -0
  12. package/dist/src/utils/function-serialization.d.ts +14 -0
  13. package/dist/tools/analysis/src/extract/adr.d.ts +37 -0
  14. package/dist/tools/analysis/src/extract/architecture.d.ts +42 -0
  15. package/dist/tools/analysis/src/extract/contexts.d.ts +74 -0
  16. package/dist/tools/analysis/src/extract/flows.d.ts +68 -0
  17. package/dist/tools/analysis/src/extract/handlers.d.ts +330 -0
  18. package/dist/tools/analysis/src/extract/index.d.ts +9 -0
  19. package/dist/tools/analysis/src/extract/integrations.d.ts +77 -0
  20. package/dist/tools/analysis/src/extract/manifest.d.ts +64 -0
  21. package/dist/tools/analysis/src/extract/project-detector.d.ts +103 -0
  22. package/dist/tools/analysis/src/extract/relationships.d.ts +119 -0
  23. package/dist/tools/analysis/src/extract/types.d.ts +139 -0
  24. package/dist/tools/analysis/src/index.d.ts +2 -0
  25. package/dist/tools/analysis/src/types/adr.d.ts +39 -0
  26. package/dist/tools/analysis/src/types/architecture.d.ts +198 -0
  27. package/dist/tools/analysis/src/types/core.d.ts +178 -0
  28. package/dist/tools/analysis/src/types/index.d.ts +4 -0
  29. package/dist/tools/teach/src/cli.js +140 -69
  30. package/dist/tools/teach/src/cli.js.map +12 -12
  31. package/dist/tools/teach/src/index.d.ts +28 -0
  32. package/dist/tools/teach/src/index.js +145 -72
  33. package/dist/tools/teach/src/index.js.map +13 -13
  34. package/dist/tools/verify/src/cli.js +33 -11
  35. package/dist/tools/verify/src/cli.js.map +5 -5
  36. package/dist/tools/visualize/src/cli.js +125 -66
  37. package/dist/tools/visualize/src/cli.js.map +11 -11
  38. package/dist/tools/visualize/src/codegen/structurizr.d.ts +343 -0
  39. package/dist/tools/visualize/src/types/structurizr.d.ts +235 -0
  40. package/package.json +10 -5
@@ -0,0 +1,178 @@
1
+ export type TypeKind = "boolean" | "string" | "number" | "enum" | "array" | "object" | "map" | "set" | "union" | "null" | "unknown";
2
+ export type TypeInfo = {
3
+ name: string;
4
+ kind: TypeKind;
5
+ nullable: boolean;
6
+ elementType?: TypeInfo;
7
+ valueType?: TypeInfo;
8
+ properties?: Record<string, TypeInfo>;
9
+ enumValues?: string[];
10
+ unionTypes?: TypeInfo[];
11
+ };
12
+ /**
13
+ * A node represents an entity in the system that can send/receive messages.
14
+ *
15
+ * Examples:
16
+ * - Web extension: "background", "content", "popup"
17
+ * - Actor system: Individual actor instances
18
+ * - Event bus: Emitters/listeners
19
+ * - Worker threads: Main thread + worker instances
20
+ */
21
+ export type NodeDefinition = {
22
+ /** Unique identifier for this node */
23
+ id: string;
24
+ /** Type of node (adapter-specific) */
25
+ type: string;
26
+ /** Which nodes can this send messages to? */
27
+ canSendTo: string[];
28
+ /** Which nodes can send messages to this? */
29
+ canReceiveFrom: string[];
30
+ /** Optional: Additional metadata */
31
+ metadata?: Record<string, unknown>;
32
+ };
33
+ /**
34
+ * Defines a type of message that flows through the system
35
+ */
36
+ export type MessageTypeDefinition = {
37
+ /** Name/identifier of the message type */
38
+ name: string;
39
+ /** Schema of the message payload */
40
+ payload: TypeInfo;
41
+ /** Routing constraints */
42
+ routing: {
43
+ /** Which node types can send this message? */
44
+ from: string[];
45
+ /** Which node types can receive this message? */
46
+ to: string[];
47
+ };
48
+ /** Optional: Expected response type */
49
+ response?: TypeInfo;
50
+ };
51
+ /**
52
+ * Configuration for a state field
53
+ */
54
+ export type FieldConfig = {
55
+ maxLength: number | null;
56
+ } | {
57
+ min: number | null;
58
+ max: number | null;
59
+ } | {
60
+ type: "enum";
61
+ values: string[];
62
+ } | {
63
+ values: string[] | null;
64
+ abstract?: boolean;
65
+ } | {
66
+ maxSize: number | null;
67
+ valueType?: unknown;
68
+ } | {
69
+ abstract: boolean;
70
+ };
71
+ export type StateSchema = Record<string, FieldConfig>;
72
+ /**
73
+ * Represents an assignment to a state field
74
+ */
75
+ export type StateAssignment = {
76
+ /** Field path (e.g., "user.loggedIn") */
77
+ field: string;
78
+ /** The assigned value */
79
+ value: string | boolean | number | null;
80
+ /** Optional condition guard */
81
+ conditional?: string;
82
+ };
83
+ /**
84
+ * A verification condition (precondition or postcondition)
85
+ */
86
+ export type VerificationCondition = {
87
+ /** The condition expression as a string */
88
+ expression: string;
89
+ /** Optional error message */
90
+ message?: string;
91
+ /** Source location */
92
+ location: {
93
+ line: number;
94
+ column: number;
95
+ };
96
+ };
97
+ /**
98
+ * Constraint declared at the state level.
99
+ * These are automatically wired to message handlers by the parser.
100
+ */
101
+ export type StateConstraint = {
102
+ /** State field this constraint applies to */
103
+ field: string;
104
+ /** Message type this constraint applies to */
105
+ messageType: string;
106
+ /** Precondition expression (e.g., "loggedIn === true") */
107
+ requires?: string;
108
+ /** Postcondition expression */
109
+ ensures?: string;
110
+ /** Optional error message */
111
+ message?: string;
112
+ /** Source location */
113
+ location: {
114
+ file: string;
115
+ line: number;
116
+ };
117
+ };
118
+ /**
119
+ * Component relationship detected from code analysis
120
+ */
121
+ export type ComponentRelationship = {
122
+ /** Source component */
123
+ from: string;
124
+ /** Target component */
125
+ to: string;
126
+ /** Description of the relationship */
127
+ description: string;
128
+ /** Technology/method used */
129
+ technology?: string;
130
+ /** Confidence level */
131
+ confidence: "high" | "medium" | "low";
132
+ /** Evidence supporting this detection */
133
+ evidence: string[];
134
+ };
135
+ /**
136
+ * Represents a message handler extracted from code
137
+ */
138
+ export type MessageHandler = {
139
+ /** Which message type does this handle? */
140
+ messageType: string;
141
+ /** Which node handles this message? */
142
+ node: string;
143
+ /** State assignments made by this handler */
144
+ assignments: StateAssignment[];
145
+ /** Preconditions (requires() calls) */
146
+ preconditions: VerificationCondition[];
147
+ /** Postconditions (ensures() calls) */
148
+ postconditions: VerificationCondition[];
149
+ /** Source location */
150
+ location: {
151
+ file: string;
152
+ line: number;
153
+ };
154
+ /** Component relationships detected from this handler's code */
155
+ relationships?: ComponentRelationship[];
156
+ };
157
+ export type Confidence = "high" | "medium" | "low";
158
+ export type FieldAnalysis = {
159
+ path: string;
160
+ type: TypeInfo;
161
+ confidence: Confidence;
162
+ evidence: string[];
163
+ suggestions: string[];
164
+ bounds?: {
165
+ min?: number;
166
+ max?: number;
167
+ maxLength?: number;
168
+ maxSize?: number;
169
+ values?: string[];
170
+ };
171
+ };
172
+ export type CodebaseAnalysis = {
173
+ stateType: TypeInfo | null;
174
+ messageTypes: string[];
175
+ fields: FieldAnalysis[];
176
+ handlers: MessageHandler[];
177
+ stateConstraints: StateConstraint[];
178
+ };
@@ -0,0 +1,4 @@
1
+ export * from "./adr";
2
+ export * from "./architecture";
3
+ export * from "./core";
4
+ export type Context = "background" | "content" | "popup" | "devtools" | "options" | "offscreen" | "sidepanel";
@@ -94,25 +94,30 @@ class ProjectDetector {
94
94
  };
95
95
  }
96
96
  detectBackgroundEntry(manifest, entryPoints) {
97
- const background = manifest.background;
97
+ const background = manifest["background"];
98
98
  if (!background)
99
99
  return;
100
- const file = background.service_worker || background.scripts?.[0] || background.page;
100
+ const file = background["service_worker"] || background["scripts"]?.[0] || background["page"];
101
101
  if (file) {
102
102
  entryPoints["background"] = this.findSourceFile(file);
103
103
  }
104
104
  }
105
105
  detectContentScriptEntry(manifest, entryPoints) {
106
- const contentScripts = manifest.content_scripts;
106
+ const contentScripts = manifest["content_scripts"];
107
107
  if (!contentScripts || contentScripts.length === 0)
108
108
  return;
109
- const firstScript = contentScripts[0].js?.[0];
109
+ const firstScriptObj = contentScripts[0];
110
+ if (!firstScriptObj)
111
+ return;
112
+ const firstScript = firstScriptObj["js"]?.[0];
110
113
  if (firstScript) {
111
114
  entryPoints["content"] = this.findSourceFile(firstScript);
112
115
  }
113
116
  }
114
117
  detectPopupEntry(manifest, entryPoints) {
115
- const popup = manifest.action?.default_popup || manifest.browser_action?.default_popup;
118
+ const action = manifest["action"];
119
+ const browserAction = manifest["browser_action"];
120
+ const popup = action?.["default_popup"] || browserAction?.["default_popup"];
116
121
  if (!popup)
117
122
  return;
118
123
  const jsFile = this.findAssociatedJS(path4.join(this.projectRoot, popup));
@@ -121,7 +126,8 @@ class ProjectDetector {
121
126
  }
122
127
  }
123
128
  detectOptionsEntry(manifest, entryPoints) {
124
- const options = manifest.options_ui?.page || manifest.options_page;
129
+ const optionsUi = manifest["options_ui"];
130
+ const options = optionsUi?.["page"] || manifest["options_page"];
125
131
  if (!options)
126
132
  return;
127
133
  const jsFile = this.findAssociatedJS(path4.join(this.projectRoot, options));
@@ -176,7 +182,7 @@ class ProjectDetector {
176
182
  detectElectron(packageJson) {
177
183
  const entryPoints = {};
178
184
  const mainCandidates = [
179
- packageJson.main,
185
+ packageJson["main"],
180
186
  "src/main/index.ts",
181
187
  "src/electron/main.ts",
182
188
  "electron/main.ts",
@@ -210,9 +216,9 @@ class ProjectDetector {
210
216
  renderer: "Renderer Process"
211
217
  },
212
218
  metadata: {
213
- name: packageJson.name,
214
- version: packageJson.version,
215
- description: packageJson.description
219
+ name: packageJson["name"],
220
+ version: packageJson["version"],
221
+ description: packageJson["description"]
216
222
  }
217
223
  };
218
224
  }
@@ -271,9 +277,9 @@ class ProjectDetector {
271
277
  client: "Client"
272
278
  },
273
279
  metadata: {
274
- name: packageJson.name,
275
- version: packageJson.version,
276
- description: packageJson.description
280
+ name: packageJson["name"],
281
+ version: packageJson["version"],
282
+ description: packageJson["description"]
277
283
  }
278
284
  };
279
285
  }
@@ -4645,9 +4651,12 @@ class ContextAnalyzer {
4645
4651
  const leadingComments = firstStatement.getLeadingCommentRanges();
4646
4652
  if (leadingComments.length === 0)
4647
4653
  return;
4648
- const comment = leadingComments[0].getText();
4654
+ const firstComment = leadingComments[0];
4655
+ if (!firstComment)
4656
+ return;
4657
+ const comment = firstComment.getText();
4649
4658
  const descMatch = comment.match(/@description\s+(.+?)(?:\n|$)/s);
4650
- if (descMatch) {
4659
+ if (descMatch?.[1]) {
4651
4660
  return descMatch[1].trim();
4652
4661
  }
4653
4662
  const lines = comment.split(`
@@ -4746,6 +4755,8 @@ class ContextAnalyzer {
4746
4755
  if (params.length === 0)
4747
4756
  return [];
4748
4757
  const propsParam = params[0];
4758
+ if (!propsParam)
4759
+ return [];
4749
4760
  const type = propsParam.getType();
4750
4761
  const props = [];
4751
4762
  for (const prop of type.getProperties()) {
@@ -4761,6 +4772,8 @@ class ContextAnalyzer {
4761
4772
  if (typeArgs.length === 0)
4762
4773
  return [];
4763
4774
  const propsType = typeArgs[0];
4775
+ if (!propsType)
4776
+ return [];
4764
4777
  const props = [];
4765
4778
  for (const prop of propsType.getProperties()) {
4766
4779
  props.push(prop.getName());
@@ -4768,10 +4781,15 @@ class ContextAnalyzer {
4768
4781
  return props;
4769
4782
  }
4770
4783
  extractJSDocDescription(node) {
4784
+ if (!Node.isJSDocable(node))
4785
+ return;
4771
4786
  const jsDocs = node.getJsDocs();
4772
4787
  if (jsDocs.length === 0)
4773
4788
  return;
4774
- const description = jsDocs[0].getDescription().trim();
4789
+ const firstDoc = jsDocs[0];
4790
+ if (!firstDoc)
4791
+ return;
4792
+ const description = firstDoc.getDescription().trim();
4775
4793
  return description || undefined;
4776
4794
  }
4777
4795
  isUIContext(contextType) {
@@ -4853,7 +4871,10 @@ class FlowAnalyzer {
4853
4871
  if (args.length === 0) {
4854
4872
  return;
4855
4873
  }
4856
- const msgType = this.extractMessageTypeFromArg(args[0]);
4874
+ const firstArg = args[0];
4875
+ if (!firstArg)
4876
+ return;
4877
+ const msgType = this.extractMessageTypeFromArg(firstArg);
4857
4878
  if (msgType === messageType) {
4858
4879
  senders.push({
4859
4880
  context,
@@ -4873,7 +4894,10 @@ class FlowAnalyzer {
4873
4894
  if (args.length === 0) {
4874
4895
  return;
4875
4896
  }
4876
- const msgType = this.extractMessageTypeFromArg(args[0]);
4897
+ const firstArg = args[0];
4898
+ if (!firstArg)
4899
+ return;
4900
+ const msgType = this.extractMessageTypeFromArg(firstArg);
4877
4901
  if (msgType === messageType) {
4878
4902
  senders.push({
4879
4903
  context,
@@ -4943,7 +4967,10 @@ class FlowAnalyzer {
4943
4967
  if (args.length === 0) {
4944
4968
  return;
4945
4969
  }
4946
- const messageType = this.extractMessageTypeFromArg(args[0]);
4970
+ const firstArg = args[0];
4971
+ if (!firstArg)
4972
+ return;
4973
+ const messageType = this.extractMessageTypeFromArg(firstArg);
4947
4974
  if (messageType) {
4948
4975
  sends.push({
4949
4976
  messageType,
@@ -4996,10 +5023,17 @@ class FlowAnalyzer {
4996
5023
  });
4997
5024
  if (!targetNode)
4998
5025
  return {};
4999
- const jsDocs = targetNode.getJsDocs?.() || [];
5026
+ const nodeAny = targetNode;
5027
+ if (!("getJsDocs" in nodeAny) || typeof nodeAny.getJsDocs !== "function") {
5028
+ return {};
5029
+ }
5030
+ const jsDocs = nodeAny.getJsDocs();
5000
5031
  if (jsDocs.length === 0)
5001
5032
  return {};
5002
- const comment = jsDocs[0].getText();
5033
+ const firstDoc = jsDocs[0];
5034
+ if (!firstDoc)
5035
+ return {};
5036
+ const comment = firstDoc.getText();
5003
5037
  const flowMatch = comment.match(/@flow\s+([^\s]+)/);
5004
5038
  const flowName = flowMatch ? flowMatch[1] : undefined;
5005
5039
  const triggerMatch = comment.match(/@trigger\s+(.+?)(?:\n|$)/);
@@ -5802,7 +5836,10 @@ class HandlerExtractor {
5802
5836
  if (!body) {
5803
5837
  return;
5804
5838
  }
5805
- const firstAwaitPos = awaitExpressions[0].getStart();
5839
+ const firstAwait = awaitExpressions[0];
5840
+ if (!firstAwait)
5841
+ return;
5842
+ const firstAwaitPos = firstAwait.getStart();
5806
5843
  funcNode.forEachDescendant((node) => {
5807
5844
  if (Node4.isBinaryExpression(node)) {
5808
5845
  this.checkBinaryExpressionMutation(node, firstAwaitPos, mutations);
@@ -5853,6 +5890,8 @@ class HandlerExtractor {
5853
5890
  return null;
5854
5891
  }
5855
5892
  const conditionArg = args[0];
5893
+ if (!conditionArg)
5894
+ return null;
5856
5895
  const expression = conditionArg.getText();
5857
5896
  let message;
5858
5897
  if (args.length >= 2 && Node4.isStringLiteral(args[1])) {
@@ -6158,12 +6197,17 @@ class HandlerExtractor {
6158
6197
  return;
6159
6198
  }
6160
6199
  extractMessageTypeFromTypePredicateFunction(node, returnTypeNode) {
6161
- const typeNode = returnTypeNode.getTypeNode();
6162
- if (typeNode) {
6163
- const typeName = typeNode.getText();
6164
- const messageType = this.extractMessageTypeFromTypeName(typeName);
6165
- if (messageType) {
6166
- return messageType;
6200
+ if (!Node4.isTypePredicate(returnTypeNode)) {
6201
+ return null;
6202
+ }
6203
+ if ("getTypeNode" in returnTypeNode && typeof returnTypeNode.getTypeNode === "function") {
6204
+ const typeNode = returnTypeNode.getTypeNode();
6205
+ if (typeNode) {
6206
+ const typeName = typeNode.getText();
6207
+ const messageType = this.extractMessageTypeFromTypeName(typeName);
6208
+ if (messageType) {
6209
+ return messageType;
6210
+ }
6167
6211
  }
6168
6212
  }
6169
6213
  return this.extractMessageTypeFromFunctionBodyText(node);
@@ -6495,7 +6539,10 @@ class IntegrationAnalyzer {
6495
6539
  if (args.length === 0) {
6496
6540
  return;
6497
6541
  }
6498
- const url = this.extractURLFromArg(args[0]);
6542
+ const firstArg = args[0];
6543
+ if (!firstArg)
6544
+ return;
6545
+ const url = this.extractURLFromArg(firstArg);
6499
6546
  if (!url) {
6500
6547
  return;
6501
6548
  }
@@ -6676,10 +6723,15 @@ class IntegrationAnalyzer {
6676
6723
  }
6677
6724
  }
6678
6725
  extractJSDocDescription(node) {
6679
- const jsDocs = node.getJsDocs?.() || [];
6726
+ if (!Node5.isJSDocable(node))
6727
+ return;
6728
+ const jsDocs = node.getJsDocs();
6680
6729
  if (jsDocs.length === 0)
6681
6730
  return;
6682
- const comment = jsDocs[0].getDescription().trim();
6731
+ const firstDoc = jsDocs[0];
6732
+ if (!firstDoc)
6733
+ return;
6734
+ const comment = firstDoc.getDescription().trim();
6683
6735
  return comment || undefined;
6684
6736
  }
6685
6737
  }
@@ -6718,17 +6770,17 @@ class ManifestParser {
6718
6770
  }
6719
6771
  const manifest = this.manifestData;
6720
6772
  return {
6721
- name: manifest.name || "Unknown Extension",
6722
- version: manifest.version || "0.0.0",
6723
- description: manifest.description,
6724
- manifestVersion: manifest.manifest_version || 2,
6773
+ name: manifest["name"] || "Unknown Extension",
6774
+ version: manifest["version"] || "0.0.0",
6775
+ description: manifest["description"],
6776
+ manifestVersion: manifest["manifest_version"] || 2,
6725
6777
  background: this.parseBackground(),
6726
6778
  contentScripts: this.parseContentScripts(),
6727
6779
  popup: this.parsePopup(),
6728
6780
  options: this.parseOptions(),
6729
6781
  devtools: this.parseDevtools(),
6730
- permissions: manifest.permissions || [],
6731
- hostPermissions: manifest.host_permissions || []
6782
+ permissions: manifest["permissions"] || [],
6783
+ hostPermissions: manifest["host_permissions"] || []
6732
6784
  };
6733
6785
  }
6734
6786
  getContextEntryPoints() {
@@ -6794,25 +6846,25 @@ class ManifestParser {
6794
6846
  parseBackground() {
6795
6847
  if (!this.manifestData)
6796
6848
  return;
6797
- const bg = this.manifestData.background;
6849
+ const bg = this.manifestData["background"];
6798
6850
  if (!bg)
6799
6851
  return;
6800
- if (bg.service_worker) {
6852
+ if (bg["service_worker"]) {
6801
6853
  return {
6802
6854
  type: "service_worker",
6803
- files: [bg.service_worker]
6855
+ files: [bg["service_worker"]]
6804
6856
  };
6805
6857
  }
6806
- if (bg.scripts) {
6858
+ if (bg["scripts"]) {
6807
6859
  return {
6808
6860
  type: "script",
6809
- files: bg.scripts
6861
+ files: bg["scripts"]
6810
6862
  };
6811
6863
  }
6812
- if (bg.page) {
6864
+ if (bg["page"]) {
6813
6865
  return {
6814
6866
  type: "script",
6815
- files: [bg.page]
6867
+ files: [bg["page"]]
6816
6868
  };
6817
6869
  }
6818
6870
  return;
@@ -6820,24 +6872,24 @@ class ManifestParser {
6820
6872
  parseContentScripts() {
6821
6873
  if (!this.manifestData)
6822
6874
  return;
6823
- const cs = this.manifestData.content_scripts;
6875
+ const cs = this.manifestData["content_scripts"];
6824
6876
  if (!cs || !Array.isArray(cs))
6825
6877
  return;
6826
6878
  return cs.map((script) => ({
6827
- matches: script.matches || [],
6828
- js: script.js || [],
6829
- css: script.css
6879
+ matches: script["matches"] || [],
6880
+ js: script["js"] || [],
6881
+ css: script["css"]
6830
6882
  }));
6831
6883
  }
6832
6884
  parsePopup() {
6833
6885
  if (!this.manifestData)
6834
6886
  return;
6835
- const action = this.manifestData.action || this.manifestData.browser_action;
6887
+ const action = this.manifestData["action"] || this.manifestData["browser_action"];
6836
6888
  if (!action)
6837
6889
  return;
6838
- if (action.default_popup) {
6890
+ if (action["default_popup"]) {
6839
6891
  return {
6840
- html: action.default_popup,
6892
+ html: action["default_popup"],
6841
6893
  default: true
6842
6894
  };
6843
6895
  }
@@ -6846,7 +6898,7 @@ class ManifestParser {
6846
6898
  parseOptions() {
6847
6899
  if (!this.manifestData)
6848
6900
  return;
6849
- const options = this.manifestData.options_ui || this.manifestData.options_page;
6901
+ const options = this.manifestData["options_ui"] || this.manifestData["options_page"];
6850
6902
  if (!options)
6851
6903
  return;
6852
6904
  if (typeof options === "string") {
@@ -6855,15 +6907,16 @@ class ManifestParser {
6855
6907
  openInTab: false
6856
6908
  };
6857
6909
  }
6910
+ const optionsObj = options;
6858
6911
  return {
6859
- page: options.page,
6860
- openInTab: options.open_in_tab
6912
+ page: optionsObj["page"],
6913
+ openInTab: optionsObj["open_in_tab"]
6861
6914
  };
6862
6915
  }
6863
6916
  parseDevtools() {
6864
6917
  if (!this.manifestData)
6865
6918
  return;
6866
- const devtools = this.manifestData.devtools_page;
6919
+ const devtools = this.manifestData["devtools_page"];
6867
6920
  if (!devtools)
6868
6921
  return;
6869
6922
  return {
@@ -7060,11 +7113,20 @@ class TypeExtractor {
7060
7113
  const handlerAnalysis = this.extractHandlerAnalysis();
7061
7114
  const validMessageTypes = this.filterAndLogMessageTypes(messageTypes, handlerAnalysis.messageTypes);
7062
7115
  const validHandlers = this.filterAndLogHandlers(handlerAnalysis.handlers);
7116
+ const completeHandlers = validHandlers.map((h) => ({
7117
+ messageType: h.messageType,
7118
+ node: h.node || "unknown",
7119
+ assignments: h.assignments || [],
7120
+ preconditions: h.preconditions || [],
7121
+ postconditions: h.postconditions || [],
7122
+ location: h.location,
7123
+ relationships: h.relationships
7124
+ }));
7063
7125
  return {
7064
7126
  stateType,
7065
7127
  messageTypes: validMessageTypes,
7066
7128
  fields,
7067
- handlers: validHandlers,
7129
+ handlers: completeHandlers,
7068
7130
  stateConstraints: handlerAnalysis.stateConstraints
7069
7131
  };
7070
7132
  }
@@ -7166,7 +7228,7 @@ class TypeExtractor {
7166
7228
  if (type.getAliasSymbol()) {
7167
7229
  return this.extractFromTypeAlias(type, typeName, sourceFile, warnings);
7168
7230
  }
7169
- if (type.isConditionalType?.()) {
7231
+ if (typeof type.isConditionalType === "function" && type.isConditionalType()) {
7170
7232
  return this.extractFromConditionalType(type, warnings);
7171
7233
  }
7172
7234
  if (type.getText().includes("[K in ")) {
@@ -7231,7 +7293,10 @@ class TypeExtractor {
7231
7293
  if (parts.length < 2) {
7232
7294
  return messageTypes;
7233
7295
  }
7234
- const branches = parts[1].split(":");
7296
+ const secondPart = parts[1];
7297
+ if (!secondPart)
7298
+ return messageTypes;
7299
+ const branches = secondPart.split(":");
7235
7300
  for (const branch of branches) {
7236
7301
  const extracted = this.extractStringLiteralFromBranch(branch);
7237
7302
  if (extracted) {
@@ -7693,9 +7758,12 @@ class StructurizrDSLGenerator {
7693
7758
  }
7694
7759
  for (const [messageType, handlers2] of handlersByType) {
7695
7760
  const componentName = this.toComponentName(messageType);
7696
- const description = this.generateComponentDescription(messageType, handlers2[0]);
7697
- const tags = this.getComponentTags(messageType, handlers2[0]);
7698
- const properties = this.getComponentProperties(messageType, handlers2[0], contextType);
7761
+ const firstHandler = handlers2[0];
7762
+ if (!firstHandler)
7763
+ continue;
7764
+ const description = this.generateComponentDescription(messageType, firstHandler);
7765
+ const tags = this.getComponentTags(messageType, firstHandler);
7766
+ const properties = this.getComponentProperties(messageType, firstHandler, contextType);
7699
7767
  componentDefs.push({
7700
7768
  id: this.toId(componentName),
7701
7769
  name: componentName,
@@ -8226,7 +8294,8 @@ class StructurizrDSLGenerator {
8226
8294
  let stepCount = 0;
8227
8295
  for (const { handler, contextName: _contextName } of handlers2) {
8228
8296
  const handlerComponentId = this.toId(`${handler.messageType}_handler`);
8229
- for (const rel of handler.relationships) {
8297
+ const relationships = handler.relationships || [];
8298
+ for (const rel of relationships) {
8230
8299
  const toComponent = this.toId(rel.to);
8231
8300
  parts.push(` ${handlerComponentId} -> ${toComponent} "${rel.description}"`);
8232
8301
  stepCount++;
@@ -8307,7 +8376,7 @@ class StructurizrDSLGenerator {
8307
8376
  state: "Application state synchronization",
8308
8377
  general: "Message flow through the system"
8309
8378
  };
8310
- return descriptions[domain] || descriptions.general;
8379
+ return descriptions[domain] || descriptions["general"] || "Message flow through the system";
8311
8380
  }
8312
8381
  getUserAction(domain) {
8313
8382
  const actions = {
@@ -8316,7 +8385,7 @@ class StructurizrDSLGenerator {
8316
8385
  state: "Requests state",
8317
8386
  general: "Interacts"
8318
8387
  };
8319
- return actions[domain] || actions.general;
8388
+ return actions[domain] || actions["general"] || "Interacts";
8320
8389
  }
8321
8390
  getMessageDescription(messageType) {
8322
8391
  const type = messageType.toLowerCase();
@@ -8555,11 +8624,13 @@ class StructurizrDSLGenerator {
8555
8624
  }
8556
8625
  if (this.options.perspectives?.[comp.id]) {
8557
8626
  const perspectives = this.options.perspectives[comp.id];
8558
- parts.push(`${indent} perspectives {`);
8559
- for (const perspective of perspectives) {
8560
- parts.push(`${indent} "${this.escape(perspective.name)}" "${this.escape(perspective.description)}"`);
8627
+ if (perspectives) {
8628
+ parts.push(`${indent} perspectives {`);
8629
+ for (const perspective of perspectives) {
8630
+ parts.push(`${indent} "${this.escape(perspective.name)}" "${this.escape(perspective.description)}"`);
8631
+ }
8632
+ parts.push(`${indent} }`);
8561
8633
  }
8562
- parts.push(`${indent} }`);
8563
8634
  }
8564
8635
  parts.push(`${indent}}`);
8565
8636
  return parts.join(`
@@ -9508,4 +9579,4 @@ Goodbye!`);
9508
9579
  }
9509
9580
  main();
9510
9581
 
9511
- //# debugId=CDFF2E3A99C1DA5C64756E2164756E21
9582
+ //# debugId=770FFA3847E6590364756E2164756E21