@fabrika/email 0.2.0 → 0.3.1

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 (2) hide show
  1. package/package.json +4 -1
  2. package/src/resend.ts +7 -12
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fabrika/email",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
@@ -29,5 +29,8 @@
29
29
  "scripts": {
30
30
  "typecheck": "tsc --noEmit",
31
31
  "test": "bun test src/__tests__"
32
+ },
33
+ "dependencies": {
34
+ "zod": "^3.25.76"
32
35
  }
33
36
  }
package/src/resend.ts CHANGED
@@ -1,7 +1,10 @@
1
+ import { z } from 'zod'
1
2
  import { EmailDeliveryError, type EmailDeliveryResult, type EmailMessage, type EmailSender } from './email.js'
2
3
  import { isValidEmailFrom, validateEmailMessage } from './validation.js'
3
4
 
4
5
  const RESEND_EMAILS_URL = 'https://api.resend.com/emails'
6
+ const resendSuccessSchema = z.object({ id: z.string().min(1) })
7
+ const resendErrorSchema = z.object({ name: z.string() })
5
8
 
6
9
  export type EmailFetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>
7
10
 
@@ -103,17 +106,13 @@ async function responseError(response: Response): Promise<EmailDeliveryError> {
103
106
  }
104
107
 
105
108
  async function readMessageId(response: Response): Promise<string | undefined> {
106
- const body = await readJson(response)
107
- if (!isRecord(body)) return undefined
108
- const id: unknown = Reflect.get(body, 'id')
109
- return typeof id === 'string' && id.length > 0 ? id : undefined
109
+ const parsed = resendSuccessSchema.safeParse(await readJson(response))
110
+ return parsed.success ? parsed.data.id : undefined
110
111
  }
111
112
 
112
113
  async function readProviderError(response: Response): Promise<string | undefined> {
113
- const body = await readJson(response)
114
- if (!isRecord(body)) return undefined
115
- const name: unknown = Reflect.get(body, 'name')
116
- return typeof name === 'string' ? name : undefined
114
+ const parsed = resendErrorSchema.safeParse(await readJson(response))
115
+ return parsed.success ? parsed.data.name : undefined
117
116
  }
118
117
 
119
118
  async function readJson(response: Response): Promise<unknown> {
@@ -124,10 +123,6 @@ async function readJson(response: Response): Promise<unknown> {
124
123
  }
125
124
  }
126
125
 
127
- function isRecord(value: unknown): value is Record<string, unknown> {
128
- return typeof value === 'object' && value !== null && !Array.isArray(value)
129
- }
130
-
131
126
  function validApiKey(value: string): boolean {
132
127
  if (value.length === 0 || value.trim() !== value) return false
133
128
  for (const character of value) {