@technomoron/mail-magic-client 1.0.23 → 1.0.25

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 CHANGED
@@ -1,3 +1,8 @@
1
+ Version 1.0.25 (2026-02-07)
2
+
3
+ - `sendFormMessage()` now requires `domain` when sending by `formid`, and also
4
+ supports sending by `form_key`.
5
+
1
6
  Version 1.0.23 (2026-01-31)
2
7
 
3
8
  - Fixed the per-package release script name and tag format used to trigger
@@ -1,3 +1,8 @@
1
+ type JsonPrimitive = string | number | boolean | null;
2
+ type JsonValue = JsonPrimitive | JsonValue[] | {
3
+ [key: string]: JsonValue;
4
+ };
5
+ type RequestBody = JsonValue | object;
1
6
  interface templateData {
2
7
  template: string;
3
8
  domain: string;
@@ -22,18 +27,19 @@ interface sendTemplateData {
22
27
  rcpt: string;
23
28
  domain: string;
24
29
  locale?: string;
25
- vars?: object;
30
+ vars?: Record<string, unknown>;
26
31
  replyTo?: string;
27
32
  headers?: Record<string, string>;
28
33
  attachments?: AttachmentInput[];
29
34
  }
30
35
  interface sendFormData {
31
- formid: string;
36
+ formid?: string;
37
+ form_key?: string;
32
38
  secret?: string;
33
39
  recipient?: string;
34
40
  domain?: string;
35
41
  locale?: string;
36
- vars?: object;
42
+ vars?: Record<string, unknown>;
37
43
  replyTo?: string;
38
44
  fields?: Record<string, unknown>;
39
45
  attachments?: AttachmentInput[];
@@ -57,11 +63,11 @@ declare class templateClient {
57
63
  private baseURL;
58
64
  private apiKey;
59
65
  constructor(baseURL: string, apiKey: string);
60
- request<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', command: string, body?: any): Promise<T>;
66
+ request<T>(method: 'GET' | 'POST' | 'PUT' | 'DELETE', command: string, body?: RequestBody): Promise<T>;
61
67
  get<T>(command: string): Promise<T>;
62
- post<T>(command: string, body: any): Promise<T>;
63
- put<T>(command: string, body: any): Promise<T>;
64
- delete<T>(command: string, body?: any): Promise<T>;
68
+ post<T>(command: string, body: RequestBody): Promise<T>;
69
+ put<T>(command: string, body: RequestBody): Promise<T>;
70
+ delete<T>(command: string, body?: RequestBody): Promise<T>;
65
71
  validateEmails(list: string): {
66
72
  valid: string[];
67
73
  invalid: string[];
@@ -71,12 +77,12 @@ declare class templateClient {
71
77
  private createAttachmentPayload;
72
78
  private appendFields;
73
79
  private postFormData;
74
- storeTemplate(td: templateData): Promise<any>;
75
- sendTemplate(std: sendTemplateData): Promise<any>;
76
- storeTxTemplate(td: templateData): Promise<any>;
77
- sendTxMessage(std: sendTemplateData): Promise<any>;
78
- storeFormTemplate(data: formTemplateData): Promise<any>;
79
- sendFormMessage(data: sendFormData): Promise<any>;
80
- uploadAssets(data: uploadAssetsData): Promise<any>;
80
+ storeTemplate(td: templateData): Promise<unknown>;
81
+ sendTemplate(std: sendTemplateData): Promise<unknown>;
82
+ storeTxTemplate(td: templateData): Promise<unknown>;
83
+ sendTxMessage(std: sendTemplateData): Promise<unknown>;
84
+ storeFormTemplate(data: formTemplateData): Promise<unknown>;
85
+ sendFormMessage(data: sendFormData): Promise<unknown>;
86
+ uploadAssets(data: uploadAssetsData): Promise<unknown>;
81
87
  }
82
88
  export default templateClient;
@@ -71,7 +71,7 @@ class templateClient {
71
71
  validateTemplate(template) {
72
72
  try {
73
73
  const env = new nunjucks_1.default.Environment(new nunjucks_1.default.FileSystemLoader(['./templates']));
74
- const t = env.renderString(template, {});
74
+ env.renderString(template, {});
75
75
  }
76
76
  catch (error) {
77
77
  if (error instanceof Error) {
@@ -168,7 +168,7 @@ class templateClient {
168
168
  if (!std.name || !std.rcpt) {
169
169
  throw new Error('Invalid request body; name/rcpt required');
170
170
  }
171
- const { valid, invalid } = this.validateEmails(std.rcpt);
171
+ const { invalid } = this.validateEmails(std.rcpt);
172
172
  if (invalid.length > 0) {
173
173
  throw new Error('Invalid email address(es): ' + invalid.join(','));
174
174
  }
@@ -218,12 +218,16 @@ class templateClient {
218
218
  return this.post('/api/v1/form/template', data);
219
219
  }
220
220
  async sendFormMessage(data) {
221
- if (!data.formid) {
222
- throw new Error('Invalid request body; formid required');
221
+ if (!data.form_key && !data.formid) {
222
+ throw new Error('Invalid request body; formid or form_key required');
223
+ }
224
+ if (!data.form_key && !data.domain) {
225
+ throw new Error('Invalid request body; domain required when sending by formid');
223
226
  }
224
227
  const fields = data.fields || {};
225
228
  const baseFields = {
226
229
  formid: data.formid,
230
+ form_key: data.form_key,
227
231
  secret: data.secret,
228
232
  recipient: data.recipient,
229
233
  domain: data.domain,
@@ -236,6 +240,7 @@ class templateClient {
236
240
  const { formData } = this.createAttachmentPayload(data.attachments);
237
241
  this.appendFields(formData, {
238
242
  formid: data.formid,
243
+ form_key: data.form_key,
239
244
  secret: data.secret,
240
245
  recipient: data.recipient,
241
246
  domain: data.domain,
package/dist/cli.js CHANGED
@@ -66,6 +66,24 @@ const getTemplateData = async () => {
66
66
  return await readStdin();
67
67
  }
68
68
  };
69
+ const isPlainObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
70
+ const parseVarsOption = (input) => {
71
+ if (!input) {
72
+ return {};
73
+ }
74
+ let parsed;
75
+ try {
76
+ parsed = JSON.parse(input);
77
+ }
78
+ catch (error) {
79
+ const message = error instanceof Error ? error.message : String(error);
80
+ throw new Error(`Invalid JSON for --vars: ${message}`);
81
+ }
82
+ if (!isPlainObject(parsed)) {
83
+ throw new Error('--vars must be a JSON object');
84
+ }
85
+ return parsed;
86
+ };
69
87
  program
70
88
  .command('template')
71
89
  .description('Store a template on the server')
@@ -82,7 +100,7 @@ program
82
100
  domain: program.opts().domain,
83
101
  part: !!program.opts().part
84
102
  };
85
- const result = await client.storeTemplate(templateData);
103
+ await client.storeTemplate(templateData);
86
104
  console.log('Template updated');
87
105
  }
88
106
  catch (error) {
@@ -101,8 +119,7 @@ program
101
119
  .action(async () => {
102
120
  const client = new mail_magic_client_1.default(program.opts().api, program.opts().token);
103
121
  try {
104
- const template = await getTemplateData();
105
- const vars = program.opts().vars ? JSON.parse(program.opts().vars) : '{}';
122
+ const vars = parseVarsOption(program.opts().vars);
106
123
  const templateData = {
107
124
  name: program.opts().name,
108
125
  rcpt: program.opts().rcpt,
@@ -110,7 +127,7 @@ program
110
127
  locale: program.opts().locale,
111
128
  vars
112
129
  };
113
- const result = await client.sendTemplate(templateData);
130
+ await client.sendTemplate(templateData);
114
131
  console.log('Template sent');
115
132
  }
116
133
  catch (error) {
@@ -126,7 +143,7 @@ program
126
143
  program
127
144
  .command('version')
128
145
  .description('Show current client version')
129
- .action(async (cmdOptions) => {
146
+ .action(async () => {
130
147
  console.log('1.0.19');
131
148
  });
132
149
  program
@@ -66,7 +66,7 @@ class templateClient {
66
66
  validateTemplate(template) {
67
67
  try {
68
68
  const env = new nunjucks.Environment(new nunjucks.FileSystemLoader(['./templates']));
69
- const t = env.renderString(template, {});
69
+ env.renderString(template, {});
70
70
  }
71
71
  catch (error) {
72
72
  if (error instanceof Error) {
@@ -163,7 +163,7 @@ class templateClient {
163
163
  if (!std.name || !std.rcpt) {
164
164
  throw new Error('Invalid request body; name/rcpt required');
165
165
  }
166
- const { valid, invalid } = this.validateEmails(std.rcpt);
166
+ const { invalid } = this.validateEmails(std.rcpt);
167
167
  if (invalid.length > 0) {
168
168
  throw new Error('Invalid email address(es): ' + invalid.join(','));
169
169
  }
@@ -213,12 +213,16 @@ class templateClient {
213
213
  return this.post('/api/v1/form/template', data);
214
214
  }
215
215
  async sendFormMessage(data) {
216
- if (!data.formid) {
217
- throw new Error('Invalid request body; formid required');
216
+ if (!data.form_key && !data.formid) {
217
+ throw new Error('Invalid request body; formid or form_key required');
218
+ }
219
+ if (!data.form_key && !data.domain) {
220
+ throw new Error('Invalid request body; domain required when sending by formid');
218
221
  }
219
222
  const fields = data.fields || {};
220
223
  const baseFields = {
221
224
  formid: data.formid,
225
+ form_key: data.form_key,
222
226
  secret: data.secret,
223
227
  recipient: data.recipient,
224
228
  domain: data.domain,
@@ -231,6 +235,7 @@ class templateClient {
231
235
  const { formData } = this.createAttachmentPayload(data.attachments);
232
236
  this.appendFields(formData, {
233
237
  formid: data.formid,
238
+ form_key: data.form_key,
234
239
  secret: data.secret,
235
240
  recipient: data.recipient,
236
241
  domain: data.domain,
@@ -71,7 +71,7 @@ class templateClient {
71
71
  validateTemplate(template) {
72
72
  try {
73
73
  const env = new nunjucks_1.default.Environment(new nunjucks_1.default.FileSystemLoader(['./templates']));
74
- const t = env.renderString(template, {});
74
+ env.renderString(template, {});
75
75
  }
76
76
  catch (error) {
77
77
  if (error instanceof Error) {
@@ -168,7 +168,7 @@ class templateClient {
168
168
  if (!std.name || !std.rcpt) {
169
169
  throw new Error('Invalid request body; name/rcpt required');
170
170
  }
171
- const { valid, invalid } = this.validateEmails(std.rcpt);
171
+ const { invalid } = this.validateEmails(std.rcpt);
172
172
  if (invalid.length > 0) {
173
173
  throw new Error('Invalid email address(es): ' + invalid.join(','));
174
174
  }
@@ -218,12 +218,16 @@ class templateClient {
218
218
  return this.post('/api/v1/form/template', data);
219
219
  }
220
220
  async sendFormMessage(data) {
221
- if (!data.formid) {
222
- throw new Error('Invalid request body; formid required');
221
+ if (!data.form_key && !data.formid) {
222
+ throw new Error('Invalid request body; formid or form_key required');
223
+ }
224
+ if (!data.form_key && !data.domain) {
225
+ throw new Error('Invalid request body; domain required when sending by formid');
223
226
  }
224
227
  const fields = data.fields || {};
225
228
  const baseFields = {
226
229
  formid: data.formid,
230
+ form_key: data.form_key,
227
231
  secret: data.secret,
228
232
  recipient: data.recipient,
229
233
  domain: data.domain,
@@ -236,6 +240,7 @@ class templateClient {
236
240
  const { formData } = this.createAttachmentPayload(data.attachments);
237
241
  this.appendFields(formData, {
238
242
  formid: data.formid,
243
+ form_key: data.form_key,
239
244
  secret: data.secret,
240
245
  recipient: data.recipient,
241
246
  domain: data.domain,
@@ -55,7 +55,6 @@ class PreprocessExtension {
55
55
  constructor() {
56
56
  this.tags = ['process_layout'];
57
57
  }
58
- // types from nunjucks are not exported for parser/nodes; use any
59
58
  parse(parser, nodes) {
60
59
  const token = parser.nextToken();
61
60
  const args = parser.parseSignature(null, true);
@@ -114,8 +113,8 @@ function process_template(tplname, writeOutput = true) {
114
113
  // decodeEntities: false
115
114
  });
116
115
  // <container> -> <table>
117
- $('container').each(function () {
118
- const $container = $(this);
116
+ $('container').each((_index, element) => {
117
+ const $container = $(element);
119
118
  const $table = $('<table/>').attr({
120
119
  align: 'center',
121
120
  class: $container.attr('class') || '',
@@ -130,8 +129,8 @@ function process_template(tplname, writeOutput = true) {
130
129
  $container.replaceWith($table);
131
130
  });
132
131
  // <row> -> <tr>
133
- $('row').each(function () {
134
- const $row = $(this);
132
+ $('row').each((_index, element) => {
133
+ const $row = $(element);
135
134
  const background = $row.attr('background') || '';
136
135
  const $tr = $('<tr/>').attr({ class: $row.attr('class') || '' });
137
136
  if (background)
@@ -140,8 +139,8 @@ function process_template(tplname, writeOutput = true) {
140
139
  $row.replaceWith($tr);
141
140
  });
142
141
  // <columns> -> <td>
143
- $('columns').each(function () {
144
- const $columns = $(this);
142
+ $('columns').each((_index, element) => {
143
+ const $columns = $(element);
145
144
  const padding = $columns.attr('padding') || '0';
146
145
  const $td = $('<td/>').attr({
147
146
  class: $columns.attr('class') || '',
@@ -151,8 +150,8 @@ function process_template(tplname, writeOutput = true) {
151
150
  $columns.replaceWith($td);
152
151
  });
153
152
  // <button> -> <a>
154
- $('button').each(function () {
155
- const $button = $(this);
153
+ $('button').each((_index, element) => {
154
+ const $button = $(element);
156
155
  const href = $button.attr('href') || '#';
157
156
  const buttonClass = $button.attr('class') || '';
158
157
  const $a = $('<a/>').attr({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@technomoron/mail-magic-client",
3
- "version": "1.0.23",
3
+ "version": "1.0.25",
4
4
  "description": "Client library for mail-magic",
5
5
  "main": "dist/cjs/mail-magic-client.js",
6
6
  "types": "dist/cjs/mail-magic-client.d.ts",
@@ -17,11 +17,11 @@
17
17
  "build": "npm run build:cjs && npm run build:esm && npm run build:cli",
18
18
  "test": "vitest run",
19
19
  "test:watch": "vitest",
20
- "lint": "eslint --ext .js,.ts,.vue ./src",
21
- "lintfix": "eslint --fix --ext .js,.ts,.vue,.json ./src",
20
+ "lint": "node ../../node_modules/eslint/bin/eslint.js --config ../../eslint.config.mjs --no-error-on-unmatched-pattern --ext .js,.cjs,.mjs,.ts,.mts,.tsx,.vue,.json ./src",
21
+ "lintfix": "node ../../node_modules/eslint/bin/eslint.js --config ../../eslint.config.mjs --fix --no-error-on-unmatched-pattern --ext .js,.cjs,.mjs,.ts,.mts,.tsx,.vue,.json ./src",
22
22
  "format": "npm run lintfix && npm run pretty",
23
- "pretty": "prettier --write \"**/*.{js,ts,vue,json,css,scss,md}\"",
24
- "cleanbuild": "rm -rf ./dist/ && npm run lintfix && npm run format && npm run build"
23
+ "pretty": "node ../../node_modules/prettier/bin/prettier.cjs --config ../../.prettierrc --write \"**/*.{js,ts,vue,json,css,scss,md}\"",
24
+ "cleanbuild": "rm -rf ./dist/ && npm run format && npm run build"
25
25
  },
26
26
  "repository": {
27
27
  "type": "git",
@@ -40,30 +40,13 @@
40
40
  "cheerio": "^1.1.2",
41
41
  "commander": "^10.0.1",
42
42
  "email-addresses": "^5.0.0",
43
- "foundation-emails": "^2.4.0",
44
- "inky": "^0.1.0",
45
43
  "juice": "^11.0.1",
46
- "node-fetch": "^3.3.2",
47
44
  "nunjucks": "^3.2.4"
48
45
  },
49
46
  "devDependencies": {
50
- "@types/cheerio": "^1.0.0",
51
47
  "@types/node": "^20.19.11",
52
48
  "@types/nunjucks": "^3.2.6",
53
- "@typescript-eslint/eslint-plugin": "^8.30.1",
54
- "@typescript-eslint/parser": "^8.30.1",
55
- "@vue/eslint-config-prettier": "^10.2.0",
56
- "@vue/eslint-config-typescript": "^14.5.0",
57
- "eslint": "^9.34.0",
58
- "eslint-config-prettier": "^10.1.5",
59
- "eslint-import-resolver-alias": "^1.1.2",
60
- "eslint-plugin-import": "^2.31.0",
61
- "eslint-plugin-nuxt": "^4.0.0",
62
- "eslint-plugin-prettier": "^5.4.1",
63
- "eslint-plugin-vue": "^10.0.0",
64
- "prettier": "^3.5.3",
65
49
  "typescript": "^5.9.2",
66
- "vitest": "^4.0.16",
67
- "vue-eslint-parser": "^10.1.3"
50
+ "vitest": "^4.0.16"
68
51
  }
69
52
  }