karavan-core 4.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/.bebelrc +3 -0
  2. package/.mocharc.json +11 -0
  3. package/.prettierignore +9 -0
  4. package/.prettierrc +14 -0
  5. package/package.json +62 -0
  6. package/src/core/api/CamelDefinitionApi.ts +3271 -0
  7. package/src/core/api/CamelDefinitionApiExt.ts +757 -0
  8. package/src/core/api/CamelDefinitionYaml.ts +412 -0
  9. package/src/core/api/CamelDefinitionYamlStep.ts +4733 -0
  10. package/src/core/api/CamelDisplayUtil.ts +143 -0
  11. package/src/core/api/CamelUtil.ts +360 -0
  12. package/src/core/api/ComponentApi.ts +368 -0
  13. package/src/core/api/KameletApi.ts +147 -0
  14. package/src/core/api/MainConfigurationApi.ts +47 -0
  15. package/src/core/api/ProjectModelApi.ts +75 -0
  16. package/src/core/api/SpiBeanApi.ts +104 -0
  17. package/src/core/api/TemplateApi.ts +58 -0
  18. package/src/core/api/TopologyUtils.ts +392 -0
  19. package/src/core/api/VariableUtil.ts +104 -0
  20. package/src/core/model/CamelDefinition.ts +3783 -0
  21. package/src/core/model/CamelMetadata.ts +2714 -0
  22. package/src/core/model/ComponentModels.ts +106 -0
  23. package/src/core/model/IntegrationDefinition.ts +188 -0
  24. package/src/core/model/KameletModels.ts +223 -0
  25. package/src/core/model/MainConfigurationModel.ts +37 -0
  26. package/src/core/model/ProjectModel.ts +43 -0
  27. package/src/core/model/SpiBeanModels.ts +53 -0
  28. package/src/core/model/TopologyDefinition.ts +117 -0
  29. package/test/addStep.spec.ts +124 -0
  30. package/test/addStep1.yaml +27 -0
  31. package/test/allowableValues.camel.yaml +19 -0
  32. package/test/allowableValues.spec.ts +30 -0
  33. package/test/avro-serialize-action.kamelet.yaml +70 -0
  34. package/test/beans.spec.ts +92 -0
  35. package/test/beans1.yaml +36 -0
  36. package/test/beans2.yaml +42 -0
  37. package/test/beans3.yaml +7 -0
  38. package/test/checkRequired.spec.ts +53 -0
  39. package/test/circuitBreaker.spec.ts +57 -0
  40. package/test/circuitBreaker.yaml +19 -0
  41. package/test/cloneDefinition.spec.ts +106 -0
  42. package/test/createKamelet.spec.ts +38 -0
  43. package/test/cxf.json +615 -0
  44. package/test/cxf.spec.ts +44 -0
  45. package/test/cxf.yaml +15 -0
  46. package/test/deleteStep.spec.ts +74 -0
  47. package/test/demo.spec.ts +49 -0
  48. package/test/demo.yaml +32 -0
  49. package/test/doCatchOnWhen.camel.yaml +20 -0
  50. package/test/doCatchOnWhen.spec.ts +36 -0
  51. package/test/errorHandler.spec.ts +38 -0
  52. package/test/errorHandler1.yaml +27 -0
  53. package/test/expression.spec.ts +55 -0
  54. package/test/findStep.spec.ts +112 -0
  55. package/test/findStep.yaml +65 -0
  56. package/test/getElementProperties.spec.ts +32 -0
  57. package/test/getElementPropertiesByName.spec.ts +31 -0
  58. package/test/getExpressionLanguage.spec.ts +40 -0
  59. package/test/hasElementWithId.camel.yaml +98 -0
  60. package/test/hasElementWithId.spec.ts +57 -0
  61. package/test/hasElementWithId1.camel.yaml +16 -0
  62. package/test/hasElementWithIdError.camel.yaml +98 -0
  63. package/test/integration.spec.ts +60 -0
  64. package/test/integration1.yaml +24 -0
  65. package/test/integration2.yaml +23 -0
  66. package/test/integrationToYaml.spec.ts +51 -0
  67. package/test/intercept.spec.ts +62 -0
  68. package/test/intercept.yaml +19 -0
  69. package/test/is-not-integration.yaml +5114 -0
  70. package/test/isIntegration.spec.ts +45 -0
  71. package/test/kamelet.spec.ts +61 -0
  72. package/test/metadata/components.json +697 -0
  73. package/test/metadata/kamelets.yaml +23414 -0
  74. package/test/metadata/spiBeans.json +3094 -0
  75. package/test/multiObjectProperties.spec.ts +46 -0
  76. package/test/multiObjectProperties1.yaml +19 -0
  77. package/test/multiple.spec.ts +38 -0
  78. package/test/multiple.yaml +29 -0
  79. package/test/openapi.spec.ts +48 -0
  80. package/test/openapi.yaml +7 -0
  81. package/test/placeholder.spec.ts +32 -0
  82. package/test/placeholder.yaml +133 -0
  83. package/test/plain-try-catch.yaml +31 -0
  84. package/test/plain.spec.ts +72 -0
  85. package/test/plain1.yaml +22 -0
  86. package/test/plain2.yaml +13 -0
  87. package/test/plain3.yaml +5 -0
  88. package/test/plain4.yaml +5 -0
  89. package/test/postgresql-source.kamelet.yaml +113 -0
  90. package/test/restConfigDsl.yaml +15 -0
  91. package/test/restDsl.spec.ts +83 -0
  92. package/test/restDsl.yaml +29 -0
  93. package/test/routes.spec.ts +37 -0
  94. package/test/routes1.yaml +31 -0
  95. package/test/supported-components.json +1221 -0
  96. package/test/supportedComponents.spec.ts +34 -0
  97. package/test/template1.AggregationStrategy.java +21 -0
  98. package/test/template1.Processor.java +13 -0
  99. package/test/template2.AggregationStrategy.java +21 -0
  100. package/test/template2.Processor.java +13 -0
  101. package/test/templateApi.spec.ts +45 -0
  102. package/test/timer-source.kamelet.yaml +75 -0
  103. package/test/tod.spec.ts +31 -0
  104. package/test/tod.yaml +9 -0
  105. package/test/topology.spec.ts +51 -0
  106. package/test/topology1.camel.yaml +56 -0
  107. package/test/topology2.camel.yaml +44 -0
  108. package/test/topology3.camel.yaml +27 -0
  109. package/test/tsconfig.testing.json +14 -0
  110. package/test/updateStep.spec.ts +72 -0
  111. package/test/variable1.camel.yaml +42 -0
  112. package/test/variable2.camel.yaml +42 -0
  113. package/test/variables.spec.ts +34 -0
  114. package/tsconfig.json +34 -0
