serverless-spy 0.0.36 → 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 +3 -3
- 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 +91 -14
- package/functions/sendMessage.ts +4 -2
- 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 +251 -181
- package/lib/extension/dist/layer/nodejs/node_modules/interceptor.js.map +3 -3
- 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.js +11 -11
- package/lib/listener/WsListener.mjs +12 -12
- package/lib/src/ServerlessSpy.js +2 -3
- package/lib/src/ServerlessSpy.mjs +1 -2
- package/listener/SpyHandlers.ts.ts +70 -9
- package/listener/WsListener.ts +21 -18
- 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
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DynamoDBSpyEvent } from '../common/spyEvents/DynamoDBSpyEvent';
|
|
2
2
|
import { EventBridgeRuleSpyEvent } from '../common/spyEvents/EventBridgeRuleSpyEvent';
|
|
3
3
|
import { EventBridgeSpyEvent } from '../common/spyEvents/EventBridgeSpyEvent';
|
|
4
|
+
import { FunctionConsole } from '../common/spyEvents/FunctionConsole';
|
|
4
5
|
import { FunctionConsoleSpyEvent } from '../common/spyEvents/FunctionConsoleSpyEvent';
|
|
5
6
|
import { FunctionContext } from '../common/spyEvents/FunctionContext';
|
|
6
7
|
import { FunctionRequestSpyEvent } from '../common/spyEvents/FunctionRequestSpyEvent';
|
|
@@ -112,13 +113,26 @@ export interface FunctionBaseSpyHandler<TData = any>
|
|
|
112
113
|
FunctionRequestSpyEvent<TData>,
|
|
113
114
|
FunctionRequestSpyHandler<TData>
|
|
114
115
|
> {
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
116
|
+
followedByConsole: (
|
|
117
|
+
// This implementation confuses TypeScript which does not accurately display the type.
|
|
118
|
+
param?: {
|
|
119
|
+
condition?: (event: {
|
|
120
|
+
spyEventType: 'FunctionConsole';
|
|
121
|
+
request: TData;
|
|
122
|
+
context: FunctionContext;
|
|
123
|
+
console: FunctionConsole;
|
|
124
|
+
}) => boolean;
|
|
125
|
+
timoutMs?: number;
|
|
126
|
+
}
|
|
127
|
+
) => Promise<
|
|
128
|
+
FunctionBaseSpyHandler<TData> &
|
|
129
|
+
FunctionConsoleSpyHandler<TData> &
|
|
130
|
+
JestExpectWithSpyMethods<
|
|
131
|
+
FunctionConsoleSpyEvent<TData>,
|
|
132
|
+
FunctionRequestSpyHandler<TData>
|
|
133
|
+
>
|
|
134
|
+
>;
|
|
135
|
+
|
|
122
136
|
followedByResponse: <TDataResponse = any>(
|
|
123
137
|
// This implementation confuses TypeScript which does not accurately display the type.
|
|
124
138
|
// Leave it for reference!
|
|
@@ -137,7 +151,7 @@ export interface FunctionBaseSpyHandler<TData = any>
|
|
|
137
151
|
timoutMs?: number;
|
|
138
152
|
}
|
|
139
153
|
) => Promise<
|
|
140
|
-
FunctionResponseSpyHandler &
|
|
154
|
+
FunctionResponseSpyHandler<TData> &
|
|
141
155
|
JestExpectWithSpyMethods<
|
|
142
156
|
FunctionRequestSpyEvent<TData>,
|
|
143
157
|
FunctionRequestSpyHandler<TData>
|
|
@@ -151,8 +165,55 @@ export interface FunctionRequestSpyHandler<TData = any>
|
|
|
151
165
|
}
|
|
152
166
|
|
|
153
167
|
export interface FunctionConsoleSpyHandler<TData = any>
|
|
154
|
-
extends
|
|
168
|
+
extends JestExpectWithSpyMethods<
|
|
169
|
+
FunctionConsoleSpyEvent<TData>,
|
|
170
|
+
FunctionConsoleSpyHandler<TData>
|
|
171
|
+
> {
|
|
155
172
|
getData: () => PrettifyForDisplay<FunctionConsoleSpyEvent<TData>>;
|
|
173
|
+
followedByConsole: (
|
|
174
|
+
// This implementation confuses TypeScript which does not accurately display the type.
|
|
175
|
+
param?: {
|
|
176
|
+
condition?: (event: {
|
|
177
|
+
spyEventType: 'FunctionConsole';
|
|
178
|
+
request: TData;
|
|
179
|
+
context: FunctionContext;
|
|
180
|
+
console: FunctionConsole;
|
|
181
|
+
}) => boolean;
|
|
182
|
+
timoutMs?: number;
|
|
183
|
+
}
|
|
184
|
+
) => Promise<
|
|
185
|
+
FunctionBaseSpyHandler<TData> &
|
|
186
|
+
FunctionConsoleSpyHandler<TData> &
|
|
187
|
+
JestExpectWithSpyMethods<
|
|
188
|
+
FunctionConsoleSpyEvent<TData>,
|
|
189
|
+
FunctionRequestSpyHandler<TData>
|
|
190
|
+
>
|
|
191
|
+
>;
|
|
192
|
+
|
|
193
|
+
followedByResponse: <TDataResponse = any>(
|
|
194
|
+
// This implementation confuses TypeScript which does not accurately display the type.
|
|
195
|
+
// Leave it for reference!
|
|
196
|
+
// param: PrettifyForDisplay<
|
|
197
|
+
// WaitForParams<
|
|
198
|
+
// PrettifyForDisplay<FunctionResponseSpyEvent<TData, TDataResponse>>
|
|
199
|
+
// >
|
|
200
|
+
// >
|
|
201
|
+
param?: {
|
|
202
|
+
condition?: (event: {
|
|
203
|
+
spyEventType: 'FunctionResponse';
|
|
204
|
+
request: TData;
|
|
205
|
+
context: FunctionContext;
|
|
206
|
+
response: TDataResponse;
|
|
207
|
+
}) => boolean;
|
|
208
|
+
timoutMs?: number;
|
|
209
|
+
}
|
|
210
|
+
) => Promise<
|
|
211
|
+
FunctionResponseSpyHandler<TData> &
|
|
212
|
+
JestExpectWithSpyMethods<
|
|
213
|
+
FunctionRequestSpyEvent<TData>,
|
|
214
|
+
FunctionRequestSpyHandler<TData>
|
|
215
|
+
>
|
|
216
|
+
>;
|
|
156
217
|
}
|
|
157
218
|
|
|
158
219
|
export interface FunctionResponseSpyHandler<TData = any>
|
package/listener/WsListener.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { WebSocket } from 'ws';
|
|
2
|
-
import {
|
|
2
|
+
import { getSignedWebSocketUrl } from '../common/getWebSocketUrl';
|
|
3
3
|
import { FunctionRequestSpyEvent } from '../common/spyEvents/FunctionRequestSpyEvent';
|
|
4
4
|
import { SpyEvent } from '../common/spyEvents/SpyEvent';
|
|
5
5
|
import { SpyMessage } from '../common/spyEvents/SpyMessage';
|
|
@@ -25,7 +25,7 @@ export class WsListener<TSpyEvents> {
|
|
|
25
25
|
this.connectionOpenResolve = resolve;
|
|
26
26
|
});
|
|
27
27
|
|
|
28
|
-
const urlSigned = await
|
|
28
|
+
const urlSigned = await getSignedWebSocketUrl(
|
|
29
29
|
params.serverlessSpyWsUrl,
|
|
30
30
|
params.credentials
|
|
31
31
|
);
|
|
@@ -90,27 +90,30 @@ export class WsListener<TSpyEvents> {
|
|
|
90
90
|
(serviceKeyForFunction.endsWith('Request') ||
|
|
91
91
|
serviceKeyForFunction.endsWith('Console'))
|
|
92
92
|
) {
|
|
93
|
-
let
|
|
94
|
-
|
|
95
|
-
if (
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
serviceKeyForFunctionResponse.length - 'Console'.length
|
|
106
|
-
);
|
|
93
|
+
let serviceKeyForFunctionChain = serviceKeyForFunction;
|
|
94
|
+
|
|
95
|
+
if (serviceKeyForFunctionChain.endsWith('Request')) {
|
|
96
|
+
serviceKeyForFunctionChain = serviceKeyForFunctionChain.substring(
|
|
97
|
+
0,
|
|
98
|
+
serviceKeyForFunctionChain.length - 'Request'.length
|
|
99
|
+
);
|
|
100
|
+
} else if (serviceKeyForFunctionChain.endsWith('Console')) {
|
|
101
|
+
serviceKeyForFunctionChain = serviceKeyForFunctionChain.substring(
|
|
102
|
+
0,
|
|
103
|
+
serviceKeyForFunctionChain.length - 'Console'.length
|
|
104
|
+
);
|
|
107
105
|
}
|
|
108
106
|
|
|
109
|
-
|
|
107
|
+
spyAndJestMatchers.followedByConsole = (paramsW: WaitForParams) => {
|
|
108
|
+
return this.createWaitForXXXFunc(
|
|
109
|
+
`${serviceKeyForFunctionChain}Console`,
|
|
110
|
+
(message.data as FunctionRequestSpyEvent).context.awsRequestId
|
|
111
|
+
)(paramsW);
|
|
112
|
+
};
|
|
110
113
|
|
|
111
114
|
spyAndJestMatchers.followedByResponse = (paramsW: WaitForParams) => {
|
|
112
115
|
return this.createWaitForXXXFunc(
|
|
113
|
-
|
|
116
|
+
`${serviceKeyForFunctionChain}Response`,
|
|
114
117
|
(message.data as FunctionRequestSpyEvent).context.awsRequestId
|
|
115
118
|
)(paramsW);
|
|
116
119
|
};
|
package/package.json
CHANGED
|
@@ -32,7 +32,8 @@
|
|
|
32
32
|
"lint": "eslint **/*.ts",
|
|
33
33
|
"lint-fix": "eslint --fix './**/*.ts'",
|
|
34
34
|
"pretty": "prettier --write '**/*.ts'",
|
|
35
|
-
"bundle-extension": "scripts/run-task bundle-extension"
|
|
35
|
+
"bundle-extension": "scripts/run-task bundle-extension",
|
|
36
|
+
"cli": "scripts/run-task cli"
|
|
36
37
|
},
|
|
37
38
|
"author": {
|
|
38
39
|
"name": "Marko (ServerlessLife.com)",
|
|
@@ -78,7 +79,8 @@
|
|
|
78
79
|
},
|
|
79
80
|
"workspaces": [
|
|
80
81
|
"test",
|
|
81
|
-
"test/cdk"
|
|
82
|
+
"test/cdk",
|
|
83
|
+
"cli"
|
|
82
84
|
],
|
|
83
85
|
"peerDependencies": {
|
|
84
86
|
"aws-cdk-lib": "^2.37.1",
|
|
@@ -116,7 +118,7 @@
|
|
|
116
118
|
"require": "./lib/index.js"
|
|
117
119
|
},
|
|
118
120
|
"license": "Apache-2.0",
|
|
119
|
-
"version": "0.0.
|
|
121
|
+
"version": "0.0.37",
|
|
120
122
|
"types": "lib/index.d.ts",
|
|
121
123
|
"stability": "stable",
|
|
122
124
|
"jsii": {
|
package/cli/serverlessSpy.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
function run() {
|
|
2
|
-
const tableBody = document.getElementById("tableBody");
|
|
3
|
-
var modal = document.getElementById("myModal");
|
|
4
|
-
var span = document.getElementsByClassName("close")[0];
|
|
5
|
-
const modalContent = document.getElementById("modalContent");
|
|
6
|
-
span.onclick = function () {
|
|
7
|
-
modal.style.display = "none";
|
|
8
|
-
};
|
|
9
|
-
window.onclick = function (event) {
|
|
10
|
-
if (event.target == modal) {
|
|
11
|
-
modal.style.display = "none";
|
|
12
|
-
}
|
|
13
|
-
};
|
|
14
|
-
|
|
15
|
-
tableBody.addEventListener("click", function (e) {
|
|
16
|
-
const dataJson = JSON.stringify(
|
|
17
|
-
JSON.parse(e.target.parentElement.children[2].textContent),
|
|
18
|
-
null,
|
|
19
|
-
2
|
|
20
|
-
);
|
|
21
|
-
modalContent.innerText = dataJson;
|
|
22
|
-
modal.style.display = "block";
|
|
23
|
-
//alert();
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
const url = "SERVERLESS_SPY_WS_URL";
|
|
27
|
-
//"wss://m6g3w6ttdh.execute-api.eu-west-1.amazonaws.com/prod?X-Amz-Security-Token=IQoJb3JpZ2luX2VjELL%2F%2F%2F%2F%2F%2F%2F%2F%2F%2FwEaCWV1LXdlc3QtMSJGMEQCIDk%2BzQd0RC2DmEgCJEPoRFAkmnhCZl%2BSIlEG4TummRkIAiBIgNG8Yw%2FOAew3XNAE3yrNCK0G0q%2BZI8MwjEa8xoEonirrAQgbEAQaDDA3NjU4NTk2NzA3NSIMxVUxKhwdqGjFOsRtKsgB2eotQMFgl4CrD8uy%2Fe1UE6K4HVc6uWo0gdjgHMPb5C9Mq0wFgHTiDFjFxIFkJpmCiTRXKqNFrx5lpo9C5Ml1bpcv%2BTopT6wvpbFksxChhhnaqUDHiBaGuys8zEy8Bjlu4jF0nKccmUYdieD70%2FXz99OU4wKPxXyWbr0w82y1Xd6ag8g4VNx3EXEdULq7vkM6H2shSAH8EUlZoTD%2BqvIQvyKS8nta3ebhprO%2BsLRQv2YC6k1w46jHuOjtI7hSnmfSKnkUqAxS6g4wgZrFlwY6mQFNSXz7jSF3IRtdcpMEIp%2Bnghf2LhvZKeW6GkZs4DMeuhPjoBehfmXLJIJWgcvLoheQvIt28ddgHU60%2BoRKhZTxQKhpvSOaAbI6M%2B%2FyHvkC2hTR4fEBtESAMnzo8WocfxdaQQ0YVYq2m5NKSXs3QrrsYIIirkFYhB%2BjAwG8bqBAuE9SQNeIthHjT27hB7KUeIIoXtwSVGutv70%3D&X-Amz-Date=20220808T175057Z&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ASIARDVHBDXR4QCRLL4O%2F20220808%2Feu-west-1%2Fexecute-api%2Faws4_request&X-Amz-SignedHeaders=host&X-Amz-Signature=d58ab2b792a69f20f8e3bf9bf4fb19c8ec8f271bd1b594f8cd25c02d4c85521d";
|
|
28
|
-
const ws = new WebSocket(url);
|
|
29
|
-
|
|
30
|
-
ws.addEventListener("open", function (event) {
|
|
31
|
-
console.log("connected " + new Date().toISOString());
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
ws.addEventListener("message", function ({ data }) {
|
|
35
|
-
//debugger;
|
|
36
|
-
//console.log(`From server: ${data}`);
|
|
37
|
-
|
|
38
|
-
let parsed;
|
|
39
|
-
try {
|
|
40
|
-
parsed = JSON.parse(data);
|
|
41
|
-
} catch (err) {
|
|
42
|
-
console.error("Can not parse " + data);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
addLog(parsed);
|
|
46
|
-
|
|
47
|
-
// if (parsed) {
|
|
48
|
-
// console.log(
|
|
49
|
-
// `\x1b[47m\x1b[34m${parsed.timestamp} \x1b[31m🍕 ${
|
|
50
|
-
// parsed.serviceKey
|
|
51
|
-
// }\x1b[0m\x1b[32m\n${JSON.stringify(parsed.data, null, 2)}\x1b[0m`
|
|
52
|
-
// );
|
|
53
|
-
// }
|
|
54
|
-
});
|
|
55
|
-
ws.addEventListener("close", function () {
|
|
56
|
-
console.log("disconnected " + new Date().toISOString());
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
function addLog(data) {
|
|
60
|
-
const newRow = document.createElement("tr");
|
|
61
|
-
newRow.innerHTML = `
|
|
62
|
-
<td>${new Date(data.timestamp).toLocaleTimeString()}</td>
|
|
63
|
-
<td>${data.serviceKey}</td>
|
|
64
|
-
<td>${JSON.stringify(data.data)}</td>
|
|
65
|
-
`;
|
|
66
|
-
tableBody.append(newRow);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
document.addEventListener("DOMContentLoaded", function () {
|
|
71
|
-
console.log("RUN");
|
|
72
|
-
run();
|
|
73
|
-
});
|
package/cli/ws.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import * as fs from 'fs';
|
|
2
|
-
import * as readline from 'readline';
|
|
3
|
-
import WebSocket from 'ws';
|
|
4
|
-
import { getWebSocketUrl } from '../common/getWebSocketUrl';
|
|
5
|
-
|
|
6
|
-
async function run() {
|
|
7
|
-
// var credentialsProvider = awsCp.fromTemporaryCredentials();
|
|
8
|
-
// const credentials = await credentialsProvider();
|
|
9
|
-
|
|
10
|
-
// const client = new STSClient({});
|
|
11
|
-
// client.send()
|
|
12
|
-
|
|
13
|
-
// const command = new GetSessionTokenCommand({});
|
|
14
|
-
// const { Credentials: credentials } = await client.send(command);
|
|
15
|
-
// //const credentials = s.Credentials;
|
|
16
|
-
|
|
17
|
-
// console.log("credentials", credentials);
|
|
18
|
-
|
|
19
|
-
// const url = process.argv[2];
|
|
20
|
-
const url = 'wss://preh1xo1xh.execute-api.eu-west-1.amazonaws.com/prod';
|
|
21
|
-
|
|
22
|
-
// https://medium.com/@o.bredenberg/iam-sign-your-api-gateway-websocket-connection-request-no-custom-auth-from-your-frontend-65451166757d
|
|
23
|
-
const url2 = await getWebSocketUrl(url);
|
|
24
|
-
|
|
25
|
-
const ws = new WebSocket(url2);
|
|
26
|
-
|
|
27
|
-
const fileDescriptor = fs.openSync('spy_log.json', 'w');
|
|
28
|
-
// 📢📁⚡️💾 💽 💾 💿 📀🛢🪣📑🔊
|
|
29
|
-
|
|
30
|
-
ws.on('open', () => console.log(`connected ${new Date().toISOString()}`));
|
|
31
|
-
ws.on('message', (data: any) => {
|
|
32
|
-
// console.log(`From server: ${data}`);
|
|
33
|
-
|
|
34
|
-
let parsed;
|
|
35
|
-
try {
|
|
36
|
-
parsed = JSON.parse(data);
|
|
37
|
-
} catch (err) {
|
|
38
|
-
console.error(`Can not parse ${data}`);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
if (parsed) {
|
|
42
|
-
console.log(
|
|
43
|
-
`\x1b[47m\x1b[34m${parsed.timestamp} \x1b[31m🍕 ${
|
|
44
|
-
parsed.serviceKey
|
|
45
|
-
}\x1b[0m\x1b[32m\n${JSON.stringify(parsed.data, null, 2)}\x1b[0m`
|
|
46
|
-
);
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
fs.write(fileDescriptor, data, (error) => {
|
|
50
|
-
if (!error) {
|
|
51
|
-
// fs.close(fileDescriptor);
|
|
52
|
-
} else {
|
|
53
|
-
console.error(error);
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
|
-
fs.write(fileDescriptor, '\n', (error) => {
|
|
57
|
-
if (!error) {
|
|
58
|
-
// fs.close(fileDescriptor);
|
|
59
|
-
} else {
|
|
60
|
-
console.error(error);
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
});
|
|
64
|
-
ws.on('close', () => {
|
|
65
|
-
console.log(`disconnected ${new Date().toISOString()}`);
|
|
66
|
-
fs.close(fileDescriptor, () => undefined);
|
|
67
|
-
process.exit();
|
|
68
|
-
});
|
|
69
|
-
|
|
70
|
-
readline
|
|
71
|
-
.createInterface({
|
|
72
|
-
input: process.stdin,
|
|
73
|
-
output: process.stdout,
|
|
74
|
-
})
|
|
75
|
-
.on('line', (data) => {
|
|
76
|
-
ws.send(data);
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
run().catch(console.error);
|
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ApiGatewayManagementApi,
|
|
3
|
-
PostToConnectionCommand,
|
|
4
|
-
} from '@aws-sdk/client-apigatewaymanagementapi';
|
|
5
|
-
import {
|
|
6
|
-
AttributeValue,
|
|
7
|
-
DeleteItemCommand,
|
|
8
|
-
DynamoDBClient,
|
|
9
|
-
ScanCommand,
|
|
10
|
-
} from '@aws-sdk/client-dynamodb';
|
|
11
|
-
|
|
12
|
-
import { unmarshall } from '@aws-sdk/util-dynamodb';
|
|
13
|
-
import {
|
|
14
|
-
DynamoDBStreamEvent,
|
|
15
|
-
S3Event,
|
|
16
|
-
SNSEvent,
|
|
17
|
-
EventBridgeEvent,
|
|
18
|
-
SQSEvent,
|
|
19
|
-
} from 'aws-lambda';
|
|
20
|
-
import { envVariableNames } from '../src/common/envVariableNames';
|
|
21
|
-
import { DynamoDBSpyEvent } from './spyEvents/DynamoDBSpyEvent';
|
|
22
|
-
import { EventBridgeRuleSpyEvent } from './spyEvents/EventBridgeRuleSpyEvent';
|
|
23
|
-
import { EventBridgeSpyEvent } from './spyEvents/EventBridgeSpyEvent';
|
|
24
|
-
import { S3SpyEvent } from './spyEvents/S3SpyEvent';
|
|
25
|
-
import { SnsSubscriptionSpyEvent } from './spyEvents/SnsSubscriptionSpyEvent';
|
|
26
|
-
import { SnsTopicSpyEvent } from './spyEvents/SnsTopicSpyEvent';
|
|
27
|
-
import { SpyMessage } from './spyEvents/SpyMessage';
|
|
28
|
-
import { SqsSpyEvent } from './spyEvents/SqsSpyEvent';
|
|
29
|
-
|
|
30
|
-
const ddb = new DynamoDBClient({
|
|
31
|
-
region: process.env.AWS_REGION,
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const apigwManagementApi = new ApiGatewayManagementApi({
|
|
35
|
-
apiVersion: '2018-11-29',
|
|
36
|
-
endpoint: process.env[envVariableNames.SSPY_WS_ENDPOINT]!,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
let connections: Record<string, AttributeValue>[] | undefined;
|
|
40
|
-
|
|
41
|
-
export async function publishSpyEvent(event: any) {
|
|
42
|
-
console.log('EVENT', JSON.stringify(event));
|
|
43
|
-
|
|
44
|
-
const mapping = JSON.parse(process.env[envVariableNames.SSPY_INFRA_MAPPING]!);
|
|
45
|
-
console.log('mapping', JSON.stringify(mapping));
|
|
46
|
-
|
|
47
|
-
let connectionData;
|
|
48
|
-
|
|
49
|
-
const scanParams = new ScanCommand({
|
|
50
|
-
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME] as string,
|
|
51
|
-
ProjectionExpression: 'connectionId',
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
connectionData = await ddb.send(scanParams);
|
|
55
|
-
|
|
56
|
-
connections = connectionData.Items;
|
|
57
|
-
|
|
58
|
-
console.log(
|
|
59
|
-
`connections at ${new Date().toISOString()}`,
|
|
60
|
-
JSON.stringify(connections)
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
const postDataPromises: Promise<any>[] = [];
|
|
64
|
-
|
|
65
|
-
if (event?.Records && event.Records[0]?.Sns) {
|
|
66
|
-
console.log('*** SNS ***');
|
|
67
|
-
const eventSns = event as SNSEvent;
|
|
68
|
-
for (const record of eventSns.Records) {
|
|
69
|
-
const subscriptionArn = record.EventSubscriptionArn;
|
|
70
|
-
|
|
71
|
-
let serviceKey: string;
|
|
72
|
-
if (mapping[subscriptionArn]) {
|
|
73
|
-
// subscription event that could contain filter based on existing subscription
|
|
74
|
-
serviceKey = mapping[subscriptionArn];
|
|
75
|
-
} else {
|
|
76
|
-
// catch all subscription
|
|
77
|
-
const topicArn = record.Sns.TopicArn;
|
|
78
|
-
serviceKey = mapping[topicArn];
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let message: string;
|
|
82
|
-
|
|
83
|
-
try {
|
|
84
|
-
message = JSON.parse(record.Sns.Message);
|
|
85
|
-
} catch {
|
|
86
|
-
message = record.Sns.Message;
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const spyEventType = getSpyEventType(serviceKey) as
|
|
90
|
-
| 'FunctionSnsTopic'
|
|
91
|
-
| 'FunctionSnsSubscription';
|
|
92
|
-
|
|
93
|
-
const data: SnsTopicSpyEvent | SnsSubscriptionSpyEvent = {
|
|
94
|
-
spyEventType,
|
|
95
|
-
message,
|
|
96
|
-
subject: record.Sns.Subject,
|
|
97
|
-
timestamp: record.Sns.Timestamp,
|
|
98
|
-
topicArn: record.Sns.TopicArn,
|
|
99
|
-
messageId: record.Sns.MessageId,
|
|
100
|
-
messageAttributes: record.Sns.MessageAttributes,
|
|
101
|
-
};
|
|
102
|
-
|
|
103
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = {
|
|
104
|
-
data,
|
|
105
|
-
serviceKey,
|
|
106
|
-
};
|
|
107
|
-
postDataPromises.push(postData(fluentEvent));
|
|
108
|
-
}
|
|
109
|
-
} else if (event?.Records && event.Records[0]?.eventSource === 'aws:sqs') {
|
|
110
|
-
console.log('*** SQS ***');
|
|
111
|
-
const eventSqs = event as SQSEvent;
|
|
112
|
-
for (const record of eventSqs.Records) {
|
|
113
|
-
const subscriptionArn = record.eventSourceARN;
|
|
114
|
-
|
|
115
|
-
const serviceKey = mapping[subscriptionArn];
|
|
116
|
-
let body: string;
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
body = JSON.parse(record.body);
|
|
120
|
-
} catch {
|
|
121
|
-
body = record.body;
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
const data: SqsSpyEvent = {
|
|
125
|
-
spyEventType: 'Sqs',
|
|
126
|
-
body,
|
|
127
|
-
messageAttributes: record.messageAttributes,
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = {
|
|
131
|
-
data,
|
|
132
|
-
serviceKey,
|
|
133
|
-
};
|
|
134
|
-
postDataPromises.push(postData(fluentEvent));
|
|
135
|
-
}
|
|
136
|
-
} else if (event?.Records && event.Records[0]?.s3) {
|
|
137
|
-
console.log('*** S3 ***');
|
|
138
|
-
const eventS3 = event as S3Event;
|
|
139
|
-
for (const record of eventS3.Records) {
|
|
140
|
-
const bucketArn = record.s3.bucket.arn;
|
|
141
|
-
|
|
142
|
-
const data: S3SpyEvent = {
|
|
143
|
-
spyEventType: 'S3',
|
|
144
|
-
eventName: record.eventName,
|
|
145
|
-
eventTime: record.eventTime,
|
|
146
|
-
bucket: record.s3.bucket.name,
|
|
147
|
-
key: record.s3.object.key,
|
|
148
|
-
};
|
|
149
|
-
|
|
150
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = {
|
|
151
|
-
data,
|
|
152
|
-
serviceKey: mapping[bucketArn],
|
|
153
|
-
};
|
|
154
|
-
postDataPromises.push(postData(fluentEvent));
|
|
155
|
-
}
|
|
156
|
-
} else if (event.Records && event.Records[0]?.dynamodb) {
|
|
157
|
-
console.log('*** DYNAMODB ***');
|
|
158
|
-
const eventDynamoDB = event as DynamoDBStreamEvent;
|
|
159
|
-
for (const record of eventDynamoDB.Records) {
|
|
160
|
-
let arn = record.eventSourceARN!;
|
|
161
|
-
arn = arn.substring(0, arn.indexOf('/stream/'));
|
|
162
|
-
|
|
163
|
-
const data: DynamoDBSpyEvent = {
|
|
164
|
-
spyEventType: 'DynamoDB',
|
|
165
|
-
eventName: record.eventName,
|
|
166
|
-
newImage: unmarshall(record.dynamodb?.NewImage as any),
|
|
167
|
-
keys: unmarshall(record.dynamodb?.Keys as any),
|
|
168
|
-
oldImage: record.dynamodb?.OldImage
|
|
169
|
-
? unmarshall(record.dynamodb?.OldImage as any)
|
|
170
|
-
: undefined,
|
|
171
|
-
};
|
|
172
|
-
|
|
173
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = {
|
|
174
|
-
data,
|
|
175
|
-
serviceKey: mapping[arn],
|
|
176
|
-
};
|
|
177
|
-
postDataPromises.push(postData(fluentEvent));
|
|
178
|
-
}
|
|
179
|
-
} else if (
|
|
180
|
-
event.detail &&
|
|
181
|
-
event['detail-type'] &&
|
|
182
|
-
event.version &&
|
|
183
|
-
event.source
|
|
184
|
-
) {
|
|
185
|
-
console.log('*** EventBridge ***');
|
|
186
|
-
const eventEb = event as EventBridgeEvent<any, any>;
|
|
187
|
-
|
|
188
|
-
const serviceKey = mapping.eventBridge; // the is new lambda for each subscription
|
|
189
|
-
|
|
190
|
-
const spyEventType = getSpyEventType(serviceKey) as
|
|
191
|
-
| 'EventBridge'
|
|
192
|
-
| 'EventBridgeRule';
|
|
193
|
-
|
|
194
|
-
const message = eventEb.detail;
|
|
195
|
-
|
|
196
|
-
const data: EventBridgeSpyEvent | EventBridgeRuleSpyEvent = {
|
|
197
|
-
spyEventType,
|
|
198
|
-
detail: message,
|
|
199
|
-
detailType: eventEb['detail-type'],
|
|
200
|
-
source: eventEb.source,
|
|
201
|
-
time: eventEb.time,
|
|
202
|
-
account: eventEb.account,
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = {
|
|
206
|
-
data,
|
|
207
|
-
serviceKey,
|
|
208
|
-
};
|
|
209
|
-
postDataPromises.push(postData(fluentEvent));
|
|
210
|
-
} else {
|
|
211
|
-
console.log('*** OTHER ***');
|
|
212
|
-
const fluentEvent: Omit<SpyMessage, 'timestamp'> = event;
|
|
213
|
-
postDataPromises.push(postData(fluentEvent));
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
await Promise.all(postDataPromises);
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
export async function postData(spyMessage: Omit<SpyMessage, 'timestamp'>) {
|
|
220
|
-
// const postData = JSON.parse(event.body!).data;
|
|
221
|
-
console.log('postData', JSON.stringify(spyMessage));
|
|
222
|
-
|
|
223
|
-
if (!connections) {
|
|
224
|
-
return;
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const postCalls = connections.map(async ({ connectionId }) => {
|
|
228
|
-
console.log(`Sending message to: ${connectionId.S}`);
|
|
229
|
-
|
|
230
|
-
try {
|
|
231
|
-
const postToConnectionCommand = new PostToConnectionCommand({
|
|
232
|
-
ConnectionId: connectionId.S,
|
|
233
|
-
Data: JSON.stringify({
|
|
234
|
-
timestamp: new Date().toISOString(),
|
|
235
|
-
serviceKey: spyMessage.serviceKey,
|
|
236
|
-
data: spyMessage.data,
|
|
237
|
-
}) as any,
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
await apigwManagementApi.send(postToConnectionCommand);
|
|
241
|
-
} catch (e) {
|
|
242
|
-
console.error(`Fails sending message to: ${connectionId.S}`, e);
|
|
243
|
-
console.error(`Status code: ${(e as any).statusCode}`);
|
|
244
|
-
if ((e as any).$metadata.httpStatusCode === 410) {
|
|
245
|
-
console.log(`Found stale connection, deleting ${connectionId}`);
|
|
246
|
-
|
|
247
|
-
const deleteParams = new DeleteItemCommand({
|
|
248
|
-
TableName: process.env[envVariableNames.SSPY_WS_TABLE_NAME],
|
|
249
|
-
Key: { connectionId },
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
await ddb.send(deleteParams);
|
|
253
|
-
} else {
|
|
254
|
-
throw e;
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
});
|
|
258
|
-
|
|
259
|
-
await Promise.all(postCalls);
|
|
260
|
-
console.log('Send message finish');
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
export function getSpyEventType(serviceKey: string) {
|
|
264
|
-
if (!serviceKey) {
|
|
265
|
-
throw new Error('Missing serviceKey');
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
return serviceKey.substring(0, serviceKey.indexOf('#'));
|
|
269
|
-
}
|
package/lib/cli/ws.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|