Skip to content

Commit 54b5018

Browse files
finished error handling, added http transport to Klepper server, handling client options in NodeJS global scope
1 parent b522760 commit 54b5018

17 files changed

Lines changed: 26717 additions & 1680 deletions

File tree

package-lock.json

Lines changed: 25564 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@
33
"private": true,
44
"workspaces": [
55
"packages/node",
6-
"packages/transport"
6+
"packages/transport",
7+
"packages/commons"
78
],
89
"scripts": {
9-
"build": "lerna run build"
10+
"build": "lerna run build",
11+
"lint": "lerna run lint",
12+
"test": "lerna run test"
1013
},
1114
"dependencies": {},
1215
"devDependencies": {

packages/commons/package.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"name": "@klepper/commons",
33
"version": "0.0.1",
4+
"description": "",
5+
"author": "",
46
"main": "dist/index.js",
57
"types": "dist/index.d.ts",
68
"private": "false",
@@ -16,7 +18,22 @@
1618
"test:watch": "jest --watch --notify"
1719
},
1820
"dependencies": {
21+
"@klepper/transport": "0.0.1",
1922
"tslint": "^6.1.3",
2023
"typescript": "^4.6.2"
24+
},
25+
"jest": {
26+
"verbose": false,
27+
"testURL": "http://localhost/",
28+
"transform": {
29+
"^.+\\.ts$": "ts-jest"
30+
},
31+
"moduleFileExtensions": [
32+
"js",
33+
"ts"
34+
],
35+
"testMatch": [
36+
"**/*.test.ts"
37+
]
2138
}
2239
}

packages/commons/src/global.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { KlepperGlobal } from "@klepper/transport";
2+
3+
export const getGlobalClientData = (): KlepperGlobal => global.__KLEPPER__ || {};
4+
5+
export const setGlobalClientData = (data: KlepperGlobal): void => {
6+
global.__KLEPPER__ = { ...data };
7+
}
8+
9+
export const clearGlobalClientData = (): void => {
10+
setGlobalClientData({
11+
environment: undefined,
12+
privateKey: undefined
13+
})
14+
}

packages/commons/src/http.ts

Lines changed: 72 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,90 @@
1+
import { RequestPayload, RequestOptions, KlepperResponse, KlepperIncomingMessage, RequestStatus } from "@klepper/transport";
12
import * as http from "http";
3+
import { getGlobalClientData } from "./global";
24

3-
type RequestType = "" | "" | "";
5+
const KLEPPER_HOST = process.env.KLEPPER_HOST || "localhost";
6+
const KLEPPER_API = process.env.KLEPPER_API || "/test";
7+
const KLEPPER_PORT = process.env.KLEPPER_PORT || 3000;
48

