@diffsome/sdk 3.2.8 → 3.2.9
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 +174 -1
- package/dist/index.d.ts +174 -1
- package/dist/index.js +325 -0
- package/dist/index.mjs +325 -0
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -12581,6 +12581,177 @@ declare class SiteResource {
|
|
|
12581
12581
|
formatPrice(amount: number, currency: CurrencyInfo): string;
|
|
12582
12582
|
}
|
|
12583
12583
|
|
|
12584
|
+
/**
|
|
12585
|
+
* Chat Resource for Diffsome SDK
|
|
12586
|
+
* Real-time customer support chat with WebSocket support
|
|
12587
|
+
*/
|
|
12588
|
+
|
|
12589
|
+
interface ChatConversation {
|
|
12590
|
+
id: number;
|
|
12591
|
+
visitor_id: string;
|
|
12592
|
+
visitor_name: string | null;
|
|
12593
|
+
visitor_email: string | null;
|
|
12594
|
+
status: 'open' | 'assigned' | 'closed';
|
|
12595
|
+
channel: 'web' | 'mobile' | 'api';
|
|
12596
|
+
created_at: string;
|
|
12597
|
+
last_message_at: string | null;
|
|
12598
|
+
}
|
|
12599
|
+
interface ChatMessage {
|
|
12600
|
+
id: number;
|
|
12601
|
+
conversation_id: number;
|
|
12602
|
+
content: string;
|
|
12603
|
+
type: 'text' | 'image' | 'file' | 'system';
|
|
12604
|
+
sender_type: 'visitor' | 'agent' | 'system';
|
|
12605
|
+
sender_name: string;
|
|
12606
|
+
is_read: boolean;
|
|
12607
|
+
created_at: string;
|
|
12608
|
+
attachments?: Array<{
|
|
12609
|
+
url: string;
|
|
12610
|
+
name: string;
|
|
12611
|
+
type: string;
|
|
12612
|
+
size: number;
|
|
12613
|
+
}>;
|
|
12614
|
+
}
|
|
12615
|
+
interface StartConversationData {
|
|
12616
|
+
visitor_name?: string;
|
|
12617
|
+
visitor_email?: string;
|
|
12618
|
+
initial_message?: string;
|
|
12619
|
+
channel?: 'web' | 'mobile' | 'api';
|
|
12620
|
+
metadata?: Record<string, unknown>;
|
|
12621
|
+
}
|
|
12622
|
+
interface SendMessageData {
|
|
12623
|
+
content: string;
|
|
12624
|
+
type?: 'text' | 'image' | 'file';
|
|
12625
|
+
attachments?: Array<{
|
|
12626
|
+
url: string;
|
|
12627
|
+
name: string;
|
|
12628
|
+
type: string;
|
|
12629
|
+
size: number;
|
|
12630
|
+
}>;
|
|
12631
|
+
}
|
|
12632
|
+
interface ChatAvailability {
|
|
12633
|
+
available: boolean;
|
|
12634
|
+
agents_online: number;
|
|
12635
|
+
}
|
|
12636
|
+
interface PollResponse {
|
|
12637
|
+
messages: ChatMessage[];
|
|
12638
|
+
conversation_status: 'open' | 'assigned' | 'closed';
|
|
12639
|
+
}
|
|
12640
|
+
interface ReverbConfig {
|
|
12641
|
+
host: string;
|
|
12642
|
+
port?: number;
|
|
12643
|
+
key: string;
|
|
12644
|
+
scheme?: 'ws' | 'wss';
|
|
12645
|
+
}
|
|
12646
|
+
type MessageCallback = (message: ChatMessage) => void;
|
|
12647
|
+
type StatusCallback = (status: 'open' | 'assigned' | 'closed') => void;
|
|
12648
|
+
type TypingCallback = (senderType: 'visitor' | 'agent') => void;
|
|
12649
|
+
declare class ChatResource {
|
|
12650
|
+
private http;
|
|
12651
|
+
private lastMessageIds;
|
|
12652
|
+
private visitorId;
|
|
12653
|
+
private reverbConfig;
|
|
12654
|
+
private websocket;
|
|
12655
|
+
private subscribedChannels;
|
|
12656
|
+
constructor(http: HttpClient);
|
|
12657
|
+
/**
|
|
12658
|
+
* Configure WebSocket connection (Laravel Reverb)
|
|
12659
|
+
*/
|
|
12660
|
+
configureWebSocket(config: ReverbConfig): void;
|
|
12661
|
+
/**
|
|
12662
|
+
* Start a new chat conversation
|
|
12663
|
+
*/
|
|
12664
|
+
start(data?: StartConversationData): Promise<{
|
|
12665
|
+
conversation_id: number;
|
|
12666
|
+
visitor_id: string;
|
|
12667
|
+
status: string;
|
|
12668
|
+
}>;
|
|
12669
|
+
/**
|
|
12670
|
+
* Get list of conversations
|
|
12671
|
+
*/
|
|
12672
|
+
list(params?: {
|
|
12673
|
+
per_page?: number;
|
|
12674
|
+
page?: number;
|
|
12675
|
+
}): Promise<{
|
|
12676
|
+
data: ChatConversation[];
|
|
12677
|
+
meta: {
|
|
12678
|
+
current_page: number;
|
|
12679
|
+
last_page: number;
|
|
12680
|
+
total: number;
|
|
12681
|
+
};
|
|
12682
|
+
}>;
|
|
12683
|
+
/**
|
|
12684
|
+
* Get conversation details
|
|
12685
|
+
*/
|
|
12686
|
+
get(conversationId: number): Promise<ChatConversation>;
|
|
12687
|
+
/**
|
|
12688
|
+
* Send a message
|
|
12689
|
+
*/
|
|
12690
|
+
send(conversationId: number, data: SendMessageData): Promise<ChatMessage>;
|
|
12691
|
+
/**
|
|
12692
|
+
* Get messages for a conversation
|
|
12693
|
+
*/
|
|
12694
|
+
getMessages(conversationId: number, params?: {
|
|
12695
|
+
after?: number;
|
|
12696
|
+
limit?: number;
|
|
12697
|
+
}): Promise<ChatMessage[]>;
|
|
12698
|
+
/**
|
|
12699
|
+
* Poll for new messages (fallback when WebSocket not available)
|
|
12700
|
+
*/
|
|
12701
|
+
poll(conversationId: number, lastMessageId?: number): Promise<PollResponse>;
|
|
12702
|
+
/**
|
|
12703
|
+
* Close conversation
|
|
12704
|
+
*/
|
|
12705
|
+
close(conversationId: number): Promise<void>;
|
|
12706
|
+
/**
|
|
12707
|
+
* Send typing indicator
|
|
12708
|
+
*/
|
|
12709
|
+
sendTyping(conversationId: number): Promise<void>;
|
|
12710
|
+
/**
|
|
12711
|
+
* Check agent availability
|
|
12712
|
+
*/
|
|
12713
|
+
checkAvailability(): Promise<ChatAvailability>;
|
|
12714
|
+
/**
|
|
12715
|
+
* Connect to a conversation with real-time updates
|
|
12716
|
+
* Uses WebSocket if configured, falls back to polling
|
|
12717
|
+
*/
|
|
12718
|
+
connect(conversationId: number): {
|
|
12719
|
+
send: (content: string, type?: "text" | "image" | "file") => Promise<ChatMessage>;
|
|
12720
|
+
getMessages: (params?: {
|
|
12721
|
+
after?: number;
|
|
12722
|
+
limit?: number;
|
|
12723
|
+
}) => Promise<ChatMessage[]>;
|
|
12724
|
+
onMessage: (callback: MessageCallback) => () => void;
|
|
12725
|
+
onStatusChange: (callback: StatusCallback) => () => void;
|
|
12726
|
+
onTyping: (callback: TypingCallback) => () => void;
|
|
12727
|
+
sendTyping: () => Promise<void>;
|
|
12728
|
+
close: () => Promise<void>;
|
|
12729
|
+
disconnect: () => void;
|
|
12730
|
+
useWebSocket: () => Promise<void>;
|
|
12731
|
+
usePolling: () => void;
|
|
12732
|
+
};
|
|
12733
|
+
/**
|
|
12734
|
+
* Generate a random socket ID
|
|
12735
|
+
*/
|
|
12736
|
+
private generateSocketId;
|
|
12737
|
+
/**
|
|
12738
|
+
* Get visitor ID header
|
|
12739
|
+
*/
|
|
12740
|
+
private getVisitorHeader;
|
|
12741
|
+
/**
|
|
12742
|
+
* Set visitor ID manually (useful for server-side rendering)
|
|
12743
|
+
*/
|
|
12744
|
+
setVisitorId(visitorId: string): void;
|
|
12745
|
+
/**
|
|
12746
|
+
* Get current visitor ID
|
|
12747
|
+
*/
|
|
12748
|
+
getVisitorId(): string | null;
|
|
12749
|
+
/**
|
|
12750
|
+
* Disconnect WebSocket
|
|
12751
|
+
*/
|
|
12752
|
+
disconnectWebSocket(): void;
|
|
12753
|
+
}
|
|
12754
|
+
|
|
12584
12755
|
/**
|
|
12585
12756
|
* Diffsome SDK
|
|
12586
12757
|
*
|
|
@@ -12625,6 +12796,8 @@ declare class Diffsome {
|
|
|
12625
12796
|
readonly reservation: ReservationResource;
|
|
12626
12797
|
/** Site settings - currency, SEO, contact info */
|
|
12627
12798
|
readonly site: SiteResource;
|
|
12799
|
+
/** Live chat - customer support conversations */
|
|
12800
|
+
readonly chat: ChatResource;
|
|
12628
12801
|
constructor(config: DiffsomeConfig);
|
|
12629
12802
|
/**
|
|
12630
12803
|
* Check if user is authenticated
|
|
@@ -12660,4 +12833,4 @@ declare class Diffsome {
|
|
|
12660
12833
|
getApiKey(): string | null;
|
|
12661
12834
|
}
|
|
12662
12835
|
|
|
12663
|
-
export { type $defs, type AddToCartData, type AddToWishlistData, type ApiError, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogCategory, type BlogListParams, type BlogPost, type BlogPostCollection, type Board, type BoardCollection, type BoardComment, type BoardListParams, type BoardPost, type BoardPostCollection, type BoardPostListParams, type BundleItem, type BundlePricing, type CanReviewResponse, type Cart, type CartItem, type CartShippingInfo, type Comment, type CommentCollection, type CommentListParams$1 as CommentListParams, type Coupon, type CouponType, type CouponValidation, type CreateBoardPostData, type CreateCommentData, type CreateEntityData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateProductReviewData, type CreateReservationData, type CreateReservationResult, type CreateSubscriptionData, type CreateSubscriptionResult, type CurrencyInfo, type CustomEntity, Diffsome, type DiffsomeConfig, DiffsomeError, type DigitalDownloadLink, type DigitalFile, type Entity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormListParams, type FormSubmission, type FormSubmissionData, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type MemberSubscription, type Order, type OrderItem, type OrderListParams, type OrderOrderer, type OrderShipping, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PaymentStatusResponse, type PostListParams, type Product, type ProductAttribute, type ProductAttributeValue, type ProductCategory, type ProductCategoryCollection, type ProductCollection, type ProductListParams, type ProductListParamsExtended, type ProductOption, type ProductOptionValue, type ProductReview, type ProductReviewAuthor, type ProductReviewListParams, type ProductReviewStats, type ProductStatus, type ProductType, type ProductVariant, Diffsome as Promptly, type PromptlyConfig, DiffsomeError as PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationServiceStaff, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ResetPasswordData, type SetupIntentResult, type SiteInfo, type SocialAuthUrl, type SocialProvider, type StripeCheckoutData, type StripeCheckoutResponse, type StripeVerifyData, type StripeVerifyResponse, type SubmissionListParams, type SubmitFormData, type SubscriptionInterval, type SubscriptionPlan, type SubscriptionStatus, type TossPaymentConfirmData, type TossPaymentConfirmResponse, type TossPaymentReadyData, type TossPaymentReadyResponse, type UpdateBoardPostData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProductReviewData, type UpdateProfileData, type WishlistCheckBulkResult, type WishlistCheckResult, type WishlistItem, type WishlistListParams, type WishlistMoveToCartResult, type WishlistToggleResult, type components, Diffsome as default, type operations, type paths, type webhooks };
|
|
12836
|
+
export { type $defs, type AddToCartData, type AddToWishlistData, type ApiError, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogCategory, type BlogListParams, type BlogPost, type BlogPostCollection, type Board, type BoardCollection, type BoardComment, type BoardListParams, type BoardPost, type BoardPostCollection, type BoardPostListParams, type BundleItem, type BundlePricing, type CanReviewResponse, type Cart, type CartItem, type CartShippingInfo, type ChatAvailability, type ChatConversation, type ChatMessage, type Comment, type CommentCollection, type CommentListParams$1 as CommentListParams, type Coupon, type CouponType, type CouponValidation, type CreateBoardPostData, type CreateCommentData, type CreateEntityData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateProductReviewData, type CreateReservationData, type CreateReservationResult, type CreateSubscriptionData, type CreateSubscriptionResult, type CurrencyInfo, type CustomEntity, Diffsome, type DiffsomeConfig, DiffsomeError, type DigitalDownloadLink, type DigitalFile, type Entity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormListParams, type FormSubmission, type FormSubmissionData, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type MemberSubscription, type Order, type OrderItem, type OrderListParams, type OrderOrderer, type OrderShipping, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PaymentStatusResponse, type PollResponse, type PostListParams, type Product, type ProductAttribute, type ProductAttributeValue, type ProductCategory, type ProductCategoryCollection, type ProductCollection, type ProductListParams, type ProductListParamsExtended, type ProductOption, type ProductOptionValue, type ProductReview, type ProductReviewAuthor, type ProductReviewListParams, type ProductReviewStats, type ProductStatus, type ProductType, type ProductVariant, Diffsome as Promptly, type PromptlyConfig, DiffsomeError as PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationServiceStaff, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ResetPasswordData, type ReverbConfig, type SendMessageData, type SetupIntentResult, type SiteInfo, type SocialAuthUrl, type SocialProvider, type StartConversationData, type StripeCheckoutData, type StripeCheckoutResponse, type StripeVerifyData, type StripeVerifyResponse, type SubmissionListParams, type SubmitFormData, type SubscriptionInterval, type SubscriptionPlan, type SubscriptionStatus, type TossPaymentConfirmData, type TossPaymentConfirmResponse, type TossPaymentReadyData, type TossPaymentReadyResponse, type UpdateBoardPostData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProductReviewData, type UpdateProfileData, type WishlistCheckBulkResult, type WishlistCheckResult, type WishlistItem, type WishlistListParams, type WishlistMoveToCartResult, type WishlistToggleResult, type components, Diffsome as default, type operations, type paths, type webhooks };
|
package/dist/index.d.ts
CHANGED
|
@@ -12581,6 +12581,177 @@ declare class SiteResource {
|
|
|
12581
12581
|
formatPrice(amount: number, currency: CurrencyInfo): string;
|
|
12582
12582
|
}
|
|
12583
12583
|
|
|
12584
|
+
/**
|
|
12585
|
+
* Chat Resource for Diffsome SDK
|
|
12586
|
+
* Real-time customer support chat with WebSocket support
|
|
12587
|
+
*/
|
|
12588
|
+
|
|
12589
|
+
interface ChatConversation {
|
|
12590
|
+
id: number;
|
|
12591
|
+
visitor_id: string;
|
|
12592
|
+
visitor_name: string | null;
|
|
12593
|
+
visitor_email: string | null;
|
|
12594
|
+
status: 'open' | 'assigned' | 'closed';
|
|
12595
|
+
channel: 'web' | 'mobile' | 'api';
|
|
12596
|
+
created_at: string;
|
|
12597
|
+
last_message_at: string | null;
|
|
12598
|
+
}
|
|
12599
|
+
interface ChatMessage {
|
|
12600
|
+
id: number;
|
|
12601
|
+
conversation_id: number;
|
|
12602
|
+
content: string;
|
|
12603
|
+
type: 'text' | 'image' | 'file' | 'system';
|
|
12604
|
+
sender_type: 'visitor' | 'agent' | 'system';
|
|
12605
|
+
sender_name: string;
|
|
12606
|
+
is_read: boolean;
|
|
12607
|
+
created_at: string;
|
|
12608
|
+
attachments?: Array<{
|
|
12609
|
+
url: string;
|
|
12610
|
+
name: string;
|
|
12611
|
+
type: string;
|
|
12612
|
+
size: number;
|
|
12613
|
+
}>;
|
|
12614
|
+
}
|
|
12615
|
+
interface StartConversationData {
|
|
12616
|
+
visitor_name?: string;
|
|
12617
|
+
visitor_email?: string;
|
|
12618
|
+
initial_message?: string;
|
|
12619
|
+
channel?: 'web' | 'mobile' | 'api';
|
|
12620
|
+
metadata?: Record<string, unknown>;
|
|
12621
|
+
}
|
|
12622
|
+
interface SendMessageData {
|
|
12623
|
+
content: string;
|
|
12624
|
+
type?: 'text' | 'image' | 'file';
|
|
12625
|
+
attachments?: Array<{
|
|
12626
|
+
url: string;
|
|
12627
|
+
name: string;
|
|
12628
|
+
type: string;
|
|
12629
|
+
size: number;
|
|
12630
|
+
}>;
|
|
12631
|
+
}
|
|
12632
|
+
interface ChatAvailability {
|
|
12633
|
+
available: boolean;
|
|
12634
|
+
agents_online: number;
|
|
12635
|
+
}
|
|
12636
|
+
interface PollResponse {
|
|
12637
|
+
messages: ChatMessage[];
|
|
12638
|
+
conversation_status: 'open' | 'assigned' | 'closed';
|
|
12639
|
+
}
|
|
12640
|
+
interface ReverbConfig {
|
|
12641
|
+
host: string;
|
|
12642
|
+
port?: number;
|
|
12643
|
+
key: string;
|
|
12644
|
+
scheme?: 'ws' | 'wss';
|
|
12645
|
+
}
|
|
12646
|
+
type MessageCallback = (message: ChatMessage) => void;
|
|
12647
|
+
type StatusCallback = (status: 'open' | 'assigned' | 'closed') => void;
|
|
12648
|
+
type TypingCallback = (senderType: 'visitor' | 'agent') => void;
|
|
12649
|
+
declare class ChatResource {
|
|
12650
|
+
private http;
|
|
12651
|
+
private lastMessageIds;
|
|
12652
|
+
private visitorId;
|
|
12653
|
+
private reverbConfig;
|
|
12654
|
+
private websocket;
|
|
12655
|
+
private subscribedChannels;
|
|
12656
|
+
constructor(http: HttpClient);
|
|
12657
|
+
/**
|
|
12658
|
+
* Configure WebSocket connection (Laravel Reverb)
|
|
12659
|
+
*/
|
|
12660
|
+
configureWebSocket(config: ReverbConfig): void;
|
|
12661
|
+
/**
|
|
12662
|
+
* Start a new chat conversation
|
|
12663
|
+
*/
|
|
12664
|
+
start(data?: StartConversationData): Promise<{
|
|
12665
|
+
conversation_id: number;
|
|
12666
|
+
visitor_id: string;
|
|
12667
|
+
status: string;
|
|
12668
|
+
}>;
|
|
12669
|
+
/**
|
|
12670
|
+
* Get list of conversations
|
|
12671
|
+
*/
|
|
12672
|
+
list(params?: {
|
|
12673
|
+
per_page?: number;
|
|
12674
|
+
page?: number;
|
|
12675
|
+
}): Promise<{
|
|
12676
|
+
data: ChatConversation[];
|
|
12677
|
+
meta: {
|
|
12678
|
+
current_page: number;
|
|
12679
|
+
last_page: number;
|
|
12680
|
+
total: number;
|
|
12681
|
+
};
|
|
12682
|
+
}>;
|
|
12683
|
+
/**
|
|
12684
|
+
* Get conversation details
|
|
12685
|
+
*/
|
|
12686
|
+
get(conversationId: number): Promise<ChatConversation>;
|
|
12687
|
+
/**
|
|
12688
|
+
* Send a message
|
|
12689
|
+
*/
|
|
12690
|
+
send(conversationId: number, data: SendMessageData): Promise<ChatMessage>;
|
|
12691
|
+
/**
|
|
12692
|
+
* Get messages for a conversation
|
|
12693
|
+
*/
|
|
12694
|
+
getMessages(conversationId: number, params?: {
|
|
12695
|
+
after?: number;
|
|
12696
|
+
limit?: number;
|
|
12697
|
+
}): Promise<ChatMessage[]>;
|
|
12698
|
+
/**
|
|
12699
|
+
* Poll for new messages (fallback when WebSocket not available)
|
|
12700
|
+
*/
|
|
12701
|
+
poll(conversationId: number, lastMessageId?: number): Promise<PollResponse>;
|
|
12702
|
+
/**
|
|
12703
|
+
* Close conversation
|
|
12704
|
+
*/
|
|
12705
|
+
close(conversationId: number): Promise<void>;
|
|
12706
|
+
/**
|
|
12707
|
+
* Send typing indicator
|
|
12708
|
+
*/
|
|
12709
|
+
sendTyping(conversationId: number): Promise<void>;
|
|
12710
|
+
/**
|
|
12711
|
+
* Check agent availability
|
|
12712
|
+
*/
|
|
12713
|
+
checkAvailability(): Promise<ChatAvailability>;
|
|
12714
|
+
/**
|
|
12715
|
+
* Connect to a conversation with real-time updates
|
|
12716
|
+
* Uses WebSocket if configured, falls back to polling
|
|
12717
|
+
*/
|
|
12718
|
+
connect(conversationId: number): {
|
|
12719
|
+
send: (content: string, type?: "text" | "image" | "file") => Promise<ChatMessage>;
|
|
12720
|
+
getMessages: (params?: {
|
|
12721
|
+
after?: number;
|
|
12722
|
+
limit?: number;
|
|
12723
|
+
}) => Promise<ChatMessage[]>;
|
|
12724
|
+
onMessage: (callback: MessageCallback) => () => void;
|
|
12725
|
+
onStatusChange: (callback: StatusCallback) => () => void;
|
|
12726
|
+
onTyping: (callback: TypingCallback) => () => void;
|
|
12727
|
+
sendTyping: () => Promise<void>;
|
|
12728
|
+
close: () => Promise<void>;
|
|
12729
|
+
disconnect: () => void;
|
|
12730
|
+
useWebSocket: () => Promise<void>;
|
|
12731
|
+
usePolling: () => void;
|
|
12732
|
+
};
|
|
12733
|
+
/**
|
|
12734
|
+
* Generate a random socket ID
|
|
12735
|
+
*/
|
|
12736
|
+
private generateSocketId;
|
|
12737
|
+
/**
|
|
12738
|
+
* Get visitor ID header
|
|
12739
|
+
*/
|
|
12740
|
+
private getVisitorHeader;
|
|
12741
|
+
/**
|
|
12742
|
+
* Set visitor ID manually (useful for server-side rendering)
|
|
12743
|
+
*/
|
|
12744
|
+
setVisitorId(visitorId: string): void;
|
|
12745
|
+
/**
|
|
12746
|
+
* Get current visitor ID
|
|
12747
|
+
*/
|
|
12748
|
+
getVisitorId(): string | null;
|
|
12749
|
+
/**
|
|
12750
|
+
* Disconnect WebSocket
|
|
12751
|
+
*/
|
|
12752
|
+
disconnectWebSocket(): void;
|
|
12753
|
+
}
|
|
12754
|
+
|
|
12584
12755
|
/**
|
|
12585
12756
|
* Diffsome SDK
|
|
12586
12757
|
*
|
|
@@ -12625,6 +12796,8 @@ declare class Diffsome {
|
|
|
12625
12796
|
readonly reservation: ReservationResource;
|
|
12626
12797
|
/** Site settings - currency, SEO, contact info */
|
|
12627
12798
|
readonly site: SiteResource;
|
|
12799
|
+
/** Live chat - customer support conversations */
|
|
12800
|
+
readonly chat: ChatResource;
|
|
12628
12801
|
constructor(config: DiffsomeConfig);
|
|
12629
12802
|
/**
|
|
12630
12803
|
* Check if user is authenticated
|
|
@@ -12660,4 +12833,4 @@ declare class Diffsome {
|
|
|
12660
12833
|
getApiKey(): string | null;
|
|
12661
12834
|
}
|
|
12662
12835
|
|
|
12663
|
-
export { type $defs, type AddToCartData, type AddToWishlistData, type ApiError, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogCategory, type BlogListParams, type BlogPost, type BlogPostCollection, type Board, type BoardCollection, type BoardComment, type BoardListParams, type BoardPost, type BoardPostCollection, type BoardPostListParams, type BundleItem, type BundlePricing, type CanReviewResponse, type Cart, type CartItem, type CartShippingInfo, type Comment, type CommentCollection, type CommentListParams$1 as CommentListParams, type Coupon, type CouponType, type CouponValidation, type CreateBoardPostData, type CreateCommentData, type CreateEntityData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateProductReviewData, type CreateReservationData, type CreateReservationResult, type CreateSubscriptionData, type CreateSubscriptionResult, type CurrencyInfo, type CustomEntity, Diffsome, type DiffsomeConfig, DiffsomeError, type DigitalDownloadLink, type DigitalFile, type Entity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormListParams, type FormSubmission, type FormSubmissionData, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type MemberSubscription, type Order, type OrderItem, type OrderListParams, type OrderOrderer, type OrderShipping, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PaymentStatusResponse, type PostListParams, type Product, type ProductAttribute, type ProductAttributeValue, type ProductCategory, type ProductCategoryCollection, type ProductCollection, type ProductListParams, type ProductListParamsExtended, type ProductOption, type ProductOptionValue, type ProductReview, type ProductReviewAuthor, type ProductReviewListParams, type ProductReviewStats, type ProductStatus, type ProductType, type ProductVariant, Diffsome as Promptly, type PromptlyConfig, DiffsomeError as PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationServiceStaff, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ResetPasswordData, type SetupIntentResult, type SiteInfo, type SocialAuthUrl, type SocialProvider, type StripeCheckoutData, type StripeCheckoutResponse, type StripeVerifyData, type StripeVerifyResponse, type SubmissionListParams, type SubmitFormData, type SubscriptionInterval, type SubscriptionPlan, type SubscriptionStatus, type TossPaymentConfirmData, type TossPaymentConfirmResponse, type TossPaymentReadyData, type TossPaymentReadyResponse, type UpdateBoardPostData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProductReviewData, type UpdateProfileData, type WishlistCheckBulkResult, type WishlistCheckResult, type WishlistItem, type WishlistListParams, type WishlistMoveToCartResult, type WishlistToggleResult, type components, Diffsome as default, type operations, type paths, type webhooks };
|
|
12836
|
+
export { type $defs, type AddToCartData, type AddToWishlistData, type ApiError, type ApplyCouponData, type AuthResponse, type AvailableDatesParams, type AvailableSlotsParams, type BlogCategory, type BlogListParams, type BlogPost, type BlogPostCollection, type Board, type BoardCollection, type BoardComment, type BoardListParams, type BoardPost, type BoardPostCollection, type BoardPostListParams, type BundleItem, type BundlePricing, type CanReviewResponse, type Cart, type CartItem, type CartShippingInfo, type ChatAvailability, type ChatConversation, type ChatMessage, type Comment, type CommentCollection, type CommentListParams$1 as CommentListParams, type Coupon, type CouponType, type CouponValidation, type CreateBoardPostData, type CreateCommentData, type CreateEntityData, type CreateEntityRecordData, type CreateOrderData, type CreatePostData, type CreateProductReviewData, type CreateReservationData, type CreateReservationResult, type CreateSubscriptionData, type CreateSubscriptionResult, type CurrencyInfo, type CustomEntity, Diffsome, type DiffsomeConfig, DiffsomeError, type DigitalDownloadLink, type DigitalFile, type Entity, type EntityField, type EntityListParams, type EntityRecord, type EntitySchema, type ForgotPasswordData, type Form, type FormListParams, type FormSubmission, type FormSubmissionData, type ListParams, type ListResponse, type LoginCredentials, type Media, type Member, type MemberSubscription, type Order, type OrderItem, type OrderListParams, type OrderOrderer, type OrderShipping, type OrderStatus, type PaginatedResponse, type PaginationMeta, type Payment, type PaymentCancelData, type PaymentConfirmData, type PaymentMethod, type PaymentReadyData, type PaymentStatus, type PaymentStatusResponse, type PollResponse, type PostListParams, type Product, type ProductAttribute, type ProductAttributeValue, type ProductCategory, type ProductCategoryCollection, type ProductCollection, type ProductListParams, type ProductListParamsExtended, type ProductOption, type ProductOptionValue, type ProductReview, type ProductReviewAuthor, type ProductReviewListParams, type ProductReviewStats, type ProductStatus, type ProductType, type ProductVariant, Diffsome as Promptly, type PromptlyConfig, DiffsomeError as PromptlyError, type RegisterData, type Reservation, type ReservationListParams, type ReservationService, type ReservationServiceStaff, type ReservationSettings, type ReservationSlot, type ReservationStaff, type ResetPasswordData, type ReverbConfig, type SendMessageData, type SetupIntentResult, type SiteInfo, type SocialAuthUrl, type SocialProvider, type StartConversationData, type StripeCheckoutData, type StripeCheckoutResponse, type StripeVerifyData, type StripeVerifyResponse, type SubmissionListParams, type SubmitFormData, type SubscriptionInterval, type SubscriptionPlan, type SubscriptionStatus, type TossPaymentConfirmData, type TossPaymentConfirmResponse, type TossPaymentReadyData, type TossPaymentReadyResponse, type UpdateBoardPostData, type UpdateCartItemData, type UpdateCommentData, type UpdateEntityData, type UpdateEntityRecordData, type UpdatePostData, type UpdateProductReviewData, type UpdateProfileData, type WishlistCheckBulkResult, type WishlistCheckResult, type WishlistItem, type WishlistListParams, type WishlistMoveToCartResult, type WishlistToggleResult, type components, Diffsome as default, type operations, type paths, type webhooks };
|
package/dist/index.js
CHANGED
|
@@ -1705,6 +1705,330 @@ var SiteResource = class {
|
|
|
1705
1705
|
}
|
|
1706
1706
|
};
|
|
1707
1707
|
|
|
1708
|
+
// src/resources/chat.ts
|
|
1709
|
+
var ChatResource = class {
|
|
1710
|
+
constructor(http) {
|
|
1711
|
+
this.http = http;
|
|
1712
|
+
this.lastMessageIds = /* @__PURE__ */ new Map();
|
|
1713
|
+
this.visitorId = null;
|
|
1714
|
+
this.reverbConfig = null;
|
|
1715
|
+
this.websocket = null;
|
|
1716
|
+
this.subscribedChannels = /* @__PURE__ */ new Set();
|
|
1717
|
+
if (typeof localStorage !== "undefined") {
|
|
1718
|
+
this.visitorId = localStorage.getItem("diffsome_visitor_id");
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
/**
|
|
1722
|
+
* Configure WebSocket connection (Laravel Reverb)
|
|
1723
|
+
*/
|
|
1724
|
+
configureWebSocket(config) {
|
|
1725
|
+
this.reverbConfig = config;
|
|
1726
|
+
}
|
|
1727
|
+
/**
|
|
1728
|
+
* Start a new chat conversation
|
|
1729
|
+
*/
|
|
1730
|
+
async start(data = {}) {
|
|
1731
|
+
const response = await this.http.post("/chat/conversations", data);
|
|
1732
|
+
this.visitorId = response.visitor_id;
|
|
1733
|
+
if (typeof localStorage !== "undefined") {
|
|
1734
|
+
localStorage.setItem("diffsome_visitor_id", this.visitorId);
|
|
1735
|
+
}
|
|
1736
|
+
return response;
|
|
1737
|
+
}
|
|
1738
|
+
/**
|
|
1739
|
+
* Get list of conversations
|
|
1740
|
+
*/
|
|
1741
|
+
async list(params) {
|
|
1742
|
+
return this.http.request("/chat/conversations", {
|
|
1743
|
+
method: "GET",
|
|
1744
|
+
params,
|
|
1745
|
+
headers: this.getVisitorHeader()
|
|
1746
|
+
});
|
|
1747
|
+
}
|
|
1748
|
+
/**
|
|
1749
|
+
* Get conversation details
|
|
1750
|
+
*/
|
|
1751
|
+
async get(conversationId) {
|
|
1752
|
+
return this.http.request(
|
|
1753
|
+
`/chat/conversations/${conversationId}`,
|
|
1754
|
+
{
|
|
1755
|
+
method: "GET",
|
|
1756
|
+
headers: this.getVisitorHeader()
|
|
1757
|
+
}
|
|
1758
|
+
);
|
|
1759
|
+
}
|
|
1760
|
+
/**
|
|
1761
|
+
* Send a message
|
|
1762
|
+
*/
|
|
1763
|
+
async send(conversationId, data) {
|
|
1764
|
+
return this.http.request(
|
|
1765
|
+
`/chat/conversations/${conversationId}/messages`,
|
|
1766
|
+
{
|
|
1767
|
+
method: "POST",
|
|
1768
|
+
body: data,
|
|
1769
|
+
headers: this.getVisitorHeader()
|
|
1770
|
+
}
|
|
1771
|
+
);
|
|
1772
|
+
}
|
|
1773
|
+
/**
|
|
1774
|
+
* Get messages for a conversation
|
|
1775
|
+
*/
|
|
1776
|
+
async getMessages(conversationId, params) {
|
|
1777
|
+
return this.http.request(
|
|
1778
|
+
`/chat/conversations/${conversationId}/messages`,
|
|
1779
|
+
{
|
|
1780
|
+
method: "GET",
|
|
1781
|
+
params,
|
|
1782
|
+
headers: this.getVisitorHeader()
|
|
1783
|
+
}
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
/**
|
|
1787
|
+
* Poll for new messages (fallback when WebSocket not available)
|
|
1788
|
+
*/
|
|
1789
|
+
async poll(conversationId, lastMessageId) {
|
|
1790
|
+
return this.http.request(
|
|
1791
|
+
`/chat/conversations/${conversationId}/poll`,
|
|
1792
|
+
{
|
|
1793
|
+
method: "GET",
|
|
1794
|
+
params: { last_id: lastMessageId },
|
|
1795
|
+
headers: this.getVisitorHeader()
|
|
1796
|
+
}
|
|
1797
|
+
);
|
|
1798
|
+
}
|
|
1799
|
+
/**
|
|
1800
|
+
* Close conversation
|
|
1801
|
+
*/
|
|
1802
|
+
async close(conversationId) {
|
|
1803
|
+
await this.http.request(
|
|
1804
|
+
`/chat/conversations/${conversationId}/close`,
|
|
1805
|
+
{
|
|
1806
|
+
method: "POST",
|
|
1807
|
+
body: {},
|
|
1808
|
+
headers: this.getVisitorHeader()
|
|
1809
|
+
}
|
|
1810
|
+
);
|
|
1811
|
+
}
|
|
1812
|
+
/**
|
|
1813
|
+
* Send typing indicator
|
|
1814
|
+
*/
|
|
1815
|
+
async sendTyping(conversationId) {
|
|
1816
|
+
await this.http.request(
|
|
1817
|
+
`/chat/conversations/${conversationId}/typing`,
|
|
1818
|
+
{
|
|
1819
|
+
method: "POST",
|
|
1820
|
+
body: {},
|
|
1821
|
+
headers: this.getVisitorHeader()
|
|
1822
|
+
}
|
|
1823
|
+
);
|
|
1824
|
+
}
|
|
1825
|
+
/**
|
|
1826
|
+
* Check agent availability
|
|
1827
|
+
*/
|
|
1828
|
+
async checkAvailability() {
|
|
1829
|
+
return this.http.get("/chat/availability");
|
|
1830
|
+
}
|
|
1831
|
+
/**
|
|
1832
|
+
* Connect to a conversation with real-time updates
|
|
1833
|
+
* Uses WebSocket if configured, falls back to polling
|
|
1834
|
+
*/
|
|
1835
|
+
connect(conversationId) {
|
|
1836
|
+
const messageListeners = [];
|
|
1837
|
+
const statusListeners = [];
|
|
1838
|
+
const typingListeners = [];
|
|
1839
|
+
let pollingActive = false;
|
|
1840
|
+
let pollingTimeout = null;
|
|
1841
|
+
let wsChannel = null;
|
|
1842
|
+
const connectWebSocket = async () => {
|
|
1843
|
+
if (!this.reverbConfig) {
|
|
1844
|
+
startPolling();
|
|
1845
|
+
return;
|
|
1846
|
+
}
|
|
1847
|
+
try {
|
|
1848
|
+
const channelName = `private-chat.conversation.${conversationId}`;
|
|
1849
|
+
const authResponse = await this.http.request(
|
|
1850
|
+
"/broadcasting/auth",
|
|
1851
|
+
{
|
|
1852
|
+
method: "POST",
|
|
1853
|
+
body: {
|
|
1854
|
+
socket_id: this.generateSocketId(),
|
|
1855
|
+
channel_name: channelName
|
|
1856
|
+
},
|
|
1857
|
+
headers: this.getVisitorHeader()
|
|
1858
|
+
}
|
|
1859
|
+
);
|
|
1860
|
+
const { host, port = 443, key, scheme = "wss" } = this.reverbConfig;
|
|
1861
|
+
const wsUrl = `${scheme}://${host}:${port}/app/${key}`;
|
|
1862
|
+
if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
|
|
1863
|
+
this.websocket = new WebSocket(wsUrl);
|
|
1864
|
+
this.websocket.onopen = () => {
|
|
1865
|
+
console.log("WebSocket connected");
|
|
1866
|
+
subscribeToChannel(channelName, authResponse.auth);
|
|
1867
|
+
};
|
|
1868
|
+
this.websocket.onmessage = (event) => {
|
|
1869
|
+
const data = JSON.parse(event.data);
|
|
1870
|
+
handleWebSocketMessage(data);
|
|
1871
|
+
};
|
|
1872
|
+
this.websocket.onerror = (error) => {
|
|
1873
|
+
console.error("WebSocket error:", error);
|
|
1874
|
+
startPolling();
|
|
1875
|
+
};
|
|
1876
|
+
this.websocket.onclose = () => {
|
|
1877
|
+
console.log("WebSocket closed");
|
|
1878
|
+
this.subscribedChannels.delete(channelName);
|
|
1879
|
+
};
|
|
1880
|
+
} else {
|
|
1881
|
+
subscribeToChannel(channelName, authResponse.auth);
|
|
1882
|
+
}
|
|
1883
|
+
wsChannel = channelName;
|
|
1884
|
+
} catch (error) {
|
|
1885
|
+
console.error("WebSocket connection failed:", error);
|
|
1886
|
+
startPolling();
|
|
1887
|
+
}
|
|
1888
|
+
};
|
|
1889
|
+
const subscribeToChannel = (channelName, auth) => {
|
|
1890
|
+
if (!this.websocket || this.subscribedChannels.has(channelName)) return;
|
|
1891
|
+
this.websocket.send(JSON.stringify({
|
|
1892
|
+
event: "pusher:subscribe",
|
|
1893
|
+
data: {
|
|
1894
|
+
auth,
|
|
1895
|
+
channel: channelName
|
|
1896
|
+
}
|
|
1897
|
+
}));
|
|
1898
|
+
this.subscribedChannels.add(channelName);
|
|
1899
|
+
};
|
|
1900
|
+
const handleWebSocketMessage = (data) => {
|
|
1901
|
+
if (data.event === "message.sent") {
|
|
1902
|
+
const message = data.data;
|
|
1903
|
+
messageListeners.forEach((cb) => cb(message));
|
|
1904
|
+
this.lastMessageIds.set(conversationId, message.id);
|
|
1905
|
+
} else if (data.event === "conversation.updated") {
|
|
1906
|
+
statusListeners.forEach((cb) => cb(data.data.status));
|
|
1907
|
+
} else if (data.event === "typing") {
|
|
1908
|
+
typingListeners.forEach((cb) => cb(data.data.sender_type));
|
|
1909
|
+
}
|
|
1910
|
+
};
|
|
1911
|
+
const startPolling = () => {
|
|
1912
|
+
if (pollingActive) return;
|
|
1913
|
+
pollingActive = true;
|
|
1914
|
+
pollLoop();
|
|
1915
|
+
};
|
|
1916
|
+
const pollLoop = async () => {
|
|
1917
|
+
if (!pollingActive) return;
|
|
1918
|
+
try {
|
|
1919
|
+
const lastId = this.lastMessageIds.get(conversationId) || 0;
|
|
1920
|
+
const result = await this.poll(conversationId, lastId);
|
|
1921
|
+
for (const msg of result.messages) {
|
|
1922
|
+
if (msg.id > lastId) {
|
|
1923
|
+
this.lastMessageIds.set(conversationId, msg.id);
|
|
1924
|
+
messageListeners.forEach((cb) => cb(msg));
|
|
1925
|
+
}
|
|
1926
|
+
}
|
|
1927
|
+
statusListeners.forEach((cb) => cb(result.conversation_status));
|
|
1928
|
+
} catch (error) {
|
|
1929
|
+
console.error("Chat polling error:", error);
|
|
1930
|
+
}
|
|
1931
|
+
if (pollingActive) {
|
|
1932
|
+
pollingTimeout = setTimeout(pollLoop, 3e3);
|
|
1933
|
+
}
|
|
1934
|
+
};
|
|
1935
|
+
const stopPolling = () => {
|
|
1936
|
+
pollingActive = false;
|
|
1937
|
+
if (pollingTimeout) {
|
|
1938
|
+
clearTimeout(pollingTimeout);
|
|
1939
|
+
pollingTimeout = null;
|
|
1940
|
+
}
|
|
1941
|
+
};
|
|
1942
|
+
const disconnect = () => {
|
|
1943
|
+
stopPolling();
|
|
1944
|
+
if (wsChannel && this.websocket) {
|
|
1945
|
+
this.websocket.send(JSON.stringify({
|
|
1946
|
+
event: "pusher:unsubscribe",
|
|
1947
|
+
data: { channel: wsChannel }
|
|
1948
|
+
}));
|
|
1949
|
+
this.subscribedChannels.delete(wsChannel);
|
|
1950
|
+
}
|
|
1951
|
+
};
|
|
1952
|
+
if (this.reverbConfig) {
|
|
1953
|
+
connectWebSocket();
|
|
1954
|
+
}
|
|
1955
|
+
return {
|
|
1956
|
+
send: (content, type) => this.send(conversationId, { content, type }),
|
|
1957
|
+
getMessages: (params) => this.getMessages(conversationId, params),
|
|
1958
|
+
onMessage: (callback) => {
|
|
1959
|
+
messageListeners.push(callback);
|
|
1960
|
+
if (!this.reverbConfig) startPolling();
|
|
1961
|
+
return () => {
|
|
1962
|
+
const idx = messageListeners.indexOf(callback);
|
|
1963
|
+
if (idx > -1) messageListeners.splice(idx, 1);
|
|
1964
|
+
if (messageListeners.length === 0 && statusListeners.length === 0) {
|
|
1965
|
+
disconnect();
|
|
1966
|
+
}
|
|
1967
|
+
};
|
|
1968
|
+
},
|
|
1969
|
+
onStatusChange: (callback) => {
|
|
1970
|
+
statusListeners.push(callback);
|
|
1971
|
+
if (!this.reverbConfig) startPolling();
|
|
1972
|
+
return () => {
|
|
1973
|
+
const idx = statusListeners.indexOf(callback);
|
|
1974
|
+
if (idx > -1) statusListeners.splice(idx, 1);
|
|
1975
|
+
};
|
|
1976
|
+
},
|
|
1977
|
+
onTyping: (callback) => {
|
|
1978
|
+
typingListeners.push(callback);
|
|
1979
|
+
return () => {
|
|
1980
|
+
const idx = typingListeners.indexOf(callback);
|
|
1981
|
+
if (idx > -1) typingListeners.splice(idx, 1);
|
|
1982
|
+
};
|
|
1983
|
+
},
|
|
1984
|
+
sendTyping: () => this.sendTyping(conversationId),
|
|
1985
|
+
close: () => this.close(conversationId),
|
|
1986
|
+
disconnect,
|
|
1987
|
+
// Use WebSocket if available
|
|
1988
|
+
useWebSocket: () => connectWebSocket(),
|
|
1989
|
+
// Force polling mode
|
|
1990
|
+
usePolling: () => {
|
|
1991
|
+
disconnect();
|
|
1992
|
+
startPolling();
|
|
1993
|
+
}
|
|
1994
|
+
};
|
|
1995
|
+
}
|
|
1996
|
+
/**
|
|
1997
|
+
* Generate a random socket ID
|
|
1998
|
+
*/
|
|
1999
|
+
generateSocketId() {
|
|
2000
|
+
return `${Math.random().toString(36).substring(2)}.${Math.random().toString(36).substring(2)}`;
|
|
2001
|
+
}
|
|
2002
|
+
/**
|
|
2003
|
+
* Get visitor ID header
|
|
2004
|
+
*/
|
|
2005
|
+
getVisitorHeader() {
|
|
2006
|
+
return this.visitorId ? { "X-Visitor-Id": this.visitorId } : {};
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Set visitor ID manually (useful for server-side rendering)
|
|
2010
|
+
*/
|
|
2011
|
+
setVisitorId(visitorId) {
|
|
2012
|
+
this.visitorId = visitorId;
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Get current visitor ID
|
|
2016
|
+
*/
|
|
2017
|
+
getVisitorId() {
|
|
2018
|
+
return this.visitorId;
|
|
2019
|
+
}
|
|
2020
|
+
/**
|
|
2021
|
+
* Disconnect WebSocket
|
|
2022
|
+
*/
|
|
2023
|
+
disconnectWebSocket() {
|
|
2024
|
+
if (this.websocket) {
|
|
2025
|
+
this.websocket.close();
|
|
2026
|
+
this.websocket = null;
|
|
2027
|
+
this.subscribedChannels.clear();
|
|
2028
|
+
}
|
|
2029
|
+
}
|
|
2030
|
+
};
|
|
2031
|
+
|
|
1708
2032
|
// src/index.ts
|
|
1709
2033
|
var Diffsome = class {
|
|
1710
2034
|
constructor(config) {
|
|
@@ -1722,6 +2046,7 @@ var Diffsome = class {
|
|
|
1722
2046
|
this.entities = new EntitiesResource(this.http);
|
|
1723
2047
|
this.reservation = new ReservationResource(this.http);
|
|
1724
2048
|
this.site = new SiteResource(this.http);
|
|
2049
|
+
this.chat = new ChatResource(this.http);
|
|
1725
2050
|
}
|
|
1726
2051
|
/**
|
|
1727
2052
|
* Check if user is authenticated
|
package/dist/index.mjs
CHANGED
|
@@ -1675,6 +1675,330 @@ var SiteResource = class {
|
|
|
1675
1675
|
}
|
|
1676
1676
|
};
|
|
1677
1677
|
|
|
1678
|
+
// src/resources/chat.ts
|
|
1679
|
+
var ChatResource = class {
|
|
1680
|
+
constructor(http) {
|
|
1681
|
+
this.http = http;
|
|
1682
|
+
this.lastMessageIds = /* @__PURE__ */ new Map();
|
|
1683
|
+
this.visitorId = null;
|
|
1684
|
+
this.reverbConfig = null;
|
|
1685
|
+
this.websocket = null;
|
|
1686
|
+
this.subscribedChannels = /* @__PURE__ */ new Set();
|
|
1687
|
+
if (typeof localStorage !== "undefined") {
|
|
1688
|
+
this.visitorId = localStorage.getItem("diffsome_visitor_id");
|
|
1689
|
+
}
|
|
1690
|
+
}
|
|
1691
|
+
/**
|
|
1692
|
+
* Configure WebSocket connection (Laravel Reverb)
|
|
1693
|
+
*/
|
|
1694
|
+
configureWebSocket(config) {
|
|
1695
|
+
this.reverbConfig = config;
|
|
1696
|
+
}
|
|
1697
|
+
/**
|
|
1698
|
+
* Start a new chat conversation
|
|
1699
|
+
*/
|
|
1700
|
+
async start(data = {}) {
|
|
1701
|
+
const response = await this.http.post("/chat/conversations", data);
|
|
1702
|
+
this.visitorId = response.visitor_id;
|
|
1703
|
+
if (typeof localStorage !== "undefined") {
|
|
1704
|
+
localStorage.setItem("diffsome_visitor_id", this.visitorId);
|
|
1705
|
+
}
|
|
1706
|
+
return response;
|
|
1707
|
+
}
|
|
1708
|
+
/**
|
|
1709
|
+
* Get list of conversations
|
|
1710
|
+
*/
|
|
1711
|
+
async list(params) {
|
|
1712
|
+
return this.http.request("/chat/conversations", {
|
|
1713
|
+
method: "GET",
|
|
1714
|
+
params,
|
|
1715
|
+
headers: this.getVisitorHeader()
|
|
1716
|
+
});
|
|
1717
|
+
}
|
|
1718
|
+
/**
|
|
1719
|
+
* Get conversation details
|
|
1720
|
+
*/
|
|
1721
|
+
async get(conversationId) {
|
|
1722
|
+
return this.http.request(
|
|
1723
|
+
`/chat/conversations/${conversationId}`,
|
|
1724
|
+
{
|
|
1725
|
+
method: "GET",
|
|
1726
|
+
headers: this.getVisitorHeader()
|
|
1727
|
+
}
|
|
1728
|
+
);
|
|
1729
|
+
}
|
|
1730
|
+
/**
|
|
1731
|
+
* Send a message
|
|
1732
|
+
*/
|
|
1733
|
+
async send(conversationId, data) {
|
|
1734
|
+
return this.http.request(
|
|
1735
|
+
`/chat/conversations/${conversationId}/messages`,
|
|
1736
|
+
{
|
|
1737
|
+
method: "POST",
|
|
1738
|
+
body: data,
|
|
1739
|
+
headers: this.getVisitorHeader()
|
|
1740
|
+
}
|
|
1741
|
+
);
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Get messages for a conversation
|
|
1745
|
+
*/
|
|
1746
|
+
async getMessages(conversationId, params) {
|
|
1747
|
+
return this.http.request(
|
|
1748
|
+
`/chat/conversations/${conversationId}/messages`,
|
|
1749
|
+
{
|
|
1750
|
+
method: "GET",
|
|
1751
|
+
params,
|
|
1752
|
+
headers: this.getVisitorHeader()
|
|
1753
|
+
}
|
|
1754
|
+
);
|
|
1755
|
+
}
|
|
1756
|
+
/**
|
|
1757
|
+
* Poll for new messages (fallback when WebSocket not available)
|
|
1758
|
+
*/
|
|
1759
|
+
async poll(conversationId, lastMessageId) {
|
|
1760
|
+
return this.http.request(
|
|
1761
|
+
`/chat/conversations/${conversationId}/poll`,
|
|
1762
|
+
{
|
|
1763
|
+
method: "GET",
|
|
1764
|
+
params: { last_id: lastMessageId },
|
|
1765
|
+
headers: this.getVisitorHeader()
|
|
1766
|
+
}
|
|
1767
|
+
);
|
|
1768
|
+
}
|
|
1769
|
+
/**
|
|
1770
|
+
* Close conversation
|
|
1771
|
+
*/
|
|
1772
|
+
async close(conversationId) {
|
|
1773
|
+
await this.http.request(
|
|
1774
|
+
`/chat/conversations/${conversationId}/close`,
|
|
1775
|
+
{
|
|
1776
|
+
method: "POST",
|
|
1777
|
+
body: {},
|
|
1778
|
+
headers: this.getVisitorHeader()
|
|
1779
|
+
}
|
|
1780
|
+
);
|
|
1781
|
+
}
|
|
1782
|
+
/**
|
|
1783
|
+
* Send typing indicator
|
|
1784
|
+
*/
|
|
1785
|
+
async sendTyping(conversationId) {
|
|
1786
|
+
await this.http.request(
|
|
1787
|
+
`/chat/conversations/${conversationId}/typing`,
|
|
1788
|
+
{
|
|
1789
|
+
method: "POST",
|
|
1790
|
+
body: {},
|
|
1791
|
+
headers: this.getVisitorHeader()
|
|
1792
|
+
}
|
|
1793
|
+
);
|
|
1794
|
+
}
|
|
1795
|
+
/**
|
|
1796
|
+
* Check agent availability
|
|
1797
|
+
*/
|
|
1798
|
+
async checkAvailability() {
|
|
1799
|
+
return this.http.get("/chat/availability");
|
|
1800
|
+
}
|
|
1801
|
+
/**
|
|
1802
|
+
* Connect to a conversation with real-time updates
|
|
1803
|
+
* Uses WebSocket if configured, falls back to polling
|
|
1804
|
+
*/
|
|
1805
|
+
connect(conversationId) {
|
|
1806
|
+
const messageListeners = [];
|
|
1807
|
+
const statusListeners = [];
|
|
1808
|
+
const typingListeners = [];
|
|
1809
|
+
let pollingActive = false;
|
|
1810
|
+
let pollingTimeout = null;
|
|
1811
|
+
let wsChannel = null;
|
|
1812
|
+
const connectWebSocket = async () => {
|
|
1813
|
+
if (!this.reverbConfig) {
|
|
1814
|
+
startPolling();
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
try {
|
|
1818
|
+
const channelName = `private-chat.conversation.${conversationId}`;
|
|
1819
|
+
const authResponse = await this.http.request(
|
|
1820
|
+
"/broadcasting/auth",
|
|
1821
|
+
{
|
|
1822
|
+
method: "POST",
|
|
1823
|
+
body: {
|
|
1824
|
+
socket_id: this.generateSocketId(),
|
|
1825
|
+
channel_name: channelName
|
|
1826
|
+
},
|
|
1827
|
+
headers: this.getVisitorHeader()
|
|
1828
|
+
}
|
|
1829
|
+
);
|
|
1830
|
+
const { host, port = 443, key, scheme = "wss" } = this.reverbConfig;
|
|
1831
|
+
const wsUrl = `${scheme}://${host}:${port}/app/${key}`;
|
|
1832
|
+
if (!this.websocket || this.websocket.readyState !== WebSocket.OPEN) {
|
|
1833
|
+
this.websocket = new WebSocket(wsUrl);
|
|
1834
|
+
this.websocket.onopen = () => {
|
|
1835
|
+
console.log("WebSocket connected");
|
|
1836
|
+
subscribeToChannel(channelName, authResponse.auth);
|
|
1837
|
+
};
|
|
1838
|
+
this.websocket.onmessage = (event) => {
|
|
1839
|
+
const data = JSON.parse(event.data);
|
|
1840
|
+
handleWebSocketMessage(data);
|
|
1841
|
+
};
|
|
1842
|
+
this.websocket.onerror = (error) => {
|
|
1843
|
+
console.error("WebSocket error:", error);
|
|
1844
|
+
startPolling();
|
|
1845
|
+
};
|
|
1846
|
+
this.websocket.onclose = () => {
|
|
1847
|
+
console.log("WebSocket closed");
|
|
1848
|
+
this.subscribedChannels.delete(channelName);
|
|
1849
|
+
};
|
|
1850
|
+
} else {
|
|
1851
|
+
subscribeToChannel(channelName, authResponse.auth);
|
|
1852
|
+
}
|
|
1853
|
+
wsChannel = channelName;
|
|
1854
|
+
} catch (error) {
|
|
1855
|
+
console.error("WebSocket connection failed:", error);
|
|
1856
|
+
startPolling();
|
|
1857
|
+
}
|
|
1858
|
+
};
|
|
1859
|
+
const subscribeToChannel = (channelName, auth) => {
|
|
1860
|
+
if (!this.websocket || this.subscribedChannels.has(channelName)) return;
|
|
1861
|
+
this.websocket.send(JSON.stringify({
|
|
1862
|
+
event: "pusher:subscribe",
|
|
1863
|
+
data: {
|
|
1864
|
+
auth,
|
|
1865
|
+
channel: channelName
|
|
1866
|
+
}
|
|
1867
|
+
}));
|
|
1868
|
+
this.subscribedChannels.add(channelName);
|
|
1869
|
+
};
|
|
1870
|
+
const handleWebSocketMessage = (data) => {
|
|
1871
|
+
if (data.event === "message.sent") {
|
|
1872
|
+
const message = data.data;
|
|
1873
|
+
messageListeners.forEach((cb) => cb(message));
|
|
1874
|
+
this.lastMessageIds.set(conversationId, message.id);
|
|
1875
|
+
} else if (data.event === "conversation.updated") {
|
|
1876
|
+
statusListeners.forEach((cb) => cb(data.data.status));
|
|
1877
|
+
} else if (data.event === "typing") {
|
|
1878
|
+
typingListeners.forEach((cb) => cb(data.data.sender_type));
|
|
1879
|
+
}
|
|
1880
|
+
};
|
|
1881
|
+
const startPolling = () => {
|
|
1882
|
+
if (pollingActive) return;
|
|
1883
|
+
pollingActive = true;
|
|
1884
|
+
pollLoop();
|
|
1885
|
+
};
|
|
1886
|
+
const pollLoop = async () => {
|
|
1887
|
+
if (!pollingActive) return;
|
|
1888
|
+
try {
|
|
1889
|
+
const lastId = this.lastMessageIds.get(conversationId) || 0;
|
|
1890
|
+
const result = await this.poll(conversationId, lastId);
|
|
1891
|
+
for (const msg of result.messages) {
|
|
1892
|
+
if (msg.id > lastId) {
|
|
1893
|
+
this.lastMessageIds.set(conversationId, msg.id);
|
|
1894
|
+
messageListeners.forEach((cb) => cb(msg));
|
|
1895
|
+
}
|
|
1896
|
+
}
|
|
1897
|
+
statusListeners.forEach((cb) => cb(result.conversation_status));
|
|
1898
|
+
} catch (error) {
|
|
1899
|
+
console.error("Chat polling error:", error);
|
|
1900
|
+
}
|
|
1901
|
+
if (pollingActive) {
|
|
1902
|
+
pollingTimeout = setTimeout(pollLoop, 3e3);
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
const stopPolling = () => {
|
|
1906
|
+
pollingActive = false;
|
|
1907
|
+
if (pollingTimeout) {
|
|
1908
|
+
clearTimeout(pollingTimeout);
|
|
1909
|
+
pollingTimeout = null;
|
|
1910
|
+
}
|
|
1911
|
+
};
|
|
1912
|
+
const disconnect = () => {
|
|
1913
|
+
stopPolling();
|
|
1914
|
+
if (wsChannel && this.websocket) {
|
|
1915
|
+
this.websocket.send(JSON.stringify({
|
|
1916
|
+
event: "pusher:unsubscribe",
|
|
1917
|
+
data: { channel: wsChannel }
|
|
1918
|
+
}));
|
|
1919
|
+
this.subscribedChannels.delete(wsChannel);
|
|
1920
|
+
}
|
|
1921
|
+
};
|
|
1922
|
+
if (this.reverbConfig) {
|
|
1923
|
+
connectWebSocket();
|
|
1924
|
+
}
|
|
1925
|
+
return {
|
|
1926
|
+
send: (content, type) => this.send(conversationId, { content, type }),
|
|
1927
|
+
getMessages: (params) => this.getMessages(conversationId, params),
|
|
1928
|
+
onMessage: (callback) => {
|
|
1929
|
+
messageListeners.push(callback);
|
|
1930
|
+
if (!this.reverbConfig) startPolling();
|
|
1931
|
+
return () => {
|
|
1932
|
+
const idx = messageListeners.indexOf(callback);
|
|
1933
|
+
if (idx > -1) messageListeners.splice(idx, 1);
|
|
1934
|
+
if (messageListeners.length === 0 && statusListeners.length === 0) {
|
|
1935
|
+
disconnect();
|
|
1936
|
+
}
|
|
1937
|
+
};
|
|
1938
|
+
},
|
|
1939
|
+
onStatusChange: (callback) => {
|
|
1940
|
+
statusListeners.push(callback);
|
|
1941
|
+
if (!this.reverbConfig) startPolling();
|
|
1942
|
+
return () => {
|
|
1943
|
+
const idx = statusListeners.indexOf(callback);
|
|
1944
|
+
if (idx > -1) statusListeners.splice(idx, 1);
|
|
1945
|
+
};
|
|
1946
|
+
},
|
|
1947
|
+
onTyping: (callback) => {
|
|
1948
|
+
typingListeners.push(callback);
|
|
1949
|
+
return () => {
|
|
1950
|
+
const idx = typingListeners.indexOf(callback);
|
|
1951
|
+
if (idx > -1) typingListeners.splice(idx, 1);
|
|
1952
|
+
};
|
|
1953
|
+
},
|
|
1954
|
+
sendTyping: () => this.sendTyping(conversationId),
|
|
1955
|
+
close: () => this.close(conversationId),
|
|
1956
|
+
disconnect,
|
|
1957
|
+
// Use WebSocket if available
|
|
1958
|
+
useWebSocket: () => connectWebSocket(),
|
|
1959
|
+
// Force polling mode
|
|
1960
|
+
usePolling: () => {
|
|
1961
|
+
disconnect();
|
|
1962
|
+
startPolling();
|
|
1963
|
+
}
|
|
1964
|
+
};
|
|
1965
|
+
}
|
|
1966
|
+
/**
|
|
1967
|
+
* Generate a random socket ID
|
|
1968
|
+
*/
|
|
1969
|
+
generateSocketId() {
|
|
1970
|
+
return `${Math.random().toString(36).substring(2)}.${Math.random().toString(36).substring(2)}`;
|
|
1971
|
+
}
|
|
1972
|
+
/**
|
|
1973
|
+
* Get visitor ID header
|
|
1974
|
+
*/
|
|
1975
|
+
getVisitorHeader() {
|
|
1976
|
+
return this.visitorId ? { "X-Visitor-Id": this.visitorId } : {};
|
|
1977
|
+
}
|
|
1978
|
+
/**
|
|
1979
|
+
* Set visitor ID manually (useful for server-side rendering)
|
|
1980
|
+
*/
|
|
1981
|
+
setVisitorId(visitorId) {
|
|
1982
|
+
this.visitorId = visitorId;
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* Get current visitor ID
|
|
1986
|
+
*/
|
|
1987
|
+
getVisitorId() {
|
|
1988
|
+
return this.visitorId;
|
|
1989
|
+
}
|
|
1990
|
+
/**
|
|
1991
|
+
* Disconnect WebSocket
|
|
1992
|
+
*/
|
|
1993
|
+
disconnectWebSocket() {
|
|
1994
|
+
if (this.websocket) {
|
|
1995
|
+
this.websocket.close();
|
|
1996
|
+
this.websocket = null;
|
|
1997
|
+
this.subscribedChannels.clear();
|
|
1998
|
+
}
|
|
1999
|
+
}
|
|
2000
|
+
};
|
|
2001
|
+
|
|
1678
2002
|
// src/index.ts
|
|
1679
2003
|
var Diffsome = class {
|
|
1680
2004
|
constructor(config) {
|
|
@@ -1692,6 +2016,7 @@ var Diffsome = class {
|
|
|
1692
2016
|
this.entities = new EntitiesResource(this.http);
|
|
1693
2017
|
this.reservation = new ReservationResource(this.http);
|
|
1694
2018
|
this.site = new SiteResource(this.http);
|
|
2019
|
+
this.chat = new ChatResource(this.http);
|
|
1695
2020
|
}
|
|
1696
2021
|
/**
|
|
1697
2022
|
* Check if user is authenticated
|