@triproject/nestjs-core 1.0.5 → 1.0.13

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.
Files changed (55) hide show
  1. package/.swcrc +24 -0
  2. package/README.md +297 -38
  3. package/dist/bootstrap.js +1 -43
  4. package/dist/config.js +1 -50
  5. package/dist/controllers/controller.js +1 -56
  6. package/dist/drivers/cache/cache.d.ts +1 -1
  7. package/dist/drivers/cache/cache.driver.js +1 -22
  8. package/dist/drivers/cache/cache.js +1 -92
  9. package/dist/drivers/cache/index.js +1 -19
  10. package/dist/drivers/cache/redis.js +1 -52
  11. package/dist/drivers/db/db.helper.js +1 -217
  12. package/dist/drivers/db/db.module.js +1 -44
  13. package/dist/drivers/db/db.service.js +1 -49
  14. package/dist/drivers/db/index.js +1 -21
  15. package/dist/drivers/db/migration.d.ts +133 -5
  16. package/dist/drivers/db/migration.js +1 -81
  17. package/dist/drivers/db/repository.js +1 -255
  18. package/dist/drivers/encryptions/encryption.js +1 -50
  19. package/dist/drivers/encryptions/encryption.module.js +1 -24
  20. package/dist/drivers/encryptions/index.js +1 -19
  21. package/dist/drivers/encryptions/jwt.js +1 -46
  22. package/dist/drivers/encryptions/password-hash.js +1 -38
  23. package/dist/drivers/encryptions/snap.signature.js +1 -110
  24. package/dist/drivers/logger/app.logger.js +2 -183
  25. package/dist/drivers/logger/cloudwatch.d.ts +18 -0
  26. package/dist/drivers/logger/cloudwatch.js +1 -0
  27. package/dist/drivers/logger/cloudwatch.logger.d.ts +1 -0
  28. package/dist/drivers/logger/cloudwatch.logger.js +1 -0
  29. package/dist/drivers/logger/index.js +1 -18
  30. package/dist/drivers/logger/slack.logger.js +1 -24
  31. package/dist/drivers/mail/index.js +1 -22
  32. package/dist/drivers/mail/mail-template.js +8 -41
  33. package/dist/drivers/mail/mail.config.js +1 -4
  34. package/dist/drivers/mail/mail.js +13 -73
  35. package/dist/drivers/mail/mail.module.js +1 -26
  36. package/dist/drivers/mail/mail.queue.js +1 -37
  37. package/dist/drivers/mail/mailer.js +1 -62
  38. package/dist/drivers/notifications/index.js +1 -21
  39. package/dist/drivers/notifications/notification.config.js +1 -4
  40. package/dist/drivers/notifications/notification.module.js +1 -25
  41. package/dist/drivers/notifications/notification.queue.js +1 -37
  42. package/dist/drivers/notifications/push-notification.js +1 -75
  43. package/dist/drivers/notifications/slack.js +1 -95
  44. package/dist/drivers/queues/app.queue.js +1 -66
  45. package/dist/drivers/queues/index.js +1 -18
  46. package/dist/drivers/queues/queue.module.js +1 -41
  47. package/dist/helpers/exception.helper.js +1 -71
  48. package/dist/helpers/http.helper.js +1 -134
  49. package/dist/helpers/swagger.helper.js +1 -287
  50. package/dist/helpers/totp.helper.js +1 -30
  51. package/dist/index.d.ts +1 -0
  52. package/dist/index.js +1 -24
  53. package/dist/middlewares/log.middleware.js +1 -59
  54. package/dist/types.d.js +1 -0
  55. package/package.json +27 -14
