@t4h.framework/smtp 0.4.0 → 0.6.0

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.
@@ -6,7 +6,7 @@ description: >-
6
6
  Smtp client, recipients/cc/bcc normalization, HTML bodies, Binary attachments,
7
7
  and SmtpSendEmailOutput. Use when sending email from workflows, wiring SMTP
8
8
  claim providers, testing email activities, implementing SmtpSendEmailClaim,
9
- or working in packages/smtp or examples/email.
9
+ or working in packages/smtp.
10
10
  ---
11
11
 
12
12
  # @t4h.framework/smtp
@@ -72,19 +72,14 @@ type ISmtpSendEmailOutput = { messageId: string }
72
72
 
73
73
  ---
74
74
 
75
- ## SmtpSendEmailActivity
75
+ ## Send options and payload
76
76
 
77
- `SyncActivity` with args `[smtp: Smtp, content: SmtpSendEmailActivityOptions]`.
77
+ The exported `SmtpSendEmailActivity` — driven by `smtp.send` or directly via
78
+ `History.reconciler(SmtpSendEmailActivity, smtp, content)` — is replay-safe and
79
+ delegates to `SmtpSendEmailClaim.send`, returning a `SmtpSendEmailOutput`. Its
80
+ input shapes:
78
81
 
79
- | Method | Role |
80
- |--------|------|
81
- | `toInput(smtp, content)` | Builds serializable `SmtpSendEmailActivityInput` |
82
- | `run(payload)` | `this.claims.smtp.send(payload)` |
83
- | `toOutput(raw)` | `new SmtpSendEmailOutput(raw)` |
84
-
85
- Claim wiring (private `Claim` with key `smtp` → `SmtpSendEmailClaim`).
86
-
87
- ### SmtpSendEmailActivityOptions (designer / `Smtp.send`)
82
+ ### SmtpSendEmailActivityOptions (what `smtp.send` accepts)
88
83
 
89
84
  | Field | Type | Required | Notes |
90
85
  |-------|------|----------|-------|
@@ -120,7 +115,7 @@ type SmtpSendEmailActivityAttachment = {
120
115
  }
121
116
  ```
122
117
 
123
- Use framework `Binary` instances (e.g. from HTTP `response.body.binary` in `examples/email`).
118
+ Use framework `Binary` instances (e.g. from an HTTP `response.body`).
124
119
 
125
120
  ---
126
121
 
@@ -158,9 +153,11 @@ await smtp.send({
158
153
  })
159
154
  ```
160
155
 
161
- ### Invoking the activity directly
156
+ ### Using the exported activity directly via `History.reconciler`
162
157
 
163
- Prefer `smtp.send` in workflows. For low-level control:
158
+ Prefer `smtp.send` in workflows. When you need the exported activity directly,
159
+ drive the **shipped** `SmtpSendEmailActivity` through `History.reconciler` — a
160
+ ready, replay-safe helper. Never define or extend your own activity:
164
161
 
165
162
  ```typescript
166
163
  import { History } from '@t4h.framework/core'
@@ -174,7 +171,7 @@ const result = await History.reconciler(SmtpSendEmailActivity, smtp, {
174
171
  })
175
172
  ```
176
173
 
177
- Must run inside `History.run` (workflow runtime or test harness).
174
+ Runs inside a workflow (the runtime, or `TestWorkflowEnvironment` in tests, provides the reconciler context).
178
175
 
179
176
  ---
180
177
 
@@ -193,8 +190,6 @@ Activity and `Smtp.send` surface this type, not the raw `{ messageId }` object.
193
190
 
194
191
  ## Workflow example
195
192
 
196
- From `examples/email/src/main.tsx`:
197
-
198
193
  ```typescript
199
194
  import { App, EnvDesign, Workflow } from '@t4h.framework/core'
200
195
  import { http } from '@t4h.framework/http'
@@ -234,99 +229,32 @@ Connection strings are opaque to the package; dev implementation expects URL for
234
229
 
235
230
  Run package tests: `yarn test` in `packages/smtp` (Vitest).
236
231
 
237
- ### 1. Unit-test `toInput` / `run` / `toOutput`
238
-
239
- Pattern from `SmtpSendEmailActivity.spec.ts`:
232
+ Test the **workflow** with `TestWorkflowEnvironment` from
233
+ `@t4h.framework/core/testing`, mocking `SmtpSendEmailClaim` — the single claim
234
+ the send activity resolves. See the **framework-workflow-testing** skill for the
235
+ harness API.
240
236
 
241
237
  ```typescript
