@tiquo/dom-package 1.4.1 → 1.5.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 +13 -1
- package/dist/index.d.mts +185 -2
- package/dist/index.d.ts +185 -2
- package/dist/index.js +256 -10
- package/dist/index.mjs +255 -10
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -137,12 +137,24 @@ const result = await auth.updateProfile({
|
|
|
137
137
|
console.log(result.customer.firstName); // 'John'
|
|
138
138
|
```
|
|
139
139
|
|
|
140
|
+
Profile photos can be passed as a URL, a browser `File`/`Blob`, or a `data:image/...`/`blob:...` URI:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
const file = fileInput.files?.[0];
|
|
144
|
+
if (file) {
|
|
145
|
+
await auth.updateProfile({ profilePhoto: file });
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// Or upload just the photo:
|
|
149
|
+
await auth.uploadProfilePhoto(file);
|
|
150
|
+
```
|
|
151
|
+
|
|
140
152
|
**Available fields:**
|
|
141
153
|
- `firstName` - Customer's first name
|
|
142
154
|
- `lastName` - Customer's last name
|
|
143
155
|
- `displayName` - Display name (nickname)
|
|
144
156
|
- `phone` - Primary phone number (E.164 format recommended: `+[country code][number]`)
|
|
145
|
-
- `profilePhoto` - URL
|
|
157
|
+
- `profilePhoto` - URL, File/Blob, or `data:image/...`/`blob:...` URI for profile photo
|
|
146
158
|
- `phones` - Full phone list (array of `{ number, isPrimary, order }`)
|
|
147
159
|
|
|
148
160
|
> **Important:** Phone numbers should include a country code (e.g., `+1` for US, `+44` for UK). Use `TiquoPhone.buildPhone()` to construct properly formatted numbers from a country selector + national number input. See [Phone Number Utilities](#phone-number-utilities) below.
|
package/dist/index.d.mts
CHANGED
|
@@ -209,6 +209,18 @@ declare function buildPhone(countryCode: string, nationalNumber: string): string
|
|
|
209
209
|
* ```
|
|
210
210
|
*/
|
|
211
211
|
|
|
212
|
+
declare class TiquoCMS {
|
|
213
|
+
private config;
|
|
214
|
+
constructor(config: TiquoCMSConfig);
|
|
215
|
+
/**
|
|
216
|
+
* Fetch a published CMS page for the website attached to this public key.
|
|
217
|
+
*
|
|
218
|
+
* This intentionally goes through the Tiquo edge API rather than exposing
|
|
219
|
+
* Convex connection details to the consuming website.
|
|
220
|
+
*/
|
|
221
|
+
getPage(request: TiquoCMSPageRequest): Promise<TiquoCMSPage | null>;
|
|
222
|
+
private log;
|
|
223
|
+
}
|
|
212
224
|
interface TiquoAuthConfig {
|
|
213
225
|
/** Public key from your Tiquo Auth DOM settings */
|
|
214
226
|
publicKey: string;
|
|
@@ -225,6 +237,53 @@ interface TiquoAuthConfig {
|
|
|
225
237
|
/** Pre-authenticated refresh token (for WebView injection from native apps) */
|
|
226
238
|
refreshToken?: string;
|
|
227
239
|
}
|
|
240
|
+
interface TiquoCMSConfig {
|
|
241
|
+
/** Public key from your Tiquo Auth DOM settings */
|
|
242
|
+
publicKey: string;
|
|
243
|
+
/** API endpoint (defaults to production) */
|
|
244
|
+
apiEndpoint?: string;
|
|
245
|
+
/** Enable debug logging */
|
|
246
|
+
debug?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface TiquoCMSPageRequest {
|
|
249
|
+
/** CMS website slug */
|
|
250
|
+
siteSlug: string;
|
|
251
|
+
/** CMS page slug, defaults to "home" */
|
|
252
|
+
pageSlug?: string;
|
|
253
|
+
/** Optional template contract guard */
|
|
254
|
+
templateId?: string;
|
|
255
|
+
}
|
|
256
|
+
interface TiquoCMSBlock {
|
|
257
|
+
id: string;
|
|
258
|
+
type: string;
|
|
259
|
+
props: Record<string, unknown>;
|
|
260
|
+
locked?: boolean;
|
|
261
|
+
lockedBy?: string;
|
|
262
|
+
required?: boolean;
|
|
263
|
+
}
|
|
264
|
+
interface TiquoCMSPage {
|
|
265
|
+
id: string;
|
|
266
|
+
site: {
|
|
267
|
+
id: string;
|
|
268
|
+
name: string;
|
|
269
|
+
slug?: string;
|
|
270
|
+
templateId?: string;
|
|
271
|
+
templateVersion?: number;
|
|
272
|
+
globalConfig?: unknown;
|
|
273
|
+
};
|
|
274
|
+
page: {
|
|
275
|
+
id: string;
|
|
276
|
+
title: string;
|
|
277
|
+
slug: string;
|
|
278
|
+
path: string;
|
|
279
|
+
blocks: TiquoCMSBlock[];
|
|
280
|
+
settings?: unknown;
|
|
281
|
+
metaTitle?: string;
|
|
282
|
+
metaDescription?: string;
|
|
283
|
+
publishedAt?: number;
|
|
284
|
+
updatedAt: number;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
228
287
|
declare global {
|
|
229
288
|
interface Window {
|
|
230
289
|
__TIQUO_INIT_TOKEN__?: {
|
|
@@ -305,7 +364,13 @@ interface ProfileUpdateData {
|
|
|
305
364
|
* for country+national input, or TiquoPhone.validate() to pre-check.
|
|
306
365
|
*/
|
|
307
366
|
phone?: string;
|
|
308
|
-
|
|
367
|
+
/**
|
|
368
|
+
* URL to a profile photo, a data/blob URI, or a browser File/Blob.
|
|
369
|
+
*
|
|
370
|
+
* File/Blob and data/blob URI values are uploaded to Tiquo storage before the
|
|
371
|
+
* profile is updated. Remote URLs are stored as-is.
|
|
372
|
+
*/
|
|
373
|
+
profilePhoto?: string | Blob;
|
|
309
374
|
emails?: TiquoCustomerEmail[];
|
|
310
375
|
/**
|
|
311
376
|
* Full phone list. Each number should be in E.164 format: +[country code][number].
|
|
@@ -317,6 +382,10 @@ interface ProfileUpdateResult {
|
|
|
317
382
|
success: boolean;
|
|
318
383
|
customer: TiquoCustomer;
|
|
319
384
|
}
|
|
385
|
+
interface ProfilePhotoUploadResult extends ProfileUpdateResult {
|
|
386
|
+
profilePhoto: string;
|
|
387
|
+
storageId: string;
|
|
388
|
+
}
|
|
320
389
|
interface TiquoOrderItem {
|
|
321
390
|
id: string;
|
|
322
391
|
name: string;
|
|
@@ -492,6 +561,80 @@ interface GetEnquiriesResult {
|
|
|
492
561
|
hasMore: boolean;
|
|
493
562
|
nextCursor?: string;
|
|
494
563
|
}
|
|
564
|
+
type TiquoCompanyRelationship = 'employee' | 'contractor' | 'manager' | 'executive' | 'owner' | 'contact' | 'other';
|
|
565
|
+
/**
|
|
566
|
+
* The authenticated customer's membership in a company. Each company the
|
|
567
|
+
* customer belongs to has its own membership record — a customer can be
|
|
568
|
+
* an admin of one company and a regular employee of another.
|
|
569
|
+
*/
|
|
570
|
+
interface TiquoCompanyMembership {
|
|
571
|
+
relationship: TiquoCompanyRelationship;
|
|
572
|
+
title?: string;
|
|
573
|
+
department?: string;
|
|
574
|
+
isPrimaryContact: boolean;
|
|
575
|
+
/** True when this customer can call `getCompanyColleagues(company.id)`. */
|
|
576
|
+
isCompanyAdmin: boolean;
|
|
577
|
+
startDate?: number;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* A company the authenticated customer is a member of. Bundles the
|
|
581
|
+
* company's public-ish details with the caller's own role inside it
|
|
582
|
+
* (`membership`). CRM/financial fields are intentionally omitted.
|
|
583
|
+
*/
|
|
584
|
+
interface TiquoCompany {
|
|
585
|
+
id: string;
|
|
586
|
+
name: string;
|
|
587
|
+
displayName?: string;
|
|
588
|
+
companyNumber: string;
|
|
589
|
+
description?: string;
|
|
590
|
+
email?: string;
|
|
591
|
+
phone?: string;
|
|
592
|
+
website?: string;
|
|
593
|
+
websites?: string[];
|
|
594
|
+
logo?: string;
|
|
595
|
+
addressLine1?: string;
|
|
596
|
+
addressLine2?: string;
|
|
597
|
+
city?: string;
|
|
598
|
+
state?: string;
|
|
599
|
+
postalCode?: string;
|
|
600
|
+
country?: string;
|
|
601
|
+
industry?: string;
|
|
602
|
+
companySize?: '1-10' | '11-50' | '51-200' | '201-500' | '501-1000' | '1000+';
|
|
603
|
+
status: 'active' | 'inactive' | 'archived';
|
|
604
|
+
type?: 'client' | 'prospect' | 'vendor' | 'partner' | 'other';
|
|
605
|
+
membership: TiquoCompanyMembership;
|
|
606
|
+
}
|
|
607
|
+
interface GetCompaniesResult {
|
|
608
|
+
companies: TiquoCompany[];
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* A colleague — another customer in the same company. Returned only to
|
|
612
|
+
* Company Admins via `getCompanyColleagues()`. Limited to display-card
|
|
613
|
+
* info; CRM/financial data is never exposed.
|
|
614
|
+
*/
|
|
615
|
+
interface TiquoCompanyColleague {
|
|
616
|
+
id: string;
|
|
617
|
+
firstName?: string;
|
|
618
|
+
lastName?: string;
|
|
619
|
+
displayName?: string;
|
|
620
|
+
profilePhoto?: string;
|
|
621
|
+
email?: string;
|
|
622
|
+
phone?: string;
|
|
623
|
+
relationship: TiquoCompanyRelationship;
|
|
624
|
+
title?: string;
|
|
625
|
+
department?: string;
|
|
626
|
+
isPrimaryContact: boolean;
|
|
627
|
+
isCompanyAdmin: boolean;
|
|
628
|
+
/** True when this colleague is the authenticated customer themselves. */
|
|
629
|
+
isSelf: boolean;
|
|
630
|
+
}
|
|
631
|
+
interface GetCompanyColleaguesResult {
|
|
632
|
+
company: {
|
|
633
|
+
id: string;
|
|
634
|
+
name: string;
|
|
635
|
+
};
|
|
636
|
+
colleagues: TiquoCompanyColleague[];
|
|
637
|
+
}
|
|
495
638
|
type AuthStateChangeCallback = (session: TiquoSession | null) => void;
|
|
496
639
|
declare class TiquoAuthError extends Error {
|
|
497
640
|
code: string;
|
|
@@ -541,6 +684,14 @@ declare class TiquoAuth {
|
|
|
541
684
|
* to construct from a country selector and national number.
|
|
542
685
|
*/
|
|
543
686
|
updateProfile(updates: ProfileUpdateData): Promise<ProfileUpdateResult>;
|
|
687
|
+
/**
|
|
688
|
+
* Upload and save the authenticated customer's profile photo.
|
|
689
|
+
*
|
|
690
|
+
* Accepts a browser File/Blob, `data:image/...` URI, or `blob:...` URI. The
|
|
691
|
+
* image is uploaded to Tiquo storage first, and the customer profile is
|
|
692
|
+
* updated with the URL.
|
|
693
|
+
*/
|
|
694
|
+
uploadProfilePhoto(photo: Blob | string): Promise<ProfilePhotoUploadResult>;
|
|
544
695
|
/**
|
|
545
696
|
* Log out the current user
|
|
546
697
|
*/
|
|
@@ -603,6 +754,32 @@ declare class TiquoAuth {
|
|
|
603
754
|
* Only returns enquiries for the logged-in customer
|
|
604
755
|
*/
|
|
605
756
|
getEnquiries(options?: GetEnquiriesOptions): Promise<GetEnquiriesResult>;
|
|
757
|
+
/**
|
|
758
|
+
* Get the companies the authenticated customer belongs to.
|
|
759
|
+
*
|
|
760
|
+
* Each entry includes the customer's role inside that company via
|
|
761
|
+
* `membership` — branch on `membership.isCompanyAdmin` to decide whether
|
|
762
|
+
* to render admin features (e.g. a colleagues list).
|
|
763
|
+
*
|
|
764
|
+
* Returns an empty array (not an error) when the customer isn't a
|
|
765
|
+
* member of any company.
|
|
766
|
+
*/
|
|
767
|
+
getCompanies(): Promise<GetCompaniesResult>;
|
|
768
|
+
/**
|
|
769
|
+
* Get the colleagues (other customers) inside a company the authenticated
|
|
770
|
+
* customer is a member of.
|
|
771
|
+
*
|
|
772
|
+
* Restricted to Company Admins — if the caller isn't flagged as
|
|
773
|
+
* `isCompanyAdmin` on that company, this throws `TiquoAuthError` with
|
|
774
|
+
* code `NOT_COMPANY_ADMIN` (status 403). Check `membership.isCompanyAdmin`
|
|
775
|
+
* from `getCompanies()` before calling this if you want to render the
|
|
776
|
+
* admin UI conditionally.
|
|
777
|
+
*
|
|
778
|
+
* Each colleague includes basic contact info and their relationship to
|
|
779
|
+
* the company. The authenticated customer is included in the list with
|
|
780
|
+
* `isSelf: true` so the UI can highlight or skip them.
|
|
781
|
+
*/
|
|
782
|
+
getCompanyColleagues(companyId: string): Promise<GetCompanyColleaguesResult>;
|
|
606
783
|
/**
|
|
607
784
|
* Generate a short-lived token for customer flow iframe authentication
|
|
608
785
|
*/
|
|
@@ -647,6 +824,9 @@ declare class TiquoAuth {
|
|
|
647
824
|
* Check for tokens injected by native apps (WebView integration)
|
|
648
825
|
*/
|
|
649
826
|
private checkForInjectedTokens;
|
|
827
|
+
private extractUploadableProfilePhoto;
|
|
828
|
+
private isProfilePhotoBlobUrl;
|
|
829
|
+
private profilePhotoToBlob;
|
|
650
830
|
private request;
|
|
651
831
|
/**
|
|
652
832
|
* Ensure we have a valid access token, refreshing if necessary
|
|
@@ -691,11 +871,14 @@ declare function useTiquoAuth(auth: TiquoAuth): {
|
|
|
691
871
|
verifyOTP: (email: string, otp: string) => Promise<VerifyOTPResult>;
|
|
692
872
|
logout: () => Promise<void>;
|
|
693
873
|
updateProfile: (updates: ProfileUpdateData) => Promise<ProfileUpdateResult>;
|
|
874
|
+
uploadProfilePhoto: (photo: Blob | string) => Promise<ProfilePhotoUploadResult>;
|
|
694
875
|
getOrders: (options?: GetOrdersOptions) => Promise<GetOrdersResult>;
|
|
695
876
|
getBookings: (options?: GetBookingsOptions) => Promise<GetBookingsResult>;
|
|
696
877
|
getUpcomingBookings: (options?: Omit<GetBookingsOptions, "upcoming">) => Promise<GetBookingsResult>;
|
|
697
878
|
getReceipt: (orderId: string) => Promise<TiquoReceipt>;
|
|
698
879
|
getEnquiries: (options?: GetEnquiriesOptions) => Promise<GetEnquiriesResult>;
|
|
880
|
+
getCompanies: () => Promise<GetCompaniesResult>;
|
|
881
|
+
getCompanyColleagues: (companyId: string) => Promise<GetCompanyColleaguesResult>;
|
|
699
882
|
getIframeToken: (flowId?: string) => Promise<IframeTokenResult>;
|
|
700
883
|
embedCustomerFlow: (flowUrl: string, container: HTMLElement | string, options?: {
|
|
701
884
|
width?: string;
|
|
@@ -758,4 +941,4 @@ declare class TiquoPhone {
|
|
|
758
941
|
static buildPhone: typeof buildPhone;
|
|
759
942
|
}
|
|
760
943
|
|
|
761
|
-
export { type AuthStateChangeCallback, type CountryPhoneInfo, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type PhoneValidationResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, TiquoPhone, type TiquoReceipt, type TiquoReceiptBusiness, type TiquoReceiptCustomer, type TiquoReceiptItem, type TiquoReceiptOrder, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isDashboardSession, trackCustomerPresence, useTiquoAuth };
|
|
944
|
+
export { type AuthStateChangeCallback, type CountryPhoneInfo, type GetBookingsOptions, type GetBookingsResult, type GetCompaniesResult, type GetCompanyColleaguesResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type PhoneValidationResult, type ProfilePhotoUploadResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, TiquoCMS, type TiquoCMSBlock, type TiquoCMSConfig, type TiquoCMSPage, type TiquoCMSPageRequest, type TiquoCompany, type TiquoCompanyColleague, type TiquoCompanyMembership, type TiquoCompanyRelationship, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, TiquoPhone, type TiquoReceipt, type TiquoReceiptBusiness, type TiquoReceiptCustomer, type TiquoReceiptItem, type TiquoReceiptOrder, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isDashboardSession, trackCustomerPresence, useTiquoAuth };
|
package/dist/index.d.ts
CHANGED
|
@@ -209,6 +209,18 @@ declare function buildPhone(countryCode: string, nationalNumber: string): string
|
|
|
209
209
|
* ```
|
|
210
210
|
*/
|
|
211
211
|
|
|
212
|
+
declare class TiquoCMS {
|
|
213
|
+
private config;
|
|
214
|
+
constructor(config: TiquoCMSConfig);
|
|
215
|
+
/**
|
|
216
|
+
* Fetch a published CMS page for the website attached to this public key.
|
|
217
|
+
*
|
|
218
|
+
* This intentionally goes through the Tiquo edge API rather than exposing
|
|
219
|
+
* Convex connection details to the consuming website.
|
|
220
|
+
*/
|
|
221
|
+
getPage(request: TiquoCMSPageRequest): Promise<TiquoCMSPage | null>;
|
|
222
|
+
private log;
|
|
223
|
+
}
|
|
212
224
|
interface TiquoAuthConfig {
|
|
213
225
|
/** Public key from your Tiquo Auth DOM settings */
|
|
214
226
|
publicKey: string;
|
|
@@ -225,6 +237,53 @@ interface TiquoAuthConfig {
|
|
|
225
237
|
/** Pre-authenticated refresh token (for WebView injection from native apps) */
|
|
226
238
|
refreshToken?: string;
|
|
227
239
|
}
|
|
240
|
+
interface TiquoCMSConfig {
|
|
241
|
+
/** Public key from your Tiquo Auth DOM settings */
|
|
242
|
+
publicKey: string;
|
|
243
|
+
/** API endpoint (defaults to production) */
|
|
244
|
+
apiEndpoint?: string;
|
|
245
|
+
/** Enable debug logging */
|
|
246
|
+
debug?: boolean;
|
|
247
|
+
}
|
|
248
|
+
interface TiquoCMSPageRequest {
|
|
249
|
+
/** CMS website slug */
|
|
250
|
+
siteSlug: string;
|
|
251
|
+
/** CMS page slug, defaults to "home" */
|
|
252
|
+
pageSlug?: string;
|
|
253
|
+
/** Optional template contract guard */
|
|
254
|
+
templateId?: string;
|
|
255
|
+
}
|
|
256
|
+
interface TiquoCMSBlock {
|
|
257
|
+
id: string;
|
|
258
|
+
type: string;
|
|
259
|
+
props: Record<string, unknown>;
|
|
260
|
+
locked?: boolean;
|
|
261
|
+
lockedBy?: string;
|
|
262
|
+
required?: boolean;
|
|
263
|
+
}
|
|
264
|
+
interface TiquoCMSPage {
|
|
265
|
+
id: string;
|
|
266
|
+
site: {
|
|
267
|
+
id: string;
|
|
268
|
+
name: string;
|
|
269
|
+
slug?: string;
|
|
270
|
+
templateId?: string;
|
|
271
|
+
templateVersion?: number;
|
|
272
|
+
globalConfig?: unknown;
|
|
273
|
+
};
|
|
274
|
+
page: {
|
|
275
|
+
id: string;
|
|
276
|
+
title: string;
|
|
277
|
+
slug: string;
|
|
278
|
+
path: string;
|
|
279
|
+
blocks: TiquoCMSBlock[];
|
|
280
|
+
settings?: unknown;
|
|
281
|
+
metaTitle?: string;
|
|
282
|
+
metaDescription?: string;
|
|
283
|
+
publishedAt?: number;
|
|
284
|
+
updatedAt: number;
|
|
285
|
+
};
|
|
286
|
+
}
|
|
228
287
|
declare global {
|
|
229
288
|
interface Window {
|
|
230
289
|
__TIQUO_INIT_TOKEN__?: {
|
|
@@ -305,7 +364,13 @@ interface ProfileUpdateData {
|
|
|
305
364
|
* for country+national input, or TiquoPhone.validate() to pre-check.
|
|
306
365
|
*/
|
|
307
366
|
phone?: string;
|
|
308
|
-
|
|
367
|
+
/**
|
|
368
|
+
* URL to a profile photo, a data/blob URI, or a browser File/Blob.
|
|
369
|
+
*
|
|
370
|
+
* File/Blob and data/blob URI values are uploaded to Tiquo storage before the
|
|
371
|
+
* profile is updated. Remote URLs are stored as-is.
|
|
372
|
+
*/
|
|
373
|
+
profilePhoto?: string | Blob;
|
|
309
374
|
emails?: TiquoCustomerEmail[];
|
|
310
375
|
/**
|
|
311
376
|
* Full phone list. Each number should be in E.164 format: +[country code][number].
|
|
@@ -317,6 +382,10 @@ interface ProfileUpdateResult {
|
|
|
317
382
|
success: boolean;
|
|
318
383
|
customer: TiquoCustomer;
|
|
319
384
|
}
|
|
385
|
+
interface ProfilePhotoUploadResult extends ProfileUpdateResult {
|
|
386
|
+
profilePhoto: string;
|
|
387
|
+
storageId: string;
|
|
388
|
+
}
|
|
320
389
|
interface TiquoOrderItem {
|
|
321
390
|
id: string;
|
|
322
391
|
name: string;
|
|
@@ -492,6 +561,80 @@ interface GetEnquiriesResult {
|
|
|
492
561
|
hasMore: boolean;
|
|
493
562
|
nextCursor?: string;
|
|
494
563
|
}
|
|
564
|
+
type TiquoCompanyRelationship = 'employee' | 'contractor' | 'manager' | 'executive' | 'owner' | 'contact' | 'other';
|
|
565
|
+
/**
|
|
566
|
+
* The authenticated customer's membership in a company. Each company the
|
|
567
|
+
* customer belongs to has its own membership record — a customer can be
|
|
568
|
+
* an admin of one company and a regular employee of another.
|
|
569
|
+
*/
|
|
570
|
+
interface TiquoCompanyMembership {
|
|
571
|
+
relationship: TiquoCompanyRelationship;
|
|
572
|
+
title?: string;
|
|
573
|
+
department?: string;
|
|
574
|
+
isPrimaryContact: boolean;
|
|
575
|
+
/** True when this customer can call `getCompanyColleagues(company.id)`. */
|
|
576
|
+
isCompanyAdmin: boolean;
|
|
577
|
+
startDate?: number;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* A company the authenticated customer is a member of. Bundles the
|
|
581
|
+
* company's public-ish details with the caller's own role inside it
|
|
582
|
+
* (`membership`). CRM/financial fields are intentionally omitted.
|
|
583
|
+
*/
|
|
584
|
+
interface TiquoCompany {
|
|
585
|
+
id: string;
|
|
586
|
+
name: string;
|
|
587
|
+
displayName?: string;
|
|
588
|
+
companyNumber: string;
|
|
589
|
+
description?: string;
|
|
590
|
+
email?: string;
|
|
591
|
+
phone?: string;
|
|
592
|
+
website?: string;
|
|
593
|
+
websites?: string[];
|
|
594
|
+
logo?: string;
|
|
595
|
+
addressLine1?: string;
|
|
596
|
+
addressLine2?: string;
|
|
597
|
+
city?: string;
|
|
598
|
+
state?: string;
|
|
599
|
+
postalCode?: string;
|
|
600
|
+
country?: string;
|
|
601
|
+
industry?: string;
|
|
602
|
+
companySize?: '1-10' | '11-50' | '51-200' | '201-500' | '501-1000' | '1000+';
|
|
603
|
+
status: 'active' | 'inactive' | 'archived';
|
|
604
|
+
type?: 'client' | 'prospect' | 'vendor' | 'partner' | 'other';
|
|
605
|
+
membership: TiquoCompanyMembership;
|
|
606
|
+
}
|
|
607
|
+
interface GetCompaniesResult {
|
|
608
|
+
companies: TiquoCompany[];
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* A colleague — another customer in the same company. Returned only to
|
|
612
|
+
* Company Admins via `getCompanyColleagues()`. Limited to display-card
|
|
613
|
+
* info; CRM/financial data is never exposed.
|
|
614
|
+
*/
|
|
615
|
+
interface TiquoCompanyColleague {
|
|
616
|
+
id: string;
|
|
617
|
+
firstName?: string;
|
|
618
|
+
lastName?: string;
|
|
619
|
+
displayName?: string;
|
|
620
|
+
profilePhoto?: string;
|
|
621
|
+
email?: string;
|
|
622
|
+
phone?: string;
|
|
623
|
+
relationship: TiquoCompanyRelationship;
|
|
624
|
+
title?: string;
|
|
625
|
+
department?: string;
|
|
626
|
+
isPrimaryContact: boolean;
|
|
627
|
+
isCompanyAdmin: boolean;
|
|
628
|
+
/** True when this colleague is the authenticated customer themselves. */
|
|
629
|
+
isSelf: boolean;
|
|
630
|
+
}
|
|
631
|
+
interface GetCompanyColleaguesResult {
|
|
632
|
+
company: {
|
|
633
|
+
id: string;
|
|
634
|
+
name: string;
|
|
635
|
+
};
|
|
636
|
+
colleagues: TiquoCompanyColleague[];
|
|
637
|
+
}
|
|
495
638
|
type AuthStateChangeCallback = (session: TiquoSession | null) => void;
|
|
496
639
|
declare class TiquoAuthError extends Error {
|
|
497
640
|
code: string;
|
|
@@ -541,6 +684,14 @@ declare class TiquoAuth {
|
|
|
541
684
|
* to construct from a country selector and national number.
|
|
542
685
|
*/
|
|
543
686
|
updateProfile(updates: ProfileUpdateData): Promise<ProfileUpdateResult>;
|
|
687
|
+
/**
|
|
688
|
+
* Upload and save the authenticated customer's profile photo.
|
|
689
|
+
*
|
|
690
|
+
* Accepts a browser File/Blob, `data:image/...` URI, or `blob:...` URI. The
|
|
691
|
+
* image is uploaded to Tiquo storage first, and the customer profile is
|
|
692
|
+
* updated with the URL.
|
|
693
|
+
*/
|
|
694
|
+
uploadProfilePhoto(photo: Blob | string): Promise<ProfilePhotoUploadResult>;
|
|
544
695
|
/**
|
|
545
696
|
* Log out the current user
|
|
546
697
|
*/
|
|
@@ -603,6 +754,32 @@ declare class TiquoAuth {
|
|
|
603
754
|
* Only returns enquiries for the logged-in customer
|
|
604
755
|
*/
|
|
605
756
|
getEnquiries(options?: GetEnquiriesOptions): Promise<GetEnquiriesResult>;
|
|
757
|
+
/**
|
|
758
|
+
* Get the companies the authenticated customer belongs to.
|
|
759
|
+
*
|
|
760
|
+
* Each entry includes the customer's role inside that company via
|
|
761
|
+
* `membership` — branch on `membership.isCompanyAdmin` to decide whether
|
|
762
|
+
* to render admin features (e.g. a colleagues list).
|
|
763
|
+
*
|
|
764
|
+
* Returns an empty array (not an error) when the customer isn't a
|
|
765
|
+
* member of any company.
|
|
766
|
+
*/
|
|
767
|
+
getCompanies(): Promise<GetCompaniesResult>;
|
|
768
|
+
/**
|
|
769
|
+
* Get the colleagues (other customers) inside a company the authenticated
|
|
770
|
+
* customer is a member of.
|
|
771
|
+
*
|
|
772
|
+
* Restricted to Company Admins — if the caller isn't flagged as
|
|
773
|
+
* `isCompanyAdmin` on that company, this throws `TiquoAuthError` with
|
|
774
|
+
* code `NOT_COMPANY_ADMIN` (status 403). Check `membership.isCompanyAdmin`
|
|
775
|
+
* from `getCompanies()` before calling this if you want to render the
|
|
776
|
+
* admin UI conditionally.
|
|
777
|
+
*
|
|
778
|
+
* Each colleague includes basic contact info and their relationship to
|
|
779
|
+
* the company. The authenticated customer is included in the list with
|
|
780
|
+
* `isSelf: true` so the UI can highlight or skip them.
|
|
781
|
+
*/
|
|
782
|
+
getCompanyColleagues(companyId: string): Promise<GetCompanyColleaguesResult>;
|
|
606
783
|
/**
|
|
607
784
|
* Generate a short-lived token for customer flow iframe authentication
|
|
608
785
|
*/
|
|
@@ -647,6 +824,9 @@ declare class TiquoAuth {
|
|
|
647
824
|
* Check for tokens injected by native apps (WebView integration)
|
|
648
825
|
*/
|
|
649
826
|
private checkForInjectedTokens;
|
|
827
|
+
private extractUploadableProfilePhoto;
|
|
828
|
+
private isProfilePhotoBlobUrl;
|
|
829
|
+
private profilePhotoToBlob;
|
|
650
830
|
private request;
|
|
651
831
|
/**
|
|
652
832
|
* Ensure we have a valid access token, refreshing if necessary
|
|
@@ -691,11 +871,14 @@ declare function useTiquoAuth(auth: TiquoAuth): {
|
|
|
691
871
|
verifyOTP: (email: string, otp: string) => Promise<VerifyOTPResult>;
|
|
692
872
|
logout: () => Promise<void>;
|
|
693
873
|
updateProfile: (updates: ProfileUpdateData) => Promise<ProfileUpdateResult>;
|
|
874
|
+
uploadProfilePhoto: (photo: Blob | string) => Promise<ProfilePhotoUploadResult>;
|
|
694
875
|
getOrders: (options?: GetOrdersOptions) => Promise<GetOrdersResult>;
|
|
695
876
|
getBookings: (options?: GetBookingsOptions) => Promise<GetBookingsResult>;
|
|
696
877
|
getUpcomingBookings: (options?: Omit<GetBookingsOptions, "upcoming">) => Promise<GetBookingsResult>;
|
|
697
878
|
getReceipt: (orderId: string) => Promise<TiquoReceipt>;
|
|
698
879
|
getEnquiries: (options?: GetEnquiriesOptions) => Promise<GetEnquiriesResult>;
|
|
880
|
+
getCompanies: () => Promise<GetCompaniesResult>;
|
|
881
|
+
getCompanyColleagues: (companyId: string) => Promise<GetCompanyColleaguesResult>;
|
|
699
882
|
getIframeToken: (flowId?: string) => Promise<IframeTokenResult>;
|
|
700
883
|
embedCustomerFlow: (flowUrl: string, container: HTMLElement | string, options?: {
|
|
701
884
|
width?: string;
|
|
@@ -758,4 +941,4 @@ declare class TiquoPhone {
|
|
|
758
941
|
static buildPhone: typeof buildPhone;
|
|
759
942
|
}
|
|
760
943
|
|
|
761
|
-
export { type AuthStateChangeCallback, type CountryPhoneInfo, type GetBookingsOptions, type GetBookingsResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type PhoneValidationResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, TiquoPhone, type TiquoReceipt, type TiquoReceiptBusiness, type TiquoReceiptCustomer, type TiquoReceiptItem, type TiquoReceiptOrder, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isDashboardSession, trackCustomerPresence, useTiquoAuth };
|
|
944
|
+
export { type AuthStateChangeCallback, type CountryPhoneInfo, type GetBookingsOptions, type GetBookingsResult, type GetCompaniesResult, type GetCompanyColleaguesResult, type GetEnquiriesOptions, type GetEnquiriesResult, type GetOrdersOptions, type GetOrdersResult, type IframeTokenResult, type PhoneValidationResult, type ProfilePhotoUploadResult, type ProfileUpdateData, type ProfileUpdateResult, type SendOTPResult, TiquoAuth, type TiquoAuthConfig, TiquoAuthError, type TiquoBooking, TiquoCMS, type TiquoCMSBlock, type TiquoCMSConfig, type TiquoCMSPage, type TiquoCMSPageRequest, type TiquoCompany, type TiquoCompanyColleague, type TiquoCompanyMembership, type TiquoCompanyRelationship, type TiquoCustomer, type TiquoCustomerEmail, type TiquoCustomerPhone, type TiquoEnquiry, type TiquoOrder, type TiquoOrderItem, TiquoPhone, type TiquoReceipt, type TiquoReceiptBusiness, type TiquoReceiptCustomer, type TiquoReceiptItem, type TiquoReceiptOrder, type TiquoSession, type TiquoUser, type VerifyOTPResult, addCustomerUserId, clearCachedEmail, TiquoAuth as default, getCustomerUserIds, getPrefilledEmailFromCookie, isDashboardSession, trackCustomerPresence, useTiquoAuth };
|
package/dist/index.js
CHANGED
|
@@ -22,6 +22,7 @@ var index_exports = {};
|
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
TiquoAuth: () => TiquoAuth,
|
|
24
24
|
TiquoAuthError: () => TiquoAuthError,
|
|
25
|
+
TiquoCMS: () => TiquoCMS,
|
|
25
26
|
TiquoPhone: () => TiquoPhone,
|
|
26
27
|
addCustomerUserId: () => addCustomerUserId,
|
|
27
28
|
clearCachedEmail: () => clearCachedEmail,
|
|
@@ -677,6 +678,68 @@ function printTiquoBranding() {
|
|
|
677
678
|
}
|
|
678
679
|
}
|
|
679
680
|
printTiquoBranding();
|
|
681
|
+
var TiquoCMS = class {
|
|
682
|
+
constructor(config) {
|
|
683
|
+
if (!config.publicKey) {
|
|
684
|
+
throw new TiquoAuthError("publicKey is required", "MISSING_PUBLIC_KEY");
|
|
685
|
+
}
|
|
686
|
+
if (!config.publicKey.startsWith("pk_dom_")) {
|
|
687
|
+
throw new TiquoAuthError(
|
|
688
|
+
"Invalid public key format. Expected pk_dom_xxx",
|
|
689
|
+
"INVALID_PUBLIC_KEY"
|
|
690
|
+
);
|
|
691
|
+
}
|
|
692
|
+
this.config = {
|
|
693
|
+
publicKey: config.publicKey,
|
|
694
|
+
apiEndpoint: config.apiEndpoint || "https://edge.tiquo.app",
|
|
695
|
+
debug: config.debug || false
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
/**
|
|
699
|
+
* Fetch a published CMS page for the website attached to this public key.
|
|
700
|
+
*
|
|
701
|
+
* This intentionally goes through the Tiquo edge API rather than exposing
|
|
702
|
+
* Convex connection details to the consuming website.
|
|
703
|
+
*/
|
|
704
|
+
async getPage(request) {
|
|
705
|
+
const response = await fetch(`${this.config.apiEndpoint}/api/dom-cms/page`, {
|
|
706
|
+
method: "POST",
|
|
707
|
+
headers: {
|
|
708
|
+
"Content-Type": "text/plain;charset=UTF-8"
|
|
709
|
+
},
|
|
710
|
+
credentials: "include",
|
|
711
|
+
body: JSON.stringify({
|
|
712
|
+
publicKey: this.config.publicKey,
|
|
713
|
+
siteSlug: request.siteSlug,
|
|
714
|
+
pageSlug: request.pageSlug || "home",
|
|
715
|
+
templateId: request.templateId
|
|
716
|
+
})
|
|
717
|
+
});
|
|
718
|
+
if (response.status === 404) {
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
if (!response.ok) {
|
|
722
|
+
let message = "Failed to fetch CMS page";
|
|
723
|
+
try {
|
|
724
|
+
const error = await response.json();
|
|
725
|
+
if (typeof error?.error === "string") message = error.error;
|
|
726
|
+
} catch {
|
|
727
|
+
}
|
|
728
|
+
throw new TiquoAuthError(message, "CMS_PAGE_FETCH_FAILED", response.status);
|
|
729
|
+
}
|
|
730
|
+
const result = await response.json();
|
|
731
|
+
if (!result?.success || !result?.data) {
|
|
732
|
+
return null;
|
|
733
|
+
}
|
|
734
|
+
this.log("Fetched CMS page", request.siteSlug, request.pageSlug || "home");
|
|
735
|
+
return result.data;
|
|
736
|
+
}
|
|
737
|
+
log(...args) {
|
|
738
|
+
if (this.config.debug) {
|
|
739
|
+
console.log("[TiquoCMS]", ...args);
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
};
|
|
680
743
|
var TiquoAuthError = class extends Error {
|
|
681
744
|
constructor(message, code, statusCode) {
|
|
682
745
|
super(message);
|
|
@@ -843,6 +906,10 @@ var TiquoAuth = class {
|
|
|
843
906
|
async updateProfile(updates) {
|
|
844
907
|
await this.ensureValidToken();
|
|
845
908
|
const normalizedUpdates = { ...updates };
|
|
909
|
+
const profilePhotoUpload = this.extractUploadableProfilePhoto(normalizedUpdates.profilePhoto);
|
|
910
|
+
if (profilePhotoUpload) {
|
|
911
|
+
delete normalizedUpdates.profilePhoto;
|
|
912
|
+
}
|
|
846
913
|
if (normalizedUpdates.phone !== void 0 && normalizedUpdates.phone !== "") {
|
|
847
914
|
const normalized = normalizePhone(normalizedUpdates.phone);
|
|
848
915
|
const validation = validatePhone(normalizedUpdates.phone);
|
|
@@ -865,26 +932,109 @@ var TiquoAuth = class {
|
|
|
865
932
|
});
|
|
866
933
|
}
|
|
867
934
|
this.log("Updating customer profile:", normalizedUpdates);
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
935
|
+
let customer = this.session?.customer || void 0;
|
|
936
|
+
if (Object.keys(normalizedUpdates).length > 0) {
|
|
937
|
+
const response = await this.request("/api/client/v1/profile", {
|
|
938
|
+
method: "PATCH",
|
|
939
|
+
body: JSON.stringify(normalizedUpdates)
|
|
940
|
+
});
|
|
941
|
+
if (!response.ok) {
|
|
942
|
+
const error = await response.json().catch(() => ({ error: "Failed to update profile" }));
|
|
943
|
+
throw new TiquoAuthError(error.error || "Failed to update profile", "PROFILE_UPDATE_FAILED", response.status);
|
|
944
|
+
}
|
|
945
|
+
const result = await response.json();
|
|
946
|
+
if (this.session && result.data?.customer) {
|
|
947
|
+
this.session = {
|
|
948
|
+
...this.session,
|
|
949
|
+
customer: result.data.customer
|
|
950
|
+
};
|
|
951
|
+
this.notifyListeners();
|
|
952
|
+
this.broadcastTabSync("SESSION_UPDATE");
|
|
953
|
+
}
|
|
954
|
+
customer = result.data?.customer;
|
|
955
|
+
}
|
|
956
|
+
if (profilePhotoUpload) {
|
|
957
|
+
return this.uploadProfilePhoto(profilePhotoUpload);
|
|
958
|
+
}
|
|
959
|
+
return {
|
|
960
|
+
success: true,
|
|
961
|
+
customer
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Upload and save the authenticated customer's profile photo.
|
|
966
|
+
*
|
|
967
|
+
* Accepts a browser File/Blob, `data:image/...` URI, or `blob:...` URI. The
|
|
968
|
+
* image is uploaded to Tiquo storage first, and the customer profile is
|
|
969
|
+
* updated with the URL.
|
|
970
|
+
*/
|
|
971
|
+
async uploadProfilePhoto(photo) {
|
|
972
|
+
await this.ensureValidToken();
|
|
973
|
+
const blob = await this.profilePhotoToBlob(photo);
|
|
974
|
+
if (!blob.type.startsWith("image/")) {
|
|
975
|
+
throw new TiquoAuthError("Profile photo must be an image", "INVALID_PROFILE_PHOTO");
|
|
976
|
+
}
|
|
977
|
+
const uploadUrlResponse = await this.request("/api/client/v1/profile/photo-upload-url", {
|
|
978
|
+
method: "POST",
|
|
979
|
+
body: JSON.stringify({})
|
|
871
980
|
});
|
|
872
|
-
if (!
|
|
873
|
-
const error = await
|
|
874
|
-
throw new TiquoAuthError(
|
|
981
|
+
if (!uploadUrlResponse.ok) {
|
|
982
|
+
const error = await uploadUrlResponse.json().catch(() => ({ error: "Failed to create profile photo upload URL" }));
|
|
983
|
+
throw new TiquoAuthError(
|
|
984
|
+
error.error || "Failed to create profile photo upload URL",
|
|
985
|
+
"PROFILE_PHOTO_UPLOAD_URL_FAILED",
|
|
986
|
+
uploadUrlResponse.status
|
|
987
|
+
);
|
|
875
988
|
}
|
|
876
|
-
const
|
|
877
|
-
|
|
989
|
+
const uploadUrlResult = await uploadUrlResponse.json();
|
|
990
|
+
const uploadUrl = uploadUrlResult.data?.uploadUrl;
|
|
991
|
+
if (!uploadUrl) {
|
|
992
|
+
throw new TiquoAuthError("Profile photo upload URL was missing", "PROFILE_PHOTO_UPLOAD_URL_FAILED");
|
|
993
|
+
}
|
|
994
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
995
|
+
method: "POST",
|
|
996
|
+
headers: { "Content-Type": blob.type },
|
|
997
|
+
body: blob
|
|
998
|
+
});
|
|
999
|
+
if (!uploadResponse.ok) {
|
|
1000
|
+
throw new TiquoAuthError("Failed to upload profile photo", "PROFILE_PHOTO_UPLOAD_FAILED", uploadResponse.status);
|
|
1001
|
+
}
|
|
1002
|
+
const uploadResult = await uploadResponse.json();
|
|
1003
|
+
const storageId = uploadResult.storageId;
|
|
1004
|
+
if (!storageId) {
|
|
1005
|
+
throw new TiquoAuthError("Profile photo storage ID was missing", "PROFILE_PHOTO_UPLOAD_FAILED");
|
|
1006
|
+
}
|
|
1007
|
+
const finalizeResponse = await this.request("/api/client/v1/profile/photo", {
|
|
1008
|
+
method: "POST",
|
|
1009
|
+
body: JSON.stringify({ storageId })
|
|
1010
|
+
});
|
|
1011
|
+
if (!finalizeResponse.ok) {
|
|
1012
|
+
const error = await finalizeResponse.json().catch(() => ({ error: "Failed to update profile photo" }));
|
|
1013
|
+
throw new TiquoAuthError(
|
|
1014
|
+
error.error || "Failed to update profile photo",
|
|
1015
|
+
"PROFILE_PHOTO_UPDATE_FAILED",
|
|
1016
|
+
finalizeResponse.status
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
const finalizeResult = await finalizeResponse.json();
|
|
1020
|
+
const customer = finalizeResult.data?.customer;
|
|
1021
|
+
const profilePhoto = finalizeResult.data?.profilePhoto;
|
|
1022
|
+
if (!customer || !profilePhoto) {
|
|
1023
|
+
throw new TiquoAuthError("Profile photo update response was incomplete", "PROFILE_PHOTO_UPDATE_FAILED");
|
|
1024
|
+
}
|
|
1025
|
+
if (this.session && customer) {
|
|
878
1026
|
this.session = {
|
|
879
1027
|
...this.session,
|
|
880
|
-
customer
|
|
1028
|
+
customer
|
|
881
1029
|
};
|
|
882
1030
|
this.notifyListeners();
|
|
883
1031
|
this.broadcastTabSync("SESSION_UPDATE");
|
|
884
1032
|
}
|
|
885
1033
|
return {
|
|
886
1034
|
success: true,
|
|
887
|
-
customer
|
|
1035
|
+
customer,
|
|
1036
|
+
profilePhoto,
|
|
1037
|
+
storageId
|
|
888
1038
|
};
|
|
889
1039
|
}
|
|
890
1040
|
/**
|
|
@@ -1074,6 +1224,67 @@ var TiquoAuth = class {
|
|
|
1074
1224
|
const result = await response.json();
|
|
1075
1225
|
return result.data || { enquiries: [], hasMore: false };
|
|
1076
1226
|
}
|
|
1227
|
+
/**
|
|
1228
|
+
* Get the companies the authenticated customer belongs to.
|
|
1229
|
+
*
|
|
1230
|
+
* Each entry includes the customer's role inside that company via
|
|
1231
|
+
* `membership` — branch on `membership.isCompanyAdmin` to decide whether
|
|
1232
|
+
* to render admin features (e.g. a colleagues list).
|
|
1233
|
+
*
|
|
1234
|
+
* Returns an empty array (not an error) when the customer isn't a
|
|
1235
|
+
* member of any company.
|
|
1236
|
+
*/
|
|
1237
|
+
async getCompanies() {
|
|
1238
|
+
await this.ensureValidToken();
|
|
1239
|
+
this.log("Fetching customer companies");
|
|
1240
|
+
const response = await fetch(`${this.config.apiEndpoint}/api/client/v1/companies`, {
|
|
1241
|
+
method: "GET",
|
|
1242
|
+
headers: {
|
|
1243
|
+
"Authorization": `Bearer ${this.accessToken}`
|
|
1244
|
+
},
|
|
1245
|
+
credentials: "include"
|
|
1246
|
+
});
|
|
1247
|
+
if (!response.ok) {
|
|
1248
|
+
const error = await response.json().catch(() => ({ error: "Failed to get companies" }));
|
|
1249
|
+
throw new TiquoAuthError(error.error || "Failed to get companies", "GET_COMPANIES_FAILED", response.status);
|
|
1250
|
+
}
|
|
1251
|
+
const result = await response.json();
|
|
1252
|
+
return result.data || { companies: [] };
|
|
1253
|
+
}
|
|
1254
|
+
/**
|
|
1255
|
+
* Get the colleagues (other customers) inside a company the authenticated
|
|
1256
|
+
* customer is a member of.
|
|
1257
|
+
*
|
|
1258
|
+
* Restricted to Company Admins — if the caller isn't flagged as
|
|
1259
|
+
* `isCompanyAdmin` on that company, this throws `TiquoAuthError` with
|
|
1260
|
+
* code `NOT_COMPANY_ADMIN` (status 403). Check `membership.isCompanyAdmin`
|
|
1261
|
+
* from `getCompanies()` before calling this if you want to render the
|
|
1262
|
+
* admin UI conditionally.
|
|
1263
|
+
*
|
|
1264
|
+
* Each colleague includes basic contact info and their relationship to
|
|
1265
|
+
* the company. The authenticated customer is included in the list with
|
|
1266
|
+
* `isSelf: true` so the UI can highlight or skip them.
|
|
1267
|
+
*/
|
|
1268
|
+
async getCompanyColleagues(companyId) {
|
|
1269
|
+
await this.ensureValidToken();
|
|
1270
|
+
this.log("Fetching company colleagues for:", companyId);
|
|
1271
|
+
const url = new URL(`${this.config.apiEndpoint}/api/client/v1/companies/colleagues`);
|
|
1272
|
+
url.searchParams.set("companyId", companyId);
|
|
1273
|
+
const response = await fetch(url.toString(), {
|
|
1274
|
+
method: "GET",
|
|
1275
|
+
headers: {
|
|
1276
|
+
"Authorization": `Bearer ${this.accessToken}`
|
|
1277
|
+
},
|
|
1278
|
+
credentials: "include"
|
|
1279
|
+
});
|
|
1280
|
+
if (!response.ok) {
|
|
1281
|
+
const error = await response.json().catch(() => ({ error: "Failed to get colleagues" }));
|
|
1282
|
+
const code = response.status === 403 ? "NOT_COMPANY_ADMIN" : "GET_COLLEAGUES_FAILED";
|
|
1283
|
+
throw new TiquoAuthError(error.error || "Failed to get colleagues", code, response.status);
|
|
1284
|
+
}
|
|
1285
|
+
const result = await response.json();
|
|
1286
|
+
return result.data;
|
|
1287
|
+
}
|
|
1077
1288
|
/**
|
|
1078
1289
|
* Generate a short-lived token for customer flow iframe authentication
|
|
1079
1290
|
*/
|
|
@@ -1265,6 +1476,37 @@ var TiquoAuth = class {
|
|
|
1265
1476
|
}
|
|
1266
1477
|
}
|
|
1267
1478
|
}
|
|
1479
|
+
extractUploadableProfilePhoto(profilePhoto) {
|
|
1480
|
+
if (typeof Blob !== "undefined" && profilePhoto instanceof Blob) {
|
|
1481
|
+
return profilePhoto;
|
|
1482
|
+
}
|
|
1483
|
+
if (typeof profilePhoto === "string") {
|
|
1484
|
+
const trimmed = profilePhoto.trim();
|
|
1485
|
+
if (trimmed.startsWith("data:") || trimmed.startsWith("blob:")) {
|
|
1486
|
+
return trimmed;
|
|
1487
|
+
}
|
|
1488
|
+
}
|
|
1489
|
+
return null;
|
|
1490
|
+
}
|
|
1491
|
+
isProfilePhotoBlobUrl(photo) {
|
|
1492
|
+
return photo.trim().startsWith("data:") || photo.trim().startsWith("blob:");
|
|
1493
|
+
}
|
|
1494
|
+
async profilePhotoToBlob(photo) {
|
|
1495
|
+
if (typeof Blob !== "undefined" && photo instanceof Blob) {
|
|
1496
|
+
return photo;
|
|
1497
|
+
}
|
|
1498
|
+
if (typeof photo === "string" && this.isProfilePhotoBlobUrl(photo)) {
|
|
1499
|
+
const response = await fetch(photo);
|
|
1500
|
+
if (!response.ok) {
|
|
1501
|
+
throw new TiquoAuthError("Failed to read profile photo URI", "INVALID_PROFILE_PHOTO");
|
|
1502
|
+
}
|
|
1503
|
+
return response.blob();
|
|
1504
|
+
}
|
|
1505
|
+
throw new TiquoAuthError(
|
|
1506
|
+
"uploadProfilePhoto expects a File, Blob, data URI, or blob URI. Use updateProfile({ profilePhoto: url }) for remote URLs.",
|
|
1507
|
+
"INVALID_PROFILE_PHOTO"
|
|
1508
|
+
);
|
|
1509
|
+
}
|
|
1268
1510
|
async request(path, options) {
|
|
1269
1511
|
const url = `${this.config.apiEndpoint}${path}`;
|
|
1270
1512
|
const headers = {
|
|
@@ -1640,11 +1882,14 @@ function useTiquoAuth(auth) {
|
|
|
1640
1882
|
verifyOTP: (email, otp) => auth.verifyOTP(email, otp),
|
|
1641
1883
|
logout: () => auth.logout(),
|
|
1642
1884
|
updateProfile: (updates) => auth.updateProfile(updates),
|
|
1885
|
+
uploadProfilePhoto: (photo) => auth.uploadProfilePhoto(photo),
|
|
1643
1886
|
getOrders: (options) => auth.getOrders(options),
|
|
1644
1887
|
getBookings: (options) => auth.getBookings(options),
|
|
1645
1888
|
getUpcomingBookings: (options) => auth.getUpcomingBookings(options),
|
|
1646
1889
|
getReceipt: (orderId) => auth.getReceipt(orderId),
|
|
1647
1890
|
getEnquiries: (options) => auth.getEnquiries(options),
|
|
1891
|
+
getCompanies: () => auth.getCompanies(),
|
|
1892
|
+
getCompanyColleagues: (companyId) => auth.getCompanyColleagues(companyId),
|
|
1648
1893
|
getIframeToken: (flowId) => auth.getIframeToken(flowId),
|
|
1649
1894
|
embedCustomerFlow: auth.embedCustomerFlow.bind(auth),
|
|
1650
1895
|
onAuthStateChange: (cb) => auth.onAuthStateChange(cb)
|
|
@@ -1671,6 +1916,7 @@ var index_default = TiquoAuth;
|
|
|
1671
1916
|
0 && (module.exports = {
|
|
1672
1917
|
TiquoAuth,
|
|
1673
1918
|
TiquoAuthError,
|
|
1919
|
+
TiquoCMS,
|
|
1674
1920
|
TiquoPhone,
|
|
1675
1921
|
addCustomerUserId,
|
|
1676
1922
|
clearCachedEmail,
|
package/dist/index.mjs
CHANGED
|
@@ -641,6 +641,68 @@ function printTiquoBranding() {
|
|
|
641
641
|
}
|
|
642
642
|
}
|
|
643
643
|
printTiquoBranding();
|
|
644
|
+
var TiquoCMS = class {
|
|
645
|
+
constructor(config) {
|
|
646
|
+
if (!config.publicKey) {
|
|
647
|
+
throw new TiquoAuthError("publicKey is required", "MISSING_PUBLIC_KEY");
|
|
648
|
+
}
|
|
649
|
+
if (!config.publicKey.startsWith("pk_dom_")) {
|
|
650
|
+
throw new TiquoAuthError(
|
|
651
|
+
"Invalid public key format. Expected pk_dom_xxx",
|
|
652
|
+
"INVALID_PUBLIC_KEY"
|
|
653
|
+
);
|
|
654
|
+
}
|
|
655
|
+
this.config = {
|
|
656
|
+
publicKey: config.publicKey,
|
|
657
|
+
apiEndpoint: config.apiEndpoint || "https://edge.tiquo.app",
|
|
658
|
+
debug: config.debug || false
|
|
659
|
+
};
|
|
660
|
+
}
|
|
661
|
+
/**
|
|
662
|
+
* Fetch a published CMS page for the website attached to this public key.
|
|
663
|
+
*
|
|
664
|
+
* This intentionally goes through the Tiquo edge API rather than exposing
|
|
665
|
+
* Convex connection details to the consuming website.
|
|
666
|
+
*/
|
|
667
|
+
async getPage(request) {
|
|
668
|
+
const response = await fetch(`${this.config.apiEndpoint}/api/dom-cms/page`, {
|
|
669
|
+
method: "POST",
|
|
670
|
+
headers: {
|
|
671
|
+
"Content-Type": "text/plain;charset=UTF-8"
|
|
672
|
+
},
|
|
673
|
+
credentials: "include",
|
|
674
|
+
body: JSON.stringify({
|
|
675
|
+
publicKey: this.config.publicKey,
|
|
676
|
+
siteSlug: request.siteSlug,
|
|
677
|
+
pageSlug: request.pageSlug || "home",
|
|
678
|
+
templateId: request.templateId
|
|
679
|
+
})
|
|
680
|
+
});
|
|
681
|
+
if (response.status === 404) {
|
|
682
|
+
return null;
|
|
683
|
+
}
|
|
684
|
+
if (!response.ok) {
|
|
685
|
+
let message = "Failed to fetch CMS page";
|
|
686
|
+
try {
|
|
687
|
+
const error = await response.json();
|
|
688
|
+
if (typeof error?.error === "string") message = error.error;
|
|
689
|
+
} catch {
|
|
690
|
+
}
|
|
691
|
+
throw new TiquoAuthError(message, "CMS_PAGE_FETCH_FAILED", response.status);
|
|
692
|
+
}
|
|
693
|
+
const result = await response.json();
|
|
694
|
+
if (!result?.success || !result?.data) {
|
|
695
|
+
return null;
|
|
696
|
+
}
|
|
697
|
+
this.log("Fetched CMS page", request.siteSlug, request.pageSlug || "home");
|
|
698
|
+
return result.data;
|
|
699
|
+
}
|
|
700
|
+
log(...args) {
|
|
701
|
+
if (this.config.debug) {
|
|
702
|
+
console.log("[TiquoCMS]", ...args);
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
};
|
|
644
706
|
var TiquoAuthError = class extends Error {
|
|
645
707
|
constructor(message, code, statusCode) {
|
|
646
708
|
super(message);
|
|
@@ -807,6 +869,10 @@ var TiquoAuth = class {
|
|
|
807
869
|
async updateProfile(updates) {
|
|
808
870
|
await this.ensureValidToken();
|
|
809
871
|
const normalizedUpdates = { ...updates };
|
|
872
|
+
const profilePhotoUpload = this.extractUploadableProfilePhoto(normalizedUpdates.profilePhoto);
|
|
873
|
+
if (profilePhotoUpload) {
|
|
874
|
+
delete normalizedUpdates.profilePhoto;
|
|
875
|
+
}
|
|
810
876
|
if (normalizedUpdates.phone !== void 0 && normalizedUpdates.phone !== "") {
|
|
811
877
|
const normalized = normalizePhone(normalizedUpdates.phone);
|
|
812
878
|
const validation = validatePhone(normalizedUpdates.phone);
|
|
@@ -829,26 +895,109 @@ var TiquoAuth = class {
|
|
|
829
895
|
});
|
|
830
896
|
}
|
|
831
897
|
this.log("Updating customer profile:", normalizedUpdates);
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
898
|
+
let customer = this.session?.customer || void 0;
|
|
899
|
+
if (Object.keys(normalizedUpdates).length > 0) {
|
|
900
|
+
const response = await this.request("/api/client/v1/profile", {
|
|
901
|
+
method: "PATCH",
|
|
902
|
+
body: JSON.stringify(normalizedUpdates)
|
|
903
|
+
});
|
|
904
|
+
if (!response.ok) {
|
|
905
|
+
const error = await response.json().catch(() => ({ error: "Failed to update profile" }));
|
|
906
|
+
throw new TiquoAuthError(error.error || "Failed to update profile", "PROFILE_UPDATE_FAILED", response.status);
|
|
907
|
+
}
|
|
908
|
+
const result = await response.json();
|
|
909
|
+
if (this.session && result.data?.customer) {
|
|
910
|
+
this.session = {
|
|
911
|
+
...this.session,
|
|
912
|
+
customer: result.data.customer
|
|
913
|
+
};
|
|
914
|
+
this.notifyListeners();
|
|
915
|
+
this.broadcastTabSync("SESSION_UPDATE");
|
|
916
|
+
}
|
|
917
|
+
customer = result.data?.customer;
|
|
918
|
+
}
|
|
919
|
+
if (profilePhotoUpload) {
|
|
920
|
+
return this.uploadProfilePhoto(profilePhotoUpload);
|
|
921
|
+
}
|
|
922
|
+
return {
|
|
923
|
+
success: true,
|
|
924
|
+
customer
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
/**
|
|
928
|
+
* Upload and save the authenticated customer's profile photo.
|
|
929
|
+
*
|
|
930
|
+
* Accepts a browser File/Blob, `data:image/...` URI, or `blob:...` URI. The
|
|
931
|
+
* image is uploaded to Tiquo storage first, and the customer profile is
|
|
932
|
+
* updated with the URL.
|
|
933
|
+
*/
|
|
934
|
+
async uploadProfilePhoto(photo) {
|
|
935
|
+
await this.ensureValidToken();
|
|
936
|
+
const blob = await this.profilePhotoToBlob(photo);
|
|
937
|
+
if (!blob.type.startsWith("image/")) {
|
|
938
|
+
throw new TiquoAuthError("Profile photo must be an image", "INVALID_PROFILE_PHOTO");
|
|
939
|
+
}
|
|
940
|
+
const uploadUrlResponse = await this.request("/api/client/v1/profile/photo-upload-url", {
|
|
941
|
+
method: "POST",
|
|
942
|
+
body: JSON.stringify({})
|
|
835
943
|
});
|
|
836
|
-
if (!
|
|
837
|
-
const error = await
|
|
838
|
-
throw new TiquoAuthError(
|
|
944
|
+
if (!uploadUrlResponse.ok) {
|
|
945
|
+
const error = await uploadUrlResponse.json().catch(() => ({ error: "Failed to create profile photo upload URL" }));
|
|
946
|
+
throw new TiquoAuthError(
|
|
947
|
+
error.error || "Failed to create profile photo upload URL",
|
|
948
|
+
"PROFILE_PHOTO_UPLOAD_URL_FAILED",
|
|
949
|
+
uploadUrlResponse.status
|
|
950
|
+
);
|
|
839
951
|
}
|
|
840
|
-
const
|
|
841
|
-
|
|
952
|
+
const uploadUrlResult = await uploadUrlResponse.json();
|
|
953
|
+
const uploadUrl = uploadUrlResult.data?.uploadUrl;
|
|
954
|
+
if (!uploadUrl) {
|
|
955
|
+
throw new TiquoAuthError("Profile photo upload URL was missing", "PROFILE_PHOTO_UPLOAD_URL_FAILED");
|
|
956
|
+
}
|
|
957
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
958
|
+
method: "POST",
|
|
959
|
+
headers: { "Content-Type": blob.type },
|
|
960
|
+
body: blob
|
|
961
|
+
});
|
|
962
|
+
if (!uploadResponse.ok) {
|
|
963
|
+
throw new TiquoAuthError("Failed to upload profile photo", "PROFILE_PHOTO_UPLOAD_FAILED", uploadResponse.status);
|
|
964
|
+
}
|
|
965
|
+
const uploadResult = await uploadResponse.json();
|
|
966
|
+
const storageId = uploadResult.storageId;
|
|
967
|
+
if (!storageId) {
|
|
968
|
+
throw new TiquoAuthError("Profile photo storage ID was missing", "PROFILE_PHOTO_UPLOAD_FAILED");
|
|
969
|
+
}
|
|
970
|
+
const finalizeResponse = await this.request("/api/client/v1/profile/photo", {
|
|
971
|
+
method: "POST",
|
|
972
|
+
body: JSON.stringify({ storageId })
|
|
973
|
+
});
|
|
974
|
+
if (!finalizeResponse.ok) {
|
|
975
|
+
const error = await finalizeResponse.json().catch(() => ({ error: "Failed to update profile photo" }));
|
|
976
|
+
throw new TiquoAuthError(
|
|
977
|
+
error.error || "Failed to update profile photo",
|
|
978
|
+
"PROFILE_PHOTO_UPDATE_FAILED",
|
|
979
|
+
finalizeResponse.status
|
|
980
|
+
);
|
|
981
|
+
}
|
|
982
|
+
const finalizeResult = await finalizeResponse.json();
|
|
983
|
+
const customer = finalizeResult.data?.customer;
|
|
984
|
+
const profilePhoto = finalizeResult.data?.profilePhoto;
|
|
985
|
+
if (!customer || !profilePhoto) {
|
|
986
|
+
throw new TiquoAuthError("Profile photo update response was incomplete", "PROFILE_PHOTO_UPDATE_FAILED");
|
|
987
|
+
}
|
|
988
|
+
if (this.session && customer) {
|
|
842
989
|
this.session = {
|
|
843
990
|
...this.session,
|
|
844
|
-
customer
|
|
991
|
+
customer
|
|
845
992
|
};
|
|
846
993
|
this.notifyListeners();
|
|
847
994
|
this.broadcastTabSync("SESSION_UPDATE");
|
|
848
995
|
}
|
|
849
996
|
return {
|
|
850
997
|
success: true,
|
|
851
|
-
customer
|
|
998
|
+
customer,
|
|
999
|
+
profilePhoto,
|
|
1000
|
+
storageId
|
|
852
1001
|
};
|
|
853
1002
|
}
|
|
854
1003
|
/**
|
|
@@ -1038,6 +1187,67 @@ var TiquoAuth = class {
|
|
|
1038
1187
|
const result = await response.json();
|
|
1039
1188
|
return result.data || { enquiries: [], hasMore: false };
|
|
1040
1189
|
}
|
|
1190
|
+
/**
|
|
1191
|
+
* Get the companies the authenticated customer belongs to.
|
|
1192
|
+
*
|
|
1193
|
+
* Each entry includes the customer's role inside that company via
|
|
1194
|
+
* `membership` — branch on `membership.isCompanyAdmin` to decide whether
|
|
1195
|
+
* to render admin features (e.g. a colleagues list).
|
|
1196
|
+
*
|
|
1197
|
+
* Returns an empty array (not an error) when the customer isn't a
|
|
1198
|
+
* member of any company.
|
|
1199
|
+
*/
|
|
1200
|
+
async getCompanies() {
|
|
1201
|
+
await this.ensureValidToken();
|
|
1202
|
+
this.log("Fetching customer companies");
|
|
1203
|
+
const response = await fetch(`${this.config.apiEndpoint}/api/client/v1/companies`, {
|
|
1204
|
+
method: "GET",
|
|
1205
|
+
headers: {
|
|
1206
|
+
"Authorization": `Bearer ${this.accessToken}`
|
|
1207
|
+
},
|
|
1208
|
+
credentials: "include"
|
|
1209
|
+
});
|
|
1210
|
+
if (!response.ok) {
|
|
1211
|
+
const error = await response.json().catch(() => ({ error: "Failed to get companies" }));
|
|
1212
|
+
throw new TiquoAuthError(error.error || "Failed to get companies", "GET_COMPANIES_FAILED", response.status);
|
|
1213
|
+
}
|
|
1214
|
+
const result = await response.json();
|
|
1215
|
+
return result.data || { companies: [] };
|
|
1216
|
+
}
|
|
1217
|
+
/**
|
|
1218
|
+
* Get the colleagues (other customers) inside a company the authenticated
|
|
1219
|
+
* customer is a member of.
|
|
1220
|
+
*
|
|
1221
|
+
* Restricted to Company Admins — if the caller isn't flagged as
|
|
1222
|
+
* `isCompanyAdmin` on that company, this throws `TiquoAuthError` with
|
|
1223
|
+
* code `NOT_COMPANY_ADMIN` (status 403). Check `membership.isCompanyAdmin`
|
|
1224
|
+
* from `getCompanies()` before calling this if you want to render the
|
|
1225
|
+
* admin UI conditionally.
|
|
1226
|
+
*
|
|
1227
|
+
* Each colleague includes basic contact info and their relationship to
|
|
1228
|
+
* the company. The authenticated customer is included in the list with
|
|
1229
|
+
* `isSelf: true` so the UI can highlight or skip them.
|
|
1230
|
+
*/
|
|
1231
|
+
async getCompanyColleagues(companyId) {
|
|
1232
|
+
await this.ensureValidToken();
|
|
1233
|
+
this.log("Fetching company colleagues for:", companyId);
|
|
1234
|
+
const url = new URL(`${this.config.apiEndpoint}/api/client/v1/companies/colleagues`);
|
|
1235
|
+
url.searchParams.set("companyId", companyId);
|
|
1236
|
+
const response = await fetch(url.toString(), {
|
|
1237
|
+
method: "GET",
|
|
1238
|
+
headers: {
|
|
1239
|
+
"Authorization": `Bearer ${this.accessToken}`
|
|
1240
|
+
},
|
|
1241
|
+
credentials: "include"
|
|
1242
|
+
});
|
|
1243
|
+
if (!response.ok) {
|
|
1244
|
+
const error = await response.json().catch(() => ({ error: "Failed to get colleagues" }));
|
|
1245
|
+
const code = response.status === 403 ? "NOT_COMPANY_ADMIN" : "GET_COLLEAGUES_FAILED";
|
|
1246
|
+
throw new TiquoAuthError(error.error || "Failed to get colleagues", code, response.status);
|
|
1247
|
+
}
|
|
1248
|
+
const result = await response.json();
|
|
1249
|
+
return result.data;
|
|
1250
|
+
}
|
|
1041
1251
|
/**
|
|
1042
1252
|
* Generate a short-lived token for customer flow iframe authentication
|
|
1043
1253
|
*/
|
|
@@ -1229,6 +1439,37 @@ var TiquoAuth = class {
|
|
|
1229
1439
|
}
|
|
1230
1440
|
}
|
|
1231
1441
|
}
|
|
1442
|
+
extractUploadableProfilePhoto(profilePhoto) {
|
|
1443
|
+
if (typeof Blob !== "undefined" && profilePhoto instanceof Blob) {
|
|
1444
|
+
return profilePhoto;
|
|
1445
|
+
}
|
|
1446
|
+
if (typeof profilePhoto === "string") {
|
|
1447
|
+
const trimmed = profilePhoto.trim();
|
|
1448
|
+
if (trimmed.startsWith("data:") || trimmed.startsWith("blob:")) {
|
|
1449
|
+
return trimmed;
|
|
1450
|
+
}
|
|
1451
|
+
}
|
|
1452
|
+
return null;
|
|
1453
|
+
}
|
|
1454
|
+
isProfilePhotoBlobUrl(photo) {
|
|
1455
|
+
return photo.trim().startsWith("data:") || photo.trim().startsWith("blob:");
|
|
1456
|
+
}
|
|
1457
|
+
async profilePhotoToBlob(photo) {
|
|
1458
|
+
if (typeof Blob !== "undefined" && photo instanceof Blob) {
|
|
1459
|
+
return photo;
|
|
1460
|
+
}
|
|
1461
|
+
if (typeof photo === "string" && this.isProfilePhotoBlobUrl(photo)) {
|
|
1462
|
+
const response = await fetch(photo);
|
|
1463
|
+
if (!response.ok) {
|
|
1464
|
+
throw new TiquoAuthError("Failed to read profile photo URI", "INVALID_PROFILE_PHOTO");
|
|
1465
|
+
}
|
|
1466
|
+
return response.blob();
|
|
1467
|
+
}
|
|
1468
|
+
throw new TiquoAuthError(
|
|
1469
|
+
"uploadProfilePhoto expects a File, Blob, data URI, or blob URI. Use updateProfile({ profilePhoto: url }) for remote URLs.",
|
|
1470
|
+
"INVALID_PROFILE_PHOTO"
|
|
1471
|
+
);
|
|
1472
|
+
}
|
|
1232
1473
|
async request(path, options) {
|
|
1233
1474
|
const url = `${this.config.apiEndpoint}${path}`;
|
|
1234
1475
|
const headers = {
|
|
@@ -1604,11 +1845,14 @@ function useTiquoAuth(auth) {
|
|
|
1604
1845
|
verifyOTP: (email, otp) => auth.verifyOTP(email, otp),
|
|
1605
1846
|
logout: () => auth.logout(),
|
|
1606
1847
|
updateProfile: (updates) => auth.updateProfile(updates),
|
|
1848
|
+
uploadProfilePhoto: (photo) => auth.uploadProfilePhoto(photo),
|
|
1607
1849
|
getOrders: (options) => auth.getOrders(options),
|
|
1608
1850
|
getBookings: (options) => auth.getBookings(options),
|
|
1609
1851
|
getUpcomingBookings: (options) => auth.getUpcomingBookings(options),
|
|
1610
1852
|
getReceipt: (orderId) => auth.getReceipt(orderId),
|
|
1611
1853
|
getEnquiries: (options) => auth.getEnquiries(options),
|
|
1854
|
+
getCompanies: () => auth.getCompanies(),
|
|
1855
|
+
getCompanyColleagues: (companyId) => auth.getCompanyColleagues(companyId),
|
|
1612
1856
|
getIframeToken: (flowId) => auth.getIframeToken(flowId),
|
|
1613
1857
|
embedCustomerFlow: auth.embedCustomerFlow.bind(auth),
|
|
1614
1858
|
onAuthStateChange: (cb) => auth.onAuthStateChange(cb)
|
|
@@ -1634,6 +1878,7 @@ var index_default = TiquoAuth;
|
|
|
1634
1878
|
export {
|
|
1635
1879
|
TiquoAuth,
|
|
1636
1880
|
TiquoAuthError,
|
|
1881
|
+
TiquoCMS,
|
|
1637
1882
|
TiquoPhone,
|
|
1638
1883
|
addCustomerUserId,
|
|
1639
1884
|
clearCachedEmail,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tiquo/dom-package",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Tiquo SDK for third-party websites - authentication, customer profiles, orders, bookings, and
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Tiquo SDK for third-party websites - authentication, customer profiles, orders, bookings, enquiries, receipts, and companies",
|
|
5
5
|
"sideEffects": true,
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "restricted"
|