@cruxstack/node-sdk
Version:
A Node.js SDK for event tracking, user traits lookup, validation, and automatic retry with queueing.
182 lines (181 loc) • 6.78 kB
JavaScript
import axios, { AxiosError } from "axios";
export async function sendEvent(event) {
try {
// Construct outgoing payload with all available fields
const payload = {
cid: event.cid,
cna: event.cna,
uid: event.uid,
eid: event.eid,
dtm: event.dtm,
e: event.e,
ev: event.ev,
tna: event.tna,
tv: event.tv,
// Optional fields - only include if they exist
...(event.sid && { sid: event.sid }),
...(event.ua && { ua: event.ua }),
...(event.sh && { sh: event.sh }),
...(event.sw && { sw: event.sw }),
...(event.l && { l: event.l }),
...(event.p && { p: event.p }),
...(event.an !== undefined && { an: event.an }),
...(event.vh && { vh: event.vh }),
...(event.vw && { vw: event.vw }),
...(event.pt && { pt: event.pt }),
...(event.pu && { pu: event.pu }),
...(event.pp && { pp: event.pp }),
...(event.pd && { pd: event.pd }),
...(event.pl && { pl: event.pl }),
...(event.pr && { pr: event.pr }),
...(event.ip && { ip: event.ip }),
...(event.tz && { tz: event.tz }),
};
// Wrap payload in events array
const eventsPayload = {
events: [payload],
};
const response = await axios.post("https://api.cruxstack.com/api/v1/events", eventsPayload, {
headers: {
"Content-Type": "application/json",
"x-client-id": event.client_id,
},
});
if (response.status >= 200 && response.status < 300) {
console.log(`Event sent successfully: ${event.eid}`);
}
else {
throw new Error(`API returned status ${response.status}`);
}
}
catch (error) {
if (error instanceof AxiosError) {
const message = error.response?.data?.message || error.message;
console.error(`Failed to send event: ${message}`);
throw new Error(`Failed to send event: ${message}`);
}
throw new Error(`Failed to send event: ${error instanceof Error ? error.message : "Unknown error"}`);
}
}
export async function getUserTraitsFromAPI(clientId, customerId, request) {
try {
// Add validation for customerId
if (!customerId || customerId === "undefined") {
throw new Error("customerId is required for getUserTraits");
}
const response = await axios.post(`https://api.cruxstack.com/backend/v1/users/traits?customerId=${encodeURIComponent(customerId)}`, request, {
headers: {
"Content-Type": "application/json",
"x-client-id": clientId,
},
});
if (response.status >= 200 && response.status < 300) {
return {
success: true,
data: response.data,
message: "User traits retrieved successfully",
};
}
else {
throw new Error(`API returned status ${response.status}`);
}
}
catch (error) {
if (error instanceof AxiosError) {
const message = error.response?.data?.message || error.message;
console.error(`Failed to get user traits: ${message}`);
return {
success: false,
error: `Failed to get user traits: ${message}`,
};
}
return {
success: false,
error: `Failed to get user traits: ${error instanceof Error ? error.message : "Unknown error"}`,
};
}
}
export async function sendBulkEvents(events) {
try {
if (!events || events.length === 0) {
throw new Error('Events array cannot be empty');
}
if (events.length > 1000) {
throw new Error('Maximum 1000 events per batch');
}
// Validate all events have the same client_id
const clientId = events[0].client_id;
for (const event of events) {
if (event.client_id !== clientId) {
throw new Error('All events in a batch must have the same client_id');
}
}
// Transform all events to API format
const payloads = events.map(event => ({
cid: event.cid,
cna: event.cna,
uid: event.uid,
eid: event.eid,
dtm: event.dtm,
e: event.e,
ev: event.ev,
tna: event.tna,
tv: event.tv,
...(event.sid && { sid: event.sid }),
...(event.ua && { ua: event.ua }),
...(event.sh && { sh: event.sh }),
...(event.sw && { sw: event.sw }),
...(event.l && { l: event.l }),
...(event.p && { p: event.p }),
...(event.an !== undefined && { an: event.an }),
...(event.vh && { vh: event.vh }),
...(event.vw && { vw: event.vw }),
...(event.pt && { pt: event.pt }),
...(event.pu && { pu: event.pu }),
...(event.pp && { pp: event.pp }),
...(event.pd && { pd: event.pd }),
...(event.pl && { pl: event.pl }),
...(event.pr && { pr: event.pr }),
...(event.ip && { ip: event.ip }),
...(event.tz && { tz: event.tz }),
}));
const eventsPayload = {
events: payloads
};
const response = await axios.post("https://api.cruxstack.com/api/v1/events", eventsPayload, {
headers: {
"Content-Type": "application/json",
"x-client-id": clientId,
},
});
if (response.status >= 200 && response.status < 300) {
console.log(`Bulk events sent successfully: ${events.length} events`);
return {
success: true,
processed: events.length,
failed: 0
};
}
else {
throw new Error(`API returned status ${response.status}`);
}
}
catch (error) {
if (error instanceof AxiosError) {
const message = error.response?.data?.message || error.message;
console.error(`Failed to send bulk events: ${message}`);
return {
success: false,
processed: 0,
failed: events.length,
errors: [message]
};
}
return {
success: false,
processed: 0,
failed: events.length,
errors: [error instanceof Error ? error.message : "Unknown error"]
};
}
}