242
- import { Claim } from '@t4h.framework/core'
243
- import { vi } from 'vitest'
244
- import {
245
- Smtp,
246
- SmtpSendEmailActivity,
247
- SmtpSendEmailClaim,
248
- type SmtpSendEmailActivityInput,
249
- } from '@t4h.framework/smtp'
250
-
251
- const mockSend = vi.fn().mockReturnValue({ messageId: 'msg-123' })
252
-
253
- Claim.run(
254
- [{ provide: SmtpSendEmailClaim, value: { send: mockSend } as SmtpSendEmailClaim }],
255
- () => {
256
- const activity = Reflect.construct(SmtpSendEmailActivity, [])
257
- const input: SmtpSendEmailActivityInput = {
258
- connectionString: 'smtp://user:pass@smtp.example.com:587',
259
- from: 'sender@example.com',
260
- subject: 'Test',
261
- html: '<p>Hello</p>',
262
- to: ['recipient@example.com'],
263
- }
264
- const output = activity.run(input)
265
- expect(mockSend).toHaveBeenCalledWith(input)
266
- expect(output).toEqual({ messageId: 'msg-123' })
267
- },
268
- )
269
- ```
270
-
271
- Use `mockResolvedValue` when testing async `send` implementations.
272
-
273
- Assert `toInput` normalization: single `to` → array; `content.from` over `smtp.options.from`; `cc`/`bcc` string → array; attachments reference equality.
238
+ import { TestWorkflowEnvironment, mockClaim } from '@t4h.framework/core/testing'
239
+ import { SmtpSendEmailClaim } from '@t4h.framework/smtp'
274
240
 
275
- ### 2. Assert `Smtp.send` schedules `SmtpSendEmailActivity`
241
+ const mockSend = vi.fn().mockImplementation(async () => ({ messageId: 'msg-123' }))
276
242
 
277
- Pattern from `Smtp.spec.ts`:
243
+ const env = TestWorkflowEnvironment.create({ now: 0 })
278
244
 
279
- ```typescript
280
- import { History, PushActivity, type Activity } from '@t4h.framework/core'
281
- import { Smtp, SmtpSendEmailActivity } from '@t4h.framework/smtp'
282
-
283
- async function captureReconcilerTrigger(fn: () => unknown) {
284
- try {
285
- await History.run([], fn)
286
- } catch (error) {
287
- if (error instanceof PushActivity) return error as PushActivity<Activity>
288
- throw error
289
- }
290
- }
291
-
292
- const client = new Smtp(connectionString, { from: 'noreply@example.com' })
293
- const trigger = await captureReconcilerTrigger(() =>
294
- client.send({ to: 'a@example.com', subject: 'Test', html: '<p>Hi</p>' }),
295
- )
245
+ await env.execute(workflow, input, {
246
+ claims: [mockClaim(SmtpSendEmailClaim, { send: mockSend })],
247
+ env: { SMTP_CONNECTION_STRING: 'smtp://user:pass@smtp.example.com:587' },
248
+ })
296
249
 
