@channlize/core 0.1.0 → 0.4.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/CHANGELOG.md +39 -1
- package/README.md +105 -16
- package/dist/index.d.mts +221 -29
- package/dist/index.d.ts +221 -29
- package/dist/index.js +276 -68
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +266 -67
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# @channlize/core
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 5663cd2: Make `@channlize/core` the single source for what the packages share.
|
|
8
|
+
|
|
9
|
+
- core exports `DEFAULT_BASE_URL`, `DEFAULT_TIMEOUT`, `EVENT_SEVERITIES`, `EVENT_KEY_PATTERN`, `isValidEventKey`, `keyKind` (widget vs. server key), `readChannlizeEnv` (the `CHANNLIZE_*` variables) and `parseApiError` (the API's error shape). `createNotifier`, the client and `@channlize/mcp` use them instead of their own copies.
|
|
10
|
+
- `ChannlizeError` gains `requestId` and `details` (the API's error body, e.g. `limit`, `used` and `resetAt` on a plan-limit 429). When a legacy route puts its human-readable text in `error`, it becomes the message instead of `HTTP <status>`.
|
|
11
|
+
- The chat types document where the API differs from them (ISO string timestamps, session summaries without `messages`).
|
|
12
|
+
- `@channlize/react` and `@channlize/mcp` re-export the error classes as values, so `instanceof` works without importing core.
|
|
13
|
+
- mcp tool errors no longer end with a doubled period when a core error message ends with one.
|
|
14
|
+
|
|
15
|
+
- Release every `@channlize/*` package under one shared version. From 0.4.0 on, core, react, mcp and skills always publish together at the same version, so matching versions work together.
|
|
16
|
+
|
|
17
|
+
## 0.2.2
|
|
18
|
+
|
|
19
|
+
Not published on its own; these changes ship in 0.4.0.
|
|
20
|
+
|
|
21
|
+
### Patch Changes
|
|
22
|
+
|
|
23
|
+
- 097ad44: Log tracking no longer throws when the API refuses an event with a 429: `trackEvent` and `trackServerEvent` resolve with `{ success: false, id: '', dropped: 'plan_limit' | 'rate_limit' }` and log one console warning, so reaching the plan's log tracking limit (`PLAN_LIMIT_REACHED`) or the rate limit never breaks the calling app. `RateLimitError.code` is now `PLAN_LIMIT_REACHED` for plan-limit refusals (for example from `notify()`), and `TrackEventResult` is exported.
|
|
24
|
+
|
|
25
|
+
## 0.2.1
|
|
26
|
+
|
|
27
|
+
### Patch Changes
|
|
28
|
+
|
|
29
|
+
- 69f414f: `submitContactForm` now sends `customFields` (they were silently dropped), so a contact form's topic, company and custom fields reach the API and the Slack post.
|
|
30
|
+
|
|
31
|
+
## 0.2.0
|
|
32
|
+
|
|
33
|
+
### Minor Changes
|
|
34
|
+
|
|
35
|
+
- c113208: Add Events: post a Slack message from your server when something happens.
|
|
36
|
+
|
|
37
|
+
- `@channlize/core`: `client.notify(event, data?, { idempotencyKey?, channel? })` and a standalone `createNotifier()` that reads `CHANNLIZE_SERVER_API_KEY` / `CHANNLIZE_API_KEY` and `CHANNLIZE_PROJECT_ID`. Both call `POST /v1/notify` with the server API key (write scope). Event keys and data can be typed with `createNotifier<AppEvents>()` or by augmenting `ChannlizeEvents`. `trackEvent` / `trackServerEvent` are unchanged and now documented as log tracking. Fix: an explicit `baseUrl: undefined` or `timeout: undefined` no longer overrides the defaults.
|
|
38
|
+
- `@channlize/mcp`: new `notify_event` tool, enabled with `--server-api-key` / `CHANNLIZE_SERVER_API_KEY`.
|
|
39
|
+
- `@channlize/react`: docs only. `useChannlizeAnalytics().track` is documented as log tracking.
|
|
40
|
+
|
|
3
41
|
## 0.1.0
|
|
4
42
|
|
|
5
43
|
### Minor Changes
|
|
@@ -7,7 +45,7 @@
|
|
|
7
45
|
- 9ddf630: Errors thrown by the client now carry the API's human-readable `message`
|
|
8
46
|
(field messages joined for validation failures) instead of the error code,
|
|
9
47
|
and `ChannlizeError.code` is set from the API's `error` code.
|
|
10
|
-
|
|
48
|
+
|
|
11
49
|
`CreateContactResponse` gains the fields the API actually returns:
|
|
12
50
|
`success`, `conversationId` and `message`. The old `id`, `status` and
|
|
13
51
|
`slackThreadUrl` fields were never returned and are deprecated. The MCP
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @channlize/core
|
|
2
2
|
|
|
3
|
-
Core TypeScript SDK for the Channlize platform. Provides API client functionality for submitting contact forms
|
|
3
|
+
Core TypeScript SDK for the Channlize platform. Provides API client functionality for submitting contact forms, managing chat sessions, posting Events to Slack from your server, and log tracking.
|
|
4
4
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
@@ -8,6 +8,15 @@ Core TypeScript SDK for the Channlize platform. Provides API client functionalit
|
|
|
8
8
|
npm install @channlize/core
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
+
## Quick start: notify Slack from your server (Events)
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { createNotifier } from '@channlize/core';
|
|
15
|
+
|
|
16
|
+
const notify = createNotifier(); // reads CHANNLIZE_API_KEY (server key) + CHANNLIZE_PROJECT_ID
|
|
17
|
+
await notify('user.subscribed', { username: user.name, plan: 'Pro' });
|
|
18
|
+
```
|
|
19
|
+
|
|
11
20
|
## Usage
|
|
12
21
|
|
|
13
22
|
### Basic Setup
|
|
@@ -16,7 +25,7 @@ npm install @channlize/core
|
|
|
16
25
|
import { ChannlizeClient } from '@channlize/core';
|
|
17
26
|
|
|
18
27
|
const client = new ChannlizeClient({
|
|
19
|
-
apiKey: '
|
|
28
|
+
apiKey: 'wk_…', // public widget key
|
|
20
29
|
projectId: 'your-project-id',
|
|
21
30
|
baseUrl: 'https://api.channlize.com', // optional
|
|
22
31
|
timeout: 10000, // optional, default 10s
|
|
@@ -38,18 +47,15 @@ const response = await client.submitContactForm({
|
|
|
38
47
|
},
|
|
39
48
|
});
|
|
40
49
|
|
|
41
|
-
console.log('
|
|
42
|
-
console.log('Slack thread:', response.slackThreadUrl);
|
|
50
|
+
console.log('Conversation:', response.conversationId);
|
|
43
51
|
```
|
|
44
52
|
|
|
45
53
|
### Chat Sessions
|
|
46
54
|
|
|
47
55
|
```typescript
|
|
48
56
|
// Create a new chat session
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
pageUrl: window.location.href,
|
|
52
|
-
});
|
|
57
|
+
// Metadata is optional; pageUrl and userAgent are added in the browser.
|
|
58
|
+
const sessionResponse = await client.createChatSession({ plan: 'pro' });
|
|
53
59
|
|
|
54
60
|
const session = sessionResponse.session;
|
|
55
61
|
|
|
@@ -69,13 +75,81 @@ const messages = await client.getChatMessages(session.id, 50, 0);
|
|
|
69
75
|
// Close session
|
|
70
76
|
await client.closeChatSession(session.id);
|
|
71
77
|
|
|
72
|
-
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Events: notify Slack from your server
|
|
81
|
+
|
|
82
|
+
Post a Slack message when something happens in your app. Each event key (`user.subscribed`, `invoice.paid`…) has its own Slack channel and message template, configured under **Events** in the dashboard; `data` fills the template's `{{field}}` placeholders (e.g. `:tada: *{{username}}* subscribed to {{plan}}`).
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { createNotifier } from '@channlize/core';
|
|
86
|
+
|
|
87
|
+
// Server key from CHANNLIZE_SERVER_API_KEY or CHANNLIZE_API_KEY (ch_live_…, write scope),
|
|
88
|
+
// project from CHANNLIZE_PROJECT_ID, API from CHANNLIZE_BASE_URL (optional).
|
|
89
|
+
// Or pass them: createNotifier({ serverApiKey, projectId, baseUrl }).
|
|
90
|
+
const notify = createNotifier();
|
|
91
|
+
|
|
92
|
+
const res = await notify('user.subscribed', { username: 'ada', plan: 'Pro' });
|
|
93
|
+
// res.status: 'queued' (posting to Slack) or 'skipped' (see res.reason)
|
|
94
|
+
|
|
95
|
+
// Retry-safe: the same idempotency key is only posted once.
|
|
96
|
+
await notify('invoice.paid', { amount: '$49' }, { idempotencyKey: invoice.id });
|
|
97
|
+
|
|
98
|
+
// Post one call to another channel (Slack channel ID).
|
|
99
|
+
await notify('deploy.finished', { version: '1.4.2' }, { channel: 'C0123456' });
|
|
100
|
+
|
|
101
|
+
// Or on a client configured with serverApiKey + projectId:
|
|
102
|
+
await client.notify('user.subscribed', { username: 'ada', plan: 'Pro' });
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
- **Server only.** It needs a server API key; never ship it to the browser. Calling with the public widget key (`wk_…`) throws a `ValidationError`.
|
|
106
|
+
- **Ship code before configuring.** An event key the dashboard doesn't know yet is saved as a disabled draft and answered `status: 'skipped'` (no exception), ready to configure and enable.
|
|
107
|
+
- The Channlize bot must be in the Slack channel (`/invite @Channlize`); otherwise the delivery fails, and the dashboard shows why under **Events → Recent deliveries**.
|
|
108
|
+
|
|
109
|
+
Typed event names and data (optional):
|
|
110
|
+
|
|
111
|
+
```typescript
|
|
112
|
+
type AppEvents = {
|
|
113
|
+
'user.subscribed': { username: string; plan: string };
|
|
114
|
+
'invoice.paid': { amount: string };
|
|
115
|
+
};
|
|
116
|
+
const notify = createNotifier<AppEvents>();
|
|
117
|
+
await notify('user.subscribed', { username: 'ada', plan: 'Pro' }); // autocompleted + type-checked
|
|
118
|
+
|
|
119
|
+
// Or app-wide, for client.notify too:
|
|
120
|
+
declare module '@channlize/core' {
|
|
121
|
+
interface ChannlizeEvents {
|
|
122
|
+
'user.subscribed': { username: string; plan: string };
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Without the SDK:
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
curl -X POST https://api.channlize.com/api/v1/notify \
|
|
131
|
+
-H "Authorization: Bearer $CHANNLIZE_API_KEY" \
|
|
132
|
+
-H "Content-Type: application/json" \
|
|
133
|
+
-H "Idempotency-Key: signup-42" \
|
|
134
|
+
-d '{"projectId":"<project id>","event":"user.subscribed","data":{"username":"ada","plan":"Pro"}}'
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
### Log tracking
|
|
138
|
+
|
|
139
|
+
Record logs that show up under **Log tracking** in the dashboard (Settings → Log tracking can alert Slack on matching logs).
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// Browser (widget key)
|
|
73
143
|
await client.trackEvent('page.viewed', { properties: { path: '/pricing' } });
|
|
74
144
|
|
|
75
|
-
//
|
|
145
|
+
// Server (set serverApiKey on the client)
|
|
76
146
|
await client.trackServerEvent('webhook.received', { severity: 'warning' });
|
|
77
147
|
```
|
|
78
148
|
|
|
149
|
+
Log tracking never breaks your app over limits: when the API answers `429` (the rate limit, or your plan's log tracking limit for the billing period, `PLAN_LIMIT_REACHED`), both calls resolve with `{ success: false, id: '', dropped: 'plan_limit' | 'rate_limit' }` instead of throwing, and the client logs one console warning. Other errors (bad input, network) still throw.
|
|
150
|
+
|
|
151
|
+
`notify()` is different: a `429` there throws a `RateLimitError` whose `code` is `PLAN_LIMIT_REACHED` when the plan's Events limit is reached, so your server can see that the Slack message was not sent.
|
|
152
|
+
|
|
79
153
|
### Error Handling
|
|
80
154
|
|
|
81
155
|
```typescript
|
|
@@ -111,8 +185,9 @@ try {
|
|
|
111
185
|
|
|
112
186
|
```typescript
|
|
113
187
|
interface ChannlizeConfig {
|
|
114
|
-
apiKey: string; // Required: Your
|
|
188
|
+
apiKey: string; // Required: Your widget key
|
|
115
189
|
projectId: string; // Required: Your project ID
|
|
190
|
+
serverApiKey?: string; // Server-side only: server API key, for notify / trackServerEvent
|
|
116
191
|
baseUrl?: string; // Optional: API base URL
|
|
117
192
|
timeout?: number; // Optional: Request timeout in ms
|
|
118
193
|
}
|
|
@@ -126,10 +201,17 @@ interface ChannlizeConfig {
|
|
|
126
201
|
- `getChatSession(sessionId: string): Promise<ChatSession>`
|
|
127
202
|
- `getChatMessages(sessionId: string, limit?: number, offset?: number): Promise<ChatMessage[]>`
|
|
128
203
|
- `closeChatSession(sessionId: string): Promise<ChatSession>`
|
|
204
|
+
- `notify(event: string, data?: Record<string, unknown>, options?: NotifyOptions): Promise<NotifyResponse>` — Events (server)
|
|
205
|
+
- `trackEvent(name: string, options?: TrackEventOptions): Promise<TrackEventResult>` — log tracking (browser); a 429 resolves with `dropped`
|
|
206
|
+
- `trackServerEvent(name: string, options?): Promise<TrackEventResult>` — log tracking (server); a 429 resolves with `dropped`
|
|
207
|
+
|
|
208
|
+
### createNotifier
|
|
209
|
+
|
|
210
|
+
`createNotifier<TEvents>(config?: NotifierConfig): (event, data?, options?) => Promise<NotifyResponse>` — standalone server-side Events sender (see above).
|
|
129
211
|
|
|
130
212
|
### Types
|
|
131
213
|
|
|
132
|
-
All TypeScript types are exported from the package:
|
|
214
|
+
All TypeScript types are exported from the package. The error classes (`ChannlizeError`, `ValidationError`, `AuthenticationError`, `RateLimitError`) are values, so import them without `type` for `instanceof` checks (see Error Handling):
|
|
133
215
|
|
|
134
216
|
```typescript
|
|
135
217
|
import type {
|
|
@@ -141,13 +223,20 @@ import type {
|
|
|
141
223
|
CreateContactResponse,
|
|
142
224
|
CreateChatSessionResponse,
|
|
143
225
|
SendMessageResponse,
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
AuthenticationError,
|
|
147
|
-
RateLimitError,
|
|
226
|
+
NotifyResponse,
|
|
227
|
+
TrackEventResult,
|
|
148
228
|
} from '@channlize/core';
|
|
149
229
|
```
|
|
150
230
|
|
|
231
|
+
## Documentation
|
|
232
|
+
|
|
233
|
+
- Guide: https://channlize.com/docs/core
|
|
234
|
+
- All docs: https://channlize.com/docs (quick start, API keys, troubleshooting)
|
|
235
|
+
|
|
236
|
+
## Changelog
|
|
237
|
+
|
|
238
|
+
[CHANGELOG.md](./CHANGELOG.md) lists every release of `@channlize/core`. Product updates: https://channlize.com/docs/changelog
|
|
239
|
+
|
|
151
240
|
## License
|
|
152
241
|
|
|
153
242
|
MIT
|
package/dist/index.d.mts
CHANGED
|
@@ -1,8 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helpers shared by `@channlize/core`, `@channlize/react` and
|
|
3
|
+
* `@channlize/mcp`: defaults, key detection, environment variables, event
|
|
4
|
+
* keys and the API's error shape. Core is the single source for these.
|
|
5
|
+
*/
|
|
6
|
+
/** Default API base URL. */
|
|
7
|
+
declare const DEFAULT_BASE_URL = "https://api.channlize.com";
|
|
8
|
+
/** Default request timeout, in milliseconds. */
|
|
9
|
+
declare const DEFAULT_TIMEOUT = 10000;
|
|
10
|
+
/** Log tracking severities, lowest first. */
|
|
11
|
+
declare const EVENT_SEVERITIES: readonly ["info", "warning", "error"];
|
|
12
|
+
/**
|
|
13
|
+
* Valid Events key (same rule as the API): lowercase letters, digits,
|
|
14
|
+
* dots, underscores and dashes, e.g. `user.subscribed`. At most 100
|
|
15
|
+
* characters.
|
|
16
|
+
*/
|
|
17
|
+
declare const EVENT_KEY_PATTERN: RegExp;
|
|
18
|
+
/** Whether `event` is a valid Events key for `notify`. */
|
|
19
|
+
declare function isValidEventKey(event: unknown): event is string;
|
|
20
|
+
type KeyKind = 'widget' | 'server';
|
|
21
|
+
/**
|
|
22
|
+
* `wk_…` is the public widget key (browser: contact form, chat, browser
|
|
23
|
+
* log tracking); anything else is a server API key (`ch_live_…`).
|
|
24
|
+
*/
|
|
25
|
+
declare function keyKind(key: string): KeyKind;
|
|
26
|
+
/** The `CHANNLIZE_*` environment variables, trimmed (empty → undefined). */
|
|
27
|
+
interface ChannlizeEnv {
|
|
28
|
+
/** `CHANNLIZE_SERVER_API_KEY` */
|
|
29
|
+
serverApiKey?: string;
|
|
30
|
+
/** `CHANNLIZE_WIDGET_KEY` */
|
|
31
|
+
widgetKey?: string;
|
|
32
|
+
/** `CHANNLIZE_API_KEY` (either kind of key) */
|
|
33
|
+
apiKey?: string;
|
|
34
|
+
/** `CHANNLIZE_PROJECT_ID` */
|
|
35
|
+
projectId?: string;
|
|
36
|
+
/** `CHANNLIZE_BASE_URL` */
|
|
37
|
+
baseUrl?: string;
|
|
38
|
+
/** `CHANNLIZE_TIMEOUT` (milliseconds, unparsed) */
|
|
39
|
+
timeout?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Reads the `CHANNLIZE_*` environment variables. Safe in browsers and edge
|
|
43
|
+
* runtimes without `process` (everything is undefined there).
|
|
44
|
+
*/
|
|
45
|
+
declare function readChannlizeEnv(env?: Record<string, string | undefined> | undefined): ChannlizeEnv;
|
|
46
|
+
/** A failed API response, parsed from its JSON body. */
|
|
47
|
+
interface ApiErrorInfo {
|
|
48
|
+
status: number;
|
|
49
|
+
/** Human-readable text (field messages joined with `, `). */
|
|
50
|
+
message: string;
|
|
51
|
+
/** Machine-readable code: the body's `code`, else its `error` (e.g. `NOT_FOUND`). */
|
|
52
|
+
code?: string;
|
|
53
|
+
/** `requestId` from the body, to quote to support. */
|
|
54
|
+
requestId?: string;
|
|
55
|
+
/** The parsed body (e.g. `limit`, `used`, `resetAt` on a plan-limit 429). */
|
|
56
|
+
body: Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Parses the API's error shape (`api/lib/api/error.ts`):
|
|
60
|
+
* `{ statusCode, error: "NOT_FOUND", message: string | string[], requestId? }`.
|
|
61
|
+
* A few legacy routes put the human text in `error`.
|
|
62
|
+
*/
|
|
63
|
+
declare function parseApiError(status: number, body: unknown, statusText?: string): ApiErrorInfo;
|
|
64
|
+
|
|
1
65
|
/**
|
|
2
66
|
* Core types for Channlize SDK
|
|
3
67
|
*/
|
|
4
|
-
|
|
5
|
-
|
|
68
|
+
|
|
69
|
+
/** Severity for log tracking (`trackEvent` / `trackServerEvent`); Slack alerts use project settings. */
|
|
70
|
+
type EventSeverity = (typeof EVENT_SEVERITIES)[number];
|
|
71
|
+
/** Options for log tracking (`trackEvent` / `trackServerEvent`). */
|
|
6
72
|
interface TrackEventOptions {
|
|
7
73
|
properties?: Record<string, unknown>;
|
|
8
74
|
severity?: EventSeverity;
|
|
@@ -11,20 +77,78 @@ interface TrackEventOptions {
|
|
|
11
77
|
userAgent?: string;
|
|
12
78
|
}
|
|
13
79
|
interface ChannlizeConfig {
|
|
14
|
-
/** Widget key used for public SDK endpoints (contact form, chat, browser
|
|
80
|
+
/** Widget key used for public SDK endpoints (contact form, chat, browser log tracking) */
|
|
15
81
|
apiKey: string;
|
|
16
82
|
/** Base URL for the Channlize API */
|
|
17
83
|
baseUrl?: string;
|
|
18
|
-
/** Project ID (required for server-side `trackServerEvent`) */
|
|
84
|
+
/** Project ID (required for server-side `trackServerEvent` and `notify`) */
|
|
19
85
|
projectId: string;
|
|
20
86
|
/** Request timeout in milliseconds */
|
|
21
87
|
timeout?: number;
|
|
22
88
|
/**
|
|
23
|
-
* Organization API key for
|
|
24
|
-
*
|
|
89
|
+
* Organization (server) API key, `ch_live_…`, for `trackServerEvent`
|
|
90
|
+
* (`POST /v1/events`) and `notify` (`POST /v1/notify`, needs the `write`
|
|
91
|
+
* scope). Do not expose in browser bundles.
|
|
25
92
|
*/
|
|
26
93
|
serverApiKey?: string;
|
|
27
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Events (notify Slack from code). Augment this interface to type event
|
|
97
|
+
* keys and their data across your app:
|
|
98
|
+
*
|
|
99
|
+
* ```ts
|
|
100
|
+
* declare module '@channlize/core' {
|
|
101
|
+
* interface ChannlizeEvents {
|
|
102
|
+
* 'user.subscribed': { username: string; plan: string };
|
|
103
|
+
* }
|
|
104
|
+
* }
|
|
105
|
+
* ```
|
|
106
|
+
*
|
|
107
|
+
* Or pass a map as a type argument: `createNotifier<AppEvents>()`.
|
|
108
|
+
*/
|
|
109
|
+
interface ChannlizeEvents {
|
|
110
|
+
}
|
|
111
|
+
/** A declared event key (autocompleted) or any other key. */
|
|
112
|
+
type NotifyEventName<TEvents extends object = ChannlizeEvents> = (keyof TEvents & string) | (string & {});
|
|
113
|
+
/** The declared data for a key, or any object for undeclared keys. */
|
|
114
|
+
type NotifyEventData<TEvents extends object = ChannlizeEvents, K = string> = K extends keyof TEvents ? TEvents[K] : Record<string, unknown>;
|
|
115
|
+
interface NotifyOptions {
|
|
116
|
+
/**
|
|
117
|
+
* Retry-safe sends: a key already used on the project returns the first
|
|
118
|
+
* delivery (`duplicate: true`) and posts nothing. Sent as `Idempotency-Key`.
|
|
119
|
+
*/
|
|
120
|
+
idempotencyKey?: string;
|
|
121
|
+
/** Slack channel ID to post to instead of the event's channel, for this call. */
|
|
122
|
+
channel?: string;
|
|
123
|
+
}
|
|
124
|
+
interface NotifyResponse {
|
|
125
|
+
success: boolean;
|
|
126
|
+
/** Delivery ID (see Events → Recent deliveries in the dashboard). */
|
|
127
|
+
id: string;
|
|
128
|
+
event: string;
|
|
129
|
+
/**
|
|
130
|
+
* `queued`: will be posted to Slack. `skipped`: not posted (see `reason`):
|
|
131
|
+
* the event is disabled, is new (saved as a draft to configure), or there
|
|
132
|
+
* is no Slack workspace / channel. With `duplicate`, the first call's status.
|
|
133
|
+
*/
|
|
134
|
+
status: 'queued' | 'skipped' | 'sent' | 'failed';
|
|
135
|
+
reason?: string;
|
|
136
|
+
duplicate?: boolean;
|
|
137
|
+
}
|
|
138
|
+
/** `createNotifier` options; each falls back to an environment variable. */
|
|
139
|
+
interface NotifierConfig {
|
|
140
|
+
/**
|
|
141
|
+
* Server API key (`ch_live_…`, write scope). Default:
|
|
142
|
+
* `CHANNLIZE_SERVER_API_KEY`, else `CHANNLIZE_API_KEY`.
|
|
143
|
+
*/
|
|
144
|
+
serverApiKey?: string;
|
|
145
|
+
/** Project ID. Default: `CHANNLIZE_PROJECT_ID`. */
|
|
146
|
+
projectId?: string;
|
|
147
|
+
/** API base URL. Default: `CHANNLIZE_BASE_URL`, else `https://api.channlize.com`. */
|
|
148
|
+
baseUrl?: string;
|
|
149
|
+
/** Request timeout in ms (default 10000). */
|
|
150
|
+
timeout?: number;
|
|
151
|
+
}
|
|
28
152
|
interface ContactFormData {
|
|
29
153
|
/** Contact's name */
|
|
30
154
|
name: string;
|
|
@@ -46,11 +170,15 @@ interface ChatMessage {
|
|
|
46
170
|
id: string;
|
|
47
171
|
/** Message content */
|
|
48
172
|
content: string;
|
|
49
|
-
/**
|
|
173
|
+
/**
|
|
174
|
+
* Message timestamp. The API sends an ISO 8601 string, which
|
|
175
|
+
* `ChannlizeClient` passes through as is; `@channlize/react` converts it
|
|
176
|
+
* to a `Date`. Wrap it in `new Date(...)` before using `Date` methods.
|
|
177
|
+
*/
|
|
50
178
|
timestamp: Date;
|
|
51
179
|
/** Message author (user or agent) */
|
|
52
180
|
author: 'user' | 'agent';
|
|
53
|
-
/** Author metadata */
|
|
181
|
+
/** Author metadata (`name` / `email` can be `null` in message history) */
|
|
54
182
|
authorData?: {
|
|
55
183
|
name?: string;
|
|
56
184
|
email?: string;
|
|
@@ -74,15 +202,23 @@ interface FileAttachment {
|
|
|
74
202
|
interface ChatSession {
|
|
75
203
|
/** Session ID */
|
|
76
204
|
id: string;
|
|
77
|
-
/**
|
|
205
|
+
/**
|
|
206
|
+
* Session status. `createChatSession` answers `active`; `getChatSession`
|
|
207
|
+
* and `closeChatSession` answer the conversation's status (`open`,
|
|
208
|
+
* `pending`, `resolved` or `closed`).
|
|
209
|
+
*/
|
|
78
210
|
status: 'active' | 'closed' | 'waiting';
|
|
79
|
-
/**
|
|
211
|
+
/**
|
|
212
|
+
* Messages in the session. Only `createChatSession` returns it (empty);
|
|
213
|
+
* `getChatSession`, `closeChatSession` and `sendMessage` return a session
|
|
214
|
+
* summary without it. Load history with `getChatMessages`.
|
|
215
|
+
*/
|
|
80
216
|
messages: ChatMessage[];
|
|
81
217
|
/** Session metadata */
|
|
82
218
|
metadata?: Record<string, unknown>;
|
|
83
|
-
/** Created timestamp */
|
|
219
|
+
/** Created timestamp (an ISO 8601 string on the wire; not sent by `closeChatSession`) */
|
|
84
220
|
createdAt: Date;
|
|
85
|
-
/** Updated timestamp */
|
|
221
|
+
/** Updated timestamp (an ISO 8601 string on the wire) */
|
|
86
222
|
updatedAt: Date;
|
|
87
223
|
}
|
|
88
224
|
interface ApiResponse<T = unknown> {
|
|
@@ -119,7 +255,7 @@ interface CreateChatSessionResponse {
|
|
|
119
255
|
interface SendMessageResponse {
|
|
120
256
|
/** The sent message */
|
|
121
257
|
message: ChatMessage;
|
|
122
|
-
/**
|
|
258
|
+
/** The session (the API sends only `id` and `status`) */
|
|
123
259
|
session: ChatSession;
|
|
124
260
|
}
|
|
125
261
|
/**
|
|
@@ -128,6 +264,13 @@ interface SendMessageResponse {
|
|
|
128
264
|
declare class ChannlizeError extends Error {
|
|
129
265
|
statusCode?: number | undefined;
|
|
130
266
|
code?: string | undefined;
|
|
267
|
+
/** The API's `requestId` for a failed response, to quote to support. */
|
|
268
|
+
requestId?: string;
|
|
269
|
+
/**
|
|
270
|
+
* The API's JSON error body, e.g. `limit`, `used`, `resetAt` and
|
|
271
|
+
* `upgradeUrl` on a plan-limit 429. Undefined for network errors.
|
|
272
|
+
*/
|
|
273
|
+
details?: Record<string, unknown>;
|
|
131
274
|
constructor(message: string, statusCode?: number | undefined, code?: string | undefined);
|
|
132
275
|
}
|
|
133
276
|
declare class ValidationError extends ChannlizeError {
|
|
@@ -137,20 +280,39 @@ declare class ValidationError extends ChannlizeError {
|
|
|
137
280
|
declare class AuthenticationError extends ChannlizeError {
|
|
138
281
|
constructor(message?: string);
|
|
139
282
|
}
|
|
283
|
+
/**
|
|
284
|
+
* A 429. `code` is `PLAN_LIMIT_REACHED` when the organization is past its
|
|
285
|
+
* plan's limit for the billing period (the API's 110 % hard cap), else
|
|
286
|
+
* `RATE_LIMIT_ERROR`.
|
|
287
|
+
*/
|
|
140
288
|
declare class RateLimitError extends ChannlizeError {
|
|
141
|
-
constructor(message?: string);
|
|
289
|
+
constructor(message?: string, code?: string);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* What `trackEvent` / `trackServerEvent` resolve with. When the API refuses
|
|
293
|
+
* the event with a 429 (rate limit or plan limit), the call resolves with
|
|
294
|
+
* `success: false` and `dropped` instead of throwing: log tracking never
|
|
295
|
+
* breaks the app that calls it.
|
|
296
|
+
*/
|
|
297
|
+
interface TrackEventResult {
|
|
298
|
+
success: boolean;
|
|
299
|
+
id: string;
|
|
300
|
+
/** Set when the event was refused and not stored. */
|
|
301
|
+
dropped?: 'plan_limit' | 'rate_limit';
|
|
142
302
|
}
|
|
143
303
|
|
|
144
304
|
/**
|
|
145
305
|
* Channlize API Client
|
|
146
|
-
* Provides methods to interact with the Channlize platform
|
|
306
|
+
* Provides methods to interact with the Channlize platform.
|
|
307
|
+
*
|
|
308
|
+
* `TEvents` types `notify()` event keys and data (defaults to the
|
|
309
|
+
* augmentable `ChannlizeEvents` interface; any string key is accepted).
|
|
147
310
|
*/
|
|
148
|
-
declare class ChannlizeClient {
|
|
311
|
+
declare class ChannlizeClient<TEvents extends object = ChannlizeEvents> {
|
|
149
312
|
private readonly config;
|
|
150
313
|
constructor(config: ChannlizeConfig);
|
|
151
314
|
private validateConfig;
|
|
152
315
|
private makeRequest;
|
|
153
|
-
private handleErrorResponse;
|
|
154
316
|
/**
|
|
155
317
|
* Submit a contact form
|
|
156
318
|
*/
|
|
@@ -178,23 +340,53 @@ declare class ChannlizeClient {
|
|
|
178
340
|
*/
|
|
179
341
|
closeChatSession(sessionId: string): Promise<ChatSession>;
|
|
180
342
|
/**
|
|
181
|
-
*
|
|
343
|
+
* Log tracking: record a log line from the browser (widget key →
|
|
344
|
+
* `POST /public/events`). Shown under Log tracking in the dashboard.
|
|
182
345
|
*/
|
|
183
|
-
trackEvent(name: string, options?: TrackEventOptions): Promise<
|
|
184
|
-
|
|
185
|
-
id: string;
|
|
186
|
-
}>;
|
|
346
|
+
trackEvent(name: string, options?: TrackEventOptions): Promise<TrackEventResult>;
|
|
347
|
+
private sendBrowserEvent;
|
|
187
348
|
/**
|
|
188
|
-
*
|
|
349
|
+
* Log tracking from a trusted server, using the organization API key
|
|
350
|
+
* (`POST /v1/events`). Shown under Log tracking in the dashboard.
|
|
189
351
|
*/
|
|
190
352
|
trackServerEvent(name: string, options?: {
|
|
191
353
|
properties?: Record<string, unknown>;
|
|
192
354
|
severity?: EventSeverity;
|
|
193
|
-
}): Promise<
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
355
|
+
}): Promise<TrackEventResult>;
|
|
356
|
+
/**
|
|
357
|
+
* Log tracking must never break the caller: a 429 (rate limit, or the
|
|
358
|
+
* plan's limit for the billing period) resolves with `success: false`
|
|
359
|
+
* and `dropped` instead of throwing, with one console warning per client.
|
|
360
|
+
*/
|
|
361
|
+
private nonFatalTracking;
|
|
362
|
+
private warnedDropped;
|
|
363
|
+
private sendServerEvent;
|
|
364
|
+
/**
|
|
365
|
+
* Events: post a Slack message from your server when something happens
|
|
366
|
+
* (`POST /v1/notify`). The event key picks the channel and message
|
|
367
|
+
* template configured under Events in the dashboard; `data` fills the
|
|
368
|
+
* template's `{{field}}` placeholders. Needs `serverApiKey` (write scope)
|
|
369
|
+
* and `projectId` — never call it from browser code.
|
|
370
|
+
*
|
|
371
|
+
* An unknown key is saved as a disabled draft and answered with
|
|
372
|
+
* `status: 'skipped'`, so it never throws for a missing setup.
|
|
373
|
+
*/
|
|
374
|
+
notify<K extends NotifyEventName<TEvents>>(event: K, data?: NotifyEventData<TEvents, K>, options?: NotifyOptions): Promise<NotifyResponse>;
|
|
197
375
|
}
|
|
198
376
|
|
|
199
|
-
|
|
200
|
-
|
|
377
|
+
type Notifier<TEvents extends object = ChannlizeEvents> = <K extends NotifyEventName<TEvents>>(event: K, data?: NotifyEventData<TEvents, K>, options?: NotifyOptions) => Promise<NotifyResponse>;
|
|
378
|
+
/**
|
|
379
|
+
* Events: a standalone server-side `notify(event, data)` function. Reads
|
|
380
|
+
* the server key from `CHANNLIZE_SERVER_API_KEY` or `CHANNLIZE_API_KEY`, and
|
|
381
|
+
* `CHANNLIZE_PROJECT_ID`, unless given — when it is called, so creating it
|
|
382
|
+
* at module load never throws.
|
|
383
|
+
*
|
|
384
|
+
* ```ts
|
|
385
|
+
* const notify = createNotifier();
|
|
386
|
+
* await notify('user.subscribed', { username: 'ada', plan: 'Pro' });
|
|
387
|
+
* ```
|
|
388
|
+
*/
|
|
389
|
+
declare function createNotifier<TEvents extends object = ChannlizeEvents>(config?: NotifierConfig): Notifier<TEvents>;
|
|
390
|
+
|
|
391
|
+
export { AuthenticationError, ChannlizeClient, ChannlizeError, DEFAULT_BASE_URL, DEFAULT_TIMEOUT, EVENT_KEY_PATTERN, EVENT_SEVERITIES, RateLimitError, ValidationError, createNotifier, ChannlizeClient as default, isValidEventKey, keyKind, parseApiError, readChannlizeEnv };
|
|
392
|
+
export type { ApiErrorInfo, ApiResponse, ChannlizeConfig, ChannlizeEnv, ChannlizeEvents, ChatMessage, ChatSession, ContactFormData, CreateChatSessionResponse, CreateContactResponse, EventSeverity, FileAttachment, KeyKind, Notifier, NotifierConfig, NotifyEventData, NotifyEventName, NotifyOptions, NotifyResponse, SendMessageResponse, TrackEventOptions, TrackEventResult };
|