serverless-spy 0.0.35 → 0.0.37
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/.jsii +236 -9
- package/API.md +161 -0
- package/cli/cli.ts +145 -75
- package/cli/icons/Arch_AWS-Lambda_16.svg +18 -0
- package/cli/icons/Arch_Amazon-DynamoDB_16.svg +18 -0
- package/cli/icons/Arch_Amazon-EventBridge_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Notification-Service_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Queue-Service_16.svg +18 -0
- package/cli/icons/Arch_Amazon-Simple-Storage-Service_16.svg +18 -0
- package/cli/index.html +84 -25
- package/cli/node_modules/commander/LICENSE +22 -0
- package/cli/node_modules/commander/Readme.md +1114 -0
- package/cli/node_modules/commander/esm.mjs +16 -0
- package/cli/node_modules/commander/index.js +27 -0
- package/cli/node_modules/commander/lib/argument.js +147 -0
- package/cli/node_modules/commander/lib/command.js +2161 -0
- package/cli/node_modules/commander/lib/error.js +45 -0
- package/cli/node_modules/commander/lib/help.js +406 -0
- package/cli/node_modules/commander/lib/option.js +324 -0
- package/cli/node_modules/commander/lib/suggestSimilar.js +100 -0
- package/cli/node_modules/commander/package-support.json +16 -0
- package/cli/node_modules/commander/package.json +80 -0
- package/cli/node_modules/commander/typings/index.d.ts +879 -0
- package/cli/package.json +23 -0
- package/cli/sampleData.ts +518 -0
- package/cli/style.css +66 -42
- package/cli/webServerlessSpy.ts +461 -0
- package/common/SpyEventSender.ts +291 -0
- package/common/getWebSocketUrl.ts +21 -4
- package/common/spyEvents/EventBridgeBaseSpyEvent.ts +13 -0
- package/common/spyEvents/EventBridgeRuleSpyEvent.ts +2 -7
- package/common/spyEvents/EventBridgeSpyEvent.ts +2 -7
- package/common/spyEvents/FunctionBaseSpyEvent.ts +7 -0
- package/common/spyEvents/FunctionConsole.ts +5 -0
- package/common/spyEvents/FunctionConsoleSpyEvent.ts +5 -8
- package/common/spyEvents/FunctionResponseSpyEvent.ts +2 -5
- package/common/spyEvents/SnsSpyEventBase.ts +11 -0
- package/common/spyEvents/SnsSubscriptionSpyEvent.ts +3 -9
- package/common/spyEvents/SnsTopicSpyEvent.ts +3 -9
- package/dist/releasetag.txt +1 -1
- package/extension/interceptor.ts +107 -27
- package/functions/sendMessage.ts +4 -2
- package/functions/sqsSubscriptionAndDropAllMessages.ts +3 -0
- package/lib/cli/cli.js +124 -65
- package/lib/cli/cli.mjs +125 -66
- package/lib/cli/sampleData.d.ts +892 -0
- package/lib/cli/sampleData.js +481 -0
- package/lib/cli/sampleData.mjs +478 -0
- package/lib/cli/webServerlessSpy.js +5516 -0
- package/lib/cli/webServerlessSpy.js.map +7 -0
- package/lib/common/SpyEventSender.d.ts +17 -0
- package/lib/common/SpyEventSender.js +227 -0
- package/lib/common/SpyEventSender.mjs +223 -0
- package/lib/common/getWebSocketUrl.d.ts +1 -1
- package/lib/common/getWebSocketUrl.js +19 -7
- package/lib/common/getWebSocketUrl.mjs +17 -5
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.d.ts +9 -0
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.js +3 -0
- package/lib/common/spyEvents/EventBridgeBaseSpyEvent.mjs +2 -0
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.d.ts +2 -7
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.js +1 -1
- package/lib/common/spyEvents/EventBridgeRuleSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/EventBridgeSpyEvent.d.ts +2 -7
- package/lib/common/spyEvents/EventBridgeSpyEvent.js +1 -1
- package/lib/common/spyEvents/EventBridgeSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/FunctionBaseSpyEvent.d.ts +6 -0
- package/lib/common/spyEvents/FunctionBaseSpyEvent.js +3 -0
- package/lib/common/spyEvents/FunctionBaseSpyEvent.mjs +2 -0
- package/lib/common/spyEvents/FunctionConsole.d.ts +5 -0
- package/lib/common/spyEvents/FunctionConsole.js +3 -0
- package/lib/common/spyEvents/FunctionConsole.mjs +2 -0
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.d.ts +4 -8
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.js +1 -1
- package/lib/common/spyEvents/FunctionConsoleSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/FunctionResponseSpyEvent.d.ts +2 -5
- package/lib/common/spyEvents/FunctionResponseSpyEvent.js +1 -1
- package/lib/common/spyEvents/FunctionResponseSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/SnsSpyEventBase.d.ts +10 -0
- package/lib/common/spyEvents/SnsSpyEventBase.js +3 -0
- package/lib/common/spyEvents/SnsSpyEventBase.mjs +2 -0
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.d.ts +2 -9
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.js +1 -1
- package/lib/common/spyEvents/SnsSubscriptionSpyEvent.mjs +1 -1
- package/lib/common/spyEvents/SnsTopicSpyEvent.d.ts +2 -9
- package/lib/common/spyEvents/SnsTopicSpyEvent.js +1 -1
- package/lib/common/spyEvents/SnsTopicSpyEvent.mjs +1 -1
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js +10793 -23825
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js.map +4 -4
- package/lib/listener/ServerlessSpyListenerParams.d.ts +1 -0
- package/lib/listener/ServerlessSpyListenerParams.js +1 -1
- package/lib/listener/ServerlessSpyListenerParams.mjs +1 -1
- package/lib/listener/SpyHandlers.ts.d.ts +30 -2
- package/lib/listener/SpyHandlers.ts.js +1 -1
- package/lib/listener/SpyHandlers.ts.mjs +1 -1
- package/lib/listener/WsListener.d.ts +4 -21
- package/lib/listener/WsListener.js +21 -13
- package/lib/listener/WsListener.mjs +22 -14
- package/lib/src/ServerlessSpy.d.ts +44 -14
- package/lib/src/ServerlessSpy.js +228 -86
- package/lib/src/ServerlessSpy.mjs +227 -85
- package/lib/src/common/envVariableNames.d.ts +6 -2
- package/lib/src/common/envVariableNames.js +6 -2
- package/lib/src/common/envVariableNames.mjs +6 -2
- package/listener/ServerlessSpyListenerParams.ts +1 -0
- package/listener/SpyHandlers.ts.ts +70 -9
- package/listener/WsListener.ts +39 -24
- package/package.json +5 -3
- package/cli/serverlessSpy.js +0 -73
- package/cli/ws.ts +0 -79
- package/common/publishSpyEvent.ts +0 -269
- package/lib/cli/ws.d.ts +0 -1
- package/lib/cli/ws.js +0 -68
- package/lib/cli/ws.mjs +0 -66
- package/lib/common/publishSpyEvent.d.ts +0 -4
- package/lib/common/publishSpyEvent.js +0 -211
- package/lib/common/publishSpyEvent.mjs +0 -205
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
import { Modal, Tooltip } from 'bootstrap';
|
|
2
|
+
import formatHighlight from 'json-format-highlight';
|
|
3
|
+
import { EventBridgeBaseSpyEvent } from '../common/spyEvents/EventBridgeBaseSpyEvent';
|
|
4
|
+
import { FunctionBaseSpyEvent } from '../common/spyEvents/FunctionBaseSpyEvent';
|
|
5
|
+
import { SnsSpyEventBase } from '../common/spyEvents/SnsSpyEventBase';
|
|
6
|
+
import { SpyEvent } from '../common/spyEvents/SpyEvent';
|
|
7
|
+
import { SpyMessage } from '../common/spyEvents/SpyMessage';
|
|
8
|
+
//import { sampleData } from './sampleData'; // Leave this for testing
|
|
9
|
+
|
|
10
|
+
//needed because of strange bug in Bootstrap Tooltip
|
|
11
|
+
(window as any).process = { env: {} };
|
|
12
|
+
|
|
13
|
+
document.addEventListener('DOMContentLoaded', function () {
|
|
14
|
+
run();
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function run() {
|
|
18
|
+
// ************* variables *************
|
|
19
|
+
const spyMessages: (SpyMessageExt | SpyMessageGroup)[] = [];
|
|
20
|
+
const snsEventsByMessageId: Record<string, SpyMessageExt<SnsSpyEventBase>[]> =
|
|
21
|
+
{};
|
|
22
|
+
const functionEventsByRequestId: Record<
|
|
23
|
+
string,
|
|
24
|
+
SpyMessageExt<FunctionBaseSpyEvent>[]
|
|
25
|
+
> = {};
|
|
26
|
+
const eventBridgeById: Record<
|
|
27
|
+
string,
|
|
28
|
+
SpyMessageExt<EventBridgeBaseSpyEvent>[]
|
|
29
|
+
> = {};
|
|
30
|
+
let uiNeedsRefresh = false;
|
|
31
|
+
let stackList: string[] | undefined;
|
|
32
|
+
const selectedStackLocalStorageKey = 'selectedStack';
|
|
33
|
+
let ws: WebSocket;
|
|
34
|
+
|
|
35
|
+
// ************* HTML elements *************
|
|
36
|
+
const tableBodyElement = document.getElementById('tableBody')!;
|
|
37
|
+
const modalTimeElement = document.getElementById('time')!;
|
|
38
|
+
const modalServiceKeyElement = document.getElementById('serviceKey')!;
|
|
39
|
+
const modalDataElement = document.getElementById('data')!;
|
|
40
|
+
const errorContentElement = document.getElementById('errorContent')!;
|
|
41
|
+
const stackListContainerElement =
|
|
42
|
+
document.getElementById('stackListContainer')!;
|
|
43
|
+
const stackListElement = document.getElementById(
|
|
44
|
+
'stackList'
|
|
45
|
+
) as HTMLSelectElement;
|
|
46
|
+
const serviceKeyFilterInputElement = document.getElementById(
|
|
47
|
+
'serviceKeyFilter'
|
|
48
|
+
) as HTMLInputElement;
|
|
49
|
+
const dataFilterInputElement = document.getElementById(
|
|
50
|
+
'dataFilter'
|
|
51
|
+
) as HTMLInputElement;
|
|
52
|
+
const detailsModal = new Modal('#detailsModal', {
|
|
53
|
+
backdrop: true,
|
|
54
|
+
keyboard: true,
|
|
55
|
+
});
|
|
56
|
+
const errorModal = new Modal('#errorModal', {
|
|
57
|
+
backdrop: true,
|
|
58
|
+
keyboard: true,
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
// ************* events *************
|
|
62
|
+
serviceKeyFilterInputElement.addEventListener('input', () => {
|
|
63
|
+
uiNeedsRefresh = true;
|
|
64
|
+
});
|
|
65
|
+
dataFilterInputElement.addEventListener('input', () => {
|
|
66
|
+
uiNeedsRefresh = true;
|
|
67
|
+
});
|
|
68
|
+
tableBodyElement.addEventListener('click', openDetails());
|
|
69
|
+
stackListElement.addEventListener('change', () => {
|
|
70
|
+
switchStack();
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
void (async () => {
|
|
74
|
+
await fillStacks();
|
|
75
|
+
await connectToWebSocket();
|
|
76
|
+
})();
|
|
77
|
+
window.requestAnimationFrame(render);
|
|
78
|
+
setupTooltip();
|
|
79
|
+
|
|
80
|
+
// Do not remove!
|
|
81
|
+
// sample data for testing purposes
|
|
82
|
+
// for (const sm of sampleData) {
|
|
83
|
+
// addSpyMessage(sm as any);
|
|
84
|
+
// }
|
|
85
|
+
|
|
86
|
+
function switchStack() {
|
|
87
|
+
spyMessages.length = 0;
|
|
88
|
+
uiNeedsRefresh = true;
|
|
89
|
+
ws.close();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function fillStacks() {
|
|
93
|
+
const response = await fetch('/stackList');
|
|
94
|
+
try {
|
|
95
|
+
stackList = await response.json();
|
|
96
|
+
} catch {
|
|
97
|
+
stackList = [];
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
const selectedStack = localStorage.getItem(selectedStackLocalStorageKey);
|
|
101
|
+
|
|
102
|
+
stackListElement.innerHTML =
|
|
103
|
+
stackList
|
|
104
|
+
?.map(
|
|
105
|
+
(s) =>
|
|
106
|
+
`<option value="${s}" ${
|
|
107
|
+
selectedStack === s ? 'selected' : ''
|
|
108
|
+
}>${s}</option>`
|
|
109
|
+
)
|
|
110
|
+
.join('') ?? '';
|
|
111
|
+
|
|
112
|
+
console.log(stackListContainerElement.style.display);
|
|
113
|
+
stackListContainerElement.style.display =
|
|
114
|
+
stackList && stackList.length > 1 ? '' : 'none';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
async function connectToWebSocket() {
|
|
118
|
+
try {
|
|
119
|
+
const stack = stackListElement.value;
|
|
120
|
+
const response = await fetch(`/wsUrl/${stack}`);
|
|
121
|
+
if (response.ok) {
|
|
122
|
+
const url = await response.text();
|
|
123
|
+
ws = new WebSocket(url);
|
|
124
|
+
|
|
125
|
+
ws.addEventListener('open', () => {
|
|
126
|
+
console.log(
|
|
127
|
+
`Connected ${new Date().toISOString()} to stack ${stack}`
|
|
128
|
+
);
|
|
129
|
+
});
|
|
130
|
+
ws.addEventListener('message', receiveSpyMessage());
|
|
131
|
+
ws.addEventListener('close', () => {
|
|
132
|
+
console.log(`Disconnected ${new Date().toISOString()}, reconnecting`);
|
|
133
|
+
void connectToWebSocket();
|
|
134
|
+
});
|
|
135
|
+
} else {
|
|
136
|
+
showError(await response.text());
|
|
137
|
+
}
|
|
138
|
+
} catch (err) {
|
|
139
|
+
showError(err.message);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function showError(messsage: string) {
|
|
144
|
+
errorContentElement.innerHTML = messsage;
|
|
145
|
+
errorModal.show();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function render() {
|
|
149
|
+
if (uiNeedsRefresh) {
|
|
150
|
+
tableBodyElement.innerHTML = spyMessages
|
|
151
|
+
.map((sm) => renderSpyMessage(sm))
|
|
152
|
+
.join('');
|
|
153
|
+
uiNeedsRefresh = false;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
window.requestAnimationFrame(render);
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
function receiveSpyMessage(): (
|
|
160
|
+
this: WebSocket,
|
|
161
|
+
ev: MessageEvent<any>
|
|
162
|
+
) => any {
|
|
163
|
+
return ({ data }) => {
|
|
164
|
+
//console.log(data);
|
|
165
|
+
let parsed;
|
|
166
|
+
try {
|
|
167
|
+
parsed = JSON.parse(data);
|
|
168
|
+
} catch (err) {
|
|
169
|
+
console.error('Can not parse ' + data);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
addSpyMessage(parsed);
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function openDetails(): (this: HTMLElement, ev: MouseEvent) => any {
|
|
177
|
+
return (e) => {
|
|
178
|
+
const row = (e.target as HTMLElement).closest('tr');
|
|
179
|
+
const dataElements = row?.getElementsByClassName('data');
|
|
180
|
+
const timeElements = row?.getElementsByClassName('time');
|
|
181
|
+
const serviceKeyElements = row?.getElementsByClassName('serviceKey');
|
|
182
|
+
|
|
183
|
+
if (
|
|
184
|
+
!dataElements ||
|
|
185
|
+
dataElements.length === 0 ||
|
|
186
|
+
!timeElements ||
|
|
187
|
+
timeElements.length === 0 ||
|
|
188
|
+
!serviceKeyElements ||
|
|
189
|
+
serviceKeyElements.length === 0
|
|
190
|
+
) {
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
modalTimeElement.innerHTML = timeElements[0].textContent || '';
|
|
195
|
+
modalServiceKeyElement.innerHTML =
|
|
196
|
+
serviceKeyElements[0].textContent || '';
|
|
197
|
+
modalDataElement.innerHTML = formatDataJson(
|
|
198
|
+
dataElements[0].textContent || ''
|
|
199
|
+
);
|
|
200
|
+
detailsModal.show();
|
|
201
|
+
};
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function formatDataJson(dataJson: string) {
|
|
205
|
+
return formatHighlight(JSON.stringify(JSON.parse(dataJson), null, 2), {
|
|
206
|
+
keyColor: 'black',
|
|
207
|
+
numberColor: 'blue',
|
|
208
|
+
stringColor: '#0B7500',
|
|
209
|
+
trueColor: '#00cc00',
|
|
210
|
+
falseColor: '#ff8080',
|
|
211
|
+
nullColor: 'cornflowerblue',
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function addSpyMessage(spyMessage: SpyMessageExt) {
|
|
216
|
+
const spyMessageExt = spyMessage as SpyMessageExt;
|
|
217
|
+
spyMessageExt.dataJsonLowerCase = JSON.stringify(
|
|
218
|
+
spyMessageExt.data
|
|
219
|
+
).toLocaleLowerCase();
|
|
220
|
+
spyMessageExt.serviceKeyLowerCase =
|
|
221
|
+
spyMessageExt.serviceKey.toLocaleLowerCase();
|
|
222
|
+
|
|
223
|
+
const service = getServiceNameFromServiceKey(spyMessageExt.serviceKey);
|
|
224
|
+
let spyMessageToAdd: SpyMessageExt | SpyMessageGroup | undefined =
|
|
225
|
+
spyMessageExt;
|
|
226
|
+
|
|
227
|
+
if (service === 'Function') {
|
|
228
|
+
const spyMessageFunction =
|
|
229
|
+
spyMessageExt as SpyMessageExt<FunctionBaseSpyEvent>;
|
|
230
|
+
const awsRequestId = spyMessageFunction.data.context.awsRequestId;
|
|
231
|
+
let functionEvents = functionEventsByRequestId[awsRequestId];
|
|
232
|
+
if (!functionEvents) {
|
|
233
|
+
functionEvents = [];
|
|
234
|
+
functionEventsByRequestId[awsRequestId] = functionEvents;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
const step = getFunctionStepFromServiceKey(spyMessageExt.serviceKey);
|
|
238
|
+
|
|
239
|
+
if (step === 'Request') {
|
|
240
|
+
spyMessageToAdd = <SpyMessageGroup>{
|
|
241
|
+
timestamp: spyMessageExt.timestamp,
|
|
242
|
+
serviceKey: spyMessageExt.serviceKey,
|
|
243
|
+
messages: functionEvents,
|
|
244
|
+
};
|
|
245
|
+
functionEvents.unshift(spyMessageFunction);
|
|
246
|
+
} else {
|
|
247
|
+
addSpyMessageToArraySorted(spyMessageFunction, functionEvents);
|
|
248
|
+
spyMessageToAdd = undefined;
|
|
249
|
+
}
|
|
250
|
+
} else if (service === 'SnsSubscription' || service === 'SnsTopic') {
|
|
251
|
+
const spyMessageSns = spyMessageExt as SpyMessageExt<SnsSpyEventBase>;
|
|
252
|
+
const messageId = spyMessageSns.data.messageId;
|
|
253
|
+
let snsEvents = snsEventsByMessageId[messageId];
|
|
254
|
+
if (!snsEvents) {
|
|
255
|
+
snsEvents = [];
|
|
256
|
+
snsEventsByMessageId[messageId] = snsEvents;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (service === 'SnsTopic') {
|
|
260
|
+
spyMessageToAdd = <SpyMessageGroup>{
|
|
261
|
+
timestamp: spyMessageExt.timestamp,
|
|
262
|
+
serviceKey: spyMessageExt.serviceKey,
|
|
263
|
+
messages: snsEvents,
|
|
264
|
+
};
|
|
265
|
+
snsEvents.unshift(spyMessageSns);
|
|
266
|
+
} else {
|
|
267
|
+
addSpyMessageToArraySorted(spyMessageSns, snsEvents);
|
|
268
|
+
spyMessageToAdd = undefined;
|
|
269
|
+
}
|
|
270
|
+
} else if (service === 'EventBridge' || service === 'EventBridgeRule') {
|
|
271
|
+
const spyMessageEventBridge =
|
|
272
|
+
spyMessageExt as SpyMessageExt<EventBridgeBaseSpyEvent>;
|
|
273
|
+
const eventBridgeId = spyMessageEventBridge.data.eventBridgeId;
|
|
274
|
+
let eventBridgeEvents = eventBridgeById[eventBridgeId];
|
|
275
|
+
if (!eventBridgeEvents) {
|
|
276
|
+
eventBridgeEvents = [];
|
|
277
|
+
eventBridgeById[eventBridgeId] = eventBridgeEvents;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
if (service === 'EventBridge') {
|
|
281
|
+
spyMessageToAdd = <SpyMessageGroup>{
|
|
282
|
+
timestamp: spyMessageExt.timestamp,
|
|
283
|
+
serviceKey: spyMessageExt.serviceKey,
|
|
284
|
+
messages: eventBridgeEvents,
|
|
285
|
+
};
|
|
286
|
+
eventBridgeEvents.unshift(spyMessageEventBridge);
|
|
287
|
+
} else {
|
|
288
|
+
addSpyMessageToArraySorted(spyMessageEventBridge, eventBridgeEvents);
|
|
289
|
+
spyMessageToAdd = undefined;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
if (spyMessageToAdd) {
|
|
294
|
+
//add in correct order
|
|
295
|
+
addSpyMessageToArraySorted(spyMessageToAdd, spyMessages);
|
|
296
|
+
uiNeedsRefresh = true;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
function matchFilter(
|
|
301
|
+
spyMessage: SpyMessageExt,
|
|
302
|
+
filter: {
|
|
303
|
+
serviceKey: string;
|
|
304
|
+
data: string;
|
|
305
|
+
}
|
|
306
|
+
) {
|
|
307
|
+
let testServiceKey = false;
|
|
308
|
+
|
|
309
|
+
try {
|
|
310
|
+
testServiceKey =
|
|
311
|
+
!filter.serviceKey ||
|
|
312
|
+
new RegExp(filter.serviceKey).test(spyMessage.serviceKeyLowerCase);
|
|
313
|
+
} catch {}
|
|
314
|
+
|
|
315
|
+
let testData = false;
|
|
316
|
+
|
|
317
|
+
try {
|
|
318
|
+
testData =
|
|
319
|
+
!filter.data ||
|
|
320
|
+
new RegExp(filter.data).test(spyMessage.dataJsonLowerCase);
|
|
321
|
+
} catch {}
|
|
322
|
+
|
|
323
|
+
return testServiceKey && testData;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function getFunctionStepFromServiceKey(serviceKey: string) {
|
|
327
|
+
const serviceKeyParts = serviceKey.split('#');
|
|
328
|
+
const step =
|
|
329
|
+
serviceKeyParts.length > 0
|
|
330
|
+
? serviceKeyParts[serviceKeyParts.length - 1]
|
|
331
|
+
: undefined;
|
|
332
|
+
return step;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
function renderSpyMessage(spyMessage: SpyMessageExt | SpyMessageGroup) {
|
|
336
|
+
const serviceKey = serviceKeyFilterInputElement.value?.toLocaleLowerCase();
|
|
337
|
+
const data = dataFilterInputElement.value?.toLocaleLowerCase();
|
|
338
|
+
|
|
339
|
+
let messages: SpyMessageExt[];
|
|
340
|
+
if ((spyMessage as SpyMessageGroup).messages) {
|
|
341
|
+
messages = (spyMessage as SpyMessageGroup).messages;
|
|
342
|
+
} else {
|
|
343
|
+
messages = [spyMessage as SpyMessageExt];
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
const html = messages
|
|
347
|
+
.filter((sm) => matchFilter(sm, { serviceKey, data }))
|
|
348
|
+
.map((sm, i) => {
|
|
349
|
+
const service = getServiceNameFromServiceKey(sm.serviceKey);
|
|
350
|
+
let icon: string | undefined;
|
|
351
|
+
|
|
352
|
+
let iconLinked = '<i class="icon-linked bi bi-arrow-return-right"></i>';
|
|
353
|
+
|
|
354
|
+
switch (service) {
|
|
355
|
+
case 'Function':
|
|
356
|
+
const step = getFunctionStepFromServiceKey(sm.serviceKey);
|
|
357
|
+
|
|
358
|
+
if (i === 0) {
|
|
359
|
+
icon = `<img class="aws-icon" src="icons/Arch_AWS-Lambda_16.svg" ></img>`;
|
|
360
|
+
} else {
|
|
361
|
+
icon = iconLinked;
|
|
362
|
+
}
|
|
363
|
+
break;
|
|
364
|
+
case 'S3':
|
|
365
|
+
icon =
|
|
366
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-Simple-Storage-Service_16.svg"/>';
|
|
367
|
+
break;
|
|
368
|
+
case 'SnsTopic':
|
|
369
|
+
icon =
|
|
370
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-Simple-Notification-Service_16.svg" />';
|
|
371
|
+
break;
|
|
372
|
+
case 'EventBridge':
|
|
373
|
+
icon =
|
|
374
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-EventBridge_16.svg" />';
|
|
375
|
+
break;
|
|
376
|
+
case 'DynamoDB':
|
|
377
|
+
icon =
|
|
378
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-DynamoDB_16.svg" />';
|
|
379
|
+
break;
|
|
380
|
+
case 'Sqs':
|
|
381
|
+
icon =
|
|
382
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-Simple-Queue-Service_16.svg" />';
|
|
383
|
+
break;
|
|
384
|
+
case 'EventBridgeRule':
|
|
385
|
+
if (i === 0) {
|
|
386
|
+
icon =
|
|
387
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-EventBridge_16.svg" />';
|
|
388
|
+
} else {
|
|
389
|
+
icon = iconLinked;
|
|
390
|
+
}
|
|
391
|
+
break;
|
|
392
|
+
case 'SnsSubscription':
|
|
393
|
+
if (i === 0) {
|
|
394
|
+
icon =
|
|
395
|
+
'<img class="aws-icon" src="icons/Arch_Amazon-Simple-Notification-Service_16.svg" />';
|
|
396
|
+
} else {
|
|
397
|
+
icon = iconLinked;
|
|
398
|
+
}
|
|
399
|
+
break;
|
|
400
|
+
default:
|
|
401
|
+
break;
|
|
402
|
+
}
|
|
403
|
+
return `<tr>
|
|
404
|
+
<td class="col-time"><span class="time">${new Date(
|
|
405
|
+
sm.timestamp
|
|
406
|
+
).toISOString()}</span></td>
|
|
407
|
+
<td class="col-servicekey">${icon}<span class="serviceKey">${
|
|
408
|
+
sm.serviceKey
|
|
409
|
+
}</span></td>
|
|
410
|
+
<td class="col-data"><div class="data">${JSON.stringify(
|
|
411
|
+
sm.data
|
|
412
|
+
)}</div></td></tr>
|
|
413
|
+
|
|
414
|
+
`;
|
|
415
|
+
})
|
|
416
|
+
.join('');
|
|
417
|
+
return html;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
function getServiceNameFromServiceKey(serviceKey: string) {
|
|
421
|
+
const serviceKeyParts = serviceKey.split('#');
|
|
422
|
+
const service = serviceKeyParts.length > 0 ? serviceKeyParts[0] : undefined;
|
|
423
|
+
return service;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
function setupTooltip() {
|
|
427
|
+
var tooltipTriggerList = [].slice.call(
|
|
428
|
+
document.querySelectorAll('[data-bs-toggle="tooltip"]')
|
|
429
|
+
);
|
|
430
|
+
|
|
431
|
+
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
|
432
|
+
return new Tooltip(tooltipTriggerEl);
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
function addSpyMessageToArraySorted(
|
|
437
|
+
spyMessageToAdd: SpyMessageExt | SpyMessageGroup,
|
|
438
|
+
spyMessages: (SpyMessageExt | SpyMessageGroup)[]
|
|
439
|
+
) {
|
|
440
|
+
let index = 0;
|
|
441
|
+
for (let i = spyMessages.length - 1; i >= 0; i--) {
|
|
442
|
+
const currentSpyMessages = spyMessages[i];
|
|
443
|
+
index = i + 1;
|
|
444
|
+
if (i === 0 || currentSpyMessages.timestamp < spyMessageToAdd.timestamp) {
|
|
445
|
+
break;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
spyMessages.splice(index, 0, spyMessageToAdd);
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
type SpyMessageExt<T extends SpyEvent = SpyEvent> = SpyMessage<T> & {
|
|
453
|
+
dataJsonLowerCase: string;
|
|
454
|
+
serviceKeyLowerCase: string;
|
|
455
|
+
};
|
|
456
|
+
|
|
457
|
+
type SpyMessageGroup<T extends SpyEvent = SpyEvent> = {
|
|
458
|
+
timestamp: string;
|
|
459
|
+
serviceKey: string;
|
|
460
|
+
messages: SpyMessageExt<T>[];
|
|
461
|
+
};
|