@akanjs/nest 0.0.53 → 0.0.55
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/index.mjs +1 -0
- package/package.json +7 -1
- package/src/authGuards.mjs +119 -0
- package/src/authentication.mjs +82 -0
- package/src/authorization.mjs +45 -0
- package/src/cacheClient.mjs +24 -0
- package/src/databaseClient.mjs +30 -0
- package/src/decorators.mjs +144 -0
- package/src/exceptions.mjs +57 -0
- package/src/exporter.mjs +76 -0
- package/src/generateSecrets.mjs +109 -0
- package/src/index.mjs +22 -0
- package/src/interceptors.mjs +169 -0
- package/src/mongoose.mjs +60 -0
- package/src/pipes.mjs +118 -0
- package/src/redis-io.adapter.mjs +61 -0
- package/src/searchClient.mjs +46 -0
- package/src/sso.mjs +155 -0
- package/src/verifyPayment.mjs +17 -0
package/index.mjs
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./src";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@akanjs/nest",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.55",
|
|
4
4
|
"type": "commonjs",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -38,5 +38,11 @@
|
|
|
38
38
|
"rxjs": "^7.8.1",
|
|
39
39
|
"tunnel-ssh": "^5.2.0",
|
|
40
40
|
"ua-parser-js": "^1.0.40"
|
|
41
|
+
},
|
|
42
|
+
"exports": {
|
|
43
|
+
".": {
|
|
44
|
+
"require": "./index.js",
|
|
45
|
+
"import": "./index.mjs"
|
|
46
|
+
}
|
|
41
47
|
}
|
|
42
48
|
}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import { Injectable } from "@nestjs/common";
|
|
13
|
+
import { GqlExecutionContext } from "@nestjs/graphql";
|
|
14
|
+
import * as Auth from "./authorization";
|
|
15
|
+
const getRequest = (context) => {
|
|
16
|
+
const type = context.getType();
|
|
17
|
+
if (type === "ws")
|
|
18
|
+
throw new Error("Getting Request in Websocket is not allowed");
|
|
19
|
+
return type === "http" ? context.switchToHttp().getRequest() : GqlExecutionContext.create(context).getContext().req;
|
|
20
|
+
};
|
|
21
|
+
const getResponse = (context) => {
|
|
22
|
+
const type = context.getType();
|
|
23
|
+
if (type === "ws")
|
|
24
|
+
throw new Error("Getting Response in Websocket is not allowed");
|
|
25
|
+
return type === "http" ? context.switchToHttp().getResponse() : GqlExecutionContext.create(context).getContext().req.res;
|
|
26
|
+
};
|
|
27
|
+
const getArgs = (context) => {
|
|
28
|
+
const type = context.getType();
|
|
29
|
+
if (type === "ws")
|
|
30
|
+
throw new Error("Getting Args in Websocket is not allowed");
|
|
31
|
+
if (type === "graphql")
|
|
32
|
+
return GqlExecutionContext.create(context).getArgs();
|
|
33
|
+
else if (type === "http") {
|
|
34
|
+
const { params, query, body } = context.switchToHttp().getRequest();
|
|
35
|
+
return { ...params, ...query, ...body };
|
|
36
|
+
} else
|
|
37
|
+
throw new Error("Getting Args in Unknown context is not allowed");
|
|
38
|
+
};
|
|
39
|
+
const getSocket = (context) => {
|
|
40
|
+
const type = context.getType();
|
|
41
|
+
if (type !== "ws")
|
|
42
|
+
throw new Error("Getting Socket in Http or GraphQL is not allowed");
|
|
43
|
+
const socket = context.getArgByIndex(0);
|
|
44
|
+
return socket;
|
|
45
|
+
};
|
|
46
|
+
let Public = class {
|
|
47
|
+
canActivate(context) {
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
Public = __decorateClass([
|
|
52
|
+
Injectable()
|
|
53
|
+
], Public);
|
|
54
|
+
let None = class {
|
|
55
|
+
canActivate() {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
None = __decorateClass([
|
|
60
|
+
Injectable()
|
|
61
|
+
], None);
|
|
62
|
+
let Every = class {
|
|
63
|
+
canActivate(context) {
|
|
64
|
+
const { account } = getRequest(context);
|
|
65
|
+
return Auth.allow(account, ["user", "admin", "superAdmin"]);
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
Every = __decorateClass([
|
|
69
|
+
Injectable()
|
|
70
|
+
], Every);
|
|
71
|
+
let Owner = class {
|
|
72
|
+
canActivate(context) {
|
|
73
|
+
const { account } = getRequest(context);
|
|
74
|
+
return Auth.allow(account, ["user", "admin", "superAdmin"]);
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
Owner = __decorateClass([
|
|
78
|
+
Injectable()
|
|
79
|
+
], Owner);
|
|
80
|
+
let Admin = class {
|
|
81
|
+
canActivate(context) {
|
|
82
|
+
const { account } = getRequest(context);
|
|
83
|
+
return Auth.allow(account, ["admin", "superAdmin"]);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
Admin = __decorateClass([
|
|
87
|
+
Injectable()
|
|
88
|
+
], Admin);
|
|
89
|
+
let SuperAdmin = class {
|
|
90
|
+
canActivate(context) {
|
|
91
|
+
const { account } = getRequest(context);
|
|
92
|
+
return Auth.allow(account, ["superAdmin"]);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
SuperAdmin = __decorateClass([
|
|
96
|
+
Injectable()
|
|
97
|
+
], SuperAdmin);
|
|
98
|
+
let User = class {
|
|
99
|
+
canActivate(context) {
|
|
100
|
+
const { account } = getRequest(context);
|
|
101
|
+
return Auth.allow(account, ["user"]);
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
User = __decorateClass([
|
|
105
|
+
Injectable()
|
|
106
|
+
], User);
|
|
107
|
+
export {
|
|
108
|
+
Admin,
|
|
109
|
+
Every,
|
|
110
|
+
None,
|
|
111
|
+
Owner,
|
|
112
|
+
Public,
|
|
113
|
+
SuperAdmin,
|
|
114
|
+
User,
|
|
115
|
+
getArgs,
|
|
116
|
+
getRequest,
|
|
117
|
+
getResponse,
|
|
118
|
+
getSocket
|
|
119
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { dayjs } from "@akanjs/base";
|
|
2
|
+
import { createParamDecorator, UnauthorizedException } from "@nestjs/common";
|
|
3
|
+
import UAParser from "ua-parser-js";
|
|
4
|
+
import { getRequest, getResponse } from "./authGuards";
|
|
5
|
+
const Account = createParamDecorator((option, context) => {
|
|
6
|
+
const { account } = getRequest(context);
|
|
7
|
+
return account;
|
|
8
|
+
});
|
|
9
|
+
const Self = createParamDecorator((option, context) => {
|
|
10
|
+
const { account } = getRequest(context);
|
|
11
|
+
const self = account.self;
|
|
12
|
+
if (!self && !option.nullable)
|
|
13
|
+
throw new UnauthorizedException("No or Invalid Account in Self (User)");
|
|
14
|
+
return self;
|
|
15
|
+
});
|
|
16
|
+
const Me = createParamDecorator((option, context) => {
|
|
17
|
+
const { account } = getRequest(context);
|
|
18
|
+
const me = account.me;
|
|
19
|
+
if (!me && !option.nullable)
|
|
20
|
+
throw new UnauthorizedException("No or Invalid Account in Me (Admin)");
|
|
21
|
+
return me;
|
|
22
|
+
});
|
|
23
|
+
const UserIp = createParamDecorator((option, context) => {
|
|
24
|
+
const req = getRequest(context);
|
|
25
|
+
const ip = req.ip;
|
|
26
|
+
if (!ip && !option.nullable)
|
|
27
|
+
throw new UnauthorizedException("Invalid IP");
|
|
28
|
+
return { ip };
|
|
29
|
+
});
|
|
30
|
+
const Access = createParamDecorator((option, context) => {
|
|
31
|
+
const req = getRequest(context);
|
|
32
|
+
const res = new UAParser(req.userAgent).getResult();
|
|
33
|
+
if (!req.userAgent && !option.nullable)
|
|
34
|
+
throw new UnauthorizedException("Invalid UserAgent");
|
|
35
|
+
return {
|
|
36
|
+
...req.geolocation ? JSON.parse(req.geolocation) : {},
|
|
37
|
+
osName: res.os.name,
|
|
38
|
+
osVersion: res.os.version,
|
|
39
|
+
browserName: res.browser.name,
|
|
40
|
+
browserVersion: res.browser.version,
|
|
41
|
+
mobileModel: res.device.model,
|
|
42
|
+
mobileVendor: res.device.vendor,
|
|
43
|
+
deviceType: res.device.type ?? "desktop",
|
|
44
|
+
at: dayjs(),
|
|
45
|
+
period: 0
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
const Req = createParamDecorator((option, context) => {
|
|
49
|
+
return getRequest(context);
|
|
50
|
+
});
|
|
51
|
+
const Res = createParamDecorator((option, context) => {
|
|
52
|
+
return getResponse(context);
|
|
53
|
+
});
|
|
54
|
+
const Ws = createParamDecorator((option, context) => {
|
|
55
|
+
const socket = context.getArgByIndex(0);
|
|
56
|
+
const { __subscribe__ } = context.getArgByIndex(1);
|
|
57
|
+
return {
|
|
58
|
+
socket,
|
|
59
|
+
subscribe: __subscribe__,
|
|
60
|
+
onDisconnect: (handler) => {
|
|
61
|
+
socket.on("disconnect", handler);
|
|
62
|
+
},
|
|
63
|
+
onSubscribe: (handler) => {
|
|
64
|
+
if (__subscribe__)
|
|
65
|
+
handler();
|
|
66
|
+
},
|
|
67
|
+
onUnsubscribe: (handler) => {
|
|
68
|
+
if (!__subscribe__)
|
|
69
|
+
handler();
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
});
|
|
73
|
+
export {
|
|
74
|
+
Access,
|
|
75
|
+
Account,
|
|
76
|
+
Me,
|
|
77
|
+
Req,
|
|
78
|
+
Res,
|
|
79
|
+
Self,
|
|
80
|
+
UserIp,
|
|
81
|
+
Ws
|
|
82
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { baseEnv } from "@akanjs/base";
|
|
2
|
+
import { defaultAccount } from "@akanjs/signal";
|
|
3
|
+
import { AuthenticationError } from "@nestjs/apollo";
|
|
4
|
+
import * as jwt from "jsonwebtoken";
|
|
5
|
+
const verifyToken = (secret, authorization) => {
|
|
6
|
+
const [type, token] = authorization?.split(" ") ?? [void 0, void 0];
|
|
7
|
+
if (!token || type !== "Bearer")
|
|
8
|
+
return defaultAccount;
|
|
9
|
+
try {
|
|
10
|
+
const account = jwt.verify(token, secret);
|
|
11
|
+
if (account.appName !== baseEnv.appName || account.environment !== baseEnv.environment)
|
|
12
|
+
return defaultAccount;
|
|
13
|
+
return {
|
|
14
|
+
__InternalArg__: "Account",
|
|
15
|
+
self: account.self && !account.self.removedAt ? account.self : void 0,
|
|
16
|
+
me: account.me && !account.me.removedAt ? account.me : void 0,
|
|
17
|
+
appName: account.appName,
|
|
18
|
+
environment: account.environment
|
|
19
|
+
};
|
|
20
|
+
} catch (e) {
|
|
21
|
+
return defaultAccount;
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
const allow = (account, roles, userId) => {
|
|
25
|
+
if (!account)
|
|
26
|
+
throw new AuthenticationError("No Authentication Account");
|
|
27
|
+
for (const role of roles) {
|
|
28
|
+
if (role === "user" && account.self?.roles.includes("user"))
|
|
29
|
+
return true;
|
|
30
|
+
else if (role === "admin" && account.me?.roles.includes("admin"))
|
|
31
|
+
return true;
|
|
32
|
+
else if (role === "superAdmin" && account.me?.roles.includes("superAdmin"))
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
throw new AuthenticationError(
|
|
36
|
+
`No Authentication With Roles: ${roles.join(", ")}, Your roles are ${[
|
|
37
|
+
...account.self?.roles ?? [],
|
|
38
|
+
...account.me?.roles ?? []
|
|
39
|
+
].join(", ")}${!account.self?.roles.length && !account.me?.roles.length ? " (No Roles)" : ""}`
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
export {
|
|
43
|
+
allow,
|
|
44
|
+
verifyToken
|
|
45
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import { Inject, Injectable } from "@nestjs/common";
|
|
13
|
+
let CacheClient = class {
|
|
14
|
+
redis;
|
|
15
|
+
};
|
|
16
|
+
__decorateClass([
|
|
17
|
+
Inject("REDIS_CLIENT")
|
|
18
|
+
], CacheClient.prototype, "redis", 2);
|
|
19
|
+
CacheClient = __decorateClass([
|
|
20
|
+
Injectable()
|
|
21
|
+
], CacheClient);
|
|
22
|
+
export {
|
|
23
|
+
CacheClient
|
|
24
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import { capitalize } from "@akanjs/common";
|
|
13
|
+
import { Injectable } from "@nestjs/common";
|
|
14
|
+
import { InjectConnection } from "@nestjs/mongoose";
|
|
15
|
+
let DatabaseClient = class {
|
|
16
|
+
connection;
|
|
17
|
+
getModel(modelName) {
|
|
18
|
+
const model = this.connection.models[capitalize(modelName)];
|
|
19
|
+
return model;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
__decorateClass([
|
|
23
|
+
InjectConnection()
|
|
24
|
+
], DatabaseClient.prototype, "connection", 2);
|
|
25
|
+
DatabaseClient = __decorateClass([
|
|
26
|
+
Injectable()
|
|
27
|
+
], DatabaseClient);
|
|
28
|
+
export {
|
|
29
|
+
DatabaseClient
|
|
30
|
+
};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import "reflect-metadata";
|
|
2
|
+
import { Cron as NestCron, Interval as NestInterval } from "@nestjs/schedule";
|
|
3
|
+
const Try = () => {
|
|
4
|
+
return function(target, key, descriptor) {
|
|
5
|
+
const originMethod = descriptor.value;
|
|
6
|
+
descriptor.value = async function(...args) {
|
|
7
|
+
try {
|
|
8
|
+
const result = await originMethod.apply(this, args);
|
|
9
|
+
return result;
|
|
10
|
+
} catch (e) {
|
|
11
|
+
this.logger?.warn(`${key} action error return: ${e}`);
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
};
|
|
15
|
+
};
|
|
16
|
+
const Cron = (cronTime, { lock = true, serverMode, enabled = true } = {}) => {
|
|
17
|
+
return function(target, key, descriptor) {
|
|
18
|
+
const originMethod = descriptor.value;
|
|
19
|
+
let isRunning = false;
|
|
20
|
+
descriptor.value = async function(...args) {
|
|
21
|
+
if (lock && isRunning)
|
|
22
|
+
return this.logger?.warn(`Cronjob-${key} is already running, skipped`);
|
|
23
|
+
try {
|
|
24
|
+
isRunning = true;
|
|
25
|
+
this.logger?.verbose(`Cron Job-${key} started`);
|
|
26
|
+
const res = await originMethod.apply(this, args);
|
|
27
|
+
this.logger?.verbose(`Cron Job-${key} finished`);
|
|
28
|
+
isRunning = false;
|
|
29
|
+
return res;
|
|
30
|
+
} catch (e) {
|
|
31
|
+
this.logger?.error(`Cron Job-${key} error return: ${e}`);
|
|
32
|
+
isRunning = false;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
if (!enabled)
|
|
36
|
+
return;
|
|
37
|
+
if (!serverMode || process.env.SERVER_MODE === "all" || serverMode === process.env.SERVER_MODE)
|
|
38
|
+
NestCron(cronTime)(target, key, descriptor);
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
const getIntervalMetaMap = (prototype) => {
|
|
42
|
+
return Reflect.getMetadata("serviceInterval", prototype) ?? /* @__PURE__ */ new Map();
|
|
43
|
+
};
|
|
44
|
+
const setIntervalMetaMap = (prototype, intervalMetaMap) => {
|
|
45
|
+
Reflect.defineMetadata("serviceInterval", intervalMetaMap, prototype);
|
|
46
|
+
};
|
|
47
|
+
const Interval = (ms, { lock = true, serverMode, enabled = true } = {}) => {
|
|
48
|
+
return function(target, key, descriptor) {
|
|
49
|
+
const intervalMetaMap = getIntervalMetaMap(target);
|
|
50
|
+
if (intervalMetaMap.has(key))
|
|
51
|
+
return descriptor;
|
|
52
|
+
intervalMetaMap.set(key, descriptor.value);
|
|
53
|
+
setIntervalMetaMap(target, intervalMetaMap);
|
|
54
|
+
const originMethod = descriptor.value;
|
|
55
|
+
let isRunning = false;
|
|
56
|
+
descriptor.value = async function(...args) {
|
|
57
|
+
if (lock && isRunning)
|
|
58
|
+
return this.logger?.warn(`Cronjob-${key} is already running, skipped`);
|
|
59
|
+
try {
|
|
60
|
+
isRunning = true;
|
|
61
|
+
this.logger?.verbose(`Interval Job-${key} started`);
|
|
62
|
+
const res = await originMethod.apply(this, args);
|
|
63
|
+
this.logger?.verbose(`Interval Job-${key} finished`);
|
|
64
|
+
isRunning = false;
|
|
65
|
+
return res;
|
|
66
|
+
} catch (e) {
|
|
67
|
+
this.logger?.error(`Cronjob-${key} error return: ${e}`);
|
|
68
|
+
isRunning = false;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
if (!enabled)
|
|
72
|
+
return;
|
|
73
|
+
if (!serverMode || process.env.SERVER_MODE === "all" || serverMode === process.env.SERVER_MODE)
|
|
74
|
+
NestInterval(ms)(target, key, descriptor);
|
|
75
|
+
};
|
|
76
|
+
};
|
|
77
|
+
const Transaction = () => {
|
|
78
|
+
return function(target, key, descriptor) {
|
|
79
|
+
const originMethod = descriptor.value;
|
|
80
|
+
descriptor.value = function(...args) {
|
|
81
|
+
if (!this.connection)
|
|
82
|
+
throw new Error(`No Connection in function ${key}`);
|
|
83
|
+
return new Promise((resolve, reject) => {
|
|
84
|
+
this.connection.transaction(async () => {
|
|
85
|
+
const res = await originMethod.apply(this, args);
|
|
86
|
+
resolve(res);
|
|
87
|
+
}).catch(reject);
|
|
88
|
+
});
|
|
89
|
+
};
|
|
90
|
+
return descriptor;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
const Cache = (timeout = 1e3, getCacheKey) => {
|
|
94
|
+
return function(target, key, descriptor) {
|
|
95
|
+
const originMethod = descriptor.value;
|
|
96
|
+
const cacheMap = /* @__PURE__ */ new Map();
|
|
97
|
+
const timerMap = /* @__PURE__ */ new Map();
|
|
98
|
+
descriptor.value = async function(...args) {
|
|
99
|
+
const classType = this.__model ? "doc" : this.__databaseModel ? "service" : "class";
|
|
100
|
+
const model = this.__model ?? this.__databaseModel?.__model;
|
|
101
|
+
const cache = this.__cache ?? this.__databaseModel?.__cache;
|
|
102
|
+
const getCacheKeyFn = getCacheKey ?? JSON.stringify;
|
|
103
|
+
const cacheKey = `${classType}:${model.modelName}:${key}:${getCacheKeyFn(...args)}`;
|
|
104
|
+
const getCache = async (cacheKey2) => {
|
|
105
|
+
if (classType === "class")
|
|
106
|
+
return cacheMap.get(cacheKey2);
|
|
107
|
+
const cached = await cache.get(cacheKey2);
|
|
108
|
+
if (cached)
|
|
109
|
+
return JSON.parse(cached);
|
|
110
|
+
return null;
|
|
111
|
+
};
|
|
112
|
+
const setCache = async (cacheKey2, value) => {
|
|
113
|
+
if (classType === "class") {
|
|
114
|
+
const existingTimer = timerMap.get(cacheKey2);
|
|
115
|
+
if (existingTimer)
|
|
116
|
+
clearTimeout(existingTimer);
|
|
117
|
+
cacheMap.set(cacheKey2, value);
|
|
118
|
+
const timer = setTimeout(() => {
|
|
119
|
+
cacheMap.delete(cacheKey2);
|
|
120
|
+
timerMap.delete(cacheKey2);
|
|
121
|
+
}, timeout);
|
|
122
|
+
timerMap.set(cacheKey2, timer);
|
|
123
|
+
} else
|
|
124
|
+
await cache.set(cacheKey2, JSON.stringify(value), { PX: timeout });
|
|
125
|
+
};
|
|
126
|
+
const cachedData = await getCache(cacheKey);
|
|
127
|
+
if (cachedData) {
|
|
128
|
+
this.logger?.trace(`${model.modelName} cache hit: ${cacheKey}`);
|
|
129
|
+
return cachedData;
|
|
130
|
+
}
|
|
131
|
+
const result = await originMethod.apply(this, args);
|
|
132
|
+
await setCache(cacheKey, result);
|
|
133
|
+
this.logger?.trace(`${model.modelName} cache set: ${cacheKey}`);
|
|
134
|
+
return result;
|
|
135
|
+
};
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
export {
|
|
139
|
+
Cache,
|
|
140
|
+
Cron,
|
|
141
|
+
Interval,
|
|
142
|
+
Transaction,
|
|
143
|
+
Try
|
|
144
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result)
|
|
9
|
+
__defProp(target, key, result);
|
|
10
|
+
return result;
|
|
11
|
+
};
|
|
12
|
+
import { Logger } from "@akanjs/common";
|
|
13
|
+
import { Catch, HttpException } from "@nestjs/common";
|
|
14
|
+
let AllExceptionsFilter = class {
|
|
15
|
+
logger = new Logger("Exception Filter");
|
|
16
|
+
catch(exception, host) {
|
|
17
|
+
if (host.getType() !== "http") {
|
|
18
|
+
const gqlArgs = host.getArgByIndex(1);
|
|
19
|
+
const gqlReq = host.getArgByIndex(3);
|
|
20
|
+
const reqType2 = gqlReq?.parentType?.name ?? "unknown";
|
|
21
|
+
const reqName2 = gqlReq?.fieldName ?? "unknown";
|
|
22
|
+
this.logger.error(
|
|
23
|
+
`GraphQL Error
|
|
24
|
+
Request: ${reqType2}-${reqName2}
|
|
25
|
+
Args: ${JSON.stringify(gqlArgs, null, 2)}
|
|
26
|
+
${exception.stack}`
|
|
27
|
+
);
|
|
28
|
+
throw exception;
|
|
29
|
+
}
|
|
30
|
+
const ctx = host.switchToHttp();
|
|
31
|
+
const res = ctx.getResponse();
|
|
32
|
+
const req = ctx.getRequest();
|
|
33
|
+
const reqType = req.method;
|
|
34
|
+
const reqName = req.url;
|
|
35
|
+
const status = exception instanceof HttpException ? exception.getStatus() : null;
|
|
36
|
+
if (status) {
|
|
37
|
+
res.status(status).json({
|
|
38
|
+
statusCode: status,
|
|
39
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
40
|
+
path: req.url,
|
|
41
|
+
message: exception instanceof HttpException ? exception.getResponse() : exception.message
|
|
42
|
+
});
|
|
43
|
+
this.logger.error(
|
|
44
|
+
`Http Error: ${status}
|
|
45
|
+
Request: ${reqType}-${reqName}
|
|
46
|
+
Body: ${JSON.stringify(req.body, null, 2)}
|
|
47
|
+
${exception.stack}`
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
AllExceptionsFilter = __decorateClass([
|
|
53
|
+
Catch()
|
|
54
|
+
], AllExceptionsFilter);
|
|
55
|
+
export {
|
|
56
|
+
AllExceptionsFilter
|
|
57
|
+
};
|
package/src/exporter.mjs
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
const objPath = (o, p) => p.split(".").reduce((a, v) => a[v], o);
|
|
3
|
+
class FileSystem {
|
|
4
|
+
filename = "";
|
|
5
|
+
dirname = "./";
|
|
6
|
+
writeStream;
|
|
7
|
+
constructor(dirname = "./", filename = "") {
|
|
8
|
+
this.dirname = dirname;
|
|
9
|
+
this.filename = filename;
|
|
10
|
+
}
|
|
11
|
+
async init() {
|
|
12
|
+
return new Promise((resolve, reject) => {
|
|
13
|
+
fs.mkdirSync(this.dirname, { recursive: true });
|
|
14
|
+
const writeStream = fs.createWriteStream(`${this.dirname}/${this.filename}.csv`);
|
|
15
|
+
if (!writeStream) {
|
|
16
|
+
reject(new Error("No WriteStream"));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
writeStream.once(`open`, () => {
|
|
20
|
+
this.writeStream = writeStream;
|
|
21
|
+
resolve(writeStream);
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
write(body) {
|
|
26
|
+
if (!this.writeStream)
|
|
27
|
+
throw new Error("no write stream");
|
|
28
|
+
return this.writeStream.write(`${body.replace(/\n/g, "")}
|
|
29
|
+
`);
|
|
30
|
+
}
|
|
31
|
+
// async finish() {}
|
|
32
|
+
}
|
|
33
|
+
const exportToCsv = async ({ items, path, fields, delimiter, options }) => {
|
|
34
|
+
return new Promise((resolve, reject) => {
|
|
35
|
+
const dirs = path.split("/");
|
|
36
|
+
if (dirs.length > 1) {
|
|
37
|
+
const dirname = dirs.slice(-1).join("/");
|
|
38
|
+
if (!fs.existsSync(dirname))
|
|
39
|
+
fs.mkdirSync(dirname, { recursive: true });
|
|
40
|
+
}
|
|
41
|
+
if (!fields)
|
|
42
|
+
throw new Error("Fields Required");
|
|
43
|
+
const writeStream = !options?.append && fs.createWriteStream(path);
|
|
44
|
+
const header = fields.reduce((acc, cur) => acc + (delimiter ?? `,`) + cur) + `
|
|
45
|
+
`;
|
|
46
|
+
if (!writeStream) {
|
|
47
|
+
reject(new Error("No WriteStream"));
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
writeStream.once(`open`, () => {
|
|
51
|
+
writeStream.write(header);
|
|
52
|
+
for (const item of items) {
|
|
53
|
+
const data = fields.map((field) => objPath(item, field) ?? null).map((field) => String(field).replace(/\n/g, "").replace(/,/g, ""));
|
|
54
|
+
const body = data.reduce((acc, cur) => acc + (delimiter ?? `,`) + cur) + `
|
|
55
|
+
`;
|
|
56
|
+
if (options?.append)
|
|
57
|
+
fs.appendFileSync(path, body);
|
|
58
|
+
}
|
|
59
|
+
resolve();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const exportToJson = (items, localPath) => {
|
|
64
|
+
const dirname = localPath.split("/").slice(0, -1).join("/");
|
|
65
|
+
if (!fs.existsSync(dirname))
|
|
66
|
+
fs.mkdirSync(dirname, { recursive: true });
|
|
67
|
+
fs.writeFileSync(localPath, JSON.stringify(items));
|
|
68
|
+
};
|
|
69
|
+
const readJson = (localPath) => JSON.parse(fs.readFileSync(localPath).toString("utf-8"));
|
|
70
|
+
export {
|
|
71
|
+
FileSystem,
|
|
72
|
+
exportToCsv,
|
|
73
|
+
exportToJson,
|
|
74
|
+
objPath,
|
|
75
|
+
readJson
|
|
76
|
+
};
|