@ixblix/sdk-js 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +201 -0
- package/dist/client.d.ts +132 -0
- package/dist/client.js +251 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto.d.ts +92 -0
- package/dist/crypto.js +195 -0
- package/dist/crypto.js.map +1 -0
- package/dist/errors.d.ts +21 -0
- package/dist/errors.js +20 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +25 -0
- package/dist/index.js +22 -0
- package/dist/index.js.map +1 -0
- package/dist/keypair.d.ts +8 -0
- package/dist/keypair.js +44 -0
- package/dist/keypair.js.map +1 -0
- package/dist/types.d.ts +300 -0
- package/dist/types.js +9 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks.d.ts +35 -0
- package/dist/webhooks.js +78 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +54 -0
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the ixblix SDK.
|
|
3
|
+
*
|
|
4
|
+
* These types mirror the ixblix public REST API. They are intentionally
|
|
5
|
+
* self-contained (no dependency on any private package) so the SDK can be
|
|
6
|
+
* published and consumed by any desk/CRM integration.
|
|
7
|
+
*/
|
|
8
|
+
/** Who sent a message. */
|
|
9
|
+
export type SenderType = "CONTACT" | "COMPANY" | "SYSTEM";
|
|
10
|
+
/** Lifecycle state of the E2EE key exchange for a conversation. */
|
|
11
|
+
export type ConversationKeyStatus = "AWAITING_OPERATOR" | "AWAITING_CUSTOMER" | "ACTIVE";
|
|
12
|
+
/** Lifecycle state of a conversation. */
|
|
13
|
+
export type ConversationStatus = "ACTIVE" | "CLOSED" | "EXPIRED";
|
|
14
|
+
/** Consent state of a contact (LGPD). */
|
|
15
|
+
export type ConsentStatus = "PENDING" | "GRANTED" | "DENIED" | "REVOKED";
|
|
16
|
+
/** A contact (customer) in a conversation. */
|
|
17
|
+
export interface Contact {
|
|
18
|
+
id: string;
|
|
19
|
+
externalId: string;
|
|
20
|
+
name?: string;
|
|
21
|
+
phone?: string;
|
|
22
|
+
email?: string;
|
|
23
|
+
consentStatus: ConsentStatus;
|
|
24
|
+
}
|
|
25
|
+
/** Payload used to create a conversation for a contact. */
|
|
26
|
+
export interface ContactInput {
|
|
27
|
+
/** Unique identifier of the contact in the original channel. */
|
|
28
|
+
externalId: string;
|
|
29
|
+
name?: string;
|
|
30
|
+
phone?: string;
|
|
31
|
+
email?: string;
|
|
32
|
+
/** Free-form metadata from the CRM. */
|
|
33
|
+
metadata?: Record<string, unknown>;
|
|
34
|
+
}
|
|
35
|
+
/** A conversation as returned by the ixblix API. */
|
|
36
|
+
export interface Conversation {
|
|
37
|
+
id: string;
|
|
38
|
+
token: string;
|
|
39
|
+
status: ConversationStatus;
|
|
40
|
+
keyStatus: ConversationKeyStatus;
|
|
41
|
+
sourceChannel: string;
|
|
42
|
+
createdAt: string;
|
|
43
|
+
}
|
|
44
|
+
/** Company branding customizations (white-label). */
|
|
45
|
+
export interface CompanyCustomization {
|
|
46
|
+
id: string;
|
|
47
|
+
brandName?: string;
|
|
48
|
+
logoUrl?: string;
|
|
49
|
+
primaryColor?: string;
|
|
50
|
+
faviconUrl?: string;
|
|
51
|
+
welcomeMessage?: string;
|
|
52
|
+
}
|
|
53
|
+
/** Company summary returned when creating a conversation. */
|
|
54
|
+
export interface CompanySummary {
|
|
55
|
+
id: string;
|
|
56
|
+
name: string;
|
|
57
|
+
customizations?: CompanyCustomization;
|
|
58
|
+
}
|
|
59
|
+
/** Result of creating a conversation. */
|
|
60
|
+
export interface CreateConversationResult {
|
|
61
|
+
conversation: Conversation;
|
|
62
|
+
contact: Contact;
|
|
63
|
+
/** URL to share with the contact so they can join the secure chat. */
|
|
64
|
+
deeplink: string;
|
|
65
|
+
company: CompanySummary;
|
|
66
|
+
}
|
|
67
|
+
/** Current E2EE key state of a conversation (operator view). */
|
|
68
|
+
export interface ConversationKeys {
|
|
69
|
+
conversationId: string;
|
|
70
|
+
keyStatus: ConversationKeyStatus;
|
|
71
|
+
operatorPublicKey: string | null;
|
|
72
|
+
customerPublicKey: string | null;
|
|
73
|
+
}
|
|
74
|
+
/** Result of registering the customer's public key. */
|
|
75
|
+
export interface RegisterCustomerKeyResult {
|
|
76
|
+
conversationId: string;
|
|
77
|
+
keyStatus: ConversationKeyStatus;
|
|
78
|
+
}
|
|
79
|
+
/** Result of erasing a conversation's encrypted content. */
|
|
80
|
+
export interface EraseConversationResult {
|
|
81
|
+
conversationId: string;
|
|
82
|
+
deletedMessages: number;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Cryptographic envelope attached to an encrypted message or media file.
|
|
86
|
+
*
|
|
87
|
+
* The ixblix backend only ever stores and relays these fields — it never sees the
|
|
88
|
+
* plaintext content nor any private key. `content` holds the base64 AES-GCM
|
|
89
|
+
* ciphertext; `encryptedKey` holds the per-message AES key wrapped to the
|
|
90
|
+
* recipient's RSA-OAEP public key, and `selfEncryptedKey` holds the same AES
|
|
91
|
+
* key wrapped to the sender's own public key so the sender can read back its
|
|
92
|
+
* own sent messages.
|
|
93
|
+
*/
|
|
94
|
+
export interface MessageEnvelope {
|
|
95
|
+
/** Base64 AES-256-GCM ciphertext of the plaintext content. */
|
|
96
|
+
content: string;
|
|
97
|
+
/** Base64 AES-GCM initialization vector (12 bytes). */
|
|
98
|
+
iv: string;
|
|
99
|
+
/** Base64 AES-GCM authentication tag (16 bytes). */
|
|
100
|
+
authTag: string;
|
|
101
|
+
/** Base64 RSA-OAEP-wrapped per-message AES key (to the recipient). */
|
|
102
|
+
encryptedKey: string;
|
|
103
|
+
/** Base64 RSA-OAEP-wrapped per-message AES key (to the sender, for self-read). */
|
|
104
|
+
selfEncryptedKey: string;
|
|
105
|
+
/** Identifier of the sender's public key. */
|
|
106
|
+
keyId: string;
|
|
107
|
+
}
|
|
108
|
+
/** A message as returned by the ixblix API. */
|
|
109
|
+
export interface Message {
|
|
110
|
+
id: string;
|
|
111
|
+
conversationId: string;
|
|
112
|
+
senderType: SenderType;
|
|
113
|
+
/** Plaintext for legacy/system messages, or base64 ciphertext when encrypted. */
|
|
114
|
+
content: string;
|
|
115
|
+
contentType: string;
|
|
116
|
+
/** True when `content` is ciphertext and the envelope fields are populated. */
|
|
117
|
+
contentEncrypted: boolean;
|
|
118
|
+
keyId?: string;
|
|
119
|
+
iv?: string;
|
|
120
|
+
authTag?: string;
|
|
121
|
+
encryptedKey?: string;
|
|
122
|
+
selfEncryptedKey?: string;
|
|
123
|
+
/** Present when the message carries an attached media file. */
|
|
124
|
+
mediaId?: string;
|
|
125
|
+
media?: Media;
|
|
126
|
+
sentAt: string;
|
|
127
|
+
}
|
|
128
|
+
/** Metadata of a media file attached to a message. */
|
|
129
|
+
export interface Media {
|
|
130
|
+
id: string;
|
|
131
|
+
companyId: string;
|
|
132
|
+
conversationId: string;
|
|
133
|
+
messageId?: string;
|
|
134
|
+
mimeType: string;
|
|
135
|
+
fileName: string;
|
|
136
|
+
sizeBytes: number;
|
|
137
|
+
iv?: string;
|
|
138
|
+
authTag?: string;
|
|
139
|
+
encryptedKey?: string;
|
|
140
|
+
selfEncryptedKey?: string;
|
|
141
|
+
keyId?: string;
|
|
142
|
+
createdAt: string;
|
|
143
|
+
}
|
|
144
|
+
/** A subscription plan offered by ixblix. */
|
|
145
|
+
export interface Plan {
|
|
146
|
+
id: string;
|
|
147
|
+
name: string;
|
|
148
|
+
description?: string;
|
|
149
|
+
billingType: "MESSAGES" | "CONVERSATIONS" | "COMPANY" | "TIME" | "CHANNEL";
|
|
150
|
+
includedConversations?: number | null;
|
|
151
|
+
includedMessages?: number | null;
|
|
152
|
+
durationDays?: number | null;
|
|
153
|
+
priceCents: number;
|
|
154
|
+
overagePriceCents?: number | null;
|
|
155
|
+
isActive: boolean;
|
|
156
|
+
isPublic: boolean;
|
|
157
|
+
createdAt: string;
|
|
158
|
+
}
|
|
159
|
+
/** Company registration payload (keyless onboarding). */
|
|
160
|
+
export interface RegisterCompanyInput {
|
|
161
|
+
name: string;
|
|
162
|
+
slug: string;
|
|
163
|
+
planId?: string;
|
|
164
|
+
paymentProvider?: string;
|
|
165
|
+
confirmationWebhookUrl?: string;
|
|
166
|
+
}
|
|
167
|
+
/** Payment instructions returned when registering a company. */
|
|
168
|
+
export interface PaymentInstructions {
|
|
169
|
+
transactionId: string;
|
|
170
|
+
provider: string;
|
|
171
|
+
amountCents: number;
|
|
172
|
+
currency: string;
|
|
173
|
+
confirmationUrl: string;
|
|
174
|
+
status: string;
|
|
175
|
+
}
|
|
176
|
+
/** Result of registering a company. */
|
|
177
|
+
export interface RegisterCompanyResult {
|
|
178
|
+
company: {
|
|
179
|
+
id: string;
|
|
180
|
+
name: string;
|
|
181
|
+
slug: string;
|
|
182
|
+
status: string;
|
|
183
|
+
planId?: string;
|
|
184
|
+
createdAt: string;
|
|
185
|
+
};
|
|
186
|
+
payment: PaymentInstructions;
|
|
187
|
+
}
|
|
188
|
+
/** Result of activating a company (payment confirmed). */
|
|
189
|
+
export interface ActivateCompanyResult {
|
|
190
|
+
apiKey: string;
|
|
191
|
+
status: string;
|
|
192
|
+
}
|
|
193
|
+
/** Company balance / plan state. */
|
|
194
|
+
export interface CompanyBalance {
|
|
195
|
+
id: string;
|
|
196
|
+
name: string;
|
|
197
|
+
balanceCents: number;
|
|
198
|
+
planId?: string;
|
|
199
|
+
planExpiresAt?: string;
|
|
200
|
+
}
|
|
201
|
+
/** A credit purchase record. */
|
|
202
|
+
export interface CreditPurchase {
|
|
203
|
+
id: string;
|
|
204
|
+
companyId: string;
|
|
205
|
+
amountCents: number;
|
|
206
|
+
currency: string;
|
|
207
|
+
provider: string;
|
|
208
|
+
providerTransactionId?: string;
|
|
209
|
+
status: "PENDING" | "COMPLETED" | "FAILED" | "REFUNDED";
|
|
210
|
+
metadata?: Record<string, unknown>;
|
|
211
|
+
purchasedAt: string;
|
|
212
|
+
createdAt: string;
|
|
213
|
+
}
|
|
214
|
+
/** Result of purchasing credits. */
|
|
215
|
+
export interface PurchaseCreditsResult {
|
|
216
|
+
purchase: CreditPurchase;
|
|
217
|
+
result: {
|
|
218
|
+
success: boolean;
|
|
219
|
+
transactionId?: string;
|
|
220
|
+
provider?: string;
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
/** Available payment providers. */
|
|
224
|
+
export interface PaymentProvidersResult {
|
|
225
|
+
providers: string[];
|
|
226
|
+
}
|
|
227
|
+
/** Payload relayed from the original channel via webhook. */
|
|
228
|
+
export interface OriginalChannelMessageInput {
|
|
229
|
+
conversationId: string;
|
|
230
|
+
/** Base64 AES-GCM ciphertext (end-to-end encrypted). */
|
|
231
|
+
content: string;
|
|
232
|
+
iv: string;
|
|
233
|
+
authTag: string;
|
|
234
|
+
encryptedKey: string;
|
|
235
|
+
selfEncryptedKey: string;
|
|
236
|
+
keyId: string;
|
|
237
|
+
/** Free-form metadata from the original channel (e.g. channelMessageId). */
|
|
238
|
+
metadata?: Record<string, unknown>;
|
|
239
|
+
}
|
|
240
|
+
/** Webhook event payloads ixblix may deliver to a company. */
|
|
241
|
+
export type WebhookEvent = CompanyActivatedEvent | MessageReceivedEvent | MessageReadEvent | CustomerJoinedEvent | ConversationClosedEvent | PresenceEvent | BalanceLowEvent;
|
|
242
|
+
/** Delivered when a company is activated after payment confirmation. */
|
|
243
|
+
export interface CompanyActivatedEvent {
|
|
244
|
+
event: "COMPANY_ACTIVATED";
|
|
245
|
+
companyId: string;
|
|
246
|
+
transactionId: string;
|
|
247
|
+
apiKey: string;
|
|
248
|
+
}
|
|
249
|
+
/** Delivered when a contact sends a message (text or media). */
|
|
250
|
+
export interface MessageReceivedEvent {
|
|
251
|
+
event: "MESSAGE_RECEIVED";
|
|
252
|
+
companyId: string;
|
|
253
|
+
conversationId: string;
|
|
254
|
+
messageId: string;
|
|
255
|
+
sentAt: string;
|
|
256
|
+
}
|
|
257
|
+
/** Delivered when the customer reads a company-sent message. */
|
|
258
|
+
export interface MessageReadEvent {
|
|
259
|
+
event: "MESSAGE_READ";
|
|
260
|
+
companyId: string;
|
|
261
|
+
conversationId: string;
|
|
262
|
+
messageId: string;
|
|
263
|
+
readAt: string;
|
|
264
|
+
}
|
|
265
|
+
/** Delivered when the customer joins the secure conversation and registers its public key. */
|
|
266
|
+
export interface CustomerJoinedEvent {
|
|
267
|
+
event: "CUSTOMER_JOINED";
|
|
268
|
+
companyId: string;
|
|
269
|
+
conversationId: string;
|
|
270
|
+
customerPublicKey: string;
|
|
271
|
+
}
|
|
272
|
+
/** Delivered when a conversation is closed. */
|
|
273
|
+
export interface ConversationClosedEvent {
|
|
274
|
+
event: "CONVERSATION_CLOSED";
|
|
275
|
+
companyId: string;
|
|
276
|
+
conversationId: string;
|
|
277
|
+
}
|
|
278
|
+
/** Presence/metadata event reported by the customer's chat window. */
|
|
279
|
+
export interface PresenceEvent {
|
|
280
|
+
event: "TYPING" | "STOPPED_TYPING" | "RECORDING" | "CHAT_CLOSED";
|
|
281
|
+
companyId: string;
|
|
282
|
+
conversationId: string;
|
|
283
|
+
/** Human-readable presence type. */
|
|
284
|
+
type: "typing" | "stopped" | "recording" | "chat_closed";
|
|
285
|
+
}
|
|
286
|
+
/** Delivered when the company credit balance is low. */
|
|
287
|
+
export interface BalanceLowEvent {
|
|
288
|
+
event: "BALANCE_LOW";
|
|
289
|
+
companyId: string;
|
|
290
|
+
balanceCents: number;
|
|
291
|
+
}
|
|
292
|
+
/** Standard ixblix error payload. */
|
|
293
|
+
export interface IxblixErrorBody {
|
|
294
|
+
error: string;
|
|
295
|
+
code: string;
|
|
296
|
+
errors?: Array<{
|
|
297
|
+
path: string;
|
|
298
|
+
message: string;
|
|
299
|
+
}>;
|
|
300
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared types for the ixblix SDK.
|
|
3
|
+
*
|
|
4
|
+
* These types mirror the ixblix public REST API. They are intentionally
|
|
5
|
+
* self-contained (no dependency on any private package) so the SDK can be
|
|
6
|
+
* published and consumed by any desk/CRM integration.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { WebhookEvent } from "./types.js";
|
|
2
|
+
/** Header carrying the HMAC-SHA256 signature of the raw body. */
|
|
3
|
+
export declare const WEBHOOK_SIGNATURE_HEADER = "X-Ixblix-Signature";
|
|
4
|
+
/** Header carrying the event id (for idempotent receivers). */
|
|
5
|
+
export declare const WEBHOOK_ID_HEADER = "X-Ixblix-Event-Id";
|
|
6
|
+
/** Header carrying the event type. */
|
|
7
|
+
export declare const WEBHOOK_EVENT_HEADER = "X-Ixblix-Event";
|
|
8
|
+
/** Result of parsing a webhook payload. */
|
|
9
|
+
export interface ParsedWebhook<T extends WebhookEvent = WebhookEvent> {
|
|
10
|
+
/** The parsed, validated event. */
|
|
11
|
+
event: T;
|
|
12
|
+
/** The raw payload as received. */
|
|
13
|
+
raw: unknown;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse and validate an ixblix webhook payload.
|
|
17
|
+
*
|
|
18
|
+
* @param body The raw request body (already JSON-parsed).
|
|
19
|
+
* @returns The typed event.
|
|
20
|
+
* @throws {Error} When the payload is not a recognized ixblix webhook event.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseWebhook(body: unknown): ParsedWebhook;
|
|
23
|
+
/**
|
|
24
|
+
* Verify an ixblix webhook request.
|
|
25
|
+
*
|
|
26
|
+
* Computes the HMAC-SHA256 signature of the raw body using the shared secret
|
|
27
|
+
* and compares it (in constant time) against the `X-Ixblix-Signature` header.
|
|
28
|
+
* Throws when the signature is missing or does not match.
|
|
29
|
+
*
|
|
30
|
+
* @param body The raw request body (already JSON-parsed).
|
|
31
|
+
* @param secret The company's webhook secret (from `whsec_...`).
|
|
32
|
+
* @param signature The signature from the `X-Ixblix-Signature` header.
|
|
33
|
+
* @returns The typed, validated event.
|
|
34
|
+
*/
|
|
35
|
+
export declare function verifyWebhook(body: unknown, secret: string, signature?: string): ParsedWebhook;
|
package/dist/webhooks.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers for receiving ixblix webhooks.
|
|
3
|
+
*
|
|
4
|
+
* ixblix signs webhook payloads with HMAC-SHA256 using the company's webhook
|
|
5
|
+
* secret. The signature is sent in the `X-Ixblix-Signature` header. Integrations
|
|
6
|
+
* should call {@link verifyWebhook} with the raw body and the secret to
|
|
7
|
+
* authenticate the request before acting on it.
|
|
8
|
+
*/
|
|
9
|
+
import { createHmac, timingSafeEqual } from "node:crypto";
|
|
10
|
+
/** Header carrying the HMAC-SHA256 signature of the raw body. */
|
|
11
|
+
export const WEBHOOK_SIGNATURE_HEADER = "X-Ixblix-Signature";
|
|
12
|
+
/** Header carrying the event id (for idempotent receivers). */
|
|
13
|
+
export const WEBHOOK_ID_HEADER = "X-Ixblix-Event-Id";
|
|
14
|
+
/** Header carrying the event type. */
|
|
15
|
+
export const WEBHOOK_EVENT_HEADER = "X-Ixblix-Event";
|
|
16
|
+
/**
|
|
17
|
+
* Parse and validate an ixblix webhook payload.
|
|
18
|
+
*
|
|
19
|
+
* @param body The raw request body (already JSON-parsed).
|
|
20
|
+
* @returns The typed event.
|
|
21
|
+
* @throws {Error} When the payload is not a recognized ixblix webhook event.
|
|
22
|
+
*/
|
|
23
|
+
export function parseWebhook(body) {
|
|
24
|
+
if (typeof body !== "object" || body === null) {
|
|
25
|
+
throw new Error("ixblix webhook payload must be a JSON object");
|
|
26
|
+
}
|
|
27
|
+
const record = body;
|
|
28
|
+
const event = record.event;
|
|
29
|
+
if (typeof event !== "string") {
|
|
30
|
+
throw new Error("ixblix webhook payload is missing the 'event' field");
|
|
31
|
+
}
|
|
32
|
+
switch (event) {
|
|
33
|
+
case "COMPANY_ACTIVATED":
|
|
34
|
+
case "MESSAGE_RECEIVED":
|
|
35
|
+
case "MESSAGE_READ":
|
|
36
|
+
case "CUSTOMER_JOINED":
|
|
37
|
+
case "CONVERSATION_CLOSED":
|
|
38
|
+
case "TYPING":
|
|
39
|
+
case "STOPPED_TYPING":
|
|
40
|
+
case "RECORDING":
|
|
41
|
+
case "CHAT_CLOSED":
|
|
42
|
+
case "BALANCE_LOW":
|
|
43
|
+
return { event: body, raw: body };
|
|
44
|
+
default:
|
|
45
|
+
throw new Error(`Unknown ixblix webhook event: ${event}`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Verify an ixblix webhook request.
|
|
50
|
+
*
|
|
51
|
+
* Computes the HMAC-SHA256 signature of the raw body using the shared secret
|
|
52
|
+
* and compares it (in constant time) against the `X-Ixblix-Signature` header.
|
|
53
|
+
* Throws when the signature is missing or does not match.
|
|
54
|
+
*
|
|
55
|
+
* @param body The raw request body (already JSON-parsed).
|
|
56
|
+
* @param secret The company's webhook secret (from `whsec_...`).
|
|
57
|
+
* @param signature The signature from the `X-Ixblix-Signature` header.
|
|
58
|
+
* @returns The typed, validated event.
|
|
59
|
+
*/
|
|
60
|
+
export function verifyWebhook(body, secret, signature) {
|
|
61
|
+
if (!signature) {
|
|
62
|
+
throw new Error("ixblix webhook is missing the X-Ixblix-Signature header; cannot verify authenticity");
|
|
63
|
+
}
|
|
64
|
+
if (!secret) {
|
|
65
|
+
throw new Error("A webhook secret is required to verify ixblix webhook signatures");
|
|
66
|
+
}
|
|
67
|
+
const expected = createHmac("sha256", secret)
|
|
68
|
+
.update(JSON.stringify(body))
|
|
69
|
+
.digest("hex");
|
|
70
|
+
const expectedBuf = Buffer.from(expected, "hex");
|
|
71
|
+
const receivedBuf = Buffer.from(signature, "hex");
|
|
72
|
+
if (expectedBuf.length !== receivedBuf.length ||
|
|
73
|
+
!timingSafeEqual(expectedBuf, receivedBuf)) {
|
|
74
|
+
throw new Error("ixblix webhook signature verification failed");
|
|
75
|
+
}
|
|
76
|
+
return parseWebhook(body);
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"webhooks.js","sourceRoot":"","sources":["../src/webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG1D,iEAAiE;AACjE,MAAM,CAAC,MAAM,wBAAwB,GAAG,oBAAoB,CAAC;AAC7D,+DAA+D;AAC/D,MAAM,CAAC,MAAM,iBAAiB,GAAG,mBAAmB,CAAC;AACrD,sCAAsC;AACtC,MAAM,CAAC,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAUrD;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,IAAa;IACxC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IACD,MAAM,MAAM,GAAG,IAA+B,CAAC;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IAC3B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,qDAAqD,CAAC,CAAC;IACzE,CAAC;IAED,QAAQ,KAAK,EAAE,CAAC;QACd,KAAK,mBAAmB,CAAC;QACzB,KAAK,kBAAkB,CAAC;QACxB,KAAK,cAAc,CAAC;QACpB,KAAK,iBAAiB,CAAC;QACvB,KAAK,qBAAqB,CAAC;QAC3B,KAAK,QAAQ,CAAC;QACd,KAAK,gBAAgB,CAAC;QACtB,KAAK,WAAW,CAAC;QACjB,KAAK,aAAa,CAAC;QACnB,KAAK,aAAa;YAChB,OAAO,EAAE,KAAK,EAAE,IAAoB,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;QACpD;YACE,MAAM,IAAI,KAAK,CAAC,iCAAiC,KAAK,EAAE,CAAC,CAAC;IAC9D,CAAC;AACH,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,IAAa,EACb,MAAc,EACd,SAAkB;IAElB,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,qFAAqF,CACtF,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CACb,kEAAkE,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC;SAC1C,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;SAC5B,MAAM,CAAC,KAAK,CAAC,CAAC;IACjB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACjD,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAClD,IACE,WAAW,CAAC,MAAM,KAAK,WAAW,CAAC,MAAM;QACzC,CAAC,eAAe,CAAC,WAAW,EAAE,WAAW,CAAC,EAC1C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,OAAO,YAAY,CAAC,IAAI,CAAC,CAAC;AAC5B,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ixblix/sdk-js",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Official ixblix SDK for desk/CRM integrations. Create overflow conversations, exchange end-to-end encrypted messages and media, and manage company onboarding.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/ixblix/ixblix-sdk-js.git"
|
|
10
|
+
},
|
|
11
|
+
"main": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18.0.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc -p tsconfig.build.json",
|
|
29
|
+
"typecheck": "tsc --noEmit",
|
|
30
|
+
"lint": "eslint src --ext .ts",
|
|
31
|
+
"lint:fix": "eslint src --ext .ts --fix",
|
|
32
|
+
"test": "vitest run",
|
|
33
|
+
"test:e2e": "tsx src/e2e.ts",
|
|
34
|
+
"prepublishOnly": "npm run build"
|
|
35
|
+
},
|
|
36
|
+
"keywords": [
|
|
37
|
+
"ixblix",
|
|
38
|
+
"messaging",
|
|
39
|
+
"overflow",
|
|
40
|
+
"desk",
|
|
41
|
+
"crm",
|
|
42
|
+
"e2ee",
|
|
43
|
+
"encryption"
|
|
44
|
+
],
|
|
45
|
+
"devDependencies": {
|
|
46
|
+
"@types/node": "^20.0.0",
|
|
47
|
+
"@typescript-eslint/eslint-plugin": "^6.0.0",
|
|
48
|
+
"@typescript-eslint/parser": "^6.0.0",
|
|
49
|
+
"eslint": "^8.0.0",
|
|
50
|
+
"tsx": "^4.0.0",
|
|
51
|
+
"typescript": "^5.3.0",
|
|
52
|
+
"vitest": "^1.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|