@tickrorg/common 1.0.16 → 1.0.18
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/dist/services/kafka.d.ts +1 -1
- package/dist/services/kafka.d.ts.map +1 -1
- package/dist/services/kafka.js +2 -2
- package/dist/services/kafka.js.map +1 -1
- package/dist/services/token.d.ts +9 -4
- package/dist/services/token.d.ts.map +1 -1
- package/dist/services/token.js +40 -35
- package/dist/services/token.js.map +1 -1
- package/dist/types/events.d.ts +1 -1
- package/dist/types/events.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/services/kafka.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Producer, Consumer } from "kafkajs";
|
|
|
2
2
|
declare class KafkaService {
|
|
3
3
|
private kafka;
|
|
4
4
|
private producer;
|
|
5
|
-
connect(broker: string): Promise<void>;
|
|
5
|
+
connect(broker: string, clientId: string): Promise<void>;
|
|
6
6
|
getConsumer(groupId: string, config?: any): Consumer;
|
|
7
7
|
getProducer(): Producer;
|
|
8
8
|
close(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kafka.d.ts","sourceRoot":"","sources":["../../src/services/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,QAAQ,EAAE,QAAQ,EAAY,MAAM,SAAS,CAAC;AAE9D,cAAM,YAAY;IAChB,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,QAAQ,CAAyB;IAEnC,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"kafka.d.ts","sourceRoot":"","sources":["../../src/services/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,QAAQ,EAAE,QAAQ,EAAY,MAAM,SAAS,CAAC;AAE9D,cAAM,YAAY;IAChB,OAAO,CAAC,KAAK,CAAsB;IACnC,OAAO,CAAC,QAAQ,CAAyB;IAEnC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9D,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,GAAG,QAAQ;IAKpD,WAAW,IAAI,QAAQ;IAKjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAQ7B;AAED,eAAO,MAAM,WAAW,cAAqB,CAAC"}
|
package/dist/services/kafka.js
CHANGED
|
@@ -4,11 +4,11 @@ class KafkaService {
|
|
|
4
4
|
this.kafka = null;
|
|
5
5
|
this.producer = null;
|
|
6
6
|
}
|
|
7
|
-
async connect(broker) {
|
|
7
|
+
async connect(broker, clientId) {
|
|
8
8
|
if (this.producer)
|
|
9
9
|
return;
|
|
10
10
|
this.kafka = new Kafka({
|
|
11
|
-
clientId
|
|
11
|
+
clientId,
|
|
12
12
|
brokers: [broker],
|
|
13
13
|
logLevel: logLevel.ERROR,
|
|
14
14
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kafka.js","sourceRoot":"","sources":["../../src/services/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAsB,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9D,MAAM,YAAY;IAAlB;QACU,UAAK,GAAiB,IAAI,CAAC;QAC3B,aAAQ,GAAoB,IAAI,CAAC;IAkC3C,CAAC;IAhCC,KAAK,CAAC,OAAO,CAAC,MAAc;
|
|
1
|
+
{"version":3,"file":"kafka.js","sourceRoot":"","sources":["../../src/services/kafka.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAsB,QAAQ,EAAE,MAAM,SAAS,CAAC;AAE9D,MAAM,YAAY;IAAlB;QACU,UAAK,GAAiB,IAAI,CAAC;QAC3B,aAAQ,GAAoB,IAAI,CAAC;IAkC3C,CAAC;IAhCC,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,QAAgB;QAC5C,IAAI,IAAI,CAAC,QAAQ;YAAE,OAAO;QAE1B,IAAI,CAAC,KAAK,GAAG,IAAI,KAAK,CAAC;YACrB,QAAQ;YACR,OAAO,EAAE,CAAC,MAAM,CAAC;YACjB,QAAQ,EAAE,QAAQ,CAAC,KAAK;SACzB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;QACtC,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC;IAChC,CAAC;IAGD,WAAW,CAAC,OAAe,EAAE,MAAY;QACvC,IAAI,CAAC,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC1D,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,WAAW;QACT,IAAI,CAAC,IAAI,CAAC,QAAQ;YAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;QAC7D,OAAO,IAAI,CAAC,QAAQ,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,QAAQ,EAAE,UAAU,EAAE,CAAC;QACpC,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;YACrB,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;IACH,CAAC;CACF;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,YAAY,EAAE,CAAC"}
|
package/dist/services/token.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
1
|
import { Response, Request } from "express";
|
|
2
2
|
export interface TokenPayload {
|
|
3
|
-
|
|
3
|
+
_id: string;
|
|
4
4
|
email: string;
|
|
5
5
|
type: number;
|
|
6
6
|
}
|
|
7
7
|
export declare class Token {
|
|
8
|
+
private static readonly ACCESS_TOKEN_EXPIRY;
|
|
9
|
+
private static readonly REFRESH_TOKEN_EXPIRY;
|
|
10
|
+
private static readonly ACCESS_COOKIE_PATH;
|
|
11
|
+
private static readonly REFRESH_COOKIE_PATH;
|
|
8
12
|
static generateAccess(payload: TokenPayload): string;
|
|
9
|
-
static generateRefresh(
|
|
13
|
+
static generateRefresh(): string;
|
|
14
|
+
static hashRefresh(token: string): string;
|
|
10
15
|
static generatePair(payload: TokenPayload): {
|
|
11
16
|
accessToken: string;
|
|
12
17
|
refreshToken: string;
|
|
18
|
+
refreshTokenHash: string;
|
|
13
19
|
};
|
|
14
20
|
static verifyAccess(token: string): TokenPayload | null;
|
|
15
|
-
static
|
|
16
|
-
static refresh(req: Request, res: Response): TokenPayload | null;
|
|
21
|
+
static getRefreshFromRequest(req: Request): string | null;
|
|
17
22
|
static fromRequest(req: Request): TokenPayload | null;
|
|
18
23
|
static setCookies(res: Response, accessToken: string, refreshToken: string): void;
|
|
19
24
|
static clearCookies(res: Response): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/services/token.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../src/services/token.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAE5C,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,KAAK;IAChB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAS;IACpD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,oBAAoB,CAA2B;IAEvE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAO;IACjD,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,mBAAmB,CAAmB;IAE9D,MAAM,CAAC,cAAc,CAAC,OAAO,EAAE,YAAY,GAAG,MAAM;IAOpD,MAAM,CAAC,eAAe,IAAI,MAAM;IAIhC,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAIzC,MAAM,CAAC,YAAY,CAAC,OAAO,EAAE,YAAY;;;;;IAUzC,MAAM,CAAC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,IAAI;IA0BvD,MAAM,CAAC,qBAAqB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI;IAMzD,MAAM,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,GAAG,YAAY,GAAG,IAAI;IAQrD,MAAM,CAAC,UAAU,CACf,GAAG,EAAE,QAAQ,EACb,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM,GACnB,IAAI;IAkBP,MAAM,CAAC,YAAY,CAAC,GAAG,EAAE,QAAQ,GAAG,IAAI;CASzC"}
|
package/dist/services/token.js
CHANGED
|
@@ -1,52 +1,49 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
1
2
|
import jwt from "jsonwebtoken";
|
|
2
3
|
export class Token {
|
|
3
4
|
static generateAccess(payload) {
|
|
4
|
-
|
|
5
|
-
|
|
5
|
+
return jwt.sign(payload, process.env.JWT_ACCESS_KEY, {
|
|
6
|
+
expiresIn: Token.ACCESS_TOKEN_EXPIRY,
|
|
7
|
+
algorithm: "HS256",
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
static generateRefresh() {
|
|
11
|
+
return crypto.randomBytes(32).toString("base64url");
|
|
6
12
|
}
|
|
7
|
-
static
|
|
8
|
-
return
|
|
13
|
+
static hashRefresh(token) {
|
|
14
|
+
return crypto.createHash("sha256").update(token).digest("hex");
|
|
9
15
|
}
|
|
10
16
|
static generatePair(payload) {
|
|
17
|
+
const refreshToken = Token.generateRefresh();
|
|
11
18
|
return {
|
|
12
19
|
accessToken: Token.generateAccess(payload),
|
|
13
|
-
refreshToken
|
|
20
|
+
refreshToken,
|
|
21
|
+
refreshTokenHash: Token.hashRefresh(refreshToken),
|
|
14
22
|
};
|
|
15
23
|
}
|
|
16
24
|
static verifyAccess(token) {
|
|
17
25
|
try {
|
|
18
|
-
|
|
26
|
+
const decoded = jwt.verify(token, process.env.JWT_ACCESS_KEY, { algorithms: ["HS256"] });
|
|
27
|
+
if (typeof decoded === "string")
|
|
28
|
+
return null;
|
|
29
|
+
const { _id, email, type } = decoded;
|
|
30
|
+
if (typeof _id !== "string" ||
|
|
31
|
+
typeof email !== "string" ||
|
|
32
|
+
typeof type !== "number") {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return { _id, email, type };
|
|
19
36
|
}
|
|
20
37
|
catch {
|
|
21
38
|
return null;
|
|
22
39
|
}
|
|
23
40
|
}
|
|
24
|
-
static
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
catch {
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
static refresh(req, res) {
|
|
33
|
-
const refreshToken = req.cookies.refresh_token;
|
|
34
|
-
if (!refreshToken)
|
|
35
|
-
return null;
|
|
36
|
-
const payload = Token.verifyRefresh(refreshToken);
|
|
37
|
-
if (!payload)
|
|
38
|
-
return null;
|
|
39
|
-
const { id, email, type } = payload;
|
|
40
|
-
const { accessToken, refreshToken: newRefreshToken } = Token.generatePair({
|
|
41
|
-
id,
|
|
42
|
-
email,
|
|
43
|
-
type: type,
|
|
44
|
-
});
|
|
45
|
-
Token.setCookies(res, accessToken, newRefreshToken);
|
|
46
|
-
return { id, email, type };
|
|
41
|
+
static getRefreshFromRequest(req) {
|
|
42
|
+
const token = req.cookies?.refresh_token;
|
|
43
|
+
return typeof token === "string" ? token : null;
|
|
47
44
|
}
|
|
48
45
|
static fromRequest(req) {
|
|
49
|
-
const token = req.cookies
|
|
46
|
+
const token = req.cookies?.access_token;
|
|
50
47
|
if (!token)
|
|
51
48
|
return null;
|
|
52
49
|
return Token.verifyAccess(token);
|
|
@@ -57,19 +54,27 @@ export class Token {
|
|
|
57
54
|
secure: process.env.NODE_ENV === "production",
|
|
58
55
|
sameSite: "lax",
|
|
59
56
|
maxAge: 15 * 60 * 1000,
|
|
60
|
-
path:
|
|
57
|
+
path: Token.ACCESS_COOKIE_PATH,
|
|
61
58
|
});
|
|
62
59
|
res.cookie("refresh_token", refreshToken, {
|
|
63
60
|
httpOnly: true,
|
|
64
61
|
secure: process.env.NODE_ENV === "production",
|
|
65
62
|
sameSite: "lax",
|
|
66
|
-
maxAge:
|
|
67
|
-
path:
|
|
63
|
+
maxAge: Token.REFRESH_TOKEN_EXPIRY,
|
|
64
|
+
path: Token.REFRESH_COOKIE_PATH,
|
|
68
65
|
});
|
|
69
66
|
}
|
|
70
67
|
static clearCookies(res) {
|
|
71
|
-
res.clearCookie("access_token"
|
|
72
|
-
|
|
68
|
+
res.clearCookie("access_token", {
|
|
69
|
+
path: Token.ACCESS_COOKIE_PATH,
|
|
70
|
+
});
|
|
71
|
+
res.clearCookie("refresh_token", {
|
|
72
|
+
path: Token.REFRESH_COOKIE_PATH,
|
|
73
|
+
});
|
|
73
74
|
}
|
|
74
75
|
}
|
|
76
|
+
Token.ACCESS_TOKEN_EXPIRY = "15m";
|
|
77
|
+
Token.REFRESH_TOKEN_EXPIRY = 7 * 24 * 60 * 60 * 1000;
|
|
78
|
+
Token.ACCESS_COOKIE_PATH = "/";
|
|
79
|
+
Token.REFRESH_COOKIE_PATH = "/auth/refresh";
|
|
75
80
|
//# sourceMappingURL=token.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/services/token.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAC;AAS/B,MAAM,OAAO,KAAK;
|
|
1
|
+
{"version":3,"file":"token.js","sourceRoot":"","sources":["../../src/services/token.ts"],"names":[],"mappings":"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"}
|
package/dist/types/events.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;CACjB;AACD,oBAAY,aAAa;IACvB,aAAa,mBAAmB;IAChC,aAAa,mBAAmB;IAChC,YAAY,kBAAkB;IAC9B,cAAc,oBAAoB;IAClC,gBAAgB,sBAAsB;IACtC,WAAW,iBAAiB;IAC5B,WAAW,iBAAiB;CAC7B;AAED,MAAM,WAAW,KAAK,CAAC,CAAC,GAAG,OAAO;IAChC,OAAO,EAAE,aAAa,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC;CACT"}
|