@diffsome/sdk 3.2.7 → 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 +257 -11
- package/dist/index.d.ts +257 -11
- package/dist/index.js +362 -0
- package/dist/index.mjs +362 -0
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -1639,6 +1639,366 @@ var ReservationResource = class {
|
|
|
1639
1639
|
}
|
|
1640
1640
|
};
|
|
1641
1641
|
|
|
1642
|
+
// src/resources/site.ts
|
|
1643
|
+
var SiteResource = class {
|
|
1644
|
+
constructor(http) {
|
|
1645
|
+
this.http = http;
|
|
1646
|
+
}
|
|
1647
|
+
/**
|
|
1648
|
+
* Get site information
|
|
1649
|
+
* Returns site settings including currency, SEO, contact info
|
|
1650
|
+
*/
|
|
1651
|
+
async getInfo() {
|
|
1652
|
+
return this.http.get("/site");
|
|
1653
|
+
}
|
|
1654
|
+
/**
|
|
1655
|
+
* Get currency info only (lightweight)
|
|
1656
|
+
*/
|
|
1657
|
+
async getCurrency() {
|
|
1658
|
+
const response = await this.http.get("/site/currency");
|
|
1659
|
+
return response.currency;
|
|
1660
|
+
}
|
|
1661
|
+
/**
|
|
1662
|
+
* Format price with site's currency settings
|
|
1663
|
+
* @param amount - The amount to format
|
|
1664
|
+
* @param currency - Optional currency info (uses fetched currency if not provided)
|
|
1665
|
+
*/
|
|
1666
|
+
formatPrice(amount, currency) {
|
|
1667
|
+
const formatted = amount.toLocaleString(void 0, {
|
|
1668
|
+
minimumFractionDigits: currency.decimals,
|
|
1669
|
+
maximumFractionDigits: currency.decimals
|
|
1670
|
+
});
|
|
1671
|
+
if (currency.position === "after") {
|
|
1672
|
+
return `${formatted}${currency.symbol}`;
|
|
1673
|
+
}
|
|
1674
|
+
return `${currency.symbol}${formatted}`;
|
|
1675
|
+
}
|
|
1676
|
+
};
|
|
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
|
+
|
|
1642
2002
|
// src/index.ts
|
|
1643
2003
|
var Diffsome = class {
|
|
1644
2004
|
constructor(config) {
|
|
@@ -1655,6 +2015,8 @@ var Diffsome = class {
|
|
|
1655
2015
|
this.media = new MediaResource(this.http);
|
|
1656
2016
|
this.entities = new EntitiesResource(this.http);
|
|
1657
2017
|
this.reservation = new ReservationResource(this.http);
|
|
2018
|
+
this.site = new SiteResource(this.http);
|
|
2019
|
+
this.chat = new ChatResource(this.http);
|
|
1658
2020
|
}
|
|
1659
2021
|
/**
|
|
1660
2022
|
* Check if user is authenticated
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@diffsome/sdk",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.9",
|
|
4
4
|
"description": "Diffsome SDK for JavaScript/TypeScript - Different + Awesome",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"repository": {
|
|
35
35
|
"type": "git",
|
|
36
|
-
"url": "https://github.com/diffsome/sdk.git"
|
|
36
|
+
"url": "https://github.com/diffsome/diffsome-sdk.git"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
39
|
"openapi-typescript": "^7.10.1",
|