ugly-app 0.1.547 → 0.1.548
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/dist/cli/version.d.ts +1 -1
- package/dist/cli/version.js +1 -1
- package/dist/server/Email.d.ts.map +1 -1
- package/dist/server/Email.js +68 -0
- package/dist/server/Email.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/version.ts +1 -1
- package/src/server/Email.ts +78 -0
package/dist/cli/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const CLI_VERSION = "0.1.
|
|
1
|
+
export declare const CLI_VERSION = "0.1.548";
|
|
2
2
|
//# sourceMappingURL=version.d.ts.map
|
package/dist/cli/version.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Email.d.ts","sourceRoot":"","sources":["../../src/server/Email.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,yFAAyF;AACzF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAMD,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKxD;AAgBD,wBAAgB,SAAS,IAAI,IAAI,CAEhC;AAED,wBAAgB,SAAS,IAAI,IAAI,CAEhC;AAID;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,YAAY,GAAG,oBAAoB,GAC3C,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"Email.d.ts","sourceRoot":"","sources":["../../src/server/Email.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,YAAY;IAC3B,kEAAkE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,gFAAgF;IAChF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,yFAAyF;AACzF,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAMD,MAAM,WAAW,WAAW;IAC1B,kCAAkC;IAClC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAKD,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,CAKxD;AAgBD,wBAAgB,SAAS,IAAI,IAAI,CAEhC;AAED,wBAAgB,SAAS,IAAI,IAAI,CAEhC;AAID;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAC7B,OAAO,EAAE,YAAY,GAAG,oBAAoB,GAC3C,OAAO,CAAC,IAAI,CAAC,CA2Ff;AAED;;;GAGG;AACH,wBAAgB,iBAAiB;kBAET;QAClB,MAAM,EAAE,MAAM,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,EAAE,CAAC,EAAE,MAAM,CAAC;QACZ,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO,CAAC,IAAI,CAAC;EAWpB"}
|
package/dist/server/Email.js
CHANGED
|
@@ -52,6 +52,31 @@ export async function emailSend(options) {
|
|
|
52
52
|
if (!hasUserId && !hasTo) {
|
|
53
53
|
throw new Error('[Email] Recipient is required (userId or to)');
|
|
54
54
|
}
|
|
55
|
+
// Direct Cloudflare Email Sending API path. When the CF email creds are
|
|
56
|
+
// present AND we have a concrete recipient address (`to`, e.g. magic-link),
|
|
57
|
+
// send via Cloudflare's `/email/sending/send` endpoint instead of the
|
|
58
|
+
// ugly.bot email proxy. This lets a lean platform core (which drops the
|
|
59
|
+
// /v1/email proxy in favor of direct CF email) still send transactional
|
|
60
|
+
// mail. `userId`-addressed sends still route through the proxy (which
|
|
61
|
+
// resolves the address server-side). Pure fetch → Workers-compatible.
|
|
62
|
+
const cfToken = process.env['CLOUDFLARE_EMAIL_API_TOKEN'];
|
|
63
|
+
const cfAccount = process.env['CLOUDFLARE_ACCOUNT_ID'];
|
|
64
|
+
const toAddr = 'to' in options ? options.to?.trim() : undefined;
|
|
65
|
+
if (cfToken && cfAccount && toAddr) {
|
|
66
|
+
await sendViaCloudflare({
|
|
67
|
+
token: cfToken,
|
|
68
|
+
accountId: cfAccount,
|
|
69
|
+
...(process.env['CLOUDFLARE_EMAIL_SENDING_DOMAIN']
|
|
70
|
+
? { sendingDomain: process.env['CLOUDFLARE_EMAIL_SENDING_DOMAIN'] }
|
|
71
|
+
: {}),
|
|
72
|
+
to: toAddr,
|
|
73
|
+
subject: options.subject,
|
|
74
|
+
html: options.html,
|
|
75
|
+
...(options.replyTo !== undefined ? { replyTo: options.replyTo } : {}),
|
|
76
|
+
...(options.headers !== undefined ? { headers: options.headers } : {}),
|
|
77
|
+
});
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
55
80
|
const { url, token, timeoutMs } = resolveConfig();
|
|
56
81
|
if (!token) {
|
|
57
82
|
throw new Error('[Email] EMAIL_PROXY_TOKEN is not set. Run `npx ugly-app login` ' +
|
|
@@ -131,4 +156,47 @@ export function createEmailSender() {
|
|
|
131
156
|
},
|
|
132
157
|
};
|
|
133
158
|
}
|
|
159
|
+
// ── Direct Cloudflare Email Sending API ─────────────────────────────────────
|
|
160
|
+
// Mirrors the monolith's CloudflareEmailSend: POST to
|
|
161
|
+
// `/accounts/{id}/email/sending/send` with a CF Email API token. Pure fetch,
|
|
162
|
+
// so it runs on Workers. Used by emailSend() when CF email creds are present
|
|
163
|
+
// (lean cores send transactional mail directly instead of via the proxy).
|
|
164
|
+
async function sendViaCloudflare(opts) {
|
|
165
|
+
// Parse "Name <email@domain>" or plain "email@domain".
|
|
166
|
+
const from = `noreply@${opts.sendingDomain ?? 'ugly.bot'}`;
|
|
167
|
+
const body = {
|
|
168
|
+
from, // string form (CF rejects object form when no display name)
|
|
169
|
+
to: opts.to,
|
|
170
|
+
subject: opts.subject,
|
|
171
|
+
html: opts.html,
|
|
172
|
+
};
|
|
173
|
+
if (opts.replyTo)
|
|
174
|
+
body['reply_to'] = opts.replyTo;
|
|
175
|
+
if (opts.headers && Object.keys(opts.headers).length > 0) {
|
|
176
|
+
body['headers'] = opts.headers;
|
|
177
|
+
}
|
|
178
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${opts.accountId}/email/sending/send`;
|
|
179
|
+
const res = await fetch(url, {
|
|
180
|
+
method: 'POST',
|
|
181
|
+
headers: {
|
|
182
|
+
Authorization: `Bearer ${opts.token}`,
|
|
183
|
+
'Content-Type': 'application/json',
|
|
184
|
+
},
|
|
185
|
+
body: JSON.stringify(body),
|
|
186
|
+
});
|
|
187
|
+
if (!res.ok) {
|
|
188
|
+
let msg = `HTTP ${res.status}`;
|
|
189
|
+
try {
|
|
190
|
+
const env = (await res.json());
|
|
191
|
+
if (env.errors?.length)
|
|
192
|
+
msg = env.errors.map((e) => e.message).join('; ');
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
/* fall back to status */
|
|
196
|
+
}
|
|
197
|
+
throw new Error('[Email] Cloudflare send failed: ' + msg);
|
|
198
|
+
}
|
|
199
|
+
// eslint-disable-next-line no-console
|
|
200
|
+
console.log('[Email] Sent via Cloudflare', { to: opts.to, subject: opts.subject });
|
|
201
|
+
}
|
|
134
202
|
//# sourceMappingURL=Email.js.map
|
package/dist/server/Email.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Email.js","sourceRoot":"","sources":["../../src/server/Email.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"Email.js","sourceRoot":"","sources":["../../src/server/Email.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/cli/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by prebuild — do not edit manually
|
|
2
|
-
export const CLI_VERSION = "0.1.
|
|
2
|
+
export const CLI_VERSION = "0.1.548";
|
package/src/server/Email.ts
CHANGED
|
@@ -100,6 +100,32 @@ export async function emailSend(
|
|
|
100
100
|
throw new Error('[Email] Recipient is required (userId or to)');
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
+
// Direct Cloudflare Email Sending API path. When the CF email creds are
|
|
104
|
+
// present AND we have a concrete recipient address (`to`, e.g. magic-link),
|
|
105
|
+
// send via Cloudflare's `/email/sending/send` endpoint instead of the
|
|
106
|
+
// ugly.bot email proxy. This lets a lean platform core (which drops the
|
|
107
|
+
// /v1/email proxy in favor of direct CF email) still send transactional
|
|
108
|
+
// mail. `userId`-addressed sends still route through the proxy (which
|
|
109
|
+
// resolves the address server-side). Pure fetch → Workers-compatible.
|
|
110
|
+
const cfToken = process.env['CLOUDFLARE_EMAIL_API_TOKEN'];
|
|
111
|
+
const cfAccount = process.env['CLOUDFLARE_ACCOUNT_ID'];
|
|
112
|
+
const toAddr = 'to' in options ? options.to?.trim() : undefined;
|
|
113
|
+
if (cfToken && cfAccount && toAddr) {
|
|
114
|
+
await sendViaCloudflare({
|
|
115
|
+
token: cfToken,
|
|
116
|
+
accountId: cfAccount,
|
|
117
|
+
...(process.env['CLOUDFLARE_EMAIL_SENDING_DOMAIN']
|
|
118
|
+
? { sendingDomain: process.env['CLOUDFLARE_EMAIL_SENDING_DOMAIN'] }
|
|
119
|
+
: {}),
|
|
120
|
+
to: toAddr,
|
|
121
|
+
subject: options.subject,
|
|
122
|
+
html: options.html,
|
|
123
|
+
...(options.replyTo !== undefined ? { replyTo: options.replyTo } : {}),
|
|
124
|
+
...(options.headers !== undefined ? { headers: options.headers } : {}),
|
|
125
|
+
});
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
103
129
|
const { url, token, timeoutMs } = resolveConfig();
|
|
104
130
|
if (!token) {
|
|
105
131
|
throw new Error(
|
|
@@ -184,3 +210,55 @@ export function createEmailSender() {
|
|
|
184
210
|
},
|
|
185
211
|
};
|
|
186
212
|
}
|
|
213
|
+
|
|
214
|
+
// ── Direct Cloudflare Email Sending API ─────────────────────────────────────
|
|
215
|
+
// Mirrors the monolith's CloudflareEmailSend: POST to
|
|
216
|
+
// `/accounts/{id}/email/sending/send` with a CF Email API token. Pure fetch,
|
|
217
|
+
// so it runs on Workers. Used by emailSend() when CF email creds are present
|
|
218
|
+
// (lean cores send transactional mail directly instead of via the proxy).
|
|
219
|
+
async function sendViaCloudflare(opts: {
|
|
220
|
+
token: string;
|
|
221
|
+
accountId: string;
|
|
222
|
+
sendingDomain?: string;
|
|
223
|
+
to: string;
|
|
224
|
+
subject: string;
|
|
225
|
+
html: string;
|
|
226
|
+
replyTo?: string;
|
|
227
|
+
headers?: Record<string, string>;
|
|
228
|
+
}): Promise<void> {
|
|
229
|
+
// Parse "Name <email@domain>" or plain "email@domain".
|
|
230
|
+
const from = `noreply@${opts.sendingDomain ?? 'ugly.bot'}`;
|
|
231
|
+
const body: Record<string, unknown> = {
|
|
232
|
+
from, // string form (CF rejects object form when no display name)
|
|
233
|
+
to: opts.to,
|
|
234
|
+
subject: opts.subject,
|
|
235
|
+
html: opts.html,
|
|
236
|
+
};
|
|
237
|
+
if (opts.replyTo) body['reply_to'] = opts.replyTo;
|
|
238
|
+
if (opts.headers && Object.keys(opts.headers).length > 0) {
|
|
239
|
+
body['headers'] = opts.headers;
|
|
240
|
+
}
|
|
241
|
+
const url = `https://api.cloudflare.com/client/v4/accounts/${opts.accountId}/email/sending/send`;
|
|
242
|
+
const res = await fetch(url, {
|
|
243
|
+
method: 'POST',
|
|
244
|
+
headers: {
|
|
245
|
+
Authorization: `Bearer ${opts.token}`,
|
|
246
|
+
'Content-Type': 'application/json',
|
|
247
|
+
},
|
|
248
|
+
body: JSON.stringify(body),
|
|
249
|
+
});
|
|
250
|
+
if (!res.ok) {
|
|
251
|
+
let msg = `HTTP ${res.status}`;
|
|
252
|
+
try {
|
|
253
|
+
const env = (await res.json()) as {
|
|
254
|
+
errors?: { message: string }[];
|
|
255
|
+
};
|
|
256
|
+
if (env.errors?.length) msg = env.errors.map((e) => e.message).join('; ');
|
|
257
|
+
} catch {
|
|
258
|
+
/* fall back to status */
|
|
259
|
+
}
|
|
260
|
+
throw new Error('[Email] Cloudflare send failed: ' + msg);
|
|
261
|
+
}
|
|
262
|
+
// eslint-disable-next-line no-console
|
|
263
|
+
console.log('[Email] Sent via Cloudflare', { to: opts.to, subject: opts.subject });
|
|
264
|
+
}
|