groundmail 0.0.0-stage → 0.14.2

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.
@@ -0,0 +1,78 @@
1
+ import { A as ApiErrorBody, D as DnsRecord } from './client-B8xoWTgr.js';
2
+ export { a as ApiErrorCode, b as ApiKey, c as ApiKeyScope, d as ApplyDnsParams, e as ApplyDnsRecordResult, f as ApplyDnsResult, g as Asset, h as Automation, i as AutomationRun, j as AutomationRunResponse, k as AutomationRunStatus, l as AutomationRunStep, m as AutomationRunStepStatus, n as AutomationStatus, o as AutomationStep, p as AutomationTrigger, B as BatchSendEmailResult, C as CategoryUnsubscribedErrorDetails, q as ConnectTwilioParams, r as ContactWebhookEventPayload, s as CreateApiKeyParams, t as CreateApiKeyResult, u as CreateAutomationParams, v as CreateDomainParams, w as CreateDomainResult, x as CreateSuppressionParams, y as CreateTemplateParams, z as CreateWebhookParams, E as DEFAULT_API_BASE_URL, F as DeliverabilityBucket, H as DeliverabilityDomainInsight, I as DeliverabilityInsightsResult, J as DeliverabilityMailServerRelay, K as DeliverabilityWindow, L as DnsProviderName, M as Domain, N as DomainBimiAnalysis, O as DomainDetailResult, P as DomainDmarcAnalysis, Q as DomainDnsAnalysis, R as DomainStatus, T as DomainTlsMode, U as DomainTrackingDns, V as EmailListItem, W as EmailWebhookEventType, X as EventRecord, G as Groundmail, Y as GroundmailOptions, Z as ListApiKeysParams, _ as ListApiKeysResult, $ as ListAutomationRunsParams, a0 as ListAutomationRunsResult, a1 as ListAutomationsResult, a2 as ListDomainsParams, a3 as ListDomainsResult, a4 as ListEmailsParams, a5 as ListEmailsResult, a6 as ListReceivedEmailsParams, a7 as ListReceivedEmailsResult, a8 as ListSuppressionsParams, a9 as ListSuppressionsResult, aa as ListTemplatesParams, ab as ListTemplatesResult, ac as MailServerSigningStatus, ad as ReceivedEmail, ae as ReceivedEmailAttachment, af as ReceivedEmailAttachmentMeta, ag as RemoteApplyDnsCredentials, ah as SendEmailParams, S as SendEmailResult, ai as SuppressedErrorDetails, aj as Suppression, ak as Template, al as TemplateFormat, am as TemplateLintWarning, an as TemplateStarter, ao as TemplateStatus, ap as TemplateVersion, aq as TestEmailWebhookParams, ar as TestEmailWebhookResult, as as TriggerEventParams, at as TriggerEventResult, au as TwilioIntegrationResponse, av as TwilioIntegrationStatus, aw as UpdateAutomationParams, ax as UpdateDomainParams, ay as UpdateEmailParams, az as UpdateTemplateParams, aA as UpdateWebhookParams, aB as VerifyDomainResult, aC as WebhookEndpoint, aD as WebhookEndpointWithSecret, aE as WebhookEventType } from './client-B8xoWTgr.js';
3
+
4
+ type GroundmailErrorOptions = {
5
+ code?: string;
6
+ upgradeUrl?: string;
7
+ hint?: string;
8
+ docsUrl?: string;
9
+ requiredScope?: string;
10
+ };
11
+ /**
12
+ * An API error. Besides `message` and `status`, the API says how to recover:
13
+ * `code` (stable, e.g. `insufficient_scope`), `hint` (what to do next),
14
+ * `docsUrl` (the errors page entry for the code), `requiredScope` (with
15
+ * `insufficient_scope`) and `upgradeUrl` (with plan limits).
16
+ */
17
+ declare class GroundmailError extends Error {
18
+ readonly status: number;
19
+ readonly details?: unknown;
20
+ readonly code?: string;
21
+ readonly upgradeUrl?: string;
22
+ /** How to fix it, from the API. */
23
+ readonly hint?: string;
24
+ /** Docs for this error code, e.g. https://docs.groundmail.dev/errors#insufficient_scope */
25
+ readonly docsUrl?: string;
26
+ /** With `insufficient_scope`: the scope(s) the endpoint needs, space-separated. */
27
+ readonly requiredScope?: string;
28
+ constructor(message: string, status: number, details?: unknown, options?: GroundmailErrorOptions);
29
+ /** Same fields as the API's error body, snake_case, for logging. */
30
+ toJSON(): Record<string, unknown>;
31
+ /**
32
+ * Reads both error shapes the API returns: `{ error: { message, code, hint,
33
+ * docs_url, … } }`, and the older `{ error: "<message>", code, hint, docs_url }`.
34
+ */
35
+ static fromResponse(status: number, body: ApiErrorBody): GroundmailError;
36
+ }
37
+
38
+ declare function signWebhookPayload(secret: string, payload: string, timestamp: number): string;
39
+ declare function buildSignatureHeader(secret: string, payload: string, timestamp?: number): string;
40
+ /**
41
+ * Verify a Groundmail webhook signature header (`Groundmail-Signature`).
42
+ * Expects HMAC-SHA256 over `${timestamp}.${rawBody}` with the endpoint secret.
43
+ */
44
+ declare function verifyWebhookSignature(secret: string, payload: string, header: string | null | undefined, toleranceSec?: number): boolean;
45
+
46
+ /** Merge `include:host` into an existing SPF record (or create a minimal one). */
47
+ declare function mergeSpfInclude(existing: string | null | undefined, includeHost: string): string;
48
+
49
+ type DnsProviderName = 'cloudflare' | 'godaddy' | 'vercel';
50
+ type ApplyDnsRecordResult = {
51
+ purpose: string;
52
+ host: string;
53
+ action: 'created' | 'updated' | 'unchanged' | 'merged';
54
+ detail?: string;
55
+ };
56
+ type ApplyDnsResult = {
57
+ provider: DnsProviderName;
58
+ domain: string;
59
+ results: ApplyDnsRecordResult[];
60
+ };
61
+ type ApplyDnsCredentials = {
62
+ cloudflareApiToken?: string;
63
+ cloudflareZoneId?: string;
64
+ godaddyApiKey?: string;
65
+ godaddyApiSecret?: string;
66
+ vercelApiToken?: string;
67
+ vercelTeamId?: string;
68
+ };
69
+
70
+ declare function applyDnsRecords(input: {
71
+ provider: DnsProviderName;
72
+ domain: string;
73
+ records: DnsRecord[];
74
+ credentials: ApplyDnsCredentials;
75
+ fetchImpl?: typeof fetch;
76
+ }): Promise<ApplyDnsResult>;
77
+
78
+ export { DnsRecord, GroundmailError, type GroundmailErrorOptions, applyDnsRecords, buildSignatureHeader, mergeSpfInclude, signWebhookPayload, verifyWebhookSignature };
package/dist/index.js ADDED
@@ -0,0 +1,20 @@
1
+ import {
2
+ DEFAULT_API_BASE_URL,
3
+ Groundmail,
4
+ GroundmailError,
5
+ applyDnsRecords,
6
+ buildSignatureHeader,
7
+ mergeSpfInclude,
8
+ signWebhookPayload,
9
+ verifyWebhookSignature
10
+ } from "./chunk-2ZKYDDVV.js";
11
+ export {
12
+ DEFAULT_API_BASE_URL,
13
+ Groundmail,
14
+ GroundmailError,
15
+ applyDnsRecords,
16
+ buildSignatureHeader,
17
+ mergeSpfInclude,
18
+ signWebhookPayload,
19
+ verifyWebhookSignature
20
+ };
@@ -0,0 +1 @@
1
+ export { GroundmailTransportOptions, HEADER_IDEMPOTENCY, HEADER_SCHEDULED_AT, HEADER_TAG, createGroundmailTransport, groundmailTransport, mailDataToSendParams } from 'groundmail-nodemailer';
@@ -0,0 +1,17 @@
1
+ // src/nodemailer.ts
2
+ import {
3
+ createGroundmailTransport,
4
+ groundmailTransport,
5
+ mailDataToSendParams,
6
+ HEADER_IDEMPOTENCY,
7
+ HEADER_SCHEDULED_AT,
8
+ HEADER_TAG
9
+ } from "groundmail-nodemailer";
10
+ export {
11
+ HEADER_IDEMPOTENCY,
12
+ HEADER_SCHEDULED_AT,
13
+ HEADER_TAG,
14
+ createGroundmailTransport,
15
+ groundmailTransport,
16
+ mailDataToSendParams
17
+ };
@@ -0,0 +1,87 @@
1
+ import { G as Groundmail } from './client-B8xoWTgr.js';
2
+
3
+ /**
4
+ * Minimal Payload `SendEmailOptions` / address shapes used by this adapter.
5
+ * Compatible with Payload 3 without requiring `payload` at build time.
6
+ */
7
+ type PayloadEmailAddress = string | {
8
+ name?: string;
9
+ address: string;
10
+ } | Array<string | {
11
+ name?: string;
12
+ address: string;
13
+ }>;
14
+ type PayloadSendEmailOptions = {
15
+ from?: PayloadEmailAddress;
16
+ to?: PayloadEmailAddress;
17
+ cc?: PayloadEmailAddress;
18
+ bcc?: PayloadEmailAddress;
19
+ replyTo?: PayloadEmailAddress;
20
+ subject?: string;
21
+ html?: string | {
22
+ toString(): string;
23
+ };
24
+ text?: string | {
25
+ toString(): string;
26
+ };
27
+ headers?: Array<{
28
+ key: string;
29
+ value: string;
30
+ }> | Record<string, string | string[] | {
31
+ prepared: boolean;
32
+ value: string;
33
+ }>;
34
+ attachments?: Array<{
35
+ filename?: string | false;
36
+ content?: string | Buffer;
37
+ path?: string | {
38
+ href: string;
39
+ };
40
+ }>;
41
+ };
42
+ /** Payload `EmailAdapter` factory return shape (sync outer factory). */
43
+ type PayloadEmailAdapterInstance = {
44
+ name: string;
45
+ defaultFromAddress: string;
46
+ defaultFromName: string;
47
+ sendEmail: (message: PayloadSendEmailOptions) => Promise<{
48
+ id: string;
49
+ }>;
50
+ };
51
+ type PayloadEmailAdapter = () => PayloadEmailAdapterInstance;
52
+ type GroundmailPayloadAdapterArgs = {
53
+ /** Verified default From address (required by Payload). */
54
+ defaultFromAddress: string;
55
+ /** Display name for the default From. */
56
+ defaultFromName: string;
57
+ /** Groundmail API key (`gm_…`). Falls back to `GROUNDMAIL_API_KEY`. */
58
+ apiKey?: string;
59
+ /** Override API base URL (tests / self-hosted). */
60
+ baseUrl?: string;
61
+ /** Injected client (tests). */
62
+ client?: Groundmail;
63
+ /** Force all mail to this address (local/dev). */
64
+ overrideRecipientAddress?: string;
65
+ };
66
+ /**
67
+ * Payload CMS email adapter for Groundmail (HTTP API).
68
+ *
69
+ * Drop-in for Payload 3 `email:` config — same shape as official REST adapters.
70
+ *
71
+ * @example
72
+ * ```ts
73
+ * import { buildConfig } from 'payload'
74
+ * import { groundmailAdapter } from 'groundmail-payload'
75
+ *
76
+ * export default buildConfig({
77
+ * email: groundmailAdapter({
78
+ * defaultFromAddress: 'noreply@yourdomain.com',
79
+ * defaultFromName: 'Acme',
80
+ * // apiKey: process.env.GROUNDMAIL_API_KEY,
81
+ * }),
82
+ * })
83
+ * ```
84
+ */
85
+ declare function groundmailAdapter(args: GroundmailPayloadAdapterArgs): PayloadEmailAdapter;
86
+
87
+ export { type GroundmailPayloadAdapterArgs, type PayloadEmailAdapter, type PayloadEmailAdapterInstance, type PayloadEmailAddress, type PayloadSendEmailOptions, groundmailAdapter };
@@ -0,0 +1,114 @@
1
+ import {
2
+ DEFAULT_API_BASE_URL,
3
+ Groundmail
4
+ } from "./chunk-2ZKYDDVV.js";
5
+
6
+ // src/payload.ts
7
+ function resolveApiKey(args) {
8
+ return args.apiKey || (typeof process !== "undefined" ? process.env.GROUNDMAIL_API_KEY : void 0);
9
+ }
10
+ function formatAddress(address) {
11
+ if (typeof address === "string") return address;
12
+ return address.name ? `${address.name} <${address.address}>` : address.address;
13
+ }
14
+ function mapFrom(address, defaultFromName, defaultFromAddress) {
15
+ if (!address) return `${defaultFromName} <${defaultFromAddress}>`;
16
+ if (Array.isArray(address)) {
17
+ const first = address[0];
18
+ if (!first) return `${defaultFromName} <${defaultFromAddress}>`;
19
+ return formatAddress(first);
20
+ }
21
+ return formatAddress(address);
22
+ }
23
+ function mapAddresses(addresses) {
24
+ if (!addresses) return void 0;
25
+ if (typeof addresses === "string") return addresses;
26
+ if (Array.isArray(addresses)) {
27
+ return addresses.map((a) => typeof a === "string" ? a : a.address);
28
+ }
29
+ return addresses.address;
30
+ }
31
+ function mapHeaders(headers) {
32
+ if (!headers) return void 0;
33
+ if (Array.isArray(headers)) {
34
+ return headers.reduce((acc, { key, value }) => {
35
+ acc[key] = value;
36
+ return acc;
37
+ }, {});
38
+ }
39
+ return Object.entries(headers).reduce((acc, [key, value]) => {
40
+ if (typeof value === "string") acc[key] = value;
41
+ else if (Array.isArray(value)) acc[key] = value.join(", ");
42
+ else acc[key] = value.value;
43
+ return acc;
44
+ }, {});
45
+ }
46
+ function mapAttachments(attachments) {
47
+ if (!attachments?.length) return void 0;
48
+ return attachments.map((attachment) => {
49
+ if (attachment.filename == null || attachment.filename === false) {
50
+ throw new Error("Groundmail Payload adapter: attachment is missing filename");
51
+ }
52
+ if (attachment.path && !attachment.content) {
53
+ throw new Error(
54
+ "Groundmail Payload adapter: path-only attachments are not supported \u2014 pass content (base64 or string)"
55
+ );
56
+ }
57
+ if (typeof attachment.content === "string") {
58
+ return { filename: attachment.filename, content: attachment.content };
59
+ }
60
+ if (attachment.content instanceof Buffer) {
61
+ return { filename: attachment.filename, content: attachment.content.toString("base64") };
62
+ }
63
+ throw new Error("Groundmail Payload adapter: attachment content must be a string or Buffer");
64
+ });
65
+ }
66
+ function groundmailAdapter(args) {
67
+ const { defaultFromAddress, defaultFromName } = args;
68
+ if (!defaultFromAddress?.trim()) {
69
+ throw new Error("groundmailAdapter requires defaultFromAddress");
70
+ }
71
+ if (!defaultFromName?.trim()) {
72
+ throw new Error("groundmailAdapter requires defaultFromName");
73
+ }
74
+ const adapter = () => ({
75
+ name: "groundmail",
76
+ defaultFromAddress,
77
+ defaultFromName,
78
+ sendEmail: async (message) => {
79
+ const client = args.client ?? (() => {
80
+ const key = resolveApiKey(args);
81
+ if (!key) {
82
+ throw new Error(
83
+ "Groundmail Payload adapter requires `apiKey` or GROUNDMAIL_API_KEY"
84
+ );
85
+ }
86
+ return new Groundmail(key, {
87
+ baseUrl: args.baseUrl ?? DEFAULT_API_BASE_URL
88
+ });
89
+ })();
90
+ const to = args.overrideRecipientAddress ? args.overrideRecipientAddress : mapAddresses(message.to);
91
+ if (!to || Array.isArray(to) && to.length === 0) {
92
+ throw new Error("Groundmail Payload adapter: message.to is required");
93
+ }
94
+ const result = await client.emails.send({
95
+ from: mapFrom(message.from, defaultFromName, defaultFromAddress),
96
+ to,
97
+ cc: mapAddresses(message.cc),
98
+ bcc: mapAddresses(message.bcc),
99
+ replyTo: mapAddresses(message.replyTo),
100
+ subject: message.subject ?? "",
101
+ html: message.html?.toString(),
102
+ text: message.text?.toString(),
103
+ headers: mapHeaders(message.headers),
104
+ attachments: mapAttachments(message.attachments),
105
+ tags: [{ name: "product", value: "payload" }]
106
+ });
107
+ return { id: result.id };
108
+ }
109
+ });
110
+ return adapter;
111
+ }
112
+ export {
113
+ groundmailAdapter
114
+ };
package/package.json CHANGED
@@ -1,6 +1,101 @@
1
1
  {
2
2
  "name": "groundmail",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.14.2",
4
+ "description": "Groundmail transactional email API client",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./nodemailer": {
15
+ "types": "./dist/nodemailer.d.ts",
16
+ "import": "./dist/nodemailer.js"
17
+ },
18
+ "./better-auth": {
19
+ "types": "./dist/better-auth.d.ts",
20
+ "import": "./dist/better-auth.js"
21
+ },
22
+ "./authjs": {
23
+ "types": "./dist/authjs.d.ts",
24
+ "import": "./dist/authjs.js"
25
+ },
26
+ "./clerk": {
27
+ "types": "./dist/clerk.d.ts",
28
+ "import": "./dist/clerk.js"
29
+ },
30
+ "./payload": {
31
+ "types": "./dist/payload.d.ts",
32
+ "import": "./dist/payload.js"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "README.md"
38
+ ],
39
+ "repository": {
40
+ "type": "git",
41
+ "url": "git+https://github.com/Groundmail/groundmail-sdks.git"
42
+ },
43
+ "homepage": "https://docs.groundmail.dev/quickstart",
44
+ "bugs": {
45
+ "url": "https://github.com/Groundmail/groundmail-sdks/issues"
46
+ },
47
+ "keywords": [
48
+ "email",
49
+ "transactional",
50
+ "groundmail",
51
+ "smtp",
52
+ "nodemailer",
53
+ "better-auth",
54
+ "auth.js",
55
+ "next-auth",
56
+ "nextauth",
57
+ "clerk",
58
+ "payload",
59
+ "payloadcms",
60
+ "react-email"
61
+ ],
62
+ "publishConfig": {
63
+ "access": "public"
64
+ },
65
+ "engines": {
66
+ "node": ">=18"
67
+ },
68
+ "peerDependencies": {
69
+ "@react-email/render": ">=0.0.16",
70
+ "nodemailer": ">=6.0.0",
71
+ "react": ">=18.0.0"
72
+ },
73
+ "peerDependenciesMeta": {
74
+ "@react-email/render": {
75
+ "optional": true
76
+ },
77
+ "nodemailer": {
78
+ "optional": true
79
+ },
80
+ "react": {
81
+ "optional": true
82
+ }
83
+ },
84
+ "scripts": {
85
+ "build": "tsup src/index.ts src/better-auth.ts src/authjs.ts src/clerk.ts src/payload.ts --format esm --dts --clean",
86
+ "build:nodemailer-bridge": "tsup src/nodemailer.ts --format esm --dts --external groundmail-nodemailer",
87
+ "test": "vitest run",
88
+ "typecheck": "tsc --noEmit",
89
+ "prepublishOnly": "npm run build && npm run build:nodemailer-bridge"
90
+ },
91
+ "dependencies": {
92
+ "groundmail-nodemailer": "0.14.2"
93
+ },
94
+ "devDependencies": {
95
+ "@types/nodemailer": "^8.0.1",
96
+ "nodemailer": "^9.0.3",
97
+ "tsup": "^8.5.0",
98
+ "typescript": "^5",
99
+ "vitest": "^3.2.4"
100
+ }
101
+ }