@technomoron/mail-magic 1.0.34 → 1.0.35
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/CHANGES +11 -0
- package/dist/api/assets.js +2 -5
- package/dist/api/mailer.js +1 -3
- package/dist/bin/mail-magic.js +32 -2
- package/package.json +1 -1
- package/dist/api/form-replyto.js +0 -1
- package/dist/api/form-submission.js +0 -1
package/CHANGES
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
Version 1.0.35 (2026-02-17)
|
|
2
|
+
|
|
3
|
+
- Enforce deterministic locale resolution for transactional template sends:
|
|
4
|
+
requested locale first, then root fallback (`locale=''`) only.
|
|
5
|
+
- Enforce the same deterministic locale resolution for template-scoped asset uploads
|
|
6
|
+
(`POST /api/v1/assets`) for both `tx` and `form` template types.
|
|
7
|
+
- Remove non-deterministic fallback to arbitrary locale records when requested/root
|
|
8
|
+
locales are missing.
|
|
9
|
+
- Add regression tests covering deterministic locale fallback and missing-locale
|
|
10
|
+
behavior for both transactional sends and template asset upload resolution.
|
|
11
|
+
|
|
1
12
|
Version 1.0.34 (2026-02-10)
|
|
2
13
|
|
|
3
14
|
- Ensure inline form template assets (CID) are actually attached when delivering public form submissions.
|
package/dist/api/assets.js
CHANGED
|
@@ -22,11 +22,9 @@ export class AssetAPI extends ApiModule {
|
|
|
22
22
|
}
|
|
23
23
|
const templateType = templateTypeRaw.toLowerCase();
|
|
24
24
|
const domainId = apireq.domain.domain_id;
|
|
25
|
-
const deflocale = this.server.storage.deflocale || '';
|
|
26
25
|
if (templateType === 'tx') {
|
|
27
26
|
const template = (await api_txmail.findOne({ where: { name: templateName, domain_id: domainId, locale } })) ||
|
|
28
|
-
(await api_txmail.findOne({ where: { name: templateName, domain_id: domainId, locale:
|
|
29
|
-
(await api_txmail.findOne({ where: { name: templateName, domain_id: domainId } }));
|
|
27
|
+
(await api_txmail.findOne({ where: { name: templateName, domain_id: domainId, locale: '' } }));
|
|
30
28
|
if (!template) {
|
|
31
29
|
throw new ApiError({
|
|
32
30
|
code: 404,
|
|
@@ -43,8 +41,7 @@ export class AssetAPI extends ApiModule {
|
|
|
43
41
|
}
|
|
44
42
|
if (templateType === 'form') {
|
|
45
43
|
const form = (await api_form.findOne({ where: { idname: templateName, domain_id: domainId, locale } })) ||
|
|
46
|
-
(await api_form.findOne({ where: { idname: templateName, domain_id: domainId, locale:
|
|
47
|
-
(await api_form.findOne({ where: { idname: templateName, domain_id: domainId } }));
|
|
44
|
+
(await api_form.findOne({ where: { idname: templateName, domain_id: domainId, locale: '' } }));
|
|
48
45
|
if (!form) {
|
|
49
46
|
throw new ApiError({
|
|
50
47
|
code: 404,
|
package/dist/api/mailer.js
CHANGED
|
@@ -100,13 +100,11 @@ export class MailerAPI extends ApiModule {
|
|
|
100
100
|
throw new ApiError({ code: 400, message: 'Invalid email address(es): ' + invalid.join(',') });
|
|
101
101
|
}
|
|
102
102
|
let template = null;
|
|
103
|
-
const deflocale = this.server.storage.deflocale || '';
|
|
104
103
|
const domain_id = apireq.domain.domain_id;
|
|
105
104
|
try {
|
|
106
105
|
template =
|
|
107
106
|
(await api_txmail.findOne({ where: { name, domain_id, locale } })) ||
|
|
108
|
-
(await api_txmail.findOne({ where: { name, domain_id, locale:
|
|
109
|
-
(await api_txmail.findOne({ where: { name, domain_id } }));
|
|
107
|
+
(await api_txmail.findOne({ where: { name, domain_id, locale: '' } }));
|
|
110
108
|
}
|
|
111
109
|
catch (error) {
|
|
112
110
|
throw new ApiError({
|
package/dist/bin/mail-magic.js
CHANGED
|
@@ -7,13 +7,15 @@ import { startMailMagicServer } from '../index.js';
|
|
|
7
7
|
const args = process.argv.slice(2);
|
|
8
8
|
function usage(exitCode = 0) {
|
|
9
9
|
const out = exitCode === 0 ? process.stdout : process.stderr;
|
|
10
|
-
out.write(`Usage: mail-magic [--env PATH]\n\n` +
|
|
10
|
+
out.write(`Usage: mail-magic [--env PATH] [--config DIR]\n\n` +
|
|
11
11
|
`Options:\n` +
|
|
12
12
|
` -e, --env PATH Path to .env (defaults to ./.env)\n` +
|
|
13
|
+
` -c, --config DIR Config directory (overrides CONFIG_PATH)\n` +
|
|
13
14
|
` -h, --help Show this help\n`);
|
|
14
15
|
process.exit(exitCode);
|
|
15
16
|
}
|
|
16
17
|
let envPath;
|
|
18
|
+
let configPath;
|
|
17
19
|
for (let i = 0; i < args.length; i += 1) {
|
|
18
20
|
const arg = args[i];
|
|
19
21
|
if (arg === '-h' || arg === '--help') {
|
|
@@ -29,10 +31,24 @@ for (let i = 0; i < args.length; i += 1) {
|
|
|
29
31
|
i += 1;
|
|
30
32
|
continue;
|
|
31
33
|
}
|
|
34
|
+
if (arg === '-c' || arg === '--config') {
|
|
35
|
+
const next = args[i + 1];
|
|
36
|
+
if (!next) {
|
|
37
|
+
console.error('Error: --config requires a directory');
|
|
38
|
+
usage(1);
|
|
39
|
+
}
|
|
40
|
+
configPath = next;
|
|
41
|
+
i += 1;
|
|
42
|
+
continue;
|
|
43
|
+
}
|
|
32
44
|
if (arg.startsWith('--env=')) {
|
|
33
45
|
envPath = arg.slice('--env='.length);
|
|
34
46
|
continue;
|
|
35
47
|
}
|
|
48
|
+
if (arg.startsWith('--config=')) {
|
|
49
|
+
configPath = arg.slice('--config='.length);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
36
52
|
console.error(`Error: unknown option ${arg}`);
|
|
37
53
|
usage(1);
|
|
38
54
|
}
|
|
@@ -41,6 +57,19 @@ if (!fs.existsSync(resolvedEnvPath)) {
|
|
|
41
57
|
console.error(`Error: env file not found at ${resolvedEnvPath}`);
|
|
42
58
|
process.exit(1);
|
|
43
59
|
}
|
|
60
|
+
let resolvedConfigPath;
|
|
61
|
+
if (configPath) {
|
|
62
|
+
// Resolve the config dir relative to the .env directory (we chdir there next).
|
|
63
|
+
resolvedConfigPath = path.resolve(path.dirname(resolvedEnvPath), configPath);
|
|
64
|
+
if (!fs.existsSync(resolvedConfigPath)) {
|
|
65
|
+
console.error(`Error: config dir not found at ${resolvedConfigPath}`);
|
|
66
|
+
process.exit(1);
|
|
67
|
+
}
|
|
68
|
+
if (!fs.statSync(resolvedConfigPath).isDirectory()) {
|
|
69
|
+
console.error(`Error: config path is not a directory: ${resolvedConfigPath}`);
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
44
73
|
process.chdir(path.dirname(resolvedEnvPath));
|
|
45
74
|
const result = dotenv.config({ path: resolvedEnvPath });
|
|
46
75
|
if (result.error) {
|
|
@@ -50,7 +79,8 @@ if (result.error) {
|
|
|
50
79
|
}
|
|
51
80
|
async function main() {
|
|
52
81
|
try {
|
|
53
|
-
const {
|
|
82
|
+
const envOverrides = resolvedConfigPath ? { CONFIG_PATH: resolvedConfigPath } : {};
|
|
83
|
+
const { store, vars } = await startMailMagicServer({}, envOverrides);
|
|
54
84
|
console.log(`Using config path: ${store.configpath}`);
|
|
55
85
|
console.log(`mail-magic server listening on ${vars.API_HOST}:${vars.API_PORT}`);
|
|
56
86
|
}
|
package/package.json
CHANGED
package/dist/api/form-replyto.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../util/form-replyto.js';
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from '../util/form-submission.js';
|