sendrly
Version:
Official Sendrly TypeScript/JavaScript SDK - Simple, type-safe email automation for developers
275 lines (271 loc) • 9.49 kB
JavaScript
var __typeError = (msg) => {
throw TypeError(msg);
};
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
// src/validation.ts
import { z } from "zod";
var EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
var eventPayloadSchema = z.object({
email: z.string().min(1, "Email is required").transform((email) => email.toLowerCase().trim()).pipe(z.string().regex(EMAIL_REGEX, "Invalid email format")),
event: z.string().min(1, "Event name is required"),
marketing_opt_out: z.boolean().optional().default(false),
contact_properties: z.record(z.unknown()).optional().default({}),
event_properties: z.record(z.unknown()).optional().default({})
}).strict();
var mapToEdgePayload = (payload) => ({
contact: {
email: payload.email,
marketing_opt_out: payload.marketing_opt_out,
properties: payload.contact_properties
},
event: {
name: payload.event,
properties: payload.event_properties
}
});
var validatePayload = (payload) => {
return eventPayloadSchema.parse(payload);
};
// src/types.ts
var SendrlyError = class extends Error {
constructor(message, code) {
super(message);
this.name = "SendrlyError";
this.code = code;
}
};
// src/index.ts
import { ZodError } from "zod";
var _apiKey, _debug, _baseUrl, _Sendrly_instances, log_fn;
var Sendrly = class {
constructor(config) {
__privateAdd(this, _Sendrly_instances);
__privateAdd(this, _apiKey);
__privateAdd(this, _debug);
__privateAdd(this, _baseUrl, "https://stebgknkomdhjikpcytk.supabase.co/functions/v1");
__privateSet(this, _apiKey, config.apiKey);
__privateSet(this, _debug, config.debug ?? false);
if (__privateGet(this, _debug)) {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Initialized with config:", {
apiKey: __privateGet(this, _apiKey),
debug: __privateGet(this, _debug)
});
}
if (!__privateGet(this, _apiKey)) {
throw new SendrlyError("API key is required", "INVALID_CONFIG");
}
}
/**
* Send an event for a contact
* @example
* // Simple event tracking
* await sendrly.sendEvent({
* email: 'sarah@startup.com',
* event: 'user.welcome'
* })
*
* // Event with properties
* await sendrly.sendEvent({
* email: 'john@company.com',
* event: 'order.completed',
* contact_properties: {
* name: 'John Smith',
* plan: 'enterprise'
* },
* event_properties: {
* order_id: 'ORD-123',
* amount: 499.99
* }
* })
*/
async sendEvent(payload) {
try {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Sending event with payload:", payload);
const validatedPayload = validatePayload(payload);
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Payload validated successfully:", validatedPayload);
const response = await fetch(`${__privateGet(this, _baseUrl)}/event`, {
method: "POST",
headers: {
"Content-Type": "application/json",
apikey: __privateGet(this, _apiKey)
},
body: JSON.stringify(mapToEdgePayload(validatedPayload))
});
const data = await response.json();
if (!response.ok || !data.success) {
throw new SendrlyError(
data.error || "Failed to send event",
response.status === 401 ? "INVALID_API_KEY" : "API_ERROR"
);
}
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Event sent successfully:", payload);
} catch (error) {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Error sending event:", error);
if (error instanceof SendrlyError || error instanceof ZodError) {
throw error;
}
throw new SendrlyError(
error instanceof Error ? error.message : "An unknown error occurred",
"UNKNOWN_ERROR"
);
}
}
/**
* Get a contact by email address
* @example
* // Get contact details
* const contact = await sendrly.getContact('sarah@startup.com')
* console.log(contact.properties.name) // 'Sarah'
*
* // Handle non-existent contact
* try {
* const contact = await sendrly.getContact('unknown@email.com')
* } catch (error) {
* if (error.code === 'NOT_FOUND') {
* console.log('Contact does not exist')
* }
* }
*/
async getContact(email) {
try {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Getting contact:", email);
const response = await fetch(
`${__privateGet(this, _baseUrl)}/find-contact?email=${encodeURIComponent(email)}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
apikey: __privateGet(this, _apiKey)
}
}
);
const data = await response.json();
if (!response.ok || !data.success) {
throw new SendrlyError(
data.error || "Failed to get contact",
response.status === 404 ? "NOT_FOUND" : response.status === 401 ? "INVALID_API_KEY" : "API_ERROR"
);
}
return data.contact;
} catch (error) {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Error getting contact:", error);
if (error instanceof SendrlyError) {
throw error;
}
throw new SendrlyError(
error instanceof Error ? error.message : "An unknown error occurred",
"UNKNOWN_ERROR"
);
}
}
/**
* List all events with a specific name
* @example
* // List all signup events
* const signups = await sendrly.listEvents('user.signup')
* console.log(signups[0].event_properties.source)
*
* // Process completed orders
* const orders = await sendrly.listEvents('order.completed')
* const totalRevenue = orders.reduce((sum, order) =>
* sum + order.event_properties.amount, 0
* )
*/
async listEvents(eventName) {
try {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Listing events:", eventName);
const response = await fetch(
`${__privateGet(this, _baseUrl)}/get-event?event=${encodeURIComponent(eventName)}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
apikey: __privateGet(this, _apiKey)
}
}
);
const data = await response.json();
if (!response.ok || !data.success) {
throw new SendrlyError(
data.error || "Failed to list events",
response.status === 401 ? "INVALID_API_KEY" : "API_ERROR"
);
}
return data.events;
} catch (error) {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Error listing events:", error);
if (error instanceof SendrlyError) {
throw error;
}
throw new SendrlyError(
error instanceof Error ? error.message : "An unknown error occurred",
"UNKNOWN_ERROR"
);
}
}
/**
* Delete a contact and all associated data
* @example
* // Delete a contact
* await sendrly.deleteContact('sarah@startup.com')
*
* // Handle non-existent contact
* try {
* await sendrly.deleteContact('unknown@email.com')
* } catch (error) {
* if (error.code === 'NOT_FOUND') {
* console.log('Contact already deleted')
* }
* }
*/
async deleteContact(email) {
try {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Deleting contact:", email);
const response = await fetch(
`${__privateGet(this, _baseUrl)}/delete-contact?email=${encodeURIComponent(email)}`,
{
method: "DELETE",
headers: {
"Content-Type": "application/json",
apikey: __privateGet(this, _apiKey)
}
}
);
const data = await response.json();
if (!response.ok || !data.success) {
throw new SendrlyError(
data.error || "Failed to delete contact",
response.status === 404 ? "NOT_FOUND" : response.status === 401 ? "INVALID_API_KEY" : "API_ERROR"
);
}
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Contact deleted successfully");
} catch (error) {
__privateMethod(this, _Sendrly_instances, log_fn).call(this, "Error deleting contact:", error);
if (error instanceof SendrlyError) {
throw error;
}
throw new SendrlyError(
error instanceof Error ? error.message : "An unknown error occurred",
"UNKNOWN_ERROR"
);
}
}
};
_apiKey = new WeakMap();
_debug = new WeakMap();
_baseUrl = new WeakMap();
_Sendrly_instances = new WeakSet();
log_fn = function(message, data) {
if (__privateGet(this, _debug)) {
console.log(`[Sendrly] ${message}`, data);
}
};
var index_default = Sendrly;
export {
Sendrly,
index_default as default
};