@@ -0,0 +1,104 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one or more
3
+ * contributor license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright ownership.
5
+ * The ASF licenses this file to You under the Apache License, Version 2.0
6
+ * (the "License"); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import { SpiBean, SpiBeanProperty } from '../model/SpiBeanModels';
18
+ import { CamelElement } from '../model/IntegrationDefinition';
19
+
20
+ const SpiBeans: SpiBean[] = [];
21
+
22
+ export class SpiBeanApi {
23
+ private constructor() {}
24
+
25
+ static jsonToSpiBean = (json: string): SpiBean => {
26
+ const fromJson: SpiBean = JSON.parse(json).bean as SpiBean;
27
+ return new SpiBean(fromJson);
28
+ };
29
+
30
+ static saveSpiBeans = (jsons: string[], clean: boolean = false): void => {
31
+ if (clean) SpiBeans.length = 0;
32
+ const spiBeans: SpiBean[] = jsons.map(json => SpiBeanApi.jsonToSpiBean(json));
33
+ SpiBeans.push(...spiBeans);
34
+ };
35
+
36
+ static saveSpiBean = (json: string): void => {
37
+ const spiBean: SpiBean = SpiBeanApi.jsonToSpiBean(json);
38
+ if (SpiBeans.findIndex((c: SpiBean) => c.name === spiBean.name) === -1) {
39
+ SpiBeans.push(spiBean);
40
+ }
41
+ };
42
+
43
+ static getSpiBeans = (): SpiBean[] => {
44
+ const comps: SpiBean[] = [];
45
+ comps.push(...SpiBeans);
46
+ return comps;
47
+ };
48
+
49
+ static findByName = (name: string): SpiBean | undefined => {
50
+ return SpiBeanApi.getSpiBeans().find((c: SpiBean) => c.name === name);
51
+ };
52
+
53
+ static findByInterfaceType = (interfaceType: string): SpiBean[] => {
54
+ return SpiBeanApi.getSpiBeans().filter((c: SpiBean) => c.interfaceType === interfaceType);
55
+ };
56
+
57
+ // Beans without properties or without required properties
58
+ static findByInterfaceTypeSimple = (interfaceType: string): SpiBean[] => {
59
+ return SpiBeanApi.getSpiBeans().filter((c: SpiBean) => {
60
+ if (c.interfaceType === interfaceType) {
61
+ const props = c.properties;
62
+ if (props === undefined) {
63
+ return true;
64
+ } else {
65
+ return Object.getOwnPropertyNames(props).filter((name: string) => props[name].required).length == 0;
66
+ }
67
+ }
68
+ return false;
69
+ });
70
+ };
71
+
72
+ static findStepSpiBean = (step?: CamelElement): SpiBean | undefined => {
73
+ return SpiBeanApi.findByName((step as any)?.uri)
74
+ };
75
+
76
+ static getSpiBeanProperties = (spiBeanName: string): SpiBeanProperty[] => {
77
+ const spiBean: SpiBean | undefined = SpiBeanApi.findByName(spiBeanName);
78
+ const properties: SpiBeanProperty[] = [];
79
+ if (spiBean !== undefined && spiBean.properties) {
80
+ for (const [key, value] of Object.entries(spiBean.properties) as [string, any][]) {
81
+ const prop = new SpiBeanProperty();
82
+ prop.name = key;
83
+ prop.index = value.index;
84
+ prop.description = value.description;
85
+ prop.type = value.type;
86
+ prop.displayName = value.displayName;
87
+ prop.javaType = value.javaType;
88
+ prop.type = value.type;
89
+ prop.deprecated = value.deprecated;
90
+ prop.secret = value.secret;
91
+ prop.autowired = value.autowired;
92
+ prop.kind = value.kind;
93
+ prop.required = value.required;
94
+ if (value.defaultValue) {
95
+ prop.defaultValue = value.defaultValue;
96
+ }
97
+ if (!value.deprecated) {
98
+ properties.push(prop);
99
+ }
100
+ }
101
+ }
102
+ return Array.from(new Map(properties.map(item => [item.name, item])).values());
103
+ };
104
+ }
@@ -0,0 +1,58 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one or more
3
+ * contributor license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright ownership.
5
+ * The ASF licenses this file to You under the Apache License, Version 2.0
6
+ * (the "License"); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+
18
+ const Templates: Map<string, string> = new Map<string, string>();
19
+ const JavaCode: Map<string, string> = new Map<string, string>();
20
+
21
+ export class TemplateApi {
22
+ private constructor() {}
23
+
24
+ static saveTemplates = (templates: Map<string, string>, clean: boolean = false): void => {
25
+ if (clean) Templates.clear();
26
+ templates.forEach((value, key) => Templates.set(key, value));
27
+ };
28
+
29
+ static saveTemplate = (name: string, code: string): void => {
30
+ Templates.set(name, code);
31
+ };
32
+
33
+ static getTemplate = (name: string): string | undefined => {
34
+ return Templates.get(name);
35
+ };
36
+
37
+ static generateCode = (name: string, beanName: string): string | undefined => {
38
+ let template: string | undefined = TemplateApi.getTemplate(name);
39
+ if (template) {
40
+ return template.replaceAll('${NAME}', beanName);
41
+ } else {
42
+ throw new Error('Template not found');
43
+ }
44
+ };
45
+
46
+ static saveJavaCodes = (javaCode: Map<string, string>, clean: boolean = false): void => {
47
+ if (clean) JavaCode.clear();
48
+ javaCode.forEach((value, key) => JavaCode.set(key, value));
49
+ };
50
+
51
+ static saveJavaCode = (name: string, code: string): void => {
52
+ JavaCode.set(name, code);
53
+ };
54
+
55
+ static getJavaCode = (name: string): string | undefined => {
56
+ return JavaCode.get(name);
57
+ };
58
+ }
@@ -0,0 +1,392 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one or more
3
+ * contributor license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright ownership.
5
+ * The ASF licenses this file to You under the Apache License, Version 2.0
6
+ * (the "License"); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an "AS IS" BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import {
18
+ DeleteDefinition,
19
+ FromDefinition,
20
+ GetDefinition,
21
+ HeadDefinition,
22
+ PatchDefinition,
23
+ PostDefinition,
24
+ PutDefinition,
25
+ RestDefinition, RouteConfigurationDefinition, RouteDefinition, SagaDefinition,
26
+ } from '../model/CamelDefinition';
27
+ import {
28
+ CamelElement,
29
+ Integration,
30
+ } from '../model/IntegrationDefinition';
31
+ import {
32
+ TopologyIncomingNode,
33
+ TopologyOutgoingNode,
34
+ TopologyRestNode, TopologyRouteConfigurationNode,
35
+ TopologyRouteNode,
36
+ } from '../model/TopologyDefinition';
37
+ import { ComponentApi, INTERNAL_COMPONENTS } from './ComponentApi';
38
+ import { CamelDefinitionApiExt } from './CamelDefinitionApiExt';
39
+ import { CamelDisplayUtil } from './CamelDisplayUtil';
40
+ import { CamelUtil } from './CamelUtil';
41
+
42
+ const outgoingDefinitions: string[] = ['ToDefinition', 'KameletDefinition', 'ToDynamicDefinition', 'PollEnrichDefinition', 'EnrichDefinition', 'WireTapDefinition', 'SagaDefinition', 'PollDefinition'];
43
+
44
+ export class ChildElement {
45
+ constructor(public name: string = '', public className: string = '', public multiple: boolean = false) {
46
+ }
47
+ }
48
+
49
+ export class TopologyUtils {
50
+ private constructor() {
51
+ }
52
+
53
+ static getOutgoingDefinitions = (): string[] => {
54
+ return outgoingDefinitions;
55
+ };
56
+
57
+ static isElementInternalComponent = (element: CamelElement): boolean => {
58
+ const uri = (element as any).uri;
59
+ const component = ComponentApi.findByName(uri);
60
+ if (INTERNAL_COMPONENTS.includes(uri?.split(':')?.[0])) return true;
61
+ return component !== undefined && component.component.remote !== true;
62
+ };
63
+
64
+ static getConnectorType = (element: CamelElement): 'component' | 'kamelet' => {
65
+ return CamelUtil.isKameletComponent(element) ? 'kamelet' : 'component';
66
+ };
67
+
68
+ static cutKameletUriSuffix = (uri: string): string => {
69
+ if (uri.endsWith('-sink')) {
70
+ return uri.substring(0, uri.length - 5);
71
+ } else if (uri.endsWith('-source')) {
72
+ return uri.substring(0, uri.length - 7);
73
+ } else if (uri.endsWith('-action')) {
74
+ return uri.substring(0, uri.length - 7);
75
+ } else {
76
+ return uri;
77
+ }
78
+ };
79
+
80
+ static getUniqueUri = (element: CamelElement): string => {
81
+ const uri: string = (element as any).uri || '';
82
+ let result = uri.startsWith('kamelet') ? TopologyUtils.cutKameletUriSuffix(uri).concat(':') : uri.concat(':');
83
+ const className = element.dslName;
84
+ if (className === 'FromDefinition' || className === 'ToDefinition') {
85
+ if (!CamelUtil.isKameletComponent(element)) {
86
+ const requiredProperties = CamelUtil.getComponentProperties(element).filter(p => p.required);
87
+ for (const property of requiredProperties) {
88
+ const value = CamelDefinitionApiExt.getParametersValue(element, property.name, property.kind === 'path');
89
+ if (value !== undefined && property.type === 'string' && value.trim().length > 0) {
90
+ result = result + property.name + '=' + value + '&';
91
+ }
92
+ }
93
+ } else {
94
+ const requiredProperties = CamelUtil.getKameletProperties(element, true);
95
+ for (const property of requiredProperties) {
96
+ const value = CamelDefinitionApiExt.getParametersValue(element, property.id);
97
+ if (value !== undefined && property.type === 'string' && value.toString().trim().length > 0) {
98
+ result = result + property.id + '=' + value + '&';
99
+ }
100
+ }
101
+ }
102
+ }
103
+ return result.endsWith('&') ? result.substring(0, result.length - 1) : result;
104
+ };
105
+
106
+ static hasDirectUri = (element: CamelElement): boolean => {
107
+ return this.hasUriStartWith(element, 'direct');
108
+ };
109
+
110
+ static hasSedaUri = (element: CamelElement): boolean => {
111
+ return this.hasUriStartWith(element, 'seda');
112
+ };
113
+
114
+ static hasUriStartWith = (element: CamelElement, text: string): boolean => {
115
+ if ((element as any).uri && typeof (element as any).uri === 'string') {
116
+ return (element as any).uri.startsWith(text);
117
+ } else if (element.dslName === 'SagaDefinition') {
118
+ const completion = (element as SagaDefinition).completion || '';
119
+ const compensation = (element as SagaDefinition).compensation || '';
120
+ return completion.startsWith(text) || compensation.startsWith(text);
121
+ } else {
122
+ return false;
123
+ }
124
+ };
125
+
126
+ static findTopologyRestNodes = (integration: Integration[]): TopologyRestNode[] => {
127
+ const result: TopologyRestNode[] = [];
128
+ integration.forEach(i => {
129
+ try {
130
+ const filename = i.metadata.name;
131
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RestDefinition');
132
+ routes?.forEach((rest: RestDefinition) => {
133
+ const uris: string[] = [];
134
+ rest?.get?.forEach((d: GetDefinition) => {
135
+ if (d.to) uris.push(d.to);
136
+ });
137
+ rest?.post?.forEach((d: PostDefinition) => {
138
+ if (d.to) uris.push(d.to);
139
+ });
140
+ rest?.put?.forEach((d: PutDefinition) => {
141
+ if (d.to) uris.push(d.to);
142
+ });
143
+ rest?.delete?.forEach((d: DeleteDefinition) => {
144
+ if (d.to) uris.push(d.to);
145
+ });
146
+ rest?.patch?.forEach((d: PatchDefinition) => {
147
+ if (d.to) uris.push(d.to);
148
+ });
149
+ rest?.head?.forEach((d: HeadDefinition) => {
150
+ if (d.to) uris.push(d.to);
151
+ });
152
+ const title = '' + (rest.description ? rest.description : rest.id);
153
+ result.push(new TopologyRestNode(rest.path || '', '' + rest.id, uris, title, filename, rest));
154
+ });
155
+ } catch (e) {
156
+ console.error(e);
157
+ }
158
+ });
159
+ return result;
160
+ };
161
+
162
+ static findTopologyIncomingNodes = (integration: Integration[]): TopologyIncomingNode[] => {
163
+ const result: TopologyIncomingNode[] = [];
164
+ integration.forEach(i => {
165
+ try {
166
+ const filename = i.metadata.name;
167
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RouteDefinition');
168
+ const routeElements = routes?.map(r => {
169
+ const id = 'incoming-' + r.id;
170
+ const title = CamelDisplayUtil.getStepDescription(r.from);
171
+ const type = TopologyUtils.isElementInternalComponent(r.from) ? 'internal' : 'external';
172
+ const connectorType = TopologyUtils.getConnectorType(r.from);
173
+ const uniqueUri = TopologyUtils.getUniqueUri(r.from);
174
+ return new TopologyIncomingNode(id, type, connectorType, r.id, title, filename, r.from, uniqueUri);
175
+ }) || [];
176
+ result.push(...routeElements);
177
+ } catch (e) {
178
+ console.error(e);
179
+ }
180
+ });
181
+ return result;
182
+ };
183
+
184
+ static findTopologyRouteNodes = (integration: Integration[]): TopologyRouteNode[] => {
185
+ const result: TopologyRouteNode[] = [];
186
+ integration.forEach(i => {
187
+ try {
188
+ const filename = i.metadata.name;
189
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RouteDefinition');
190
+ const routeElements = routes?.map(r => {
191
+ const id = 'route-' + r.id;
192
+ const title = '' + (r.description ? r.description : r.id);
193
+ return new TopologyRouteNode(id, r.id, title, filename, r.from, r);
194
+ }) || [];
195
+ result.push(...routeElements);
196
+ } catch (e) {
197
+ console.error(e);
198
+ }
199
+ });
200
+ return result;
201
+ };
202
+
203
+ static findTopologyRouteConfigurationNodes = (integration: Integration[]): TopologyRouteConfigurationNode[] => {
204
+ const result: TopologyRouteConfigurationNode[] = [];
205
+ integration.forEach(i => {
206
+ try {
207
+ const filename = i.metadata.name;
208
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RouteConfigurationDefinition');
209
+ const routeElements = routes?.map(r => {
210
+ const id = 'route-' + r.id;
211
+ const title = '' + (r.description ? r.description : r.id);
212
+ return new TopologyRouteConfigurationNode(id, r.id, title, filename, r);
213
+ }) || [];
214
+ result.push(...routeElements);
215
+ } catch (e) {
216
+ console.error(e);
217
+ }
218
+ });
219
+ return result;
220
+ };
221
+
222
+ static findTopologyRouteOutgoingNodes = (integrations: Integration[]): TopologyOutgoingNode[] => {
223
+ const result: TopologyOutgoingNode[] = [];
224
+ integrations.forEach(i => {
225
+ try {
226
+ const filename = i.metadata.name;
227
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RouteDefinition');
228
+ routes?.forEach(route => {
229
+ const from: FromDefinition = route.from;
230
+ const elements = TopologyUtils.findOutgoingInStep(from, []);
231
+ elements.forEach((e: any) => {
232
+ const id = 'outgoing-' + route.id + '-' + e.id;
233
+ const title = CamelDisplayUtil.getStepDescription(e);
234
+ const type = TopologyUtils.isElementInternalComponent(e) ? 'internal' : 'external';
235
+ const connectorType = TopologyUtils.getConnectorType(e);
236
+ const uniqueUri = TopologyUtils.getUniqueUri(e);
237
+ if (
238
+ connectorType !== 'kamelet' ||
239
+ CamelUtil.getKamelet(e)?.metadata.labels['camel.apache.org/kamelet.type'] !== 'action'
240
+ ) {
241
+ result.push(new TopologyOutgoingNode(id, type, connectorType, route.id, title, filename, e, uniqueUri));
242
+ }
243
+ });
244
+ result.push(...TopologyUtils.findDeadLetterChannelNodes(route, filename));
245
+ });
246
+ } catch (e) {
247
+ console.error(e);
248
+ }
249
+ });
250
+ return result;
251
+ };
252
+
253
+ static findDeadLetterChannelNodes(route: RouteDefinition, filename: string): TopologyOutgoingNode[] {
254
+ const result: TopologyOutgoingNode[] = [];
255
+ try {
256
+ const deadLetterChannel = route.errorHandler?.deadLetterChannel;
257
+ const deadLetterUri = deadLetterChannel?.deadLetterUri;
258
+ if (deadLetterChannel !== undefined && deadLetterUri !== undefined) {
259
+ const parts = deadLetterUri.split(':');
260
+ if (parts.length > 1 && INTERNAL_COMPONENTS.includes(parts[0])) {
261
+ const id = 'outgoing-' + route.id + '-' + deadLetterChannel?.id;
262
+ const title = CamelDisplayUtil.getStepDescription(deadLetterChannel);
263
+ const type = 'internal';
264
+ const connectorType = 'component';
265
+ result.push(new TopologyOutgoingNode(id, type, connectorType, route.id || '', title, filename, deadLetterChannel, deadLetterUri));
266
+ }
267
+ }
268
+ } catch (e) {
269
+ console.error(e);
270
+ }
271
+ return result;
272
+ }
273
+
274
+ static findTopologyRouteConfigurationOutgoingNodes = (integrations: Integration[]): TopologyOutgoingNode[] => {
275
+ const result: TopologyOutgoingNode[] = [];
276
+ integrations.forEach(i => {
277
+ try {
278
+ const filename = i.metadata.name;
279
+ const rcs = i.spec.flows?.filter(flow => flow.dslName === 'RouteConfigurationDefinition');
280
+ rcs?.forEach((rc: RouteConfigurationDefinition) => {
281
+ const children: CamelElement[] = [];
282
+ children.push(...rc.intercept || []);
283
+ children.push(...rc.interceptFrom || []);
284
+ children.push(...rc.interceptSendToEndpoint || []);
285
+ children.push(...rc.onCompletion || []);
286
+ children.push(...rc.onException || []);
287
+ children.forEach(child => {
288
+ const elements = TopologyUtils.findOutgoingInStep(child, []);
289
+ elements.forEach((e: any) => {
290
+ const id = 'outgoing-' + rc.id + '-' + e.id;
291
+ const title = CamelDisplayUtil.getStepDescription(e);
292
+ const type = TopologyUtils.isElementInternalComponent(e) ? 'internal' : 'external';
293
+ const connectorType = TopologyUtils.getConnectorType(e);
294
+ const uniqueUri = TopologyUtils.getUniqueUri(e);
295
+ result.push(new TopologyOutgoingNode(id, type, connectorType, rc.id || 'undefined', title, filename, e, uniqueUri));
296
+ });
297
+ });
298
+ if (rc.errorHandler?.deadLetterChannel) {
299
+ const e = rc.errorHandler?.deadLetterChannel;
300
+ const id = 'outgoing-' + rc.id + '-' + e.id;
301
+ const title = CamelDisplayUtil.getStepDescription(e);
302
+ const comp = e?.deadLetterUri?.split(':')?.[0];
303
+ const type = INTERNAL_COMPONENTS.includes(comp) ? 'internal' : 'external';
304
+ const connectorType = 'component';
305
+ const uniqueUri = e?.deadLetterUri;
306
+ result.push(new TopologyOutgoingNode(id, type, connectorType, rc.id || 'undefined', title, filename, e, uniqueUri));
307
+ }
308
+ });
309
+ } catch (e) {
310
+ console.error(e);
311
+ }
312
+ });
313
+ return result;
314
+ };
315
+
316
+ static findOutgoingInStep = (step: CamelElement, result: CamelElement[]): CamelElement[] => {
317
+ if (step !== undefined) {
318
+ const el = (step as any);
319
+ try {
320
+ if (outgoingDefinitions.includes(el.dslName)) {
321
+ result.push(step);
322
+ } else {
323
+ const childElements = CamelDefinitionApiExt.getElementChildrenDefinition(el.dslName);
324
+ childElements.forEach(child => {
325
+ if (child.multiple) {
326
+ const sub = (el[child.name] as CamelElement[]);
327
+ TopologyUtils.findOutgoingInSteps(sub, result);
328
+ } else {
329
+ const sub = (el[child.name] as CamelElement);
330
+ TopologyUtils.findOutgoingInStep(sub, result);
331
+ }
332
+ });
333
+ }
334
+ } catch (e) {
335
+ console.error(e);
336
+ }
337
+ }
338
+ return result;
339
+ };
340
+
341
+ static findOutgoingInSteps = (steps: CamelElement[], result: CamelElement[]): CamelElement[] => {
342
+ if (steps !== undefined && steps.length > 0) {
343
+ steps.forEach(step => TopologyUtils.findOutgoingInStep(step, result));
344
+ }
345
+ return result;
346
+ };
347
+
348
+ static getNodeIdByUriAndName(tins: TopologyIncomingNode[], uri: string, name: string): string | undefined {
349
+ if (uri && name) {
350
+ const node = tins
351
+ .filter(r => r.from.uri === uri
352
+ && (r?.from?.parameters?.name === name || r?.from?.parameters?.address === name),
353
+ ).at(0);
354
+ if (node) {
355
+ return node.id;
356
+ }
357
+ }
358
+ }
359
+
360
+ static getNodeIdByUri(tins: TopologyIncomingNode[], uri: string): string | undefined {
361
+ const parts = uri.split(':');
362
+ if (parts.length > 1) {
363
+ return TopologyUtils.getNodeIdByUriAndName(tins, parts[0], parts[1]);
364
+ }
365
+ }
366
+
367
+ static getRouteIdByUriAndName(tins: TopologyIncomingNode[], uri: string, name: string): string | undefined {
368
+ if (uri && name) {
369
+ const node = tins
370
+ .filter(r => r.from.uri === uri
371
+ && (r?.from?.parameters?.name === name || r?.from?.parameters?.address === name),
372
+ ).at(0);
373
+ if (node) {
374
+ return 'route-' + node.routeId;
375
+ }
376
+ }
377
+ }
378
+
379
+ static getNodeIdByUniqueUri(tins: TopologyIncomingNode[], uniqueUri: string): string [] {
380
+ const result: string[] = [];
381
+ tins.filter(r => r.uniqueUri === uniqueUri)
382
+ ?.forEach(node => result.push(node.id));
383
+ return result;
384
+ }
385
+
386
+ static getRouteIdByUri(tins: TopologyIncomingNode[], uri: string): string | undefined {
387
+ const parts = uri.split(':');
388
+ if (parts.length > 1) {
389
+ return TopologyUtils.getRouteIdByUriAndName(tins, parts[0], parts[1]);
390
+ }
391
+ }
392
+ }
@@ -0,0 +1,104 @@
1
+ /*
2
+ * Licensed to the Apache Software Foundation (ASF) under one or more
3
+ * contributor license agreements. See the NOTICE file distributed with
4
+ * this work for additional information regarding copyright ownership.
5
+ * The ASF licenses this file to You under the Apache License, Version 2.0
6
+ * (the 'License'); you may not use this file except in compliance with
7
+ * the License. You may obtain a copy of the License at
8
+ *
9
+ * http://www.apache.org/licenses/LICENSE-2.0
10
+ *
11
+ * Unless required by applicable law or agreed to in writing, software
12
+ * distributed under the License is distributed on an 'AS IS' BASIS,
13
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ * See the License for the specific language governing permissions and
15
+ * limitations under the License.
16
+ */
17
+ import {
18
+ CamelElement, Integration,
19
+ IntegrationFile,
20
+ } from '../model/IntegrationDefinition';
21
+ import { CamelDefinitionYaml } from './CamelDefinitionYaml';
22
+ import { FromDefinition} from '../model/CamelDefinition';
23
+ import { CamelDefinitionApiExt } from './CamelDefinitionApiExt';
24
+
25
+ const sendReceiveDSL: string[] =
26
+ ['ToDefinition', 'FromDefinition', 'ToDynamicDefinition', 'PollEnrichDefinition',
27
+ 'EnrichDefinition', 'WireTapDefinition', 'UnmarshalDefinition', 'MarshalDefinition'];
28
+
29
+ export const GLOBAL = 'global:';
30
+ export const ROUTE = 'route:';
31
+
32
+
33
+ export class VariableUtil {
34
+ private constructor() {
35
+ }
36
+
37
+ static findVariables = (files: IntegrationFile[]): string[] => {
38
+ const integrations = files.filter(file => file.name?.endsWith(".camel.yaml"))
39
+ .map(file => CamelDefinitionYaml.yamlToIntegration(file.name, file.code));
40
+ return VariableUtil.findVariablesInIntegrations(integrations);
41
+ };
42
+
43
+ static findVariablesInIntegrations = (integrations: Integration[]): string[] => {
44
+ const result: string[] = []
45
+ integrations.forEach(i => {
46
+ const filename = i.metadata.name;
47
+ const routes = i.spec.flows?.filter(flow => flow.dslName === 'RouteDefinition');
48
+ routes?.forEach(route => {
49
+ const from: FromDefinition = route.from;
50
+ VariableUtil.findVariablesInStep(from, result);
51
+ })
52
+
53
+ })
54
+ return VariableUtil.sortVariables(result);
55
+ };
56
+
57
+ static sortVariables = (variables: string[]): string [] => {
58
+ const global = [...new Set(variables.filter(v => v && v.startsWith(GLOBAL)))].sort();
59
+ const route = [...new Set(variables.filter(v => v && v.startsWith(ROUTE)))].sort();
60
+ const exchange = [...new Set(variables.filter(v => v && !v.startsWith(ROUTE) && !v.startsWith(GLOBAL)))].sort();
61
+ return global.concat(route, exchange);
62
+ }
63
+
64
+ static findVariablesInStep = (step: CamelElement, result: string[]) => {
65
+ if (step !== undefined) {
66
+ const el = (step as any);
67
+ if (sendReceiveDSL.includes(el.dslName)) {
68
+ VariableUtil.findVariablesInProps(el, 'variableSend', result);
69
+ VariableUtil.findVariablesInProps(el, 'variableReceive', result);
70
+ } else if (el.dslName === 'ConvertVariableDefinition') {
71
+ VariableUtil.findVariablesInProps(el, 'name', result);
72
+ VariableUtil.findVariablesInProps(el, 'toName', result);
73
+ } else if (el.dslName === 'SetVariableDefinition') {
74
+ VariableUtil.findVariablesInProps(el, 'name', result);
75
+ } else if (el.dslName === 'RemoveVariableDefinition') {
76
+ VariableUtil.findVariablesInProps(el, 'name', result);
77
+ }
78
+ // check children elements
79
+ const childElements = CamelDefinitionApiExt.getElementChildrenDefinition(el.dslName);
80
+ childElements.forEach(child => {
81
+ if (child.multiple) {
82
+ const sub = (el[child.name] as CamelElement[]);
83
+ VariableUtil.findVariablesInSteps(sub, result);
84
+ } else {
85
+ const sub = (el[child.name] as CamelElement);
86
+ VariableUtil.findVariablesInStep(sub, result);
87
+ }
88
+ })
89
+ }
90
+ }
91
+
92
+ static findVariablesInSteps = (steps: CamelElement[], result: string[]) => {
93
+ if (steps !== undefined && steps.length > 0) {
94
+ steps.forEach(step => VariableUtil.findVariablesInStep(step, result))
95
+ }
96
+ }
97
+
98
+ static findVariablesInProps = (step: CamelElement, propertyName: string, result: string[]) => {
99
+ const el = (step as any);
100
+ if (el.hasOwnProperty(propertyName)) {
101
+ result.push(el[propertyName])
102
+ }
103
+ }
104
+ }