@technomoron/mail-magic-client 1.0.30 → 1.0.32

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,25 @@
1
+ CHANGES
2
+ =======
3
+
4
+ Unreleased (2026-02-22)
5
+
6
+ - chore(release): add package-level `release:check` script and wire `release` to shared publish script.
7
+ - chore(scripts): replace `rm -rf` cleanup scripts with `rimraf`.
8
+ - test(logging): quiet package test output by default (silent Vitest with compact dot reporter).
9
+ - (Changes generated/assisted by Codex (profile: chatgpt-5.3-codex/medium).)
10
+
11
+ Version 1.0.32 (2026-02-22)
12
+
13
+ - chore(changes): normalize this package changelog to required CHANGES format.
14
+ - (Changes generated/assisted by Codex (profile: chatgpt-5.3-codex/medium).)
15
+
16
+ Version 1.0.31 (2026-02-19)
17
+
18
+ - Extract CLI implementation to dedicated `@technomoron/mail-magic-cli`
19
+ package; remove CLI build/bin and CLI-only dependencies from this package.
20
+ - Replace `forEach` with `for...of` and use separate `const` declarations in
21
+ `validateEmails` for consistency with server-side style.
22
+
1
23
  Version 1.0.30 (2026-02-17)
2
24
 
3
25
  - Refactor template preprocess compilation to use per-invocation configuration
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @technomoron/mail-magic-client
2
2
 
3
- Client library and CLI for the mail-magic server.
3
+ Typed client library for the mail-magic server.
4
4
 
5
5
  ## Install
6
6
 
