sendhive 0.1.0-beta.0 → 0.1.0-beta.1
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 +16 -0
- package/dist/index.cjs +20 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +34 -1
- package/dist/index.d.ts +34 -1
- package/dist/index.js +20 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -67,6 +67,22 @@ const { data, error } = await sendhive.emails.send({
|
|
|
67
67
|
|
|
68
68
|
Every variable the template uses must have a value in `data`, otherwise you get `missing_template_variables`. Values are HTML-escaped for you, and a value used as a link must start with `http://`, `https://` or `mailto:`. An unknown template gives `template_not_found`.
|
|
69
69
|
|
|
70
|
+
Ready-made templates work without saving anything: use `preset:` plus the preset id, for example `template: 'preset:welcome'`.
|
|
71
|
+
|
|
72
|
+
## Templates
|
|
73
|
+
|
|
74
|
+
```ts
|
|
75
|
+
// Your templates and the ready-made ones (slug 'preset:welcome', 'preset:order-shipped', ...)
|
|
76
|
+
const { data: templates, error } = await sendhive.templates.list()
|
|
77
|
+
// templates[0] -> { id, slug, name, kind: 'custom' | 'preset', subject, preview_text, variables, updated_at }
|
|
78
|
+
|
|
79
|
+
// Draw a template with data. Missing values are not an error: they show as {{name}} and are listed.
|
|
80
|
+
const { data: preview } = await sendhive.templates.preview('preset:welcome', { customer_name: 'Asha' })
|
|
81
|
+
// preview -> { subject, html, text, missing_variables }
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
`list()` calls `GET /api/templates` and `preview(template, data?)` calls `POST /api/templates/preview`. Both return `{ data, error }` and use the same key and rate limit as sending.
|
|
85
|
+
|
|
70
86
|
## Get
|
|
71
87
|
|
|
72
88
|
```ts
|
package/dist/index.cjs
CHANGED
|
@@ -70,8 +70,27 @@ var Emails = class {
|
|
|
70
70
|
return this.client.request("GET", `/api/emails/${encodeURIComponent(id)}`);
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
|
+
var Templates = class {
|
|
74
|
+
constructor(client) {
|
|
75
|
+
this.client = client;
|
|
76
|
+
}
|
|
77
|
+
client;
|
|
78
|
+
/** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */
|
|
79
|
+
async list() {
|
|
80
|
+
const res = await this.client.request("GET", "/api/templates");
|
|
81
|
+
return res.error ? res : { data: res.data.data, error: null };
|
|
82
|
+
}
|
|
83
|
+
/** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */
|
|
84
|
+
async preview(template, data) {
|
|
85
|
+
return this.client.request("POST", "/api/templates/preview", {
|
|
86
|
+
template,
|
|
87
|
+
...data !== void 0 ? { data } : {}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
73
91
|
var Sendhive = class {
|
|
74
92
|
emails;
|
|
93
|
+
templates;
|
|
75
94
|
apiKey;
|
|
76
95
|
baseUrl;
|
|
77
96
|
constructor(apiKey, options = {}) {
|
|
@@ -80,6 +99,7 @@ var Sendhive = class {
|
|
|
80
99
|
if (!baseUrl) throw new Error("Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.");
|
|
81
100
|
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
82
101
|
this.emails = new Emails(this);
|
|
102
|
+
this.templates = new Templates(this);
|
|
83
103
|
}
|
|
84
104
|
/** @internal */
|
|
85
105
|
async request(method, path, body) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n Email,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveOptions,\n} from './types'\n\nexport type {\n Email,\n EmailEvent,\n EmailTag,\n Recipients,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveErrorFix,\n SendhiveOptions,\n TemplateData,\n} from './types'\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined\n}\n\n/** Optional peer: only loaded when the caller passes `react`. */\nasync function renderReact(element: unknown): Promise<string> {\n const specifier = '@react-email/render'\n let mod: { render?: (el: unknown) => string | Promise<string> }\n try {\n mod = await import(/* @vite-ignore */ specifier)\n } catch {\n throw new Error('The `react` option needs the optional peer dependency @react-email/render.')\n }\n if (!mod.render) throw new Error('@react-email/render has no `render` export.')\n return mod.render(element)\n}\n\nclass Emails {\n constructor(private readonly client: Sendhive) {}\n\n async send(options: SendEmailOptions): Promise<Result<SendEmailResponse>> {\n const { replyTo, react, ...rest } = options\n let html = rest.html\n if (react !== undefined) {\n try {\n html = await renderReact(react)\n } catch (err) {\n return {\n data: null,\n error: { statusCode: 422, name: 'validation_error', message: (err as Error).message },\n }\n }\n }\n const body = {\n ...rest,\n ...(html !== undefined ? { html } : {}),\n ...(replyTo !== undefined ? { reply_to: replyTo } : {}),\n }\n return this.client.request<SendEmailResponse>('POST', '/api/emails', body)\n }\n\n async get(id: string): Promise<Result<Email>> {\n return this.client.request<Email>('GET', `/api/emails/${encodeURIComponent(id)}`)\n }\n}\n\nexport class Sendhive {\n readonly emails: Emails\n private readonly apiKey: string | undefined\n private readonly baseUrl: string\n\n constructor(apiKey?: string, options: SendhiveOptions = {}) {\n this.apiKey = apiKey ?? env('SENDHIVE_API_KEY')\n // No default host: an API key must never be sent to a server the caller did not choose.\n const baseUrl = options.baseUrl ?? env('SENDHIVE_BASE_URL')\n if (!baseUrl) throw new Error('Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.')\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\n this.emails = new Emails(this)\n }\n\n /** @internal */\n async request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>> {\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`\n if (body !== undefined) headers['Content-Type'] = 'application/json'\n\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n } catch (err) {\n return {\n data: null,\n error: {\n statusCode: 0,\n name: 'network_error',\n message: err instanceof Error ? err.message : String(err),\n },\n }\n }\n\n let json: unknown\n try {\n json = await res.json()\n } catch {\n json = null\n }\n\n if (!res.ok) {\n const e = (json ?? {}) as Partial<SendhiveError>\n return {\n data: null,\n error: {\n statusCode: e.statusCode ?? res.status,\n name: e.name ?? 'application_error',\n message: e.message ?? (res.statusText || 'Unexpected response'),\n ...(e.fix ? { fix: e.fix } : {}),\n },\n }\n }\n return { data: json as T, error: null }\n }\n}\n\nexport default Sendhive\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n Email,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveOptions,\n TemplateData,\n TemplateList,\n TemplatePreview,\n TemplateSummary,\n} from './types'\n\nexport type {\n Email,\n EmailEvent,\n EmailTag,\n Recipients,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveErrorFix,\n SendhiveOptions,\n TemplateData,\n TemplateList,\n TemplatePreview,\n TemplateSummary,\n} from './types'\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined\n}\n\n/** Optional peer: only loaded when the caller passes `react`. */\nasync function renderReact(element: unknown): Promise<string> {\n const specifier = '@react-email/render'\n let mod: { render?: (el: unknown) => string | Promise<string> }\n try {\n mod = await import(/* @vite-ignore */ specifier)\n } catch {\n throw new Error('The `react` option needs the optional peer dependency @react-email/render.')\n }\n if (!mod.render) throw new Error('@react-email/render has no `render` export.')\n return mod.render(element)\n}\n\nclass Emails {\n constructor(private readonly client: Sendhive) {}\n\n async send(options: SendEmailOptions): Promise<Result<SendEmailResponse>> {\n const { replyTo, react, ...rest } = options\n let html = rest.html\n if (react !== undefined) {\n try {\n html = await renderReact(react)\n } catch (err) {\n return {\n data: null,\n error: { statusCode: 422, name: 'validation_error', message: (err as Error).message },\n }\n }\n }\n const body = {\n ...rest,\n ...(html !== undefined ? { html } : {}),\n ...(replyTo !== undefined ? { reply_to: replyTo } : {}),\n }\n return this.client.request<SendEmailResponse>('POST', '/api/emails', body)\n }\n\n async get(id: string): Promise<Result<Email>> {\n return this.client.request<Email>('GET', `/api/emails/${encodeURIComponent(id)}`)\n }\n}\n\nclass Templates {\n constructor(private readonly client: Sendhive) {}\n\n /** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */\n async list(): Promise<Result<TemplateSummary[]>> {\n const res = await this.client.request<TemplateList>('GET', '/api/templates')\n return res.error ? res : { data: res.data.data, error: null }\n }\n\n /** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */\n async preview(template: string, data?: TemplateData): Promise<Result<TemplatePreview>> {\n return this.client.request<TemplatePreview>('POST', '/api/templates/preview', {\n template,\n ...(data !== undefined ? { data } : {}),\n })\n }\n}\n\nexport class Sendhive {\n readonly emails: Emails\n readonly templates: Templates\n private readonly apiKey: string | undefined\n private readonly baseUrl: string\n\n constructor(apiKey?: string, options: SendhiveOptions = {}) {\n this.apiKey = apiKey ?? env('SENDHIVE_API_KEY')\n // No default host: an API key must never be sent to a server the caller did not choose.\n const baseUrl = options.baseUrl ?? env('SENDHIVE_BASE_URL')\n if (!baseUrl) throw new Error('Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.')\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\n this.emails = new Emails(this)\n this.templates = new Templates(this)\n }\n\n /** @internal */\n async request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>> {\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`\n if (body !== undefined) headers['Content-Type'] = 'application/json'\n\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n } catch (err) {\n return {\n data: null,\n error: {\n statusCode: 0,\n name: 'network_error',\n message: err instanceof Error ? err.message : String(err),\n },\n }\n }\n\n let json: unknown\n try {\n json = await res.json()\n } catch {\n json = null\n }\n\n if (!res.ok) {\n const e = (json ?? {}) as Partial<SendhiveError>\n return {\n data: null,\n error: {\n statusCode: e.statusCode ?? res.status,\n name: e.name ?? 'application_error',\n message: e.message ?? (res.statusText || 'Unexpected response'),\n ...(e.fix ? { fix: e.fix } : {}),\n },\n }\n }\n return { data: json as T, error: null }\n }\n}\n\nexport default Sendhive\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -84,6 +84,30 @@ interface Email {
|
|
|
84
84
|
delivered_at: string | null;
|
|
85
85
|
events: EmailEvent[];
|
|
86
86
|
}
|
|
87
|
+
/** One template you can send: one of your own, or a ready-made preset (`slug` is then `preset:<id>`). */
|
|
88
|
+
interface TemplateSummary {
|
|
89
|
+
id: string;
|
|
90
|
+
/** Pass this as `template` when sending. */
|
|
91
|
+
slug: string;
|
|
92
|
+
name: string;
|
|
93
|
+
kind: 'custom' | 'preset';
|
|
94
|
+
subject: string;
|
|
95
|
+
preview_text: string | null;
|
|
96
|
+
/** The `{{variables}}` the template needs in `data`. */
|
|
97
|
+
variables: string[];
|
|
98
|
+
/** Null for ready-made presets. */
|
|
99
|
+
updated_at: string | null;
|
|
100
|
+
}
|
|
101
|
+
interface TemplateList {
|
|
102
|
+
data: TemplateSummary[];
|
|
103
|
+
}
|
|
104
|
+
/** A template drawn with the data you gave. Values you left out show as `{{name}}` and are listed. */
|
|
105
|
+
interface TemplatePreview {
|
|
106
|
+
subject: string;
|
|
107
|
+
html: string;
|
|
108
|
+
text: string;
|
|
109
|
+
missing_variables: string[];
|
|
110
|
+
}
|
|
87
111
|
type Result<T> = {
|
|
88
112
|
data: T;
|
|
89
113
|
error: null;
|
|
@@ -101,8 +125,17 @@ declare class Emails {
|
|
|
101
125
|
send(options: SendEmailOptions): Promise<Result<SendEmailResponse>>;
|
|
102
126
|
get(id: string): Promise<Result<Email>>;
|
|
103
127
|
}
|
|
128
|
+
declare class Templates {
|
|
129
|
+
private readonly client;
|
|
130
|
+
constructor(client: Sendhive);
|
|
131
|
+
/** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */
|
|
132
|
+
list(): Promise<Result<TemplateSummary[]>>;
|
|
133
|
+
/** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */
|
|
134
|
+
preview(template: string, data?: TemplateData): Promise<Result<TemplatePreview>>;
|
|
135
|
+
}
|
|
104
136
|
declare class Sendhive {
|
|
105
137
|
readonly emails: Emails;
|
|
138
|
+
readonly templates: Templates;
|
|
106
139
|
private readonly apiKey;
|
|
107
140
|
private readonly baseUrl;
|
|
108
141
|
constructor(apiKey?: string, options?: SendhiveOptions);
|
|
@@ -110,4 +143,4 @@ declare class Sendhive {
|
|
|
110
143
|
request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>>;
|
|
111
144
|
}
|
|
112
145
|
|
|
113
|
-
export { type Email, type EmailEvent, type EmailTag, type Recipients, type Result, type SendEmailOptions, type SendEmailResponse, Sendhive, type SendhiveError, type SendhiveErrorFix, type SendhiveOptions, type TemplateData, Sendhive as default };
|
|
146
|
+
export { type Email, type EmailEvent, type EmailTag, type Recipients, type Result, type SendEmailOptions, type SendEmailResponse, Sendhive, type SendhiveError, type SendhiveErrorFix, type SendhiveOptions, type TemplateData, type TemplateList, type TemplatePreview, type TemplateSummary, Sendhive as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -84,6 +84,30 @@ interface Email {
|
|
|
84
84
|
delivered_at: string | null;
|
|
85
85
|
events: EmailEvent[];
|
|
86
86
|
}
|
|
87
|
+
/** One template you can send: one of your own, or a ready-made preset (`slug` is then `preset:<id>`). */
|
|
88
|
+
interface TemplateSummary {
|
|
89
|
+
id: string;
|
|
90
|
+
/** Pass this as `template` when sending. */
|
|
91
|
+
slug: string;
|
|
92
|
+
name: string;
|
|
93
|
+
kind: 'custom' | 'preset';
|
|
94
|
+
subject: string;
|
|
95
|
+
preview_text: string | null;
|
|
96
|
+
/** The `{{variables}}` the template needs in `data`. */
|
|
97
|
+
variables: string[];
|
|
98
|
+
/** Null for ready-made presets. */
|
|
99
|
+
updated_at: string | null;
|
|
100
|
+
}
|
|
101
|
+
interface TemplateList {
|
|
102
|
+
data: TemplateSummary[];
|
|
103
|
+
}
|
|
104
|
+
/** A template drawn with the data you gave. Values you left out show as `{{name}}` and are listed. */
|
|
105
|
+
interface TemplatePreview {
|
|
106
|
+
subject: string;
|
|
107
|
+
html: string;
|
|
108
|
+
text: string;
|
|
109
|
+
missing_variables: string[];
|
|
110
|
+
}
|
|
87
111
|
type Result<T> = {
|
|
88
112
|
data: T;
|
|
89
113
|
error: null;
|
|
@@ -101,8 +125,17 @@ declare class Emails {
|
|
|
101
125
|
send(options: SendEmailOptions): Promise<Result<SendEmailResponse>>;
|
|
102
126
|
get(id: string): Promise<Result<Email>>;
|
|
103
127
|
}
|
|
128
|
+
declare class Templates {
|
|
129
|
+
private readonly client;
|
|
130
|
+
constructor(client: Sendhive);
|
|
131
|
+
/** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */
|
|
132
|
+
list(): Promise<Result<TemplateSummary[]>>;
|
|
133
|
+
/** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */
|
|
134
|
+
preview(template: string, data?: TemplateData): Promise<Result<TemplatePreview>>;
|
|
135
|
+
}
|
|
104
136
|
declare class Sendhive {
|
|
105
137
|
readonly emails: Emails;
|
|
138
|
+
readonly templates: Templates;
|
|
106
139
|
private readonly apiKey;
|
|
107
140
|
private readonly baseUrl;
|
|
108
141
|
constructor(apiKey?: string, options?: SendhiveOptions);
|
|
@@ -110,4 +143,4 @@ declare class Sendhive {
|
|
|
110
143
|
request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>>;
|
|
111
144
|
}
|
|
112
145
|
|
|
113
|
-
export { type Email, type EmailEvent, type EmailTag, type Recipients, type Result, type SendEmailOptions, type SendEmailResponse, Sendhive, type SendhiveError, type SendhiveErrorFix, type SendhiveOptions, type TemplateData, Sendhive as default };
|
|
146
|
+
export { type Email, type EmailEvent, type EmailTag, type Recipients, type Result, type SendEmailOptions, type SendEmailResponse, Sendhive, type SendhiveError, type SendhiveErrorFix, type SendhiveOptions, type TemplateData, type TemplateList, type TemplatePreview, type TemplateSummary, Sendhive as default };
|
package/dist/index.js
CHANGED
|
@@ -45,8 +45,27 @@ var Emails = class {
|
|
|
45
45
|
return this.client.request("GET", `/api/emails/${encodeURIComponent(id)}`);
|
|
46
46
|
}
|
|
47
47
|
};
|
|
48
|
+
var Templates = class {
|
|
49
|
+
constructor(client) {
|
|
50
|
+
this.client = client;
|
|
51
|
+
}
|
|
52
|
+
client;
|
|
53
|
+
/** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */
|
|
54
|
+
async list() {
|
|
55
|
+
const res = await this.client.request("GET", "/api/templates");
|
|
56
|
+
return res.error ? res : { data: res.data.data, error: null };
|
|
57
|
+
}
|
|
58
|
+
/** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */
|
|
59
|
+
async preview(template, data) {
|
|
60
|
+
return this.client.request("POST", "/api/templates/preview", {
|
|
61
|
+
template,
|
|
62
|
+
...data !== void 0 ? { data } : {}
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
};
|
|
48
66
|
var Sendhive = class {
|
|
49
67
|
emails;
|
|
68
|
+
templates;
|
|
50
69
|
apiKey;
|
|
51
70
|
baseUrl;
|
|
52
71
|
constructor(apiKey, options = {}) {
|
|
@@ -55,6 +74,7 @@ var Sendhive = class {
|
|
|
55
74
|
if (!baseUrl) throw new Error("Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.");
|
|
56
75
|
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
57
76
|
this.emails = new Emails(this);
|
|
77
|
+
this.templates = new Templates(this);
|
|
58
78
|
}
|
|
59
79
|
/** @internal */
|
|
60
80
|
async request(method, path, body) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n Email,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveOptions,\n} from './types'\n\nexport type {\n Email,\n EmailEvent,\n EmailTag,\n Recipients,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveErrorFix,\n SendhiveOptions,\n TemplateData,\n} from './types'\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined\n}\n\n/** Optional peer: only loaded when the caller passes `react`. */\nasync function renderReact(element: unknown): Promise<string> {\n const specifier = '@react-email/render'\n let mod: { render?: (el: unknown) => string | Promise<string> }\n try {\n mod = await import(/* @vite-ignore */ specifier)\n } catch {\n throw new Error('The `react` option needs the optional peer dependency @react-email/render.')\n }\n if (!mod.render) throw new Error('@react-email/render has no `render` export.')\n return mod.render(element)\n}\n\nclass Emails {\n constructor(private readonly client: Sendhive) {}\n\n async send(options: SendEmailOptions): Promise<Result<SendEmailResponse>> {\n const { replyTo, react, ...rest } = options\n let html = rest.html\n if (react !== undefined) {\n try {\n html = await renderReact(react)\n } catch (err) {\n return {\n data: null,\n error: { statusCode: 422, name: 'validation_error', message: (err as Error).message },\n }\n }\n }\n const body = {\n ...rest,\n ...(html !== undefined ? { html } : {}),\n ...(replyTo !== undefined ? { reply_to: replyTo } : {}),\n }\n return this.client.request<SendEmailResponse>('POST', '/api/emails', body)\n }\n\n async get(id: string): Promise<Result<Email>> {\n return this.client.request<Email>('GET', `/api/emails/${encodeURIComponent(id)}`)\n }\n}\n\nexport class Sendhive {\n readonly emails: Emails\n private readonly apiKey: string | undefined\n private readonly baseUrl: string\n\n constructor(apiKey?: string, options: SendhiveOptions = {}) {\n this.apiKey = apiKey ?? env('SENDHIVE_API_KEY')\n // No default host: an API key must never be sent to a server the caller did not choose.\n const baseUrl = options.baseUrl ?? env('SENDHIVE_BASE_URL')\n if (!baseUrl) throw new Error('Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.')\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\n this.emails = new Emails(this)\n }\n\n /** @internal */\n async request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>> {\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`\n if (body !== undefined) headers['Content-Type'] = 'application/json'\n\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n } catch (err) {\n return {\n data: null,\n error: {\n statusCode: 0,\n name: 'network_error',\n message: err instanceof Error ? err.message : String(err),\n },\n }\n }\n\n let json: unknown\n try {\n json = await res.json()\n } catch {\n json = null\n }\n\n if (!res.ok) {\n const e = (json ?? {}) as Partial<SendhiveError>\n return {\n data: null,\n error: {\n statusCode: e.statusCode ?? res.status,\n name: e.name ?? 'application_error',\n message: e.message ?? (res.statusText || 'Unexpected response'),\n ...(e.fix ? { fix: e.fix } : {}),\n },\n }\n }\n return { data: json as T, error: null }\n }\n}\n\nexport default Sendhive\n"],"mappings":";
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type {\n Email,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveOptions,\n TemplateData,\n TemplateList,\n TemplatePreview,\n TemplateSummary,\n} from './types'\n\nexport type {\n Email,\n EmailEvent,\n EmailTag,\n Recipients,\n Result,\n SendEmailOptions,\n SendEmailResponse,\n SendhiveError,\n SendhiveErrorFix,\n SendhiveOptions,\n TemplateData,\n TemplateList,\n TemplatePreview,\n TemplateSummary,\n} from './types'\n\nfunction env(name: string): string | undefined {\n return typeof process !== 'undefined' ? process.env?.[name] : undefined\n}\n\n/** Optional peer: only loaded when the caller passes `react`. */\nasync function renderReact(element: unknown): Promise<string> {\n const specifier = '@react-email/render'\n let mod: { render?: (el: unknown) => string | Promise<string> }\n try {\n mod = await import(/* @vite-ignore */ specifier)\n } catch {\n throw new Error('The `react` option needs the optional peer dependency @react-email/render.')\n }\n if (!mod.render) throw new Error('@react-email/render has no `render` export.')\n return mod.render(element)\n}\n\nclass Emails {\n constructor(private readonly client: Sendhive) {}\n\n async send(options: SendEmailOptions): Promise<Result<SendEmailResponse>> {\n const { replyTo, react, ...rest } = options\n let html = rest.html\n if (react !== undefined) {\n try {\n html = await renderReact(react)\n } catch (err) {\n return {\n data: null,\n error: { statusCode: 422, name: 'validation_error', message: (err as Error).message },\n }\n }\n }\n const body = {\n ...rest,\n ...(html !== undefined ? { html } : {}),\n ...(replyTo !== undefined ? { reply_to: replyTo } : {}),\n }\n return this.client.request<SendEmailResponse>('POST', '/api/emails', body)\n }\n\n async get(id: string): Promise<Result<Email>> {\n return this.client.request<Email>('GET', `/api/emails/${encodeURIComponent(id)}`)\n }\n}\n\nclass Templates {\n constructor(private readonly client: Sendhive) {}\n\n /** Your templates plus the ready-made ones (their `slug` starts with `preset:`). */\n async list(): Promise<Result<TemplateSummary[]>> {\n const res = await this.client.request<TemplateList>('GET', '/api/templates')\n return res.error ? res : { data: res.data.data, error: null }\n }\n\n /** Draws a template (slug, id or `preset:<id>`) with `data`; values you leave out show as `{{name}}`. */\n async preview(template: string, data?: TemplateData): Promise<Result<TemplatePreview>> {\n return this.client.request<TemplatePreview>('POST', '/api/templates/preview', {\n template,\n ...(data !== undefined ? { data } : {}),\n })\n }\n}\n\nexport class Sendhive {\n readonly emails: Emails\n readonly templates: Templates\n private readonly apiKey: string | undefined\n private readonly baseUrl: string\n\n constructor(apiKey?: string, options: SendhiveOptions = {}) {\n this.apiKey = apiKey ?? env('SENDHIVE_API_KEY')\n // No default host: an API key must never be sent to a server the caller did not choose.\n const baseUrl = options.baseUrl ?? env('SENDHIVE_BASE_URL')\n if (!baseUrl) throw new Error('Sendhive: set `baseUrl` or SENDHIVE_BASE_URL to your Sendhive server.')\n this.baseUrl = baseUrl.replace(/\\/+$/, '')\n this.emails = new Emails(this)\n this.templates = new Templates(this)\n }\n\n /** @internal */\n async request<T>(method: 'GET' | 'POST', path: string, body?: unknown): Promise<Result<T>> {\n const headers: Record<string, string> = { Accept: 'application/json' }\n if (this.apiKey) headers.Authorization = `Bearer ${this.apiKey}`\n if (body !== undefined) headers['Content-Type'] = 'application/json'\n\n let res: Response\n try {\n res = await fetch(`${this.baseUrl}${path}`, {\n method,\n headers,\n body: body === undefined ? undefined : JSON.stringify(body),\n })\n } catch (err) {\n return {\n data: null,\n error: {\n statusCode: 0,\n name: 'network_error',\n message: err instanceof Error ? err.message : String(err),\n },\n }\n }\n\n let json: unknown\n try {\n json = await res.json()\n } catch {\n json = null\n }\n\n if (!res.ok) {\n const e = (json ?? {}) as Partial<SendhiveError>\n return {\n data: null,\n error: {\n statusCode: e.statusCode ?? res.status,\n name: e.name ?? 'application_error',\n message: e.message ?? (res.statusText || 'Unexpected response'),\n ...(e.fix ? { fix: e.fix } : {}),\n },\n }\n }\n return { data: json as T, error: null }\n }\n}\n\nexport default Sendhive\n"],"mappings":"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","names":[]}
|