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.
Files changed (63) hide show
  1. package/lib/core/crypto_service.d.ts +23 -0
  2. package/lib/core/crypto_service.js +100 -0
  3. package/lib/core/engine_base.d.ts +11 -0
  4. package/lib/core/engine_base.js +9 -0
  5. package/lib/core/index.d.ts +14 -0
  6. package/lib/core/index.js +101 -0
  7. package/lib/core/mail_service.d.ts +85 -0
  8. package/lib/core/mail_service.js +156 -0
  9. package/lib/core/orm/mail_blacklist_orm.d.ts +21 -0
  10. package/lib/core/orm/mail_blacklist_orm.js +79 -0
  11. package/lib/core/orm/orm.d.ts +27 -0
  12. package/lib/core/orm/orm.js +67 -0
  13. package/lib/core/sql_service.d.ts +195 -0
  14. package/lib/core/sql_service.js +333 -0
  15. package/lib/core/translate_service.d.ts +48 -0
  16. package/lib/core/translate_service.js +913 -0
  17. package/lib/core/types/crypto_types.d.ts +4 -0
  18. package/lib/core/types/crypto_types.js +2 -0
  19. package/lib/core/types/mail_types.d.ts +95 -0
  20. package/lib/core/types/mail_types.js +2 -0
  21. package/lib/core/types/site_config.d.ts +46 -0
  22. package/lib/core/types/site_config.js +2 -0
  23. package/lib/core/types/translate_types.d.ts +69 -0
  24. package/lib/core/types/translate_types.js +46 -0
  25. package/lib/core/types/user_types.d.ts +41 -0
  26. package/lib/core/types/user_types.js +2 -0
  27. package/lib/core/user_service.d.ts +87 -0
  28. package/lib/core/user_service.js +216 -0
  29. package/lib/express/index.d.ts +1 -0
  30. package/lib/express/index.js +18 -0
  31. package/lib/index.d.ts +17 -8
  32. package/lib/index.js +60 -16
  33. package/lib/mollie/index.d.ts +5 -0
  34. package/lib/mollie/index.js +62 -0
  35. package/lib/mollie/orm/customers_orm.d.ts +16 -0
  36. package/lib/mollie/orm/customers_orm.js +115 -0
  37. package/lib/mollie/orm/invoice_items_orm.d.ts +9 -0
  38. package/lib/mollie/orm/invoice_items_orm.js +71 -0
  39. package/lib/mollie/orm/invoice_payments_orm.d.ts +10 -0
  40. package/lib/mollie/orm/invoice_payments_orm.js +70 -0
  41. package/lib/mollie/orm/invoices_orm.d.ts +40 -0
  42. package/lib/mollie/orm/invoices_orm.js +172 -0
  43. package/lib/mollie/orm/subscription_items_orm.d.ts +9 -0
  44. package/lib/mollie/orm/subscription_items_orm.js +45 -0
  45. package/lib/mollie/orm/subscriptions_orm.d.ts +17 -0
  46. package/lib/mollie/orm/subscriptions_orm.js +122 -0
  47. package/lib/mollie/services/customer_service.d.ts +14 -0
  48. package/lib/mollie/services/customer_service.js +53 -0
  49. package/lib/mollie/services/invoice_service.d.ts +102 -0
  50. package/lib/mollie/services/invoice_service.js +866 -0
  51. package/lib/mollie/services/mollie_service.d.ts +42 -0
  52. package/lib/mollie/services/mollie_service.js +370 -0
  53. package/lib/mollie/services/subscription_service.d.ts +32 -0
  54. package/lib/mollie/services/subscription_service.js +134 -0
  55. package/lib/mollie/types/internal_types.d.ts +19 -0
  56. package/lib/mollie/types/internal_types.js +2 -0
  57. package/lib/mollie/types/mollie_types.d.ts +187 -0
  58. package/lib/mollie/types/mollie_types.js +3 -0
  59. package/lib/mollie/util/subscription_utils.d.ts +8 -0
  60. package/lib/mollie/util/subscription_utils.js +37 -0
  61. package/lib/schema/MySQLSchemaExtractor.d.ts +1 -1
  62. package/lib/schema/MySQLSchemaImporter.d.ts +1 -1
  63. 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,9 @@
1
+ 'use strict';
2
+ Object.defineProperty(exports, '__esModule', { value: true });
3
+ exports.ZEngineBase = void 0;
4
+ class ZEngineBase {
5
+ static start() {
6
+ throw new Error(`Please Override ZEngineBase`);
7
+ }
8
+ }
9
+ exports.ZEngineBase = ZEngineBase;
@@ -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
+ }