@tiquo/dom-package 1.0.1 → 1.1.0

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/dist/index.d.mts CHANGED
@@ -1,3 +1,66 @@
1
+ /**
2
+ * Customer User ID Cookie Utility
3
+ *
4
+ * This module handles setting a cross-subdomain cookie that stores customer user IDs.
5
+ * The cookie is shared across all *.tiquo.app subdomains and persists for 1 year.
6
+ *
7
+ * The cookie is NOT set if the user is logged in with Clerk (dashboard staff).
8
+ */
9
+ /**
10
+ * Check if the current user is authenticated via Clerk (dashboard staff).
11
+ * If they are, we should NOT set the customer cookie.
12
+ */
13
+ declare function isClerkAuthenticated(): boolean;
14
+ /**
15
+ * Get the list of customer user IDs from the cookie.
16
+ */
17
+ declare function getCustomerUserIds(): string[];
18
+ /**
19
+ * Add a customer user ID to the cookie.
20
+ * Does nothing if:
21
+ * - The user is authenticated via Clerk (dashboard staff)
22
+ * - The user ID is already in the cookie
23
+ * - Running in a non-browser environment
24
+ *
25
+ * @param userId - The user ID from the users table to add
26
+ */
27
+ declare function addCustomerUserId(userId: string): void;
28
+ /**
29
+ * Get the pre-filled email from the customer cookie.
30
+ * This fetches the user's email associated with the cookie user IDs.
31
+ * Results are cached for 5 minutes to avoid repeated API calls.
32
+ *
33
+ * @param organizationId - The Clerk organization ID
34
+ * @returns Promise with email and optional name fields, or null if not found
35
+ */
36
+ declare function getPrefilledEmailFromCookie(organizationId: string): Promise<{
37
+ email: string;
38
+ firstName?: string;
39
+ lastName?: string;
40
+ } | null>;
41
+ /**
42
+ * Clear the cached email data.
43
+ * Call this when the user logs out or clears cookies.
44
+ */
45
+ declare function clearCachedEmail(): void;
46
+ /**
47
+ * Track customer presence when the cookie is detected.
48
+ * This updates the customer's online status and logs activity.
49
+ *
50
+ * @param organizationId - The Clerk organization ID
51
+ * @returns Promise with tracking results
52
+ */
53
+ declare function trackCustomerPresence(organizationId: string): Promise<{
54
+ success: boolean;
55
+ results?: Array<{
56
+ userId: string;
57
+ orgCustomerId?: string;
58
+ customerName?: string;
59
+ tracked: boolean;
60
+ }>;
61
+ error?: string;
62
+ }>;
63
+
1
64
  /**
2
65
  * @tiquo/dom-package
3
66
  *
@@ -42,6 +105,7 @@
42
105
  * // https://yoursite.com/#access_token=eyJ...&refresh_token=rt_...
43
106
  * ```
44
107
  */