@@ -1,38 +1 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.PasswordHash = void 0;
10
- const common_1 = require("@nestjs/common");
11
- const crypto_1 = require("crypto");
12
- const config_1 = require("../../config");
13
- let PasswordHash = class PasswordHash {
14
- DIGEST = 'sha512';
15
- ITERATIONS = 100000;
16
- KEYLEN = 64;
17
- SALT_LENGTH = 8;
18
- HASH_ENCODING = 'base64';
19
- HASH_DELIMITER = '.';
20
- _hash(password, salt) {
21
- return (0, crypto_1.pbkdf2Sync)(config_1.PASSWORD_HASH_SECRET + password, salt, this.ITERATIONS, this.KEYLEN, this.DIGEST);
22
- }
23
- sign(password) {
24
- const salt = (0, crypto_1.randomBytes)(this.SALT_LENGTH).toString('hex');
25
- const key = this._hash(password, salt).toString(this.HASH_ENCODING);
26
- return `$${salt}${this.HASH_DELIMITER}$${key}`;
27
- }
28
- verify(password, passwordHash) {
29
- const [salt, key] = passwordHash.replace('$', '').split(this.HASH_DELIMITER);
30
- const derivedKey = this._hash(password, salt);
31
- const storedHashBuffer = Buffer.from(key, this.HASH_ENCODING);
32
- return (0, crypto_1.timingSafeEqual)(storedHashBuffer, derivedKey);
33
- }
34
- };
35
- exports.PasswordHash = PasswordHash;
36
- exports.PasswordHash = PasswordHash = __decorate([
37
- (0, common_1.Injectable)()
38
- ], PasswordHash);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"PasswordHash",{enumerable:!0,get:function(){return PasswordHash}});let _common=require("@nestjs/common"),_crypto=require("crypto"),_config=require("../../config");let PasswordHash=class PasswordHash{DIGEST="sha512";ITERATIONS=1e5;KEYLEN=64;SALT_LENGTH=8;HASH_ENCODING="base64";HASH_DELIMITER=".";_hash(password,salt){return(0,_crypto.pbkdf2Sync)(_config.PASSWORD_HASH_SECRET+password,salt,this.ITERATIONS,this.KEYLEN,this.DIGEST)}sign(password){let salt=(0,_crypto.randomBytes)(this.SALT_LENGTH).toString("hex"),key=this._hash(password,salt).toString(this.HASH_ENCODING);return`$${salt}${this.HASH_DELIMITER}$${key}`}verify(password,passwordHash){let[salt,key]=passwordHash.replace("$","").split(this.HASH_DELIMITER),derivedKey=this._hash(password,salt),storedHashBuffer=Buffer.from(key,this.HASH_ENCODING);return(0,_crypto.timingSafeEqual)(storedHashBuffer,derivedKey)}};PasswordHash=function(decorators,target,key,desc){var d,c=arguments.length,r=c<3?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r}([(0,_common.Injectable)()],PasswordHash);
@@ -1,110 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.snapSignature = exports.SnapSignature = void 0;
4
- const helpers_1 = require("@triproject/helpers");
5
- const crypto_1 = require("crypto");
6
- class SnapSignature {
7
- sha256Encoding = 'base64';
8
- sha512Encoding = 'hex';
9
- minifiedObjectEncoding = 'hex';
10
- _signSHA256(stringToSign, privateKey) {
11
- const signer = (0, crypto_1.createSign)('SHA256');
12
- signer.update(stringToSign);
13
- return signer.sign((0, helpers_1.parsedKeyPair)(privateKey), this.sha256Encoding);
14
- }
15
- _verifySHA256WithRSA(stringToVerify, signature, publicKey) {
16
- const verifier = (0, crypto_1.createVerify)('SHA256');
17
- verifier.update(stringToVerify);
18
- return verifier.verify({
19
- key: (0, helpers_1.parsedKeyPair)(publicKey),
20
- padding: crypto_1.constants.RSA_PKCS1_PSS_PADDING,
21
- saltLength: 32,
22
- }, signature, this.sha256Encoding);
23
- }
24
- _verifySHA256(stringToVerify, signature, publicKey) {
25
- try {
26
- const verifier = (0, crypto_1.createVerify)('SHA256');
27
- verifier.update(stringToVerify);
28
- const isValid = verifier.verify((0, helpers_1.parsedKeyPair)(publicKey), signature, this.sha256Encoding);
29
- if (isValid)
30
- return true;
31
- return this._verifySHA256WithRSA(stringToVerify, signature, publicKey);
32
- }
33
- catch (error) {
34
- return false;
35
- }
36
- }
37
- _signSHA512(stringToSign, secret) {
38
- try {
39
- const hmac = (0, crypto_1.createHmac)('sha512', secret);
40
- hmac.update(stringToSign);
41
- return hmac.digest(this.sha256Encoding);
42
- }
43
- catch (error) {
44
- throw new Error('Error while signing data');
45
- }
46
- }
47
- _verifySHA512(stringToVerify, signature, secret) {
48
- const hmac = (0, crypto_1.createHmac)('sha512', secret);
49
- hmac.update(stringToVerify);
50
- const calculatedSignature = hmac.digest(this.sha512Encoding);
51
- return calculatedSignature === signature;
52
- }
53
- _reqBodySignatureString(params) {
54
- const stringToSign = [
55
- params?.method ?? 'POST',
56
- params.url,
57
- params.accessToken,
58
- this._minifyParams(params.body),
59
- params.timestamp,
60
- ].filter((d) => d);
61
- return stringToSign.join(':');
62
- }
63
- _minifyParams(object) {
64
- const minifiedRequestBody = typeof object === 'object' ? JSON.stringify(object) : object?.toString() ?? '';
65
- const sha256Hash = (0, crypto_1.createHash)('SHA256');
66
- sha256Hash.update(minifiedRequestBody);
67
- const sha256HashString = sha256Hash.digest(this.minifiedObjectEncoding);
68
- return sha256HashString.toLowerCase();
69
- }
70
- signBodySignature(params, secret) {
71
- return this._signSHA512(this._reqBodySignatureString(params), secret);
72
- }
73
- _verifyBodySignature(params, signature, secret) {
74
- return this._verifySHA512(this._reqBodySignatureString(params), signature, secret);
75
- }
76
- signAccessTokenSignature(params, secretKey) {
77
- const { client_id, timestamp } = params;
78
- const stringToSing = [client_id, timestamp];
79
- return this._signSHA256(stringToSing.join('|'), secretKey);
80
- }
81
- _verifyAccessTokenSignature(params, publicKey) {
82
- const { client_id, timestamp, signature } = params;
83
- if (!signature)
84
- return false;
85
- const stringToSing = [client_id, timestamp];
86
- return this._verifySHA256(stringToSing.join('|'), signature, publicKey);
87
- }
88
- middleware(secret, req) {
89
- if (!['POST', 'GET'].includes(req.method))
90
- throw new Error('Invalid request method');
91
- if (req.path?.includes('/access-token/b2b')) {
92
- const { 'client-id': client_id, 'x-timestamp': timestamp, 'x-signature': signature } = req.headers;
93
- const isValid = this._verifyAccessTokenSignature({ client_id, timestamp, signature }, secret);
94
- if (!isValid)
95
- throw new Error('Invalid signature');
96
- }
97
- const { 'x-timestamp': timestamp, 'x-signature': signature, accessToken } = req.headers;
98
- const isValid = this._verifyBodySignature({
99
- url: req.path,
100
- body: req.body,
101
- timestamp,
102
- method: req.method,
103
- accessToken: (accessToken ?? '')?.replace('Bearer ', ''),
104
- }, signature, secret);
105
- if (!isValid)
106
- throw new Error('Invalid signature');
107
- }
108
- }
109
- exports.SnapSignature = SnapSignature;
110
- exports.snapSignature = new SnapSignature();
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0});var target=exports,all={get SnapSignature(){return SnapSignature},get snapSignature(){return snapSignature}};for(var name in all)Object.defineProperty(target,name,{enumerable:!0,get:Object.getOwnPropertyDescriptor(all,name).get});let _helpers=require("@triproject/helpers"),_crypto=require("crypto");let SnapSignature=class SnapSignature{sha256Encoding="base64";sha512Encoding="hex";minifiedObjectEncoding="hex";_signSHA256(stringToSign,privateKey){let signer=(0,_crypto.createSign)("SHA256");return signer.update(stringToSign),signer.sign((0,_helpers.parsedKeyPair)(privateKey),this.sha256Encoding)}_verifySHA256WithRSA(stringToVerify,signature,publicKey){let verifier=(0,_crypto.createVerify)("SHA256");return verifier.update(stringToVerify),verifier.verify({key:(0,_helpers.parsedKeyPair)(publicKey),padding:_crypto.constants.RSA_PKCS1_PSS_PADDING,saltLength:32},signature,this.sha256Encoding)}_verifySHA256(stringToVerify,signature,publicKey){try{let verifier=(0,_crypto.createVerify)("SHA256");if(verifier.update(stringToVerify),verifier.verify((0,_helpers.parsedKeyPair)(publicKey),signature,this.sha256Encoding))return!0;return this._verifySHA256WithRSA(stringToVerify,signature,publicKey)}catch(error){return!1}}_signSHA512(stringToSign,secret){try{let hmac=(0,_crypto.createHmac)("sha512",secret);return hmac.update(stringToSign),hmac.digest(this.sha256Encoding)}catch(error){throw Error("Error while signing data")}}_verifySHA512(stringToVerify,signature,secret){let hmac=(0,_crypto.createHmac)("sha512",secret);return hmac.update(stringToVerify),hmac.digest(this.sha512Encoding)===signature}_reqBodySignatureString(params){return[params?.method??"POST",params.url,params.accessToken,this._minifyParams(params.body),params.timestamp].filter(d=>d).join(":")}_minifyParams(object){let minifiedRequestBody="object"==typeof object?JSON.stringify(object):object?.toString()??"",sha256Hash=(0,_crypto.createHash)("SHA256");return sha256Hash.update(minifiedRequestBody),sha256Hash.digest(this.minifiedObjectEncoding).toLowerCase()}signBodySignature(params,secret){return this._signSHA512(this._reqBodySignatureString(params),secret)}_verifyBodySignature(params,signature,secret){return this._verifySHA512(this._reqBodySignatureString(params),signature,secret)}signAccessTokenSignature(params,secretKey){let{client_id,timestamp}=params;return this._signSHA256([client_id,timestamp].join("|"),secretKey)}_verifyAccessTokenSignature(params,publicKey){let{client_id,timestamp,signature}=params;return!!signature&&this._verifySHA256([client_id,timestamp].join("|"),signature,publicKey)}middleware(secret,req){if(!["POST","GET"].includes(req.method))throw Error("Invalid request method");if(req.path?.includes("/access-token/b2b")){let{"client-id":client_id,"x-timestamp":timestamp,"x-signature":signature}=req.headers;if(!this._verifyAccessTokenSignature({client_id,timestamp,signature},secret))throw Error("Invalid signature")}let{"x-timestamp":timestamp,"x-signature":signature,accessToken}=req.headers;if(!this._verifyBodySignature({url:req.path,body:req.body,timestamp,method:req.method,accessToken:(accessToken??"")?.replace("Bearer ","")},signature,secret))throw Error("Invalid signature")}};let snapSignature=new SnapSignature;
@@ -1,183 +1,2 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.AppLogger = void 0;
7
- const common_1 = require("@nestjs/common");
8
- const helpers_1 = require("@triproject/helpers");
9
- const os_1 = __importDefault(require("os"));
10
- const util_1 = require("util");
11
- const config_1 = require("../../config");
12
- const slack_logger_1 = require("./slack.logger");
13
- const bgLog = (option, log) => {
14
- return (0, util_1.styleText)('reset', (0, util_1.styleText)('bold', (0, util_1.styleText)(option, (0, util_1.styleText)('black', ` ${log} `))));
15
- };
16
- const logWarnBg = (log) => bgLog('bgYellow', log);
17
- const logErrorBg = (log) => bgLog('bgRed', log);
18
- const logInfoBg = (log) => bgLog('bgGreen', log);
19
- const logDebugBg = (log) => bgLog('bgMagenta', log);
20
- const logWarn = (log) => (0, util_1.styleText)('yellow', log);
21
- const logError = (log) => (0, util_1.styleText)('red', log);
22
- class LoggerInit {
23
- host = os_1.default.hostname();
24
- slackError;
25
- constructor() {
26
- if (config_1.SLACK_ERROR_WEBHOOK_URL)
27
- this.slackError = new slack_logger_1.SlackLogger(config_1.SLACK_ERROR_WEBHOOK_URL);
28
- }
29
- }
30
- const loggerInit = new LoggerInit();
31
- class AppLogger extends common_1.ConsoleLogger {
32
- context;
33
- LOG_STACKS = 3;
34
- constructor(context = '') {
35
- super(context);
36
- this.context = context;
37
- }
38
- _notifyError(...args) {
39
- if (loggerInit.slackError)
40
- loggerInit.slackError.send(args);
41
- }
42
- excludeContexts = [
43
- 'RoutesResolver',
44
- 'InstanceLoader',
45
- 'RouterExplorer',
46
- 'Nest Application',
47
- 'Module',
48
- 'NestApplication',
49
- ];
50
- _excludeContext(context) {
51
- return this.excludeContexts.includes(context);
52
- }
53
- _sanitizePolicyData(object) {
54
- if (!object)
55
- return undefined;
56
- if (Array.isArray(object)) {
57
- return object.map((d) => (typeof d !== 'object' ? d : this._sanitizePolicyData(d)));
58
- }
59
- else {
60
- return Object.keys(object).reduce((acc, key) => {
61
- let value = object[key];
62
- if (helpers_1.sanitizeRequests.includes(key)) {
63
- // @ts-ignore
64
- value = '***';
65
- }
66
- else if (typeof value === 'object') {
67
- // @ts-ignore
68
- value = this._sanitizePolicyData(value);
69
- }
70
- return { ...acc, [key]: value };
71
- }, {});
72
- }
73
- }
74
- _formatBgLevel(level, ...args) {
75
- const msg = args.join(' ╱ ');
76
- switch (level) {
77
- case 'log':
78
- return logInfoBg(msg);
79
- case 'warn':
80
- return logWarnBg(msg);
81
- case 'error':
82
- return logErrorBg(msg);
83
- case 'fatal':
84
- return logErrorBg(msg);
85
- case 'debug':
86
- return logDebugBg(msg);
87
- default:
88
- return logInfoBg(msg);
89
- }
90
- }
91
- _formatException(error) {
92
- const stacks = (error?.stack ?? '')
93
- ?.split('\n')
94
- .map((o) => o.trim().replace?.(error.name + ': ', ''))
95
- .slice(0, config_1.NODE_ENV === 'development' ? undefined : this.LOG_STACKS);
96
- return (error?.name ?? 'UnknownErrorException') + ' ' + stacks.join(`\n`);
97
- }
98
- _parseMessage(arg) {
99
- if (arg instanceof Error)
100
- return ['error', this._formatException(arg)];
101
- if (typeof arg === 'object')
102
- return ['object', JSON.stringify(this._sanitizePolicyData(arg), null, 2)];
103
- return ['string', arg?.toString()];
104
- }
105
- _mapLog(level, ...args) {
106
- if (this._excludeContext(this.context) ||
107
- (typeof args[1] !== 'undefined' && this.excludeContexts.some((d) => args[1] === d))) {
108
- return;
109
- }
110
- const message = [];
111
- for (const arg of args?.flat()?.flat()) {
112
- if (!arg)
113
- continue;
114
- message.push(this._parseMessage(arg));
115
- }
116
- return {
117
- level,
118
- env: config_1.NODE_ENV.toUpperCase(),
119
- context: this.context ?? 'App Logger',
120
- timestamp: (0, helpers_1.dateUtil)().utc().format('YYYY-MM-DD HH:mm:ss.SSS'),
121
- host: loggerInit.host?.substring(0, 20),
122
- message,
123
- };
124
- }
125
- _formatConsoleError(error) {
126
- return error
127
- .split('\n')
128
- .map((d) => d.endsWith('Exception')
129
- ? d.replace(/(.*)Exception(.*)/, logErrorBg('$1Exception') + logError('$2'))
130
- : logError(d))
131
- .join('\n ');
132
- }
133
- _console(logMeta) {
134
- const log = this._formatBgLevel(logMeta.level, logMeta.timestamp, logMeta.host?.substring(0, 20), logMeta.level.toUpperCase(), logMeta?.context) +
135
- (0, util_1.styleText)('reset', ' ') +
136
- logMeta.message
137
- .map((d) => {
138
- if (d[0] === 'error')
139
- return logError(this._formatConsoleError(d[1]));
140
- if (d[0] === 'object')
141
- return logWarn(logWarnBg('Object') + ' ' + d[1].split('\n').join('\n '));
142
- return (0, helpers_1.chunkArray)(d[1].split(' '), 10)
143
- .map((d) => d.join(' '))
144
- .join('\n ');
145
- })
146
- .join('\n ');
147
- return console.log('\n' + log);
148
- }
149
- log(...args) {
150
- const logMeta = this._mapLog('log', ...args);
151
- if (logMeta)
152
- this._console(logMeta);
153
- }
154
- error(...args) {
155
- if (config_1.NODE_ENV.toUpperCase() === 'DEVELOPMENT') {
156
- console.error('\x1b[31m', ...args);
157
- return;
158
- }
159
- const logMeta = this._mapLog('error', ...args);
160
- if (!logMeta)
161
- return;
162
- this._console(logMeta);
163
- this._notifyError(logMeta);
164
- }
165
- fatal(...args) {
166
- const logMeta = this._mapLog('fatal', ...args);
167
- if (!logMeta)
168
- return;
169
- this._console(logMeta);
170
- this._notifyError(args);
171
- }
172
- warn(...args) {
173
- const logMeta = this._mapLog('warn', ...args);
174
- if (logMeta)
175
- this._console(logMeta);
176
- }
177
- debug(...args) {
178
- const logMeta = this._mapLog('debug', ...args);
179
- if (logMeta)
180
- this._console(logMeta);
181
- }
182
- }
183
- exports.AppLogger = AppLogger;
1
+ "use strict";var obj;Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"AppLogger",{enumerable:!0,get:function(){return AppLogger}});let _common=require("@nestjs/common"),_helpers=require("@triproject/helpers"),_os=(obj=require("os"))&&obj.__esModule?obj:{default:obj},_util=require("util"),_config=require("../../config"),_slacklogger=require("./slack.logger"),bgLog=(option,log)=>(0,_util.styleText)("reset",(0,_util.styleText)("bold",(0,_util.styleText)(option,(0,_util.styleText)("black",` ${log} `)))),logError=log=>(0,_util.styleText)("red",log);let LoggerInit=class LoggerInit{host=_os.default.hostname();slackError;constructor(){_config.SLACK_ERROR_WEBHOOK_URL&&(this.slackError=new _slacklogger.SlackLogger(_config.SLACK_ERROR_WEBHOOK_URL))}};let loggerInit=new LoggerInit;let AppLogger=class AppLogger extends _common.ConsoleLogger{context;LOG_STACKS=3;constructor(context=""){super(context),this.context=context}_notifyError(...args){loggerInit.slackError&&loggerInit.slackError.send(args)}excludeContexts=["RoutesResolver","InstanceLoader","RouterExplorer","Nest Application","Module","NestApplication","NestFactory"];_excludeContext(context){return this.excludeContexts.includes(context)}_sanitizePolicyData(object){if(object)if(Array.isArray(object))return object.map(d=>"object"!=typeof d?d:this._sanitizePolicyData(d));else return Object.keys(object).reduce((acc,key)=>{let value=object[key];return _helpers.sanitizeRequests.includes(key)?value="***":"object"==typeof value&&(value=this._sanitizePolicyData(value)),{...acc,[key]:value}},{})}_formatBgLevel(level,...args){let msg=args.join(" ╱ ");switch(level){case"log":default:return bgLog("bgGreen",msg);case"warn":return bgLog("bgYellow",msg);case"error":case"fatal":return bgLog("bgRed",msg);case"debug":return bgLog("bgMagenta",msg)}}_formatException(error){let stacks=(error?.stack??"")?.split("\n").map(o=>o.trim().replace?.(error.name+": ","")).slice(0,"development"===_config.NODE_ENV?void 0:this.LOG_STACKS);return(error?.name??"UnknownErrorException")+" "+stacks.join(`
2
+ `)}_parseMessage(arg){return arg instanceof Error?["error",this._formatException(arg)]:"object"==typeof arg?["object",JSON.stringify(this._sanitizePolicyData(arg),null,2)]:["string",arg?.toString()]}_mapLog(level,...args){if(this._excludeContext(this.context)||void 0!==args[1]&&this.excludeContexts.some(d=>args[1]===d))return;let message=[];for(let arg of args?.flat()?.flat())arg&&message.push(this._parseMessage(arg));return{level,env:_config.NODE_ENV.toUpperCase(),context:this.context??"App Logger",timestamp:(0,_helpers.dateUtil)().utc().format("YYYY-MM-DD HH:mm:ss.SSS"),host:loggerInit.host?.substring(0,20),message}}_formatConsoleError(error){return error.split("\n").map(d=>d.endsWith("Exception")?d.replace(/(.*)Exception(.*)/,bgLog("bgRed","$1Exception")+logError("$2")):logError(d)).join("\n ")}_console(logMeta){return console.log(this._formatBgLevel(logMeta.level,logMeta.timestamp,logMeta.host?.substring(0,20),"LOG"===logMeta.level.toUpperCase()?"INFO":logMeta.level.toUpperCase(),logMeta?.context)+(0,_util.styleText)("reset","\n ")+logMeta.message.map(d=>{if("error"===d[0])return logError(this._formatConsoleError(d[1]));if("object"===d[0]){let log;return log=bgLog("bgMagenta","Object")+" "+d[1].split("\n").join("\n "),(0,_util.styleText)("yellow",log)}return(0,_helpers.chunkArray)(d[1].split(" "),10).map(d=>d.join(" ")).join("\n ")}).join("\n "))}log(...args){let logMeta=this._mapLog("log",...args);logMeta&&this._console(logMeta)}error(...args){if("DEVELOPMENT"===_config.NODE_ENV.toUpperCase())return void console.error("\x1b[31m",...args);let logMeta=this._mapLog("error",...args);logMeta&&(this._console(logMeta),this._notifyError(logMeta))}fatal(...args){let logMeta=this._mapLog("fatal",...args);logMeta&&(this._console(logMeta),this._notifyError(args))}warn(...args){let logMeta=this._mapLog("warn",...args);logMeta&&this._console(logMeta)}debug(...args){let logMeta=this._mapLog("debug",...args);logMeta&&this._console(logMeta)}};
@@ -0,0 +1,18 @@
1
+ interface CloudWatchConfig {
2
+ region: string;
3
+ logGroupName: string;
4
+ logStreamName?: string;
5
+ credentials?: {
6
+ accessKeyId: string;
7
+ secretAccessKey: string;
8
+ };
9
+ }
10
+ export declare class Cloudwatch {
11
+ private client;
12
+ private config;
13
+ private sequenceToken;
14
+ constructor(config: CloudWatchConfig);
15
+ private _ensureLogStream;
16
+ send(message: string): Promise<void>;
17
+ }
18
+ export {};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"Cloudwatch",{enumerable:!0,get:function(){return Cloudwatch}});let _clientcloudwatchlogs=require("@aws-sdk/client-cloudwatch-logs"),_common=require("@nestjs/common");function _ts_metadata(k,v){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(k,v)}let Cloudwatch=class Cloudwatch{client;config;sequenceToken;constructor(config){this.config={logStreamName:`app-${new Date().toISOString().split("T")[0]}`,...config},this.client=new _clientcloudwatchlogs.CloudWatchLogsClient({region:this.config.region,credentials:this.config.credentials}),this._ensureLogStream()}async _ensureLogStream(){try{let describeCommand=new _clientcloudwatchlogs.DescribeLogStreamsCommand({logGroupName:this.config.logGroupName,logStreamNamePrefix:this.config.logStreamName}),response=await this.client.send(describeCommand),logStream=response.logStreams?.[0];if(logStream)this.sequenceToken=logStream.uploadSequenceToken;else{let createCommand=new _clientcloudwatchlogs.CreateLogStreamCommand({logGroupName:this.config.logGroupName,logStreamName:this.config.logStreamName});await this.client.send(createCommand)}}catch(error){console.error("Error ensuring log stream:",error)}}async send(message){try{let params={logGroupName:this.config.logGroupName,logStreamName:this.config.logStreamName,logEvents:[{timestamp:Date.now(),message}],sequenceToken:this.sequenceToken},command=new _clientcloudwatchlogs.PutLogEventsCommand(params),response=await this.client.send(command);this.sequenceToken=response.nextSequenceToken}catch(error){console.error("Error sending log to CloudWatch:",error),"InvalidSequenceTokenException"===error.name&&(await this._ensureLogStream(),await this.send(message))}}};Cloudwatch=function(decorators,target,key,desc){var d,c=arguments.length,r=c<3?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r}([(0,_common.Injectable)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",["u"<typeof CloudWatchConfig?Object:CloudWatchConfig])],Cloudwatch);
@@ -0,0 +1 @@
1
+ export * from './cloudwatch';
@@ -0,0 +1 @@
1
+ "use strict";var from,to;Object.defineProperty(exports,"__esModule",{value:!0}),from=require("./cloudwatch"),to=exports,Object.keys(from).forEach(function(k){"default"===k||Object.prototype.hasOwnProperty.call(to,k)||Object.defineProperty(to,k,{enumerable:!0,get:function(){return from[k]}})});
@@ -1,18 +1 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./app.logger"), exports);
18
- __exportStar(require("./slack.logger"), exports);
1
+ "use strict";function _export_star(from,to){return Object.keys(from).forEach(function(k){"default"===k||Object.prototype.hasOwnProperty.call(to,k)||Object.defineProperty(to,k,{enumerable:!0,get:function(){return from[k]}})}),from}Object.defineProperty(exports,"__esModule",{value:!0}),_export_star(require("./app.logger"),exports),_export_star(require("./slack.logger"),exports);
@@ -1,24 +1 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- var __metadata = (this && this.__metadata) || function (k, v) {
9
- if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.SlackLogger = void 0;
13
- const common_1 = require("@nestjs/common");
14
- const slack_1 = require("../notifications/slack");
15
- let SlackLogger = class SlackLogger extends slack_1.Slack {
16
- constructor(webhookUrl) {
17
- super({ webhookUrl });
18
- }
19
- };
20
- exports.SlackLogger = SlackLogger;
21
- exports.SlackLogger = SlackLogger = __decorate([
22
- (0, common_1.Injectable)(),
23
- __metadata("design:paramtypes", [String])
24
- ], SlackLogger);
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"SlackLogger",{enumerable:!0,get:function(){return SlackLogger}});let _common=require("@nestjs/common"),_slack=require("../notifications/slack");function _ts_metadata(k,v){if("object"==typeof Reflect&&"function"==typeof Reflect.metadata)return Reflect.metadata(k,v)}let SlackLogger=class SlackLogger extends _slack.Slack{constructor(webhookUrl){super({webhookUrl})}};SlackLogger=function(decorators,target,key,desc){var d,c=arguments.length,r=c<3?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r}([(0,_common.Injectable)(),_ts_metadata("design:type",Function),_ts_metadata("design:paramtypes",[String])],SlackLogger);
@@ -1,22 +1 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
- };
16
- Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./mail"), exports);
18
- __exportStar(require("./mail-template"), exports);
19
- __exportStar(require("./mail.config"), exports);
20
- __exportStar(require("./mail.module"), exports);
21
- __exportStar(require("./mail.queue"), exports);
22
- __exportStar(require("./mailer"), exports);
1
+ "use strict";function _export_star(from,to){return Object.keys(from).forEach(function(k){"default"===k||Object.prototype.hasOwnProperty.call(to,k)||Object.defineProperty(to,k,{enumerable:!0,get:function(){return from[k]}})}),from}Object.defineProperty(exports,"__esModule",{value:!0}),_export_star(require("./mail"),exports),_export_star(require("./mail-template"),exports),_export_star(require("./mail.config"),exports),_export_star(require("./mail.module"),exports),_export_star(require("./mail.queue"),exports),_export_star(require("./mailer"),exports);
@@ -1,45 +1,18 @@
1
- "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.MailTemplate = void 0;
10
- const common_1 = require("@nestjs/common");
11
- const config_1 = require("../../config");
12
- let MailTemplate = class MailTemplate {
13
- // @ts-ignore
14
- THEME_COLOR = '#3968FE';
15
- MAX_WIDTH = '530px';
16
- logo() {
17
- return `<div style="padding:1em 1.3em 0 1.3em;">
18
- <a href="${config_1.LANDING_PAGE_URL}" title="${config_1.APP_NAME}" style="underline:none;color:${this.THEME_COLOR};text-decoration:none;">
19
- ${config_1.APP_LOGO_URL
20
- ? `<img src="${config_1.APP_LOGO_URL}" alt="${config_1.APP_NAME}" width="100" />`
21
- : `<b style="font-size:1.5em;letter-spacing:0.1em;line-height:1.6;">${config_1.APP_NAME}</b>`}
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"MailTemplate",{enumerable:!0,get:function(){return MailTemplate}});let _common=require("@nestjs/common"),_config=require("../../config");let MailTemplate=class MailTemplate{THEME_COLOR="#3968FE";MAX_WIDTH="530px";logo(){return`<div style="padding:1em 1.3em 0 1.3em;">
2
+ <a href="${_config.LANDING_PAGE_URL}" title="${_config.APP_NAME}" style="underline:none;color:${this.THEME_COLOR};text-decoration:none;">
3
+ ${_config.APP_LOGO_URL?`<img src="${_config.APP_LOGO_URL}" alt="${_config.APP_NAME}" width="100" />`:`<b style="font-size:1.5em;letter-spacing:0.1em;line-height:1.6;">${_config.APP_NAME}</b>`}
22
4
  </a>
23
- </div>`;
24
- }
25
- header() {
26
- return `<div style="
5
+ </div>`}header(){return`<div style="
27
6
  width:100%;
28
7
  max-width:${this.MAX_WIDTH};margin:1.5em auto 0;
29
8
  position:relative;
30
9
  font-size:14px;padding:0.5em 0;">
31
10
  ${this.logo()}
32
- </div>`;
33
- }
34
- get FOOTER() {
35
- return `<div style="font-size:12px;color:#868686;text-align:center;padding:0 1.5em">
11
+ </div>`}get FOOTER(){return`<div style="font-size:12px;color:#868686;text-align:center;padding:0 1.5em">
36
12
  <div style="border-top:1px solid #eee;padding:1.5em 0 2em;text-align:center">
37
- ${new Date().getFullYear()} &copy; ${config_1.APP_NAME}
13
+ ${new Date().getFullYear()} &copy; ${_config.APP_NAME}
38
14
  </div>
39
- </div>`;
40
- }
41
- html(content) {
42
- return `<!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
15
+ </div>`}html(content){return`<!DOCTYPE htmlPUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
43
16
  <html>
44
17
  <head>
45
18
  <meta http-equiv="Content-Type" CONTENT="text/html charset=UTF-8" />
@@ -65,10 +38,4 @@ let MailTemplate = class MailTemplate {
65
38
  </tr>
66
39
  </tbody>
67
40
  </table>
68
- </html>`.replace(/ +/g, ' ');
69
- }
70
- };
71
- exports.MailTemplate = MailTemplate;
72
- exports.MailTemplate = MailTemplate = __decorate([
73
- (0, common_1.Injectable)()
74
- ], MailTemplate);
41
+ </html>`.replace(/ +/g," ")}};MailTemplate=function(decorators,target,key,desc){var d,c=arguments.length,r=c<3?target:null===desc?desc=Object.getOwnPropertyDescriptor(target,key):desc;if("object"==typeof Reflect&&"function"==typeof Reflect.decorate)r=Reflect.decorate(decorators,target,key,desc);else for(var i=decorators.length-1;i>=0;i--)(d=decorators[i])&&(r=(c<3?d(r):c>3?d(target,key,r):d(target,key))||r);return c>3&&r&&Object.defineProperty(target,key,r),r}([(0,_common.Injectable)()],MailTemplate);
@@ -1,4 +1 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.mailerQueue = void 0;
4
- exports.mailerQueue = 'MAILER:QUEUE';
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"mailerQueue",{enumerable:!0,get:function(){return mailerQueue}});let mailerQueue="MAILER:QUEUE";
@@ -1,45 +1,16 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Mail = void 0;
4
- class Mail {
5
- CONTENT = '';
6
- caption(content) {
7
- this.CONTENT += `<div style="margin:0 0 1.5em 0;">${content.replace(/((http:|https:)[^\s]+[\w])/g, '<a href="$1" target="_blank" style="color:#3D96FF;font-weight:500">$1</a>')}</div>`;
8
- return this;
9
- }
10
- p(content, style = '') {
11
- this.CONTENT += `<p style="
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),Object.defineProperty(exports,"Mail",{enumerable:!0,get:function(){return Mail}});let Mail=class Mail{CONTENT="";caption(content){return this.CONTENT+=`<div style="margin:0 0 1.5em 0;">${content.replace(/((http:|https:)[^\s]+[\w])/g,'<a href="$1" target="_blank" style="color:#3D96FF;font-weight:500">$1</a>')}</div>`,this}p(content,style=""){return this.CONTENT+=`<p style="
12
2
  font-family: sans-serif;
13
3
  font-weight: 400;
14
4
  font-size: 1.2em;
15
5
  margin: 1.25em 0;
16
- ${style}">${content.replace(/((http:|https:)[^\s]+[\w])/g, '<a href="$1" target="_blank" style="color:#3D96FF;font-weight:500">$1</a>')}</p>`;
17
- return this;
18
- }
19
- ln(content) {
20
- this.CONTENT += `${content}\n`;
21
- return this;
22
- }
23
- a(title, href) {
24
- this.CONTENT += `<a href="${href ?? title}" title="${title}" style="color:#3D96FF;font-weight:500">${title}</a>`;
25
- return this;
26
- }
27
- otp(code) {
28
- this.CONTENT += `<p style="padding:1em 2em;text-align:center;font-weight:bold;font-size:30px;background-color:#eee;letter-spacing: 0.2em;border-radius:5px;">
6
+ ${style}">${content.replace(/((http:|https:)[^\s]+[\w])/g,'<a href="$1" target="_blank" style="color:#3D96FF;font-weight:500">$1</a>')}</p>`,this}ln(content){return this.CONTENT+=`${content}
7
+ `,this}a(title,href){return this.CONTENT+=`<a href="${href??title}" title="${title}" style="color:#3D96FF;font-weight:500">${title}</a>`,this}otp(code){return this.CONTENT+=`<p style="padding:1em 2em;text-align:center;font-weight:bold;font-size:30px;background-color:#eee;letter-spacing: 0.2em;border-radius:5px;">
29
8
  ${code}
30
- </p>`;
31
- return this;
32
- }
33
- title(title, style = '') {
34
- this.CONTENT += `<h1 style="
9
+ </p>`,this}title(title,style=""){return this.CONTENT+=`<h1 style="
35
10
  font-family: sans-serif;
36
11
  font-weight: 600;
37
12
  font-size: 18px;
38
- ${style}">${title}</h1>`;
39
- return this;
40
- }
41
- action(title, href) {
42
- this.CONTENT += `<p style="margin: 2em 0"><a href="${href}" title="${title}" style="
13
+ ${style}">${title}</h1>`,this}action(title,href){return this.CONTENT+=`<p style="margin: 2em 0"><a href="${href}" title="${title}" style="
43
14
  display:block;
44
15
  background: #3968FE;
45
16
  color: white;
@@ -50,49 +21,18 @@ class Mail {
50
21
  font-weight: bold;
51
22
  text-decoration: none;
52
23
  font-family: sans-serif;">
53
- ${title}</a></p>`;
54
- return this;
55
- }
56
- listDetail(list, title = '') {
57
- const parsedList = list
58
- .map((li) => {
59
- return `<div style="margin-bottom:8px;display:flex;justify-CONTENT:space-between;${li?.style ?? ''}">
24
+ ${title}</a></p>`,this}listDetail(list,title=""){let parsedList=list.map(li=>`<div style="margin-bottom:8px;display:flex;justify-CONTENT:space-between;${li?.style??""}">
60
25
  <div style="margin-right:0.75em">${li.name}</div>
61
26
  <div style="text-align:right;font-weight:bold">${li.value}</div>
62
- </div>`;
63
- })
64
- .join(' ');
65
- this.CONTENT += `<p style="text-align:center;">
66
- ${title &&
67
- `<div style="background-color:#F6F6F6;padding:8px 10px;border-radius:5px;font-weight:bold;margin-bottom:1em">${title}</div>`}
68
- <div style="margin-top:5px;font-size:95%;${title ? 'padding: 0 0.75em' : ''}">
27
+ </div>`).join(" ");return this.CONTENT+=`<p style="text-align:center;">
28
+ ${title&&`<div style="background-color:#F6F6F6;padding:8px 10px;border-radius:5px;font-weight:bold;margin-bottom:1em">${title}</div>`}
29
+ <div style="margin-top:5px;font-size:95%;${title?"padding: 0 0.75em":""}">
69
30
  ${parsedList}
70
31
  </div>
71
- </p>`;
72
- return this;
73
- }
74
- list(list, type = 'bulleted') {
75
- const listStyleType = type === 'numbered' ? 'decimal' : 'disc';
76
- const parsedList = list
77
- .map((li) => {
78
- return `<li style="margin-bottom:8px;">
32
+ </p>`,this}list(list,type="bulleted"){let parsedList=list.map(li=>`<li style="margin-bottom:8px;">
79
33
  <span>${li}</span>
80
- </li>`;
81
- })
82
- .join('');
83
- this.CONTENT += `<p style="text-align:center;">
84
- <ul style="list-style-type:${listStyleType}; padding-left: 20px; margin-top:5px; font-size:100%;">
34
+ </li>`).join("");return this.CONTENT+=`<p style="text-align:center;">
35
+ <ul style="list-style-type:${"numbered"===type?"decimal":"disc"}; padding-left: 20px; margin-top:5px; font-size:100%;">
85
36
  ${parsedList}
86
37
  </ul>
87
- </p>`;
88
- return this;
89
- }
90
- hr() {
91
- this.CONTENT += `<hr style="margin: 2em 0">`;
92
- return this;
93
- }
94
- toString() {
95
- return this.CONTENT;
96
- }
97
- }
98
- exports.Mail = Mail;
38
+ </p>`,this}hr(){return this.CONTENT+='<hr style="margin: 2em 0">',this}toString(){return this.CONTENT}};