@tiquo/dom-package 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/dist/index.d.mts +154 -22
- package/dist/index.d.ts +154 -22
- package/dist/index.js +632 -59
- package/dist/index.mjs +630 -59
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -641,6 +641,333 @@ function printTiquoBranding() {
|
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
643
|
printTiquoBranding();
|
|
644
|
+
var ANALYTICS_LOCATION_EVENT = "tiquo:locationchange";
|
|
645
|
+
var analyticsHistoryPatched = false;
|
|
646
|
+
function randomId() {
|
|
647
|
+
try {
|
|
648
|
+
if (typeof crypto !== "undefined" && "randomUUID" in crypto) {
|
|
649
|
+
return crypto.randomUUID();
|
|
650
|
+
}
|
|
651
|
+
} catch {
|
|
652
|
+
}
|
|
653
|
+
return `ev_${Date.now().toString(36)}_${Math.random().toString(36).slice(2)}`;
|
|
654
|
+
}
|
|
655
|
+
function normalizeHostname(hostname) {
|
|
656
|
+
if (!hostname) return void 0;
|
|
657
|
+
const clean = hostname.trim().toLowerCase().split(":")[0];
|
|
658
|
+
return clean.startsWith("www.") ? clean.slice(4) : clean;
|
|
659
|
+
}
|
|
660
|
+
function getBrowser() {
|
|
661
|
+
if (typeof navigator === "undefined") return "Other";
|
|
662
|
+
const ua = navigator.userAgent;
|
|
663
|
+
if (/Edg(e|A|iOS)?\//i.test(ua)) return "Edge";
|
|
664
|
+
if (/Firefox\//i.test(ua)) return "Firefox";
|
|
665
|
+
if (/Chrome\/|CriOS\//i.test(ua)) return "Chrome";
|
|
666
|
+
if (/Safari\//i.test(ua) && !/Chrome/i.test(ua)) return "Safari";
|
|
667
|
+
return "Other";
|
|
668
|
+
}
|
|
669
|
+
function getDevice() {
|
|
670
|
+
if (typeof navigator === "undefined") return "Desktop";
|
|
671
|
+
const ua = navigator.userAgent;
|
|
672
|
+
if (/iPad|tablet|PlayBook|Silk/i.test(ua)) return "Tablet";
|
|
673
|
+
if (/Android(?!.*Mobile)/i.test(ua) && /Android/i.test(ua) && !/Mobile/i.test(ua))
|
|
674
|
+
return "Tablet";
|
|
675
|
+
if (/Mobile|iPhone|iPod|Android.*Mobile|webOS|BlackBerry|Opera Mini|IEMobile/i.test(
|
|
676
|
+
ua
|
|
677
|
+
))
|
|
678
|
+
return "Mobile";
|
|
679
|
+
return "Desktop";
|
|
680
|
+
}
|
|
681
|
+
function getOperatingSystem() {
|
|
682
|
+
if (typeof navigator === "undefined") return "Other";
|
|
683
|
+
const ua = navigator.userAgent;
|
|
684
|
+
if (/iPhone|iPad|iPod/i.test(ua)) return "iOS";
|
|
685
|
+
if (/Android/i.test(ua)) return "Android";
|
|
686
|
+
if (/CrOS/i.test(ua)) return "Chrome OS";
|
|
687
|
+
if (/Windows/i.test(ua)) return "Windows";
|
|
688
|
+
if (/Macintosh|Mac OS X/i.test(ua)) return "macOS";
|
|
689
|
+
if (/Linux/i.test(ua)) return "Linux";
|
|
690
|
+
return "Other";
|
|
691
|
+
}
|
|
692
|
+
function getUtmParams() {
|
|
693
|
+
if (typeof window === "undefined") return {};
|
|
694
|
+
const params = new URLSearchParams(window.location.search);
|
|
695
|
+
return {
|
|
696
|
+
source: params.get("utm_source") || void 0,
|
|
697
|
+
medium: params.get("utm_medium") || void 0,
|
|
698
|
+
campaign: params.get("utm_campaign") || void 0,
|
|
699
|
+
content: params.get("utm_content") || void 0,
|
|
700
|
+
term: params.get("utm_term") || void 0
|
|
701
|
+
};
|
|
702
|
+
}
|
|
703
|
+
function patchHistoryForAnalytics() {
|
|
704
|
+
if (analyticsHistoryPatched || typeof window === "undefined") return;
|
|
705
|
+
analyticsHistoryPatched = true;
|
|
706
|
+
const notify = () => {
|
|
707
|
+
window.dispatchEvent(
|
|
708
|
+
new Event(ANALYTICS_LOCATION_EVENT)
|
|
709
|
+
);
|
|
710
|
+
};
|
|
711
|
+
const pushState = history.pushState;
|
|
712
|
+
history.pushState = function patchedPushState(...args) {
|
|
713
|
+
const result = pushState.apply(this, args);
|
|
714
|
+
notify();
|
|
715
|
+
return result;
|
|
716
|
+
};
|
|
717
|
+
const replaceState = history.replaceState;
|
|
718
|
+
history.replaceState = function patchedReplaceState(...args) {
|
|
719
|
+
const result = replaceState.apply(this, args);
|
|
720
|
+
notify();
|
|
721
|
+
return result;
|
|
722
|
+
};
|
|
723
|
+
window.addEventListener("popstate", notify);
|
|
724
|
+
}
|
|
725
|
+
var _TiquoAnalytics = class _TiquoAnalytics {
|
|
726
|
+
constructor(config) {
|
|
727
|
+
this.pageStartedAt = Date.now();
|
|
728
|
+
this.lastPath = null;
|
|
729
|
+
this.started = false;
|
|
730
|
+
if (!config.publicKey) {
|
|
731
|
+
throw new TiquoAuthError("publicKey is required", "MISSING_PUBLIC_KEY");
|
|
732
|
+
}
|
|
733
|
+
if (!config.publicKey.startsWith("pk_dom_")) {
|
|
734
|
+
throw new TiquoAuthError(
|
|
735
|
+
"Invalid public key format. Expected pk_dom_xxx",
|
|
736
|
+
"INVALID_PUBLIC_KEY"
|
|
737
|
+
);
|
|
738
|
+
}
|
|
739
|
+
this.config = {
|
|
740
|
+
publicKey: config.publicKey,
|
|
741
|
+
apiEndpoint: config.apiEndpoint || "https://edge.tiquo.app",
|
|
742
|
+
debug: config.debug || false,
|
|
743
|
+
autoTrackPageviews: config.autoTrackPageviews !== false,
|
|
744
|
+
getAccessToken: config.getAccessToken,
|
|
745
|
+
siteSlug: config.siteSlug
|
|
746
|
+
};
|
|
747
|
+
this.clientSessionId = this.getClientSessionId();
|
|
748
|
+
if (this.config.autoTrackPageviews) {
|
|
749
|
+
this.start();
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
start() {
|
|
753
|
+
if (this.started || typeof window === "undefined") return;
|
|
754
|
+
const activeKey = `${this.config.publicKey}:${this.config.siteSlug || ""}`;
|
|
755
|
+
const existing = _TiquoAnalytics.activeInstances.get(activeKey);
|
|
756
|
+
if (existing && existing !== this) {
|
|
757
|
+
existing.adoptConfig(this.config);
|
|
758
|
+
return;
|
|
759
|
+
}
|
|
760
|
+
_TiquoAnalytics.activeInstances.set(activeKey, this);
|
|
761
|
+
this.started = true;
|
|
762
|
+
patchHistoryForAnalytics();
|
|
763
|
+
this.trackPageview();
|
|
764
|
+
window.addEventListener(
|
|
765
|
+
ANALYTICS_LOCATION_EVENT,
|
|
766
|
+
() => this.trackPageview()
|
|
767
|
+
);
|
|
768
|
+
window.addEventListener("pagehide", () => this.trackEngagement());
|
|
769
|
+
document.addEventListener("visibilitychange", () => {
|
|
770
|
+
if (document.visibilityState === "hidden") this.trackEngagement();
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
async trackPageview(options = {}) {
|
|
774
|
+
if (typeof window === "undefined") return;
|
|
775
|
+
const path = options.path || `${window.location.pathname}${window.location.search}`;
|
|
776
|
+
if (path === this.lastPath) return;
|
|
777
|
+
if (this.lastPath) {
|
|
778
|
+
this.trackEngagement().catch(() => void 0);
|
|
779
|
+
}
|
|
780
|
+
this.lastPath = path;
|
|
781
|
+
this.pageStartedAt = Date.now();
|
|
782
|
+
await this.track("pageview", {
|
|
783
|
+
...options,
|
|
784
|
+
path,
|
|
785
|
+
url: options.url || window.location.href,
|
|
786
|
+
title: options.title || document.title,
|
|
787
|
+
referrer: options.referrer || document.referrer || void 0
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
async track(eventType, options = {}) {
|
|
791
|
+
if (typeof window === "undefined") return;
|
|
792
|
+
const utm = getUtmParams();
|
|
793
|
+
const payload = {
|
|
794
|
+
publicKey: this.config.publicKey,
|
|
795
|
+
eventId: randomId(),
|
|
796
|
+
eventType,
|
|
797
|
+
eventName: options.eventName,
|
|
798
|
+
eventProperties: options.eventProperties,
|
|
799
|
+
clientSessionId: this.clientSessionId,
|
|
800
|
+
siteSlug: options.siteSlug || this.config.siteSlug,
|
|
801
|
+
pageSlug: options.pageSlug,
|
|
802
|
+
hostname: normalizeHostname(window.location.hostname),
|
|
803
|
+
path: options.path || `${window.location.pathname}${window.location.search}`,
|
|
804
|
+
url: options.url || window.location.href,
|
|
805
|
+
title: options.title || document.title,
|
|
806
|
+
referrer: options.referrer || document.referrer || void 0,
|
|
807
|
+
timestamp: Date.now(),
|
|
808
|
+
browser: getBrowser(),
|
|
809
|
+
device: getDevice(),
|
|
810
|
+
operatingSystem: getOperatingSystem(),
|
|
811
|
+
language: navigator.language,
|
|
812
|
+
screenWidth: window.screen?.width,
|
|
813
|
+
screenHeight: window.screen?.height,
|
|
814
|
+
viewportWidth: window.innerWidth,
|
|
815
|
+
viewportHeight: window.innerHeight,
|
|
816
|
+
durationMs: options.durationMs,
|
|
817
|
+
scrollDepth: options.scrollDepth,
|
|
818
|
+
identityLinkType: options.identityLinkType,
|
|
819
|
+
...utm
|
|
820
|
+
};
|
|
821
|
+
await this.send(payload);
|
|
822
|
+
}
|
|
823
|
+
async identify(options = {}) {
|
|
824
|
+
await this.track("identify", {
|
|
825
|
+
...options,
|
|
826
|
+
identityLinkType: options.identityLinkType || "auth_dom_login"
|
|
827
|
+
});
|
|
828
|
+
}
|
|
829
|
+
async trackEngagement() {
|
|
830
|
+
if (typeof window === "undefined" || !this.lastPath) return;
|
|
831
|
+
const durationMs = Date.now() - this.pageStartedAt;
|
|
832
|
+
const scrollHeight = Math.max(
|
|
833
|
+
document.documentElement.scrollHeight,
|
|
834
|
+
document.body?.scrollHeight || 0,
|
|
835
|
+
window.innerHeight
|
|
836
|
+
);
|
|
837
|
+
const scrollDepth = scrollHeight > 0 ? Math.min(1, (window.scrollY + window.innerHeight) / scrollHeight) : void 0;
|
|
838
|
+
await this.track("engagement", {
|
|
839
|
+
path: this.lastPath,
|
|
840
|
+
durationMs,
|
|
841
|
+
scrollDepth
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
async send(payload) {
|
|
845
|
+
const headers = {
|
|
846
|
+
"Content-Type": "text/plain;charset=UTF-8",
|
|
847
|
+
"X-Public-Key": this.config.publicKey
|
|
848
|
+
};
|
|
849
|
+
const accessToken = this.config.getAccessToken?.();
|
|
850
|
+
if (accessToken) {
|
|
851
|
+
headers.Authorization = `Bearer ${accessToken}`;
|
|
852
|
+
}
|
|
853
|
+
try {
|
|
854
|
+
await fetch(`${this.config.apiEndpoint}/api/dom-analytics/event`, {
|
|
855
|
+
method: "POST",
|
|
856
|
+
headers,
|
|
857
|
+
credentials: "include",
|
|
858
|
+
keepalive: true,
|
|
859
|
+
body: JSON.stringify(payload)
|
|
860
|
+
});
|
|
861
|
+
} catch (error) {
|
|
862
|
+
this.log("Analytics event failed:", error);
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
getClientSessionId() {
|
|
866
|
+
const key = `tiquo_analytics_session_${this.config.publicKey}`;
|
|
867
|
+
try {
|
|
868
|
+
const existing = sessionStorage.getItem(key);
|
|
869
|
+
if (existing) return existing;
|
|
870
|
+
const next = randomId();
|
|
871
|
+
sessionStorage.setItem(key, next);
|
|
872
|
+
return next;
|
|
873
|
+
} catch {
|
|
874
|
+
return randomId();
|
|
875
|
+
}
|
|
876
|
+
}
|
|
877
|
+
log(...args) {
|
|
878
|
+
if (this.config.debug) {
|
|
879
|
+
console.log("[TiquoAnalytics]", ...args);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
adoptConfig(nextConfig) {
|
|
883
|
+
if (nextConfig.getAccessToken) {
|
|
884
|
+
this.config.getAccessToken = nextConfig.getAccessToken;
|
|
885
|
+
}
|
|
886
|
+
if (nextConfig.siteSlug && !this.config.siteSlug) {
|
|
887
|
+
this.config.siteSlug = nextConfig.siteSlug;
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
_TiquoAnalytics.activeInstances = /* @__PURE__ */ new Map();
|
|
892
|
+
var TiquoAnalytics = _TiquoAnalytics;
|
|
893
|
+
var TiquoCMS = class {
|
|
894
|
+
constructor(config) {
|
|
895
|
+
this.analytics = null;
|
|
896
|
+
if (!config.publicKey) {
|
|
897
|
+
throw new TiquoAuthError("publicKey is required", "MISSING_PUBLIC_KEY");
|
|
898
|
+
}
|
|
899
|
+
if (!config.publicKey.startsWith("pk_dom_")) {
|
|
900
|
+
throw new TiquoAuthError(
|
|
901
|
+
"Invalid public key format. Expected pk_dom_xxx",
|
|
902
|
+
"INVALID_PUBLIC_KEY"
|
|
903
|
+
);
|
|
904
|
+
}
|
|
905
|
+
this.config = {
|
|
906
|
+
publicKey: config.publicKey,
|
|
907
|
+
apiEndpoint: config.apiEndpoint || "https://edge.tiquo.app",
|
|
908
|
+
debug: config.debug || false,
|
|
909
|
+
analytics: config.analytics !== false
|
|
910
|
+
};
|
|
911
|
+
if (this.config.analytics) {
|
|
912
|
+
this.analytics = new TiquoAnalytics({
|
|
913
|
+
publicKey: this.config.publicKey,
|
|
914
|
+
apiEndpoint: this.config.apiEndpoint,
|
|
915
|
+
debug: this.config.debug
|
|
916
|
+
});
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
/**
|
|
920
|
+
* Fetch a published CMS page for the website attached to this public key.
|
|
921
|
+
*
|
|
922
|
+
* This intentionally goes through the Tiquo edge API rather than exposing
|
|
923
|
+
* Convex connection details to the consuming website.
|
|
924
|
+
*/
|
|
925
|
+
async getPage(request) {
|
|
926
|
+
const response = await fetch(
|
|
927
|
+
`${this.config.apiEndpoint}/api/dom-cms/page`,
|
|
928
|
+
{
|
|
929
|
+
method: "POST",
|
|
930
|
+
headers: {
|
|
931
|
+
"Content-Type": "text/plain;charset=UTF-8"
|
|
932
|
+
},
|
|
933
|
+
credentials: "include",
|
|
934
|
+
body: JSON.stringify({
|
|
935
|
+
publicKey: this.config.publicKey,
|
|
936
|
+
siteSlug: request.siteSlug,
|
|
937
|
+
pageSlug: request.pageSlug || "home",
|
|
938
|
+
templateId: request.templateId
|
|
939
|
+
})
|
|
940
|
+
}
|
|
941
|
+
);
|
|
942
|
+
if (response.status === 404) {
|
|
943
|
+
return null;
|
|
944
|
+
}
|
|
945
|
+
if (!response.ok) {
|
|
946
|
+
let message = "Failed to fetch CMS page";
|
|
947
|
+
try {
|
|
948
|
+
const error = await response.json();
|
|
949
|
+
if (typeof error?.error === "string") message = error.error;
|
|
950
|
+
} catch {
|
|
951
|
+
}
|
|
952
|
+
throw new TiquoAuthError(
|
|
953
|
+
message,
|
|
954
|
+
"CMS_PAGE_FETCH_FAILED",
|
|
955
|
+
response.status
|
|
956
|
+
);
|
|
957
|
+
}
|
|
958
|
+
const result = await response.json();
|
|
959
|
+
if (!result?.success || !result?.data) {
|
|
960
|
+
return null;
|
|
961
|
+
}
|
|
962
|
+
this.log("Fetched CMS page", request.siteSlug, request.pageSlug || "home");
|
|
963
|
+
return result.data;
|
|
964
|
+
}
|
|
965
|
+
log(...args) {
|
|
966
|
+
if (this.config.debug) {
|
|
967
|
+
console.log("[TiquoCMS]", ...args);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
};
|
|
644
971
|
var TiquoAuthError = class extends Error {
|
|
645
972
|
constructor(message, code, statusCode) {
|
|
646
973
|
super(message);
|
|
@@ -678,6 +1005,7 @@ var TiquoAuth = class {
|
|
|
678
1005
|
this.visibilityHandler = null;
|
|
679
1006
|
this.iframeObserver = null;
|
|
680
1007
|
this.injectedIframes = /* @__PURE__ */ new WeakSet();
|
|
1008
|
+
this.analytics = null;
|
|
681
1009
|
// Multi-tab sync
|
|
682
1010
|
this.broadcastChannel = null;
|
|
683
1011
|
this.isProcessingTabSync = false;
|
|
@@ -698,10 +1026,19 @@ var TiquoAuth = class {
|
|
|
698
1026
|
debug: config.debug || false,
|
|
699
1027
|
enableTabSync: config.enableTabSync !== false,
|
|
700
1028
|
// Default true
|
|
1029
|
+
analytics: config.analytics !== false,
|
|
701
1030
|
accessToken: config.accessToken,
|
|
702
1031
|
refreshToken: config.refreshToken
|
|
703
1032
|
};
|
|
704
1033
|
this.tabId = this.generateTabId();
|
|
1034
|
+
if (this.config.analytics) {
|
|
1035
|
+
this.analytics = new TiquoAnalytics({
|
|
1036
|
+
publicKey: this.config.publicKey,
|
|
1037
|
+
apiEndpoint: this.config.apiEndpoint,
|
|
1038
|
+
debug: this.config.debug,
|
|
1039
|
+
getAccessToken: () => this.accessToken
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
705
1042
|
if (this.config.enableTabSync) {
|
|
706
1043
|
this.initTabSync();
|
|
707
1044
|
}
|
|
@@ -727,7 +1064,11 @@ var TiquoAuth = class {
|
|
|
727
1064
|
});
|
|
728
1065
|
if (!response.ok) {
|
|
729
1066
|
const error = await response.json().catch(() => ({ error: "Failed to send OTP" }));
|
|
730
|
-
throw new TiquoAuthError(
|
|
1067
|
+
throw new TiquoAuthError(
|
|
1068
|
+
error.error || "Failed to send OTP",
|
|
1069
|
+
"OTP_SEND_FAILED",
|
|
1070
|
+
response.status
|
|
1071
|
+
);
|
|
731
1072
|
}
|
|
732
1073
|
const result = await response.json();
|
|
733
1074
|
return {
|
|
@@ -750,7 +1091,11 @@ var TiquoAuth = class {
|
|
|
750
1091
|
});
|
|
751
1092
|
if (!response.ok) {
|
|
752
1093
|
const error = await response.json().catch(() => ({ error: "Invalid OTP" }));
|
|
753
|
-
throw new TiquoAuthError(
|
|
1094
|
+
throw new TiquoAuthError(
|
|
1095
|
+
error.error || "Invalid OTP",
|
|
1096
|
+
"OTP_VERIFY_FAILED",
|
|
1097
|
+
response.status
|
|
1098
|
+
);
|
|
754
1099
|
}
|
|
755
1100
|
const result = await response.json();
|
|
756
1101
|
this.accessToken = result.accessToken;
|
|
@@ -760,6 +1105,7 @@ var TiquoAuth = class {
|
|
|
760
1105
|
if (this.session?.user?.id) {
|
|
761
1106
|
addCustomerUserId(this.session.user.id);
|
|
762
1107
|
}
|
|
1108
|
+
this.analytics?.identify({ identityLinkType: "auth_dom_login" }).catch(() => void 0);
|
|
763
1109
|
this.broadcastTabSync("LOGIN");
|
|
764
1110
|
return {
|
|
765
1111
|
success: true,
|
|
@@ -807,11 +1153,22 @@ var TiquoAuth = class {
|
|
|
807
1153
|
async updateProfile(updates) {
|
|
808
1154
|
await this.ensureValidToken();
|
|
809
1155
|
const normalizedUpdates = { ...updates };
|
|
1156
|
+
const profilePhotoUpload = this.extractUploadableProfilePhoto(
|
|
1157
|
+
normalizedUpdates.profilePhoto
|
|
1158
|
+
);
|
|
1159
|
+
if (profilePhotoUpload) {
|
|
1160
|
+
delete normalizedUpdates.profilePhoto;
|
|
1161
|
+
}
|
|
810
1162
|
if (normalizedUpdates.phone !== void 0 && normalizedUpdates.phone !== "") {
|
|
811
1163
|
const normalized = normalizePhone(normalizedUpdates.phone);
|
|
812
1164
|
const validation = validatePhone(normalizedUpdates.phone);
|
|
813
1165
|
if (!validation.valid) {
|
|
814
|
-
this.log(
|
|
1166
|
+
this.log(
|
|
1167
|
+
"\u26A0\uFE0F Phone validation warning:",
|
|
1168
|
+
validation.reason,
|
|
1169
|
+
"- Original:",
|
|
1170
|
+
normalizedUpdates.phone
|
|
1171
|
+
);
|
|
815
1172
|
} else {
|
|
816
1173
|
this.log("Phone normalized:", normalizedUpdates.phone, "\u2192", normalized);
|
|
817
1174
|
}
|
|
@@ -823,32 +1180,146 @@ var TiquoAuth = class {
|
|
|
823
1180
|
const normalized = normalizePhone(p.number);
|
|
824
1181
|
const validation = validatePhone(p.number);
|
|
825
1182
|
if (!validation.valid) {
|
|
826
|
-
this.log(
|
|
1183
|
+
this.log(
|
|
1184
|
+
"\u26A0\uFE0F Phone validation warning:",
|
|
1185
|
+
validation.reason,
|
|
1186
|
+
"- Original:",
|
|
1187
|
+
p.number
|
|
1188
|
+
);
|
|
827
1189
|
}
|
|
828
1190
|
return { ...p, number: normalized || p.number };
|
|
829
1191
|
});
|
|
830
1192
|
}
|
|
831
1193
|
this.log("Updating customer profile:", normalizedUpdates);
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1194
|
+
let customer = this.session?.customer || void 0;
|
|
1195
|
+
if (Object.keys(normalizedUpdates).length > 0) {
|
|
1196
|
+
const response = await this.request("/api/client/v1/profile", {
|
|
1197
|
+
method: "PATCH",
|
|
1198
|
+
body: JSON.stringify(normalizedUpdates)
|
|
1199
|
+
});
|
|
1200
|
+
if (!response.ok) {
|
|
1201
|
+
const error = await response.json().catch(() => ({ error: "Failed to update profile" }));
|
|
1202
|
+
throw new TiquoAuthError(
|
|
1203
|
+
error.error || "Failed to update profile",
|
|
1204
|
+
"PROFILE_UPDATE_FAILED",
|
|
1205
|
+
response.status
|
|
1206
|
+
);
|
|
1207
|
+
}
|
|
1208
|
+
const result = await response.json();
|
|
1209
|
+
if (this.session && result.data?.customer) {
|
|
1210
|
+
this.session = {
|
|
1211
|
+
...this.session,
|
|
1212
|
+
customer: result.data.customer
|
|
1213
|
+
};
|
|
1214
|
+
this.notifyListeners();
|
|
1215
|
+
this.broadcastTabSync("SESSION_UPDATE");
|
|
1216
|
+
}
|
|
1217
|
+
customer = result.data?.customer;
|
|
1218
|
+
}
|
|
1219
|
+
if (profilePhotoUpload) {
|
|
1220
|
+
return this.uploadProfilePhoto(profilePhotoUpload);
|
|
1221
|
+
}
|
|
1222
|
+
return {
|
|
1223
|
+
success: true,
|
|
1224
|
+
customer
|
|
1225
|
+
};
|
|
1226
|
+
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Upload and save the authenticated customer's profile photo.
|
|
1229
|
+
*
|
|
1230
|
+
* Accepts a browser File/Blob, `data:image/...` URI, or `blob:...` URI. The
|
|
1231
|
+
* image is uploaded to Tiquo storage first, and the customer profile is
|
|
1232
|
+
* updated with the URL.
|
|
1233
|
+
*/
|
|
1234
|
+
async uploadProfilePhoto(photo) {
|
|
1235
|
+
await this.ensureValidToken();
|
|
1236
|
+
const blob = await this.profilePhotoToBlob(photo);
|
|
1237
|
+
if (!blob.type.startsWith("image/")) {
|
|
1238
|
+
throw new TiquoAuthError(
|
|
1239
|
+
"Profile photo must be an image",
|
|
1240
|
+
"INVALID_PROFILE_PHOTO"
|
|
1241
|
+
);
|
|
1242
|
+
}
|
|
1243
|
+
const uploadUrlResponse = await this.request(
|
|
1244
|
+
"/api/client/v1/profile/photo-upload-url",
|
|
1245
|
+
{
|
|
1246
|
+
method: "POST",
|
|
1247
|
+
body: JSON.stringify({})
|
|
1248
|
+
}
|
|
1249
|
+
);
|
|
1250
|
+
if (!uploadUrlResponse.ok) {
|
|
1251
|
+
const error = await uploadUrlResponse.json().catch(() => ({ error: "Failed to create profile photo upload URL" }));
|
|
1252
|
+
throw new TiquoAuthError(
|
|
1253
|
+
error.error || "Failed to create profile photo upload URL",
|
|
1254
|
+
"PROFILE_PHOTO_UPLOAD_URL_FAILED",
|
|
1255
|
+
uploadUrlResponse.status
|
|
1256
|
+
);
|
|
1257
|
+
}
|
|
1258
|
+
const uploadUrlResult = await uploadUrlResponse.json();
|
|
1259
|
+
const uploadUrl = uploadUrlResult.data?.uploadUrl;
|
|
1260
|
+
if (!uploadUrl) {
|
|
1261
|
+
throw new TiquoAuthError(
|
|
1262
|
+
"Profile photo upload URL was missing",
|
|
1263
|
+
"PROFILE_PHOTO_UPLOAD_URL_FAILED"
|
|
1264
|
+
);
|
|
1265
|
+
}
|
|
1266
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
1267
|
+
method: "POST",
|
|
1268
|
+
headers: { "Content-Type": blob.type },
|
|
1269
|
+
body: blob
|
|
835
1270
|
});
|
|
836
|
-
if (!
|
|
837
|
-
|
|
838
|
-
|
|
1271
|
+
if (!uploadResponse.ok) {
|
|
1272
|
+
throw new TiquoAuthError(
|
|
1273
|
+
"Failed to upload profile photo",
|
|
1274
|
+
"PROFILE_PHOTO_UPLOAD_FAILED",
|
|
1275
|
+
uploadResponse.status
|
|
1276
|
+
);
|
|
839
1277
|
}
|
|
840
|
-
const
|
|
841
|
-
|
|
1278
|
+
const uploadResult = await uploadResponse.json();
|
|
1279
|
+
const storageId = uploadResult.storageId;
|
|
1280
|
+
if (!storageId) {
|
|
1281
|
+
throw new TiquoAuthError(
|
|
1282
|
+
"Profile photo storage ID was missing",
|
|
1283
|
+
"PROFILE_PHOTO_UPLOAD_FAILED"
|
|
1284
|
+
);
|
|
1285
|
+
}
|
|
1286
|
+
const finalizeResponse = await this.request(
|
|
1287
|
+
"/api/client/v1/profile/photo",
|
|
1288
|
+
{
|
|
1289
|
+
method: "POST",
|
|
1290
|
+
body: JSON.stringify({ storageId })
|
|
1291
|
+
}
|
|
1292
|
+
);
|
|
1293
|
+
if (!finalizeResponse.ok) {
|
|
1294
|
+
const error = await finalizeResponse.json().catch(() => ({ error: "Failed to update profile photo" }));
|
|
1295
|
+
throw new TiquoAuthError(
|
|
1296
|
+
error.error || "Failed to update profile photo",
|
|
1297
|
+
"PROFILE_PHOTO_UPDATE_FAILED",
|
|
1298
|
+
finalizeResponse.status
|
|
1299
|
+
);
|
|
1300
|
+
}
|
|
1301
|
+
const finalizeResult = await finalizeResponse.json();
|
|
1302
|
+
const customer = finalizeResult.data?.customer;
|
|
1303
|
+
const profilePhoto = finalizeResult.data?.profilePhoto;
|
|
1304
|
+
if (!customer || !profilePhoto) {
|
|
1305
|
+
throw new TiquoAuthError(
|
|
1306
|
+
"Profile photo update response was incomplete",
|
|
1307
|
+
"PROFILE_PHOTO_UPDATE_FAILED"
|
|
1308
|
+
);
|
|
1309
|
+
}
|
|
1310
|
+
if (this.session && customer) {
|
|
842
1311
|
this.session = {
|
|
843
1312
|
...this.session,
|
|
844
|
-
customer
|
|
1313
|
+
customer
|
|
845
1314
|
};
|
|
846
1315
|
this.notifyListeners();
|
|
847
1316
|
this.broadcastTabSync("SESSION_UPDATE");
|
|
848
1317
|
}
|
|
849
1318
|
return {
|
|
850
1319
|
success: true,
|
|
851
|
-
customer
|
|
1320
|
+
customer,
|
|
1321
|
+
profilePhoto,
|
|
1322
|
+
storageId
|
|
852
1323
|
};
|
|
853
1324
|
}
|
|
854
1325
|
/**
|
|
@@ -909,13 +1380,17 @@ var TiquoAuth = class {
|
|
|
909
1380
|
const response = await fetch(url.toString(), {
|
|
910
1381
|
method: "GET",
|
|
911
1382
|
headers: {
|
|
912
|
-
|
|
1383
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
913
1384
|
},
|
|
914
1385
|
credentials: "include"
|
|
915
1386
|
});
|
|
916
1387
|
if (!response.ok) {
|
|
917
1388
|
const error = await response.json().catch(() => ({ error: "Failed to get orders" }));
|
|
918
|
-
throw new TiquoAuthError(
|
|
1389
|
+
throw new TiquoAuthError(
|
|
1390
|
+
error.error || "Failed to get orders",
|
|
1391
|
+
"GET_ORDERS_FAILED",
|
|
1392
|
+
response.status
|
|
1393
|
+
);
|
|
919
1394
|
}
|
|
920
1395
|
const result = await response.json();
|
|
921
1396
|
return result.data || { orders: [], hasMore: false };
|
|
@@ -947,13 +1422,17 @@ var TiquoAuth = class {
|
|
|
947
1422
|
const response = await fetch(url.toString(), {
|
|
948
1423
|
method: "GET",
|
|
949
1424
|
headers: {
|
|
950
|
-
|
|
1425
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
951
1426
|
},
|
|
952
1427
|
credentials: "include"
|
|
953
1428
|
});
|
|
954
1429
|
if (!response.ok) {
|
|
955
1430
|
const error = await response.json().catch(() => ({ error: "Failed to get bookings" }));
|
|
956
|
-
throw new TiquoAuthError(
|
|
1431
|
+
throw new TiquoAuthError(
|
|
1432
|
+
error.error || "Failed to get bookings",
|
|
1433
|
+
"GET_BOOKINGS_FAILED",
|
|
1434
|
+
response.status
|
|
1435
|
+
);
|
|
957
1436
|
}
|
|
958
1437
|
const result = await response.json();
|
|
959
1438
|
return result.data || { bookings: [], hasMore: false };
|
|
@@ -995,14 +1474,18 @@ var TiquoAuth = class {
|
|
|
995
1474
|
const response = await fetch(url.toString(), {
|
|
996
1475
|
method: "GET",
|
|
997
1476
|
headers: {
|
|
998
|
-
|
|
1477
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
999
1478
|
},
|
|
1000
1479
|
credentials: "include"
|
|
1001
1480
|
});
|
|
1002
1481
|
if (!response.ok) {
|
|
1003
1482
|
const error = await response.json().catch(() => ({ error: "Failed to get receipt" }));
|
|
1004
1483
|
const code = response.status === 404 ? "RECEIPT_NOT_AVAILABLE" : "GET_RECEIPT_FAILED";
|
|
1005
|
-
throw new TiquoAuthError(
|
|
1484
|
+
throw new TiquoAuthError(
|
|
1485
|
+
error.error || "Failed to get receipt",
|
|
1486
|
+
code,
|
|
1487
|
+
response.status
|
|
1488
|
+
);
|
|
1006
1489
|
}
|
|
1007
1490
|
const result = await response.json();
|
|
1008
1491
|
return result.data;
|
|
@@ -1027,13 +1510,17 @@ var TiquoAuth = class {
|
|
|
1027
1510
|
const response = await fetch(url.toString(), {
|
|
1028
1511
|
method: "GET",
|
|
1029
1512
|
headers: {
|
|
1030
|
-
|
|
1513
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
1031
1514
|
},
|
|
1032
1515
|
credentials: "include"
|
|
1033
1516
|
});
|
|
1034
1517
|
if (!response.ok) {
|
|
1035
1518
|
const error = await response.json().catch(() => ({ error: "Failed to get enquiries" }));
|
|
1036
|
-
throw new TiquoAuthError(
|
|
1519
|
+
throw new TiquoAuthError(
|
|
1520
|
+
error.error || "Failed to get enquiries",
|
|
1521
|
+
"GET_ENQUIRIES_FAILED",
|
|
1522
|
+
response.status
|
|
1523
|
+
);
|
|
1037
1524
|
}
|
|
1038
1525
|
const result = await response.json();
|
|
1039
1526
|
return result.data || { enquiries: [], hasMore: false };
|
|
@@ -1051,16 +1538,23 @@ var TiquoAuth = class {
|
|
|
1051
1538
|
async getCompanies() {
|
|
1052
1539
|
await this.ensureValidToken();
|
|
1053
1540
|
this.log("Fetching customer companies");
|
|
1054
|
-
const response = await fetch(
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
"
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1541
|
+
const response = await fetch(
|
|
1542
|
+
`${this.config.apiEndpoint}/api/client/v1/companies`,
|
|
1543
|
+
{
|
|
1544
|
+
method: "GET",
|
|
1545
|
+
headers: {
|
|
1546
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
1547
|
+
},
|
|
1548
|
+
credentials: "include"
|
|
1549
|
+
}
|
|
1550
|
+
);
|
|
1061
1551
|
if (!response.ok) {
|
|
1062
1552
|
const error = await response.json().catch(() => ({ error: "Failed to get companies" }));
|
|
1063
|
-
throw new TiquoAuthError(
|
|
1553
|
+
throw new TiquoAuthError(
|
|
1554
|
+
error.error || "Failed to get companies",
|
|
1555
|
+
"GET_COMPANIES_FAILED",
|
|
1556
|
+
response.status
|
|
1557
|
+
);
|
|
1064
1558
|
}
|
|
1065
1559
|
const result = await response.json();
|
|
1066
1560
|
return result.data || { companies: [] };
|
|
@@ -1082,19 +1576,25 @@ var TiquoAuth = class {
|
|
|
1082
1576
|
async getCompanyColleagues(companyId) {
|
|
1083
1577
|
await this.ensureValidToken();
|
|
1084
1578
|
this.log("Fetching company colleagues for:", companyId);
|
|
1085
|
-
const url = new URL(
|
|
1579
|
+
const url = new URL(
|
|
1580
|
+
`${this.config.apiEndpoint}/api/client/v1/companies/colleagues`
|
|
1581
|
+
);
|
|
1086
1582
|
url.searchParams.set("companyId", companyId);
|
|
1087
1583
|
const response = await fetch(url.toString(), {
|
|
1088
1584
|
method: "GET",
|
|
1089
1585
|
headers: {
|
|
1090
|
-
|
|
1586
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
1091
1587
|
},
|
|
1092
1588
|
credentials: "include"
|
|
1093
1589
|
});
|
|
1094
1590
|
if (!response.ok) {
|
|
1095
1591
|
const error = await response.json().catch(() => ({ error: "Failed to get colleagues" }));
|
|
1096
1592
|
const code = response.status === 403 ? "NOT_COMPANY_ADMIN" : "GET_COLLEAGUES_FAILED";
|
|
1097
|
-
throw new TiquoAuthError(
|
|
1593
|
+
throw new TiquoAuthError(
|
|
1594
|
+
error.error || "Failed to get colleagues",
|
|
1595
|
+
code,
|
|
1596
|
+
response.status
|
|
1597
|
+
);
|
|
1098
1598
|
}
|
|
1099
1599
|
const result = await response.json();
|
|
1100
1600
|
return result.data;
|
|
@@ -1115,13 +1615,17 @@ var TiquoAuth = class {
|
|
|
1115
1615
|
});
|
|
1116
1616
|
if (!response.ok) {
|
|
1117
1617
|
const error = await response.json().catch(() => ({ error: "Failed to generate token" }));
|
|
1118
|
-
throw new TiquoAuthError(
|
|
1618
|
+
throw new TiquoAuthError(
|
|
1619
|
+
error.error || "Failed to generate token",
|
|
1620
|
+
"IFRAME_TOKEN_FAILED",
|
|
1621
|
+
response.status
|
|
1622
|
+
);
|
|
1119
1623
|
}
|
|
1120
1624
|
return response.json();
|
|
1121
1625
|
}
|
|
1122
1626
|
/**
|
|
1123
1627
|
* Embed a customer flow with automatic authentication
|
|
1124
|
-
*
|
|
1628
|
+
*
|
|
1125
1629
|
* @param flowUrl - The URL of the customer flow (book.tiquo.app/...)
|
|
1126
1630
|
* @param container - Container element or selector
|
|
1127
1631
|
* @param options - Optional iframe configuration
|
|
@@ -1129,7 +1633,10 @@ var TiquoAuth = class {
|
|
|
1129
1633
|
async embedCustomerFlow(flowUrl, container, options) {
|
|
1130
1634
|
const containerEl = typeof container === "string" ? document.querySelector(container) : container;
|
|
1131
1635
|
if (!containerEl) {
|
|
1132
|
-
throw new TiquoAuthError(
|
|
1636
|
+
throw new TiquoAuthError(
|
|
1637
|
+
"Container element not found",
|
|
1638
|
+
"CONTAINER_NOT_FOUND"
|
|
1639
|
+
);
|
|
1133
1640
|
}
|
|
1134
1641
|
let authToken;
|
|
1135
1642
|
if (this.accessToken) {
|
|
@@ -1155,7 +1662,10 @@ var TiquoAuth = class {
|
|
|
1155
1662
|
iframe.addEventListener("load", options.onLoad);
|
|
1156
1663
|
}
|
|
1157
1664
|
if (options?.onError) {
|
|
1158
|
-
iframe.addEventListener(
|
|
1665
|
+
iframe.addEventListener(
|
|
1666
|
+
"error",
|
|
1667
|
+
() => options.onError(new Error("Failed to load iframe"))
|
|
1668
|
+
);
|
|
1159
1669
|
}
|
|
1160
1670
|
containerEl.innerHTML = "";
|
|
1161
1671
|
containerEl.appendChild(iframe);
|
|
@@ -1284,12 +1794,50 @@ var TiquoAuth = class {
|
|
|
1284
1794
|
this.accessToken = accessToken;
|
|
1285
1795
|
this.refreshToken = params.get("refresh_token");
|
|
1286
1796
|
if (window.history?.replaceState) {
|
|
1287
|
-
window.history.replaceState(
|
|
1797
|
+
window.history.replaceState(
|
|
1798
|
+
null,
|
|
1799
|
+
"",
|
|
1800
|
+
window.location.pathname + window.location.search
|
|
1801
|
+
);
|
|
1288
1802
|
}
|
|
1289
1803
|
return;
|
|
1290
1804
|
}
|
|
1291
1805
|
}
|
|
1292
1806
|
}
|
|
1807
|
+
extractUploadableProfilePhoto(profilePhoto) {
|
|
1808
|
+
if (typeof Blob !== "undefined" && profilePhoto instanceof Blob) {
|
|
1809
|
+
return profilePhoto;
|
|
1810
|
+
}
|
|
1811
|
+
if (typeof profilePhoto === "string") {
|
|
1812
|
+
const trimmed = profilePhoto.trim();
|
|
1813
|
+
if (trimmed.startsWith("data:") || trimmed.startsWith("blob:")) {
|
|
1814
|
+
return trimmed;
|
|
1815
|
+
}
|
|
1816
|
+
}
|
|
1817
|
+
return null;
|
|
1818
|
+
}
|
|
1819
|
+
isProfilePhotoBlobUrl(photo) {
|
|
1820
|
+
return photo.trim().startsWith("data:") || photo.trim().startsWith("blob:");
|
|
1821
|
+
}
|
|
1822
|
+
async profilePhotoToBlob(photo) {
|
|
1823
|
+
if (typeof Blob !== "undefined" && photo instanceof Blob) {
|
|
1824
|
+
return photo;
|
|
1825
|
+
}
|
|
1826
|
+
if (typeof photo === "string" && this.isProfilePhotoBlobUrl(photo)) {
|
|
1827
|
+
const response = await fetch(photo);
|
|
1828
|
+
if (!response.ok) {
|
|
1829
|
+
throw new TiquoAuthError(
|
|
1830
|
+
"Failed to read profile photo URI",
|
|
1831
|
+
"INVALID_PROFILE_PHOTO"
|
|
1832
|
+
);
|
|
1833
|
+
}
|
|
1834
|
+
return response.blob();
|
|
1835
|
+
}
|
|
1836
|
+
throw new TiquoAuthError(
|
|
1837
|
+
"uploadProfilePhoto expects a File, Blob, data URI, or blob URI. Use updateProfile({ profilePhoto: url }) for remote URLs.",
|
|
1838
|
+
"INVALID_PROFILE_PHOTO"
|
|
1839
|
+
);
|
|
1840
|
+
}
|
|
1293
1841
|
async request(path, options) {
|
|
1294
1842
|
const url = `${this.config.apiEndpoint}${path}`;
|
|
1295
1843
|
const headers = {
|
|
@@ -1349,16 +1897,19 @@ var TiquoAuth = class {
|
|
|
1349
1897
|
this.isRefreshing = true;
|
|
1350
1898
|
this.log("Refreshing access token");
|
|
1351
1899
|
try {
|
|
1352
|
-
const response = await fetch(
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1900
|
+
const response = await fetch(
|
|
1901
|
+
`${this.config.apiEndpoint}/api/client/v1/refresh`,
|
|
1902
|
+
{
|
|
1903
|
+
method: "POST",
|
|
1904
|
+
headers: {
|
|
1905
|
+
"Content-Type": "application/json"
|
|
1906
|
+
},
|
|
1907
|
+
body: JSON.stringify({
|
|
1908
|
+
refresh_token: this.refreshToken
|
|
1909
|
+
}),
|
|
1910
|
+
credentials: "include"
|
|
1911
|
+
}
|
|
1912
|
+
);
|
|
1362
1913
|
if (!response.ok) {
|
|
1363
1914
|
this.log("Token refresh failed, clearing session");
|
|
1364
1915
|
this.clearTokens();
|
|
@@ -1395,13 +1946,16 @@ var TiquoAuth = class {
|
|
|
1395
1946
|
}
|
|
1396
1947
|
try {
|
|
1397
1948
|
await this.refreshTokenIfNeeded();
|
|
1398
|
-
const response = await fetch(
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
"
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1949
|
+
const response = await fetch(
|
|
1950
|
+
`${this.config.apiEndpoint}/api/client/v1/profile`,
|
|
1951
|
+
{
|
|
1952
|
+
method: "GET",
|
|
1953
|
+
headers: {
|
|
1954
|
+
Authorization: `Bearer ${this.accessToken}`
|
|
1955
|
+
},
|
|
1956
|
+
credentials: "include"
|
|
1957
|
+
}
|
|
1958
|
+
);
|
|
1405
1959
|
if (!response.ok) {
|
|
1406
1960
|
this.log("Session invalid, clearing");
|
|
1407
1961
|
this.clearTokens();
|
|
@@ -1419,6 +1973,9 @@ var TiquoAuth = class {
|
|
|
1419
1973
|
if (this.session.user?.id) {
|
|
1420
1974
|
addCustomerUserId(this.session.user.id);
|
|
1421
1975
|
}
|
|
1976
|
+
if (this.session.customer) {
|
|
1977
|
+
this.analytics?.identify({ identityLinkType: "auth_dom_login" }).catch(() => void 0);
|
|
1978
|
+
}
|
|
1422
1979
|
this.notifyListeners();
|
|
1423
1980
|
this.scheduleRefresh();
|
|
1424
1981
|
return this.session;
|
|
@@ -1453,8 +2010,12 @@ var TiquoAuth = class {
|
|
|
1453
2010
|
return;
|
|
1454
2011
|
}
|
|
1455
2012
|
try {
|
|
1456
|
-
const accessToken = localStorage.getItem(
|
|
1457
|
-
|
|
2013
|
+
const accessToken = localStorage.getItem(
|
|
2014
|
+
`${this.config.storagePrefix}access_token`
|
|
2015
|
+
);
|
|
2016
|
+
const refreshToken = localStorage.getItem(
|
|
2017
|
+
`${this.config.storagePrefix}refresh_token`
|
|
2018
|
+
);
|
|
1458
2019
|
if (accessToken) {
|
|
1459
2020
|
this.accessToken = accessToken;
|
|
1460
2021
|
this.refreshToken = refreshToken;
|
|
@@ -1566,7 +2127,12 @@ var TiquoAuth = class {
|
|
|
1566
2127
|
if (message.tabId === this.tabId) return;
|
|
1567
2128
|
if (this.isProcessingTabSync) return;
|
|
1568
2129
|
this.isProcessingTabSync = true;
|
|
1569
|
-
this.log(
|
|
2130
|
+
this.log(
|
|
2131
|
+
"Received tab sync message:",
|
|
2132
|
+
message.type,
|
|
2133
|
+
"from tab:",
|
|
2134
|
+
message.tabId
|
|
2135
|
+
);
|
|
1570
2136
|
try {
|
|
1571
2137
|
switch (message.type) {
|
|
1572
2138
|
case "LOGIN":
|
|
@@ -1593,7 +2159,9 @@ var TiquoAuth = class {
|
|
|
1593
2159
|
}
|
|
1594
2160
|
try {
|
|
1595
2161
|
localStorage.removeItem(`${this.config.storagePrefix}access_token`);
|
|
1596
|
-
localStorage.removeItem(
|
|
2162
|
+
localStorage.removeItem(
|
|
2163
|
+
`${this.config.storagePrefix}refresh_token`
|
|
2164
|
+
);
|
|
1597
2165
|
} catch {
|
|
1598
2166
|
}
|
|
1599
2167
|
this.notifyListeners();
|
|
@@ -1665,6 +2233,7 @@ function useTiquoAuth(auth) {
|
|
|
1665
2233
|
verifyOTP: (email, otp) => auth.verifyOTP(email, otp),
|
|
1666
2234
|
logout: () => auth.logout(),
|
|
1667
2235
|
updateProfile: (updates) => auth.updateProfile(updates),
|
|
2236
|
+
uploadProfilePhoto: (photo) => auth.uploadProfilePhoto(photo),
|
|
1668
2237
|
getOrders: (options) => auth.getOrders(options),
|
|
1669
2238
|
getBookings: (options) => auth.getBookings(options),
|
|
1670
2239
|
getUpcomingBookings: (options) => auth.getUpcomingBookings(options),
|
|
@@ -1695,8 +2264,10 @@ TiquoPhone.getDialCode = getDialCode;
|
|
|
1695
2264
|
TiquoPhone.buildPhone = buildPhone;
|
|
1696
2265
|
var index_default = TiquoAuth;
|
|
1697
2266
|
export {
|
|
2267
|
+
TiquoAnalytics,
|
|
1698
2268
|
TiquoAuth,
|
|
1699
2269
|
TiquoAuthError,
|
|
2270
|
+
TiquoCMS,
|
|
1700
2271
|
TiquoPhone,
|
|
1701
2272
|
addCustomerUserId,
|
|
1702
2273
|
clearCachedEmail,
|