5-
type HttpMethodType = "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
6-
7-
const KLEPPER_API = process.env.KLEPPER_API;
8-
const KLEPPER_PORT = process.env.KLEPPER_PORT;
9-
10-
export interface RequestOptions extends http.RequestOptions {
11-
hostname: string;
12-
port: number;
13-
method: HttpMethodType;
14-
path?: string;
15-
headers?: { [key: string]: string };
16-
}
17-
18-
export interface RequestPayload {
19-
data: string;
20-
type: RequestType;
21-
url: string;
22-
}
23-
24-
export const getRequestPath = (path: string) =>
25-
`http://api.klepper.io/api/${path}`;
26-
27-
export const getRequestHeaders = () => {};
28-
29-
export const createHttpOptions = (payload: RequestPayload): RequestOptions => {
30-
const { url } = payload;
9+
const createHttpOptions = (payload: RequestPayload): http.RequestOptions => {
10+
const client = getGlobalClientData();
11+
const { privateKey } = client;
12+
const { data } = payload;
3113
const baseOptions: RequestOptions = {
32-
hostname: KLEPPER_API!,
33-
method: "POST",
34-
port: +KLEPPER_PORT!,
14+
hostname: KLEPPER_HOST,
15+
port: +KLEPPER_PORT,
16+
method: 'POST',
17+
headers: {
18+
'Content-Type': 'application/json',
19+
'Content-Length': `${Buffer.byteLength(JSON.stringify(data))}`,
20+
'Klepper-Project-Key': privateKey as string
21+
}
3522
};
3623

3724
return {
38-
path: getRequestPath(url),
25+
path: KLEPPER_API,
3926
...baseOptions,
4027
};
4128
};
4229

30+
const statusFromCode = (code: number) => code >= 200 && code <= 299 ? RequestStatus.SUCCESS : RequestStatus.ERROR;
31+
4332
/**
4433
* Send data to Klepper server
4534
*
4635
* @param payload
4736
*/
48-
export const sendHttpRequest = (payload: RequestPayload) => {
37+
export const sendEvent = async (payload: RequestPayload): Promise<KlepperResponse> => {
4938
const { data } = payload;
50-
const options = createHttpOptions(payload);
51-
const request = http.request(options, (res: http.IncomingMessage) => {
52-
res.setEncoding("utf8");
53-
54-
res.on("data", () => {});
55-
res.on("end", () => {});
56-
});
57-
request.end(data);
39+
40+
// global.Object = Object({ test: "test" })
41+
// console.log("GLOBAL: ", global.Object);
42+
43+
/**
44+
* IMPORTANT TO HANDLE GLOBAL DATA
45+
*/
46+
47+
try {
48+
return new Promise<KlepperResponse>((resolve, reject) => {
49+
const httpOptions = createHttpOptions(payload);
50+
const client = getGlobalClientData();
51+
52+
if (!httpOptions) {
53+
reject(new Error("NO HTTP OPTIONS"))
54+
}
55+
56+
if (!client) {
57+
reject(new Error("NO CLIENT DATA IN GLOBAL OBJECT"))
58+
}
59+
60+
const request = http.request(httpOptions, (res: KlepperIncomingMessage) => {
61+
res.setEncoding("utf8");
62+
63+
const status = statusFromCode(res?.statusCode as number);
64+
const isSuccess = status === RequestStatus.SUCCESS;
65+
66+
if (!isSuccess) {
67+
reject(new Error("HTTP ERROR: ${res.statusCode}"))
68+
} else {
69+
resolve({
70+
statusCode: res?.statusCode as number,
71+
statusMessage: "Event successfully sended to Klepper"
72+
})
73+
}
74+
75+
res.on("error", reject);
76+
});
77+
request.on("error", reject);
78+
79+
request.on('timeout', () => {
80+
request.destroy()
81+
reject(new Error("TIMEOUT"));
82+
})
83+
84+
request.write(JSON.stringify(data));
85+
request.end();
86+
})
87+
} catch (error) {
88+
throw new Error(""); //to properly handling
89+
}
5890
};

packages/commons/src/index.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import * as http from "./http";
2+
import * as global from "./global";
3+
4+
export { http, global };
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { KlepperGlobal } from "@klepper/transport";
2+
3+
declare global {
4+
var __KLEPPER__: KlepperGlobal;
5+
}
6+
export { };

packages/commons/test/http.test.ts

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { RequestPayload, KlepperEvent, KlepperRequest, KlepperResponse } from "@klepper/transport";
2+
import { sendEvent } from "../src/http"
3+
4+
describe("send()", () => {
5+
6+
let payload: RequestPayload;
7+
8+
const event: KlepperEvent = {
9+
date: new Date().getDate(),
10+
message: "OMG IT NOT WORK",
11+
type: "OMG",
12+
traces: [],
13+
requestData: {
14+
headers: {
15+
hello: "guys"
16+
},
17+
query: "/hello",
18+
method: "POST"
19+
}
20+
}
21+
22+
beforeEach(() => {
23+
payload = {
24+
data: event
25+
}
26+
});
27+
28+
it("should send a sample request", async () => {
29+
const response: KlepperResponse = await sendEvent(payload);
30+
31+
expect(response?.statusCode).toBeDefined();
32+
expect(response?.statusCode).toBe(200);
33+
});
34+
})

packages/config/tsconfig.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@
1414
"noImplicitReturns": true,
1515
"noImplicitThis": true,
1616
"noImplicitUseStrict": true,
17-
"noUnusedLocals": true,
18-
"noUnusedParameters": true,
17+
// "noUnusedLocals": true,
18+
// "noUnusedParameters": true,
1919
"preserveWatchOutput": true,
2020
"pretty": true,
2121
"sourceMap": true,

packages/node/src/helpers.ts

Lines changed: 13 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,23 @@
1-
import { BaseObject, KlepperIncomingMessage, KlepperRequest, KlepperResponse, KlepperStackFrame } from "@klepper/transport";
1+
import { BaseObject, KlepperIncomingMessage, KlepperRequest, Trace } from "@klepper/transport";
22
import { StackFrame } from "stack-trace";
33

4-
const mapStackFrames = (stackFrames: StackFrame[], onlyInternal: boolean = true) => {
5-
const frames: KlepperStackFrame[] = [];
6-
7-
const parse = (stackFrame: StackFrame): KlepperStackFrame => {
4+
const prepareStackTraces = (stackFrames: StackFrame[]): Trace[] => {
5+
const parseTraces = (frame: StackFrame): Trace => {
86
return {
9-
functionName: stackFrame.getFunctionName(),
10-
lineNumber: stackFrame.getLineNumber(),
11-
columnNumber: stackFrame.getColumnNumber(),
12-
fileName: stackFrame.getFileName(),
13-
methodName: stackFrame.getMethodName(),
7+
functionName: frame.getFunctionName(), //return absolut path, need to extract also function name
8+
rowNo: frame.getLineNumber(),
9+
colNo: frame.getColumnNumber(),
10+
fileName: frame.getFileName(),
11+
absolutePath: frame.getFunctionName(),
12+
isInternal: isInternal(frame.getFileName()),
1413
}
1514
}
1615

17-
stackFrames.map((f) => {
18-
if (onlyInternal) {
19-
const fileName = f.getFileName();
20-
const isInternal = fileName && !fileName.includes('node_modules') && !fileName.startsWith('/') && !fileName.startsWith('node:') && fileName.includes(":\\");
21-
22-
isInternal ? frames.push(parse(f)) : null;
23-
} else {
24-
frames.push(parse(f));
25-
}
26-
});
27-
28-
return frames;
16+
const traces = stackFrames.map((frame) => parseTraces(frame)) || [];
17+
return traces;
2918
}
3019

31-
const createPayloadFromRequest = (req: KlepperRequest, res: KlepperResponse) => {
32-
return {
33-
request: req,
34-
response: res,
35-
date: new Date().getDate()
36-
}
37-
}
20+
const isInternal = (fileName: string): boolean => !!fileName && !fileName.includes('node_modules') && !fileName.startsWith('/') && !fileName.startsWith('node:') && fileName.includes(":\\");
3821

3922
const mapRequestData = (req: BaseObject): KlepperRequest => {
4023
const headersData = req.headers || req.header || {};
@@ -93,9 +76,8 @@ const getProtocol = (req: KlepperIncomingMessage): string => {
9376

9477
export const helpers = {
9578
getIp,
96-
createPayloadFromRequest,
9779
mapRequestData,
98-
mapStackFrames,
80+
prepareStackTraces,
9981
getProtocol,
10082
isLocalhost
10183
}

0 commit comments

Comments
 (0)