108
+
45
109
  interface TiquoAuthConfig {
46
110
  /** Public key from your Tiquo Auth DOM settings */
47
111
  publicKey: string;
@@ -70,14 +134,35 @@ interface TiquoUser {
70
134
  id: string;
71
135
  email: string;
72
136
  }
137
+ interface TiquoCustomerEmail {
138
+ address: string;
139
+ isPrimary: boolean;
140
+ order: number;
141
+ }
142
+ interface TiquoCustomerPhone {
143
+ number: string;
144
+ isPrimary: boolean;
145
+ order: number;
146
+ }
73
147
  interface TiquoCustomer {
74
148
  id: string;
75
149
  firstName?: string;
76
150
  lastName?: string;
77
151
  displayName?: string;
78
152
  customerNumber: string;
153
+ /** Primary email address (convenience field derived from emails array) */
79
154
  email?: string;
155
+ /** Primary phone number (convenience field derived from phones array) */
80
156
  phone?: string;
157
+ profilePhoto?: string;
158
+ status?: string;
159
+ totalOrders?: number;
160
+ totalSpent?: number;
161
+ lifetimeValue?: number;
162
+ /** Full list of customer email addresses */
163
+ emails?: TiquoCustomerEmail[];
164
+ /** Full list of customer phone numbers */
165
+ phones?: TiquoCustomerPhone[];
81
166
  }
82
167
  interface TiquoSession {
83
168
  user: TiquoUser;
@@ -107,12 +192,12 @@ interface ProfileUpdateData {
107
192
  displayName?: string;
108
193
  phone?: string;
109
194
  profilePhoto?: string;
195
+ emails?: TiquoCustomerEmail[];
196
+ phones?: TiquoCustomerPhone[];
110
197
  }
111
198
  interface ProfileUpdateResult {
112
199
  success: boolean;
113
- customer: TiquoCustomer & {
114
- profilePhoto?: string;
115
- };
200
+ customer: TiquoCustomer;
116
201
  }
117
202
  interface TiquoOrderItem {
118
203
  id: string;
@@ -126,7 +211,7 @@ interface TiquoOrder {
126
211
  id: string;
127
212
  orderNumber: string;
128
213
  status: 'draft' | 'pending' | 'confirmed' | 'processing' | 'completed' | 'cancelled' | 'refunded' | 'open_tab';
129
- paymentStatus: 'pending' | 'paid' | 'partial' | 'refunded' | 'failed' | 'cancelled';
214
+ paymentStatus: 'pending' | 'paid' | 'partial' | 'refunded' | 'partially_refunded' | 'failed' | 'cancelled';
130
215
  total: number;
131
216
  subtotal: number;
132
217
  taxTotal: number;
@@ -149,7 +234,6 @@ interface GetOrdersResult {
149
234
  interface TiquoBooking {
150
235
  id: string;
151
236
  bookingNumber: string;
152
- confirmationCode: string;
153
237
  status: 'draft' | 'scheduled' | 'confirmed' | 'reminder_sent' | 'waiting_room' | 'waiting_list' | 'checked_in' | 'active' | 'in_progress' | 'completed' | 'cancelled' | 'no_show' | 'rescheduled';
154
238
  date: number;
155
239
  startTime: string;
@@ -355,4 +439,4 @@ declare function useTiquoAuth(auth: TiquoAuth): {
355
439
  onAuthStateChange: (cb: AuthStateChangeCallback) => () => void;
356
440
  };
357
441
 
358
- export { type AuthStateChangeCallback, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, type TiquoSession, type TiquoUser, type VerifyOTPResult, TiquoAuth as default, useTiquoAuth };
442
+ export { type AuthStateChangeCallback, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isClerkAuthenticated, trackCustomerPresence, useTiquoAuth };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,66 @@
1
+ /**
2
+ * Customer User ID Cookie Utility
3
+ *
4
+ * This module handles setting a cross-subdomain cookie that stores customer user IDs.
5
+ * The cookie is shared across all *.tiquo.app subdomains and persists for 1 year.
6
+ *
7
+ * The cookie is NOT set if the user is logged in with Clerk (dashboard staff).
8
+ */
9
+ /**
10
+ * Check if the current user is authenticated via Clerk (dashboard staff).
11
+ * If they are, we should NOT set the customer cookie.
12
+ */
13
+ declare function isClerkAuthenticated(): boolean;
14
+ /**
15
+ * Get the list of customer user IDs from the cookie.
16
+ */
17
+ declare function getCustomerUserIds(): string[];
18
+ /**
19
+ * Add a customer user ID to the cookie.
20
+ * Does nothing if:
21
+ * - The user is authenticated via Clerk (dashboard staff)
22
+ * - The user ID is already in the cookie
23
+ * - Running in a non-browser environment
24
+ *
25
+ * @param userId - The user ID from the users table to add
26
+ */
27
+ declare function addCustomerUserId(userId: string): void;
28
+ /**
29
+ * Get the pre-filled email from the customer cookie.
30
+ * This fetches the user's email associated with the cookie user IDs.
31
+ * Results are cached for 5 minutes to avoid repeated API calls.
32
+ *
33
+ * @param organizationId - The Clerk organization ID
34
+ * @returns Promise with email and optional name fields, or null if not found
35
+ */
36
+ declare function getPrefilledEmailFromCookie(organizationId: string): Promise<{
37
+ email: string;
38
+ firstName?: string;
39
+ lastName?: string;
40
+ } | null>;
41
+ /**
42
+ * Clear the cached email data.
43
+ * Call this when the user logs out or clears cookies.
44
+ */
45
+ declare function clearCachedEmail(): void;
46
+ /**
47
+ * Track customer presence when the cookie is detected.
48
+ * This updates the customer's online status and logs activity.
49
+ *
50
+ * @param organizationId - The Clerk organization ID
51
+ * @returns Promise with tracking results
52
+ */
53
+ declare function trackCustomerPresence(organizationId: string): Promise<{
54
+ success: boolean;
55
+ results?: Array<{
56
+ userId: string;
57
+ orgCustomerId?: string;
58
+ customerName?: string;
59
+ tracked: boolean;
60
+ }>;
61
+ error?: string;
62
+ }>;
63
+
1
64
  /**
2
65
  * @tiquo/dom-package
3
66
  *
@@ -42,6 +105,7 @@
42
105
  * // https://yoursite.com/#access_token=eyJ...&refresh_token=rt_...
43
106
  * ```
44
107
  */
108
+
45
109
  interface TiquoAuthConfig {
46
110
  /** Public key from your Tiquo Auth DOM settings */
47
111
  publicKey: string;
@@ -70,14 +134,35 @@ interface TiquoUser {
70
134
  id: string;
71
135
  email: string;
72
136
  }
137
+ interface TiquoCustomerEmail {
138
+ address: string;
139
+ isPrimary: boolean;
140
+ order: number;
141
+ }
142
+ interface TiquoCustomerPhone {
143
+ number: string;
144
+ isPrimary: boolean;
145
+ order: number;
146
+ }
73
147
  interface TiquoCustomer {
74
148
  id: string;
75
149
  firstName?: string;
76
150
  lastName?: string;
77
151
  displayName?: string;
78
152
  customerNumber: string;
153
+ /** Primary email address (convenience field derived from emails array) */
79
154
  email?: string;
155
+ /** Primary phone number (convenience field derived from phones array) */
80
156
  phone?: string;
157
+ profilePhoto?: string;
158
+ status?: string;
159
+ totalOrders?: number;
160
+ totalSpent?: number;
161
+ lifetimeValue?: number;
162
+ /** Full list of customer email addresses */
163
+ emails?: TiquoCustomerEmail[];
164
+ /** Full list of customer phone numbers */
165
+ phones?: TiquoCustomerPhone[];
81
166
  }
82
167
  interface TiquoSession {
83
168
  user: TiquoUser;
@@ -107,12 +192,12 @@ interface ProfileUpdateData {
107
192
  displayName?: string;
108
193
  phone?: string;
109
194
  profilePhoto?: string;
195
+ emails?: TiquoCustomerEmail[];
196
+ phones?: TiquoCustomerPhone[];
110
197
  }
111
198
  interface ProfileUpdateResult {
112
199
  success: boolean;
113
- customer: TiquoCustomer & {
114
- profilePhoto?: string;
115
- };
200
+ customer: TiquoCustomer;
116
201
  }
117
202
  interface TiquoOrderItem {
118
203
  id: string;
@@ -126,7 +211,7 @@ interface TiquoOrder {
126
211
  id: string;
127
212
  orderNumber: string;
128
213
  status: 'draft' | 'pending' | 'confirmed' | 'processing' | 'completed' | 'cancelled' | 'refunded' | 'open_tab';
129
- paymentStatus: 'pending' | 'paid' | 'partial' | 'refunded' | 'failed' | 'cancelled';
214
+ paymentStatus: 'pending' | 'paid' | 'partial' | 'refunded' | 'partially_refunded' | 'failed' | 'cancelled';
130
215
  total: number;
131
216
  subtotal: number;
132
217
  taxTotal: number;
@@ -149,7 +234,6 @@ interface GetOrdersResult {
149
234
  interface TiquoBooking {
150
235
  id: string;
151
236
  bookingNumber: string;
152
- confirmationCode: string;
153
237
  status: 'draft' | 'scheduled' | 'confirmed' | 'reminder_sent' | 'waiting_room' | 'waiting_list' | 'checked_in' | 'active' | 'in_progress' | 'completed' | 'cancelled' | 'no_show' | 'rescheduled';
154
238
  date: number;
155
239
  startTime: string;
@@ -355,4 +439,4 @@ declare function useTiquoAuth(auth: TiquoAuth): {
355
439
  onAuthStateChange: (cb: AuthStateChangeCallback) => () => void;
356
440
  };
357
441
 
358
- export { type AuthStateChangeCallback, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, type TiquoSession, type TiquoUser, type VerifyOTPResult, TiquoAuth as default, useTiquoAuth };
442
+ export { type AuthStateChangeCallback, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isClerkAuthenticated, trackCustomerPresence, useTiquoAuth };
package/dist/index.js CHANGED
@@ -22,10 +22,154 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  TiquoAuth: () => TiquoAuth,
24
24
  TiquoAuthError: () => TiquoAuthError,
25
+ addCustomerUserId: () => addCustomerUserId,
26
+ clearCachedEmail: () => clearCachedEmail,
25
27
  default: () => index_default,
28
+ getCustomerUserIds: () => getCustomerUserIds,
29
+ getPrefilledEmailFromCookie: () => getPrefilledEmailFromCookie,
30
+ isClerkAuthenticated: () => isClerkAuthenticated,
31
+ trackCustomerPresence: () => trackCustomerPresence,
26
32
  useTiquoAuth: () => useTiquoAuth
27
33
  });
28
34
  module.exports = __toCommonJS(index_exports);
35
+
36
+ // src/customer-cookie.ts
37
+ var COOKIE_NAME = "tiquo_customer_user_ids";
38
+ var COOKIE_MAX_AGE = 31536e3;
39
+ function isClerkAuthenticated() {
40
+ if (typeof document === "undefined") return false;
41
+ return document.cookie.includes("__clerk_db_jwt") || document.cookie.includes("__session");
42
+ }
43
+ function getCustomerUserIds() {
44
+ if (typeof document === "undefined") return [];
45
+ const match = document.cookie.match(new RegExp(`${COOKIE_NAME}=([^;]+)`));
46
+ if (match) {
47
+ try {
48
+ const decoded = decodeURIComponent(match[1]);
49
+ const parsed = JSON.parse(decoded);
50
+ if (Array.isArray(parsed)) {
51
+ return parsed.filter((id) => typeof id === "string");
52
+ }
53
+ } catch {
54
+ return [];
55
+ }
56
+ }
57
+ return [];
58
+ }
59
+ function addCustomerUserId(userId) {
60
+ if (typeof document === "undefined") return;
61
+ if (typeof window === "undefined") return;
62
+ if (isClerkAuthenticated()) {
63
+ console.log("[Customer Cookie] Skipping - Clerk user detected");
64
+ return;
65
+ }
66
+ if (!userId || typeof userId !== "string") {
67
+ console.warn("[Customer Cookie] Invalid userId provided");
68
+ return;
69
+ }
70
+ const existing = getCustomerUserIds();
71
+ if (existing.includes(userId)) {
72
+ console.log("[Customer Cookie] User ID already in cookie");
73
+ return;
74
+ }
75
+ existing.push(userId);
76
+ const hostname = window.location.hostname;
77
+ const isProduction = hostname.endsWith(".tiquo.app") || hostname === "tiquo.app";
78
+ const cookieParts = [
79
+ `${COOKIE_NAME}=${encodeURIComponent(JSON.stringify(existing))}`,
80
+ "path=/",
81
+ `max-age=${COOKIE_MAX_AGE}`,
82
+ "SameSite=Lax"
83
+ ];
84
+ if (isProduction) {
85
+ cookieParts.push("domain=.tiquo.app");
86
+ cookieParts.push("Secure");
87
+ }
88
+ document.cookie = cookieParts.join("; ");
89
+ console.log("[Customer Cookie] Added user ID to cookie:", userId);
90
+ }
91
+ var CONVEX_SITE_URL = "https://edge.tiquo.app";
92
+ var cachedEmailData = null;
93
+ var EMAIL_CACHE_TTL = 5 * 60 * 1e3;
94
+ async function getPrefilledEmailFromCookie(organizationId) {
95
+ if (typeof window === "undefined") {
96
+ return null;
97
+ }
98
+ if (isClerkAuthenticated()) {
99
+ return null;
100
+ }
101
+ const userIds = getCustomerUserIds();
102
+ if (userIds.length === 0) {
103
+ return null;
104
+ }
105
+ if (cachedEmailData && cachedEmailData.organizationId === organizationId && Date.now() - cachedEmailData.fetchedAt < EMAIL_CACHE_TTL) {
106
+ return {
107
+ email: cachedEmailData.email,
108
+ firstName: cachedEmailData.firstName,
109
+ lastName: cachedEmailData.lastName
110
+ };
111
+ }
112
+ try {
113
+ const response = await fetch(`${CONVEX_SITE_URL}/api/customer-cookie-email`, {
114
+ method: "POST",
115
+ headers: { "Content-Type": "application/json" },
116
+ body: JSON.stringify({ userIds, organizationId })
117
+ });
118
+ if (response.ok) {
119
+ const data = await response.json();
120
+ if (data.success && data.email) {
121
+ cachedEmailData = {
122
+ organizationId,
123
+ email: data.email,
124
+ firstName: data.firstName,
125
+ lastName: data.lastName,
126
+ fetchedAt: Date.now()
127
+ };
128
+ return {
129
+ email: data.email,
130
+ firstName: data.firstName,
131
+ lastName: data.lastName
132
+ };
133
+ }
134
+ }
135
+ return null;
136
+ } catch (error) {
137
+ console.error("[Customer Cookie] Failed to get prefilled email:", error);
138
+ return null;
139
+ }
140
+ }
141
+ function clearCachedEmail() {
142
+ cachedEmailData = null;
143
+ }
144
+ async function trackCustomerPresence(organizationId) {
145
+ if (typeof window === "undefined") {
146
+ return { success: false, error: "Not in browser environment" };
147
+ }
148
+ if (isClerkAuthenticated()) {
149
+ return { success: false, error: "Clerk user detected" };
150
+ }
151
+ const userIds = getCustomerUserIds();
152
+ if (userIds.length === 0) {
153
+ return { success: false, error: "No user IDs in cookie" };
154
+ }
155
+ try {
156
+ const response = await fetch(`${CONVEX_SITE_URL}/api/customer-presence`, {
157
+ method: "POST",
158
+ headers: { "Content-Type": "application/json" },
159
+ body: JSON.stringify({ userIds, organizationId })
160
+ });
161
+ if (response.ok) {
162
+ const data = await response.json();
163
+ return data;
164
+ }
165
+ return { success: false, error: "Failed to track presence" };
166
+ } catch (error) {
167
+ console.error("[Customer Cookie] Failed to track presence:", error);
168
+ return { success: false, error: "Network error" };
169
+ }
170
+ }
171
+
172
+ // src/index.ts
29
173
  var TiquoAuthError = class extends Error {
30
174
  constructor(message, code, statusCode) {
31
175
  super(message);
@@ -136,6 +280,9 @@ var TiquoAuth = class {
136
280
  this.refreshToken = result.refreshToken;
137
281
  this.saveTokens();
138
282
  await this.refreshSession();
283
+ if (this.session?.user?.id) {
284
+ addCustomerUserId(this.session.user.id);
285
+ }
139
286
  this.broadcastTabSync("LOGIN");
140
287
  return {
141
288
  success: true,
@@ -185,15 +332,7 @@ var TiquoAuth = class {
185
332
  if (this.session && result.data?.customer) {
186
333
  this.session = {
187
334
  ...this.session,
188
- customer: {
189
- id: result.data.customer.id,
190
- firstName: result.data.customer.firstName,
191
- lastName: result.data.customer.lastName,
192
- displayName: result.data.customer.displayName,
193
- customerNumber: result.data.customer.customerNumber,
194
- email: result.data.customer.email,
195
- phone: result.data.customer.phone
196
- }
335
+ customer: result.data.customer
197
336
  };
198
337
  this.notifyListeners();
199
338
  this.broadcastTabSync("SESSION_UPDATE");
@@ -341,7 +480,6 @@ var TiquoAuth = class {
341
480
  body: JSON.stringify({
342
481
  publicKey: this.config.publicKey,
343
482
  sessionToken: this.accessToken,
344
- // Use access token for backward compatibility
345
483
  customerFlowId
346
484
  })
347
485
  });
@@ -570,6 +708,9 @@ var TiquoAuth = class {
570
708
  customer: result.data.customer,
571
709
  expiresAt
572
710
  };
711
+ if (this.session.user?.id) {
712
+ addCustomerUserId(this.session.user.id);
713
+ }
573
714
  this.notifyListeners();
574
715
  this.scheduleRefresh();
575
716
  return this.session;
@@ -804,5 +945,11 @@ var index_default = TiquoAuth;
804
945
  0 && (module.exports = {
805
946
  TiquoAuth,
806
947
  TiquoAuthError,
948
+ addCustomerUserId,
949
+ clearCachedEmail,
950
+ getCustomerUserIds,
951
+ getPrefilledEmailFromCookie,
952
+ isClerkAuthenticated,
953
+ trackCustomerPresence,
807
954
  useTiquoAuth
808
955
  });
package/dist/index.mjs CHANGED
@@ -1,3 +1,139 @@
1
+ // src/customer-cookie.ts
2
+ var COOKIE_NAME = "tiquo_customer_user_ids";
3
+ var COOKIE_MAX_AGE = 31536e3;
4
+ function isClerkAuthenticated() {
5
+ if (typeof document === "undefined") return false;
6
+ return document.cookie.includes("__clerk_db_jwt") || document.cookie.includes("__session");
7
+ }
8
+ function getCustomerUserIds() {
9
+ if (typeof document === "undefined") return [];
10
+ const match = document.cookie.match(new RegExp(`${COOKIE_NAME}=([^;]+)`));
11
+ if (match) {
12
+ try {
13
+ const decoded = decodeURIComponent(match[1]);
14
+ const parsed = JSON.parse(decoded);
15
+ if (Array.isArray(parsed)) {
16
+ return parsed.filter((id) => typeof id === "string");
17
+ }
18
+ } catch {
19
+ return [];
20
+ }
21
+ }
22
+ return [];
23
+ }
24
+ function addCustomerUserId(userId) {
25
+ if (typeof document === "undefined") return;
26
+ if (typeof window === "undefined") return;
27
+ if (isClerkAuthenticated()) {
28
+ console.log("[Customer Cookie] Skipping - Clerk user detected");
29
+ return;
30
+ }
31
+ if (!userId || typeof userId !== "string") {
32
+ console.warn("[Customer Cookie] Invalid userId provided");
33
+ return;
34
+ }
35
+ const existing = getCustomerUserIds();
36
+ if (existing.includes(userId)) {
37
+ console.log("[Customer Cookie] User ID already in cookie");
38
+ return;
39
+ }
40
+ existing.push(userId);
41
+ const hostname = window.location.hostname;
42
+ const isProduction = hostname.endsWith(".tiquo.app") || hostname === "tiquo.app";
43
+ const cookieParts = [
44
+ `${COOKIE_NAME}=${encodeURIComponent(JSON.stringify(existing))}`,
45
+ "path=/",
46
+ `max-age=${COOKIE_MAX_AGE}`,
47
+ "SameSite=Lax"
48
+ ];
49
+ if (isProduction) {
50
+ cookieParts.push("domain=.tiquo.app");
51
+ cookieParts.push("Secure");
52
+ }
53
+ document.cookie = cookieParts.join("; ");
54
+ console.log("[Customer Cookie] Added user ID to cookie:", userId);
55
+ }
56
+ var CONVEX_SITE_URL = "https://edge.tiquo.app";
57
+ var cachedEmailData = null;
58
+ var EMAIL_CACHE_TTL = 5 * 60 * 1e3;
59
+ async function getPrefilledEmailFromCookie(organizationId) {
60
+ if (typeof window === "undefined") {
61
+ return null;
62
+ }
63
+ if (isClerkAuthenticated()) {
64
+ return null;
65
+ }
66
+ const userIds = getCustomerUserIds();
67
+ if (userIds.length === 0) {
68
+ return null;
69
+ }
70
+ if (cachedEmailData && cachedEmailData.organizationId === organizationId && Date.now() - cachedEmailData.fetchedAt < EMAIL_CACHE_TTL) {
71
+ return {
72
+ email: cachedEmailData.email,
73
+ firstName: cachedEmailData.firstName,
74
+ lastName: cachedEmailData.lastName
75
+ };
76
+ }
77
+ try {
78
+ const response = await fetch(`${CONVEX_SITE_URL}/api/customer-cookie-email`, {
79
+ method: "POST",
80
+ headers: { "Content-Type": "application/json" },
81
+ body: JSON.stringify({ userIds, organizationId })
82
+ });
83
+ if (response.ok) {
84
+ const data = await response.json();
85
+ if (data.success && data.email) {
86
+ cachedEmailData = {
87
+ organizationId,
88
+ email: data.email,
89
+ firstName: data.firstName,
90
+ lastName: data.lastName,
91
+ fetchedAt: Date.now()
92
+ };
93
+ return {
94
+ email: data.email,
95
+ firstName: data.firstName,
96
+ lastName: data.lastName
97
+ };
98
+ }
99
+ }
100
+ return null;
101
+ } catch (error) {
102
+ console.error("[Customer Cookie] Failed to get prefilled email:", error);
103
+ return null;
104
+ }
105
+ }
106
+ function clearCachedEmail() {
107
+ cachedEmailData = null;
108
+ }
109
+ async function trackCustomerPresence(organizationId) {
110
+ if (typeof window === "undefined") {
111
+ return { success: false, error: "Not in browser environment" };
112
+ }
113
+ if (isClerkAuthenticated()) {
114
+ return { success: false, error: "Clerk user detected" };
115
+ }
116
+ const userIds = getCustomerUserIds();
117
+ if (userIds.length === 0) {
118
+ return { success: false, error: "No user IDs in cookie" };
119
+ }
120
+ try {
121
+ const response = await fetch(`${CONVEX_SITE_URL}/api/customer-presence`, {
122
+ method: "POST",
123
+ headers: { "Content-Type": "application/json" },
124
+ body: JSON.stringify({ userIds, organizationId })
125
+ });
126
+ if (response.ok) {
127
+ const data = await response.json();
128
+ return data;
129
+ }
130
+ return { success: false, error: "Failed to track presence" };
131
+ } catch (error) {
132
+ console.error("[Customer Cookie] Failed to track presence:", error);
133
+ return { success: false, error: "Network error" };
134
+ }
135
+ }
136
+
1
137
  // src/index.ts
2
138
  var TiquoAuthError = class extends Error {
3
139
  constructor(message, code, statusCode) {
@@ -109,6 +245,9 @@ var TiquoAuth = class {
109
245
  this.refreshToken = result.refreshToken;
110
246
  this.saveTokens();
111
247
  await this.refreshSession();
248
+ if (this.session?.user?.id) {
249
+ addCustomerUserId(this.session.user.id);
250
+ }
112
251
  this.broadcastTabSync("LOGIN");
113
252
  return {
114
253
  success: true,
@@ -158,15 +297,7 @@ var TiquoAuth = class {
158
297
  if (this.session && result.data?.customer) {
159
298
  this.session = {
160
299
  ...this.session,
161
- customer: {
162
- id: result.data.customer.id,
163
- firstName: result.data.customer.firstName,
164
- lastName: result.data.customer.lastName,
165
- displayName: result.data.customer.displayName,
166
- customerNumber: result.data.customer.customerNumber,
167
- email: result.data.customer.email,
168
- phone: result.data.customer.phone
169
- }
300
+ customer: result.data.customer
170
301
  };
171
302
  this.notifyListeners();
172
303
  this.broadcastTabSync("SESSION_UPDATE");
@@ -314,7 +445,6 @@ var TiquoAuth = class {
314
445
  body: JSON.stringify({
315
446
  publicKey: this.config.publicKey,
316
447
  sessionToken: this.accessToken,
317
- // Use access token for backward compatibility
318
448
  customerFlowId
319
449
  })
320
450
  });
@@ -543,6 +673,9 @@ var TiquoAuth = class {
543
673
  customer: result.data.customer,
544
674
  expiresAt
545
675
  };
676
+ if (this.session.user?.id) {
677
+ addCustomerUserId(this.session.user.id);
678
+ }
546
679
  this.notifyListeners();
547
680
  this.scheduleRefresh();
548
681
  return this.session;
@@ -776,6 +909,12 @@ var index_default = TiquoAuth;
776
909
  export {
777
910
  TiquoAuth,
778
911
  TiquoAuthError,
912
+ addCustomerUserId,
913
+ clearCachedEmail,
779
914
  index_default as default,
915
+ getCustomerUserIds,
916
+ getPrefilledEmailFromCookie,
917
+ isClerkAuthenticated,
918
+ trackCustomerPresence,
780
919
  useTiquoAuth
781
920
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiquo/dom-package",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Tiquo SDK for third-party websites - authentication, customer profiles, orders, bookings, and enquiries",
5
5
  "publishConfig": {
6
6
  "access": "restricted"
@@ -17,6 +17,7 @@
17
17
  },
18
18
  "files": [
19
19
  "dist",
20
+ "scripts",
20
21
  "README.md"
21
22
  ],
22
23
  "scripts": {
@@ -24,7 +25,8 @@
24
25
  "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
25
26
  "lint": "eslint src/",
26
27
  "typecheck": "tsc --noEmit",
27
- "prepublishOnly": "npm run build"
28
+ "prepublishOnly": "npm run build",
29
+ "postinstall": "node scripts/postinstall.js"
28
30
  },
29
31
  "keywords": [
30
32
  "tiquo",
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env node
2
+
3
+ const asciiArt = `
4
+ _ _
5
+ | |_(_) __ _ _ _ ___
6
+ | __| |/ _\` | | | |/ _ \\
7
+ | |_| | (_| | |_| | (_) |
8
+ \\__|_|\\__, |\\__,_|\\___/
9
+ |_|
10
+ `;
11
+
12
+ console.log(asciiArt);
13
+ console.log('To find out more about Tiquo, visit \x1b[34mhttps://www.tiquo.co/\x1b[0m');
14
+ console.log('');