@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.
Files changed (72) hide show
  1. package/README.md +357 -0
  2. package/dist/client/_generated/_ignore.d.ts +1 -0
  3. package/dist/client/_generated/_ignore.d.ts.map +1 -0
  4. package/dist/client/_generated/_ignore.js +3 -0
  5. package/dist/client/_generated/_ignore.js.map +1 -0
  6. package/dist/client/index.d.ts +282 -0
  7. package/dist/client/index.d.ts.map +1 -0
  8. package/dist/client/index.js +265 -0
  9. package/dist/client/index.js.map +1 -0
  10. package/dist/client/webhook.d.ts +42 -0
  11. package/dist/client/webhook.d.ts.map +1 -0
  12. package/dist/client/webhook.js +89 -0
  13. package/dist/client/webhook.js.map +1 -0
  14. package/dist/component/_generated/api.d.ts +43 -0
  15. package/dist/component/_generated/api.d.ts.map +1 -0
  16. package/dist/component/_generated/api.js +31 -0
  17. package/dist/component/_generated/api.js.map +1 -0
  18. package/dist/component/_generated/component.d.ts +226 -0
  19. package/dist/component/_generated/component.d.ts.map +1 -0
  20. package/dist/component/_generated/component.js +11 -0
  21. package/dist/component/_generated/component.js.map +1 -0
  22. package/dist/component/_generated/dataModel.d.ts +46 -0
  23. package/dist/component/_generated/dataModel.d.ts.map +1 -0
  24. package/dist/component/_generated/dataModel.js +11 -0
  25. package/dist/component/_generated/dataModel.js.map +1 -0
  26. package/dist/component/_generated/server.d.ts +121 -0
  27. package/dist/component/_generated/server.d.ts.map +1 -0
  28. package/dist/component/_generated/server.js +78 -0
  29. package/dist/component/_generated/server.js.map +1 -0
  30. package/dist/component/convex.config.d.ts +3 -0
  31. package/dist/component/convex.config.d.ts.map +1 -0
  32. package/dist/component/convex.config.js +10 -0
  33. package/dist/component/convex.config.js.map +1 -0
  34. package/dist/component/lib.d.ts +319 -0
  35. package/dist/component/lib.d.ts.map +1 -0
  36. package/dist/component/lib.js +725 -0
  37. package/dist/component/lib.js.map +1 -0
  38. package/dist/component/schema.d.ts +259 -0
  39. package/dist/component/schema.d.ts.map +1 -0
  40. package/dist/component/schema.js +99 -0
  41. package/dist/component/schema.js.map +1 -0
  42. package/dist/component/shared.d.ts +280 -0
  43. package/dist/component/shared.d.ts.map +1 -0
  44. package/dist/component/shared.js +213 -0
  45. package/dist/component/shared.js.map +1 -0
  46. package/dist/component/sweego.d.ts +95 -0
  47. package/dist/component/sweego.d.ts.map +1 -0
  48. package/dist/component/sweego.js +210 -0
  49. package/dist/component/sweego.js.map +1 -0
  50. package/dist/component/utils.d.ts +16 -0
  51. package/dist/component/utils.d.ts.map +1 -0
  52. package/dist/component/utils.js +29 -0
  53. package/dist/component/utils.js.map +1 -0
  54. package/package.json +100 -0
  55. package/src/client/_generated/_ignore.ts +1 -0
  56. package/src/client/index.ts +490 -0
  57. package/src/client/webhook.test.ts +146 -0
  58. package/src/client/webhook.ts +130 -0
  59. package/src/component/_generated/api.ts +59 -0
  60. package/src/component/_generated/component.ts +244 -0
  61. package/src/component/_generated/dataModel.ts +60 -0
  62. package/src/component/_generated/server.ts +156 -0
  63. package/src/component/convex.config.ts +12 -0
  64. package/src/component/lib.test.ts +189 -0
  65. package/src/component/lib.ts +835 -0
  66. package/src/component/schema.ts +117 -0
  67. package/src/component/shared.test.ts +64 -0
  68. package/src/component/shared.ts +315 -0
  69. package/src/component/sweego.test.ts +141 -0
  70. package/src/component/sweego.ts +310 -0
  71. package/src/component/utils.ts +35 -0
  72. package/src/test.ts +20 -0