297
- expect(trigger.activity.constructor).toBe(SmtpSendEmailActivity)
298
- expect(trigger.input).toEqual({
299
- connectionString,
300
- from: 'noreply@example.com',
250
+ // `send` receives the normalized activity input (single `to` becomes an array, etc.)
251
+ expect(mockSend.mock.calls[0][0]).toMatchObject({
252
+ to: ['recipient@example.com'],
301
253
  subject: 'Test',
302
- html: '<p>Hi</p>',
303
- to: ['a@example.com'],
304
- cc: undefined,
305
- bcc: undefined,
306
- attachments: undefined,
254
+ html: '<p>Hello</p>',
307
255
  })
308
256
  ```
309
257
 
310
- ### 3. Replay with history
311
-
312
- ```typescript
313
- import { History } from '@t4h.framework/core'
314
- import { Smtp, SmtpSendEmailOutput } from '@t4h.framework/smtp'
315
-
316
- const result = await History.run(
317
- [{ output: { messageId: '<msg-123@example.com>' }, type: 'sync' }],
318
- () =>
319
- client.send({
320
- to: 'user@example.com',
321
- subject: 'Subject',
322
- html: '<p>Body</p>',
323
- }),
324
- )
325
-
326
- expect(result).toBeInstanceOf(SmtpSendEmailOutput)
327
- expect(result.messageId).toBe('<msg-123@example.com>')
328
- ```
329
-
330
258
  ---
331
259
 
332
260
  ## Implementing SmtpSendEmailClaim
@@ -341,14 +269,14 @@ expect(result.messageId).toBe('<msg-123@example.com>')
341
269
 
342
270
  ## Checklist for agents
343
271
 
344
- 1. Prefer **`Smtp` + `smtp.send()`** in workflows unless a custom typed activity is required.
272
+ 1. In workflows, use **`Smtp` + `smtp.send()`** (or `History.reconciler` with the exported `SmtpSendEmailActivity`) — never define or extend your own activity.
345
273
  2. Ensure runtime provides **`SmtpSendEmailClaim`** (or a mock in tests).
346
274
  3. Use **`html`** for the message body; required fields on send options are **`to`**, **`subject`**, **`html`**.
347
275
  4. Set default **`from`** on `new Smtp(connectionString, { from })` or per-send; per-send wins.
348
276
  5. Pass **`Binary`** for attachment `content`, not raw `Buffer` in activity options.
349
277
  6. Expect **`SmtpSendEmailOutput`** from `send`, not a plain object — use `.messageId`.
350
- 7. When testing, mirror **`Claim.run`** + mock `send`, or **`History.run`** + **`PushActivity`** from `packages/smtp/src/**/__tests__`.
278
+ 7. Test workflows with **`TestWorkflowEnvironment`** + **`mockClaim(SmtpSendEmailClaim, { send })`**; assert on the mock's `mock.calls`.
351
279
  8. Do not document or import APIs not exported from `@t4h.framework/smtp`.
352
280
  9. For core workflow/reconciler concepts, use the **framework-core** skill (`@t4h.framework/core`).
353
281
 
354
- See also: `packages/smtp/README.md`, `examples/email/src/main.tsx`.
282
+ See also: `packages/smtp/README.md`; **framework-workflow-testing** for the test harness.
package/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ # @t4h.framework/smtp
2
+
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Updated dependencies [[`8098041`](https://github.com/tech4humans-brasil/framework/commit/80980419d59a987378b7c94372ee2f7b7dcc00f5)]:
8
+ - @t4h.framework/core@0.10.0
9
+
10
+ ## 0.5.0
11
+
12
+ ### Minor Changes
13
+
14
+ - Update history to satisfies core contract ([`30b3d38`](https://github.com/tech4humans-brasil/framework/commit/30b3d38bfd631990e4c4f740344910d5958ddfb9))
15
+
16
+ ### Patch Changes
17
+
18
+ - Update skills ([`6d7e7bc`](https://github.com/tech4humans-brasil/framework/commit/6d7e7bca0c780a9c53a0c9e5aa0a865c5af67959))
19
+
20
+ ## 0.4.0
21
+
22
+ ### Patch Changes
23
+
24
+ - Internal dependency updates
25
+
26
+ ## 0.3.0
27
+
28
+ ### Minor Changes
29
+
30
+ - Implements smtp activity ([`ca20afd`](https://github.com/tech4humans-brasil/framework/commit/ca20afdfc324a1004e77ef1881c049e7f97f0eff))
31
+ - Adds type to history item ([#47](https://github.com/tech4humans-brasil/framework/pull/47))
32
+ - Adds .ai/skills in packages ([#88](https://github.com/tech4humans-brasil/framework/pull/88))
33
+
34
+ ### Patch Changes
35
+
36
+ - Update package metadata and author information across multiple packages ([`2ca73df`](https://github.com/tech4humans-brasil/framework/commit/2ca73df42dc63c86ed44717b50d5402fca45b4e7))
37
+ - Improve repository info ([`1fad92d`](https://github.com/tech4humans-brasil/framework/commit/1fad92d959b804189fd1486d047115995ac81eb0))
38
+ - Up repo coverage ([`24c057c`](https://github.com/tech4humans-brasil/framework/commit/24c057c470d0829ea9a1e1f71011b6eff408180c))
39
+ - Fix resolve module resolution issues in check-types ([`c97a0d2`](https://github.com/tech4humans-brasil/framework/commit/c97a0d2747f38e561cc5c7d592b20de0459bc1ee))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t4h.framework/smtp",
3
- "version": "0.4.0",
3
+ "version": "0.6.0",
4
4
  "description": "SMTP module for the T4H Framework",
5
5
  "homepage": "https://github.com/tech4humans-brasil/framework/tree/main/packages/smtp",
6
6
  "bugs": "https://github.com/tech4humans-brasil/framework/issues",
@@ -31,12 +31,12 @@
31
31
  "test:watch": "vitest"
32
32
  },
33
33
  "devDependencies": {
34
- "@t4h.framework/core": "^0.6.0",
34
+ "@t4h.framework/core": "^0.10.0",
35
35
  "typescript": "^5.9.3",
36
36
  "vitest": "^4.0.18"
37
37
  },
38
38
  "peerDependencies": {
39
- "@t4h.framework/core": "^0.6.0"
39
+ "@t4h.framework/core": "^0.10.0"
40
40
  },
41
41
  "packageManager": "yarn@4.12.0",
42
42
  "engines": {