@@ -95,73 +95,10 @@ await client.sendFormMessage({
95
95
 
96
96
  ## CLI
97
97
 
98
- The package ships `mm-cli`.
99
-
100
- ### .mmcli-env
101
-
102
- Create `.mmcli-env` in your working directory to set defaults:
103
-
104
- ```ini
105
- MMCLI_API=http://127.0.0.1:3776
106
- MMCLI_TOKEN=example-token
107
- MMCLI_DOMAIN=example.test
108
- ```
109
-
110
- `MMCLI_TOKEN` is treated as the server token string. As a convenience, `MMCLI_USERNAME` + `MMCLI_PASSWORD` can be used
111
- to build a combined token string (for legacy setups).
112
-
113
- ### Template Commands
114
-
115
- Compile a template locally:
116
-
117
- ```bash
118
- mm-cli compile --input ./templates --output ./templates-dist
119
- ```
120
-
121
- Push a single transactional template (compile + upload):
122
-
123
- ```bash
124
- mm-cli push --template tx-template/en/welcome --domain example.test --input ./templates
125
- ```
126
-
127
- Dry-run a single template upload:
128
-
129
- ```bash
130
- mm-cli push --template tx-template/en/welcome --domain example.test --input ./templates --dry-run
131
- ```
132
-
133
- Push an entire config-style directory:
134
-
135
- ```bash
136
- mm-cli push-dir --input ./data --domain example.test
137
- mm-cli push-dir --input ./data --domain example.test --dry-run
138
- mm-cli push-dir --input ./data --domain example.test --skip-assets
139
- ```
140
-
141
- ### Asset Uploads
142
-
143
- Upload stand-alone domain assets:
144
-
145
- ```bash
146
- mm-cli assets --file ./logo.png --domain example.test
147
- ```
148
-
149
- Dry-run an asset upload:
150
-
151
- ```bash
152
- mm-cli assets --file ./logo.png --domain example.test --dry-run
153
- ```
154
-
155
- Upload assets scoped to a template:
156
-
157
- ```bash
158
- mm-cli assets --file ./hero.png --domain example.test --template-type tx --template welcome --locale en --path images
159
- ```
98
+ The CLI is now a separate package: `@technomoron/mail-magic-cli`.
160
99
 
161
100
  ## Notes
162
101
 
163
- - `push-dir` expects a `init-data.json` and domain folders that match the server config layout.
164
- - Asset uploads use the server endpoint `POST /api/v1/assets`.
165
102
  - OpenAPI spec (when enabled): `await client.getSwaggerSpec()`
166
103
  - Public asset fetch helpers:
167
104
  - `await client.fetchPublicAsset('example.test', 'images/logo.png')` -> `/asset/{domain}/{path}`
@@ -3,7 +3,13 @@ type JsonValue = JsonPrimitive | JsonValue[] | {
3
3
  [key: string]: JsonValue;
4
4
  };
5
5
  type RequestBody = JsonValue | object;
6
- interface templateData {
6
+ export type ApiResponse<T = unknown> = {
7
+ Status?: string;
8
+ data?: T;
9
+ message?: string;
10
+ [key: string]: unknown;
11
+ };
12
+ export interface StoreTxTemplateInput {
7
13
  template: string;
8
14
  domain: string;
9
15
  sender?: string;
@@ -12,7 +18,7 @@ interface templateData {
12
18
  locale?: string;
13
19
  part?: boolean;
14
20
  }
15
- interface formTemplateData {
21
+ export interface StoreFormTemplateInput {
16
22
  idname: string;
17
23
  domain: string;
18
24
  template: string;
@@ -26,7 +32,7 @@ interface formTemplateData {
26
32
  allowed_fields?: string[] | string;
27
33
  captcha_required?: boolean;
28
34
  }
29
- interface formRecipientData {
35
+ export interface StoreFormRecipientInput {
30
36
  domain: string;
31
37
  idname: string;
32
38
  email: string;
@@ -35,7 +41,7 @@ interface formRecipientData {
35
41
  formid?: string;
36
42
  locale?: string;
37
43
  }
38
- interface sendTemplateData {
44
+ export interface SendTxMessageInput {
39
45
  name: string;
40
46
  rcpt: string;
41
47
  domain: string;
@@ -45,21 +51,21 @@ interface sendTemplateData {
45
51
  headers?: Record<string, string>;
46
52
  attachments?: AttachmentInput[];
47
53
  }
48
- interface sendFormData {
54
+ export interface SendFormMessageInput {
49
55
  _mm_form_key: string;
50
56
  _mm_locale?: string;
51
57
  _mm_recipients?: string[] | string;
52
58
  fields?: Record<string, unknown>;
53
59
  attachments?: AttachmentInput[];
54
60
  }
55
- type AttachmentInput = {
61
+ export type AttachmentInput = {
56
62
  path: string;
57
63
  filename?: string;
58
64
  contentType?: string;
59
65
  field?: string;
60
66
  };
61
67
  type UploadAssetInput = string | AttachmentInput;
62
- interface uploadAssetsData {
68
+ export interface UploadAssetsInput {
63
69
  domain: string;
64
70
  files: UploadAssetInput[];
65
71
  templateType?: 'tx' | 'form';
@@ -67,7 +73,7 @@ interface uploadAssetsData {
67
73
  locale?: string;
68
74
  path?: string;
69
75
  }
70
- declare class templateClient {
76
+ declare class TemplateClient {
71
77
  private baseURL;
72
78
  private apiKey;
73
79
  constructor(baseURL: string, apiKey: string);
@@ -85,15 +91,15 @@ declare class templateClient {
85
91
  private createAttachmentPayload;
86
92
  private appendFields;
87
93
  private postFormData;
88
- storeTemplate(td: templateData): Promise<unknown>;
89
- sendTemplate(std: sendTemplateData): Promise<unknown>;
90
- storeTxTemplate(td: templateData): Promise<unknown>;
91
- sendTxMessage(std: sendTemplateData): Promise<unknown>;
92
- storeFormTemplate(data: formTemplateData): Promise<unknown>;
93
- storeFormRecipient(data: formRecipientData): Promise<unknown>;
94
- sendFormMessage(data: sendFormData): Promise<unknown>;
95
- uploadAssets(data: uploadAssetsData): Promise<unknown>;
96
- getSwaggerSpec(): Promise<unknown>;
94
+ storeTemplate(td: StoreTxTemplateInput): Promise<ApiResponse>;
95
+ sendTemplate(std: SendTxMessageInput): Promise<ApiResponse>;
96
+ storeTxTemplate(td: StoreTxTemplateInput): Promise<ApiResponse>;
97
+ sendTxMessage(std: SendTxMessageInput): Promise<ApiResponse>;
98
+ storeFormTemplate(data: StoreFormTemplateInput): Promise<ApiResponse>;
99
+ storeFormRecipient(data: StoreFormRecipientInput): Promise<ApiResponse>;
100
+ sendFormMessage(data: SendFormMessageInput): Promise<ApiResponse>;
101
+ uploadAssets(data: UploadAssetsInput): Promise<ApiResponse>;
102
+ getSwaggerSpec(): Promise<ApiResponse>;
97
103
  fetchPublicAsset(domain: string, assetPath: string, viaApiBase?: boolean): Promise<ArrayBuffer>;
98
104
  }
99
- export default templateClient;
105
+ export default TemplateClient;
@@ -7,7 +7,7 @@ const fs_1 = __importDefault(require("fs"));
7
7
  const path_1 = __importDefault(require("path"));
8
8
  const email_addresses_1 = __importDefault(require("email-addresses"));
9
9
  const nunjucks_1 = __importDefault(require("nunjucks"));
10
- class templateClient {
10
+ class TemplateClient {
11
11
  constructor(baseURL, apiKey) {
12
12
  this.baseURL = baseURL;
13
13
  this.apiKey = apiKey;
@@ -55,12 +55,13 @@ class templateClient {
55
55
  return this.request('DELETE', command, body);
56
56
  }
57
57
  validateEmails(list) {
58
- const valid = [], invalid = [];
58
+ const valid = [];
59
+ const invalid = [];
59
60
  const emails = list
60
61
  .split(',')
61
62
  .map((email) => email.trim())
62
63
  .filter((email) => email !== '');
63
- emails.forEach((email) => {
64
+ for (const email of emails) {
64
65
  const parsed = email_addresses_1.default.parseOneAddress(email);
65
66
  if (parsed && parsed.address) {
66
67
  valid.push(parsed.address);
@@ -68,7 +69,7 @@ class templateClient {
68
69
  else {
69
70
  invalid.push(email);
70
71
  }
71
- });
72
+ }
72
73
  return { valid, invalid };
73
74
  }
74
75
  validateTemplate(template) {
@@ -325,4 +326,4 @@ class templateClient {
325
326
  return response.arrayBuffer();
326
327
  }
327
328
  }
328
- exports.default = templateClient;
329
+ exports.default = TemplateClient;
@@ -2,7 +2,7 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import emailAddresses from 'email-addresses';
4
4
  import nunjucks from 'nunjucks';
5
- class templateClient {
5
+ class TemplateClient {
6
6
  constructor(baseURL, apiKey) {
7
7
  this.baseURL = baseURL;
8
8
  this.apiKey = apiKey;
@@ -50,12 +50,13 @@ class templateClient {
50
50
  return this.request('DELETE', command, body);
51
51
  }
52
52
  validateEmails(list) {
53
- const valid = [], invalid = [];
53
+ const valid = [];
54
+ const invalid = [];
54
55
  const emails = list
55
56
  .split(',')
56
57
  .map((email) => email.trim())
57
58
  .filter((email) => email !== '');
58
- emails.forEach((email) => {
59
+ for (const email of emails) {
59
60
  const parsed = emailAddresses.parseOneAddress(email);
60
61
  if (parsed && parsed.address) {
61
62
  valid.push(parsed.address);
@@ -63,7 +64,7 @@ class templateClient {
63
64
  else {
64
65
  invalid.push(email);
65
66
  }
66
- });
67
+ }
67
68
  return { valid, invalid };
68
69
  }
69
70
  validateTemplate(template) {
@@ -320,4 +321,4 @@ class templateClient {
320
321
  return response.arrayBuffer();
321
322
  }
322
323
  }
323
- export default templateClient;
324
+ export default TemplateClient;