@@ -0,0 +1,210 @@
1
+ import { DEFAULT_PROVIDER, SWEEGO_API_BASE_URL } from "./shared.js";
2
+ /* -------------------------------------------------------------------------- */
3
+ /* HTTP */
4
+ /* -------------------------------------------------------------------------- */
5
+ /**
6
+ * HTTP status codes from which retrying will never help. Everything else
7
+ * (429 rate limits, 409 conflicts, 5xx) is treated as transient and retried
8
+ * by the workpool. Derived from Sweego's documented status codes.
9
+ */
10
+ export const PERMANENT_ERROR_CODES = new Set([
11
+ 400, // malformed request
12
+ 401, // bad / missing API key
13
+ 403, // forbidden / restricted account
14
+ 404, // resource not found
15
+ 405, // method not allowed
16
+ 406, // not acceptable
17
+ 410, // route is gone
18
+ 413, // request too large
19
+ 418, // I'm a teapot
20
+ 422, // validation error (missing / wrong-type field)
21
+ 501, // route / channel not implemented
22
+ ]);
23
+ /** Low-level fetch against the Sweego API with the `Api-Key` auth header. */
24
+ export async function sweegoFetch(apiKey, path, init = {}) {
25
+ const { json, ...rest } = init;
26
+ const headers = new Headers(rest.headers ?? {});
27
+ headers.set("Api-Key", apiKey);
28
+ if (json !== undefined && !headers.has("Content-Type")) {
29
+ headers.set("Content-Type", "application/json");
30
+ }
31
+ return fetch(`${SWEEGO_API_BASE_URL}${path}`, {
32
+ ...rest,
33
+ headers,
34
+ body: json !== undefined ? JSON.stringify(json) : rest.body,
35
+ });
36
+ }
37
+ /** Turn a non-OK Sweego response into a concise, non-leaky Error message. */
38
+ export function sanitizeSweegoError(status, errorText) {
39
+ if (status === 401 || status === 403) {
40
+ return "Sweego authentication failed. Check your SWEEGO_API_KEY.";
41
+ }
42
+ if (status === 422) {
43
+ return `Sweego rejected the request (422): ${truncate(errorText, 500)}`;
44
+ }
45
+ if (status === 404)
46
+ return "Sweego resource not found (404).";
47
+ if (status === 413)
48
+ return "Sweego request too large (413).";
49
+ if (status === 429)
50
+ return "Sweego rate limit exceeded (429).";
51
+ if (status >= 500)
52
+ return `Sweego service error (${status}).`;
53
+ return `Sweego API error (${status}): ${truncate(errorText, 300)}`;
54
+ }
55
+ function truncate(text, max) {
56
+ return text.length > max ? `${text.slice(0, max)}…` : text;
57
+ }
58
+ /** Drop keys whose value is `undefined`. */
59
+ function compact(obj) {
60
+ const out = {};
61
+ for (const [key, value] of Object.entries(obj)) {
62
+ if (value !== undefined)
63
+ out[key] = value;
64
+ }
65
+ return out;
66
+ }
67
+ function mapAttachments(message) {
68
+ if (!message.attachments?.length)
69
+ return undefined;
70
+ return message.attachments.map((a) => compact({
71
+ content: a.content,
72
+ filename: a.filename,
73
+ content_id: a.contentId,
74
+ disposition: a.disposition,
75
+ is_related: a.isRelated,
76
+ }));
77
+ }
78
+ /** Fields common to single and bulk email payloads. */
79
+ function commonEmailFields(message) {
80
+ return {
81
+ channel: "email",
82
+ provider: message.provider || DEFAULT_PROVIDER,
83
+ from: message.from,
84
+ subject: message.subject,
85
+ "message-html": message.html,
86
+ "message-txt": message.text,
87
+ "template-id": message.templateId,
88
+ attachments: mapAttachments(message),
89
+ headers: message.headers,
90
+ "list-unsub": message.listUnsub
91
+ ? compact({
92
+ method: message.listUnsub.method,
93
+ value: message.listUnsub.value,
94
+ })
95
+ : undefined,
96
+ expires: message.expires,
97
+ "campaign-id": message.campaignId,
98
+ "campaign-tags": message.campaignTags,
99
+ "campaign-type": message.campaignType,
100
+ compress_style: message.compressStyle,
101
+ force_inline_style: message.forceInlineStyle,
102
+ "dry-run": message.dryRun,
103
+ };
104
+ }
105
+ function buildEmailPayload(message) {
106
+ return compact({
107
+ ...commonEmailFields(message),
108
+ recipients: (message.emailRecipients ?? []).map((r) => compact({ email: r.email, name: r.name })),
109
+ cc: message.cc?.map((r) => compact({ email: r.email, name: r.name })),
110
+ bcc: message.bcc?.map((r) => compact({ email: r.email, name: r.name })),
111
+ "reply-to": message.replyTo
112
+ ? compact({ email: message.replyTo.email, name: message.replyTo.name })
113
+ : undefined,
114
+ // Sweego only honors root-level `variables` for a single recipient on /send.
115
+ variables: message.variables,
116
+ });
117
+ }
118
+ function buildBulkEmailPayload(message) {
119
+ return compact({
120
+ ...commonEmailFields(message),
121
+ // Bulk: per-recipient variables; no cc/bcc/reply-to.
122
+ recipients: (message.emailRecipients ?? []).map((r) => compact({ email: r.email, name: r.name, variables: r.variables })),
123
+ });
124
+ }
125
+ function buildSmsPayload(message) {
126
+ return compact({
127
+ channel: "sms",
128
+ provider: message.provider || DEFAULT_PROVIDER,
129
+ "campaign-type": message.campaignType,
130
+ recipients: (message.smsRecipients ?? []).map((r) => ({
131
+ num: r.num,
132
+ region: r.region.toUpperCase(),
133
+ })),
134
+ "message-txt": message.text,
135
+ "template-id": message.templateId,
136
+ variables: message.variables,
137
+ "sender-id": message.senderId,
138
+ "shorten-urls": message.shortenUrls,
139
+ "shorten-with-protocol": message.shortenWithProtocol,
140
+ bat: message.bat,
141
+ "campaign-id": message.campaignId,
142
+ });
143
+ }
144
+ /** Build the `{ path, body }` for a stored message. */
145
+ export function buildSendRequest(message) {
146
+ if (message.channel === "sms") {
147
+ return { path: "/send", body: buildSmsPayload(message) };
148
+ }
149
+ if (message.bulk) {
150
+ return { path: "/send/bulk/email", body: buildBulkEmailPayload(message) };
151
+ }
152
+ return { path: "/send", body: buildEmailPayload(message) };
153
+ }
154
+ /** Parse a Sweego `ModelOutSend` body into a normalized result. */
155
+ export function parseSendResponse(data) {
156
+ const obj = (typeof data === "object" && data !== null ? data : {});
157
+ const rawUids = obj["swg_uids"];
158
+ const swgUids = {};
159
+ if (typeof rawUids === "object" && rawUids !== null) {
160
+ for (const [key, value] of Object.entries(rawUids)) {
161
+ if (typeof value === "string")
162
+ swgUids[key] = value;
163
+ }
164
+ }
165
+ return {
166
+ channel: typeof obj["channel"] === "string" ? obj["channel"] : undefined,
167
+ provider: typeof obj["provider"] === "string" ? obj["provider"] : undefined,
168
+ swgUids,
169
+ transactionId: typeof obj["transaction_id"] === "string"
170
+ ? obj["transaction_id"]
171
+ : undefined,
172
+ // Sweego documents credit_left as a string, but coerce a number defensively
173
+ // so a numeric value isn't silently dropped.
174
+ creditLeft: typeof obj["credit_left"] === "string"
175
+ ? obj["credit_left"]
176
+ : typeof obj["credit_left"] === "number"
177
+ ? String(obj["credit_left"])
178
+ : undefined,
179
+ };
180
+ }
181
+ /* -------------------------------------------------------------------------- */
182
+ /* Logs (webhook-free status polling) */
183
+ /* -------------------------------------------------------------------------- */
184
+ /** GET /logs/{swg_uid}/status — current remote status for one message. */
185
+ export async function fetchLogStatus(apiKey, swgUid) {
186
+ const response = await sweegoFetch(apiKey, `/logs/${encodeURIComponent(swgUid)}/status`, { method: "GET", headers: { Accept: "application/json" } });
187
+ if (!response.ok)
188
+ return null;
189
+ const data = (await response.json());
190
+ const status = data["status"];
191
+ if (typeof status !== "string")
192
+ return null;
193
+ return {
194
+ status,
195
+ channel: typeof data["channel"] === "string" ? data["channel"] : undefined,
196
+ };
197
+ }
198
+ /** POST /sms/estimate — estimate the cost/segments of an SMS send. */
199
+ export async function fetchSmsEstimate(apiKey, body) {
200
+ const response = await sweegoFetch(apiKey, "/sms/estimate", {
201
+ method: "POST",
202
+ json: body,
203
+ });
204
+ const data = await response.json().catch(() => null);
205
+ if (!response.ok) {
206
+ throw new Error(sanitizeSweegoError(response.status, JSON.stringify(data ?? {})));
207
+ }
208
+ return data;
209
+ }
210
+ //# sourceMappingURL=sweego.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sweego.js","sourceRoot":"","sources":["../../src/component/sweego.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import type { Infer, Validator } from "convex/values";
2
+ export declare const assertExhaustive: (value: never) => never;
3
+ /**
4
+ * Attempt to parse an unknown value against a validator, with TypeScript type
5
+ * narrowing. Strips out anything not declared by the validator.
6
+ */
7
+ export declare function attemptToParse<T extends Validator<any, any, any>>(validator: T, value: unknown): {
8
+ kind: "success";
9
+ data: Infer<T>;
10
+ } | {
11
+ kind: "error";
12
+ error: unknown;
13
+ };
14
+ /** Pull a string field from an unknown object, if present. */
15
+ export declare function pickString(obj: unknown, ...keys: string[]): string | undefined;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/component/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAEtD,eAAO,MAAM,gBAAgB,GAAI,OAAO,KAAK,KAAG,KAE/C,CAAC;AAEF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAC/D,SAAS,EAAE,CAAC,EACZ,KAAK,EAAE,OAAO,GACb;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,CAMzE;AAED,8DAA8D;AAC9D,wBAAgB,UAAU,CACxB,GAAG,EAAE,OAAO,EACZ,GAAG,IAAI,EAAE,MAAM,EAAE,GAChB,MAAM,GAAG,SAAS,CAQpB"}
@@ -0,0 +1,29 @@
1
+ import { parse } from "convex-helpers/validators";
2
+ export const assertExhaustive = (value) => {
3
+ throw new Error(`Unhandled case: ${value}`);
4
+ };
5
+ /**
6
+ * Attempt to parse an unknown value against a validator, with TypeScript type
7
+ * narrowing. Strips out anything not declared by the validator.
8
+ */
9
+ export function attemptToParse(validator, value) {
10
+ try {
11
+ return { kind: "success", data: parse(validator, value) };
12
+ }
13
+ catch (error) {
14
+ return { kind: "error", error };
15
+ }
16
+ }
17
+ /** Pull a string field from an unknown object, if present. */
18
+ export function pickString(obj, ...keys) {
19
+ if (typeof obj !== "object" || obj === null)
20
+ return undefined;
21
+ const record = obj;
22
+ for (const key of keys) {
23
+ const value = record[key];
24
+ if (typeof value === "string" && value.length > 0)
25
+ return value;
26
+ }
27
+ return undefined;
28
+ }
29
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/component/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,2BAA2B,CAAC;AAGlD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAY,EAAS,EAAE;IACtD,MAAM,IAAI,KAAK,CAAC,mBAAmB,KAAe,EAAE,CAAC,CAAC;AACxD,CAAC,CAAC;AAEF;;;GAGG;AACH,MAAM,UAAU,cAAc,CAC5B,SAAY,EACZ,KAAc;IAEd,IAAI,CAAC;QACH,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC;IAC5D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAClC,CAAC;AACH,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,UAAU,CACxB,GAAY,EACZ,GAAG,IAAc;IAEjB,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC9D,MAAM,MAAM,GAAG,GAA8B,CAAC;IAC9C,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;QACvB,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC;IAClE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
package/package.json ADDED
@@ -0,0 +1,100 @@
1
+ {
2
+ "name": "@christian-ek/sweego",
3
+ "description": "A Sweego email & SMS component for Convex.",
4
+ "repository": "github:christian-ek/sweego",
5
+ "homepage": "https://github.com/christian-ek/sweego#readme",
6
+ "bugs": {
7
+ "url": "https://github.com/christian-ek/sweego/issues"
8
+ },
9
+ "version": "0.1.0",
10
+ "license": "Apache-2.0",
11
+ "keywords": [
12
+ "convex",
13
+ "component",
14
+ "sweego",
15
+ "email",
16
+ "sms"
17
+ ],
18
+ "type": "module",
19
+ "scripts": {
20
+ "dev": "convex dev --start 'npm run dev:build'",
21
+ "dev:build": "chokidar 'tsconfig*.json' 'src/**/*.ts' -i '**/*.test.ts' -c 'npm run build:codegen' --initial",
22
+ "dev:frontend": "vite example --clearScreen false",
23
+ "build:frontend": "vite build example",
24
+ "predev": "convex codegen --component-dir ./src/component && npm run build",
25
+ "clean": "rm -rf dist *.tsbuildinfo",
26
+ "build": "tsc --project ./tsconfig.build.json",
27
+ "prepublishOnly": "npm run build",
28
+ "build:codegen": "npx convex codegen --component-dir ./src/component && npm run build",
29
+ "build:clean": "rm -rf dist *.tsbuildinfo && npm run build:codegen",
30
+ "typecheck": "tsc --noEmit && tsc -p example/convex",
31
+ "lint": "eslint .",
32
+ "test": "vitest run --typecheck",
33
+ "test:watch": "vitest --typecheck --clearScreen false",
34
+ "test:debug": "vitest --inspect-brk --no-file-parallelism",
35
+ "test:coverage": "vitest run --coverage --coverage.reporter=text",
36
+ "preversion": "npm ci && npm run build:clean && npm run test && npm run lint && npm run typecheck",
37
+ "alpha": "npm version prerelease --preid alpha && npm publish --tag alpha && git push --follow-tags",
38
+ "release": "npm version patch && npm publish && git push --follow-tags"
39
+ },
40
+ "files": [
41
+ "dist",
42
+ "src"
43
+ ],
44
+ "publishConfig": {
45
+ "access": "public"
46
+ },
47
+ "exports": {
48
+ "./package.json": "./package.json",
49
+ ".": {
50
+ "types": "./dist/client/index.d.ts",
51
+ "default": "./dist/client/index.js"
52
+ },
53
+ "./test": "./src/test.ts",
54
+ "./_generated/component.js": {
55
+ "types": "./dist/component/_generated/component.d.ts"
56
+ },
57
+ "./convex.config": {
58
+ "types": "./dist/component/convex.config.d.ts",
59
+ "default": "./dist/component/convex.config.js"
60
+ },
61
+ "./convex.config.js": {
62
+ "types": "./dist/component/convex.config.d.ts",
63
+ "default": "./dist/component/convex.config.js"
64
+ }
65
+ },
66
+ "peerDependencies": {
67
+ "convex": "^1.31.7",
68
+ "convex-helpers": "^0.1.106"
69
+ },
70
+ "devDependencies": {
71
+ "@convex-dev/eslint-plugin": "2.0.0",
72
+ "@edge-runtime/vm": "5.0.0",
73
+ "@eslint/js": "10.0.1",
74
+ "@tailwindcss/vite": "^4.1.16",
75
+ "@types/node": "24.12.4",
76
+ "@types/react": "^19.2.2",
77
+ "@types/react-dom": "^19.2.2",
78
+ "@vitejs/plugin-react": "^4.5.2",
79
+ "chokidar-cli": "3.0.0",
80
+ "convex": "1.39.1",
81
+ "convex-helpers": "0.1.106",
82
+ "convex-test": "0.0.53",
83
+ "eslint": "10.4.1",
84
+ "globals": "17.6.0",
85
+ "pkg-pr-new": "0.0.75",
86
+ "prettier": "3.8.3",
87
+ "react": "^19.2.0",
88
+ "react-dom": "^19.2.0",
89
+ "tailwindcss": "^4.1.16",
90
+ "typescript": "5.9.3",
91
+ "typescript-eslint": "8.60.0",
92
+ "vite": "^6.3.5",
93
+ "vitest": "4.1.7"
94
+ },
95
+ "types": "./dist/client/index.d.ts",
96
+ "module": "./dist/client/index.js",
97
+ "dependencies": {
98
+ "@convex-dev/workpool": "^0.4.6"
99
+ }
100
+ }
@@ -0,0 +1 @@
1
+ // This is only here so convex-test can detect a _generated folder