ztechno_core 0.0.105 → 0.0.108
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/lib/core/crypto_service.d.ts +23 -0
- package/lib/core/crypto_service.js +100 -0
- package/lib/core/engine_base.d.ts +11 -0
- package/lib/core/engine_base.js +9 -0
- package/lib/core/index.d.ts +14 -0
- package/lib/core/index.js +101 -0
- package/lib/core/mail_service.d.ts +85 -0
- package/lib/core/mail_service.js +156 -0
- package/lib/core/orm/mail_blacklist_orm.d.ts +21 -0
- package/lib/core/orm/mail_blacklist_orm.js +79 -0
- package/lib/core/orm/orm.d.ts +27 -0
- package/lib/core/orm/orm.js +67 -0
- package/lib/core/sql_service.d.ts +195 -0
- package/lib/core/sql_service.js +333 -0
- package/lib/core/translate_service.d.ts +48 -0
- package/lib/core/translate_service.js +913 -0
- package/lib/core/types/crypto_types.d.ts +4 -0
- package/lib/core/types/crypto_types.js +2 -0
- package/lib/core/types/mail_types.d.ts +95 -0
- package/lib/core/types/mail_types.js +2 -0
- package/lib/core/types/site_config.d.ts +46 -0
- package/lib/core/types/site_config.js +2 -0
- package/lib/core/types/translate_types.d.ts +69 -0
- package/lib/core/types/translate_types.js +46 -0
- package/lib/core/types/user_types.d.ts +41 -0
- package/lib/core/types/user_types.js +2 -0
- package/lib/core/user_service.d.ts +87 -0
- package/lib/core/user_service.js +216 -0
- package/lib/express/index.d.ts +1 -0
- package/lib/express/index.js +18 -0
- package/lib/index.d.ts +17 -8
- package/lib/index.js +60 -16
- package/lib/mollie/index.d.ts +5 -0
- package/lib/mollie/index.js +62 -0
- package/lib/mollie/orm/customers_orm.d.ts +16 -0
- package/lib/mollie/orm/customers_orm.js +115 -0
- package/lib/mollie/orm/invoice_items_orm.d.ts +9 -0
- package/lib/mollie/orm/invoice_items_orm.js +71 -0
- package/lib/mollie/orm/invoice_payments_orm.d.ts +10 -0
- package/lib/mollie/orm/invoice_payments_orm.js +70 -0
- package/lib/mollie/orm/invoices_orm.d.ts +40 -0
- package/lib/mollie/orm/invoices_orm.js +172 -0
- package/lib/mollie/orm/subscription_items_orm.d.ts +9 -0
- package/lib/mollie/orm/subscription_items_orm.js +45 -0
- package/lib/mollie/orm/subscriptions_orm.d.ts +17 -0
- package/lib/mollie/orm/subscriptions_orm.js +122 -0
- package/lib/mollie/services/customer_service.d.ts +14 -0
- package/lib/mollie/services/customer_service.js +53 -0
- package/lib/mollie/services/invoice_service.d.ts +102 -0
- package/lib/mollie/services/invoice_service.js +866 -0
- package/lib/mollie/services/mollie_service.d.ts +42 -0
- package/lib/mollie/services/mollie_service.js +370 -0
- package/lib/mollie/services/subscription_service.d.ts +32 -0
- package/lib/mollie/services/subscription_service.js +134 -0
- package/lib/mollie/types/internal_types.d.ts +19 -0
- package/lib/mollie/types/internal_types.js +2 -0
- package/lib/mollie/types/mollie_types.d.ts +187 -0
- package/lib/mollie/types/mollie_types.js +3 -0
- package/lib/mollie/util/subscription_utils.d.ts +8 -0
- package/lib/mollie/util/subscription_utils.js +37 -0
- package/lib/schema/MySQLSchemaExtractor.d.ts +1 -1
- package/lib/schema/MySQLSchemaImporter.d.ts +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { HashStruct } from './types/crypto_types';
|
|
2
|
+
export declare class ZCryptoService {
|
|
3
|
+
static encrypt(text: string): HashStruct;
|
|
4
|
+
static decrypt(data: HashStruct): string;
|
|
5
|
+
static decrypt(encrypted: string): string;
|
|
6
|
+
static decryptJSON<T = any>(data: HashStruct): T;
|
|
7
|
+
static decryptJSON<T = any>(data: string): T;
|
|
8
|
+
static hash(
|
|
9
|
+
hashAlgorithm: 'sha256' | 'sha512' | 'md5',
|
|
10
|
+
data: string,
|
|
11
|
+
opt?: {
|
|
12
|
+
itt?: number;
|
|
13
|
+
} & (
|
|
14
|
+
| {
|
|
15
|
+
saltMode: 'none';
|
|
16
|
+
}
|
|
17
|
+
| {
|
|
18
|
+
saltMode: 'simple';
|
|
19
|
+
salt: string;
|
|
20
|
+
}
|
|
21
|
+
),
|
|
22
|
+
): string;
|
|
23
|
+
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return m[k];
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}
|
|
18
|
+
: function (o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
});
|
|
22
|
+
var __setModuleDefault =
|
|
23
|
+
(this && this.__setModuleDefault) ||
|
|
24
|
+
(Object.create
|
|
25
|
+
? function (o, v) {
|
|
26
|
+
Object.defineProperty(o, 'default', { enumerable: true, value: v });
|
|
27
|
+
}
|
|
28
|
+
: function (o, v) {
|
|
29
|
+
o['default'] = v;
|
|
30
|
+
});
|
|
31
|
+
var __importStar =
|
|
32
|
+
(this && this.__importStar) ||
|
|
33
|
+
function (mod) {
|
|
34
|
+
if (mod && mod.__esModule) return mod;
|
|
35
|
+
var result = {};
|
|
36
|
+
if (mod != null)
|
|
37
|
+
for (var k in mod)
|
|
38
|
+
if (k !== 'default' && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
43
|
+
exports.ZCryptoService = void 0;
|
|
44
|
+
const crypto = __importStar(require('crypto'));
|
|
45
|
+
const algorithm = 'aes-256-cbc';
|
|
46
|
+
const key = Buffer.from([
|
|
47
|
+
253, 144, 73, 128, 71, 94, 34, 3, 28, 128, 194, 166, 132, 154, 14, 87, 221, 202, 92, 56, 139, 10, 38, 122, 120, 7,
|
|
48
|
+
149, 40, 211, 218, 217, 3,
|
|
49
|
+
]);
|
|
50
|
+
const iv = Buffer.from([0, 209, 223, 20, 147, 45, 14, 107, 93, 6, 76, 206, 176, 55, 245, 134]);
|
|
51
|
+
class ZCryptoService {
|
|
52
|
+
static encrypt(text) {
|
|
53
|
+
const cipher = crypto.createCipheriv(algorithm, key, iv);
|
|
54
|
+
let encrypted = cipher.update(text);
|
|
55
|
+
encrypted = Buffer.concat([encrypted, cipher.final()]);
|
|
56
|
+
return { iv: iv.toString('hex'), encryptedData: encrypted.toString('hex') };
|
|
57
|
+
}
|
|
58
|
+
static decrypt(data) {
|
|
59
|
+
if (typeof data === 'string') {
|
|
60
|
+
const encryptedText = Buffer.from(data, 'hex');
|
|
61
|
+
const decipher = crypto.createDecipheriv(algorithm, key, iv);
|
|
62
|
+
let decrypted = decipher.update(encryptedText);
|
|
63
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
64
|
+
return decrypted.toString();
|
|
65
|
+
}
|
|
66
|
+
const niv = Buffer.from(data.iv, 'hex');
|
|
67
|
+
const encryptedText = Buffer.from(data.encryptedData, 'hex');
|
|
68
|
+
const decipher = crypto.createDecipheriv(algorithm, key, niv);
|
|
69
|
+
let decrypted = decipher.update(encryptedText);
|
|
70
|
+
decrypted = Buffer.concat([decrypted, decipher.final()]);
|
|
71
|
+
return decrypted.toString();
|
|
72
|
+
}
|
|
73
|
+
static decryptJSON(data) {
|
|
74
|
+
try {
|
|
75
|
+
const decrypted = ZCryptoService.decrypt(data);
|
|
76
|
+
return JSON.parse(decrypted);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
throw new Error(`Couldn't decrypt JSON ${JSON.stringify(data)}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
static hash(hashAlgorithm, data, opt) {
|
|
82
|
+
const itt = opt?.itt || 1;
|
|
83
|
+
let salt;
|
|
84
|
+
if (opt && opt.saltMode === 'simple') {
|
|
85
|
+
salt = opt.salt;
|
|
86
|
+
data = data
|
|
87
|
+
.split('')
|
|
88
|
+
.map((c, i) => c + salt.charAt(i % salt.length))
|
|
89
|
+
.join('');
|
|
90
|
+
}
|
|
91
|
+
let hash = data;
|
|
92
|
+
for (let i = 0; i < itt; i++) {
|
|
93
|
+
hash = crypto.createHash(hashAlgorithm).update(hash).digest('hex');
|
|
94
|
+
}
|
|
95
|
+
const cut = itt.toString().length + 1;
|
|
96
|
+
hash = `${itt}$${hash.substring(cut)}`;
|
|
97
|
+
return hash;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.ZCryptoService = ZCryptoService;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ZMailService } from './mail_service';
|
|
2
|
+
import { ZSQLService } from './sql_service';
|
|
3
|
+
import { ZTranslateService } from './translate_service';
|
|
4
|
+
import { ZUserService } from './user_service';
|
|
5
|
+
export declare class ZEngineBase {
|
|
6
|
+
static mailService?: ZMailService;
|
|
7
|
+
static sqlService?: ZSQLService;
|
|
8
|
+
static translateService?: ZTranslateService;
|
|
9
|
+
static userService?: ZUserService;
|
|
10
|
+
protected static start(): any;
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export { ZEngineBase } from './engine_base';
|
|
2
|
+
export { ZCryptoService } from './crypto_service';
|
|
3
|
+
export { ZMailService } from './mail_service';
|
|
4
|
+
export { ZSQLService } from './sql_service';
|
|
5
|
+
export type { ZSQLOptions, ZTransaction } from './sql_service';
|
|
6
|
+
export { ZTranslateService } from './translate_service';
|
|
7
|
+
export { ZUserService } from './user_service';
|
|
8
|
+
export * from './types/crypto_types';
|
|
9
|
+
export * from './types/mail_types';
|
|
10
|
+
export * from './types/translate_types';
|
|
11
|
+
export * from './types/user_types';
|
|
12
|
+
export * from './types/site_config';
|
|
13
|
+
export { ZOrm } from './orm/orm';
|
|
14
|
+
export { ZMailBlacklistOrm } from './orm/mail_blacklist_orm';
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __createBinding =
|
|
3
|
+
(this && this.__createBinding) ||
|
|
4
|
+
(Object.create
|
|
5
|
+
? function (o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ('get' in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = {
|
|
10
|
+
enumerable: true,
|
|
11
|
+
get: function () {
|
|
12
|
+
return m[k];
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}
|
|
18
|
+
: function (o, m, k, k2) {
|
|
19
|
+
if (k2 === undefined) k2 = k;
|
|
20
|
+
o[k2] = m[k];
|
|
21
|
+
});
|
|
22
|
+
var __exportStar =
|
|
23
|
+
(this && this.__exportStar) ||
|
|
24
|
+
function (m, exports) {
|
|
25
|
+
for (var p in m)
|
|
26
|
+
if (p !== 'default' && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
27
|
+
};
|
|
28
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
29
|
+
exports.ZMailBlacklistOrm =
|
|
30
|
+
exports.ZOrm =
|
|
31
|
+
exports.ZUserService =
|
|
32
|
+
exports.ZTranslateService =
|
|
33
|
+
exports.ZSQLService =
|
|
34
|
+
exports.ZMailService =
|
|
35
|
+
exports.ZCryptoService =
|
|
36
|
+
exports.ZEngineBase =
|
|
37
|
+
void 0;
|
|
38
|
+
// Services
|
|
39
|
+
var engine_base_1 = require('./engine_base');
|
|
40
|
+
Object.defineProperty(exports, 'ZEngineBase', {
|
|
41
|
+
enumerable: true,
|
|
42
|
+
get: function () {
|
|
43
|
+
return engine_base_1.ZEngineBase;
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
var crypto_service_1 = require('./crypto_service');
|
|
47
|
+
Object.defineProperty(exports, 'ZCryptoService', {
|
|
48
|
+
enumerable: true,
|
|
49
|
+
get: function () {
|
|
50
|
+
return crypto_service_1.ZCryptoService;
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
var mail_service_1 = require('./mail_service');
|
|
54
|
+
Object.defineProperty(exports, 'ZMailService', {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return mail_service_1.ZMailService;
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
var sql_service_1 = require('./sql_service');
|
|
61
|
+
Object.defineProperty(exports, 'ZSQLService', {
|
|
62
|
+
enumerable: true,
|
|
63
|
+
get: function () {
|
|
64
|
+
return sql_service_1.ZSQLService;
|
|
65
|
+
},
|
|
66
|
+
});
|
|
67
|
+
var translate_service_1 = require('./translate_service');
|
|
68
|
+
Object.defineProperty(exports, 'ZTranslateService', {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
get: function () {
|
|
71
|
+
return translate_service_1.ZTranslateService;
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
var user_service_1 = require('./user_service');
|
|
75
|
+
Object.defineProperty(exports, 'ZUserService', {
|
|
76
|
+
enumerable: true,
|
|
77
|
+
get: function () {
|
|
78
|
+
return user_service_1.ZUserService;
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
// Types
|
|
82
|
+
__exportStar(require('./types/crypto_types'), exports);
|
|
83
|
+
__exportStar(require('./types/mail_types'), exports);
|
|
84
|
+
__exportStar(require('./types/translate_types'), exports);
|
|
85
|
+
__exportStar(require('./types/user_types'), exports);
|
|
86
|
+
__exportStar(require('./types/site_config'), exports);
|
|
87
|
+
// ORM
|
|
88
|
+
var orm_1 = require('./orm/orm');
|
|
89
|
+
Object.defineProperty(exports, 'ZOrm', {
|
|
90
|
+
enumerable: true,
|
|
91
|
+
get: function () {
|
|
92
|
+
return orm_1.ZOrm;
|
|
93
|
+
},
|
|
94
|
+
});
|
|
95
|
+
var mail_blacklist_orm_1 = require('./orm/mail_blacklist_orm');
|
|
96
|
+
Object.defineProperty(exports, 'ZMailBlacklistOrm', {
|
|
97
|
+
enumerable: true,
|
|
98
|
+
get: function () {
|
|
99
|
+
return mail_blacklist_orm_1.ZMailBlacklistOrm;
|
|
100
|
+
},
|
|
101
|
+
});
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MailOptions,
|
|
3
|
+
MailOptionsHtml,
|
|
4
|
+
MailOptionsText,
|
|
5
|
+
MailResponse,
|
|
6
|
+
MailServiceOptions,
|
|
7
|
+
ZMailBlacklist,
|
|
8
|
+
ZMailSendOptTemplate,
|
|
9
|
+
} from './types/mail_types';
|
|
10
|
+
import { ZMailBlacklistOrm } from './orm/mail_blacklist_orm';
|
|
11
|
+
export declare class ZMailService {
|
|
12
|
+
private opt;
|
|
13
|
+
protected get sql(): import('./sql_service').ZSQLService;
|
|
14
|
+
protected blacklistOrm: ZMailBlacklistOrm;
|
|
15
|
+
protected blacklist: ZMailBlacklist[];
|
|
16
|
+
/**
|
|
17
|
+
* Creates a new ZMailService instance
|
|
18
|
+
* @param opt - Configuration options for the mail service including authentication, sender email, and SQL service
|
|
19
|
+
*/
|
|
20
|
+
constructor(opt: MailServiceOptions);
|
|
21
|
+
updateBlacklist(opt: Pick<ZMailBlacklist, 'email' | 'is_blacklisted' | 'hash'>): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Refreshes the email blacklist from the database
|
|
24
|
+
* @returns Promise that resolves when the blacklist has been refreshed
|
|
25
|
+
*/
|
|
26
|
+
protected refreshBlacklist(): Promise<void>;
|
|
27
|
+
/**
|
|
28
|
+
* Fetches the content of a template file from the filesystem
|
|
29
|
+
* @param template - Path to the template file to read
|
|
30
|
+
* @returns Promise that resolves to the template content as a string
|
|
31
|
+
* @throws Will throw an error if the file cannot be read
|
|
32
|
+
* @private
|
|
33
|
+
*/
|
|
34
|
+
private fetchTemplate;
|
|
35
|
+
/**
|
|
36
|
+
* Checks if an email is allowed to be sent by verifying it's not blacklisted
|
|
37
|
+
* @param mailOpts - Mail options containing the recipient email to check
|
|
38
|
+
* @returns Promise that resolves to true if email is allowed, false if blacklisted
|
|
39
|
+
* @protected
|
|
40
|
+
*/
|
|
41
|
+
protected allowSend(mailOpts: MailOptions): Promise<boolean>;
|
|
42
|
+
/**
|
|
43
|
+
* Sends an email with text content
|
|
44
|
+
* @param mailOpts - Mail options with text body
|
|
45
|
+
* @returns Promise that resolves to mail response or undefined if sending is not allowed
|
|
46
|
+
*/
|
|
47
|
+
send(mailOpts: MailOptionsText): Promise<MailResponse | undefined>;
|
|
48
|
+
/**
|
|
49
|
+
* Sends an email with HTML content
|
|
50
|
+
* @param mailOpts - Mail options with HTML body
|
|
51
|
+
* @returns Promise that resolves to mail response or undefined if sending is not allowed
|
|
52
|
+
*/
|
|
53
|
+
send(mailOpts: MailOptionsHtml): Promise<MailResponse | undefined>;
|
|
54
|
+
/**
|
|
55
|
+
* Sends an advanced email with text content, supporting templates and variable injection
|
|
56
|
+
* @param mailOpts - Mail options with text body
|
|
57
|
+
* @returns Promise that resolves to mail response
|
|
58
|
+
*/
|
|
59
|
+
sendAdvanced(mailOpts: MailOptionsText): Promise<any>;
|
|
60
|
+
/**
|
|
61
|
+
* Sends an advanced email with HTML content, supporting templates and variable injection
|
|
62
|
+
* @param mailOpts - Mail options with HTML body
|
|
63
|
+
* @returns Promise that resolves to mail response
|
|
64
|
+
*/
|
|
65
|
+
sendAdvanced(mailOpts: MailOptionsHtml): Promise<any>;
|
|
66
|
+
/**
|
|
67
|
+
* Sends an advanced email using a template file, supporting variable injection
|
|
68
|
+
* @param mailOpts - Mail options with template path and injection variables
|
|
69
|
+
* @returns Promise that resolves to mail response
|
|
70
|
+
*/
|
|
71
|
+
sendAdvanced(mailOpts: ZMailSendOptTemplate): Promise<any>;
|
|
72
|
+
/**
|
|
73
|
+
* Injects variables into a body string by replacing placeholder tokens
|
|
74
|
+
* @param body - The string content where variables should be injected
|
|
75
|
+
* @param inject - Object containing key-value pairs where keys are variable names and values are replacement content
|
|
76
|
+
* @returns Promise that resolves to the body string with all variables injected
|
|
77
|
+
* @example
|
|
78
|
+
* ```typescript
|
|
79
|
+
* const result = await inject('Hello :name from :company', { name: 'John', company: 'ACME' });
|
|
80
|
+
* // Returns: 'Hello John from ACME'
|
|
81
|
+
* ```
|
|
82
|
+
* @private
|
|
83
|
+
*/
|
|
84
|
+
private inject;
|
|
85
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
var __importDefault =
|
|
3
|
+
(this && this.__importDefault) ||
|
|
4
|
+
function (mod) {
|
|
5
|
+
return mod && mod.__esModule ? mod : { default: mod };
|
|
6
|
+
};
|
|
7
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
8
|
+
exports.ZMailService = void 0;
|
|
9
|
+
const nodemailer_1 = __importDefault(require('nodemailer'));
|
|
10
|
+
const fs_1 = __importDefault(require('fs'));
|
|
11
|
+
const promises_1 = __importDefault(require('fs/promises'));
|
|
12
|
+
const path_1 = __importDefault(require('path'));
|
|
13
|
+
const mail_blacklist_orm_1 = require('./orm/mail_blacklist_orm');
|
|
14
|
+
class ZMailService {
|
|
15
|
+
get sql() {
|
|
16
|
+
return this.opt.sqlService;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Creates a new ZMailService instance
|
|
20
|
+
* @param opt - Configuration options for the mail service including authentication, sender email, and SQL service
|
|
21
|
+
*/
|
|
22
|
+
constructor(opt) {
|
|
23
|
+
this.opt = opt;
|
|
24
|
+
this.blacklist = [];
|
|
25
|
+
this.blacklistOrm = new mail_blacklist_orm_1.ZMailBlacklistOrm(opt);
|
|
26
|
+
this.opt.dirTemplate = path_1.default.isAbsolute(this.opt.dirTemplate || '')
|
|
27
|
+
? this.opt.dirTemplate
|
|
28
|
+
: path_1.default.join(process.cwd(), this.opt.dirTemplate || '');
|
|
29
|
+
}
|
|
30
|
+
async updateBlacklist(opt) {
|
|
31
|
+
const newItem = await this.blacklistOrm.upsert(opt);
|
|
32
|
+
const found = this.blacklist.find((item) => item.email === opt.email);
|
|
33
|
+
if (found) {
|
|
34
|
+
found.is_blacklisted = opt.is_blacklisted;
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
this.blacklist.push(newItem);
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Refreshes the email blacklist from the database
|
|
42
|
+
* @returns Promise that resolves when the blacklist has been refreshed
|
|
43
|
+
*/
|
|
44
|
+
async refreshBlacklist() {
|
|
45
|
+
this.blacklist = await this.blacklistOrm.findAll();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Fetches the content of a template file from the filesystem
|
|
49
|
+
* @param template - Path to the template file to read
|
|
50
|
+
* @returns Promise that resolves to the template content as a string
|
|
51
|
+
* @throws Will throw an error if the file cannot be read
|
|
52
|
+
* @private
|
|
53
|
+
*/
|
|
54
|
+
async fetchTemplate(template) {
|
|
55
|
+
const filepath = path_1.default.join(this.opt.dirTemplate, template);
|
|
56
|
+
if (fs_1.default.existsSync(filepath)) {
|
|
57
|
+
return await promises_1.default.readFile(filepath, { encoding: 'utf-8' });
|
|
58
|
+
}
|
|
59
|
+
throw new Error(`Template file not found: ${filepath}`);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Checks if an email is allowed to be sent by verifying it's not blacklisted
|
|
63
|
+
* @param mailOpts - Mail options containing the recipient email to check
|
|
64
|
+
* @returns Promise that resolves to true if email is allowed, false if blacklisted
|
|
65
|
+
* @protected
|
|
66
|
+
*/
|
|
67
|
+
async allowSend(mailOpts) {
|
|
68
|
+
const blacklistEntry = await this.blacklistOrm.findOne({ email: mailOpts.recipient, is_blacklisted: 1 });
|
|
69
|
+
if (blacklistEntry) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Sends an email with either text or HTML content
|
|
76
|
+
* @param mailOpts - Mail options containing recipient, subject, and body/html content
|
|
77
|
+
* @returns Promise that resolves to mail response or undefined if sending is not allowed
|
|
78
|
+
*/
|
|
79
|
+
async send(mailOpts) {
|
|
80
|
+
const allow = await this.allowSend(mailOpts);
|
|
81
|
+
if (!allow) {
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const mailTransporter = nodemailer_1.default.createTransport({
|
|
85
|
+
service: 'gmail',
|
|
86
|
+
auth: this.opt.auth,
|
|
87
|
+
});
|
|
88
|
+
const mailDetails = {
|
|
89
|
+
from: mailOpts.from || this.opt.mailSender,
|
|
90
|
+
to: mailOpts.recipient,
|
|
91
|
+
subject: mailOpts.subject,
|
|
92
|
+
text: mailOpts.body || undefined,
|
|
93
|
+
html: mailOpts.html || undefined,
|
|
94
|
+
dkim: mailOpts.dkim ?? this.opt.dkim,
|
|
95
|
+
priority: mailOpts.priority,
|
|
96
|
+
attachments: mailOpts.attachments,
|
|
97
|
+
};
|
|
98
|
+
return await new Promise((resolve, reject) => {
|
|
99
|
+
mailTransporter.sendMail(mailDetails, function (err, data) {
|
|
100
|
+
return err ? reject(err) : resolve(data);
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Sends an advanced email with enhanced features including template loading and variable injection.
|
|
106
|
+
* Automatically generates unsubscribe hash and injects common variables like email and hashToUnsubscribe.
|
|
107
|
+
* @param mailOpts - Mail options that can include template path, injection variables, and standard mail fields
|
|
108
|
+
* @returns Promise that resolves to mail response from the underlying send method
|
|
109
|
+
* @example
|
|
110
|
+
* ```typescript
|
|
111
|
+
* await mailService.sendAdvanced({
|
|
112
|
+
* recipient: 'user@example.com',
|
|
113
|
+
* subject: 'Welcome!',
|
|
114
|
+
* template: './templates/welcome.html',
|
|
115
|
+
* inject: { name: 'John', company: 'ACME Corp' }
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
async sendAdvanced(mailOpts) {
|
|
120
|
+
const opts = mailOpts;
|
|
121
|
+
const hashToUnsubscribe = await this.blacklistOrm.genEmailUnsubscribeHash({ email: mailOpts.recipient });
|
|
122
|
+
if (opts.template !== undefined) {
|
|
123
|
+
opts.html = await this.fetchTemplate(opts.template);
|
|
124
|
+
}
|
|
125
|
+
if (opts.inject !== undefined) {
|
|
126
|
+
const key = opts.html !== undefined ? 'html' : 'body';
|
|
127
|
+
const baseInject = Object.assign({ email: mailOpts.recipient, hashToUnsubscribe }, this.opt.baseInject ?? {});
|
|
128
|
+
opts[key] = await this.inject(opts[key], Object.assign(baseInject, opts.inject));
|
|
129
|
+
}
|
|
130
|
+
return await this.send(opts);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Injects variables into a body string by replacing placeholder tokens
|
|
134
|
+
* @param body - The string content where variables should be injected
|
|
135
|
+
* @param inject - Object containing key-value pairs where keys are variable names and values are replacement content
|
|
136
|
+
* @returns Promise that resolves to the body string with all variables injected
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const result = await inject('Hello :name from :company', { name: 'John', company: 'ACME' });
|
|
140
|
+
* // Returns: 'Hello John from ACME'
|
|
141
|
+
* ```
|
|
142
|
+
* @private
|
|
143
|
+
*/
|
|
144
|
+
async inject(body, inject) {
|
|
145
|
+
// Sort variable names by length (longest first) to prevent partial matches
|
|
146
|
+
const sortedKeys = Object.keys(inject ?? {}).sort((a, b) => b.length - a.length);
|
|
147
|
+
sortedKeys.forEach((variableName) => {
|
|
148
|
+
const key = `:${variableName}`;
|
|
149
|
+
while (body.indexOf(key) !== -1) {
|
|
150
|
+
body = body.replace(key, inject[variableName].toString());
|
|
151
|
+
}
|
|
152
|
+
});
|
|
153
|
+
return body;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
exports.ZMailService = ZMailService;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ZOrm } from './orm';
|
|
2
|
+
import { ZSQLService } from '../sql_service';
|
|
3
|
+
import { ZMailBlacklist, ZMailBlacklistSearch } from '../types/mail_types';
|
|
4
|
+
export declare class ZMailBlacklistOrm extends ZOrm {
|
|
5
|
+
private hashSalt;
|
|
6
|
+
constructor(opt: { sqlService: ZSQLService; alias?: string; hashSalt?: string });
|
|
7
|
+
genEmailUnsubscribeHash({ email }: { email: string }): Promise<string>;
|
|
8
|
+
create(
|
|
9
|
+
item: Omit<ZMailBlacklist, 'updated_at' | 'created_at'>,
|
|
10
|
+
): Promise<Omit<ZMailBlacklist, 'updated_at' | 'created_at'>>;
|
|
11
|
+
findOne(conditions: Partial<ZMailBlacklist>): Promise<ZMailBlacklist>;
|
|
12
|
+
findAll(
|
|
13
|
+
conditions?: Partial<ZMailBlacklistSearch>,
|
|
14
|
+
opt?: {
|
|
15
|
+
limit?: number;
|
|
16
|
+
},
|
|
17
|
+
): Promise<ZMailBlacklist[]>;
|
|
18
|
+
update({ email, is_blacklisted }: Pick<ZMailBlacklist, 'email' | 'is_blacklisted'>): Promise<boolean>;
|
|
19
|
+
upsert(item: Omit<ZMailBlacklist, 'updated_at' | 'created_at'>): Promise<ZMailBlacklist>;
|
|
20
|
+
createTable(): Promise<void>;
|
|
21
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
3
|
+
exports.ZMailBlacklistOrm = void 0;
|
|
4
|
+
const orm_1 = require('./orm');
|
|
5
|
+
const crypto_service_1 = require('../crypto_service');
|
|
6
|
+
class ZMailBlacklistOrm extends orm_1.ZOrm {
|
|
7
|
+
constructor(opt) {
|
|
8
|
+
super({ sqlService: opt.sqlService, alias: opt.alias ?? 'email_blacklist' });
|
|
9
|
+
this.sqlService = opt.sqlService;
|
|
10
|
+
this.hashSalt = opt.hashSalt ?? 'ZTECHNO';
|
|
11
|
+
}
|
|
12
|
+
async genEmailUnsubscribeHash({ email }) {
|
|
13
|
+
const existingHash = await this.findOne({ email });
|
|
14
|
+
if (existingHash !== undefined) {
|
|
15
|
+
return existingHash.hash;
|
|
16
|
+
}
|
|
17
|
+
const hash = crypto_service_1.ZCryptoService.hash('sha512', `${this.hashSalt}-${email}`);
|
|
18
|
+
await this.create({ email, hash, is_blacklisted: 0 });
|
|
19
|
+
return hash;
|
|
20
|
+
}
|
|
21
|
+
async create(item) {
|
|
22
|
+
const res = await this.sqlService.query(
|
|
23
|
+
`
|
|
24
|
+
INSERT INTO \`${this.alias}\` (email, hash, is_blacklisted, updated_at, created_at)
|
|
25
|
+
VALUES (:email, :hash, :is_blacklisted, NOW(), NOW())
|
|
26
|
+
ON DUPLICATE KEY UPDATE hash=:hash, updated_at=NOW()
|
|
27
|
+
`,
|
|
28
|
+
item,
|
|
29
|
+
);
|
|
30
|
+
return item; // return Object.assign(item, { invoice_id: res.insertId }) as ZMailBlacklist
|
|
31
|
+
}
|
|
32
|
+
async findOne(conditions) {
|
|
33
|
+
const rows = await this.findAll(conditions, { limit: 1 });
|
|
34
|
+
return rows[0];
|
|
35
|
+
}
|
|
36
|
+
async findAll(conditions, opt) {
|
|
37
|
+
const whereKeys = Object.keys(conditions ?? {});
|
|
38
|
+
const whereClause = whereKeys.length ? `WHERE ${whereKeys.map((key) => `${key}=:${key}`).join(' AND ')}` : '';
|
|
39
|
+
const limit = opt?.limit ? `LIMIT ${opt.limit}` : '';
|
|
40
|
+
return await this.sqlService.exec({
|
|
41
|
+
query: /*SQL*/ `SELECT * FROM \`${this.alias}\` ${whereClause} ${limit}`,
|
|
42
|
+
params: conditions,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async update({ email, is_blacklisted }) {
|
|
46
|
+
const res = await this.sqlService.query(
|
|
47
|
+
`
|
|
48
|
+
UPDATE \`${this.alias}\` SET is_blacklisted=:is_blacklisted, updated_at=NOW() WHERE email=:email
|
|
49
|
+
`,
|
|
50
|
+
{ email, is_blacklisted },
|
|
51
|
+
);
|
|
52
|
+
return res.affectedRows !== 0;
|
|
53
|
+
}
|
|
54
|
+
async upsert(item) {
|
|
55
|
+
await this.sqlService.query(
|
|
56
|
+
`
|
|
57
|
+
INSERT INTO \`${this.alias}\` (email, hash, is_blacklisted, updated_at, created_at)
|
|
58
|
+
VALUES (:email, :hash, :is_blacklisted, NOW(), NOW())
|
|
59
|
+
ON DUPLICATE KEY UPDATE hash=:hash, is_blacklisted=:is_blacklisted, updated_at=NOW()
|
|
60
|
+
`,
|
|
61
|
+
item,
|
|
62
|
+
);
|
|
63
|
+
return item;
|
|
64
|
+
}
|
|
65
|
+
async createTable() {
|
|
66
|
+
await this.sqlService.query(/*SQL*/ `
|
|
67
|
+
CREATE TABLE \`${this.alias}\` (
|
|
68
|
+
\`email\` varchar(512) NOT NULL,
|
|
69
|
+
\`hash\` varchar(256) NOT NULL,
|
|
70
|
+
\`is_blacklisted\` tinyint(1) NOT NULL DEFAULT 0,
|
|
71
|
+
\`updated_at\` datetime NOT NULL DEFAULT current_timestamp(),
|
|
72
|
+
\`created_at\` datetime NOT NULL DEFAULT current_timestamp(),
|
|
73
|
+
PRIMARY KEY (\`email\`),
|
|
74
|
+
KEY \`is_blacklisted\` (\`is_blacklisted\`)
|
|
75
|
+
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
|
76
|
+
`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
exports.ZMailBlacklistOrm = ZMailBlacklistOrm;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ZSQLService } from '../sql_service';
|
|
2
|
+
/**
|
|
3
|
+
* Safely converts a value to a JSON string for storage in a JSON column.
|
|
4
|
+
* Prevents the mysql driver from expanding plain objects into `key`=value pairs.
|
|
5
|
+
*/
|
|
6
|
+
export declare function toJsonColumn(value: any): string | null;
|
|
7
|
+
/**
|
|
8
|
+
* Converts an ISO 8601 date string (e.g. from Mollie API) to MySQL DATETIME format.
|
|
9
|
+
* Accepts `2026-02-26T00:47:04+00:00` → `2026-02-26 00:47:04`
|
|
10
|
+
*/
|
|
11
|
+
export declare function toDatetime(value: string | null | undefined): string | null;
|
|
12
|
+
/**
|
|
13
|
+
* Converts a Date object to MySQL DATETIME format.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatDatetime(value: Date): string;
|
|
16
|
+
/**
|
|
17
|
+
* Converts a date-only string (e.g. `2026-02-26`) to MySQL DATETIME format.
|
|
18
|
+
*/
|
|
19
|
+
export declare function toDatetimeFromDateOnly(value: string | null | undefined): string | null;
|
|
20
|
+
export declare class ZOrm {
|
|
21
|
+
readonly alias: string;
|
|
22
|
+
protected sqlService: ZSQLService;
|
|
23
|
+
constructor(opt: { alias: string; sqlService: ZSQLService });
|
|
24
|
+
ensureTableExists(): Promise<void>;
|
|
25
|
+
private checkTableExists;
|
|
26
|
+
createTable(): Promise<void>;
|
|
27
|
+
}
|