@voyantjs/notifications 0.13.0 → 0.14.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 +24 -24
- package/dist/index.d.ts +4 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -3
- package/dist/providers/voyant-cloud-email.d.ts +27 -0
- package/dist/providers/voyant-cloud-email.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-email.js +30 -0
- package/dist/providers/voyant-cloud-sms.d.ts +26 -0
- package/dist/providers/voyant-cloud-sms.d.ts.map +1 -0
- package/dist/providers/voyant-cloud-sms.js +24 -0
- package/dist/task-runtime.d.ts +1 -4
- package/dist/task-runtime.d.ts.map +1 -1
- package/dist/task-runtime.js +5 -4
- package/dist/types.d.ts +5 -3
- package/dist/types.d.ts.map +1 -1
- package/package.json +14 -13
- package/dist/provider-resolution.d.ts +0 -19
- package/dist/provider-resolution.d.ts.map +0 -1
- package/dist/provider-resolution.js +0 -52
- package/dist/providers/resend.d.ts +0 -52
- package/dist/providers/resend.d.ts.map +0 -1
- package/dist/providers/resend.js +0 -58
- package/dist/providers/twilio.d.ts +0 -24
- package/dist/providers/twilio.d.ts.map +0 -1
- package/dist/providers/twilio.js +0 -48
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
Notifications module for Voyant. It includes:
|
|
4
4
|
|
|
5
5
|
- provider abstraction via `NotificationProvider`
|
|
6
|
-
- first-party providers for local development and
|
|
6
|
+
- first-party providers for local development and Voyant Cloud (email + SMS)
|
|
7
7
|
- database-backed notification templates
|
|
8
8
|
- database-backed delivery logs
|
|
9
9
|
- notification reminder rules and reminder runs
|
|
@@ -23,55 +23,55 @@ pnpm add @voyantjs/notifications
|
|
|
23
23
|
## Usage
|
|
24
24
|
|
|
25
25
|
```typescript
|
|
26
|
+
import { getVoyantCloudClient } from "@voyantjs/voyant-cloud"
|
|
26
27
|
import { createNotificationService } from "@voyantjs/notifications"
|
|
27
28
|
import { createLocalProvider } from "@voyantjs/notifications/providers/local"
|
|
28
|
-
import {
|
|
29
|
+
import { createVoyantCloudEmailProvider } from "@voyantjs/notifications/providers/voyant-cloud-email"
|
|
30
|
+
import { createVoyantCloudSmsProvider } from "@voyantjs/notifications/providers/voyant-cloud-sms"
|
|
29
31
|
|
|
32
|
+
const cloud = getVoyantCloudClient(env)
|
|
30
33
|
const notifications = createNotificationService([
|
|
31
|
-
createLocalProvider(),
|
|
32
|
-
|
|
34
|
+
createLocalProvider({ channels: ["email"] }),
|
|
35
|
+
createVoyantCloudEmailProvider({ client: cloud, from: "noreply@example.com" }),
|
|
36
|
+
createVoyantCloudSmsProvider({ client: cloud }),
|
|
33
37
|
])
|
|
34
38
|
|
|
35
|
-
await notifications.
|
|
39
|
+
await notifications.send({
|
|
36
40
|
to: "user@example.com",
|
|
37
41
|
channel: "email",
|
|
38
42
|
template: "welcome",
|
|
39
43
|
subject: "Hello",
|
|
40
44
|
html: "<p>Welcome</p>",
|
|
41
|
-
attachments: [
|
|
42
|
-
{
|
|
43
|
-
filename: "invoice.pdf",
|
|
44
|
-
path: "https://cdn.example.com/invoices/invoice.pdf",
|
|
45
|
-
contentType: "application/pdf",
|
|
46
|
-
},
|
|
47
|
-
],
|
|
48
45
|
})
|
|
49
46
|
```
|
|
50
47
|
|
|
51
48
|
Later providers override earlier ones on channel conflict; `sendWith(name, payload)` dispatches by provider name.
|
|
52
49
|
|
|
53
|
-
The bring-your-own path is first-class: any project can
|
|
54
|
-
|
|
50
|
+
The bring-your-own path is first-class: any project can implement
|
|
51
|
+
`NotificationProvider` against another transport (raw Resend, Twilio, SES, …)
|
|
52
|
+
and register it in place of the cloud adapters.
|
|
55
53
|
|
|
56
54
|
For the Hono module:
|
|
57
55
|
|
|
58
56
|
```ts
|
|
57
|
+
import { getVoyantCloudClient } from "@voyantjs/voyant-cloud"
|
|
59
58
|
import {
|
|
60
|
-
createDefaultNotificationProviders,
|
|
61
59
|
createNotificationsHonoModule,
|
|
60
|
+
createVoyantCloudEmailProvider,
|
|
61
|
+
createVoyantCloudSmsProvider,
|
|
62
62
|
} from "@voyantjs/notifications"
|
|
63
63
|
|
|
64
64
|
const notificationsModule = createNotificationsHonoModule({
|
|
65
|
-
resolveProviders: (env) =>
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
resolveProviders: (env) => {
|
|
66
|
+
const cloud = getVoyantCloudClient(env as Record<string, unknown>)
|
|
67
|
+
return [
|
|
68
|
+
createVoyantCloudEmailProvider({ client: cloud, from: "noreply@example.com" }),
|
|
69
|
+
createVoyantCloudSmsProvider({ client: cloud }),
|
|
70
|
+
]
|
|
71
|
+
},
|
|
69
72
|
})
|
|
70
73
|
```
|
|
71
74
|
|
|
72
|
-
`createDefaultNotificationProviders(env)` is intentionally local-only by default. Built-in
|
|
73
|
-
email providers should be opted into explicitly at the app boundary.
|
|
74
|
-
|
|
75
75
|
For scheduled reminder sweeps:
|
|
76
76
|
|
|
77
77
|
```ts
|
|
@@ -115,9 +115,9 @@ time from the current storage/runtime context.
|
|
|
115
115
|
| `./routes` | Hono route factory |
|
|
116
116
|
| `./service` | Dispatcher + database-backed notifications service |
|
|
117
117
|
| `./tasks` | Reminder sweep task helpers |
|
|
118
|
-
| `./provider-resolution` | Default local/Resend provider wiring |
|
|
119
118
|
| `./providers/local` | Console sink for dev |
|
|
120
|
-
| `./providers/
|
|
119
|
+
| `./providers/voyant-cloud-email` | Voyant Cloud email provider |
|
|
120
|
+
| `./providers/voyant-cloud-sms` | Voyant Cloud SMS provider |
|
|
121
121
|
|
|
122
122
|
## License
|
|
123
123
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,14 +2,12 @@ import type { HonoModule } from "@voyantjs/hono/module";
|
|
|
2
2
|
import type { PostgresJsDatabase } from "drizzle-orm/postgres-js";
|
|
3
3
|
import { type NotificationsRoutesOptions } from "./routes.js";
|
|
4
4
|
export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
|
|
5
|
-
export type { DefaultNotificationProviderOptions } from "./provider-resolution.js";
|
|
6
|
-
export { createDefaultNotificationProviders, createResendProviderFromEnv, createTwilioProviderFromEnv, } from "./provider-resolution.js";
|
|
7
5
|
export type { LocalProviderOptions } from "./providers/local.js";
|
|
8
6
|
export { createLocalProvider } from "./providers/local.js";
|
|
9
|
-
export type {
|
|
10
|
-
export {
|
|
11
|
-
export type {
|
|
12
|
-
export {
|
|
7
|
+
export type { VoyantCloudEmailProviderOptions, VoyantCloudEmailRendered, } from "./providers/voyant-cloud-email.js";
|
|
8
|
+
export { createVoyantCloudEmailProvider } from "./providers/voyant-cloud-email.js";
|
|
9
|
+
export type { VoyantCloudSmsProviderOptions, VoyantCloudSmsRendered, } from "./providers/voyant-cloud-sms.js";
|
|
10
|
+
export { createVoyantCloudSmsProvider } from "./providers/voyant-cloud-sms.js";
|
|
13
11
|
export type { NotificationsRouteRuntime, NotificationsRoutesOptions } from "./routes.js";
|
|
14
12
|
export { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, } from "./routes.js";
|
|
15
13
|
export type { NewNotificationDelivery, NewNotificationReminderRule, NewNotificationReminderRun, NewNotificationTemplate, NotificationDelivery, NotificationReminderRule, NotificationReminderRun, NotificationsHonoModule, NotificationTemplate, } from "./schema.js";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAA;AAEjE,OAAO,EAIL,KAAK,0BAA0B,EAChC,MAAM,aAAa,CAAA;AAKpB,OAAO,EACL,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,aAAa,CAAA;AACpB,YAAY,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -3,10 +3,9 @@ import { notificationsModule } from "./schema.js";
|
|
|
3
3
|
import { createNotificationService } from "./service.js";
|
|
4
4
|
import { bookingDocumentNotificationsService } from "./service-booking-documents.js";
|
|
5
5
|
export { notificationLiquidEngine, renderLiquidTemplate, } from "./liquid.js";
|
|
6
|
-
export { createDefaultNotificationProviders, createResendProviderFromEnv, createTwilioProviderFromEnv, } from "./provider-resolution.js";
|
|
7
6
|
export { createLocalProvider } from "./providers/local.js";
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
7
|
+
export { createVoyantCloudEmailProvider } from "./providers/voyant-cloud-email.js";
|
|
8
|
+
export { createVoyantCloudSmsProvider } from "./providers/voyant-cloud-sms.js";
|
|
10
9
|
export { buildNotificationsRouteRuntime, createNotificationsRoutes, NOTIFICATIONS_ROUTE_RUNTIME_CONTAINER_KEY, } from "./routes.js";
|
|
11
10
|
export { notificationChannelEnum, notificationDeliveries, notificationDeliveryStatusEnum, notificationReminderRules, notificationReminderRunStatusEnum, notificationReminderRuns, notificationReminderStatusEnum, notificationReminderTargetTypeEnum, notificationsModule, notificationTargetTypeEnum, notificationTemplateStatusEnum, notificationTemplates, } from "./schema.js";
|
|
12
11
|
export { createDefaultBookingDocumentAttachment, createNotificationService, NotificationError, notificationsService, previewNotificationTemplate, renderNotificationTemplate, } from "./service.js";
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { VoyantCloudClient } from "@voyantjs/voyant-cloud";
|
|
2
|
+
import type { NotificationProvider } from "../types.js";
|
|
3
|
+
export interface VoyantCloudEmailRendered {
|
|
4
|
+
subject: string;
|
|
5
|
+
html?: string;
|
|
6
|
+
text?: string;
|
|
7
|
+
}
|
|
8
|
+
export interface VoyantCloudEmailProviderOptions {
|
|
9
|
+
/** Cloud SDK client. Construct via `getVoyantCloudClient(env)`. */
|
|
10
|
+
client: VoyantCloudClient;
|
|
11
|
+
/** Default sender address. Payload `from` overrides. */
|
|
12
|
+
from: string;
|
|
13
|
+
/** Optional default reply-to addresses. Payload may override per-send. */
|
|
14
|
+
replyTo?: ReadonlyArray<string>;
|
|
15
|
+
/**
|
|
16
|
+
* Render a template id + data tuple into an email body. When omitted,
|
|
17
|
+
* the payload's `template` is used as the subject and `data` is
|
|
18
|
+
* JSON-stringified into the text body.
|
|
19
|
+
*/
|
|
20
|
+
renderTemplate?: (template: string, data: unknown) => Promise<VoyantCloudEmailRendered> | VoyantCloudEmailRendered;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Notification provider that delivers email through the Voyant Cloud
|
|
24
|
+
* `/email/v1/messages` endpoint.
|
|
25
|
+
*/
|
|
26
|
+
export declare function createVoyantCloudEmailProvider(options: VoyantCloudEmailProviderOptions): NotificationProvider;
|
|
27
|
+
//# sourceMappingURL=voyant-cloud-email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyant-cloud-email.d.ts","sourceRoot":"","sources":["../../src/providers/voyant-cloud-email.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAA;AAE3E,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,+BAA+B;IAC9C,mEAAmE;IACnE,MAAM,EAAE,iBAAiB,CAAA;IACzB,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAA;IAC/B;;;;OAIG;IACH,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,KACV,OAAO,CAAC,wBAAwB,CAAC,GAAG,wBAAwB,CAAA;CAClE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,OAAO,EAAE,+BAA+B,GACvC,oBAAoB,CA8BtB"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification provider that delivers email through the Voyant Cloud
|
|
3
|
+
* `/email/v1/messages` endpoint.
|
|
4
|
+
*/
|
|
5
|
+
export function createVoyantCloudEmailProvider(options) {
|
|
6
|
+
return {
|
|
7
|
+
name: "voyant-cloud-email",
|
|
8
|
+
channels: ["email"],
|
|
9
|
+
async send(payload) {
|
|
10
|
+
if (payload.channel !== "email") {
|
|
11
|
+
throw new Error(`Voyant Cloud email provider only supports the "email" channel, got "${payload.channel}"`);
|
|
12
|
+
}
|
|
13
|
+
const rendered = options.renderTemplate
|
|
14
|
+
? await options.renderTemplate(payload.template, payload.data)
|
|
15
|
+
: {
|
|
16
|
+
subject: payload.subject ?? payload.template,
|
|
17
|
+
text: JSON.stringify(payload.data ?? {}),
|
|
18
|
+
};
|
|
19
|
+
const message = await options.client.email.sendMessage({
|
|
20
|
+
from: payload.from ?? options.from,
|
|
21
|
+
to: [payload.to],
|
|
22
|
+
subject: payload.subject ?? rendered.subject,
|
|
23
|
+
html: payload.html ?? rendered.html ?? null,
|
|
24
|
+
text: payload.text ?? rendered.text ?? null,
|
|
25
|
+
replyTo: options.replyTo ? [...options.replyTo] : null,
|
|
26
|
+
});
|
|
27
|
+
return { id: message.id, provider: "voyant-cloud-email" };
|
|
28
|
+
},
|
|
29
|
+
};
|
|
30
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { VoyantCloudClient } from "@voyantjs/voyant-cloud";
|
|
2
|
+
import type { NotificationProvider } from "../types.js";
|
|
3
|
+
export interface VoyantCloudSmsRendered {
|
|
4
|
+
text: string;
|
|
5
|
+
}
|
|
6
|
+
export interface VoyantCloudSmsProviderOptions {
|
|
7
|
+
/** Cloud SDK client. Construct via `getVoyantCloudClient(env)`. */
|
|
8
|
+
client: VoyantCloudClient;
|
|
9
|
+
/**
|
|
10
|
+
* Default sender phone number. When omitted, the cloud account's default
|
|
11
|
+
* shared number is used (server-side selection).
|
|
12
|
+
*/
|
|
13
|
+
from?: string;
|
|
14
|
+
/**
|
|
15
|
+
* Render a template id + data tuple into an SMS body. When omitted, the
|
|
16
|
+
* payload's `text` field is used directly, falling back to a JSON dump of
|
|
17
|
+
* `data`.
|
|
18
|
+
*/
|
|
19
|
+
renderTemplate?: (template: string, data: unknown) => Promise<VoyantCloudSmsRendered> | VoyantCloudSmsRendered;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Notification provider that delivers SMS through the Voyant Cloud
|
|
23
|
+
* `/sms/v1/messages` endpoint.
|
|
24
|
+
*/
|
|
25
|
+
export declare function createVoyantCloudSmsProvider(options: VoyantCloudSmsProviderOptions): NotificationProvider;
|
|
26
|
+
//# sourceMappingURL=voyant-cloud-sms.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"voyant-cloud-sms.d.ts","sourceRoot":"","sources":["../../src/providers/voyant-cloud-sms.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAA;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAA;AAE3E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,6BAA6B;IAC5C,mEAAmE;IACnE,MAAM,EAAE,iBAAiB,CAAA;IACzB;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;OAIG;IACH,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,KACV,OAAO,CAAC,sBAAsB,CAAC,GAAG,sBAAsB,CAAA;CAC9D;AAED;;;GAGG;AACH,wBAAgB,4BAA4B,CAC1C,OAAO,EAAE,6BAA6B,GACrC,oBAAoB,CAwBtB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notification provider that delivers SMS through the Voyant Cloud
|
|
3
|
+
* `/sms/v1/messages` endpoint.
|
|
4
|
+
*/
|
|
5
|
+
export function createVoyantCloudSmsProvider(options) {
|
|
6
|
+
return {
|
|
7
|
+
name: "voyant-cloud-sms",
|
|
8
|
+
channels: ["sms"],
|
|
9
|
+
async send(payload) {
|
|
10
|
+
if (payload.channel !== "sms") {
|
|
11
|
+
throw new Error(`Voyant Cloud SMS provider only supports the "sms" channel, got "${payload.channel}"`);
|
|
12
|
+
}
|
|
13
|
+
const rendered = options.renderTemplate
|
|
14
|
+
? await options.renderTemplate(payload.template, payload.data)
|
|
15
|
+
: { text: payload.text ?? JSON.stringify(payload.data ?? {}) };
|
|
16
|
+
const message = await options.client.sms.sendMessage({
|
|
17
|
+
to: payload.to,
|
|
18
|
+
from: payload.from ?? options.from ?? null,
|
|
19
|
+
body: payload.text ?? rendered.text,
|
|
20
|
+
});
|
|
21
|
+
return { id: message.id, provider: "voyant-cloud-sms" };
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
package/dist/task-runtime.d.ts
CHANGED
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import type { ExecutionLockManager } from "@voyantjs/core";
|
|
2
2
|
import type { NotificationProvider } from "./types.js";
|
|
3
|
-
export type NotificationTaskEnv =
|
|
4
|
-
RESEND_API_KEY?: unknown;
|
|
5
|
-
EMAIL_FROM?: unknown;
|
|
6
|
-
};
|
|
3
|
+
export type NotificationTaskEnv = Record<string, unknown>;
|
|
7
4
|
export type ReminderDeliveryJob = {
|
|
8
5
|
reminderRunId: string;
|
|
9
6
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-runtime.d.ts","sourceRoot":"","sources":["../src/task-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"task-runtime.d.ts","sourceRoot":"","sources":["../src/task-runtime.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAA;AAE1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;AAEzD,MAAM,MAAM,mBAAmB,GAAG;IAChC,aAAa,EAAE,MAAM,CAAA;CACtB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC9C,wBAAwB,CAAC,EAAE,oBAAoB,CAAA;IAC/C,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CACtE,CAAA;AAED,MAAM,MAAM,8BAA8B,GAAG;IAC3C,SAAS,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;IAC/C,wBAAwB,CAAC,EAAE,oBAAoB,CAAA;IAC/C,uBAAuB,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACrE,gBAAgB,CAAC,EAAE,CAAC,GAAG,EAAE,mBAAmB,KAAK,aAAa,CAAC,oBAAoB,CAAC,CAAA;CACrF,CAAA;AAED,wBAAgB,4BAA4B,CAC1C,GAAG,EAAE,mBAAmB,EACxB,OAAO,GAAE,8BAAmC,GAC3C,uBAAuB,CAazB"}
|
package/dist/task-runtime.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { createDefaultNotificationProviders } from "./provider-resolution.js";
|
|
2
1
|
export function buildNotificationTaskRuntime(env, options = {}) {
|
|
2
|
+
const providers = options.resolveProviders?.(env) ?? options.providers;
|
|
3
|
+
if (!providers) {
|
|
4
|
+
throw new Error("buildNotificationTaskRuntime requires `providers` or `resolveProviders` — there are no default providers.");
|
|
5
|
+
}
|
|
3
6
|
return {
|
|
4
|
-
providers
|
|
5
|
-
options.providers ??
|
|
6
|
-
createDefaultNotificationProviders(env),
|
|
7
|
+
providers,
|
|
7
8
|
reminderSweepLockManager: options.reminderSweepLockManager,
|
|
8
9
|
enqueueReminderDelivery: options.enqueueReminderDelivery,
|
|
9
10
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -64,10 +64,12 @@ export interface NotificationResult {
|
|
|
64
64
|
* channels and handle the actual delivery (HTTP call, SMTP, etc.).
|
|
65
65
|
*
|
|
66
66
|
* Built-in implementations:
|
|
67
|
-
* -
|
|
68
|
-
* -
|
|
67
|
+
* - `createLocalProvider` — logs to console (dev/tests)
|
|
68
|
+
* - `createVoyantCloudEmailProvider` — Voyant Cloud email API
|
|
69
|
+
* - `createVoyantCloudSmsProvider` — Voyant Cloud SMS API
|
|
69
70
|
*
|
|
70
|
-
*
|
|
71
|
+
* Self-hosters who want to deliver via a different provider (raw Resend,
|
|
72
|
+
* Twilio, SES, …) can implement this interface in their template.
|
|
71
73
|
*/
|
|
72
74
|
export interface NotificationProvider {
|
|
73
75
|
/** Unique provider name (e.g. "resend", "local", "twilio"). */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IACrC,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAA;IACV,yCAAyC;IACzC,OAAO,EAAE,mBAAmB,CAAA;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,WAAW,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,MAAM,mBAAmB,GAAG,OAAO,GAAG,KAAK,GAAG,CAAC,MAAM,GAAG,EAAE,CAAC,CAAA;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,8BAA8B;IAC9B,QAAQ,EAAE,MAAM,CAAA;IAChB,gDAAgD;IAChD,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sBAAsB;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,qCAAqC;IACrC,WAAW,CAAC,EAAE,YAAY,GAAG,QAAQ,CAAA;IACrC,kCAAkC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,mBAAmB;IAClC,wEAAwE;IACxE,EAAE,EAAE,MAAM,CAAA;IACV,yCAAyC;IACzC,OAAO,EAAE,mBAAmB,CAAA;IAC5B,wEAAwE;IACxE,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,iEAAiE;IACjE,QAAQ,EAAE,MAAM,CAAA;IAChB,iDAAiD;IACjD,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,uEAAuE;IACvE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,4DAA4D;IAC5D,WAAW,CAAC,EAAE,aAAa,CAAC,sBAAsB,CAAC,CAAA;CACpD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,uDAAuD;IACvD,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,oBAAoB;IACnC,+DAA+D;IAC/D,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,yCAAyC;IACzC,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,mBAAmB,CAAC,CAAA;IACrD,mDAAmD;IACnD,IAAI,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAA;CAChE"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@voyantjs/notifications",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"license": "FSL-1.1-Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -36,13 +36,13 @@
|
|
|
36
36
|
"types": "./dist/providers/local.d.ts",
|
|
37
37
|
"import": "./dist/providers/local.js"
|
|
38
38
|
},
|
|
39
|
-
"./providers/
|
|
40
|
-
"types": "./dist/providers/
|
|
41
|
-
"import": "./dist/providers/
|
|
39
|
+
"./providers/voyant-cloud-email": {
|
|
40
|
+
"types": "./dist/providers/voyant-cloud-email.d.ts",
|
|
41
|
+
"import": "./dist/providers/voyant-cloud-email.js"
|
|
42
42
|
},
|
|
43
|
-
"./
|
|
44
|
-
"types": "./dist/
|
|
45
|
-
"import": "./dist/
|
|
43
|
+
"./providers/voyant-cloud-sms": {
|
|
44
|
+
"types": "./dist/providers/voyant-cloud-sms.d.ts",
|
|
45
|
+
"import": "./dist/providers/voyant-cloud-sms.js"
|
|
46
46
|
}
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
@@ -50,12 +50,13 @@
|
|
|
50
50
|
"hono": "^4.12.10",
|
|
51
51
|
"liquidjs": "^10.24.0",
|
|
52
52
|
"zod": "^4.3.6",
|
|
53
|
-
"@voyantjs/bookings": "0.
|
|
54
|
-
"@voyantjs/core": "0.
|
|
55
|
-
"@voyantjs/db": "0.
|
|
56
|
-
"@voyantjs/finance": "0.
|
|
57
|
-
"@voyantjs/hono": "0.
|
|
58
|
-
"@voyantjs/legal": "0.
|
|
53
|
+
"@voyantjs/bookings": "0.14.0",
|
|
54
|
+
"@voyantjs/core": "0.14.0",
|
|
55
|
+
"@voyantjs/db": "0.14.0",
|
|
56
|
+
"@voyantjs/finance": "0.14.0",
|
|
57
|
+
"@voyantjs/hono": "0.14.0",
|
|
58
|
+
"@voyantjs/legal": "0.14.0",
|
|
59
|
+
"@voyantjs/voyant-cloud": "0.14.0"
|
|
59
60
|
},
|
|
60
61
|
"devDependencies": {
|
|
61
62
|
"typescript": "^6.0.2",
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import type { NotificationProvider } from "./types.js";
|
|
2
|
-
type NotificationProviderEnv = {
|
|
3
|
-
RESEND_API_KEY?: unknown;
|
|
4
|
-
EMAIL_FROM?: unknown;
|
|
5
|
-
TWILIO_ACCOUNT_SID?: unknown;
|
|
6
|
-
TWILIO_AUTH_TOKEN?: unknown;
|
|
7
|
-
TWILIO_SMS_FROM?: unknown;
|
|
8
|
-
};
|
|
9
|
-
export interface DefaultNotificationProviderOptions {
|
|
10
|
-
includeLocal?: boolean;
|
|
11
|
-
emailProvider?: "resend" | null;
|
|
12
|
-
smsProvider?: "twilio" | null;
|
|
13
|
-
customProviders?: ReadonlyArray<NotificationProvider>;
|
|
14
|
-
}
|
|
15
|
-
export declare function createResendProviderFromEnv(env: NotificationProviderEnv): NotificationProvider | null;
|
|
16
|
-
export declare function createTwilioProviderFromEnv(env: NotificationProviderEnv): NotificationProvider | null;
|
|
17
|
-
export declare function createDefaultNotificationProviders(env: NotificationProviderEnv, options?: DefaultNotificationProviderOptions): NotificationProvider[];
|
|
18
|
-
export {};
|
|
19
|
-
//# sourceMappingURL=provider-resolution.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"provider-resolution.d.ts","sourceRoot":"","sources":["../src/provider-resolution.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAEtD,KAAK,uBAAuB,GAAG;IAC7B,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAC3B,eAAe,CAAC,EAAE,OAAO,CAAA;CAC1B,CAAA;AAED,MAAM,WAAW,kCAAkC;IACjD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,aAAa,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC/B,WAAW,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;IAC7B,eAAe,CAAC,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAA;CACtD;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,uBAAuB,+BAcvE;AAED,wBAAgB,2BAA2B,CAAC,GAAG,EAAE,uBAAuB,+BAiBvE;AAED,wBAAgB,kCAAkC,CAChD,GAAG,EAAE,uBAAuB,EAC5B,OAAO,GAAE,kCAAuC,0BA2BjD"}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { createLocalProvider } from "./providers/local.js";
|
|
2
|
-
import { createResendProvider } from "./providers/resend.js";
|
|
3
|
-
import { createTwilioProvider } from "./providers/twilio.js";
|
|
4
|
-
export function createResendProviderFromEnv(env) {
|
|
5
|
-
if (typeof env.RESEND_API_KEY === "string" &&
|
|
6
|
-
env.RESEND_API_KEY &&
|
|
7
|
-
typeof env.EMAIL_FROM === "string" &&
|
|
8
|
-
env.EMAIL_FROM) {
|
|
9
|
-
return createResendProvider({
|
|
10
|
-
apiKey: env.RESEND_API_KEY,
|
|
11
|
-
from: env.EMAIL_FROM,
|
|
12
|
-
});
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
export function createTwilioProviderFromEnv(env) {
|
|
17
|
-
if (typeof env.TWILIO_ACCOUNT_SID === "string" &&
|
|
18
|
-
env.TWILIO_ACCOUNT_SID &&
|
|
19
|
-
typeof env.TWILIO_AUTH_TOKEN === "string" &&
|
|
20
|
-
env.TWILIO_AUTH_TOKEN &&
|
|
21
|
-
typeof env.TWILIO_SMS_FROM === "string" &&
|
|
22
|
-
env.TWILIO_SMS_FROM) {
|
|
23
|
-
return createTwilioProvider({
|
|
24
|
-
accountSid: env.TWILIO_ACCOUNT_SID,
|
|
25
|
-
authToken: env.TWILIO_AUTH_TOKEN,
|
|
26
|
-
from: env.TWILIO_SMS_FROM,
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
return null;
|
|
30
|
-
}
|
|
31
|
-
export function createDefaultNotificationProviders(env, options = {}) {
|
|
32
|
-
const providers = [];
|
|
33
|
-
if (options.includeLocal !== false) {
|
|
34
|
-
providers.push(createLocalProvider());
|
|
35
|
-
}
|
|
36
|
-
if (options.emailProvider === "resend") {
|
|
37
|
-
const resend = createResendProviderFromEnv(env);
|
|
38
|
-
if (resend) {
|
|
39
|
-
providers.push(resend);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
if (options.smsProvider === "twilio") {
|
|
43
|
-
const twilio = createTwilioProviderFromEnv(env);
|
|
44
|
-
if (twilio) {
|
|
45
|
-
providers.push(twilio);
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
if (options.customProviders?.length) {
|
|
49
|
-
providers.push(...options.customProviders);
|
|
50
|
-
}
|
|
51
|
-
return providers;
|
|
52
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type { NotificationProvider } from "../types.js";
|
|
2
|
-
/**
|
|
3
|
-
* Minimal `fetch` shape the Resend provider depends on. Works with the
|
|
4
|
-
* global `fetch` in Node 18+ / workers / browsers, and can be stubbed in
|
|
5
|
-
* tests.
|
|
6
|
-
*/
|
|
7
|
-
export type ResendFetch = (input: string, init: {
|
|
8
|
-
method: string;
|
|
9
|
-
headers: Record<string, string>;
|
|
10
|
-
body: string;
|
|
11
|
-
}) => Promise<{
|
|
12
|
-
ok: boolean;
|
|
13
|
-
status: number;
|
|
14
|
-
json: () => Promise<unknown>;
|
|
15
|
-
text: () => Promise<string>;
|
|
16
|
-
}>;
|
|
17
|
-
/**
|
|
18
|
-
* Rendered email template. At least one of `html` or `text` should be set.
|
|
19
|
-
*/
|
|
20
|
-
export interface ResendRenderedEmail {
|
|
21
|
-
subject: string;
|
|
22
|
-
html?: string;
|
|
23
|
-
text?: string;
|
|
24
|
-
}
|
|
25
|
-
/**
|
|
26
|
-
* Options for {@link createResendProvider}.
|
|
27
|
-
*/
|
|
28
|
-
export interface ResendProviderOptions {
|
|
29
|
-
/** Resend API key. */
|
|
30
|
-
apiKey: string;
|
|
31
|
-
/** Default sender address. Payload `from` overrides. */
|
|
32
|
-
from: string;
|
|
33
|
-
/** Override the Resend API base URL. Defaults to `https://api.resend.com`. */
|
|
34
|
-
baseUrl?: string;
|
|
35
|
-
/** Override `fetch` (e.g. in tests). Defaults to global `fetch`. */
|
|
36
|
-
fetch?: ResendFetch;
|
|
37
|
-
/**
|
|
38
|
-
* Render a template id + data tuple into an email body. When omitted,
|
|
39
|
-
* the payload's `template` is used as the subject and `data` is
|
|
40
|
-
* JSON-stringified into the text body.
|
|
41
|
-
*/
|
|
42
|
-
renderTemplate?: (template: string, data: unknown) => Promise<ResendRenderedEmail> | ResendRenderedEmail;
|
|
43
|
-
}
|
|
44
|
-
/**
|
|
45
|
-
* Create a notification provider that delivers email through the Resend HTTP
|
|
46
|
-
* API (https://resend.com/docs/api-reference/emails/send-email).
|
|
47
|
-
*
|
|
48
|
-
* Only the `"email"` channel is supported; attempting to send to any other
|
|
49
|
-
* channel throws.
|
|
50
|
-
*/
|
|
51
|
-
export declare function createResendProvider(options: ResendProviderOptions): NotificationProvider;
|
|
52
|
-
//# sourceMappingURL=resend.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resend.d.ts","sourceRoot":"","sources":["../../src/providers/resend.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAA;AAE3E;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;CACb,KACE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5B,CAAC,CAAA;AAEF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAA;IACf,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAA;IACZ,8EAA8E;IAC9E,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,oEAAoE;IACpE,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,KACV,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAAA;CACxD;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CAqDzF"}
|
package/dist/providers/resend.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Create a notification provider that delivers email through the Resend HTTP
|
|
3
|
-
* API (https://resend.com/docs/api-reference/emails/send-email).
|
|
4
|
-
*
|
|
5
|
-
* Only the `"email"` channel is supported; attempting to send to any other
|
|
6
|
-
* channel throws.
|
|
7
|
-
*/
|
|
8
|
-
export function createResendProvider(options) {
|
|
9
|
-
const baseUrl = options.baseUrl ?? "https://api.resend.com";
|
|
10
|
-
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
11
|
-
return {
|
|
12
|
-
name: "resend",
|
|
13
|
-
channels: ["email"],
|
|
14
|
-
async send(payload) {
|
|
15
|
-
if (payload.channel !== "email") {
|
|
16
|
-
throw new Error(`Resend provider only supports the "email" channel, got "${payload.channel}"`);
|
|
17
|
-
}
|
|
18
|
-
if (!fetchImpl) {
|
|
19
|
-
throw new Error("Resend provider requires a fetch implementation");
|
|
20
|
-
}
|
|
21
|
-
const rendered = options.renderTemplate
|
|
22
|
-
? await options.renderTemplate(payload.template, payload.data)
|
|
23
|
-
: {
|
|
24
|
-
subject: payload.subject ?? payload.template,
|
|
25
|
-
text: JSON.stringify(payload.data ?? {}),
|
|
26
|
-
};
|
|
27
|
-
const body = {
|
|
28
|
-
from: payload.from ?? options.from,
|
|
29
|
-
to: payload.to,
|
|
30
|
-
subject: payload.subject ?? rendered.subject,
|
|
31
|
-
html: payload.html ?? rendered.html,
|
|
32
|
-
text: payload.text ?? rendered.text,
|
|
33
|
-
attachments: payload.attachments?.map((attachment) => ({
|
|
34
|
-
filename: attachment.filename,
|
|
35
|
-
content: attachment.contentBase64,
|
|
36
|
-
path: attachment.path,
|
|
37
|
-
content_type: attachment.contentType,
|
|
38
|
-
disposition: attachment.disposition,
|
|
39
|
-
content_id: attachment.contentId,
|
|
40
|
-
})),
|
|
41
|
-
};
|
|
42
|
-
const response = await fetchImpl(`${baseUrl}/emails`, {
|
|
43
|
-
method: "POST",
|
|
44
|
-
headers: {
|
|
45
|
-
Authorization: `Bearer ${options.apiKey}`,
|
|
46
|
-
"Content-Type": "application/json",
|
|
47
|
-
},
|
|
48
|
-
body: JSON.stringify(body),
|
|
49
|
-
});
|
|
50
|
-
if (!response.ok) {
|
|
51
|
-
const text = await response.text().catch(() => "");
|
|
52
|
-
throw new Error(`Resend send failed (${response.status}): ${text}`);
|
|
53
|
-
}
|
|
54
|
-
const data = (await response.json());
|
|
55
|
-
return { id: data.id, provider: "resend" };
|
|
56
|
-
},
|
|
57
|
-
};
|
|
58
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import type { NotificationProvider } from "../types.js";
|
|
2
|
-
export type TwilioFetch = (input: string, init: {
|
|
3
|
-
method: string;
|
|
4
|
-
headers: Record<string, string>;
|
|
5
|
-
body: string;
|
|
6
|
-
}) => Promise<{
|
|
7
|
-
ok: boolean;
|
|
8
|
-
status: number;
|
|
9
|
-
json: () => Promise<unknown>;
|
|
10
|
-
text: () => Promise<string>;
|
|
11
|
-
}>;
|
|
12
|
-
export interface TwilioRenderedSms {
|
|
13
|
-
text: string;
|
|
14
|
-
}
|
|
15
|
-
export interface TwilioProviderOptions {
|
|
16
|
-
accountSid: string;
|
|
17
|
-
authToken: string;
|
|
18
|
-
from: string;
|
|
19
|
-
baseUrl?: string;
|
|
20
|
-
fetch?: TwilioFetch;
|
|
21
|
-
renderTemplate?: (template: string, data: unknown) => Promise<TwilioRenderedSms> | TwilioRenderedSms;
|
|
22
|
-
}
|
|
23
|
-
export declare function createTwilioProvider(options: TwilioProviderOptions): NotificationProvider;
|
|
24
|
-
//# sourceMappingURL=twilio.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"twilio.d.ts","sourceRoot":"","sources":["../../src/providers/twilio.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAsB,MAAM,aAAa,CAAA;AAE3E,MAAM,MAAM,WAAW,GAAG,CACxB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE;IACJ,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC/B,IAAI,EAAE,MAAM,CAAA;CACb,KACE,OAAO,CAAC;IACX,EAAE,EAAE,OAAO,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;IAC5B,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;CAC5B,CAAC,CAAA;AAEF,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;CACb;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,WAAW,CAAA;IACnB,cAAc,CAAC,EAAE,CACf,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,OAAO,KACV,OAAO,CAAC,iBAAiB,CAAC,GAAG,iBAAiB,CAAA;CACpD;AA0BD,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,oBAAoB,CA4CzF"}
|
package/dist/providers/twilio.js
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
function toBase64(value) {
|
|
2
|
-
if (typeof btoa === "function") {
|
|
3
|
-
return btoa(value);
|
|
4
|
-
}
|
|
5
|
-
const globals = globalThis;
|
|
6
|
-
if (globals.Buffer) {
|
|
7
|
-
return globals.Buffer.from(value).toString("base64");
|
|
8
|
-
}
|
|
9
|
-
throw new Error("Twilio provider requires a base64 encoder");
|
|
10
|
-
}
|
|
11
|
-
export function createTwilioProvider(options) {
|
|
12
|
-
const baseUrl = options.baseUrl ?? "https://api.twilio.com/2010-04-01";
|
|
13
|
-
const fetchImpl = options.fetch ?? globalThis.fetch;
|
|
14
|
-
return {
|
|
15
|
-
name: "twilio",
|
|
16
|
-
channels: ["sms"],
|
|
17
|
-
async send(payload) {
|
|
18
|
-
if (payload.channel !== "sms") {
|
|
19
|
-
throw new Error(`Twilio provider only supports the "sms" channel, got "${payload.channel}"`);
|
|
20
|
-
}
|
|
21
|
-
if (!fetchImpl) {
|
|
22
|
-
throw new Error("Twilio provider requires a fetch implementation");
|
|
23
|
-
}
|
|
24
|
-
const rendered = options.renderTemplate
|
|
25
|
-
? await options.renderTemplate(payload.template, payload.data)
|
|
26
|
-
: { text: payload.text ?? JSON.stringify(payload.data ?? {}) };
|
|
27
|
-
const body = new URLSearchParams({
|
|
28
|
-
To: payload.to,
|
|
29
|
-
From: payload.from ?? options.from,
|
|
30
|
-
Body: payload.text ?? rendered.text,
|
|
31
|
-
});
|
|
32
|
-
const response = await fetchImpl(`${baseUrl}/Accounts/${options.accountSid}/Messages.json`, {
|
|
33
|
-
method: "POST",
|
|
34
|
-
headers: {
|
|
35
|
-
Authorization: `Basic ${toBase64(`${options.accountSid}:${options.authToken}`)}`,
|
|
36
|
-
"Content-Type": "application/x-www-form-urlencoded;charset=UTF-8",
|
|
37
|
-
},
|
|
38
|
-
body: body.toString(),
|
|
39
|
-
});
|
|
40
|
-
if (!response.ok) {
|
|
41
|
-
const text = await response.text().catch(() => "");
|
|
42
|
-
throw new Error(`Twilio send failed (${response.status}): ${text}`);
|
|
43
|
-
}
|
|
44
|
-
const data = (await response.json());
|
|
45
|
-
return { id: data.sid, provider: "twilio" };
|
|
46
|
-
},
|
|
47
|
-
};
|
|
48
|
-
}
|