@lunora/mail 1.0.0-alpha.80 → 1.0.0-alpha.81

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.
@@ -1 +1 @@
1
- import{createInboundEmailHandler as n,dispatchToLunoraFunction as r}from"../packem_shared/createInboundEmailHandler-Bh10YPyJ.mjs";import{authenticatesFrom as t,parseInboundEmail as i}from"../packem_shared/authenticatesFrom-xpKAFMRN.mjs";export{t as authenticatesFrom,n as createInboundEmailHandler,r as dispatchToLunoraFunction,i as parseInboundEmail};
1
+ import{createInboundEmailHandler as n,dispatchToLunoraFunction as r}from"../packem_shared/createInboundEmailHandler-Bh10YPyJ.mjs";import{authenticatesFrom as t,parseInboundEmail as i}from"../packem_shared/authenticatesFrom-BOX-Paur.mjs";export{t as authenticatesFrom,n as createInboundEmailHandler,r as dispatchToLunoraFunction,i as parseInboundEmail};
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{createCaptureTransport as a}from"./packem_shared/createCaptureTransport-CKc6NpZR.mjs";import{createCloudflareTransport as t}from"./packem_shared/createCloudflareTransport-DpfCxn16.mjs";import{default as u}from"./packem_shared/createMailer-CjQmT7Ln.mjs";import{createCaptureSink as f,createMailerFromEnv as l,shouldCaptureMail as m}from"./packem_shared/createCaptureSink-CeV0DSsT.mjs";import{consumeQueuedSend as s,toQueuedPayload as c}from"./packem_shared/consumeQueuedSend-CRfALnCU.mjs";import{default as i}from"./packem_shared/renderEmail-BOUnr6i3.mjs";import{default as M}from"./packem_shared/createResendTransport-DDkOitck.mjs";export{s as consumeQueuedSend,f as createCaptureSink,a as createCaptureTransport,t as createCloudflareTransport,u as createMailer,l as createMailerFromEnv,M as createResendTransport,i as renderEmail,m as shouldCaptureMail,c as toQueuedPayload};
1
+ import{createCaptureTransport as a}from"./packem_shared/createCaptureTransport-CKc6NpZR.mjs";import{createCloudflareTransport as t}from"./packem_shared/createCloudflareTransport-bWoNSnK_.mjs";import{default as u}from"./packem_shared/createMailer-aRrzRLwc.mjs";import{createCaptureSink as f,createMailerFromEnv as l,shouldCaptureMail as m}from"./packem_shared/createCaptureSink-DI9tmsLn.mjs";import{consumeQueuedSend as s,toQueuedPayload as c}from"./packem_shared/consumeQueuedSend-CRfALnCU.mjs";import{default as i}from"./packem_shared/renderEmail-BOUnr6i3.mjs";import{default as M}from"./packem_shared/createResendTransport-BMjRlHmy.mjs";export{s as consumeQueuedSend,f as createCaptureSink,a as createCaptureTransport,t as createCloudflareTransport,u as createMailer,l as createMailerFromEnv,M as createResendTransport,i as renderEmail,m as shouldCaptureMail,c as toQueuedPayload};
@@ -1,3 +1,3 @@
1
1
  import{LunoraError as t}from"@lunora/errors";const n=320,a=256,d=/^([^<]*)<([^>]*)>\s*$/,i=(r,s)=>{if(s.includes("\r")||s.includes(`
2
- `)||s.includes(","))throw new t("INTERNAL",`@lunora/mail: address ${r} must not contain CR, LF, or comma`)},f=(r,s)=>{if(s.includes("\r")||s.includes(`
3
- `))throw new t("INTERNAL",`@lunora/mail: ${r} must not contain CR or LF`)},m=(r,s)=>{if(r.length>a)throw new t("INTERNAL",`@lunora/mail: address name must be <= ${String(a)} characters`);if(s.length>n)throw new t("INTERNAL",`@lunora/mail: address email must be <= ${String(n)} characters`);return r&&i("name",r),i("email",s),r?{email:s,name:r}:{email:s}},A=r=>{const s=r.trim();if(s.length>n)throw new t("INTERNAL",`@lunora/mail: address email must be <= ${String(n)} characters`);return i("email",s),{email:s}},c=r=>{const s=d.exec(r),e=(s?.[2]??"").trim();return s&&e?m((s[1]??"").trim(),e):A(r)},o=r=>r===void 0?void 0:(Array.isArray(r)?r:[r]).map(e=>c(e)),u=r=>{o(r.to),o(r.cc),o(r.bcc),r.from!==void 0&&c(r.from),r.replyTo!==void 0&&c(r.replyTo)};export{f as a,c as b,u as c,o as t};
2
+ `)||s.includes(","))throw new t("INTERNAL",`@lunora/mail: address ${r} must not contain CR, LF, or comma`)},u=(r,s)=>{if(s.includes("\r")||s.includes(`
3
+ `))throw new t("INTERNAL",`@lunora/mail: ${r} must not contain CR or LF`)},m=(r,s)=>{if(r.length>a)throw new t("INTERNAL",`@lunora/mail: address name must be <= ${String(a)} characters`);if(s.length>n)throw new t("INTERNAL",`@lunora/mail: address email must be <= ${String(n)} characters`);return r&&i("name",r),i("email",s),r?{email:s,name:r}:{email:s}},l=r=>{const s=r.trim();if(s.length>n)throw new t("INTERNAL",`@lunora/mail: address email must be <= ${String(n)} characters`);return i("email",s),{email:s}},c=r=>{const s=d.exec(r),e=(s?.[2]??"").trim();return s&&e?m((s[1]??"").trim(),e):l(r)},o=r=>{if(r===void 0)return;const s=Array.isArray(r)?r:[r];if(s.length!==0)return s.map(e=>c(e))},f=r=>{if(o(r.to)===void 0)throw new t("INTERNAL","@lunora/mail: at least one recipient is required");o(r.cc),o(r.bcc),r.from!==void 0&&c(r.from),r.replyTo!==void 0&&c(r.replyTo)};export{u as a,c as b,f as c,o as t};
@@ -1 +1 @@
1
- import p from"postal-mime";import{a as c}from"./address-soPj2Z0j.mjs";const d=(s,e)=>{if(e!==void 0)return c(`inbound ${s}`,e),e},u=s=>s.address!==void 0&&s.address!==""?s.name?`${s.name} <${s.address}>`:s.address:s.group?s.group.map(e=>e.address??"").filter(e=>e!=="").join(", "):s.name??"",l=/"(?:[^"\\]|\\.)*(?:"|$)|\((?:[^()\\]|\\.)*(?:\)|$)/g,g=s=>s.replaceAll(l,e=>e.startsWith('"')?e.replaceAll(/[;=]/gu," "):" "),m=(s,e,r)=>{const i=g(s).matchAll(new RegExp(String.raw`(?:^|;)\s*${e}\s*(?:/\s*\d+\s*)?=\s*([a-z]+)([^;]*)`,"gi")),a=new RegExp(String.raw`\b${r.split(".").join(String.raw`\s*\.\s*`)}\s*=\s*"?([^\s;"]+)`,"i");return[...i].map(t=>{const n=a.exec(t[2]??"")?.[1];return{domain:n===void 0?null:n.slice(n.lastIndexOf("@")+1).toLowerCase(),result:(t[1]??"").toLowerCase()}})},v=s=>s===void 0||s===""?{dkim:[],dmarc:[],spf:[]}:{dkim:m(s,"dkim","header.d"),dmarc:m(s,"dmarc","header.from"),spf:m(s,"spf","smtp.mailfrom")},I=async s=>{const e=await p.parse(s),r={};for(const o of e.headers)c(`inbound header \`${o.key}\``,o.value),r[o.key]=o.value;const i=e.headers.find(o=>o.key==="authentication-results")?.value,a=(e.to??[]).map(o=>{const f=u(o);return c("inbound to",f),f}),t=e.from?u(e.from):"";return c("inbound from",t),{attachments:e.attachments.map(o=>({content:o.content,disposition:o.disposition,...o.encoding===void 0?{}:{encoding:o.encoding},filename:o.filename,mimeType:o.mimeType})),authentication:v(i),from:t,headers:r,...e.html===void 0?{}:{html:e.html},...d("inReplyTo",e.inReplyTo)===void 0?{}:{inReplyTo:e.inReplyTo},...d("messageId",e.messageId)===void 0?{}:{messageId:e.messageId},...d("references",e.references)===void 0?{}:{references:e.references},...d("subject",e.subject)===void 0?{}:{subject:e.subject},...e.text===void 0?{}:{text:e.text},to:a}},h=/<([^<>]*)>$/,x=s=>{const e=h.exec(s)?.[1]??s,r=e.indexOf("@");if(!(r===-1||r!==e.lastIndexOf("@")))return e.slice(r+1).trim().toLowerCase()},$=s=>{const e=x(s.from);if(e===void 0)return!1;const r=n=>n.some(o=>o.result==="pass"&&o.domain===e),{dkim:i,dmarc:a,spf:t}=s.authentication;return r(a)||r(t)||r(i)};export{$ as authenticatesFrom,I as parseInboundEmail};
1
+ import p from"postal-mime";import{a as c}from"./address-oKy_d0aG.mjs";const d=(s,e)=>{if(e!==void 0)return c(`inbound ${s}`,e),e},u=s=>s.address!==void 0&&s.address!==""?s.name?`${s.name} <${s.address}>`:s.address:s.group?s.group.map(e=>e.address??"").filter(e=>e!=="").join(", "):s.name??"",l=/"(?:[^"\\]|\\.)*(?:"|$)|\((?:[^()\\]|\\.)*(?:\)|$)/g,g=s=>s.replaceAll(l,e=>e.startsWith('"')?e.replaceAll(/[;=]/gu," "):" "),m=(s,e,r)=>{const i=g(s).matchAll(new RegExp(String.raw`(?:^|;)\s*${e}\s*(?:/\s*\d+\s*)?=\s*([a-z]+)([^;]*)`,"gi")),a=new RegExp(String.raw`\b${r.split(".").join(String.raw`\s*\.\s*`)}\s*=\s*"?([^\s;"]+)`,"i");return[...i].map(t=>{const n=a.exec(t[2]??"")?.[1];return{domain:n===void 0?null:n.slice(n.lastIndexOf("@")+1).toLowerCase(),result:(t[1]??"").toLowerCase()}})},v=s=>s===void 0||s===""?{dkim:[],dmarc:[],spf:[]}:{dkim:m(s,"dkim","header.d"),dmarc:m(s,"dmarc","header.from"),spf:m(s,"spf","smtp.mailfrom")},I=async s=>{const e=await p.parse(s),r={};for(const o of e.headers)c(`inbound header \`${o.key}\``,o.value),r[o.key]=o.value;const i=e.headers.find(o=>o.key==="authentication-results")?.value,a=(e.to??[]).map(o=>{const f=u(o);return c("inbound to",f),f}),t=e.from?u(e.from):"";return c("inbound from",t),{attachments:e.attachments.map(o=>({content:o.content,disposition:o.disposition,...o.encoding===void 0?{}:{encoding:o.encoding},filename:o.filename,mimeType:o.mimeType})),authentication:v(i),from:t,headers:r,...e.html===void 0?{}:{html:e.html},...d("inReplyTo",e.inReplyTo)===void 0?{}:{inReplyTo:e.inReplyTo},...d("messageId",e.messageId)===void 0?{}:{messageId:e.messageId},...d("references",e.references)===void 0?{}:{references:e.references},...d("subject",e.subject)===void 0?{}:{subject:e.subject},...e.text===void 0?{}:{text:e.text},to:a}},h=/<([^<>]*)>$/,x=s=>{const e=h.exec(s)?.[1]??s,r=e.indexOf("@");if(!(r===-1||r!==e.lastIndexOf("@")))return e.slice(r+1).trim().toLowerCase()},$=s=>{const e=x(s.from);if(e===void 0)return!1;const r=n=>n.some(o=>o.result==="pass"&&o.domain===e),{dkim:i,dmarc:a,spf:t}=s.authentication;return r(a)||r(t)||r(i)};export{$ as authenticatesFrom,I as parseInboundEmail};
@@ -1 +1 @@
1
- import{createCaptureTransport as l}from"./createCaptureTransport-CKc6NpZR.mjs";import"./createCloudflareTransport-DpfCxn16.mjs";import n from"./createMailer-CjQmT7Ln.mjs";import{LunoraError as u}from"@lunora/errors";import{D as c,p as E}from"./shard-CRhAKK93.mjs";import"./consumeQueuedSend-CRfALnCU.mjs";import"./renderEmail-BOUnr6i3.mjs";import"./createResendTransport-DDkOitck.mjs";const p="__lunora_admin__:recordMail",N=/^(?:dev(?:elopment)?|local(?:host)?|test)$/iu,_=["CF_ENV","ENVIRONMENT","NODE_ENV","WORKER_ENV"],f=(e,t)=>{const r=e[t];if(typeof r!="string"||r==="")throw new u("INTERNAL",`@lunora/mail: missing env var \`${t}\` — set it in .dev.vars (and \`wrangler secret put ${t}\` for secrets).`);return r},m=e=>{const t=e.LUNORA_MAIL_CAPTURE;if(typeof t=="string"){const r=t.toLowerCase();if(r==="1"||r==="true")return!0;if(r==="0"||r==="false")return!1;console.warn(`@lunora/mail: unrecognized LUNORA_MAIL_CAPTURE value "${t}" — expected "1"/"true" or "0"/"false"; falling back to environment detection.`)}return _.some(r=>{const o=e[r];return typeof o=="string"&&N.test(o)})};let d=!1;const A=(e,t=c,r)=>({record:async o=>{const i=e.SHARD,a=typeof e.LUNORA_ADMIN_TOKEN=="string"?e.LUNORA_ADMIN_TOKEN:void 0;if(i===void 0||a===void 0)return d||(d=!0,console.warn("@lunora/mail: capturing mail but there is nowhere to record it — the `SHARD` binding and/or `LUNORA_ADMIN_TOKEN` is missing, so every captured message is discarded. Set both to see mail in the studio inbox, or set LUNORA_MAIL_CAPTURE=0 to deliver for real.")),{id:"uncaptured"};try{return{id:(await E(i,{adminToken:a,envelope:{args:o,functionPath:p},jurisdiction:r,label:"@lunora/mail: recording captured mail",shardKey:t})).result?.id??"captured"}}catch(s){return console.error("@lunora/mail: failed to record captured mail into the studio inbox —",s),{id:"uncaptured"}}}}),h=(e,t={})=>{const r=f(e,"MAIL_FROM");if(m(e))return n({from:r,transport:l(A(e,t.rootShard,t.jurisdiction))});if(t.cloudflareSend)return n({cloudflareSend:t.cloudflareSend,from:r});const o=typeof e.RESEND_API_KEY=="string"?e.RESEND_API_KEY:void 0;if(o!==void 0&&o!=="")return n({apiKey:o,from:r});throw new u("INTERNAL","@lunora/mail: no transport configured — provide `cloudflareSend` (a SEND_EMAIL binding) or RESEND_API_KEY, or run in a dev environment to capture.")};export{A as createCaptureSink,h as createMailerFromEnv,m as shouldCaptureMail};
1
+ import{createCaptureTransport as l}from"./createCaptureTransport-CKc6NpZR.mjs";import"./createCloudflareTransport-bWoNSnK_.mjs";import n from"./createMailer-aRrzRLwc.mjs";import{LunoraError as u}from"@lunora/errors";import{D as c,p as E}from"./shard-CRhAKK93.mjs";import"./consumeQueuedSend-CRfALnCU.mjs";import"./renderEmail-BOUnr6i3.mjs";import"./createResendTransport-BMjRlHmy.mjs";const p="__lunora_admin__:recordMail",N=/^(?:dev(?:elopment)?|local(?:host)?|test)$/iu,_=["CF_ENV","ENVIRONMENT","NODE_ENV","WORKER_ENV"],f=(e,t)=>{const r=e[t];if(typeof r!="string"||r==="")throw new u("INTERNAL",`@lunora/mail: missing env var \`${t}\` — set it in .dev.vars (and \`wrangler secret put ${t}\` for secrets).`);return r},m=e=>{const t=e.LUNORA_MAIL_CAPTURE;if(typeof t=="string"){const r=t.toLowerCase();if(r==="1"||r==="true")return!0;if(r==="0"||r==="false")return!1;console.warn(`@lunora/mail: unrecognized LUNORA_MAIL_CAPTURE value "${t}" — expected "1"/"true" or "0"/"false"; falling back to environment detection.`)}return _.some(r=>{const o=e[r];return typeof o=="string"&&N.test(o)})};let d=!1;const A=(e,t=c,r)=>({record:async o=>{const i=e.SHARD,a=typeof e.LUNORA_ADMIN_TOKEN=="string"?e.LUNORA_ADMIN_TOKEN:void 0;if(i===void 0||a===void 0)return d||(d=!0,console.warn("@lunora/mail: capturing mail but there is nowhere to record it — the `SHARD` binding and/or `LUNORA_ADMIN_TOKEN` is missing, so every captured message is discarded. Set both to see mail in the studio inbox, or set LUNORA_MAIL_CAPTURE=0 to deliver for real.")),{id:"uncaptured"};try{return{id:(await E(i,{adminToken:a,envelope:{args:o,functionPath:p},jurisdiction:r,label:"@lunora/mail: recording captured mail",shardKey:t})).result?.id??"captured"}}catch(s){return console.error("@lunora/mail: failed to record captured mail into the studio inbox —",s),{id:"uncaptured"}}}}),h=(e,t={})=>{const r=f(e,"MAIL_FROM");if(m(e))return n({from:r,transport:l(A(e,t.rootShard,t.jurisdiction))});if(t.cloudflareSend)return n({cloudflareSend:t.cloudflareSend,from:r});const o=typeof e.RESEND_API_KEY=="string"?e.RESEND_API_KEY:void 0;if(o!==void 0&&o!=="")return n({apiKey:o,from:r});throw new u("INTERNAL","@lunora/mail: no transport configured — provide `cloudflareSend` (a SEND_EMAIL binding) or RESEND_API_KEY, or run in a dev environment to capture.")};export{A as createCaptureSink,h as createMailerFromEnv,m as shouldCaptureMail};
@@ -1 +1 @@
1
- import{LunoraError as n}from"@lunora/errors";import{cloudflareEmailProvider as l}from"@visulima/email/providers/cloudflare-email";import{r as d,t as u,i as m}from"./provider-transport-CR4w-R0A.mjs";const E=r=>{const t=l({send:r.send});return{send:async e=>{await t.initialize();const o=e.cc!==void 0&&e.cc.length>0,s=e.bcc!==void 0&&e.bcc.length>0;if(o||s)throw new n("INTERNAL","@lunora/mail: Cloudflare Email Workers does not support cc/bcc — fan out one send per recipient instead");const{first:c,list:i}=d(e.to);if(i.length>1)throw new n("INTERNAL",`@lunora/mail: Cloudflare Email Workers is single-recipient but received ${String(i.length)} \`to\` addresses — fan out one send per recipient instead`);const a=await t.sendEmail(u(e,r.from,c));return m(a)}}};export{E as createCloudflareTransport};
1
+ import{LunoraError as n}from"@lunora/errors";import{cloudflareEmailProvider as l}from"@visulima/email/providers/cloudflare-email";import{r as d,t as u,i as m}from"./provider-transport-BnA39QbI.mjs";const E=r=>{const t=l({send:r.send});return{send:async e=>{await t.initialize();const o=e.cc!==void 0&&e.cc.length>0,s=e.bcc!==void 0&&e.bcc.length>0;if(o||s)throw new n("INTERNAL","@lunora/mail: Cloudflare Email Workers does not support cc/bcc — fan out one send per recipient instead");const{first:c,list:i}=d(e.to);if(i.length>1)throw new n("INTERNAL",`@lunora/mail: Cloudflare Email Workers is single-recipient but received ${String(i.length)} \`to\` addresses — fan out one send per recipient instead`);const a=await t.sendEmail(u(e,r.from,c));return m(a)}}};export{E as createCloudflareTransport};
@@ -0,0 +1 @@
1
+ import{LunoraError as l}from"@lunora/errors";import{a as o,c as m}from"./address-oKy_d0aG.mjs";import{isCaptureTransport as s}from"./createCaptureTransport-CKc6NpZR.mjs";import{createCloudflareTransport as y}from"./createCloudflareTransport-bWoNSnK_.mjs";import{toQueuedPayload as i}from"./consumeQueuedSend-CRfALnCU.mjs";import b from"./renderEmail-BOUnr6i3.mjs";import h from"./createResendTransport-BMjRlHmy.mjs";const w=()=>{if(typeof crypto<"u"){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();if(typeof crypto.getRandomValues=="function"){const r=crypto.getRandomValues(new Uint8Array(16));return Array.from(r,c=>c.toString(16).padStart(2,"0")).join("")}}throw new Error("randomSessionId: no Web Crypto available — a session id needs crypto.randomUUID or crypto.getRandomValues")},p=r=>{if(r.cloudflareSend)return y({from:r.from,send:r.cloudflareSend});if(r.apiKey)return h(r.apiKey,r.from);throw new l("INTERNAL","@lunora/mail: a transport is required — pass `transport`, `cloudflareSend` (Cloudflare Email Workers, the default), or `apiKey` (Resend)")},A=r=>{if(!r.from)throw new l("INTERNAL","@lunora/mail: `from` is required");const c=r.transport??p(r),n=async e=>{let{html:a}=e,{text:d}=e;if(e.react){const t=await b(e.react);a=a??t.html,d=d??t.text}if(o("subject",e.subject),e.headers)for(const[t,f]of Object.entries(e.headers))o(`header name "${t}"`,t),o(`header "${t}" value`,f);const u=e.from??r.from;return m({bcc:e.bcc,cc:e.cc,from:u,replyTo:e.replyTo,to:e.to}),{bcc:e.bcc?.length?e.bcc:void 0,cc:e.cc?.length?e.cc:void 0,from:u,headers:e.headers,html:a,replyTo:e.replyTo,subject:e.subject,text:d,to:e.to}};return{queue:async e=>{if(!r.queue){if(s(c)){const u=await n(e);return await c.send(u),{queued:!0}}throw new l("INTERNAL","@lunora/mail: `queue` binding is required for mailer.queue()")}const a=await n(e),d=e.idempotencyKey??w();return await r.queue.send(i({...a,idempotencyKey:d})),{queued:!0}},send:async e=>{const a=await n(e);return c.send(a)}}};export{A as default};
@@ -1 +1 @@
1
- import{resendProvider as a}from"@visulima/email/providers/resend";import{r as d,t as c,i as l}from"./provider-transport-CR4w-R0A.mjs";const u=(i,s)=>{const e=a({apiKey:i});return{send:async r=>{await e.initialize();const{first:n,list:t}=d(r.to),o=await e.sendEmail(c(r,s,t.length===1?n:t));return l(o)}}};export{u as default};
1
+ import{resendProvider as a}from"@visulima/email/providers/resend";import{r as d,t as c,i as l}from"./provider-transport-BnA39QbI.mjs";const u=(i,s)=>{const e=a({apiKey:i});return{send:async r=>{await e.initialize();const{first:n,list:t}=d(r.to),o=await e.sendEmail(c(r,s,t.length===1?n:t));return l(o)}}};export{u as default};
@@ -1 +1 @@
1
- import{LunoraError as o}from"@lunora/errors";import{t as n,b as s}from"./address-soPj2Z0j.mjs";const c=e=>e instanceof Error?e.message:e==null?"send failed":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"||typeof e=="bigint"?e.toString():JSON.stringify(e)??"send failed",u=e=>{const t=n(e),[i]=t??[];if(!t||i===void 0)throw new o("INTERNAL","@lunora/mail: at least one recipient is required");return{first:i,list:t}},d=(e,t,i)=>({bcc:n(e.bcc),cc:n(e.cc),from:s(e.from??t),headers:e.headers,html:e.html,replyTo:e.replyTo?s(e.replyTo):void 0,subject:e.subject,text:e.text,to:i}),m=e=>{if(!e.success||!e.data)throw console.error(`@lunora/mail: send failed: ${c(e.error)}`),new o("INTERNAL","@lunora/mail: send failed");return{id:e.data.messageId}};export{m as i,u as r,d as t};
1
+ import{LunoraError as o}from"@lunora/errors";import{t as n,b as s}from"./address-oKy_d0aG.mjs";const c=e=>e instanceof Error?e.message:e==null?"send failed":typeof e=="string"?e:typeof e=="number"||typeof e=="boolean"||typeof e=="bigint"?e.toString():JSON.stringify(e)??"send failed",u=e=>{const t=n(e),[i]=t??[];if(!t||i===void 0)throw new o("INTERNAL","@lunora/mail: at least one recipient is required");return{first:i,list:t}},d=(e,t,i)=>({bcc:n(e.bcc),cc:n(e.cc),from:s(e.from??t),headers:e.headers,html:e.html,replyTo:e.replyTo?s(e.replyTo):void 0,subject:e.subject,text:e.text,to:i}),m=e=>{if(!e.success||!e.data)throw console.error(`@lunora/mail: send failed: ${c(e.error)}`),new o("INTERNAL","@lunora/mail: send failed");return{id:e.data.messageId}};export{m as i,u as r,d as t};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/mail",
3
- "version": "1.0.0-alpha.80",
3
+ "version": "1.0.0-alpha.81",
4
4
  "description": "Email for Lunora: Resend adapter, TSX templates, and queue-backed sends",
5
5
  "keywords": [
6
6
  "cloudflare",
@@ -1 +0,0 @@
1
- import{LunoraError as f}from"@lunora/errors";import{a as o,c as m}from"./address-soPj2Z0j.mjs";import{isCaptureTransport as s}from"./createCaptureTransport-CKc6NpZR.mjs";import{createCloudflareTransport as y}from"./createCloudflareTransport-DpfCxn16.mjs";import{toQueuedPayload as i}from"./consumeQueuedSend-CRfALnCU.mjs";import b from"./renderEmail-BOUnr6i3.mjs";import w from"./createResendTransport-DDkOitck.mjs";const h=()=>{if(typeof crypto<"u"){if(typeof crypto.randomUUID=="function")return crypto.randomUUID();if(typeof crypto.getRandomValues=="function"){const r=crypto.getRandomValues(new Uint8Array(16));return Array.from(r,d=>d.toString(16).padStart(2,"0")).join("")}}throw new Error("randomSessionId: no Web Crypto available — a session id needs crypto.randomUUID or crypto.getRandomValues")},p=r=>{if(r.cloudflareSend)return y({from:r.from,send:r.cloudflareSend});if(r.apiKey)return w(r.apiKey,r.from);throw new f("INTERNAL","@lunora/mail: a transport is required — pass `transport`, `cloudflareSend` (Cloudflare Email Workers, the default), or `apiKey` (Resend)")},N=r=>{if(!r.from)throw new f("INTERNAL","@lunora/mail: `from` is required");const d=r.transport??p(r),n=async e=>{let{html:a}=e,{text:u}=e;if(e.react){const t=await b(e.react);a=a??t.html,u=u??t.text}if(o("subject",e.subject),e.headers)for(const[t,l]of Object.entries(e.headers))o(`header name "${t}"`,t),o(`header "${t}" value`,l);const c=e.from??r.from;return m({bcc:e.bcc,cc:e.cc,from:c,replyTo:e.replyTo,to:e.to}),{bcc:e.bcc,cc:e.cc,from:c,headers:e.headers,html:a,replyTo:e.replyTo,subject:e.subject,text:u,to:e.to}};return{queue:async e=>{if(!r.queue){if(s(d)){const c=await n(e);return await d.send(c),{queued:!0}}throw new f("INTERNAL","@lunora/mail: `queue` binding is required for mailer.queue()")}const a=await n(e),u=e.idempotencyKey??h();return await r.queue.send(i({...a,idempotencyKey:u})),{queued:!0}},send:async e=>{const a=await n(e);return d.send(a)}}};export{N as default};