@emmanuel-nike/ark-notify-js 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +77 -4
- package/dist/index.cjs +59 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +57 -3
- package/dist/index.js.map +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.d.cts +3 -3
- package/dist/react/index.d.ts +3 -3
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.cjs +50 -2
- package/dist/server/index.cjs.map +1 -1
- package/dist/server/index.d.cts +3 -3
- package/dist/server/index.d.ts +3 -3
- package/dist/server/index.js +50 -2
- package/dist/server/index.js.map +1 -1
- package/dist/{server-stream-Cqe0hzxt.d.ts → server-stream-CxgR5Ym7.d.cts} +7 -1
- package/dist/{server-stream-BK0sRKrW.d.cts → server-stream-DNd6ENoz.d.ts} +7 -1
- package/dist/{types-Aj_RUX12.d.cts → types-BHemo22a.d.cts} +13 -1
- package/dist/{types-Aj_RUX12.d.ts → types-BHemo22a.d.ts} +13 -1
- package/dist/{utils-BhL2YmY0.d.ts → utils-BznZ_tYI.d.ts} +8 -2
- package/dist/{utils-CGTwTv3w.d.cts → utils-CCt9kuCJ.d.cts} +8 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
JavaScript SDK for [Ark Notify](https://github.com/ark-notify/ark-notify) — real-time pub/sub, presence, SSE streaming, and platform management.
|
|
4
4
|
|
|
5
|
-
- **Core API** (`ark-notify-js`) — imperative client, WebSocket, and
|
|
5
|
+
- **Core API** (`ark-notify-js`) — imperative client, WebSocket, SSE, and server-side stream classes for any JavaScript environment
|
|
6
6
|
- **React bindings** (`ark-notify-js/react`) — hooks and provider for React 18+ applications
|
|
7
7
|
|
|
8
8
|
## Install
|
|
@@ -15,10 +15,14 @@ For React apps, `react` 18+ is a peer dependency.
|
|
|
15
15
|
|
|
16
16
|
### Node.js / AdonisJS (server)
|
|
17
17
|
|
|
18
|
-
Use the `/server` subpath for `serverAuthUrl` webhook helpers:
|
|
18
|
+
Use the `/server` subpath for `serverAuthUrl` webhook helpers and the server-side event stream:
|
|
19
19
|
|
|
20
20
|
```ts
|
|
21
|
-
import {
|
|
21
|
+
import {
|
|
22
|
+
handleServerAuth,
|
|
23
|
+
parseServerAuthRequest,
|
|
24
|
+
ArkNotifyServerStream,
|
|
25
|
+
} from '@emmanuel-nike/ark-notify-js/server'
|
|
22
26
|
import { ArkNotifyClient, fetchConnectionToken } from '@emmanuel-nike/ark-notify-js'
|
|
23
27
|
```
|
|
24
28
|
|
|
@@ -323,6 +327,74 @@ const response = await handleServerAuth({
|
|
|
323
327
|
|
|
324
328
|
Or build a response directly with `createAuthorizedServerAuthResponse()`.
|
|
325
329
|
|
|
330
|
+
## Server stream (backend)
|
|
331
|
+
|
|
332
|
+
Subscribe to channel events from your application backend over SSE. Unlike client SSE (`ArkNotifySSE`), the server stream uses app credentials (`X-App-Key` / `X-App-Secret`) — not connection tokens — and does not require per-channel HMAC tokens for private channels.
|
|
333
|
+
|
|
334
|
+
Use this when a backend service needs to react to realtime events (webhooks, workers, sync jobs) without maintaining a WebSocket client.
|
|
335
|
+
|
|
336
|
+
Each subscription entry can be an exact channel name, a prefix pattern, or a wildcard:
|
|
337
|
+
|
|
338
|
+
| Value | Matches |
|
|
339
|
+
|-------|---------|
|
|
340
|
+
| `room-1` | Exact channel name |
|
|
341
|
+
| `business-*` | Any channel whose name starts with `business-` |
|
|
342
|
+
| `*` | All channels for this application |
|
|
343
|
+
|
|
344
|
+
You can combine exact names and patterns (max 32 entries). Overlapping subscriptions may deliver the same event more than once. Message history replay applies to **exact channel names only** — not patterns or `*`.
|
|
345
|
+
|
|
346
|
+
```ts
|
|
347
|
+
import { ArkNotifyServerStream } from '@emmanuel-nike/ark-notify-js/server'
|
|
348
|
+
|
|
349
|
+
const stream = new ArkNotifyServerStream({
|
|
350
|
+
appKey: process.env.ARK_APP_KEY!,
|
|
351
|
+
credentials: {
|
|
352
|
+
appKey: process.env.ARK_APP_KEY!,
|
|
353
|
+
secret: process.env.ARK_APP_SECRET!,
|
|
354
|
+
},
|
|
355
|
+
subscriptions: ['room-1', 'business-*', 'users-*'],
|
|
356
|
+
history: true, // replays stored messages for exact names only (e.g. room-1)
|
|
357
|
+
})
|
|
358
|
+
|
|
359
|
+
// Subscribe to every channel in the app
|
|
360
|
+
const allChannels = new ArkNotifyServerStream({
|
|
361
|
+
appKey: process.env.ARK_APP_KEY!,
|
|
362
|
+
credentials: { appKey: process.env.ARK_APP_KEY!, secret: process.env.ARK_APP_SECRET! },
|
|
363
|
+
subscriptions: ['*'],
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
stream.on('connected', (msg) => {
|
|
367
|
+
console.log('Exact channels', msg.channels)
|
|
368
|
+
console.log('Patterns', msg.patterns)
|
|
369
|
+
console.log('All subscriptions', msg.subscriptions)
|
|
370
|
+
})
|
|
371
|
+
|
|
372
|
+
stream.on('event', (msg) => {
|
|
373
|
+
console.log(msg.channel, msg.event, msg.data)
|
|
374
|
+
})
|
|
375
|
+
|
|
376
|
+
stream.bind('orders', 'order.created', (data) => {
|
|
377
|
+
console.log('New order', data)
|
|
378
|
+
})
|
|
379
|
+
|
|
380
|
+
stream.bindMatching('business-*', 'order.created', (data, msg) => {
|
|
381
|
+
console.log('Business order on', msg.channel, data)
|
|
382
|
+
})
|
|
383
|
+
|
|
384
|
+
await stream.connect()
|
|
385
|
+
|
|
386
|
+
// later
|
|
387
|
+
stream.disconnect()
|
|
388
|
+
```
|
|
389
|
+
|
|
390
|
+
**Notes:**
|
|
391
|
+
|
|
392
|
+
- Backend-only — never use app credentials in browser code.
|
|
393
|
+
- Uses `fetch` with a streaming SSE parser (not `EventSource`), so custom auth headers are supported.
|
|
394
|
+
- Failed auth before the stream opens throws `ArkNotifyError` (same as other REST calls).
|
|
395
|
+
- Stream lifecycle events: `connected`, `event`, `presence`, `message`, `error`, `close`.
|
|
396
|
+
- Use `bind()` / `bindAll()` for exact channel names; use `bindMatching()` / `bindAllMatching()` to filter events by prefix pattern or `*`.
|
|
397
|
+
|
|
326
398
|
## API coverage
|
|
327
399
|
|
|
328
400
|
|
|
@@ -340,6 +412,7 @@ Or build a response directly with `createAuthorizedServerAuthResponse()`.
|
|
|
340
412
|
| Publish (client) | `useChannel`, `ArkNotifyConnection` | `.publish()` |
|
|
341
413
|
| Presence | `usePresence`, `ArkNotifyConnection` | `.presenceEnter()`, `.presenceUpdate()`, … |
|
|
342
414
|
| SSE stream | `useSSE`, `ArkNotifySSE` | `.connect()` |
|
|
415
|
+
| Server stream (backend) | `ArkNotifyServerStream` | `.connect()`, `.bind()`, `.bindMatching()`, … |
|
|
343
416
|
| Private channels | `onPrivateChannelAuth` callback | — |
|
|
344
417
|
| Auto-reconnect | `useConnection` | `autoReconnect: true` |
|
|
345
418
|
| Heartbeat | `ArkNotifyConnection` | Server ping auto-replied |
|
|
@@ -361,7 +434,7 @@ try {
|
|
|
361
434
|
}
|
|
362
435
|
```
|
|
363
436
|
|
|
364
|
-
WebSocket errors are emitted via `connection.on('error', …)` or the `useConnection` state.
|
|
437
|
+
WebSocket errors are emitted via `connection.on('error', …)` or the `useConnection` state. Server stream connection errors are emitted via `stream.on('error', …)`; failed auth before the stream opens throws `ArkNotifyError`.
|
|
365
438
|
|
|
366
439
|
## License
|
|
367
440
|
|
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,17 @@ function resolveValue(value) {
|
|
|
44
44
|
function isPrivateChannel(channel) {
|
|
45
45
|
return channel.startsWith("private-");
|
|
46
46
|
}
|
|
47
|
+
function isServerStreamPattern(subscription) {
|
|
48
|
+
return subscription === "*" || subscription.endsWith("*");
|
|
49
|
+
}
|
|
50
|
+
function isAllChannelsSubscription(subscription) {
|
|
51
|
+
return subscription === "*";
|
|
52
|
+
}
|
|
53
|
+
function matchesChannelPattern(channel, pattern) {
|
|
54
|
+
if (pattern === "*") return true;
|
|
55
|
+
if (!pattern.endsWith("*")) return channel === pattern;
|
|
56
|
+
return channel.startsWith(pattern.slice(0, -1));
|
|
57
|
+
}
|
|
47
58
|
|
|
48
59
|
// src/connection-token.ts
|
|
49
60
|
function requiresAppSecret(options) {
|
|
@@ -578,6 +589,17 @@ var ArkNotifySSE = class {
|
|
|
578
589
|
};
|
|
579
590
|
|
|
580
591
|
// src/server-stream.ts
|
|
592
|
+
var MAX_SERVER_STREAM_SUBSCRIPTIONS = 32;
|
|
593
|
+
function resolveServerStreamSubscriptions(config) {
|
|
594
|
+
const subscriptions = config.subscriptions ?? config.channels ?? [];
|
|
595
|
+
if (subscriptions.length === 0) {
|
|
596
|
+
throw new Error("At least one subscription is required (exact channel, pattern, or *)");
|
|
597
|
+
}
|
|
598
|
+
if (subscriptions.length > MAX_SERVER_STREAM_SUBSCRIPTIONS) {
|
|
599
|
+
throw new Error(`A maximum of ${MAX_SERVER_STREAM_SUBSCRIPTIONS} subscriptions is allowed per stream`);
|
|
600
|
+
}
|
|
601
|
+
return subscriptions;
|
|
602
|
+
}
|
|
581
603
|
function buildAppCredentialsHeaders(credentials) {
|
|
582
604
|
return {
|
|
583
605
|
"X-App-Key": credentials.appKey,
|
|
@@ -660,13 +682,27 @@ var ArkNotifyServerStream = class {
|
|
|
660
682
|
this.listeners = /* @__PURE__ */ new Map();
|
|
661
683
|
this.abortController = null;
|
|
662
684
|
this.connectionId = null;
|
|
685
|
+
this.connectedMessage = null;
|
|
663
686
|
this.connecting = false;
|
|
664
|
-
this.config = {
|
|
687
|
+
this.config = {
|
|
688
|
+
...config,
|
|
689
|
+
baseUrl: resolveBaseUrl(config.baseUrl),
|
|
690
|
+
subscriptions: resolveServerStreamSubscriptions(config)
|
|
691
|
+
};
|
|
665
692
|
this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis);
|
|
666
693
|
}
|
|
667
694
|
getConnectionId() {
|
|
668
695
|
return this.connectionId;
|
|
669
696
|
}
|
|
697
|
+
getSubscriptions() {
|
|
698
|
+
return this.connectedMessage?.subscriptions ?? [...this.config.subscriptions];
|
|
699
|
+
}
|
|
700
|
+
getChannels() {
|
|
701
|
+
return this.connectedMessage?.channels ?? [];
|
|
702
|
+
}
|
|
703
|
+
getPatterns() {
|
|
704
|
+
return this.connectedMessage?.patterns ?? [];
|
|
705
|
+
}
|
|
670
706
|
on(event, handler) {
|
|
671
707
|
if (!this.listeners.has(event)) {
|
|
672
708
|
this.listeners.set(event, /* @__PURE__ */ new Set());
|
|
@@ -691,7 +727,7 @@ var ArkNotifyServerStream = class {
|
|
|
691
727
|
const streamUrl = appendQueryParams(
|
|
692
728
|
`${base}/api/v1/apps/${this.config.appKey}/server-stream`,
|
|
693
729
|
{
|
|
694
|
-
channels: this.config.
|
|
730
|
+
channels: this.config.subscriptions.join(","),
|
|
695
731
|
history: this.config.history ? "true" : void 0
|
|
696
732
|
}
|
|
697
733
|
);
|
|
@@ -734,6 +770,7 @@ var ArkNotifyServerStream = class {
|
|
|
734
770
|
dispatchSseEvent(data, {
|
|
735
771
|
onConnected: (message) => {
|
|
736
772
|
this.connectionId = message.connection_id;
|
|
773
|
+
this.connectedMessage = message;
|
|
737
774
|
this.emit("connected", message);
|
|
738
775
|
},
|
|
739
776
|
onEvent: (message) => this.emit("event", message),
|
|
@@ -750,6 +787,7 @@ var ArkNotifyServerStream = class {
|
|
|
750
787
|
if (this.abortController === abortController) {
|
|
751
788
|
this.abortController = null;
|
|
752
789
|
this.connectionId = null;
|
|
790
|
+
this.connectedMessage = null;
|
|
753
791
|
this.emit("close");
|
|
754
792
|
}
|
|
755
793
|
}
|
|
@@ -774,6 +812,22 @@ var ArkNotifyServerStream = class {
|
|
|
774
812
|
};
|
|
775
813
|
return this.on("event", listener);
|
|
776
814
|
}
|
|
815
|
+
bindMatching(pattern, event, handler) {
|
|
816
|
+
const listener = (message) => {
|
|
817
|
+
if (matchesChannelPattern(message.channel, pattern) && message.event === event) {
|
|
818
|
+
handler(message.data, message);
|
|
819
|
+
}
|
|
820
|
+
};
|
|
821
|
+
return this.on("event", listener);
|
|
822
|
+
}
|
|
823
|
+
bindAllMatching(pattern, handler) {
|
|
824
|
+
const listener = (message) => {
|
|
825
|
+
if (matchesChannelPattern(message.channel, pattern)) {
|
|
826
|
+
handler(message.data, message);
|
|
827
|
+
}
|
|
828
|
+
};
|
|
829
|
+
return this.on("event", listener);
|
|
830
|
+
}
|
|
777
831
|
};
|
|
778
832
|
|
|
779
833
|
exports.ArkNotifyClient = ArkNotifyClient;
|
|
@@ -785,7 +839,10 @@ exports.DEFAULT_BASE_URL = DEFAULT_BASE_URL;
|
|
|
785
839
|
exports.appendQueryParams = appendQueryParams;
|
|
786
840
|
exports.configureArkNotify = configureArkNotify;
|
|
787
841
|
exports.fetchConnectionToken = fetchConnectionToken;
|
|
842
|
+
exports.isAllChannelsSubscription = isAllChannelsSubscription;
|
|
788
843
|
exports.isPrivateChannel = isPrivateChannel;
|
|
844
|
+
exports.isServerStreamPattern = isServerStreamPattern;
|
|
845
|
+
exports.matchesChannelPattern = matchesChannelPattern;
|
|
789
846
|
exports.resolveBaseUrl = resolveBaseUrl;
|
|
790
847
|
exports.resolveValue = resolveValue;
|
|
791
848
|
exports.toWebSocketUrl = toWebSocketUrl;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/utils.ts","../src/connection-token.ts","../src/client.ts","../src/connection.ts","../src/sse.ts","../src/server-stream.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://ark-notify-933303906015.europe-north1.run.app'\n\nlet configuredBaseUrl: string | undefined\n\nexport interface ArkNotifyGlobalConfig {\n baseUrl?: string\n}\n\n/** Set the default base URL once at application startup. */\nexport function configureArkNotify(config: ArkNotifyGlobalConfig): void {\n if (config.baseUrl !== undefined) {\n configuredBaseUrl = config.baseUrl\n }\n}\n\nexport function resolveBaseUrl(baseUrl?: string): string {\n return (baseUrl ?? configuredBaseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '')\n}\n","import type { ApiError } from './types'\n\nexport class ArkNotifyError extends Error {\n readonly status: number\n readonly code: string\n readonly retryAfterSec?: number\n readonly reason?: string\n\n constructor(status: number, body: ApiError) {\n super(body.message)\n this.name = 'ArkNotifyError'\n this.status = status\n this.code = body.error\n this.retryAfterSec = body.retryAfterSec\n this.reason = body.reason\n }\n}\n\nexport function toWebSocketUrl(baseUrl: string, path: string): string {\n const normalizedBase = baseUrl.replace(/\\/$/, '')\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n const httpUrl = `${normalizedBase}${normalizedPath}`\n // Avoid URL.protocol — not supported in React Native and some runtimes.\n return httpUrl.replace(/^https:/i, 'wss:').replace(/^http:/i, 'ws:')\n}\n\n/** Append query params without URLSearchParams (unsupported in React Native). */\nexport function appendQueryParams(\n url: string,\n params: Record<string, string | undefined | null | false>\n): string {\n const query = Object.entries(params)\n .filter((entry): entry is [string, string] => {\n const value = entry[1]\n return value !== undefined && value !== null && value !== false && value !== ''\n })\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&')\n\n if (!query) return url\n\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}${query}`\n}\n\nexport function resolveValue<T>(value: T | (() => T)): T {\n return typeof value === 'function' ? (value as () => T)() : value\n}\n\nexport function isPrivateChannel(channel: string): boolean {\n return channel.startsWith('private-')\n}\n","import { resolveBaseUrl } from './config'\nimport type { AppCredentials, ConnectionTokenInput, ConnectionTokenResponse } from './types'\nimport { ArkNotifyError } from './utils'\n\nexport interface FetchConnectionTokenOptions extends ConnectionTokenInput {\n baseUrl?: string\n appKey: string\n /** Required unless the application has a serverAuthUrl (or one is passed in the request). */\n credentials?: AppCredentials\n fetch?: typeof fetch\n}\n\nfunction requiresAppSecret(options: FetchConnectionTokenOptions): boolean {\n if ('serverAuthUrl' in options) {\n const value = options.serverAuthUrl\n return value === null || value === ''\n }\n if ('server_auth_url' in options) {\n const value = options.server_auth_url\n return value === null || value === ''\n }\n return false\n}\n\nfunction buildConnectionTokenRequest(\n options: FetchConnectionTokenOptions\n): {\n url: string\n headers: Record<string, string>\n body: ConnectionTokenInput\n} {\n const {\n baseUrl,\n appKey,\n credentials,\n client_id,\n clientId,\n user_data,\n userData,\n ttl,\n capabilities,\n server_auth_url,\n serverAuthUrl,\n } = options\n\n const resolvedClientId = client_id ?? clientId\n if (!resolvedClientId) {\n throw new Error('client_id is required to fetch a connection token')\n }\n\n if (requiresAppSecret(options) && !credentials) {\n throw new Error('credentials are required when serverAuthUrl is explicitly set to null')\n }\n\n const body: ConnectionTokenInput = {\n client_id: resolvedClientId,\n user_data: user_data ?? userData,\n ttl,\n capabilities,\n }\n\n if ('serverAuthUrl' in options) {\n body.serverAuthUrl = serverAuthUrl\n } else if ('server_auth_url' in options) {\n body.server_auth_url = server_auth_url\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (credentials) {\n headers['X-App-Key'] = credentials.appKey\n headers['X-App-Secret'] = credentials.secret\n }\n\n return {\n url: `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`,\n headers,\n body,\n }\n}\n\n/**\n * Request a signed connection token from the Ark Notify API.\n *\n * Authentication depends on server auth configuration:\n * - Application or request has a `serverAuthUrl`: public `appKey` only (frontend-safe).\n * - No `serverAuthUrl`: `credentials` with app key + secret (backend-only).\n */\nexport async function fetchConnectionToken(\n options: FetchConnectionTokenOptions\n): Promise<ConnectionTokenResponse> {\n const { fetch: fetchFn = globalThis.fetch.bind(globalThis) } = options\n const { url, headers, body } = buildConnectionTokenRequest(options)\n\n const response = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n let errorBody: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n errorBody = await response.json()\n } catch {\n errorBody = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, errorBody)\n }\n\n return response.json() as Promise<ConnectionTokenResponse>\n}\n","import { resolveBaseUrl } from './config'\nimport { fetchConnectionToken } from './connection-token'\nimport { ArkNotifyError, resolveValue } from './utils'\nimport type {\n Application,\n ArkNotifyClientConfig,\n AppCredentials,\n AuthResponse,\n ChannelAuthInput,\n ChannelAuthResponse,\n ConnectionTokenInput,\n ConnectionTokenResponse,\n CreateApplicationInput,\n HealthResponse,\n LoginInput,\n PublishEventInput,\n PublishEventResponse,\n UpdateApplicationInput,\n User,\n} from './types'\n\ntype RequestOptions = {\n method?: string\n body?: unknown\n headers?: Record<string, string>\n credentials?: AppCredentials\n}\n\nexport class ArkNotifyClient {\n private readonly baseUrl: string\n private readonly fetchFn: typeof fetch\n private token?: string | (() => string | null | undefined)\n\n constructor(config: Readonly<ArkNotifyClientConfig> = {}) {\n this.baseUrl = resolveBaseUrl(config?.baseUrl)\n this.token = config.token\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n }\n\n setToken(token: string | null): void {\n this.token = token ?? undefined\n }\n\n private getAuthHeader(): string | undefined {\n const token = resolveValue(this.token)\n return token ? `Bearer ${token}` : undefined\n }\n\n private async request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n const auth = this.getAuthHeader()\n if (auth) {\n headers.Authorization = auth\n }\n\n if (options.credentials) {\n headers['X-App-Key'] = options.credentials.appKey\n headers['X-App-Secret'] = options.credentials.secret\n }\n\n const response = await this.fetchFn(`${this.baseUrl}${path}`, {\n method: options.method ?? 'GET',\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n })\n\n if (!response.ok) {\n let body: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n body = await response.json()\n } catch {\n body = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, body)\n }\n\n if (response.status === 204) {\n return undefined as T\n }\n\n return response.json() as Promise<T>\n }\n\n // ── Health ──────────────────────────────────────────────────────────────\n\n health(): Promise<HealthResponse> {\n return this.request('/health')\n }\n\n // ── Platform auth ───────────────────────────────────────────────────────\n\n login(input: LoginInput): Promise<AuthResponse> {\n return this.request('/api/v1/auth/login', { method: 'POST', body: input })\n }\n\n me(): Promise<{ user: User }> {\n return this.request('/api/v1/auth/me')\n }\n\n // ── Applications ────────────────────────────────────────────────────────\n\n listApplications(): Promise<{ apps: Application[] }> {\n return this.request('/api/v1/applications')\n }\n\n createApplication(input: CreateApplicationInput): Promise<{ app: Application }> {\n return this.request('/api/v1/applications', { method: 'POST', body: input })\n }\n\n getApplication(id: string): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}`)\n }\n\n updateApplication(id: string, input: UpdateApplicationInput): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}`, { method: 'PUT', body: input })\n }\n\n deleteApplication(id: string): Promise<{ deleted: boolean; id: string }> {\n return this.request(`/api/v1/applications/${id}`, { method: 'DELETE' })\n }\n\n regenerateSecret(id: string): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}/regenerate-secret`, {\n method: 'POST',\n })\n }\n\n // ── Data plane ──────────────────────────────────────────────────────────\n\n publishEvent(\n appKey: string,\n credentials: AppCredentials,\n input: PublishEventInput\n ): Promise<PublishEventResponse> {\n return this.request(`/api/v1/apps/${appKey}/events`, {\n method: 'POST',\n body: input,\n credentials,\n })\n }\n\n authorizeChannel(\n appKey: string,\n credentials: AppCredentials,\n input: ChannelAuthInput\n ): Promise<ChannelAuthResponse> {\n return this.request(`/api/v1/apps/${appKey}/auth`, {\n method: 'POST',\n body: input,\n credentials,\n })\n }\n\n issueConnectionToken(\n appKey: string,\n input: ConnectionTokenInput,\n credentials?: AppCredentials\n ): Promise<ConnectionTokenResponse> {\n return fetchConnectionToken({\n baseUrl: this.baseUrl,\n appKey,\n credentials,\n ...input,\n fetch: this.fetchFn,\n })\n }\n}\n","import { resolveBaseUrl } from './config'\nimport { fetchConnectionToken } from './connection-token'\nimport type {\n ArkNotifyConnectionConfig,\n ChannelEventHandler,\n ConnectedMessage,\n ConnectionState,\n EventMessage,\n PresenceMessage,\n ServerMessage,\n SubscribeOptions,\n} from './types'\nimport { isPrivateChannel, appendQueryParams, resolveValue, toWebSocketUrl } from './utils'\n\ntype EventMap = {\n state: (state: ConnectionState) => void\n connected: (message: ConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerMessage) => void\n error: (error: { code: string; message: string }) => void\n close: (event: { code: number; reason: string }) => void\n}\n\ntype EventName = keyof EventMap\n\nexport class ArkNotifyConnection {\n private readonly config: Required<\n Pick<\n ArkNotifyConnectionConfig,\n 'baseUrl' | 'appKey' | 'autoReconnect' | 'reconnectDelayMs' | 'maxReconnectDelayMs'\n >\n > &\n ArkNotifyConnectionConfig\n\n private ws: WebSocket | null = null\n private state: ConnectionState = 'disconnected'\n private connectionId: string | null = null\n private clientId: string | null = null\n private authenticated = false\n private readonly subscribedChannels = new Set<string>()\n private readonly pendingSubscriptions = new Map<string, SubscribeOptions>()\n private readonly listeners = new Map<EventName, Set<EventMap[EventName]>>()\n private reconnectAttempt = 0\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private intentionalClose = false\n private connectPromise: Promise<void> | null = null\n private readonly WebSocketCtor: typeof WebSocket\n\n constructor(config: ArkNotifyConnectionConfig) {\n this.config = {\n autoReconnect: true,\n reconnectDelayMs: 1000,\n maxReconnectDelayMs: 30000,\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n }\n this.WebSocketCtor = config.WebSocket ?? globalThis.WebSocket\n }\n\n getConnectionState(): ConnectionState {\n return this.state\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n getClientId(): string | null {\n return this.clientId\n }\n\n isAuthenticated(): boolean {\n return this.authenticated\n }\n\n getSubscribedChannels(): string[] {\n return [...this.subscribedChannels]\n }\n\n on<E extends EventName>(event: E, handler: EventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends EventName>(event: E, handler: EventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends EventName>(event: E, ...args: Parameters<EventMap[E]>): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<EventMap[E]>) => void)(...args)\n }\n }\n\n private setState(state: ConnectionState): void {\n if (this.state !== state) {\n this.state = state\n this.emit('state', state)\n }\n }\n\n connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN || this.ws?.readyState === WebSocket.CONNECTING) {\n return Promise.resolve()\n }\n\n if (this.connectPromise) {\n return this.connectPromise\n }\n\n this.connectPromise = this.doConnect().finally(() => {\n this.connectPromise = null\n })\n\n return this.connectPromise\n }\n\n private async doConnect(): Promise<void> {\n this.intentionalClose = false\n this.clearReconnectTimer()\n this.setState(this.reconnectAttempt > 0 ? 'reconnecting' : 'connecting')\n\n let wsUrl = toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)\n\n let token = resolveValue(this.config.token)\n if (!token && this.config.clientId) {\n const result = await fetchConnectionToken({\n baseUrl: this.config.baseUrl,\n appKey: this.config.appKey,\n credentials: this.config.credentials,\n client_id: this.config.clientId,\n user_data: this.config.userData,\n serverAuthUrl: this.config.serverAuthUrl,\n fetch: this.config.fetch,\n })\n token = result.token\n }\n\n if (token) {\n wsUrl = appendQueryParams(wsUrl, { token })\n } else if (this.config.clientId) {\n wsUrl = appendQueryParams(wsUrl, { clientId: this.config.clientId })\n }\n\n this.ws = new this.WebSocketCtor(wsUrl)\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0\n }\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data as string)\n }\n\n this.ws.onerror = () => {\n this.emit('error', { code: 'websocket_error', message: 'WebSocket error' })\n }\n\n this.ws.onclose = (event) => {\n this.ws = null\n this.connectionId = null\n this.emit('close', { code: event.code, reason: event.reason })\n\n if (!this.intentionalClose && this.config.autoReconnect) {\n this.scheduleReconnect()\n } else {\n this.setState('failed')\n }\n }\n }\n\n disconnect(): void {\n this.intentionalClose = true\n this.clearReconnectTimer()\n this.subscribedChannels.clear()\n this.pendingSubscriptions.clear()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.setState('disconnected')\n }\n\n private scheduleReconnect(): void {\n this.setState('reconnecting')\n const delay = Math.min(\n this.config.reconnectDelayMs * 2 ** this.reconnectAttempt,\n this.config.maxReconnectDelayMs\n )\n this.reconnectAttempt++\n this.reconnectTimer = setTimeout(() => void this.connect(), delay)\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n }\n\n private send(payload: Record<string, unknown>): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n throw new Error('WebSocket is not connected')\n }\n this.ws.send(JSON.stringify(payload))\n }\n\n private handleMessage(raw: string): void {\n let message: ServerMessage\n try {\n message = JSON.parse(raw) as ServerMessage\n } catch {\n this.emit('error', { code: 'invalid_json', message: 'Invalid JSON from server' })\n return\n }\n\n this.emit('message', message)\n\n switch (message.type) {\n case 'connected': {\n this.connectionId = message.connection_id\n this.clientId = message.client_id\n this.authenticated = message.authenticated\n this.setState('connected')\n this.emit('connected', message)\n this.resubscribeAll()\n break\n }\n case 'event':\n this.emit('event', message)\n break\n case 'presence':\n this.emit('presence', message)\n break\n case 'subscribed':\n this.subscribedChannels.add(message.channel)\n break\n case 'unsubscribed':\n this.subscribedChannels.delete(message.channel)\n break\n case 'error':\n this.emit('error', { code: message.code, message: message.message })\n break\n case 'ping':\n this.send({ action: 'ping' })\n break\n default:\n break\n }\n }\n\n private resubscribeAll(): void {\n for (const [channel, options] of this.pendingSubscriptions) {\n void this.subscribe(channel, options)\n }\n }\n\n async subscribe(channel: string, options: SubscribeOptions = {}): Promise<void> {\n this.pendingSubscriptions.set(channel, options)\n\n if (this.state !== 'connected' || !this.connectionId) {\n return\n }\n\n const payload: Record<string, unknown> = {\n action: 'subscribe',\n channel,\n }\n\n if (options.history) payload.history = true\n if (options.presence) {\n payload.presence = true\n if (options.presence_data) payload.presence_data = options.presence_data\n }\n\n if (isPrivateChannel(channel)) {\n if (options.auth) {\n payload.auth = options.auth\n } else if (this.config.onPrivateChannelAuth) {\n payload.auth = await this.config.onPrivateChannelAuth(channel, this.connectionId)\n } else {\n throw new Error(\n `Private channel \"${channel}\" requires auth. Provide options.auth or onPrivateChannelAuth.`\n )\n }\n }\n\n this.send(payload)\n }\n\n unsubscribe(channel: string): void {\n this.pendingSubscriptions.delete(channel)\n this.subscribedChannels.delete(channel)\n if (this.state === 'connected') {\n this.send({ action: 'unsubscribe', channel })\n }\n }\n\n publish(channel: string, event: string, data?: unknown): void {\n this.send({ action: 'publish', channel, event, data })\n }\n\n presenceEnter(channel: string, data: Record<string, unknown>): void {\n this.send({ action: 'presence_enter', channel, data })\n }\n\n presenceUpdate(channel: string, data: Record<string, unknown>): void {\n this.send({ action: 'presence_update', channel, data })\n }\n\n presenceLeave(channel: string): void {\n this.send({ action: 'presence_leave', channel })\n }\n\n presenceSync(channel: string): void {\n this.send({ action: 'presence_sync', channel })\n }\n\n ping(): void {\n this.send({ action: 'ping' })\n }\n\n bind(channel: string, event: string, handler: ChannelEventHandler): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: ChannelEventHandler): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n","import { resolveBaseUrl } from './config'\nimport type {\n ArkNotifySSEConfig,\n ConnectedMessage,\n EventMessage,\n PresenceMessage,\n ServerMessage,\n} from './types'\nimport { isPrivateChannel, appendQueryParams, resolveValue } from './utils'\n\ntype SSEEventMap = {\n connected: (message: ConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerMessage) => void\n error: (error: Error) => void\n close: () => void\n}\n\ntype SSEEventName = keyof SSEEventMap\n\nexport class ArkNotifySSE {\n private readonly config: ArkNotifySSEConfig & { baseUrl: string }\n private es: EventSource | null = null\n private connectionId: string | null = null\n private readonly listeners = new Map<SSEEventName, Set<SSEEventMap[SSEEventName]>>()\n private readonly EventSourceCtor: typeof EventSource\n\n constructor(config: ArkNotifySSEConfig) {\n this.config = { ...config, baseUrl: resolveBaseUrl(config.baseUrl) }\n this.EventSourceCtor = config.EventSource ?? globalThis.EventSource\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n on<E extends SSEEventName>(event: E, handler: SSEEventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends SSEEventName>(event: E, handler: SSEEventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends SSEEventName>(event: E, ...args: Parameters<SSEEventMap[E]>): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<SSEEventMap[E]>) => void)(...args)\n }\n }\n\n async connect(): Promise<void> {\n if (this.es) return\n\n const base = this.config.baseUrl.replace(/\\/$/, '')\n const authMap = this.config.auth ? { ...this.config.auth } : {}\n\n const privateChannels = this.config.channels.filter(isPrivateChannel)\n if (privateChannels.length > 0 && this.config.onPrivateChannelAuth && !this.config.auth) {\n // Private SSE channels need auth tokens in the query before connect.\n // Fetch tokens server-side and pass them via the `auth` option, or use WebSocket instead.\n }\n\n const token = resolveValue(this.config.token)\n const streamUrl = appendQueryParams(`${base}/app/${this.config.appKey}/stream`, {\n channels: this.config.channels.join(','),\n token: token || undefined,\n clientId: !token && this.config.clientId ? this.config.clientId : undefined,\n history: this.config.history ? 'true' : undefined,\n user_data: this.config.user_data ? JSON.stringify(this.config.user_data) : undefined,\n auth: Object.keys(authMap).length > 0 ? JSON.stringify(authMap) : undefined,\n })\n\n this.es = new this.EventSourceCtor(streamUrl)\n\n this.es.addEventListener('connected', (e) => {\n const message = JSON.parse(e.data) as ConnectedMessage\n this.connectionId = message.connection_id\n this.emit('connected', message)\n this.emit('message', message)\n })\n\n this.es.addEventListener('event', (e) => {\n const message = JSON.parse(e.data) as EventMessage\n this.emit('event', message)\n this.emit('message', message)\n })\n\n this.es.addEventListener('presence', (e) => {\n const message = JSON.parse(e.data) as PresenceMessage\n this.emit('presence', message)\n this.emit('message', message)\n })\n\n this.es.onerror = () => {\n this.emit('error', new Error('SSE connection error'))\n }\n }\n\n disconnect(): void {\n if (this.es) {\n this.es.close()\n this.es = null\n this.connectionId = null\n this.emit('close')\n }\n }\n\n bind(\n channel: string,\n event: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: (data: unknown, message: EventMessage) => void): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n","import { resolveBaseUrl } from './config'\nimport type {\n AppCredentials,\n ArkNotifyServerStreamConfig,\n EventMessage,\n PresenceMessage,\n ServerErrorMessage,\n ServerStreamConnectedMessage,\n} from './types'\nimport { appendQueryParams, ArkNotifyError } from './utils'\n\ntype ServerStreamEventMap = {\n connected: (message: ServerStreamConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerStreamMessage) => void\n error: (error: Error) => void\n close: () => void\n}\n\ntype ServerStreamEventName = keyof ServerStreamEventMap\n\nfunction buildAppCredentialsHeaders(credentials: AppCredentials): Record<string, string> {\n return {\n 'X-App-Key': credentials.appKey,\n 'X-App-Secret': credentials.secret,\n }\n}\n\ntype ServerStreamMessage = ServerStreamConnectedMessage | EventMessage | PresenceMessage | ServerErrorMessage\n\nfunction dispatchSseEvent(\n data: string,\n handlers: {\n onConnected: (message: ServerStreamConnectedMessage) => void\n onEvent: (message: EventMessage) => void\n onPresence: (message: PresenceMessage) => void\n onMessage: (message: ServerStreamMessage) => void\n }\n): void {\n if (!data) return\n\n let parsed: ServerStreamMessage\n try {\n parsed = JSON.parse(data) as ServerStreamMessage\n } catch {\n return\n }\n\n if (parsed.type === 'connected') {\n handlers.onConnected(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n if (parsed.type === 'event') {\n handlers.onEvent(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n if (parsed.type === 'presence') {\n handlers.onPresence(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n handlers.onMessage(parsed)\n}\n\nasync function readSseStream(\n body: ReadableStream<Uint8Array>,\n onSseData: (data: string) => void,\n signal: AbortSignal\n): Promise<void> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let currentEvent: string | null = null\n let dataLines: string[] = []\n\n const flushEvent = () => {\n if (dataLines.length === 0 && currentEvent === null) return\n onSseData(dataLines.join('\\n'))\n currentEvent = null\n dataLines = []\n }\n\n try {\n while (!signal.aborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const rawLine of lines) {\n const line = rawLine.endsWith('\\r') ? rawLine.slice(0, -1) : rawLine\n\n if (line === '') {\n flushEvent()\n continue\n }\n\n if (line.startsWith(':')) continue\n\n if (line.startsWith('event:')) {\n currentEvent = line.slice(6).trimStart()\n continue\n }\n\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n }\n }\n }\n\n if (buffer.length > 0) {\n const line = buffer.endsWith('\\r') ? buffer.slice(0, -1) : buffer\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n }\n }\n\n flushEvent()\n } finally {\n reader.releaseLock()\n }\n}\n\nexport class ArkNotifyServerStream {\n private readonly config: ArkNotifyServerStreamConfig & { baseUrl: string }\n private readonly fetchFn: typeof fetch\n private readonly listeners = new Map<\n ServerStreamEventName,\n Set<ServerStreamEventMap[ServerStreamEventName]>\n >()\n private abortController: AbortController | null = null\n private connectionId: string | null = null\n private connecting = false\n\n constructor(config: ArkNotifyServerStreamConfig) {\n this.config = { ...config, baseUrl: resolveBaseUrl(config.baseUrl) }\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n on<E extends ServerStreamEventName>(event: E, handler: ServerStreamEventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends ServerStreamEventName>(event: E, handler: ServerStreamEventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends ServerStreamEventName>(\n event: E,\n ...args: Parameters<ServerStreamEventMap[E]>\n ): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<ServerStreamEventMap[E]>) => void)(...args)\n }\n }\n\n async connect(): Promise<void> {\n if (this.abortController || this.connecting) return\n\n this.connecting = true\n const abortController = new AbortController()\n this.abortController = abortController\n\n const base = this.config.baseUrl.replace(/\\/$/, '')\n const streamUrl = appendQueryParams(\n `${base}/api/v1/apps/${this.config.appKey}/server-stream`,\n {\n channels: this.config.channels.join(','),\n history: this.config.history ? 'true' : undefined,\n }\n )\n\n try {\n const response = await this.fetchFn(streamUrl, {\n method: 'GET',\n headers: {\n Accept: 'text/event-stream',\n ...buildAppCredentialsHeaders(this.config.credentials),\n },\n signal: abortController.signal,\n })\n\n if (!response.ok) {\n let body: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n body = await response.json()\n } catch {\n body = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, body)\n }\n\n if (!response.body) {\n throw new Error('Server stream response has no body')\n }\n\n void this.consumeStream(response.body, abortController)\n } catch (err) {\n if (abortController.signal.aborted) return\n this.abortController = null\n this.emit('error', err instanceof Error ? err : new Error(String(err)))\n this.emit('close')\n } finally {\n this.connecting = false\n }\n }\n\n private async consumeStream(body: ReadableStream<Uint8Array>, abortController: AbortController): Promise<void> {\n try {\n await readSseStream(\n body,\n (data) => {\n dispatchSseEvent(data, {\n onConnected: (message) => {\n this.connectionId = message.connection_id\n this.emit('connected', message)\n },\n onEvent: (message) => this.emit('event', message),\n onPresence: (message) => this.emit('presence', message),\n onMessage: (message) => this.emit('message', message),\n })\n },\n abortController.signal\n )\n } catch (err) {\n if (abortController.signal.aborted) return\n this.emit('error', err instanceof Error ? err : new Error(String(err)))\n } finally {\n if (this.abortController === abortController) {\n this.abortController = null\n this.connectionId = null\n this.emit('close')\n }\n }\n }\n\n disconnect(): void {\n if (!this.abortController) return\n this.abortController.abort()\n }\n\n bind(\n channel: string,\n event: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: (data: unknown, message: EventMessage) => void): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/utils.ts","../src/connection-token.ts","../src/client.ts","../src/connection.ts","../src/sse.ts","../src/server-stream.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export const DEFAULT_BASE_URL = 'https://ark-notify-933303906015.europe-north1.run.app'\n\nlet configuredBaseUrl: string | undefined\n\nexport interface ArkNotifyGlobalConfig {\n baseUrl?: string\n}\n\n/** Set the default base URL once at application startup. */\nexport function configureArkNotify(config: ArkNotifyGlobalConfig): void {\n if (config.baseUrl !== undefined) {\n configuredBaseUrl = config.baseUrl\n }\n}\n\nexport function resolveBaseUrl(baseUrl?: string): string {\n return (baseUrl ?? configuredBaseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, '')\n}\n","import type { ApiError } from './types'\n\nexport class ArkNotifyError extends Error {\n readonly status: number\n readonly code: string\n readonly retryAfterSec?: number\n readonly reason?: string\n\n constructor(status: number, body: ApiError) {\n super(body.message)\n this.name = 'ArkNotifyError'\n this.status = status\n this.code = body.error\n this.retryAfterSec = body.retryAfterSec\n this.reason = body.reason\n }\n}\n\nexport function toWebSocketUrl(baseUrl: string, path: string): string {\n const normalizedBase = baseUrl.replace(/\\/$/, '')\n const normalizedPath = path.startsWith('/') ? path : `/${path}`\n const httpUrl = `${normalizedBase}${normalizedPath}`\n // Avoid URL.protocol — not supported in React Native and some runtimes.\n return httpUrl.replace(/^https:/i, 'wss:').replace(/^http:/i, 'ws:')\n}\n\n/** Append query params without URLSearchParams (unsupported in React Native). */\nexport function appendQueryParams(\n url: string,\n params: Record<string, string | undefined | null | false>\n): string {\n const query = Object.entries(params)\n .filter((entry): entry is [string, string] => {\n const value = entry[1]\n return value !== undefined && value !== null && value !== false && value !== ''\n })\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)\n .join('&')\n\n if (!query) return url\n\n const separator = url.includes('?') ? '&' : '?'\n return `${url}${separator}${query}`\n}\n\nexport function resolveValue<T>(value: T | (() => T)): T {\n return typeof value === 'function' ? (value as () => T)() : value\n}\n\nexport function isPrivateChannel(channel: string): boolean {\n return channel.startsWith('private-')\n}\n\n/** Whether a server-stream subscription entry is a pattern (`business-*` or `*`). */\nexport function isServerStreamPattern(subscription: string): boolean {\n return subscription === '*' || subscription.endsWith('*')\n}\n\n/** Whether a server-stream subscription entry matches all channels. */\nexport function isAllChannelsSubscription(subscription: string): boolean {\n return subscription === '*'\n}\n\n/** Whether an event channel name matches a server-stream prefix pattern or `*`. */\nexport function matchesChannelPattern(channel: string, pattern: string): boolean {\n if (pattern === '*') return true\n if (!pattern.endsWith('*')) return channel === pattern\n return channel.startsWith(pattern.slice(0, -1))\n}\n","import { resolveBaseUrl } from './config'\nimport type { AppCredentials, ConnectionTokenInput, ConnectionTokenResponse } from './types'\nimport { ArkNotifyError } from './utils'\n\nexport interface FetchConnectionTokenOptions extends ConnectionTokenInput {\n baseUrl?: string\n appKey: string\n /** Required unless the application has a serverAuthUrl (or one is passed in the request). */\n credentials?: AppCredentials\n fetch?: typeof fetch\n}\n\nfunction requiresAppSecret(options: FetchConnectionTokenOptions): boolean {\n if ('serverAuthUrl' in options) {\n const value = options.serverAuthUrl\n return value === null || value === ''\n }\n if ('server_auth_url' in options) {\n const value = options.server_auth_url\n return value === null || value === ''\n }\n return false\n}\n\nfunction buildConnectionTokenRequest(\n options: FetchConnectionTokenOptions\n): {\n url: string\n headers: Record<string, string>\n body: ConnectionTokenInput\n} {\n const {\n baseUrl,\n appKey,\n credentials,\n client_id,\n clientId,\n user_data,\n userData,\n ttl,\n capabilities,\n server_auth_url,\n serverAuthUrl,\n } = options\n\n const resolvedClientId = client_id ?? clientId\n if (!resolvedClientId) {\n throw new Error('client_id is required to fetch a connection token')\n }\n\n if (requiresAppSecret(options) && !credentials) {\n throw new Error('credentials are required when serverAuthUrl is explicitly set to null')\n }\n\n const body: ConnectionTokenInput = {\n client_id: resolvedClientId,\n user_data: user_data ?? userData,\n ttl,\n capabilities,\n }\n\n if ('serverAuthUrl' in options) {\n body.serverAuthUrl = serverAuthUrl\n } else if ('server_auth_url' in options) {\n body.server_auth_url = server_auth_url\n }\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n }\n\n if (credentials) {\n headers['X-App-Key'] = credentials.appKey\n headers['X-App-Secret'] = credentials.secret\n }\n\n return {\n url: `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`,\n headers,\n body,\n }\n}\n\n/**\n * Request a signed connection token from the Ark Notify API.\n *\n * Authentication depends on server auth configuration:\n * - Application or request has a `serverAuthUrl`: public `appKey` only (frontend-safe).\n * - No `serverAuthUrl`: `credentials` with app key + secret (backend-only).\n */\nexport async function fetchConnectionToken(\n options: FetchConnectionTokenOptions\n): Promise<ConnectionTokenResponse> {\n const { fetch: fetchFn = globalThis.fetch.bind(globalThis) } = options\n const { url, headers, body } = buildConnectionTokenRequest(options)\n\n const response = await fetchFn(url, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n if (!response.ok) {\n let errorBody: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n errorBody = await response.json()\n } catch {\n errorBody = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, errorBody)\n }\n\n return response.json() as Promise<ConnectionTokenResponse>\n}\n","import { resolveBaseUrl } from './config'\nimport { fetchConnectionToken } from './connection-token'\nimport { ArkNotifyError, resolveValue } from './utils'\nimport type {\n Application,\n ArkNotifyClientConfig,\n AppCredentials,\n AuthResponse,\n ChannelAuthInput,\n ChannelAuthResponse,\n ConnectionTokenInput,\n ConnectionTokenResponse,\n CreateApplicationInput,\n HealthResponse,\n LoginInput,\n PublishEventInput,\n PublishEventResponse,\n UpdateApplicationInput,\n User,\n} from './types'\n\ntype RequestOptions = {\n method?: string\n body?: unknown\n headers?: Record<string, string>\n credentials?: AppCredentials\n}\n\nexport class ArkNotifyClient {\n private readonly baseUrl: string\n private readonly fetchFn: typeof fetch\n private token?: string | (() => string | null | undefined)\n\n constructor(config: Readonly<ArkNotifyClientConfig> = {}) {\n this.baseUrl = resolveBaseUrl(config?.baseUrl)\n this.token = config.token\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n }\n\n setToken(token: string | null): void {\n this.token = token ?? undefined\n }\n\n private getAuthHeader(): string | undefined {\n const token = resolveValue(this.token)\n return token ? `Bearer ${token}` : undefined\n }\n\n private async request<T>(path: string, options: RequestOptions = {}): Promise<T> {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n ...options.headers,\n }\n\n const auth = this.getAuthHeader()\n if (auth) {\n headers.Authorization = auth\n }\n\n if (options.credentials) {\n headers['X-App-Key'] = options.credentials.appKey\n headers['X-App-Secret'] = options.credentials.secret\n }\n\n const response = await this.fetchFn(`${this.baseUrl}${path}`, {\n method: options.method ?? 'GET',\n headers,\n body: options.body !== undefined ? JSON.stringify(options.body) : undefined,\n })\n\n if (!response.ok) {\n let body: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n body = await response.json()\n } catch {\n body = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, body)\n }\n\n if (response.status === 204) {\n return undefined as T\n }\n\n return response.json() as Promise<T>\n }\n\n // ── Health ──────────────────────────────────────────────────────────────\n\n health(): Promise<HealthResponse> {\n return this.request('/health')\n }\n\n // ── Platform auth ───────────────────────────────────────────────────────\n\n login(input: LoginInput): Promise<AuthResponse> {\n return this.request('/api/v1/auth/login', { method: 'POST', body: input })\n }\n\n me(): Promise<{ user: User }> {\n return this.request('/api/v1/auth/me')\n }\n\n // ── Applications ────────────────────────────────────────────────────────\n\n listApplications(): Promise<{ apps: Application[] }> {\n return this.request('/api/v1/applications')\n }\n\n createApplication(input: CreateApplicationInput): Promise<{ app: Application }> {\n return this.request('/api/v1/applications', { method: 'POST', body: input })\n }\n\n getApplication(id: string): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}`)\n }\n\n updateApplication(id: string, input: UpdateApplicationInput): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}`, { method: 'PUT', body: input })\n }\n\n deleteApplication(id: string): Promise<{ deleted: boolean; id: string }> {\n return this.request(`/api/v1/applications/${id}`, { method: 'DELETE' })\n }\n\n regenerateSecret(id: string): Promise<{ app: Application }> {\n return this.request(`/api/v1/applications/${id}/regenerate-secret`, {\n method: 'POST',\n })\n }\n\n // ── Data plane ──────────────────────────────────────────────────────────\n\n publishEvent(\n appKey: string,\n credentials: AppCredentials,\n input: PublishEventInput\n ): Promise<PublishEventResponse> {\n return this.request(`/api/v1/apps/${appKey}/events`, {\n method: 'POST',\n body: input,\n credentials,\n })\n }\n\n authorizeChannel(\n appKey: string,\n credentials: AppCredentials,\n input: ChannelAuthInput\n ): Promise<ChannelAuthResponse> {\n return this.request(`/api/v1/apps/${appKey}/auth`, {\n method: 'POST',\n body: input,\n credentials,\n })\n }\n\n issueConnectionToken(\n appKey: string,\n input: ConnectionTokenInput,\n credentials?: AppCredentials\n ): Promise<ConnectionTokenResponse> {\n return fetchConnectionToken({\n baseUrl: this.baseUrl,\n appKey,\n credentials,\n ...input,\n fetch: this.fetchFn,\n })\n }\n}\n","import { resolveBaseUrl } from './config'\nimport { fetchConnectionToken } from './connection-token'\nimport type {\n ArkNotifyConnectionConfig,\n ChannelEventHandler,\n ConnectedMessage,\n ConnectionState,\n EventMessage,\n PresenceMessage,\n ServerMessage,\n SubscribeOptions,\n} from './types'\nimport { isPrivateChannel, appendQueryParams, resolveValue, toWebSocketUrl } from './utils'\n\ntype EventMap = {\n state: (state: ConnectionState) => void\n connected: (message: ConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerMessage) => void\n error: (error: { code: string; message: string }) => void\n close: (event: { code: number; reason: string }) => void\n}\n\ntype EventName = keyof EventMap\n\nexport class ArkNotifyConnection {\n private readonly config: Required<\n Pick<\n ArkNotifyConnectionConfig,\n 'baseUrl' | 'appKey' | 'autoReconnect' | 'reconnectDelayMs' | 'maxReconnectDelayMs'\n >\n > &\n ArkNotifyConnectionConfig\n\n private ws: WebSocket | null = null\n private state: ConnectionState = 'disconnected'\n private connectionId: string | null = null\n private clientId: string | null = null\n private authenticated = false\n private readonly subscribedChannels = new Set<string>()\n private readonly pendingSubscriptions = new Map<string, SubscribeOptions>()\n private readonly listeners = new Map<EventName, Set<EventMap[EventName]>>()\n private reconnectAttempt = 0\n private reconnectTimer: ReturnType<typeof setTimeout> | null = null\n private intentionalClose = false\n private connectPromise: Promise<void> | null = null\n private readonly WebSocketCtor: typeof WebSocket\n\n constructor(config: ArkNotifyConnectionConfig) {\n this.config = {\n autoReconnect: true,\n reconnectDelayMs: 1000,\n maxReconnectDelayMs: 30000,\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n }\n this.WebSocketCtor = config.WebSocket ?? globalThis.WebSocket\n }\n\n getConnectionState(): ConnectionState {\n return this.state\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n getClientId(): string | null {\n return this.clientId\n }\n\n isAuthenticated(): boolean {\n return this.authenticated\n }\n\n getSubscribedChannels(): string[] {\n return [...this.subscribedChannels]\n }\n\n on<E extends EventName>(event: E, handler: EventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends EventName>(event: E, handler: EventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends EventName>(event: E, ...args: Parameters<EventMap[E]>): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<EventMap[E]>) => void)(...args)\n }\n }\n\n private setState(state: ConnectionState): void {\n if (this.state !== state) {\n this.state = state\n this.emit('state', state)\n }\n }\n\n connect(): Promise<void> {\n if (this.ws?.readyState === WebSocket.OPEN || this.ws?.readyState === WebSocket.CONNECTING) {\n return Promise.resolve()\n }\n\n if (this.connectPromise) {\n return this.connectPromise\n }\n\n this.connectPromise = this.doConnect().finally(() => {\n this.connectPromise = null\n })\n\n return this.connectPromise\n }\n\n private async doConnect(): Promise<void> {\n this.intentionalClose = false\n this.clearReconnectTimer()\n this.setState(this.reconnectAttempt > 0 ? 'reconnecting' : 'connecting')\n\n let wsUrl = toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)\n\n let token = resolveValue(this.config.token)\n if (!token && this.config.clientId) {\n const result = await fetchConnectionToken({\n baseUrl: this.config.baseUrl,\n appKey: this.config.appKey,\n credentials: this.config.credentials,\n client_id: this.config.clientId,\n user_data: this.config.userData,\n serverAuthUrl: this.config.serverAuthUrl,\n fetch: this.config.fetch,\n })\n token = result.token\n }\n\n if (token) {\n wsUrl = appendQueryParams(wsUrl, { token })\n } else if (this.config.clientId) {\n wsUrl = appendQueryParams(wsUrl, { clientId: this.config.clientId })\n }\n\n this.ws = new this.WebSocketCtor(wsUrl)\n\n this.ws.onopen = () => {\n this.reconnectAttempt = 0\n }\n\n this.ws.onmessage = (event) => {\n this.handleMessage(event.data as string)\n }\n\n this.ws.onerror = () => {\n this.emit('error', { code: 'websocket_error', message: 'WebSocket error' })\n }\n\n this.ws.onclose = (event) => {\n this.ws = null\n this.connectionId = null\n this.emit('close', { code: event.code, reason: event.reason })\n\n if (!this.intentionalClose && this.config.autoReconnect) {\n this.scheduleReconnect()\n } else {\n this.setState('failed')\n }\n }\n }\n\n disconnect(): void {\n this.intentionalClose = true\n this.clearReconnectTimer()\n this.subscribedChannels.clear()\n this.pendingSubscriptions.clear()\n if (this.ws) {\n this.ws.close()\n this.ws = null\n }\n this.setState('disconnected')\n }\n\n private scheduleReconnect(): void {\n this.setState('reconnecting')\n const delay = Math.min(\n this.config.reconnectDelayMs * 2 ** this.reconnectAttempt,\n this.config.maxReconnectDelayMs\n )\n this.reconnectAttempt++\n this.reconnectTimer = setTimeout(() => void this.connect(), delay)\n }\n\n private clearReconnectTimer(): void {\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer)\n this.reconnectTimer = null\n }\n }\n\n private send(payload: Record<string, unknown>): void {\n if (this.ws?.readyState !== WebSocket.OPEN) {\n throw new Error('WebSocket is not connected')\n }\n this.ws.send(JSON.stringify(payload))\n }\n\n private handleMessage(raw: string): void {\n let message: ServerMessage\n try {\n message = JSON.parse(raw) as ServerMessage\n } catch {\n this.emit('error', { code: 'invalid_json', message: 'Invalid JSON from server' })\n return\n }\n\n this.emit('message', message)\n\n switch (message.type) {\n case 'connected': {\n this.connectionId = message.connection_id\n this.clientId = message.client_id\n this.authenticated = message.authenticated\n this.setState('connected')\n this.emit('connected', message)\n this.resubscribeAll()\n break\n }\n case 'event':\n this.emit('event', message)\n break\n case 'presence':\n this.emit('presence', message)\n break\n case 'subscribed':\n this.subscribedChannels.add(message.channel)\n break\n case 'unsubscribed':\n this.subscribedChannels.delete(message.channel)\n break\n case 'error':\n this.emit('error', { code: message.code, message: message.message })\n break\n case 'ping':\n this.send({ action: 'ping' })\n break\n default:\n break\n }\n }\n\n private resubscribeAll(): void {\n for (const [channel, options] of this.pendingSubscriptions) {\n void this.subscribe(channel, options)\n }\n }\n\n async subscribe(channel: string, options: SubscribeOptions = {}): Promise<void> {\n this.pendingSubscriptions.set(channel, options)\n\n if (this.state !== 'connected' || !this.connectionId) {\n return\n }\n\n const payload: Record<string, unknown> = {\n action: 'subscribe',\n channel,\n }\n\n if (options.history) payload.history = true\n if (options.presence) {\n payload.presence = true\n if (options.presence_data) payload.presence_data = options.presence_data\n }\n\n if (isPrivateChannel(channel)) {\n if (options.auth) {\n payload.auth = options.auth\n } else if (this.config.onPrivateChannelAuth) {\n payload.auth = await this.config.onPrivateChannelAuth(channel, this.connectionId)\n } else {\n throw new Error(\n `Private channel \"${channel}\" requires auth. Provide options.auth or onPrivateChannelAuth.`\n )\n }\n }\n\n this.send(payload)\n }\n\n unsubscribe(channel: string): void {\n this.pendingSubscriptions.delete(channel)\n this.subscribedChannels.delete(channel)\n if (this.state === 'connected') {\n this.send({ action: 'unsubscribe', channel })\n }\n }\n\n publish(channel: string, event: string, data?: unknown): void {\n this.send({ action: 'publish', channel, event, data })\n }\n\n presenceEnter(channel: string, data: Record<string, unknown>): void {\n this.send({ action: 'presence_enter', channel, data })\n }\n\n presenceUpdate(channel: string, data: Record<string, unknown>): void {\n this.send({ action: 'presence_update', channel, data })\n }\n\n presenceLeave(channel: string): void {\n this.send({ action: 'presence_leave', channel })\n }\n\n presenceSync(channel: string): void {\n this.send({ action: 'presence_sync', channel })\n }\n\n ping(): void {\n this.send({ action: 'ping' })\n }\n\n bind(channel: string, event: string, handler: ChannelEventHandler): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: ChannelEventHandler): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n","import { resolveBaseUrl } from './config'\nimport type {\n ArkNotifySSEConfig,\n ConnectedMessage,\n EventMessage,\n PresenceMessage,\n ServerMessage,\n} from './types'\nimport { isPrivateChannel, appendQueryParams, resolveValue } from './utils'\n\ntype SSEEventMap = {\n connected: (message: ConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerMessage) => void\n error: (error: Error) => void\n close: () => void\n}\n\ntype SSEEventName = keyof SSEEventMap\n\nexport class ArkNotifySSE {\n private readonly config: ArkNotifySSEConfig & { baseUrl: string }\n private es: EventSource | null = null\n private connectionId: string | null = null\n private readonly listeners = new Map<SSEEventName, Set<SSEEventMap[SSEEventName]>>()\n private readonly EventSourceCtor: typeof EventSource\n\n constructor(config: ArkNotifySSEConfig) {\n this.config = { ...config, baseUrl: resolveBaseUrl(config.baseUrl) }\n this.EventSourceCtor = config.EventSource ?? globalThis.EventSource\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n on<E extends SSEEventName>(event: E, handler: SSEEventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends SSEEventName>(event: E, handler: SSEEventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends SSEEventName>(event: E, ...args: Parameters<SSEEventMap[E]>): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<SSEEventMap[E]>) => void)(...args)\n }\n }\n\n async connect(): Promise<void> {\n if (this.es) return\n\n const base = this.config.baseUrl.replace(/\\/$/, '')\n const authMap = this.config.auth ? { ...this.config.auth } : {}\n\n const privateChannels = this.config.channels.filter(isPrivateChannel)\n if (privateChannels.length > 0 && this.config.onPrivateChannelAuth && !this.config.auth) {\n // Private SSE channels need auth tokens in the query before connect.\n // Fetch tokens server-side and pass them via the `auth` option, or use WebSocket instead.\n }\n\n const token = resolveValue(this.config.token)\n const streamUrl = appendQueryParams(`${base}/app/${this.config.appKey}/stream`, {\n channels: this.config.channels.join(','),\n token: token || undefined,\n clientId: !token && this.config.clientId ? this.config.clientId : undefined,\n history: this.config.history ? 'true' : undefined,\n user_data: this.config.user_data ? JSON.stringify(this.config.user_data) : undefined,\n auth: Object.keys(authMap).length > 0 ? JSON.stringify(authMap) : undefined,\n })\n\n this.es = new this.EventSourceCtor(streamUrl)\n\n this.es.addEventListener('connected', (e) => {\n const message = JSON.parse(e.data) as ConnectedMessage\n this.connectionId = message.connection_id\n this.emit('connected', message)\n this.emit('message', message)\n })\n\n this.es.addEventListener('event', (e) => {\n const message = JSON.parse(e.data) as EventMessage\n this.emit('event', message)\n this.emit('message', message)\n })\n\n this.es.addEventListener('presence', (e) => {\n const message = JSON.parse(e.data) as PresenceMessage\n this.emit('presence', message)\n this.emit('message', message)\n })\n\n this.es.onerror = () => {\n this.emit('error', new Error('SSE connection error'))\n }\n }\n\n disconnect(): void {\n if (this.es) {\n this.es.close()\n this.es = null\n this.connectionId = null\n this.emit('close')\n }\n }\n\n bind(\n channel: string,\n event: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: (data: unknown, message: EventMessage) => void): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n","import { resolveBaseUrl } from './config'\nimport type {\n AppCredentials,\n ArkNotifyServerStreamConfig,\n EventMessage,\n PresenceMessage,\n ServerErrorMessage,\n ServerStreamConnectedMessage,\n} from './types'\nimport { appendQueryParams, ArkNotifyError, matchesChannelPattern } from './utils'\n\nconst MAX_SERVER_STREAM_SUBSCRIPTIONS = 32\n\nfunction resolveServerStreamSubscriptions(\n config: Pick<ArkNotifyServerStreamConfig, 'subscriptions' | 'channels'>\n): string[] {\n const subscriptions = config.subscriptions ?? config.channels ?? []\n if (subscriptions.length === 0) {\n throw new Error('At least one subscription is required (exact channel, pattern, or *)')\n }\n if (subscriptions.length > MAX_SERVER_STREAM_SUBSCRIPTIONS) {\n throw new Error(`A maximum of ${MAX_SERVER_STREAM_SUBSCRIPTIONS} subscriptions is allowed per stream`)\n }\n return subscriptions\n}\n\ntype ServerStreamEventMap = {\n connected: (message: ServerStreamConnectedMessage) => void\n event: (message: EventMessage) => void\n presence: (message: PresenceMessage) => void\n message: (message: ServerStreamMessage) => void\n error: (error: Error) => void\n close: () => void\n}\n\ntype ServerStreamEventName = keyof ServerStreamEventMap\n\nfunction buildAppCredentialsHeaders(credentials: AppCredentials): Record<string, string> {\n return {\n 'X-App-Key': credentials.appKey,\n 'X-App-Secret': credentials.secret,\n }\n}\n\ntype ServerStreamMessage = ServerStreamConnectedMessage | EventMessage | PresenceMessage | ServerErrorMessage\n\nfunction dispatchSseEvent(\n data: string,\n handlers: {\n onConnected: (message: ServerStreamConnectedMessage) => void\n onEvent: (message: EventMessage) => void\n onPresence: (message: PresenceMessage) => void\n onMessage: (message: ServerStreamMessage) => void\n }\n): void {\n if (!data) return\n\n let parsed: ServerStreamMessage\n try {\n parsed = JSON.parse(data) as ServerStreamMessage\n } catch {\n return\n }\n\n if (parsed.type === 'connected') {\n handlers.onConnected(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n if (parsed.type === 'event') {\n handlers.onEvent(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n if (parsed.type === 'presence') {\n handlers.onPresence(parsed)\n handlers.onMessage(parsed)\n return\n }\n\n handlers.onMessage(parsed)\n}\n\nasync function readSseStream(\n body: ReadableStream<Uint8Array>,\n onSseData: (data: string) => void,\n signal: AbortSignal\n): Promise<void> {\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n let currentEvent: string | null = null\n let dataLines: string[] = []\n\n const flushEvent = () => {\n if (dataLines.length === 0 && currentEvent === null) return\n onSseData(dataLines.join('\\n'))\n currentEvent = null\n dataLines = []\n }\n\n try {\n while (!signal.aborted) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n const lines = buffer.split('\\n')\n buffer = lines.pop() ?? ''\n\n for (const rawLine of lines) {\n const line = rawLine.endsWith('\\r') ? rawLine.slice(0, -1) : rawLine\n\n if (line === '') {\n flushEvent()\n continue\n }\n\n if (line.startsWith(':')) continue\n\n if (line.startsWith('event:')) {\n currentEvent = line.slice(6).trimStart()\n continue\n }\n\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n }\n }\n }\n\n if (buffer.length > 0) {\n const line = buffer.endsWith('\\r') ? buffer.slice(0, -1) : buffer\n if (line.startsWith('data:')) {\n dataLines.push(line.slice(5).trimStart())\n }\n }\n\n flushEvent()\n } finally {\n reader.releaseLock()\n }\n}\n\nexport class ArkNotifyServerStream {\n private readonly config: ArkNotifyServerStreamConfig & { baseUrl: string; subscriptions: string[] }\n private readonly fetchFn: typeof fetch\n private readonly listeners = new Map<\n ServerStreamEventName,\n Set<ServerStreamEventMap[ServerStreamEventName]>\n >()\n private abortController: AbortController | null = null\n private connectionId: string | null = null\n private connectedMessage: ServerStreamConnectedMessage | null = null\n private connecting = false\n\n constructor(config: ArkNotifyServerStreamConfig) {\n this.config = {\n ...config,\n baseUrl: resolveBaseUrl(config.baseUrl),\n subscriptions: resolveServerStreamSubscriptions(config),\n }\n this.fetchFn = config.fetch ?? globalThis.fetch.bind(globalThis)\n }\n\n getConnectionId(): string | null {\n return this.connectionId\n }\n\n getSubscriptions(): string[] {\n return this.connectedMessage?.subscriptions ?? [...this.config.subscriptions]\n }\n\n getChannels(): string[] {\n return this.connectedMessage?.channels ?? []\n }\n\n getPatterns(): string[] {\n return this.connectedMessage?.patterns ?? []\n }\n\n on<E extends ServerStreamEventName>(event: E, handler: ServerStreamEventMap[E]): () => void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, new Set())\n }\n this.listeners.get(event)!.add(handler)\n return () => this.off(event, handler)\n }\n\n off<E extends ServerStreamEventName>(event: E, handler: ServerStreamEventMap[E]): void {\n this.listeners.get(event)?.delete(handler)\n }\n\n private emit<E extends ServerStreamEventName>(\n event: E,\n ...args: Parameters<ServerStreamEventMap[E]>\n ): void {\n for (const handler of this.listeners.get(event) ?? []) {\n ;(handler as (...a: Parameters<ServerStreamEventMap[E]>) => void)(...args)\n }\n }\n\n async connect(): Promise<void> {\n if (this.abortController || this.connecting) return\n\n this.connecting = true\n const abortController = new AbortController()\n this.abortController = abortController\n\n const base = this.config.baseUrl.replace(/\\/$/, '')\n const streamUrl = appendQueryParams(\n `${base}/api/v1/apps/${this.config.appKey}/server-stream`,\n {\n channels: this.config.subscriptions.join(','),\n history: this.config.history ? 'true' : undefined,\n }\n )\n\n try {\n const response = await this.fetchFn(streamUrl, {\n method: 'GET',\n headers: {\n Accept: 'text/event-stream',\n ...buildAppCredentialsHeaders(this.config.credentials),\n },\n signal: abortController.signal,\n })\n\n if (!response.ok) {\n let body: { error: string; message: string; reason?: string; retryAfterSec?: number }\n try {\n body = await response.json()\n } catch {\n body = { error: 'request_failed', message: response.statusText }\n }\n throw new ArkNotifyError(response.status, body)\n }\n\n if (!response.body) {\n throw new Error('Server stream response has no body')\n }\n\n void this.consumeStream(response.body, abortController)\n } catch (err) {\n if (abortController.signal.aborted) return\n this.abortController = null\n this.emit('error', err instanceof Error ? err : new Error(String(err)))\n this.emit('close')\n } finally {\n this.connecting = false\n }\n }\n\n private async consumeStream(body: ReadableStream<Uint8Array>, abortController: AbortController): Promise<void> {\n try {\n await readSseStream(\n body,\n (data) => {\n dispatchSseEvent(data, {\n onConnected: (message) => {\n this.connectionId = message.connection_id\n this.connectedMessage = message\n this.emit('connected', message)\n },\n onEvent: (message) => this.emit('event', message),\n onPresence: (message) => this.emit('presence', message),\n onMessage: (message) => this.emit('message', message),\n })\n },\n abortController.signal\n )\n } catch (err) {\n if (abortController.signal.aborted) return\n this.emit('error', err instanceof Error ? err : new Error(String(err)))\n } finally {\n if (this.abortController === abortController) {\n this.abortController = null\n this.connectionId = null\n this.connectedMessage = null\n this.emit('close')\n }\n }\n }\n\n disconnect(): void {\n if (!this.abortController) return\n this.abortController.abort()\n }\n\n bind(\n channel: string,\n event: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAll(channel: string, handler: (data: unknown, message: EventMessage) => void): () => void {\n const listener = (message: EventMessage) => {\n if (message.channel === channel) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindMatching(\n pattern: string,\n event: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (matchesChannelPattern(message.channel, pattern) && message.event === event) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n\n bindAllMatching(\n pattern: string,\n handler: (data: unknown, message: EventMessage) => void\n ): () => void {\n const listener = (message: EventMessage) => {\n if (matchesChannelPattern(message.channel, pattern)) {\n handler(message.data, message)\n }\n }\n return this.on('event', listener)\n }\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { A as ArkNotifyClient, a as ArkNotifyConnection, b as ArkNotifyError, c as ArkNotifyGlobalConfig, d as ArkNotifySSE, D as DEFAULT_BASE_URL, e as appendQueryParams, f as configureArkNotify, i as isPrivateChannel, r as resolveBaseUrl,
|
|
2
|
-
export { A as ArkNotifyServerStream } from './server-stream-
|
|
3
|
-
import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './types-
|
|
4
|
-
export { b as ApiError, c as Application, d as ArkNotifyClientConfig, e as ArkNotifyConnectionConfig, f as ArkNotifySSEConfig, g as ArkNotifyServerStreamConfig, h as AuthResponse, i as ChannelAuthInput, j as ChannelAuthResponse, k as ChannelEventHandler, l as ChannelHandlers, m as ConnectedMessage, n as ConnectionCapabilities, o as ConnectionState, p as CreateApplicationInput, q as CreateAuthorizedServerAuthResponseOptions, E as EventMessage, H as HandleServerAuthOptions, r as HealthResponse, L as LoginInput, P as PingMessage, s as PongMessage, t as PresenceAction, u as PresenceLeftMessage, v as PresenceMemberInfo, w as PresenceMessage, x as PresenceUpdatedMessage, y as PrivateChannelAuthHandler, z as PublishEventInput, B as PublishEventResponse, D as PublishedMessage, S as ServerAuthAllowedResponse, F as ServerAuthApprovedResponse, G as ServerAuthDecision, I as ServerAuthDeniedResponse, J as ServerAuthRequest, K as ServerAuthResponse, M as ServerAuthTokenResponse, N as ServerErrorMessage, O as ServerMessage, Q as ServerStreamConnectedMessage, R as SubscribeOptions, T as SubscribedMessage, U as UnsubscribedMessage, V as UpdateApplicationInput, W as User, X as UserRole } from './types-
|
|
1
|
+
export { A as ArkNotifyClient, a as ArkNotifyConnection, b as ArkNotifyError, c as ArkNotifyGlobalConfig, d as ArkNotifySSE, D as DEFAULT_BASE_URL, e as appendQueryParams, f as configureArkNotify, i as isAllChannelsSubscription, g as isPrivateChannel, h as isServerStreamPattern, m as matchesChannelPattern, r as resolveBaseUrl, j as resolveValue, t as toWebSocketUrl } from './utils-CCt9kuCJ.cjs';
|
|
2
|
+
export { A as ArkNotifyServerStream } from './server-stream-CxgR5Ym7.cjs';
|
|
3
|
+
import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './types-BHemo22a.cjs';
|
|
4
|
+
export { b as ApiError, c as Application, d as ArkNotifyClientConfig, e as ArkNotifyConnectionConfig, f as ArkNotifySSEConfig, g as ArkNotifyServerStreamConfig, h as AuthResponse, i as ChannelAuthInput, j as ChannelAuthResponse, k as ChannelEventHandler, l as ChannelHandlers, m as ConnectedMessage, n as ConnectionCapabilities, o as ConnectionState, p as CreateApplicationInput, q as CreateAuthorizedServerAuthResponseOptions, E as EventMessage, H as HandleServerAuthOptions, r as HealthResponse, L as LoginInput, P as PingMessage, s as PongMessage, t as PresenceAction, u as PresenceLeftMessage, v as PresenceMemberInfo, w as PresenceMessage, x as PresenceUpdatedMessage, y as PrivateChannelAuthHandler, z as PublishEventInput, B as PublishEventResponse, D as PublishedMessage, S as ServerAuthAllowedResponse, F as ServerAuthApprovedResponse, G as ServerAuthDecision, I as ServerAuthDeniedResponse, J as ServerAuthRequest, K as ServerAuthResponse, M as ServerAuthTokenResponse, N as ServerErrorMessage, O as ServerMessage, Q as ServerStreamConnectedMessage, R as SubscribeOptions, T as SubscribedMessage, U as UnsubscribedMessage, V as UpdateApplicationInput, W as User, X as UserRole } from './types-BHemo22a.cjs';
|
|
5
5
|
|
|
6
6
|
interface FetchConnectionTokenOptions extends ConnectionTokenInput {
|
|
7
7
|
baseUrl?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { A as ArkNotifyClient, a as ArkNotifyConnection, b as ArkNotifyError, c as ArkNotifyGlobalConfig, d as ArkNotifySSE, D as DEFAULT_BASE_URL, e as appendQueryParams, f as configureArkNotify, i as isPrivateChannel, r as resolveBaseUrl,
|
|
2
|
-
export { A as ArkNotifyServerStream } from './server-stream-
|
|
3
|
-
import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './types-
|
|
4
|
-
export { b as ApiError, c as Application, d as ArkNotifyClientConfig, e as ArkNotifyConnectionConfig, f as ArkNotifySSEConfig, g as ArkNotifyServerStreamConfig, h as AuthResponse, i as ChannelAuthInput, j as ChannelAuthResponse, k as ChannelEventHandler, l as ChannelHandlers, m as ConnectedMessage, n as ConnectionCapabilities, o as ConnectionState, p as CreateApplicationInput, q as CreateAuthorizedServerAuthResponseOptions, E as EventMessage, H as HandleServerAuthOptions, r as HealthResponse, L as LoginInput, P as PingMessage, s as PongMessage, t as PresenceAction, u as PresenceLeftMessage, v as PresenceMemberInfo, w as PresenceMessage, x as PresenceUpdatedMessage, y as PrivateChannelAuthHandler, z as PublishEventInput, B as PublishEventResponse, D as PublishedMessage, S as ServerAuthAllowedResponse, F as ServerAuthApprovedResponse, G as ServerAuthDecision, I as ServerAuthDeniedResponse, J as ServerAuthRequest, K as ServerAuthResponse, M as ServerAuthTokenResponse, N as ServerErrorMessage, O as ServerMessage, Q as ServerStreamConnectedMessage, R as SubscribeOptions, T as SubscribedMessage, U as UnsubscribedMessage, V as UpdateApplicationInput, W as User, X as UserRole } from './types-
|
|
1
|
+
export { A as ArkNotifyClient, a as ArkNotifyConnection, b as ArkNotifyError, c as ArkNotifyGlobalConfig, d as ArkNotifySSE, D as DEFAULT_BASE_URL, e as appendQueryParams, f as configureArkNotify, i as isAllChannelsSubscription, g as isPrivateChannel, h as isServerStreamPattern, m as matchesChannelPattern, r as resolveBaseUrl, j as resolveValue, t as toWebSocketUrl } from './utils-BznZ_tYI.js';
|
|
2
|
+
export { A as ArkNotifyServerStream } from './server-stream-DNd6ENoz.js';
|
|
3
|
+
import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './types-BHemo22a.js';
|
|
4
|
+
export { b as ApiError, c as Application, d as ArkNotifyClientConfig, e as ArkNotifyConnectionConfig, f as ArkNotifySSEConfig, g as ArkNotifyServerStreamConfig, h as AuthResponse, i as ChannelAuthInput, j as ChannelAuthResponse, k as ChannelEventHandler, l as ChannelHandlers, m as ConnectedMessage, n as ConnectionCapabilities, o as ConnectionState, p as CreateApplicationInput, q as CreateAuthorizedServerAuthResponseOptions, E as EventMessage, H as HandleServerAuthOptions, r as HealthResponse, L as LoginInput, P as PingMessage, s as PongMessage, t as PresenceAction, u as PresenceLeftMessage, v as PresenceMemberInfo, w as PresenceMessage, x as PresenceUpdatedMessage, y as PrivateChannelAuthHandler, z as PublishEventInput, B as PublishEventResponse, D as PublishedMessage, S as ServerAuthAllowedResponse, F as ServerAuthApprovedResponse, G as ServerAuthDecision, I as ServerAuthDeniedResponse, J as ServerAuthRequest, K as ServerAuthResponse, M as ServerAuthTokenResponse, N as ServerErrorMessage, O as ServerMessage, Q as ServerStreamConnectedMessage, R as SubscribeOptions, T as SubscribedMessage, U as UnsubscribedMessage, V as UpdateApplicationInput, W as User, X as UserRole } from './types-BHemo22a.js';
|
|
5
5
|
|
|
6
6
|
interface FetchConnectionTokenOptions extends ConnectionTokenInput {
|
|
7
7
|
baseUrl?: string;
|