@christian-ek/sweego 0.1.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 +357 -0
- package/dist/client/_generated/_ignore.d.ts +1 -0
- package/dist/client/_generated/_ignore.d.ts.map +1 -0
- package/dist/client/_generated/_ignore.js +3 -0
- package/dist/client/_generated/_ignore.js.map +1 -0
- package/dist/client/index.d.ts +282 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +265 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/webhook.d.ts +42 -0
- package/dist/client/webhook.d.ts.map +1 -0
- package/dist/client/webhook.js +89 -0
- package/dist/client/webhook.js.map +1 -0
- package/dist/component/_generated/api.d.ts +43 -0
- package/dist/component/_generated/api.d.ts.map +1 -0
- package/dist/component/_generated/api.js +31 -0
- package/dist/component/_generated/api.js.map +1 -0
- package/dist/component/_generated/component.d.ts +226 -0
- package/dist/component/_generated/component.d.ts.map +1 -0
- package/dist/component/_generated/component.js +11 -0
- package/dist/component/_generated/component.js.map +1 -0
- package/dist/component/_generated/dataModel.d.ts +46 -0
- package/dist/component/_generated/dataModel.d.ts.map +1 -0
- package/dist/component/_generated/dataModel.js +11 -0
- package/dist/component/_generated/dataModel.js.map +1 -0
- package/dist/component/_generated/server.d.ts +121 -0
- package/dist/component/_generated/server.d.ts.map +1 -0
- package/dist/component/_generated/server.js +78 -0
- package/dist/component/_generated/server.js.map +1 -0
- package/dist/component/convex.config.d.ts +3 -0
- package/dist/component/convex.config.d.ts.map +1 -0
- package/dist/component/convex.config.js +10 -0
- package/dist/component/convex.config.js.map +1 -0
- package/dist/component/lib.d.ts +319 -0
- package/dist/component/lib.d.ts.map +1 -0
- package/dist/component/lib.js +725 -0
- package/dist/component/lib.js.map +1 -0
- package/dist/component/schema.d.ts +259 -0
- package/dist/component/schema.d.ts.map +1 -0
- package/dist/component/schema.js +99 -0
- package/dist/component/schema.js.map +1 -0
- package/dist/component/shared.d.ts +280 -0
- package/dist/component/shared.d.ts.map +1 -0
- package/dist/component/shared.js +213 -0
- package/dist/component/shared.js.map +1 -0
- package/dist/component/sweego.d.ts +95 -0
- package/dist/component/sweego.d.ts.map +1 -0
- package/dist/component/sweego.js +210 -0
- package/dist/component/sweego.js.map +1 -0
- package/dist/component/utils.d.ts +16 -0
- package/dist/component/utils.d.ts.map +1 -0
- package/dist/component/utils.js +29 -0
- package/dist/component/utils.js.map +1 -0
- package/package.json +100 -0
- package/src/client/_generated/_ignore.ts +1 -0
- package/src/client/index.ts +490 -0
- package/src/client/webhook.test.ts +146 -0
- package/src/client/webhook.ts +130 -0
- package/src/component/_generated/api.ts +59 -0
- package/src/component/_generated/component.ts +244 -0
- package/src/component/_generated/dataModel.ts +60 -0
- package/src/component/_generated/server.ts +156 -0
- package/src/component/convex.config.ts +12 -0
- package/src/component/lib.test.ts +189 -0
- package/src/component/lib.ts +835 -0
- package/src/component/schema.ts +117 -0
- package/src/component/shared.test.ts +64 -0
- package/src/component/shared.ts +315 -0
- package/src/component/sweego.test.ts +141 -0
- package/src/component/sweego.ts +310 -0
- package/src/component/utils.ts +35 -0
- package/src/test.ts +20 -0
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
import { createFunctionHandle, internalMutationGeneric, } from "convex/server";
|
|
2
|
+
import { v } from "convex/values";
|
|
3
|
+
import { DEFAULT_PROVIDER, parseEmailAddress, parseEmailAddresses, vSweegoEvent, } from "../component/shared.js";
|
|
4
|
+
import { readWebhookHeaders, verifySweegoSignature } from "./webhook.js";
|
|
5
|
+
export const vMessageId = v.string();
|
|
6
|
+
export { vSweegoEvent } from "../component/shared.js";
|
|
7
|
+
// Argument validators for an `onEvent` handler defined in the host app, for use
|
|
8
|
+
// directly as a function's `args` — e.g. `internalMutation({ args: vOnEventArgs })`.
|
|
9
|
+
// `event` is validated loosely (the component is the only caller and always
|
|
10
|
+
// sends a valid {@link SweegoEvent}); use {@link Sweego.defineEventHandler} for a
|
|
11
|
+
// fully-typed `event`.
|
|
12
|
+
export const vOnEventArgs = {
|
|
13
|
+
messageId: vMessageId,
|
|
14
|
+
swgUid: v.string(),
|
|
15
|
+
event: v.any(),
|
|
16
|
+
};
|
|
17
|
+
/* -------------------------------------------------------------------------- */
|
|
18
|
+
/* Client */
|
|
19
|
+
/* -------------------------------------------------------------------------- */
|
|
20
|
+
export class Sweego {
|
|
21
|
+
component;
|
|
22
|
+
config;
|
|
23
|
+
_apiKey;
|
|
24
|
+
_webhookSecret;
|
|
25
|
+
onEvent;
|
|
26
|
+
/**
|
|
27
|
+
* @param component The mounted component, e.g. `components.sweego`.
|
|
28
|
+
* @param options {@link SweegoOptions}.
|
|
29
|
+
*/
|
|
30
|
+
constructor(component, options) {
|
|
31
|
+
this.component = component;
|
|
32
|
+
this._apiKey = options?.apiKey;
|
|
33
|
+
this._webhookSecret = options?.webhookSecret;
|
|
34
|
+
this.onEvent = options?.onEvent;
|
|
35
|
+
this.config = {
|
|
36
|
+
provider: options?.provider ?? DEFAULT_PROVIDER,
|
|
37
|
+
testMode: options?.testMode ?? false,
|
|
38
|
+
initialBackoffMs: options?.initialBackoffMs ?? 30000,
|
|
39
|
+
retryAttempts: options?.retryAttempts ?? 5,
|
|
40
|
+
webhookToleranceSeconds: options?.webhookToleranceSeconds ?? 300,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// Resolved at call time so the client can be constructed at module load.
|
|
44
|
+
get apiKey() {
|
|
45
|
+
const key = this._apiKey ?? process.env.SWEEGO_API_KEY;
|
|
46
|
+
if (!key) {
|
|
47
|
+
throw new Error("Sweego API key is not set. Pass `apiKey` or set SWEEGO_API_KEY.");
|
|
48
|
+
}
|
|
49
|
+
return key;
|
|
50
|
+
}
|
|
51
|
+
get webhookSecret() {
|
|
52
|
+
const secret = this._webhookSecret ?? process.env.SWEEGO_WEBHOOK_SECRET;
|
|
53
|
+
if (!secret) {
|
|
54
|
+
throw new Error("Sweego webhook secret is not set. Pass `webhookSecret` or set SWEEGO_WEBHOOK_SECRET.");
|
|
55
|
+
}
|
|
56
|
+
return secret;
|
|
57
|
+
}
|
|
58
|
+
async runtimeConfig() {
|
|
59
|
+
return {
|
|
60
|
+
apiKey: this.apiKey,
|
|
61
|
+
provider: this.config.provider,
|
|
62
|
+
initialBackoffMs: this.config.initialBackoffMs,
|
|
63
|
+
retryAttempts: this.config.retryAttempts,
|
|
64
|
+
testMode: this.config.testMode,
|
|
65
|
+
onEvent: this.onEvent
|
|
66
|
+
? { fnHandle: await createFunctionHandle(this.onEvent) }
|
|
67
|
+
: undefined,
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Enqueue an email. It is sent durably (with retries) by the component's
|
|
72
|
+
* workpool. Returns the {@link MessageId} you can use to check status,
|
|
73
|
+
* cancel, or correlate webhook events.
|
|
74
|
+
*/
|
|
75
|
+
async sendEmail(ctx, options) {
|
|
76
|
+
const message = {
|
|
77
|
+
channel: "email",
|
|
78
|
+
bulk: false,
|
|
79
|
+
from: parseEmailAddress(options.from),
|
|
80
|
+
emailRecipients: parseEmailAddresses(options.to).map((a) => ({
|
|
81
|
+
email: a.email,
|
|
82
|
+
name: a.name,
|
|
83
|
+
})),
|
|
84
|
+
cc: options.cc ? parseEmailAddresses(options.cc) : undefined,
|
|
85
|
+
bcc: options.bcc ? parseEmailAddresses(options.bcc) : undefined,
|
|
86
|
+
replyTo: options.replyTo ? parseEmailAddress(options.replyTo) : undefined,
|
|
87
|
+
subject: options.subject,
|
|
88
|
+
html: options.html,
|
|
89
|
+
text: options.text,
|
|
90
|
+
templateId: options.templateId,
|
|
91
|
+
variables: options.variables,
|
|
92
|
+
attachments: options.attachments,
|
|
93
|
+
headers: options.headers,
|
|
94
|
+
listUnsub: options.listUnsub,
|
|
95
|
+
expires: options.expires,
|
|
96
|
+
campaignId: options.campaignId,
|
|
97
|
+
campaignTags: options.campaignTags,
|
|
98
|
+
campaignType: options.campaignType,
|
|
99
|
+
compressStyle: options.compressStyle,
|
|
100
|
+
forceInlineStyle: options.forceInlineStyle,
|
|
101
|
+
dryRun: options.dryRun ?? (this.config.testMode ? true : undefined),
|
|
102
|
+
};
|
|
103
|
+
return this.enqueue(ctx, message);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Enqueue a personalized bulk email (Sweego's `/send/bulk/email`). Each
|
|
107
|
+
* recipient may carry its own `variables`. No cc/bcc/replyTo support.
|
|
108
|
+
*/
|
|
109
|
+
async sendBulkEmail(ctx, options) {
|
|
110
|
+
const message = {
|
|
111
|
+
channel: "email",
|
|
112
|
+
bulk: true,
|
|
113
|
+
from: parseEmailAddress(options.from),
|
|
114
|
+
emailRecipients: options.recipients.map((r) => typeof r === "string"
|
|
115
|
+
? { email: r }
|
|
116
|
+
: { email: r.email, name: r.name, variables: r.variables }),
|
|
117
|
+
subject: options.subject,
|
|
118
|
+
html: options.html,
|
|
119
|
+
text: options.text,
|
|
120
|
+
templateId: options.templateId,
|
|
121
|
+
attachments: options.attachments,
|
|
122
|
+
headers: options.headers,
|
|
123
|
+
listUnsub: options.listUnsub,
|
|
124
|
+
expires: options.expires,
|
|
125
|
+
campaignId: options.campaignId,
|
|
126
|
+
campaignTags: options.campaignTags,
|
|
127
|
+
campaignType: options.campaignType,
|
|
128
|
+
compressStyle: options.compressStyle,
|
|
129
|
+
forceInlineStyle: options.forceInlineStyle,
|
|
130
|
+
dryRun: options.dryRun ?? (this.config.testMode ? true : undefined),
|
|
131
|
+
};
|
|
132
|
+
return this.enqueue(ctx, message);
|
|
133
|
+
}
|
|
134
|
+
/** Enqueue an SMS (Sweego's `/send` with `channel: "sms"`). */
|
|
135
|
+
async sendSms(ctx, options) {
|
|
136
|
+
const message = {
|
|
137
|
+
channel: "sms",
|
|
138
|
+
bulk: false,
|
|
139
|
+
smsRecipients: normalizeSmsRecipients(options.to, options.region),
|
|
140
|
+
text: options.text,
|
|
141
|
+
templateId: options.templateId,
|
|
142
|
+
variables: options.variables,
|
|
143
|
+
campaignType: options.campaignType,
|
|
144
|
+
senderId: options.senderId,
|
|
145
|
+
shortenUrls: options.shortenUrls,
|
|
146
|
+
shortenWithProtocol: options.shortenWithProtocol,
|
|
147
|
+
bat: options.bat ?? (this.config.testMode ? true : undefined),
|
|
148
|
+
campaignId: options.campaignId,
|
|
149
|
+
};
|
|
150
|
+
return this.enqueue(ctx, message);
|
|
151
|
+
}
|
|
152
|
+
async enqueue(ctx, message) {
|
|
153
|
+
const options = await this.runtimeConfig();
|
|
154
|
+
const id = await ctx.runMutation(this.component.lib.enqueueMessage, {
|
|
155
|
+
options,
|
|
156
|
+
message,
|
|
157
|
+
});
|
|
158
|
+
return id;
|
|
159
|
+
}
|
|
160
|
+
/** Aggregate status of a message plus per-recipient delivery state. */
|
|
161
|
+
async status(ctx, messageId) {
|
|
162
|
+
return ctx.runQuery(this.component.lib.getStatus, { messageId });
|
|
163
|
+
}
|
|
164
|
+
/** The full stored message plus its deliveries. */
|
|
165
|
+
async get(ctx, messageId) {
|
|
166
|
+
return ctx.runQuery(this.component.lib.get, { messageId });
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Cancel a message if it has not yet been handed to Sweego. Returns true if
|
|
170
|
+
* it was cancelled, false if it had already been sent.
|
|
171
|
+
*/
|
|
172
|
+
async cancel(ctx, messageId) {
|
|
173
|
+
return ctx.runMutation(this.component.lib.cancel, { messageId });
|
|
174
|
+
}
|
|
175
|
+
/** Estimate the cost/segments of an SMS send (Sweego `/sms/estimate`). */
|
|
176
|
+
async estimateSms(ctx, body) {
|
|
177
|
+
return ctx.runAction(this.component.lib.estimateSms, {
|
|
178
|
+
apiKey: this.apiKey,
|
|
179
|
+
body,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Poll Sweego's logs to refresh delivery status without webhooks. Returns the
|
|
184
|
+
* number of deliveries updated. Prefer webhooks where possible.
|
|
185
|
+
*/
|
|
186
|
+
async refreshStatus(ctx, messageId) {
|
|
187
|
+
return ctx.runAction(this.component.lib.refreshStatus, {
|
|
188
|
+
apiKey: this.apiKey,
|
|
189
|
+
messageId,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Verify and handle a Sweego webhook. Mount this on an HTTP route. Verifies
|
|
194
|
+
* the HMAC signature against the raw body, then updates delivery state and
|
|
195
|
+
* dispatches your `onEvent` handler.
|
|
196
|
+
*/
|
|
197
|
+
async handleSweegoWebhook(ctx, request) {
|
|
198
|
+
const secret = this.webhookSecret;
|
|
199
|
+
const rawBody = await request.text();
|
|
200
|
+
const { id, timestamp, signature } = readWebhookHeaders(request.headers);
|
|
201
|
+
const valid = await verifySweegoSignature({
|
|
202
|
+
secret,
|
|
203
|
+
id: id ?? "",
|
|
204
|
+
timestamp: timestamp ?? "",
|
|
205
|
+
body: rawBody,
|
|
206
|
+
signatureHeader: signature ?? "",
|
|
207
|
+
toleranceSeconds: this.config.webhookToleranceSeconds,
|
|
208
|
+
});
|
|
209
|
+
if (!valid) {
|
|
210
|
+
return new Response("Invalid webhook signature", { status: 401 });
|
|
211
|
+
}
|
|
212
|
+
let event;
|
|
213
|
+
try {
|
|
214
|
+
event = JSON.parse(rawBody);
|
|
215
|
+
}
|
|
216
|
+
catch {
|
|
217
|
+
// Acknowledge so Sweego doesn't retry an unparseable body forever.
|
|
218
|
+
return new Response("Invalid JSON body", { status: 200 });
|
|
219
|
+
}
|
|
220
|
+
// Pass the webhook-id so the component can deduplicate redeliveries/replays.
|
|
221
|
+
await ctx.runMutation(this.component.lib.handleEvent, {
|
|
222
|
+
event,
|
|
223
|
+
webhookId: id ?? undefined,
|
|
224
|
+
});
|
|
225
|
+
return new Response(null, { status: 200 });
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Helper to define your `onEvent` mutation with the right argument validator.
|
|
229
|
+
* Equivalent to declaring an `internalMutation` with {@link vOnEventArgs}.
|
|
230
|
+
*/
|
|
231
|
+
defineEventHandler(handler) {
|
|
232
|
+
return internalMutationGeneric({
|
|
233
|
+
args: {
|
|
234
|
+
messageId: vMessageId,
|
|
235
|
+
swgUid: v.string(),
|
|
236
|
+
event: vSweegoEvent,
|
|
237
|
+
},
|
|
238
|
+
handler,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
/* -------------------------------------------------------------------------- */
|
|
243
|
+
/* Helpers */
|
|
244
|
+
/* -------------------------------------------------------------------------- */
|
|
245
|
+
function normalizeRegion(region) {
|
|
246
|
+
const up = region.trim().toUpperCase();
|
|
247
|
+
// Sweego requires uppercase ISO-3166 alpha-2 codes (or the literal "OTHER").
|
|
248
|
+
if (up !== "OTHER" && !/^[A-Z]{2}$/.test(up)) {
|
|
249
|
+
throw new Error(`Invalid SMS region '${region}'. Expected an uppercase ISO-3166 alpha-2 code (e.g. 'FR') or 'OTHER'.`);
|
|
250
|
+
}
|
|
251
|
+
return up;
|
|
252
|
+
}
|
|
253
|
+
function normalizeSmsRecipients(to, defaultRegion) {
|
|
254
|
+
const list = Array.isArray(to) ? to : [to];
|
|
255
|
+
return list.map((r) => {
|
|
256
|
+
if (typeof r === "string") {
|
|
257
|
+
if (!defaultRegion) {
|
|
258
|
+
throw new Error("SMS recipients given as strings require a `region` option (e.g. region: 'FR').");
|
|
259
|
+
}
|
|
260
|
+
return { num: r, region: normalizeRegion(defaultRegion) };
|
|
261
|
+
}
|
|
262
|
+
return { num: r.num, region: normalizeRegion(r.region) };
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/client/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification of Sweego webhook signatures.
|
|
3
|
+
*
|
|
4
|
+
* Sweego signs webhooks with HMAC-SHA256 in a Standard-Webhooks / svix-*style*
|
|
5
|
+
* scheme, but it is NOT drop-in svix-compatible:
|
|
6
|
+
* - headers: `webhook-id`, `webhook-timestamp` (Unix seconds), `webhook-signature`
|
|
7
|
+
* - signed string: `{id}.{timestamp}.{rawBody}` over the RAW, unparsed body
|
|
8
|
+
* - the HMAC key is the secret AFTER base64-decoding it
|
|
9
|
+
* - the `webhook-signature` value is a bare base64 digest (no `v1,` prefix,
|
|
10
|
+
* no space-delimited list), though we tolerate those defensively.
|
|
11
|
+
*
|
|
12
|
+
* Implemented with Web Crypto (`crypto.subtle`) so it runs in Convex's V8
|
|
13
|
+
* runtime without any Node-only dependency.
|
|
14
|
+
*/
|
|
15
|
+
/** Constant-time string comparison to avoid timing side channels. */
|
|
16
|
+
export declare function timingSafeEqual(a: string, b: string): boolean;
|
|
17
|
+
export interface WebhookHeaders {
|
|
18
|
+
id: string | null;
|
|
19
|
+
timestamp: string | null;
|
|
20
|
+
signature: string | null;
|
|
21
|
+
}
|
|
22
|
+
/** Read Sweego's signature headers (case-insensitive via the Headers API). */
|
|
23
|
+
export declare function readWebhookHeaders(headers: Headers): WebhookHeaders;
|
|
24
|
+
export interface VerifyOptions {
|
|
25
|
+
/** The webhook signing secret (as shown in the Sweego dashboard). */
|
|
26
|
+
secret: string;
|
|
27
|
+
/** `webhook-id` header. */
|
|
28
|
+
id: string;
|
|
29
|
+
/** `webhook-timestamp` header (Unix seconds). */
|
|
30
|
+
timestamp: string;
|
|
31
|
+
/** The RAW request body, exactly as received. */
|
|
32
|
+
body: string;
|
|
33
|
+
/** `webhook-signature` header value. */
|
|
34
|
+
signatureHeader: string;
|
|
35
|
+
/** If > 0, reject when |now - timestamp| exceeds this many seconds. */
|
|
36
|
+
toleranceSeconds?: number;
|
|
37
|
+
/** Override "now" (Unix seconds) — for testing. */
|
|
38
|
+
now?: number;
|
|
39
|
+
}
|
|
40
|
+
/** Returns true iff the signature is valid for the given raw body + headers. */
|
|
41
|
+
export declare function verifySweegoSignature(options: VerifyOptions): Promise<boolean>;
|
|
42
|
+
//# sourceMappingURL=webhook.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/client/webhook.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAgBH,qEAAqE;AACrE,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAO7D;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,GAAG,IAAI,CAAC;IAClB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,8EAA8E;AAC9E,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,OAAO,GAAG,cAAc,CAMnE;AAED,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,MAAM,EAAE,MAAM,CAAC;IACf,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,iDAAiD;IACjD,SAAS,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,IAAI,EAAE,MAAM,CAAC;IACb,wCAAwC;IACxC,eAAe,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,mDAAmD;IACnD,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,gFAAgF;AAChF,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,OAAO,CAAC,CAuDlB"}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verification of Sweego webhook signatures.
|
|
3
|
+
*
|
|
4
|
+
* Sweego signs webhooks with HMAC-SHA256 in a Standard-Webhooks / svix-*style*
|
|
5
|
+
* scheme, but it is NOT drop-in svix-compatible:
|
|
6
|
+
* - headers: `webhook-id`, `webhook-timestamp` (Unix seconds), `webhook-signature`
|
|
7
|
+
* - signed string: `{id}.{timestamp}.{rawBody}` over the RAW, unparsed body
|
|
8
|
+
* - the HMAC key is the secret AFTER base64-decoding it
|
|
9
|
+
* - the `webhook-signature` value is a bare base64 digest (no `v1,` prefix,
|
|
10
|
+
* no space-delimited list), though we tolerate those defensively.
|
|
11
|
+
*
|
|
12
|
+
* Implemented with Web Crypto (`crypto.subtle`) so it runs in Convex's V8
|
|
13
|
+
* runtime without any Node-only dependency.
|
|
14
|
+
*/
|
|
15
|
+
function base64ToBytes(b64) {
|
|
16
|
+
const binary = atob(b64);
|
|
17
|
+
const bytes = new Uint8Array(binary.length);
|
|
18
|
+
for (let i = 0; i < binary.length; i++)
|
|
19
|
+
bytes[i] = binary.charCodeAt(i);
|
|
20
|
+
return bytes;
|
|
21
|
+
}
|
|
22
|
+
function bytesToBase64(buffer) {
|
|
23
|
+
const arr = new Uint8Array(buffer);
|
|
24
|
+
let binary = "";
|
|
25
|
+
for (let i = 0; i < arr.length; i++)
|
|
26
|
+
binary += String.fromCharCode(arr[i]);
|
|
27
|
+
return btoa(binary);
|
|
28
|
+
}
|
|
29
|
+
/** Constant-time string comparison to avoid timing side channels. */
|
|
30
|
+
export function timingSafeEqual(a, b) {
|
|
31
|
+
if (a.length !== b.length)
|
|
32
|
+
return false;
|
|
33
|
+
let mismatch = 0;
|
|
34
|
+
for (let i = 0; i < a.length; i++) {
|
|
35
|
+
mismatch |= a.charCodeAt(i) ^ b.charCodeAt(i);
|
|
36
|
+
}
|
|
37
|
+
return mismatch === 0;
|
|
38
|
+
}
|
|
39
|
+
/** Read Sweego's signature headers (case-insensitive via the Headers API). */
|
|
40
|
+
export function readWebhookHeaders(headers) {
|
|
41
|
+
return {
|
|
42
|
+
id: headers.get("webhook-id"),
|
|
43
|
+
timestamp: headers.get("webhook-timestamp"),
|
|
44
|
+
signature: headers.get("webhook-signature"),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/** Returns true iff the signature is valid for the given raw body + headers. */
|
|
48
|
+
export async function verifySweegoSignature(options) {
|
|
49
|
+
const { id, timestamp, body, signatureHeader } = options;
|
|
50
|
+
if (!id || !timestamp || !signatureHeader)
|
|
51
|
+
return false;
|
|
52
|
+
if (options.toleranceSeconds && options.toleranceSeconds > 0) {
|
|
53
|
+
const ts = Number(timestamp);
|
|
54
|
+
const now = options.now ?? Math.floor(Date.now() / 1000);
|
|
55
|
+
if (!Number.isFinite(ts) || Math.abs(now - ts) > options.toleranceSeconds) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// The secret is delivered base64-encoded; decode to the raw HMAC key bytes.
|
|
60
|
+
// Tolerate a leading "whsec_" and fall back to UTF-8 bytes if not base64.
|
|
61
|
+
const rawSecret = options.secret.startsWith("whsec_")
|
|
62
|
+
? options.secret.slice("whsec_".length)
|
|
63
|
+
: options.secret;
|
|
64
|
+
let keyBytes;
|
|
65
|
+
try {
|
|
66
|
+
keyBytes = base64ToBytes(rawSecret);
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
console.warn("[sweego] Webhook secret is not valid base64; check SWEEGO_WEBHOOK_SECRET. Falling back to raw UTF-8 bytes.");
|
|
70
|
+
keyBytes = new TextEncoder().encode(rawSecret);
|
|
71
|
+
}
|
|
72
|
+
if (keyBytes.length === 0) {
|
|
73
|
+
console.warn("[sweego] Webhook secret is empty; rejecting webhook.");
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
const cryptoKey = await crypto.subtle.importKey("raw", keyBytes, { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
|
|
77
|
+
const signedContent = `${id}.${timestamp}.${body}`;
|
|
78
|
+
const mac = await crypto.subtle.sign("HMAC", cryptoKey, new TextEncoder().encode(signedContent));
|
|
79
|
+
const expected = bytesToBase64(mac);
|
|
80
|
+
// The header may be a single bare base64 digest, or (svix-style) a
|
|
81
|
+
// space-delimited list of `version,signature` pairs. Accept any match.
|
|
82
|
+
const candidates = signatureHeader
|
|
83
|
+
.split(" ")
|
|
84
|
+
.map((part) => part.trim())
|
|
85
|
+
.filter(Boolean)
|
|
86
|
+
.map((part) => (part.includes(",") ? part.slice(part.indexOf(",") + 1) : part));
|
|
87
|
+
return candidates.some((candidate) => timingSafeEqual(candidate, expected));
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=webhook.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/client/webhook.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generated `api` utility.
|
|
3
|
+
*
|
|
4
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
5
|
+
*
|
|
6
|
+
* To regenerate, run `npx convex dev`.
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type * as lib from "../lib.js";
|
|
10
|
+
import type * as shared from "../shared.js";
|
|
11
|
+
import type * as sweego from "../sweego.js";
|
|
12
|
+
import type * as utils from "../utils.js";
|
|
13
|
+
import type { ApiFromModules, FilterApi, FunctionReference } from "convex/server";
|
|
14
|
+
declare const fullApi: ApiFromModules<{
|
|
15
|
+
lib: typeof lib;
|
|
16
|
+
shared: typeof shared;
|
|
17
|
+
sweego: typeof sweego;
|
|
18
|
+
utils: typeof utils;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
22
|
+
*
|
|
23
|
+
* Usage:
|
|
24
|
+
* ```js
|
|
25
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare const api: FilterApi<typeof fullApi, FunctionReference<any, "public">>;
|
|
29
|
+
/**
|
|
30
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
31
|
+
*
|
|
32
|
+
* Usage:
|
|
33
|
+
* ```js
|
|
34
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
export declare const internal: FilterApi<typeof fullApi, FunctionReference<any, "internal">>;
|
|
38
|
+
export declare const components: {
|
|
39
|
+
sendWorkpool: import("@convex-dev/workpool/_generated/component.js").ComponentApi<"sendWorkpool">;
|
|
40
|
+
callbackWorkpool: import("@convex-dev/workpool/_generated/component.js").ComponentApi<"callbackWorkpool">;
|
|
41
|
+
};
|
|
42
|
+
export {};
|
|
43
|
+
//# sourceMappingURL=api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AACA;;;;;;;GAOG;AAEH,OAAO,KAAK,KAAK,GAAG,MAAM,WAAW,CAAC;AACtC,OAAO,KAAK,KAAK,MAAM,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,KAAK,MAAM,MAAM,cAAc,CAAC;AAC5C,OAAO,KAAK,KAAK,KAAK,MAAM,aAAa,CAAC;AAE1C,OAAO,KAAK,EACV,cAAc,EACd,SAAS,EACT,iBAAiB,EAClB,MAAM,eAAe,CAAC;AAGvB,QAAA,MAAM,OAAO,EAAE,cAAc,CAAC;IAC5B,GAAG,EAAE,OAAO,GAAG,CAAC;IAChB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,MAAM,EAAE,OAAO,MAAM,CAAC;IACtB,KAAK,EAAE,OAAO,KAAK,CAAC;CACrB,CAAiB,CAAC;AAEnB;;;;;;;GAOG;AACH,eAAO,MAAM,GAAG,EAAE,SAAS,CACzB,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,CACjB,CAAC;AAElB;;;;;;;GAOG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,CAC9B,OAAO,OAAO,EACd,iBAAiB,CAAC,GAAG,EAAE,UAAU,CAAC,CACnB,CAAC;AAElB,eAAO,MAAM,UAAU,EAAqC;IAC1D,YAAY,EAAE,OAAO,8CAA8C,EAAE,YAAY,CAAC,cAAc,CAAC,CAAC;IAClG,gBAAgB,EAAE,OAAO,8CAA8C,EAAE,YAAY,CAAC,kBAAkB,CAAC,CAAC;CAC3G,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
/**
|
|
3
|
+
* Generated `api` utility.
|
|
4
|
+
*
|
|
5
|
+
* THIS CODE IS AUTOMATICALLY GENERATED.
|
|
6
|
+
*
|
|
7
|
+
* To regenerate, run `npx convex dev`.
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
import { anyApi, componentsGeneric } from "convex/server";
|
|
11
|
+
const fullApi = anyApi;
|
|
12
|
+
/**
|
|
13
|
+
* A utility for referencing Convex functions in your app's public API.
|
|
14
|
+
*
|
|
15
|
+
* Usage:
|
|
16
|
+
* ```js
|
|
17
|
+
* const myFunctionReference = api.myModule.myFunction;
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export const api = anyApi;
|
|
21
|
+
/**
|
|
22
|
+
* A utility for referencing Convex functions in your app's internal API.
|
|
23
|
+
*
|
|
24
|
+
* Usage:
|
|
25
|
+
* ```js
|
|
26
|
+
* const myFunctionReference = internal.myModule.myFunction;
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export const internal = anyApi;
|
|
30
|
+
export const components = componentsGeneric();
|
|
31
|
+
//# sourceMappingURL=api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/component/_generated/api.ts"],"names":[],"mappings":"AAAA,oBAAoB;AACpB;;;;;;;GAOG;AAYH,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,OAAO,GAKR,MAAa,CAAC;AAEnB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,GAAG,GAGZ,MAAa,CAAC;AAElB;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,QAAQ,GAGjB,MAAa,CAAC;AAElB,MAAM,CAAC,MAAM,UAAU,GAAG,iBAAiB,EAG1C,CAAC"}
|