@sendmailos/sdk 1.0.0 → 1.1.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 +119 -1
- package/dist/index.d.mts +88 -1
- package/dist/index.d.ts +88 -1
- package/dist/index.js +379 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +377 -1
- package/dist/index.mjs.map +1 -1
- package/dist/react/index.d.mts +159 -1
- package/dist/react/index.d.ts +159 -1
- package/dist/react/index.js +408 -0
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +407 -2
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -434,6 +434,382 @@ var SendMailOS = class {
|
|
|
434
434
|
}
|
|
435
435
|
};
|
|
436
436
|
|
|
437
|
+
// src/pixel.ts
|
|
438
|
+
var OPT_OUT_KEY = "smp_opt_out";
|
|
439
|
+
var IDENTIFIED_EMAIL_KEY = "smp_identified_email";
|
|
440
|
+
var SendmailPixel = class {
|
|
441
|
+
constructor(config) {
|
|
442
|
+
this.initialized = false;
|
|
443
|
+
this.rules = [];
|
|
444
|
+
this.identifiedEmail = null;
|
|
445
|
+
this.config = {
|
|
446
|
+
endpoint: "https://sendmailos.com/api/pixel/track",
|
|
447
|
+
cookieName: "sm_anon_id",
|
|
448
|
+
debug: false,
|
|
449
|
+
respectDNT: true,
|
|
450
|
+
...config
|
|
451
|
+
};
|
|
452
|
+
this.anonymousId = this.getOrSetAnonymousId();
|
|
453
|
+
this.identifiedEmail = this.getStoredEmail();
|
|
454
|
+
}
|
|
455
|
+
init() {
|
|
456
|
+
if (this.initialized) return;
|
|
457
|
+
if (typeof window === "undefined") {
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
if (this.isOptedOut()) {
|
|
461
|
+
this.log("Tracking disabled (user opted out)");
|
|
462
|
+
return;
|
|
463
|
+
}
|
|
464
|
+
if (this.config.respectDNT && this.isDNTEnabled()) {
|
|
465
|
+
this.log("Tracking disabled (Do Not Track enabled)");
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
this.initialized = true;
|
|
469
|
+
this.checkUrlForSubscriber();
|
|
470
|
+
this.loadRules();
|
|
471
|
+
this.pageView();
|
|
472
|
+
this.setupFormListeners();
|
|
473
|
+
this.setupHistoryListeners();
|
|
474
|
+
this.setupDataAttributeTracking();
|
|
475
|
+
this.log("Pixel initialized with Token:", this.config.token);
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Opt out of all tracking
|
|
479
|
+
*/
|
|
480
|
+
optOut() {
|
|
481
|
+
if (typeof localStorage !== "undefined") {
|
|
482
|
+
localStorage.setItem(OPT_OUT_KEY, "true");
|
|
483
|
+
}
|
|
484
|
+
this.log("User opted out of tracking");
|
|
485
|
+
}
|
|
486
|
+
/**
|
|
487
|
+
* Opt back in to tracking
|
|
488
|
+
*/
|
|
489
|
+
optIn() {
|
|
490
|
+
if (typeof localStorage !== "undefined") {
|
|
491
|
+
localStorage.removeItem(OPT_OUT_KEY);
|
|
492
|
+
}
|
|
493
|
+
if (!this.initialized && typeof window !== "undefined") {
|
|
494
|
+
this.init();
|
|
495
|
+
}
|
|
496
|
+
this.log("User opted in to tracking");
|
|
497
|
+
}
|
|
498
|
+
/**
|
|
499
|
+
* Check if user has opted out
|
|
500
|
+
*/
|
|
501
|
+
isOptedOut() {
|
|
502
|
+
if (typeof localStorage === "undefined") return false;
|
|
503
|
+
return localStorage.getItem(OPT_OUT_KEY) === "true";
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Reset identity (e.g., on logout)
|
|
507
|
+
*/
|
|
508
|
+
reset() {
|
|
509
|
+
this.identifiedEmail = null;
|
|
510
|
+
if (typeof localStorage !== "undefined") {
|
|
511
|
+
localStorage.removeItem(IDENTIFIED_EMAIL_KEY);
|
|
512
|
+
}
|
|
513
|
+
this.anonymousId = crypto.randomUUID();
|
|
514
|
+
this.setCookie(this.config.cookieName, this.anonymousId, 365);
|
|
515
|
+
this.log("Identity reset");
|
|
516
|
+
}
|
|
517
|
+
/**
|
|
518
|
+
* Get current visitor/anonymous ID
|
|
519
|
+
*/
|
|
520
|
+
getVisitorId() {
|
|
521
|
+
return this.anonymousId;
|
|
522
|
+
}
|
|
523
|
+
/**
|
|
524
|
+
* Get identified email address
|
|
525
|
+
*/
|
|
526
|
+
getIdentifiedEmail() {
|
|
527
|
+
return this.identifiedEmail;
|
|
528
|
+
}
|
|
529
|
+
track(eventName, properties = {}) {
|
|
530
|
+
this.sendEvent("track", {
|
|
531
|
+
event_name: eventName,
|
|
532
|
+
properties
|
|
533
|
+
});
|
|
534
|
+
}
|
|
535
|
+
identify(email, traits = {}) {
|
|
536
|
+
if (this.isOptedOut()) return;
|
|
537
|
+
this.identifiedEmail = email;
|
|
538
|
+
this.storeEmail(email);
|
|
539
|
+
this.sendEvent("identify", {
|
|
540
|
+
email,
|
|
541
|
+
traits
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
pageView() {
|
|
545
|
+
this.track("page_view", {
|
|
546
|
+
path: window.location.pathname,
|
|
547
|
+
title: document.title,
|
|
548
|
+
referrer: document.referrer,
|
|
549
|
+
url: window.location.href
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
// --- INTERNAL HELPERS ---
|
|
553
|
+
getOrSetAnonymousId() {
|
|
554
|
+
if (typeof document === "undefined") return "";
|
|
555
|
+
let id = this.getCookie(this.config.cookieName);
|
|
556
|
+
if (!id) {
|
|
557
|
+
id = crypto.randomUUID();
|
|
558
|
+
this.setCookie(this.config.cookieName, id, 365);
|
|
559
|
+
}
|
|
560
|
+
return id;
|
|
561
|
+
}
|
|
562
|
+
sendEvent(type, payload) {
|
|
563
|
+
if (typeof window === "undefined") return;
|
|
564
|
+
const smartContext = this.detectContext();
|
|
565
|
+
const body = {
|
|
566
|
+
type,
|
|
567
|
+
token: this.config.token,
|
|
568
|
+
// Send Token
|
|
569
|
+
anonymous_id: this.anonymousId,
|
|
570
|
+
url: window.location.href,
|
|
571
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
572
|
+
...payload
|
|
573
|
+
};
|
|
574
|
+
const context = {
|
|
575
|
+
userAgent: navigator.userAgent,
|
|
576
|
+
locale: navigator.language,
|
|
577
|
+
screen: { width: window.screen.width, height: window.screen.height },
|
|
578
|
+
search: window.location.search,
|
|
579
|
+
title: document.title,
|
|
580
|
+
referrer: document.referrer,
|
|
581
|
+
...smartContext
|
|
582
|
+
// Merge smart context
|
|
583
|
+
};
|
|
584
|
+
const finalBody = { ...body, context };
|
|
585
|
+
if (navigator.sendBeacon && type === "track") {
|
|
586
|
+
const blob = new Blob([JSON.stringify(finalBody)], { type: "application/json" });
|
|
587
|
+
navigator.sendBeacon(this.config.endpoint, blob);
|
|
588
|
+
} else {
|
|
589
|
+
fetch(this.config.endpoint, {
|
|
590
|
+
method: "POST",
|
|
591
|
+
headers: { "Content-Type": "application/json" },
|
|
592
|
+
body: JSON.stringify(finalBody),
|
|
593
|
+
keepalive: true
|
|
594
|
+
}).catch((err) => {
|
|
595
|
+
if (this.config.debug) console.error("[Pixel Error]", err);
|
|
596
|
+
});
|
|
597
|
+
}
|
|
598
|
+
this.log(`Event Sent [${type}]`, body);
|
|
599
|
+
}
|
|
600
|
+
// Call this after init to load rules
|
|
601
|
+
async loadRules() {
|
|
602
|
+
if (typeof window === "undefined") return;
|
|
603
|
+
try {
|
|
604
|
+
const res = await fetch(`${this.config.endpoint?.replace("/track", "")}/rules?token=${this.config.token}`);
|
|
605
|
+
if (res.ok) {
|
|
606
|
+
const data = await res.json();
|
|
607
|
+
this.rules = data.rules || [];
|
|
608
|
+
}
|
|
609
|
+
} catch (e) {
|
|
610
|
+
}
|
|
611
|
+
}
|
|
612
|
+
/**
|
|
613
|
+
* Smart Auto-Detection of Page Type & Context
|
|
614
|
+
* Uses Dynamic Rules + Static Heuristics
|
|
615
|
+
*/
|
|
616
|
+
detectContext() {
|
|
617
|
+
if (typeof document === "undefined") return {};
|
|
618
|
+
const path = window.location.pathname.toLowerCase();
|
|
619
|
+
let context = {
|
|
620
|
+
page_type: "general",
|
|
621
|
+
// Default
|
|
622
|
+
topics: []
|
|
623
|
+
};
|
|
624
|
+
for (const rule of this.rules) {
|
|
625
|
+
let matched = false;
|
|
626
|
+
try {
|
|
627
|
+
if (rule.match_type === "exact" && path === rule.url_pattern) matched = true;
|
|
628
|
+
else if (rule.match_type === "contains" && path.includes(rule.url_pattern)) matched = true;
|
|
629
|
+
else if (rule.match_type === "regex" && new RegExp(rule.url_pattern).test(path)) matched = true;
|
|
630
|
+
} catch (e) {
|
|
631
|
+
}
|
|
632
|
+
if (matched) {
|
|
633
|
+
context.page_type = rule.page_type;
|
|
634
|
+
if (rule.selectors) {
|
|
635
|
+
for (const [key, selector] of Object.entries(rule.selectors)) {
|
|
636
|
+
const el = document.querySelector(selector);
|
|
637
|
+
if (el) {
|
|
638
|
+
const val = el.value || el.textContent || el.getAttribute("content");
|
|
639
|
+
if (val) context[key] = val.trim();
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return context;
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
if (path.match(/\/(cart|basket|bag)/)) context.page_type = "cart";
|
|
647
|
+
else if (path.match(/\/(checkout|payment|order)/)) context.page_type = "checkout";
|
|
648
|
+
else if (path.match(/\/(product|item|p)\//)) context.page_type = "product";
|
|
649
|
+
else if (path.match(/\/(category|c|collection)\//)) context.page_type = "category";
|
|
650
|
+
else if (path.match(/\/(blog|article|post|news)/)) context.page_type = "content";
|
|
651
|
+
else if (path.match(/\/(login|signin)/)) context.page_type = "auth";
|
|
652
|
+
else if (path.match(/\/(signup|register)/)) context.page_type = "auth";
|
|
653
|
+
else if (path.match(/\/(pricing|plans)/)) context.page_type = "pricing";
|
|
654
|
+
else if (path.match(/\/(thank-you|confirmation|success)/)) context.page_type = "purchase_success";
|
|
655
|
+
const ogType = document.querySelector('meta[property="og:type"]')?.getAttribute("content");
|
|
656
|
+
if (ogType === "product") {
|
|
657
|
+
context.page_type = "product";
|
|
658
|
+
const price = document.querySelector('meta[property="product:price:amount"]')?.getAttribute("content");
|
|
659
|
+
if (price) context.product_price = price;
|
|
660
|
+
const currency = document.querySelector('meta[property="product:price:currency"]')?.getAttribute("content");
|
|
661
|
+
if (currency) context.currency = currency;
|
|
662
|
+
}
|
|
663
|
+
if (document.querySelector(".cart-total") || document.querySelector("#cart-summary")) {
|
|
664
|
+
context.page_type = "cart";
|
|
665
|
+
}
|
|
666
|
+
if (document.querySelector("#card-element") || document.querySelector('input[name="card_number"]')) {
|
|
667
|
+
context.page_type = "checkout";
|
|
668
|
+
}
|
|
669
|
+
const text = document.body.innerText.toLowerCase().slice(0, 2e3);
|
|
670
|
+
if (text.includes("out of stock")) context.stock_status = "out_of_stock";
|
|
671
|
+
if (text.includes("limited time")) context.urgency = "high";
|
|
672
|
+
return context;
|
|
673
|
+
}
|
|
674
|
+
setupFormListeners() {
|
|
675
|
+
if (typeof document === "undefined") return;
|
|
676
|
+
document.addEventListener("submit", (e) => {
|
|
677
|
+
const form = e.target;
|
|
678
|
+
if (!form) return;
|
|
679
|
+
const emailInput = form.querySelector('input[type="email"]');
|
|
680
|
+
if (emailInput && emailInput.value) {
|
|
681
|
+
this.log("Auto-detected email form submission", emailInput.value);
|
|
682
|
+
this.identify(emailInput.value);
|
|
683
|
+
}
|
|
684
|
+
}, true);
|
|
685
|
+
}
|
|
686
|
+
setupHistoryListeners() {
|
|
687
|
+
if (typeof window === "undefined") return;
|
|
688
|
+
const pushState = history.pushState;
|
|
689
|
+
history.pushState = (...args) => {
|
|
690
|
+
pushState.apply(history, args);
|
|
691
|
+
this.pageView();
|
|
692
|
+
};
|
|
693
|
+
window.addEventListener("popstate", () => {
|
|
694
|
+
this.pageView();
|
|
695
|
+
});
|
|
696
|
+
}
|
|
697
|
+
// --- COOKIE UTILS ---
|
|
698
|
+
setCookie(name, value, days) {
|
|
699
|
+
const d = /* @__PURE__ */ new Date();
|
|
700
|
+
d.setTime(d.getTime() + days * 24 * 60 * 60 * 1e3);
|
|
701
|
+
const expires = "expires=" + d.toUTCString();
|
|
702
|
+
document.cookie = name + "=" + value + ";" + expires + ";path=/;SameSite=Lax";
|
|
703
|
+
}
|
|
704
|
+
getCookie(name) {
|
|
705
|
+
const nameEQ = name + "=";
|
|
706
|
+
const ca = document.cookie.split(";");
|
|
707
|
+
for (let i = 0; i < ca.length; i++) {
|
|
708
|
+
let c = ca[i];
|
|
709
|
+
while (c.charAt(0) == " ") c = c.substring(1, c.length);
|
|
710
|
+
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
|
|
711
|
+
}
|
|
712
|
+
return null;
|
|
713
|
+
}
|
|
714
|
+
log(...args) {
|
|
715
|
+
if (this.config.debug) {
|
|
716
|
+
console.log("[SendmailPixel]", ...args);
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
isDNTEnabled() {
|
|
720
|
+
if (typeof navigator === "undefined") return false;
|
|
721
|
+
return navigator.doNotTrack === "1" || window.doNotTrack === "1";
|
|
722
|
+
}
|
|
723
|
+
checkUrlForSubscriber() {
|
|
724
|
+
if (typeof window === "undefined") return;
|
|
725
|
+
const params = new URLSearchParams(window.location.search);
|
|
726
|
+
const subscriberEmail = params.get("smp_email");
|
|
727
|
+
const subscriberId = params.get("smp_sub");
|
|
728
|
+
if (subscriberEmail) {
|
|
729
|
+
try {
|
|
730
|
+
const email = atob(subscriberEmail);
|
|
731
|
+
if (this.isValidEmail(email)) {
|
|
732
|
+
this.identify(email);
|
|
733
|
+
}
|
|
734
|
+
} catch {
|
|
735
|
+
if (this.isValidEmail(subscriberEmail)) {
|
|
736
|
+
this.identify(subscriberEmail);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
} else if (subscriberId) {
|
|
740
|
+
this.track("email_link_clicked", { subscriber_id: subscriberId });
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
setupDataAttributeTracking() {
|
|
744
|
+
if (typeof document === "undefined") return;
|
|
745
|
+
document.addEventListener("click", (e) => {
|
|
746
|
+
const target = e.target;
|
|
747
|
+
const tracked = target.closest("[data-smp-track]");
|
|
748
|
+
if (tracked) {
|
|
749
|
+
const eventName = tracked.getAttribute("data-smp-track");
|
|
750
|
+
const properties = {};
|
|
751
|
+
Array.from(tracked.attributes).forEach((attr) => {
|
|
752
|
+
if (attr.name.startsWith("data-smp-track-") && attr.name !== "data-smp-track") {
|
|
753
|
+
const propName = attr.name.replace("data-smp-track-", "").replace(/-/g, "_");
|
|
754
|
+
properties[propName] = attr.value;
|
|
755
|
+
}
|
|
756
|
+
});
|
|
757
|
+
if (eventName) {
|
|
758
|
+
this.track(eventName, properties);
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
getStoredEmail() {
|
|
764
|
+
if (typeof localStorage === "undefined") return null;
|
|
765
|
+
return localStorage.getItem(IDENTIFIED_EMAIL_KEY);
|
|
766
|
+
}
|
|
767
|
+
storeEmail(email) {
|
|
768
|
+
if (typeof localStorage !== "undefined") {
|
|
769
|
+
localStorage.setItem(IDENTIFIED_EMAIL_KEY, email);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
isValidEmail(email) {
|
|
773
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
var Pixel = SendmailPixel;
|
|
777
|
+
function createGlobalPixel(config) {
|
|
778
|
+
const pixel = new SendmailPixel(config);
|
|
779
|
+
if (typeof window !== "undefined") {
|
|
780
|
+
const smpFunction = (method, ...args) => {
|
|
781
|
+
switch (method) {
|
|
782
|
+
case "track":
|
|
783
|
+
pixel.track(args[0], args[1]);
|
|
784
|
+
return void 0;
|
|
785
|
+
case "identify":
|
|
786
|
+
pixel.identify(args[0], args[1]);
|
|
787
|
+
return void 0;
|
|
788
|
+
case "page":
|
|
789
|
+
pixel.pageView();
|
|
790
|
+
return void 0;
|
|
791
|
+
case "optOut":
|
|
792
|
+
pixel.optOut();
|
|
793
|
+
return void 0;
|
|
794
|
+
case "optIn":
|
|
795
|
+
pixel.optIn();
|
|
796
|
+
return void 0;
|
|
797
|
+
case "isOptedOut":
|
|
798
|
+
return pixel.isOptedOut();
|
|
799
|
+
case "reset":
|
|
800
|
+
pixel.reset();
|
|
801
|
+
return void 0;
|
|
802
|
+
default:
|
|
803
|
+
console.warn(`[SendmailPixel] Unknown method: ${method}`);
|
|
804
|
+
return void 0;
|
|
805
|
+
}
|
|
806
|
+
};
|
|
807
|
+
window.smp = smpFunction;
|
|
808
|
+
}
|
|
809
|
+
pixel.init();
|
|
810
|
+
return pixel;
|
|
811
|
+
}
|
|
812
|
+
|
|
437
813
|
// src/utils/webhook.ts
|
|
438
814
|
function verifyWebhookSignature(params) {
|
|
439
815
|
const { payload, signature, timestamp, secret, tolerance = 300 } = params;
|
|
@@ -526,11 +902,14 @@ function constructWebhookEvent(payload, headers, secret) {
|
|
|
526
902
|
|
|
527
903
|
exports.AuthenticationError = AuthenticationError;
|
|
528
904
|
exports.NotFoundError = NotFoundError;
|
|
905
|
+
exports.Pixel = Pixel;
|
|
529
906
|
exports.RateLimitError = RateLimitError;
|
|
530
907
|
exports.SendMailOS = SendMailOS;
|
|
531
908
|
exports.SendMailOSError = SendMailOSError;
|
|
909
|
+
exports.SendmailPixel = SendmailPixel;
|
|
532
910
|
exports.ValidationError = ValidationError;
|
|
533
911
|
exports.constructWebhookEvent = constructWebhookEvent;
|
|
912
|
+
exports.createGlobalPixel = createGlobalPixel;
|
|
534
913
|
exports.default = SendMailOS;
|
|
535
914
|
exports.verifyWebhookSignature = verifyWebhookSignature;
|
|
536
915
|
exports.verifyWebhookSignatureAsync = verifyWebhookSignatureAsync;
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/errors.ts","../src/resources/emails.ts","../src/resources/subscribers.ts","../src/resources/campaigns.ts","../src/resources/domains.ts","../src/client.ts","../src/utils/webhook.ts"],"names":["crypto"],"mappings":";;;;;;;;;;;;AAIO,IAAM,eAAA,GAAN,MAAM,gBAAA,SAAwB,KAAA,CAAM;AAAA,EAKzC,WAAA,CACE,OAAA,EACA,IAAA,EACA,UAAA,EACA,UAAA,EACA;AACA,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAClB,IAAA,IAAA,CAAK,UAAA,GAAa,UAAA;AAGlB,IAAA,IAAI,MAAM,iBAAA,EAAmB;AAC3B,MAAA,KAAA,CAAM,iBAAA,CAAkB,MAAM,gBAAe,CAAA;AAAA,IAC/C;AAAA,EACF;AAAA;AAAA,EAGA,IAAI,WAAA,GAAuB;AACzB,IAAA,OAAO,IAAA,CAAK,UAAA,KAAe,GAAA,IAAO,IAAA,CAAK,UAAA,IAAc,GAAA;AAAA,EACvD;AACF;AAEO,IAAM,mBAAA,GAAN,cAAkC,eAAA,CAAgB;AAAA,EACvD,WAAA,CAAY,UAAkB,iBAAA,EAAmB;AAC/C,IAAA,KAAA,CAAM,OAAA,EAAS,gBAAgB,GAAG,CAAA;AAClC,IAAA,IAAA,CAAK,IAAA,GAAO,qBAAA;AAAA,EACd;AACF;AAEO,IAAM,eAAA,GAAN,cAA8B,eAAA,CAAgB;AAAA,EACnD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAA,EAAS,oBAAoB,GAAG,CAAA;AACtC,IAAA,IAAA,CAAK,IAAA,GAAO,iBAAA;AAAA,EACd;AACF;AAEO,IAAM,cAAA,GAAN,cAA6B,eAAA,CAAgB;AAAA,EAClD,WAAA,CAAY,SAAiB,UAAA,EAAoB;AAC/C,IAAA,KAAA,CAAM,OAAA,EAAS,cAAA,EAAgB,GAAA,EAAK,UAAU,CAAA;AAC9C,IAAA,IAAA,CAAK,IAAA,GAAO,gBAAA;AAAA,EACd;AACF;AAEO,IAAM,aAAA,GAAN,cAA4B,eAAA,CAAgB;AAAA,EACjD,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAA,EAAS,aAAa,GAAG,CAAA;AAC/B,IAAA,IAAA,CAAK,IAAA,GAAO,eAAA;AAAA,EACd;AACF;;;ACtDO,IAAM,iBAAN,MAAqB;AAAA,EAC1B,YACU,OAAA,EACR;AADQ,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgBH,MAAM,KAAK,MAAA,EAAsD;AAC/D,IAAA,OAAO,IAAA,CAAK,QAA2B,OAAA,EAAS;AAAA,MAC9C,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,IAAI,MAAA,CAAO,EAAA;AAAA,QACX,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,WAAW,MAAA,CAAO,QAAA;AAAA,QAClB,YAAY,MAAA,CAAO,SAAA;AAAA,QACnB,WAAW,MAAA,CAAO,SAAA;AAAA,QAClB,IAAA,EAAM,OAAO,IAAA,IAAQ;AAAA,OACtB;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcA,MAAM,aAAa,MAAA,EAOY;AAC7B,IAAA,OAAO,KAAK,IAAA,CAAK;AAAA,MACf,IAAI,MAAA,CAAO,EAAA;AAAA,MACX,OAAA,EAAS,OAAO,OAAA,IAAW,EAAA;AAAA,MAC3B,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,IAAA,EAAM;AAAA,KACP,CAAA;AAAA,EACH;AACF,CAAA;;;AC3DO,IAAM,sBAAN,MAA0B;AAAA,EAC/B,YACU,OAAA,EACR;AADQ,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcH,MAAM,OAAO,MAAA,EAAoE;AAC/E,IAAA,OAAO,IAAA,CAAK,QAAkC,cAAA,EAAgB;AAAA,MAC5D,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,OAAO,MAAA,CAAO,KAAA;AAAA,QACd,YAAY,MAAA,CAAO,SAAA;AAAA,QACnB,WAAW,MAAA,CAAO,QAAA;AAAA,QAClB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,WAAW,MAAA,CAAO;AAAA,OACnB;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaA,MAAM,IAAA,CAAK,MAAA,GAAiC,EAAC,EAAqC;AAChF,IAAA,MAAM,YAAA,GAAe,IAAI,eAAA,EAAgB;AACzC,IAAA,IAAI,MAAA,CAAO,OAAO,YAAA,CAAa,GAAA,CAAI,SAAS,MAAA,CAAO,MAAA,CAAO,KAAK,CAAC,CAAA;AAChE,IAAA,IAAI,MAAA,CAAO,QAAQ,YAAA,CAAa,GAAA,CAAI,UAAU,MAAA,CAAO,MAAA,CAAO,MAAM,CAAC,CAAA;AAEnE,IAAA,MAAM,KAAA,GAAQ,aAAa,QAAA,EAAS;AACpC,IAAA,MAAM,QAAA,GAAW,KAAA,GAAQ,CAAA,aAAA,EAAgB,KAAK,CAAA,CAAA,GAAK,cAAA;AAEnD,IAAA,OAAO,IAAA,CAAK,QAAiC,QAAA,EAAU;AAAA,MACrD,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,YAAA,EAA6E;AACrF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,aAAA,EAAgB,YAAY,CAAA,CAAA,EAAI;AAAA,MAClD,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,MAAA,CACJ,YAAA,EACA,MAAA,EACmC;AACnC,IAAA,OAAO,IAAA,CAAK,OAAA,CAAkC,CAAA,aAAA,EAAgB,YAAY,CAAA,CAAA,EAAI;AAAA,MAC5E,MAAA,EAAQ,OAAA;AAAA,MACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,YAAY,MAAA,CAAO,SAAA;AAAA,QACnB,WAAW,MAAA,CAAO,QAAA;AAAA,QAClB,MAAM,MAAA,CAAO;AAAA,OACd;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAA,CACJ,KAAA,EACA,MAAA,EACmC;AAEnC,IAAA,OAAO,KAAK,MAAA,CAAO;AAAA,MACjB,KAAA;AAAA,MACA,GAAG;AAAA,KACJ,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,YAAA,EAAqD;AAChE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,aAAA,EAAgB,YAAY,CAAA,CAAA,EAAI;AAAA,MAClD,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAA,CAAQ,YAAA,EAAsB,IAAA,EAAmD;AACrF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAkC,CAAA,aAAA,EAAgB,YAAY,CAAA,KAAA,CAAA,EAAS;AAAA,MACjF,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,MAAM;AAAA,KAC9B,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAA,CAAW,YAAA,EAAsB,IAAA,EAAmD;AACxF,IAAA,OAAO,IAAA,CAAK,OAAA,CAAkC,CAAA,aAAA,EAAgB,YAAY,CAAA,KAAA,CAAA,EAAS;AAAA,MACjF,MAAA,EAAQ,QAAA;AAAA,MACR,IAAA,EAAM,IAAA,CAAK,SAAA,CAAU,EAAE,MAAM;AAAA,KAC9B,CAAA;AAAA,EACH;AACF,CAAA;;;AChIO,IAAM,oBAAN,MAAwB;AAAA,EAC7B,YACU,OAAA,EACR;AADQ,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBH,MAAM,KAAK,MAAA,EAA4D;AACrE,IAAA,OAAO,IAAA,CAAK,QAA8B,iBAAA,EAAmB;AAAA,MAC3D,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,SAAS,MAAA,CAAO,OAAA;AAAA,QAChB,WAAW,MAAA,CAAO,QAAA;AAAA,QAClB,YAAY,MAAA,CAAO,SAAA;AAAA,QACnB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,YAAY,MAAA,CAAO,UAAA;AAAA,QACnB,MAAM,MAAA,CAAO,IAAA;AAAA,QACb,WAAW,MAAA,CAAO;AAAA,OACnB;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,aAAa,MAAA,EAQe;AAChC,IAAA,OAAO,KAAK,IAAA,CAAK;AAAA,MACf,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,SAAS,MAAA,CAAO,OAAA;AAAA,MAChB,UAAU,MAAA,CAAO,QAAA;AAAA,MACjB,WAAW,MAAA,CAAO,SAAA;AAAA,MAClB,YAAY,MAAA,CAAO,UAAA;AAAA,MACnB,MAAM,MAAA,CAAO,IAAA;AAAA,MACb,WAAW,MAAA,CAAO;AAAA,KACnB,CAAA;AAAA,EACH;AACF,CAAA;;;ACrDO,IAAM,kBAAN,MAAsB;AAAA,EAC3B,YACU,OAAA,EACR;AADQ,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeH,MAAM,OAAO,MAAA,EAA4D;AACvE,IAAA,OAAO,IAAA,CAAK,QAA8B,UAAA,EAAY;AAAA,MACpD,MAAA,EAAQ,MAAA;AAAA,MACR,IAAA,EAAM,KAAK,SAAA,CAAU;AAAA,QACnB,QAAQ,MAAA,CAAO;AAAA,OAChB;AAAA,KACF,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAA,GAAqC;AACzC,IAAA,OAAO,IAAA,CAAK,QAA6B,UAAA,EAAY;AAAA,MACnD,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,IAAI,QAAA,EAAiE;AACzE,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAA,EAAI;AAAA,MAC1C,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,QAAA,EAAiE;AAC5E,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,QAAQ,CAAA,OAAA,CAAA,EAAW;AAAA,MACjD,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,QAAA,EAAiD;AAC5D,IAAA,OAAO,IAAA,CAAK,OAAA,CAAQ,CAAA,SAAA,EAAY,QAAQ,CAAA,CAAA,EAAI;AAAA,MAC1C,MAAA,EAAQ;AAAA,KACT,CAAA;AAAA,EACH;AACF,CAAA;;;ACjEA,IAAM,gBAAA,GAAmB,mCAAA;AACzB,IAAM,eAAA,GAAkB,GAAA;AACxB,IAAM,WAAA,GAAc,OAAA;AAyBb,IAAM,aAAN,MAAiB;AAAA,EAetB,WAAA,CAAY,MAAA,EAAgB,OAAA,GAA6B,EAAC,EAAG;AAE3D,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,MAAM,qBAAqB,CAAA;AAAA,IACvC;AAEA,IAAA,IAAI,CAAC,OAAO,UAAA,CAAW,UAAU,KAAK,CAAC,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA,EAAG;AACpE,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAEA,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,UAAU,OAAA,CAAQ,OAAA,EAAS,OAAA,CAAQ,KAAA,EAAO,EAAE,CAAA,IAAK,gBAAA;AACtD,IAAA,IAAA,CAAK,OAAA,GAAU,QAAQ,OAAA,IAAW,eAAA;AAClC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA,CAAQ,KAAA,IAAS,UAAA,CAAW,KAAA;AAG3C,IAAA,IAAI,CAAC,KAAK,OAAA,EAAS;AACjB,MAAA,MAAM,IAAI,KAAA;AAAA,QACR;AAAA,OACF;AAAA,IACF;AAGA,IAAA,MAAM,YAAA,GAAe,IAAA,CAAK,OAAA,CAAQ,IAAA,CAAK,IAAI,CAAA;AAC3C,IAAA,IAAA,CAAK,MAAA,GAAS,IAAI,cAAA,CAAe,YAAY,CAAA;AAC7C,IAAA,IAAA,CAAK,WAAA,GAAc,IAAI,mBAAA,CAAoB,YAAY,CAAA;AACvD,IAAA,IAAA,CAAK,SAAA,GAAY,IAAI,iBAAA,CAAkB,YAAY,CAAA;AACnD,IAAA,IAAA,CAAK,OAAA,GAAU,IAAI,eAAA,CAAgB,YAAY,CAAA;AAAA,EACjD;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,OAAA,CAAW,QAAA,EAAkB,OAAA,GAAuB,EAAC,EAAe;AAChF,IAAA,MAAM,GAAA,GAAM,CAAA,EAAG,IAAA,CAAK,OAAO,GAAG,QAAQ,CAAA,CAAA;AAEtC,IAAA,MAAM,UAAA,GAAa,IAAI,eAAA,EAAgB;AACvC,IAAA,MAAM,YAAY,UAAA,CAAW,MAAM,WAAW,KAAA,EAAM,EAAG,KAAK,OAAO,CAAA;AAEnE,IAAA,IAAI;AACF,MAAA,MAAM,QAAA,GAAW,MAAM,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK;AAAA,QACvC,GAAG,OAAA;AAAA,QACH,QAAQ,UAAA,CAAW,MAAA;AAAA,QACnB,OAAA,EAAS;AAAA,UACP,eAAA,EAAiB,CAAA,OAAA,EAAU,IAAA,CAAK,MAAM,CAAA,CAAA;AAAA,UACtC,cAAA,EAAgB,kBAAA;AAAA,UAChB,YAAA,EAAc,kBAAkB,WAAW,CAAA,CAAA;AAAA,UAC3C,eAAA,EAAiB,WAAA;AAAA,UACjB,GAAG,OAAA,CAAQ;AAAA;AACb,OACD,CAAA;AAED,MAAA,YAAA,CAAa,SAAS,CAAA;AAGtB,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,MAAM,UAAA,GAAa,SAAS,QAAA,CAAS,OAAA,CAAQ,IAAI,aAAa,CAAA,IAAK,MAAM,EAAE,CAAA;AAC3E,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,aAAA,CAAc,QAAQ,CAAA;AACnD,QAAA,MAAM,IAAI,cAAA;AAAA,UACR,WAAW,KAAA,IAAS,qBAAA;AAAA,UACpB;AAAA,SACF;AAAA,MACF;AAGA,MAAA,IAAI,QAAA,CAAS,WAAW,GAAA,EAAK;AAC3B,QAAA,MAAM,IAAI,mBAAA,EAAoB;AAAA,MAChC;AAGA,MAAA,IAAI,CAAC,SAAS,EAAA,EAAI;AAChB,QAAA,MAAM,SAAA,GAAY,MAAM,IAAA,CAAK,aAAA,CAAc,QAAQ,CAAA;AACnD,QAAA,MAAM,IAAI,eAAA;AAAA,UACR,SAAA,EAAW,KAAA,IAAS,CAAA,2BAAA,EAA8B,QAAA,CAAS,MAAM,CAAA,CAAA;AAAA,UACjE,WAAW,IAAA,IAAQ,eAAA;AAAA,UACnB,QAAA,CAAS;AAAA,SACX;AAAA,MACF;AAEA,MAAA,OAAO,SAAS,IAAA,EAAK;AAAA,IACvB,SAAS,KAAA,EAAO;AACd,MAAA,YAAA,CAAa,SAAS,CAAA;AAEtB,MAAA,IAAI,iBAAiB,eAAA,EAAiB;AACpC,QAAA,MAAM,KAAA;AAAA,MACR;AAEA,MAAA,IAAI,KAAA,YAAiB,KAAA,IAAS,KAAA,CAAM,IAAA,KAAS,YAAA,EAAc;AACzD,QAAA,MAAM,IAAI,eAAA,CAAgB,iBAAA,EAAmB,SAAA,EAAW,GAAG,CAAA;AAAA,MAC7D;AAEA,MAAA,MAAM,IAAI,eAAA;AAAA,QACR,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,eAAA;AAAA,QACzC,eAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAc,cAAc,QAAA,EAA8C;AACxE,IAAA,IAAI;AACF,MAAA,OAAO,MAAM,SAAS,IAAA,EAAK;AAAA,IAC7B,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,IAAA;AAAA,IACT;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAAA,GAAsB;AACxB,IAAA,OAAO,IAAA,CAAK,MAAA,CAAO,UAAA,CAAW,UAAU,CAAA;AAAA,EAC1C;AAAA;AAAA;AAAA;AAAA,EAKA,WAAW,OAAA,GAAkB;AAC3B,IAAA,OAAO,WAAA;AAAA,EACT;AACF;;;ACjIO,SAAS,uBAAuB,MAAA,EAAsC;AAC3E,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,WAAW,MAAA,EAAQ,SAAA,GAAY,KAAI,GAAI,MAAA;AAGnE,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,aAAa,CAAC,SAAA,IAAa,CAAC,MAAA,EAAQ;AACnD,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AAC3C,EAAA,IAAI,KAAA,CAAM,YAAY,CAAA,EAAG;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,YAAA;AAC5C,EAAA,IAAI,MAAM,SAAA,EAAW;AACnB,IAAA,OAAA,CAAQ,IAAA,CAAK,yCAAA,EAA2C,GAAA,EAAK,SAAS,CAAA;AACtE,IAAA,OAAO,KAAA;AAAA,EACT;AAGA,EAAA,IAAI,OAAO,UAAA,CAAW,MAAA,KAAW,WAAA,IAAe,QAAA,IAAY,WAAW,MAAA,EAAQ;AAG7E,IAAA,OAAO,UAAA,CAAW,OAAA,EAAS,SAAA,EAAW,SAAA,EAAW,MAAM,CAAA;AAAA,EACzD;AAEA,EAAA,OAAO,UAAA,CAAW,OAAA,EAAS,SAAA,EAAW,SAAA,EAAW,MAAM,CAAA;AACzD;AAKA,eAAsB,4BAA4B,MAAA,EAA+C;AAC/F,EAAA,MAAM,EAAE,OAAA,EAAS,SAAA,EAAW,WAAW,MAAA,EAAQ,SAAA,GAAY,KAAI,GAAI,MAAA;AAEnE,EAAA,IAAI,CAAC,OAAA,IAAW,CAAC,aAAa,CAAC,SAAA,IAAa,CAAC,MAAA,EAAQ;AACnD,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,YAAA,GAAe,QAAA,CAAS,SAAA,EAAW,EAAE,CAAA;AAC3C,EAAA,IAAI,KAAA,CAAM,YAAY,CAAA,EAAG;AACvB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,MAAM,IAAA,CAAK,KAAA,CAAM,KAAK,GAAA,EAAI,GAAI,GAAI,CAAA,GAAI,YAAA;AAC5C,EAAA,IAAI,MAAM,SAAA,EAAW;AACnB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAU,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AAGvC,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAChC,EAAA,MAAM,GAAA,GAAM,MAAM,MAAA,CAAO,MAAA,CAAO,SAAA;AAAA,IAC9B,KAAA;AAAA,IACA,OAAA,CAAQ,OAAO,MAAM,CAAA;AAAA,IACrB,EAAE,IAAA,EAAM,MAAA,EAAQ,IAAA,EAAM,SAAA,EAAU;AAAA,IAChC,KAAA;AAAA,IACA,CAAC,MAAM;AAAA,GACT;AAEA,EAAA,MAAM,cAAA,GAAiB,MAAM,MAAA,CAAO,MAAA,CAAO,IAAA;AAAA,IACzC,MAAA;AAAA,IACA,GAAA;AAAA,IACA,OAAA,CAAQ,OAAO,OAAO;AAAA,GACxB;AAEA,EAAA,MAAM,WAAA,GAAc,YAAY,cAAc,CAAA;AAG9C,EAAA,OAAO,eAAA,CAAgB,WAAW,WAAW,CAAA;AAC/C;AAIA,SAAS,UAAA,CAAW,OAAA,EAAiB,SAAA,EAAmB,SAAA,EAAmB,MAAA,EAAyB;AAClG,EAAA,IAAI;AAEF,IAAA,MAAMA,OAAAA,GAAS,UAAQ,QAAQ,CAAA;AAC/B,IAAA,MAAM,OAAA,GAAU,CAAA,EAAG,SAAS,CAAA,CAAA,EAAI,OAAO,CAAA,CAAA;AACvC,IAAA,MAAM,WAAA,GAAcA,OAAAA,CACjB,UAAA,CAAW,QAAA,EAAU,MAAM,EAC3B,MAAA,CAAO,OAAO,CAAA,CACd,MAAA,CAAO,KAAK,CAAA;AAGf,IAAA,OAAOA,OAAAA,CAAO,eAAA;AAAA,MACZ,MAAA,CAAO,KAAK,SAAS,CAAA;AAAA,MACrB,MAAA,CAAO,KAAK,WAAW;AAAA,KACzB;AAAA,EACF,CAAA,CAAA,MAAQ;AAEN,IAAA,OAAA,CAAQ,KAAK,+DAA+D,CAAA;AAC5E,IAAA,OAAO,KAAA;AAAA,EACT;AACF;AAEA,SAAS,YAAY,MAAA,EAA6B;AAChD,EAAA,OAAO,MAAM,IAAA,CAAK,IAAI,WAAW,MAAM,CAAC,EACrC,GAAA,CAAI,CAAA,CAAA,KAAK,EAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CACxC,KAAK,EAAE,CAAA;AACZ;AAEA,SAAS,eAAA,CAAgB,GAAW,CAAA,EAAoB;AACtD,EAAA,IAAI,CAAA,CAAE,MAAA,KAAW,CAAA,CAAE,MAAA,EAAQ;AACzB,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,IAAI,MAAA,GAAS,CAAA;AACb,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,CAAA,CAAE,QAAQ,CAAA,EAAA,EAAK;AACjC,IAAA,MAAA,IAAU,EAAE,UAAA,CAAW,CAAC,CAAA,GAAI,CAAA,CAAE,WAAW,CAAC,CAAA;AAAA,EAC5C;AACA,EAAA,OAAO,MAAA,KAAW,CAAA;AACpB;AAKO,SAAS,qBAAA,CACd,OAAA,EACA,OAAA,EACA,MAAA,EACG;AACH,EAAA,MAAM,UAAU,sBAAA,CAAuB;AAAA,IACrC,OAAA;AAAA,IACA,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB,WAAW,OAAA,CAAQ,SAAA;AAAA,IACnB;AAAA,GACD,CAAA;AAED,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,EAC7C;AAEA,EAAA,OAAO,IAAA,CAAK,MAAM,OAAO,CAAA;AAC3B","file":"index.js","sourcesContent":["/**\n * Custom error classes for SendMailOS SDK\n */\n\nexport class SendMailOSError extends Error {\n public readonly code: string;\n public readonly statusCode: number;\n public readonly retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode: number,\n retryAfter?: number\n ) {\n super(message);\n this.name = 'SendMailOSError';\n this.code = code;\n this.statusCode = statusCode;\n this.retryAfter = retryAfter;\n \n // Maintains proper stack trace for where error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, SendMailOSError);\n }\n }\n\n /** Whether this error is retryable (rate limit or server error) */\n get isRetryable(): boolean {\n return this.statusCode === 429 || this.statusCode >= 500;\n }\n}\n\nexport class AuthenticationError extends SendMailOSError {\n constructor(message: string = 'Invalid API key') {\n super(message, 'UNAUTHORIZED', 401);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ValidationError extends SendMailOSError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\nexport class RateLimitError extends SendMailOSError {\n constructor(message: string, retryAfter: number) {\n super(message, 'RATE_LIMITED', 429, retryAfter);\n this.name = 'RateLimitError';\n }\n}\n\nexport class NotFoundError extends SendMailOSError {\n constructor(message: string) {\n super(message, 'NOT_FOUND', 404);\n this.name = 'NotFoundError';\n }\n}\n","import type { SendEmailRequest, SendEmailResponse } from '../types';\n\n/**\n * Emails resource for sending transactional emails\n */\nexport class EmailsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Send a transactional email\n * \n * @example\n * ```ts\n * const result = await client.emails.send({\n * to: 'user@example.com',\n * fromName: 'Your Company',\n * fromEmail: 'hello@yourcompany.com',\n * subject: 'Welcome!',\n * html: '<h1>Hello!</h1>'\n * });\n * ```\n */\n async send(params: SendEmailRequest): Promise<SendEmailResponse> {\n return this.request<SendEmailResponse>('/send', {\n method: 'POST',\n body: JSON.stringify({\n to: params.to,\n subject: params.subject,\n html: params.html,\n templateId: params.templateId,\n from_name: params.fromName,\n from_email: params.fromEmail,\n variables: params.variables,\n type: params.type || 'transactional',\n }),\n });\n }\n\n /**\n * Send email using a template\n * \n * @example\n * ```ts\n * const result = await client.emails.sendTemplate({\n * to: 'user@example.com',\n * templateId: 'tmpl_welcome',\n * variables: { firstName: 'John' }\n * });\n * ```\n */\n async sendTemplate(params: {\n to: string;\n templateId: string;\n fromName?: string;\n fromEmail?: string;\n subject?: string;\n variables?: Record<string, unknown>;\n }): Promise<SendEmailResponse> {\n return this.send({\n to: params.to,\n subject: params.subject || '',\n templateId: params.templateId,\n fromName: params.fromName,\n fromEmail: params.fromEmail,\n variables: params.variables,\n type: 'transactional',\n });\n }\n}\n","import type {\n Subscriber,\n CreateSubscriberRequest,\n CreateSubscriberResponse,\n ListSubscribersRequest,\n ListSubscribersResponse,\n} from '../types';\n\n/**\n * Subscribers resource for managing email contacts\n */\nexport class SubscribersResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Create or update a subscriber (upsert)\n * \n * @example\n * ```ts\n * const { subscriber } = await client.subscribers.create({\n * email: 'user@example.com',\n * firstName: 'John',\n * tags: ['newsletter', 'premium']\n * });\n * ```\n */\n async create(params: CreateSubscriberRequest): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>('/subscribers', {\n method: 'POST',\n body: JSON.stringify({\n email: params.email,\n first_name: params.firstName,\n last_name: params.lastName,\n tags: params.tags,\n domain_id: params.domainId,\n }),\n });\n }\n\n /**\n * List all subscribers with pagination\n * \n * @example\n * ```ts\n * const { subscribers, total } = await client.subscribers.list({\n * limit: 50,\n * offset: 0\n * });\n * ```\n */\n async list(params: ListSubscribersRequest = {}): Promise<ListSubscribersResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n \n const query = searchParams.toString();\n const endpoint = query ? `/subscribers?${query}` : '/subscribers';\n \n return this.request<ListSubscribersResponse>(endpoint, {\n method: 'GET',\n });\n }\n\n /**\n * Get a single subscriber by ID\n */\n async get(subscriberId: string): Promise<{ success: boolean; subscriber: Subscriber }> {\n return this.request(`/subscribers/${subscriberId}`, {\n method: 'GET',\n });\n }\n\n /**\n * Update a subscriber by ID\n */\n async update(\n subscriberId: string,\n params: Partial<CreateSubscriberRequest>\n ): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}`, {\n method: 'PATCH',\n body: JSON.stringify({\n first_name: params.firstName,\n last_name: params.lastName,\n tags: params.tags,\n }),\n });\n }\n\n /**\n * Update a subscriber by email address\n */\n async updateByEmail(\n email: string,\n params: Partial<Omit<CreateSubscriberRequest, 'email'>>\n ): Promise<CreateSubscriberResponse> {\n // Upsert via create endpoint\n return this.create({\n email,\n ...params,\n });\n }\n\n /**\n * Delete/unsubscribe a subscriber\n */\n async delete(subscriberId: string): Promise<{ success: boolean }> {\n return this.request(`/subscribers/${subscriberId}`, {\n method: 'DELETE',\n });\n }\n\n /**\n * Add tags to a subscriber\n */\n async addTags(subscriberId: string, tags: string[]): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}/tags`, {\n method: 'POST',\n body: JSON.stringify({ tags }),\n });\n }\n\n /**\n * Remove tags from a subscriber\n */\n async removeTags(subscriberId: string, tags: string[]): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}/tags`, {\n method: 'DELETE',\n body: JSON.stringify({ tags }),\n });\n }\n}\n","import type { SendCampaignRequest, SendCampaignResponse } from '../types';\n\n/**\n * Campaigns resource for bulk email sending\n */\nexport class CampaignsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Send a campaign to subscribers\n * \n * @example\n * ```ts\n * const result = await client.campaigns.send({\n * name: 'January Newsletter',\n * subject: 'What\\'s new this month',\n * fromName: 'Your Company',\n * fromEmail: 'news@yourcompany.com',\n * html: '<h1>Hello {{first_name}}!</h1>',\n * tags: ['newsletter', 'active']\n * });\n * ```\n */\n async send(params: SendCampaignRequest): Promise<SendCampaignResponse> {\n return this.request<SendCampaignResponse>('/campaigns/send', {\n method: 'POST',\n body: JSON.stringify({\n name: params.name,\n subject: params.subject,\n from_name: params.fromName,\n from_email: params.fromEmail,\n html: params.html,\n templateId: params.templateId,\n tags: params.tags,\n variables: params.variables,\n }),\n });\n }\n\n /**\n * Send campaign using a saved template\n */\n async sendTemplate(params: {\n name?: string;\n templateId: string;\n subject: string;\n fromName: string;\n fromEmail: string;\n tags?: string[];\n variables?: Record<string, unknown>;\n }): Promise<SendCampaignResponse> {\n return this.send({\n name: params.name,\n subject: params.subject,\n fromName: params.fromName,\n fromEmail: params.fromEmail,\n templateId: params.templateId,\n tags: params.tags,\n variables: params.variables,\n });\n }\n}\n","import type {\n Domain,\n CreateDomainRequest,\n CreateDomainResponse,\n ListDomainsResponse,\n} from '../types';\n\n/**\n * Domains resource for managing sending domains\n */\nexport class DomainsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Add a new sending domain\n * Returns DKIM tokens and DNS records for verification\n * \n * @example\n * ```ts\n * const { domain } = await client.domains.create({\n * domain: 'yourcompany.com'\n * });\n * \n * console.log('Add these DNS records:', domain.dnsRecords);\n * ```\n */\n async create(params: CreateDomainRequest): Promise<CreateDomainResponse> {\n return this.request<CreateDomainResponse>('/domains', {\n method: 'POST',\n body: JSON.stringify({\n domain: params.domain,\n }),\n });\n }\n\n /**\n * List all domains for the organization\n */\n async list(): Promise<ListDomainsResponse> {\n return this.request<ListDomainsResponse>('/domains', {\n method: 'GET',\n });\n }\n\n /**\n * Get a single domain by ID\n */\n async get(domainId: string): Promise<{ success: boolean; domain: Domain }> {\n return this.request(`/domains/${domainId}`, {\n method: 'GET',\n });\n }\n\n /**\n * Verify a domain (trigger DNS check)\n */\n async verify(domainId: string): Promise<{ success: boolean; domain: Domain }> {\n return this.request(`/domains/${domainId}/verify`, {\n method: 'POST',\n });\n }\n\n /**\n * Delete a domain\n */\n async delete(domainId: string): Promise<{ success: boolean }> {\n return this.request(`/domains/${domainId}`, {\n method: 'DELETE',\n });\n }\n}\n","import type { SendMailOSOptions, ApiError } from './types';\nimport { SendMailOSError, AuthenticationError, RateLimitError } from './utils/errors';\nimport { EmailsResource } from './resources/emails';\nimport { SubscribersResource } from './resources/subscribers';\nimport { CampaignsResource } from './resources/campaigns';\nimport { DomainsResource } from './resources/domains';\n\nconst DEFAULT_BASE_URL = 'https://api.sendmailos.com/api/v1';\nconst DEFAULT_TIMEOUT = 30000;\nconst SDK_VERSION = '1.0.0';\n\n/**\n * SendMailOS SDK Client\n * \n * @example\n * ```ts\n * import { SendMailOS } from '@sendmailos/sdk';\n * \n * const client = new SendMailOS('sk_live_your_api_key');\n * \n * // Send an email\n * await client.emails.send({\n * to: 'user@example.com',\n * subject: 'Hello!',\n * html: '<h1>Welcome!</h1>'\n * });\n * \n * // Add a subscriber\n * await client.subscribers.create({\n * email: 'user@example.com',\n * tags: ['newsletter']\n * });\n * ```\n */\nexport class SendMailOS {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly fetchFn: typeof fetch;\n\n /** Email sending operations */\n public readonly emails: EmailsResource;\n /** Subscriber management */\n public readonly subscribers: SubscribersResource;\n /** Campaign operations */\n public readonly campaigns: CampaignsResource;\n /** Domain management */\n public readonly domains: DomainsResource;\n\n constructor(apiKey: string, options: SendMailOSOptions = {}) {\n // Validate API key format\n if (!apiKey) {\n throw new Error('API key is required');\n }\n \n if (!apiKey.startsWith('sk_live_') && !apiKey.startsWith('sk_test_')) {\n throw new Error(\n 'Invalid API key format. Keys should start with \"sk_live_\" or \"sk_test_\"'\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = options.baseUrl?.replace(/\\/$/, '') || DEFAULT_BASE_URL;\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n this.fetchFn = options.fetch || globalThis.fetch;\n\n // Ensure fetch is available\n if (!this.fetchFn) {\n throw new Error(\n 'fetch is not available. Please provide a fetch implementation or use Node.js 18+'\n );\n }\n\n // Initialize resources with bound request method\n const boundRequest = this.request.bind(this);\n this.emails = new EmailsResource(boundRequest);\n this.subscribers = new SubscribersResource(boundRequest);\n this.campaigns = new CampaignsResource(boundRequest);\n this.domains = new DomainsResource(boundRequest);\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n \n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await this.fetchFn(url, {\n ...options,\n signal: controller.signal,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `sendmailos-sdk/${SDK_VERSION}`,\n 'X-SDK-Version': SDK_VERSION,\n ...options.headers,\n },\n });\n\n clearTimeout(timeoutId);\n\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);\n const errorData = await this.safeParseJson(response);\n throw new RateLimitError(\n errorData?.error || 'Rate limit exceeded',\n retryAfter\n );\n }\n\n // Handle authentication errors\n if (response.status === 401) {\n throw new AuthenticationError();\n }\n\n // Handle other errors\n if (!response.ok) {\n const errorData = await this.safeParseJson(response) as ApiError | null;\n throw new SendMailOSError(\n errorData?.error || `Request failed with status ${response.status}`,\n errorData?.code || 'UNKNOWN_ERROR',\n response.status\n );\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof SendMailOSError) {\n throw error;\n }\n \n if (error instanceof Error && error.name === 'AbortError') {\n throw new SendMailOSError('Request timeout', 'TIMEOUT', 408);\n }\n \n throw new SendMailOSError(\n error instanceof Error ? error.message : 'Unknown error',\n 'NETWORK_ERROR',\n 0\n );\n }\n }\n\n private async safeParseJson(response: Response): Promise<ApiError | null> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n }\n\n /**\n * Check if the API key is valid (test mode only)\n */\n get isTestMode(): boolean {\n return this.apiKey.startsWith('sk_test_');\n }\n\n /**\n * Get the SDK version\n */\n static get version(): string {\n return SDK_VERSION;\n }\n}\n","/**\n * Webhook signature verification utilities\n * \n * IMPORTANT: This module uses timing-safe comparison to prevent timing attacks.\n */\n\nexport interface VerifyWebhookParams {\n /** Raw request body as string */\n payload: string;\n /** Value of X-SendMailOS-Signature header */\n signature: string;\n /** Value of X-SendMailOS-Timestamp header */\n timestamp: string;\n /** Your webhook signing secret */\n secret: string;\n /** Maximum age in seconds (default: 300 = 5 minutes) */\n tolerance?: number;\n}\n\n/**\n * Verify a webhook signature to ensure the request came from SendMailOS\n * \n * @example\n * ```ts\n * import { verifyWebhookSignature } from '@sendmailos/sdk';\n * \n * app.post('/webhooks', (req, res) => {\n * const isValid = verifyWebhookSignature({\n * payload: JSON.stringify(req.body),\n * signature: req.headers['x-sendmailos-signature'],\n * timestamp: req.headers['x-sendmailos-timestamp'],\n * secret: process.env.WEBHOOK_SECRET\n * });\n * \n * if (!isValid) {\n * return res.status(401).json({ error: 'Invalid signature' });\n * }\n * \n * // Process webhook...\n * });\n * ```\n */\nexport function verifyWebhookSignature(params: VerifyWebhookParams): boolean {\n const { payload, signature, timestamp, secret, tolerance = 300 } = params;\n\n // Validate inputs\n if (!payload || !signature || !timestamp || !secret) {\n return false;\n }\n\n // Prevent replay attacks - check timestamp age\n const timestampInt = parseInt(timestamp, 10);\n if (isNaN(timestampInt)) {\n return false;\n }\n\n const age = Math.floor(Date.now() / 1000) - timestampInt;\n if (age > tolerance) {\n console.warn('[SendMailOS] Webhook timestamp too old:', age, 'seconds');\n return false;\n }\n\n // Node.js crypto (server-side)\n if (typeof globalThis.crypto !== 'undefined' && 'subtle' in globalThis.crypto) {\n // Use SubtleCrypto for browser/edge environments\n // Note: This is synchronous verification, use verifyWebhookSignatureAsync for async\n return verifySync(payload, signature, timestamp, secret);\n }\n\n return verifySync(payload, signature, timestamp, secret);\n}\n\n/**\n * Async version of webhook verification (recommended for edge/browser)\n */\nexport async function verifyWebhookSignatureAsync(params: VerifyWebhookParams): Promise<boolean> {\n const { payload, signature, timestamp, secret, tolerance = 300 } = params;\n\n if (!payload || !signature || !timestamp || !secret) {\n return false;\n }\n\n const timestampInt = parseInt(timestamp, 10);\n if (isNaN(timestampInt)) {\n return false;\n }\n\n const age = Math.floor(Date.now() / 1000) - timestampInt;\n if (age > tolerance) {\n return false;\n }\n\n const message = `${timestamp}.${payload}`;\n \n // Use Web Crypto API\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n \n const signatureBytes = await crypto.subtle.sign(\n 'HMAC',\n key,\n encoder.encode(message)\n );\n \n const expectedSig = bufferToHex(signatureBytes);\n \n // Timing-safe comparison\n return timingSafeEqual(signature, expectedSig);\n}\n\n// ============ Internal Helpers ============\n\nfunction verifySync(payload: string, signature: string, timestamp: string, secret: string): boolean {\n try {\n // Try Node.js crypto first\n const crypto = require('crypto');\n const message = `${timestamp}.${payload}`;\n const expectedSig = crypto\n .createHmac('sha256', secret)\n .update(message)\n .digest('hex');\n \n // Use timing-safe comparison\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSig)\n );\n } catch {\n // Fallback for non-Node environments\n console.warn('[SendMailOS] Use verifyWebhookSignatureAsync for browser/edge');\n return false;\n }\n}\n\nfunction bufferToHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n \n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n\n/**\n * Construct a webhook event from raw request data\n */\nexport function constructWebhookEvent<T = unknown>(\n payload: string,\n headers: { signature: string; timestamp: string },\n secret: string\n): T {\n const isValid = verifyWebhookSignature({\n payload,\n signature: headers.signature,\n timestamp: headers.timestamp,\n secret,\n });\n\n if (!isValid) {\n throw new Error('Invalid webhook signature');\n }\n\n return JSON.parse(payload) as T;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/utils/errors.ts","../src/resources/emails.ts","../src/resources/subscribers.ts","../src/resources/campaigns.ts","../src/resources/domains.ts","../src/client.ts","../src/pixel.ts","../src/utils/webhook.ts"],"names":["crypto"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Custom error classes for SendMailOS SDK\n */\n\nexport class SendMailOSError extends Error {\n public readonly code: string;\n public readonly statusCode: number;\n public readonly retryAfter?: number;\n\n constructor(\n message: string,\n code: string,\n statusCode: number,\n retryAfter?: number\n ) {\n super(message);\n this.name = 'SendMailOSError';\n this.code = code;\n this.statusCode = statusCode;\n this.retryAfter = retryAfter;\n \n // Maintains proper stack trace for where error was thrown\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, SendMailOSError);\n }\n }\n\n /** Whether this error is retryable (rate limit or server error) */\n get isRetryable(): boolean {\n return this.statusCode === 429 || this.statusCode >= 500;\n }\n}\n\nexport class AuthenticationError extends SendMailOSError {\n constructor(message: string = 'Invalid API key') {\n super(message, 'UNAUTHORIZED', 401);\n this.name = 'AuthenticationError';\n }\n}\n\nexport class ValidationError extends SendMailOSError {\n constructor(message: string) {\n super(message, 'VALIDATION_ERROR', 400);\n this.name = 'ValidationError';\n }\n}\n\nexport class RateLimitError extends SendMailOSError {\n constructor(message: string, retryAfter: number) {\n super(message, 'RATE_LIMITED', 429, retryAfter);\n this.name = 'RateLimitError';\n }\n}\n\nexport class NotFoundError extends SendMailOSError {\n constructor(message: string) {\n super(message, 'NOT_FOUND', 404);\n this.name = 'NotFoundError';\n }\n}\n","import type { SendEmailRequest, SendEmailResponse } from '../types';\n\n/**\n * Emails resource for sending transactional emails\n */\nexport class EmailsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Send a transactional email\n * \n * @example\n * ```ts\n * const result = await client.emails.send({\n * to: 'user@example.com',\n * fromName: 'Your Company',\n * fromEmail: 'hello@yourcompany.com',\n * subject: 'Welcome!',\n * html: '<h1>Hello!</h1>'\n * });\n * ```\n */\n async send(params: SendEmailRequest): Promise<SendEmailResponse> {\n return this.request<SendEmailResponse>('/send', {\n method: 'POST',\n body: JSON.stringify({\n to: params.to,\n subject: params.subject,\n html: params.html,\n templateId: params.templateId,\n from_name: params.fromName,\n from_email: params.fromEmail,\n variables: params.variables,\n type: params.type || 'transactional',\n }),\n });\n }\n\n /**\n * Send email using a template\n * \n * @example\n * ```ts\n * const result = await client.emails.sendTemplate({\n * to: 'user@example.com',\n * templateId: 'tmpl_welcome',\n * variables: { firstName: 'John' }\n * });\n * ```\n */\n async sendTemplate(params: {\n to: string;\n templateId: string;\n fromName?: string;\n fromEmail?: string;\n subject?: string;\n variables?: Record<string, unknown>;\n }): Promise<SendEmailResponse> {\n return this.send({\n to: params.to,\n subject: params.subject || '',\n templateId: params.templateId,\n fromName: params.fromName,\n fromEmail: params.fromEmail,\n variables: params.variables,\n type: 'transactional',\n });\n }\n}\n","import type {\n Subscriber,\n CreateSubscriberRequest,\n CreateSubscriberResponse,\n ListSubscribersRequest,\n ListSubscribersResponse,\n} from '../types';\n\n/**\n * Subscribers resource for managing email contacts\n */\nexport class SubscribersResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Create or update a subscriber (upsert)\n * \n * @example\n * ```ts\n * const { subscriber } = await client.subscribers.create({\n * email: 'user@example.com',\n * firstName: 'John',\n * tags: ['newsletter', 'premium']\n * });\n * ```\n */\n async create(params: CreateSubscriberRequest): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>('/subscribers', {\n method: 'POST',\n body: JSON.stringify({\n email: params.email,\n first_name: params.firstName,\n last_name: params.lastName,\n tags: params.tags,\n domain_id: params.domainId,\n }),\n });\n }\n\n /**\n * List all subscribers with pagination\n * \n * @example\n * ```ts\n * const { subscribers, total } = await client.subscribers.list({\n * limit: 50,\n * offset: 0\n * });\n * ```\n */\n async list(params: ListSubscribersRequest = {}): Promise<ListSubscribersResponse> {\n const searchParams = new URLSearchParams();\n if (params.limit) searchParams.set('limit', String(params.limit));\n if (params.offset) searchParams.set('offset', String(params.offset));\n \n const query = searchParams.toString();\n const endpoint = query ? `/subscribers?${query}` : '/subscribers';\n \n return this.request<ListSubscribersResponse>(endpoint, {\n method: 'GET',\n });\n }\n\n /**\n * Get a single subscriber by ID\n */\n async get(subscriberId: string): Promise<{ success: boolean; subscriber: Subscriber }> {\n return this.request(`/subscribers/${subscriberId}`, {\n method: 'GET',\n });\n }\n\n /**\n * Update a subscriber by ID\n */\n async update(\n subscriberId: string,\n params: Partial<CreateSubscriberRequest>\n ): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}`, {\n method: 'PATCH',\n body: JSON.stringify({\n first_name: params.firstName,\n last_name: params.lastName,\n tags: params.tags,\n }),\n });\n }\n\n /**\n * Update a subscriber by email address\n */\n async updateByEmail(\n email: string,\n params: Partial<Omit<CreateSubscriberRequest, 'email'>>\n ): Promise<CreateSubscriberResponse> {\n // Upsert via create endpoint\n return this.create({\n email,\n ...params,\n });\n }\n\n /**\n * Delete/unsubscribe a subscriber\n */\n async delete(subscriberId: string): Promise<{ success: boolean }> {\n return this.request(`/subscribers/${subscriberId}`, {\n method: 'DELETE',\n });\n }\n\n /**\n * Add tags to a subscriber\n */\n async addTags(subscriberId: string, tags: string[]): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}/tags`, {\n method: 'POST',\n body: JSON.stringify({ tags }),\n });\n }\n\n /**\n * Remove tags from a subscriber\n */\n async removeTags(subscriberId: string, tags: string[]): Promise<CreateSubscriberResponse> {\n return this.request<CreateSubscriberResponse>(`/subscribers/${subscriberId}/tags`, {\n method: 'DELETE',\n body: JSON.stringify({ tags }),\n });\n }\n}\n","import type { SendCampaignRequest, SendCampaignResponse } from '../types';\n\n/**\n * Campaigns resource for bulk email sending\n */\nexport class CampaignsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Send a campaign to subscribers\n * \n * @example\n * ```ts\n * const result = await client.campaigns.send({\n * name: 'January Newsletter',\n * subject: 'What\\'s new this month',\n * fromName: 'Your Company',\n * fromEmail: 'news@yourcompany.com',\n * html: '<h1>Hello {{first_name}}!</h1>',\n * tags: ['newsletter', 'active']\n * });\n * ```\n */\n async send(params: SendCampaignRequest): Promise<SendCampaignResponse> {\n return this.request<SendCampaignResponse>('/campaigns/send', {\n method: 'POST',\n body: JSON.stringify({\n name: params.name,\n subject: params.subject,\n from_name: params.fromName,\n from_email: params.fromEmail,\n html: params.html,\n templateId: params.templateId,\n tags: params.tags,\n variables: params.variables,\n }),\n });\n }\n\n /**\n * Send campaign using a saved template\n */\n async sendTemplate(params: {\n name?: string;\n templateId: string;\n subject: string;\n fromName: string;\n fromEmail: string;\n tags?: string[];\n variables?: Record<string, unknown>;\n }): Promise<SendCampaignResponse> {\n return this.send({\n name: params.name,\n subject: params.subject,\n fromName: params.fromName,\n fromEmail: params.fromEmail,\n templateId: params.templateId,\n tags: params.tags,\n variables: params.variables,\n });\n }\n}\n","import type {\n Domain,\n CreateDomainRequest,\n CreateDomainResponse,\n ListDomainsResponse,\n} from '../types';\n\n/**\n * Domains resource for managing sending domains\n */\nexport class DomainsResource {\n constructor(\n private request: <T>(endpoint: string, options?: RequestInit) => Promise<T>\n ) {}\n\n /**\n * Add a new sending domain\n * Returns DKIM tokens and DNS records for verification\n * \n * @example\n * ```ts\n * const { domain } = await client.domains.create({\n * domain: 'yourcompany.com'\n * });\n * \n * console.log('Add these DNS records:', domain.dnsRecords);\n * ```\n */\n async create(params: CreateDomainRequest): Promise<CreateDomainResponse> {\n return this.request<CreateDomainResponse>('/domains', {\n method: 'POST',\n body: JSON.stringify({\n domain: params.domain,\n }),\n });\n }\n\n /**\n * List all domains for the organization\n */\n async list(): Promise<ListDomainsResponse> {\n return this.request<ListDomainsResponse>('/domains', {\n method: 'GET',\n });\n }\n\n /**\n * Get a single domain by ID\n */\n async get(domainId: string): Promise<{ success: boolean; domain: Domain }> {\n return this.request(`/domains/${domainId}`, {\n method: 'GET',\n });\n }\n\n /**\n * Verify a domain (trigger DNS check)\n */\n async verify(domainId: string): Promise<{ success: boolean; domain: Domain }> {\n return this.request(`/domains/${domainId}/verify`, {\n method: 'POST',\n });\n }\n\n /**\n * Delete a domain\n */\n async delete(domainId: string): Promise<{ success: boolean }> {\n return this.request(`/domains/${domainId}`, {\n method: 'DELETE',\n });\n }\n}\n","import type { SendMailOSOptions, ApiError } from './types';\nimport { SendMailOSError, AuthenticationError, RateLimitError } from './utils/errors';\nimport { EmailsResource } from './resources/emails';\nimport { SubscribersResource } from './resources/subscribers';\nimport { CampaignsResource } from './resources/campaigns';\nimport { DomainsResource } from './resources/domains';\n\nconst DEFAULT_BASE_URL = 'https://api.sendmailos.com/api/v1';\nconst DEFAULT_TIMEOUT = 30000;\nconst SDK_VERSION = '1.0.0';\n\n/**\n * SendMailOS SDK Client\n * \n * @example\n * ```ts\n * import { SendMailOS } from '@sendmailos/sdk';\n * \n * const client = new SendMailOS('sk_live_your_api_key');\n * \n * // Send an email\n * await client.emails.send({\n * to: 'user@example.com',\n * subject: 'Hello!',\n * html: '<h1>Welcome!</h1>'\n * });\n * \n * // Add a subscriber\n * await client.subscribers.create({\n * email: 'user@example.com',\n * tags: ['newsletter']\n * });\n * ```\n */\nexport class SendMailOS {\n private readonly apiKey: string;\n private readonly baseUrl: string;\n private readonly timeout: number;\n private readonly fetchFn: typeof fetch;\n\n /** Email sending operations */\n public readonly emails: EmailsResource;\n /** Subscriber management */\n public readonly subscribers: SubscribersResource;\n /** Campaign operations */\n public readonly campaigns: CampaignsResource;\n /** Domain management */\n public readonly domains: DomainsResource;\n\n constructor(apiKey: string, options: SendMailOSOptions = {}) {\n // Validate API key format\n if (!apiKey) {\n throw new Error('API key is required');\n }\n \n if (!apiKey.startsWith('sk_live_') && !apiKey.startsWith('sk_test_')) {\n throw new Error(\n 'Invalid API key format. Keys should start with \"sk_live_\" or \"sk_test_\"'\n );\n }\n\n this.apiKey = apiKey;\n this.baseUrl = options.baseUrl?.replace(/\\/$/, '') || DEFAULT_BASE_URL;\n this.timeout = options.timeout || DEFAULT_TIMEOUT;\n this.fetchFn = options.fetch || globalThis.fetch;\n\n // Ensure fetch is available\n if (!this.fetchFn) {\n throw new Error(\n 'fetch is not available. Please provide a fetch implementation or use Node.js 18+'\n );\n }\n\n // Initialize resources with bound request method\n const boundRequest = this.request.bind(this);\n this.emails = new EmailsResource(boundRequest);\n this.subscribers = new SubscribersResource(boundRequest);\n this.campaigns = new CampaignsResource(boundRequest);\n this.domains = new DomainsResource(boundRequest);\n }\n\n /**\n * Make an authenticated request to the API\n */\n private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${this.baseUrl}${endpoint}`;\n \n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), this.timeout);\n\n try {\n const response = await this.fetchFn(url, {\n ...options,\n signal: controller.signal,\n headers: {\n 'Authorization': `Bearer ${this.apiKey}`,\n 'Content-Type': 'application/json',\n 'User-Agent': `sendmailos-sdk/${SDK_VERSION}`,\n 'X-SDK-Version': SDK_VERSION,\n ...options.headers,\n },\n });\n\n clearTimeout(timeoutId);\n\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = parseInt(response.headers.get('Retry-After') || '60', 10);\n const errorData = await this.safeParseJson(response);\n throw new RateLimitError(\n errorData?.error || 'Rate limit exceeded',\n retryAfter\n );\n }\n\n // Handle authentication errors\n if (response.status === 401) {\n throw new AuthenticationError();\n }\n\n // Handle other errors\n if (!response.ok) {\n const errorData = await this.safeParseJson(response) as ApiError | null;\n throw new SendMailOSError(\n errorData?.error || `Request failed with status ${response.status}`,\n errorData?.code || 'UNKNOWN_ERROR',\n response.status\n );\n }\n\n return response.json() as Promise<T>;\n } catch (error) {\n clearTimeout(timeoutId);\n \n if (error instanceof SendMailOSError) {\n throw error;\n }\n \n if (error instanceof Error && error.name === 'AbortError') {\n throw new SendMailOSError('Request timeout', 'TIMEOUT', 408);\n }\n \n throw new SendMailOSError(\n error instanceof Error ? error.message : 'Unknown error',\n 'NETWORK_ERROR',\n 0\n );\n }\n }\n\n private async safeParseJson(response: Response): Promise<ApiError | null> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n }\n\n /**\n * Check if the API key is valid (test mode only)\n */\n get isTestMode(): boolean {\n return this.apiKey.startsWith('sk_test_');\n }\n\n /**\n * Get the SDK version\n */\n static get version(): string {\n return SDK_VERSION;\n }\n}\n","export interface PixelConfig {\n /** Public API key (pk_live_... or pk_test_...) or legacy token */\n token: string;\n /** API endpoint for tracking events */\n endpoint?: string;\n /** Cookie name for anonymous ID storage */\n cookieName?: string;\n /** Enable debug logging */\n debug?: boolean;\n /** Respect Do Not Track browser setting (default: true) */\n respectDNT?: boolean;\n}\n\n/** Alias for PixelConfig for SDK consistency */\nexport type PixelOptions = PixelConfig;\n\nexport interface TrackProps {\n [key: string]: string | number | boolean | null | undefined | object;\n}\n\n/** Alias for TrackProps */\nexport type TrackEventProperties = TrackProps;\n\n/** Traits for identify calls */\nexport interface IdentifyTraits {\n first_name?: string;\n last_name?: string;\n [key: string]: string | number | boolean | null | undefined | object;\n}\n\n/** Dynamic rule for context detection */\ninterface PixelRule {\n match_type: 'exact' | 'contains' | 'regex';\n url_pattern: string;\n page_type: string;\n selectors?: Record<string, string>;\n}\n\nconst OPT_OUT_KEY = 'smp_opt_out';\nconst IDENTIFIED_EMAIL_KEY = 'smp_identified_email';\n\nexport class SendmailPixel {\n private config: PixelConfig;\n private anonymousId: string;\n private initialized: boolean = false;\n private rules: PixelRule[] = [];\n private identifiedEmail: string | null = null;\n\n constructor(config: PixelConfig) {\n this.config = {\n endpoint: 'https://sendmailos.com/api/pixel/track',\n cookieName: 'sm_anon_id',\n debug: false,\n respectDNT: true,\n ...config\n };\n this.anonymousId = this.getOrSetAnonymousId();\n this.identifiedEmail = this.getStoredEmail();\n }\n\n public init() {\n if (this.initialized) return;\n\n if (typeof window === 'undefined') {\n return; // Server-side safety\n }\n\n // Check for opt-out\n if (this.isOptedOut()) {\n this.log('Tracking disabled (user opted out)');\n return;\n }\n\n // Check for Do Not Track\n if (this.config.respectDNT && this.isDNTEnabled()) {\n this.log('Tracking disabled (Do Not Track enabled)');\n return;\n }\n\n this.initialized = true;\n\n // Check URL for subscriber ID from email clicks\n this.checkUrlForSubscriber();\n\n // 0. Load Dynamic Rules (Async)\n this.loadRules();\n\n // 1. Auto-track Page View\n this.pageView();\n\n // 2. Setup Form Auto-Detection\n this.setupFormListeners();\n\n // 3. Track History State Changes (SPA Support)\n this.setupHistoryListeners();\n\n // 4. Setup data attribute tracking\n this.setupDataAttributeTracking();\n\n this.log('Pixel initialized with Token:', this.config.token);\n }\n\n /**\n * Opt out of all tracking\n */\n public optOut(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(OPT_OUT_KEY, 'true');\n }\n this.log('User opted out of tracking');\n }\n\n /**\n * Opt back in to tracking\n */\n public optIn(): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(OPT_OUT_KEY);\n }\n if (!this.initialized && typeof window !== 'undefined') {\n this.init();\n }\n this.log('User opted in to tracking');\n }\n\n /**\n * Check if user has opted out\n */\n public isOptedOut(): boolean {\n if (typeof localStorage === 'undefined') return false;\n return localStorage.getItem(OPT_OUT_KEY) === 'true';\n }\n\n /**\n * Reset identity (e.g., on logout)\n */\n public reset(): void {\n this.identifiedEmail = null;\n if (typeof localStorage !== 'undefined') {\n localStorage.removeItem(IDENTIFIED_EMAIL_KEY);\n }\n // Generate new anonymous ID\n this.anonymousId = crypto.randomUUID();\n this.setCookie(this.config.cookieName!, this.anonymousId, 365);\n this.log('Identity reset');\n }\n\n /**\n * Get current visitor/anonymous ID\n */\n public getVisitorId(): string {\n return this.anonymousId;\n }\n\n /**\n * Get identified email address\n */\n public getIdentifiedEmail(): string | null {\n return this.identifiedEmail;\n }\n\n public track(eventName: string, properties: TrackProps = {}) {\n this.sendEvent('track', {\n event_name: eventName,\n properties\n });\n }\n\n public identify(email: string, traits: TrackProps = {}) {\n if (this.isOptedOut()) return;\n\n this.identifiedEmail = email;\n this.storeEmail(email);\n\n this.sendEvent('identify', {\n email,\n traits\n });\n }\n\n public pageView() {\n this.track('page_view', {\n path: window.location.pathname,\n title: document.title,\n referrer: document.referrer,\n url: window.location.href\n });\n }\n\n // --- INTERNAL HELPERS ---\n\n private getOrSetAnonymousId(): string {\n if (typeof document === 'undefined') return '';\n\n let id = this.getCookie(this.config.cookieName!);\n if (!id) {\n id = crypto.randomUUID();\n this.setCookie(this.config.cookieName!, id, 365);\n }\n return id;\n }\n\n private sendEvent(type: 'track' | 'identify', payload: any) {\n if (typeof window === 'undefined') return;\n\n // Auto-Enrichment (Smart Context)\n const smartContext = this.detectContext();\n\n const body = {\n type,\n token: this.config.token, // Send Token\n anonymous_id: this.anonymousId,\n url: window.location.href,\n timestamp: new Date().toISOString(),\n ...payload\n };\n\n // Capture UTMs on first touch -> sent via context in API\n // For simplicity, we just send context\n const context = {\n userAgent: navigator.userAgent,\n locale: navigator.language,\n screen: { width: window.screen.width, height: window.screen.height },\n search: window.location.search,\n title: document.title,\n referrer: document.referrer,\n ...smartContext // Merge smart context\n };\n\n const finalBody = { ...body, context };\n\n // Use Beacon API if available (better for page unload)\n if (navigator.sendBeacon && type === 'track') {\n const blob = new Blob([JSON.stringify(finalBody)], { type: 'application/json' });\n navigator.sendBeacon(this.config.endpoint!, blob);\n } else {\n fetch(this.config.endpoint!, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(finalBody),\n keepalive: true\n }).catch(err => {\n if (this.config.debug) console.error('[Pixel Error]', err);\n });\n }\n\n this.log(`Event Sent [${type}]`, body);\n }\n\n // Call this after init to load rules\n public async loadRules() {\n if (typeof window === 'undefined') return;\n try {\n // Updated Endpoint Query Param\n const res = await fetch(`${this.config.endpoint?.replace('/track', '')}/rules?token=${this.config.token}`);\n if (res.ok) {\n const data = await res.json();\n this.rules = data.rules || [];\n }\n } catch (e) {\n // silent fail\n }\n }\n\n /**\n * Smart Auto-Detection of Page Type & Context\n * Uses Dynamic Rules + Static Heuristics\n */\n private detectContext(): any {\n if (typeof document === 'undefined') return {};\n\n const path = window.location.pathname.toLowerCase();\n let context: any = {\n page_type: 'general', // Default\n topics: []\n };\n\n // 0. CHECK DYNAMIC RULES (Database / AI Optimized)\n for (const rule of this.rules) {\n let matched = false;\n // URL Pattern Match\n try {\n if (rule.match_type === 'exact' && path === rule.url_pattern) matched = true;\n else if (rule.match_type === 'contains' && path.includes(rule.url_pattern)) matched = true;\n else if (rule.match_type === 'regex' && new RegExp(rule.url_pattern).test(path)) matched = true;\n } catch (e) { }\n\n if (matched) {\n context.page_type = rule.page_type;\n\n // Extract Data via Selectors\n if (rule.selectors) {\n for (const [key, selector] of Object.entries(rule.selectors)) {\n const el = document.querySelector(selector as string);\n if (el) {\n // Try value (input), then textContent, then content (meta)\n const val = (el as HTMLInputElement).value || el.textContent || el.getAttribute('content');\n if (val) context[key] = val.trim();\n }\n }\n }\n // Stop after first strong match? Or continue to merge? \n // Let's stop to allow override of default heuristics.\n return context;\n }\n }\n\n // --- FALLBACK TO STATIC HEURISTICS ---\n\n // 1. URL Heuristics\n if (path.match(/\\/(cart|basket|bag)/)) context.page_type = 'cart';\n else if (path.match(/\\/(checkout|payment|order)/)) context.page_type = 'checkout';\n else if (path.match(/\\/(product|item|p)\\//)) context.page_type = 'product';\n else if (path.match(/\\/(category|c|collection)\\//)) context.page_type = 'category';\n else if (path.match(/\\/(blog|article|post|news)/)) context.page_type = 'content';\n else if (path.match(/\\/(login|signin)/)) context.page_type = 'auth';\n else if (path.match(/\\/(signup|register)/)) context.page_type = 'auth';\n else if (path.match(/\\/(pricing|plans)/)) context.page_type = 'pricing';\n else if (path.match(/\\/(thank-you|confirmation|success)/)) context.page_type = 'purchase_success';\n\n // 2. DOM/Meta Heuristics (Stronger Signals)\n\n // Product? (Schema.org or OG Tags)\n const ogType = document.querySelector('meta[property=\"og:type\"]')?.getAttribute('content');\n if (ogType === 'product') {\n context.page_type = 'product';\n // Try to scrape price\n const price = document.querySelector('meta[property=\"product:price:amount\"]')?.getAttribute('content');\n if (price) context.product_price = price;\n const currency = document.querySelector('meta[property=\"product:price:currency\"]')?.getAttribute('content');\n if (currency) context.currency = currency;\n }\n\n // Cart?\n if (document.querySelector('.cart-total') || document.querySelector('#cart-summary')) {\n context.page_type = 'cart';\n }\n\n // Checkout?\n if (document.querySelector('#card-element') || document.querySelector('input[name=\"card_number\"]')) {\n context.page_type = 'checkout';\n }\n\n // 3. Content Scraping (Keywords)\n const text = document.body.innerText.toLowerCase().slice(0, 2000); // Check first 2k chars\n if (text.includes('out of stock')) context.stock_status = 'out_of_stock';\n if (text.includes('limited time')) context.urgency = 'high';\n\n return context;\n }\n\n private setupFormListeners() {\n if (typeof document === 'undefined') return;\n\n // Debounce to avoid performance hit\n document.addEventListener('submit', (e) => {\n const form = e.target as HTMLFormElement;\n if (!form) return;\n\n // Look for email input\n const emailInput = form.querySelector('input[type=\"email\"]') as HTMLInputElement;\n if (emailInput && emailInput.value) {\n this.log('Auto-detected email form submission', emailInput.value);\n this.identify(emailInput.value);\n }\n }, true); // Capture phase to catch it before propagation stops\n }\n\n private setupHistoryListeners() {\n if (typeof window === 'undefined') return;\n\n const pushState = history.pushState;\n history.pushState = (...args) => {\n pushState.apply(history, args);\n this.pageView();\n };\n\n window.addEventListener('popstate', () => {\n this.pageView();\n });\n }\n\n // --- COOKIE UTILS ---\n\n private setCookie(name: string, value: string, days: number) {\n const d = new Date();\n d.setTime(d.getTime() + (days * 24 * 60 * 60 * 1000));\n const expires = \"expires=\" + d.toUTCString();\n document.cookie = name + \"=\" + value + \";\" + expires + \";path=/;SameSite=Lax\";\n }\n\n private getCookie(name: string): string | null {\n const nameEQ = name + \"=\";\n const ca = document.cookie.split(';');\n for (let i = 0; i < ca.length; i++) {\n let c = ca[i];\n while (c.charAt(0) == ' ') c = c.substring(1, c.length);\n if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);\n }\n return null;\n }\n\n private log(...args: unknown[]) {\n if (this.config.debug) {\n console.log('[SendmailPixel]', ...args);\n }\n }\n\n private isDNTEnabled(): boolean {\n if (typeof navigator === 'undefined') return false;\n return navigator.doNotTrack === '1' ||\n (window as unknown as { doNotTrack?: string }).doNotTrack === '1';\n }\n\n private checkUrlForSubscriber(): void {\n if (typeof window === 'undefined') return;\n\n const params = new URLSearchParams(window.location.search);\n const subscriberEmail = params.get('smp_email');\n const subscriberId = params.get('smp_sub');\n\n if (subscriberEmail) {\n try {\n const email = atob(subscriberEmail);\n if (this.isValidEmail(email)) {\n this.identify(email);\n }\n } catch {\n if (this.isValidEmail(subscriberEmail)) {\n this.identify(subscriberEmail);\n }\n }\n } else if (subscriberId) {\n this.track('email_link_clicked', { subscriber_id: subscriberId });\n }\n }\n\n private setupDataAttributeTracking(): void {\n if (typeof document === 'undefined') return;\n\n document.addEventListener('click', (e) => {\n const target = e.target as HTMLElement;\n const tracked = target.closest('[data-smp-track]');\n\n if (tracked) {\n const eventName = tracked.getAttribute('data-smp-track');\n const properties: TrackProps = {};\n\n Array.from(tracked.attributes).forEach((attr) => {\n if (attr.name.startsWith('data-smp-track-') && attr.name !== 'data-smp-track') {\n const propName = attr.name.replace('data-smp-track-', '').replace(/-/g, '_');\n properties[propName] = attr.value;\n }\n });\n\n if (eventName) {\n this.track(eventName, properties);\n }\n }\n });\n }\n\n private getStoredEmail(): string | null {\n if (typeof localStorage === 'undefined') return null;\n return localStorage.getItem(IDENTIFIED_EMAIL_KEY);\n }\n\n private storeEmail(email: string): void {\n if (typeof localStorage !== 'undefined') {\n localStorage.setItem(IDENTIFIED_EMAIL_KEY, email);\n }\n }\n\n private isValidEmail(email: string): boolean {\n return /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/.test(email);\n }\n}\n\n/** Alias for SendmailPixel for SDK consistency */\nexport const Pixel = SendmailPixel;\n\n/**\n * Create pixel and attach global smp() function\n */\nexport function createGlobalPixel(config: PixelConfig): SendmailPixel {\n const pixel = new SendmailPixel(config);\n\n if (typeof window !== 'undefined') {\n const smpFunction = (method: string, ...args: unknown[]): unknown => {\n switch (method) {\n case 'track':\n pixel.track(args[0] as string, args[1] as TrackProps);\n return undefined;\n case 'identify':\n pixel.identify(args[0] as string, args[1] as TrackProps);\n return undefined;\n case 'page':\n pixel.pageView();\n return undefined;\n case 'optOut':\n pixel.optOut();\n return undefined;\n case 'optIn':\n pixel.optIn();\n return undefined;\n case 'isOptedOut':\n return pixel.isOptedOut();\n case 'reset':\n pixel.reset();\n return undefined;\n default:\n console.warn(`[SendmailPixel] Unknown method: ${method}`);\n return undefined;\n }\n };\n (window as unknown as { smp: typeof smpFunction }).smp = smpFunction;\n }\n\n pixel.init();\n return pixel;\n}\n","/**\n * Webhook signature verification utilities\n * \n * IMPORTANT: This module uses timing-safe comparison to prevent timing attacks.\n */\n\nexport interface VerifyWebhookParams {\n /** Raw request body as string */\n payload: string;\n /** Value of X-SendMailOS-Signature header */\n signature: string;\n /** Value of X-SendMailOS-Timestamp header */\n timestamp: string;\n /** Your webhook signing secret */\n secret: string;\n /** Maximum age in seconds (default: 300 = 5 minutes) */\n tolerance?: number;\n}\n\n/**\n * Verify a webhook signature to ensure the request came from SendMailOS\n * \n * @example\n * ```ts\n * import { verifyWebhookSignature } from '@sendmailos/sdk';\n * \n * app.post('/webhooks', (req, res) => {\n * const isValid = verifyWebhookSignature({\n * payload: JSON.stringify(req.body),\n * signature: req.headers['x-sendmailos-signature'],\n * timestamp: req.headers['x-sendmailos-timestamp'],\n * secret: process.env.WEBHOOK_SECRET\n * });\n * \n * if (!isValid) {\n * return res.status(401).json({ error: 'Invalid signature' });\n * }\n * \n * // Process webhook...\n * });\n * ```\n */\nexport function verifyWebhookSignature(params: VerifyWebhookParams): boolean {\n const { payload, signature, timestamp, secret, tolerance = 300 } = params;\n\n // Validate inputs\n if (!payload || !signature || !timestamp || !secret) {\n return false;\n }\n\n // Prevent replay attacks - check timestamp age\n const timestampInt = parseInt(timestamp, 10);\n if (isNaN(timestampInt)) {\n return false;\n }\n\n const age = Math.floor(Date.now() / 1000) - timestampInt;\n if (age > tolerance) {\n console.warn('[SendMailOS] Webhook timestamp too old:', age, 'seconds');\n return false;\n }\n\n // Node.js crypto (server-side)\n if (typeof globalThis.crypto !== 'undefined' && 'subtle' in globalThis.crypto) {\n // Use SubtleCrypto for browser/edge environments\n // Note: This is synchronous verification, use verifyWebhookSignatureAsync for async\n return verifySync(payload, signature, timestamp, secret);\n }\n\n return verifySync(payload, signature, timestamp, secret);\n}\n\n/**\n * Async version of webhook verification (recommended for edge/browser)\n */\nexport async function verifyWebhookSignatureAsync(params: VerifyWebhookParams): Promise<boolean> {\n const { payload, signature, timestamp, secret, tolerance = 300 } = params;\n\n if (!payload || !signature || !timestamp || !secret) {\n return false;\n }\n\n const timestampInt = parseInt(timestamp, 10);\n if (isNaN(timestampInt)) {\n return false;\n }\n\n const age = Math.floor(Date.now() / 1000) - timestampInt;\n if (age > tolerance) {\n return false;\n }\n\n const message = `${timestamp}.${payload}`;\n \n // Use Web Crypto API\n const encoder = new TextEncoder();\n const key = await crypto.subtle.importKey(\n 'raw',\n encoder.encode(secret),\n { name: 'HMAC', hash: 'SHA-256' },\n false,\n ['sign']\n );\n \n const signatureBytes = await crypto.subtle.sign(\n 'HMAC',\n key,\n encoder.encode(message)\n );\n \n const expectedSig = bufferToHex(signatureBytes);\n \n // Timing-safe comparison\n return timingSafeEqual(signature, expectedSig);\n}\n\n// ============ Internal Helpers ============\n\nfunction verifySync(payload: string, signature: string, timestamp: string, secret: string): boolean {\n try {\n // Try Node.js crypto first\n const crypto = require('crypto');\n const message = `${timestamp}.${payload}`;\n const expectedSig = crypto\n .createHmac('sha256', secret)\n .update(message)\n .digest('hex');\n \n // Use timing-safe comparison\n return crypto.timingSafeEqual(\n Buffer.from(signature),\n Buffer.from(expectedSig)\n );\n } catch {\n // Fallback for non-Node environments\n console.warn('[SendMailOS] Use verifyWebhookSignatureAsync for browser/edge');\n return false;\n }\n}\n\nfunction bufferToHex(buffer: ArrayBuffer): string {\n return Array.from(new Uint8Array(buffer))\n .map(b => b.toString(16).padStart(2, '0'))\n .join('');\n}\n\nfunction timingSafeEqual(a: string, b: string): boolean {\n if (a.length !== b.length) {\n return false;\n }\n \n let result = 0;\n for (let i = 0; i < a.length; i++) {\n result |= a.charCodeAt(i) ^ b.charCodeAt(i);\n }\n return result === 0;\n}\n\n/**\n * Construct a webhook event from raw request data\n */\nexport function constructWebhookEvent<T = unknown>(\n payload: string,\n headers: { signature: string; timestamp: string },\n secret: string\n): T {\n const isValid = verifyWebhookSignature({\n payload,\n signature: headers.signature,\n timestamp: headers.timestamp,\n secret,\n });\n\n if (!isValid) {\n throw new Error('Invalid webhook signature');\n }\n\n return JSON.parse(payload) as T;\n}\n"]}
|