bunderstack 0.7.0 → 0.9.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.
- package/README.md +45 -12
- package/package.json +23 -10
- package/src/config.ts +36 -6
- package/src/database/adapter.ts +26 -0
- package/src/database/bun-sql.ts +23 -0
- package/src/database/libsql.ts +28 -0
- package/src/database/pglite.ts +33 -0
- package/src/database/postgres-js.ts +33 -0
- package/src/db.ts +32 -74
- package/src/email/smtp.ts +45 -0
- package/src/email.ts +13 -59
- package/src/index.ts +405 -300
- package/src/lifecycle.ts +7 -2
- package/src/manifest.ts +4 -0
- package/src/provision-internals.ts +2 -1
- package/src/provision.ts +7 -18
- package/src/realtime/facade.ts +16 -0
- package/src/typeid.ts +2 -2
package/src/email.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
// src/email.ts — email sending:
|
|
1
|
+
// src/email.ts — email sending: console / resend / custom adapters.
|
|
2
|
+
// SMTP is provided by the static `bunderstack/email/smtp` factory subpath.
|
|
2
3
|
|
|
3
4
|
export type EmailMessage = {
|
|
4
5
|
to: string | string[]
|
|
@@ -20,7 +21,7 @@ export type EmailAdapter = {
|
|
|
20
21
|
|
|
21
22
|
export type EmailConfigInput = {
|
|
22
23
|
from: string
|
|
23
|
-
provider?: 'resend' | '
|
|
24
|
+
provider?: 'resend' | 'console' | EmailAdapter | EmailAdapter['send']
|
|
24
25
|
}
|
|
25
26
|
|
|
26
27
|
export type EmailFacade = {
|
|
@@ -31,11 +32,9 @@ export type CreateEmailOptions = {
|
|
|
31
32
|
env: { RESEND_API_KEY?: string; SMTP_URL?: string; NODE_ENV?: string }
|
|
32
33
|
/** Test seam for the resend adapter. */
|
|
33
34
|
fetchFn?: typeof fetch
|
|
34
|
-
/** Test seam for the nodemailer presence check. */
|
|
35
|
-
canResolveModule?: (specifier: string) => boolean
|
|
36
35
|
}
|
|
37
36
|
|
|
38
|
-
/**
|
|
37
|
+
/** Root string provider tag ('resend' | 'console') or undefined. */
|
|
39
38
|
export function emailProviderTag(
|
|
40
39
|
config: EmailConfigInput | undefined,
|
|
41
40
|
): string | undefined {
|
|
@@ -98,54 +97,6 @@ function createResendAdapter(
|
|
|
98
97
|
}
|
|
99
98
|
}
|
|
100
99
|
|
|
101
|
-
function createSmtpAdapter(
|
|
102
|
-
smtpUrl: string,
|
|
103
|
-
canResolve: (specifier: string) => boolean,
|
|
104
|
-
): EmailAdapter {
|
|
105
|
-
if (!canResolve('nodemailer')) {
|
|
106
|
-
throw new Error(
|
|
107
|
-
"email provider 'smtp' requires nodemailer — install it with: bun add nodemailer",
|
|
108
|
-
)
|
|
109
|
-
}
|
|
110
|
-
// Lazy import so boot stays sync; cached across sends. Variable specifier
|
|
111
|
-
// keeps TS from resolving the optional peer's types at compile time.
|
|
112
|
-
const specifier = 'nodemailer'
|
|
113
|
-
let transportPromise: Promise<{
|
|
114
|
-
sendMail(opts: Record<string, unknown>): Promise<{ messageId?: string }>
|
|
115
|
-
}> | null = null
|
|
116
|
-
const getTransport = () => {
|
|
117
|
-
transportPromise ??= import(/* @vite-ignore */ specifier).then((mod) =>
|
|
118
|
-
(mod.default ?? mod).createTransport(smtpUrl),
|
|
119
|
-
)
|
|
120
|
-
return transportPromise
|
|
121
|
-
}
|
|
122
|
-
return {
|
|
123
|
-
async send(msg) {
|
|
124
|
-
const transport = await getTransport()
|
|
125
|
-
const info = await transport.sendMail({
|
|
126
|
-
from: msg.from,
|
|
127
|
-
to: toArray(msg.to)!.join(', '),
|
|
128
|
-
subject: msg.subject,
|
|
129
|
-
html: msg.html,
|
|
130
|
-
text: msg.text,
|
|
131
|
-
replyTo: msg.replyTo,
|
|
132
|
-
cc: toArray(msg.cc)?.join(', '),
|
|
133
|
-
bcc: toArray(msg.bcc)?.join(', '),
|
|
134
|
-
})
|
|
135
|
-
return { id: info.messageId }
|
|
136
|
-
},
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function defaultCanResolve(specifier: string): boolean {
|
|
141
|
-
try {
|
|
142
|
-
Bun.resolveSync(specifier, import.meta.dir)
|
|
143
|
-
return true
|
|
144
|
-
} catch {
|
|
145
|
-
return false
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
100
|
function resolveAdapter(
|
|
150
101
|
config: EmailConfigInput,
|
|
151
102
|
opts: CreateEmailOptions,
|
|
@@ -157,18 +108,21 @@ function resolveAdapter(
|
|
|
157
108
|
switch (provider) {
|
|
158
109
|
case 'resend':
|
|
159
110
|
return createResendAdapter(opts.env.RESEND_API_KEY ?? '', fetchFn)
|
|
160
|
-
|
|
161
|
-
return createSmtpAdapter(
|
|
162
|
-
opts.env.SMTP_URL ?? '',
|
|
163
|
-
opts.canResolveModule ?? defaultCanResolve,
|
|
164
|
-
)
|
|
111
|
+
|
|
165
112
|
case 'console':
|
|
166
113
|
return createConsoleAdapter()
|
|
167
114
|
case undefined:
|
|
168
115
|
if (opts.env.NODE_ENV === 'production') {
|
|
169
116
|
throw new Error(
|
|
170
117
|
'email is configured without a provider — set email.provider ' +
|
|
171
|
-
"('resend' |
|
|
118
|
+
"('resend' | a custom adapter) for production",
|
|
119
|
+
)
|
|
120
|
+
}
|
|
121
|
+
return createConsoleAdapter()
|
|
122
|
+
default:
|
|
123
|
+
if (provider === 'smtp') {
|
|
124
|
+
throw new Error(
|
|
125
|
+
"email provider 'smtp' was removed. Import `smtp` from 'bunderstack/email/smtp' instead.",
|
|
172
126
|
)
|
|
173
127
|
}
|
|
174
128
|
return createConsoleAdapter()
|