@emmanuel-nike/ark-notify-js 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,15 +1,19 @@
1
- import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './utils-Cw2SnD6p.js';
2
- export { b as AdminChannel, c as AdminChannelsResponse, d as AdminConnection, e as ApiError, f as Application, g as ArkNotifyClient, h as ArkNotifyClientConfig, i as ArkNotifyConnection, j as ArkNotifyConnectionConfig, k as ArkNotifyError, l as ArkNotifyGlobalConfig, m as ArkNotifySSE, n as ArkNotifySSEConfig, o as AuthResponse, p as ChannelAuthInput, q as ChannelAuthResponse, r as ChannelEventHandler, s as ChannelHandlers, t as ConnectedMessage, u as ConnectionCapabilities, v as ConnectionState, w as CreateApplicationInput, D as DEFAULT_BASE_URL, E as EventMessage, H as HealthResponse, L as LoginInput, P as PingMessage, x as PongMessage, y as PresenceAction, z as PresenceLeftMessage, B as PresenceMember, F as PresenceMemberInfo, G as PresenceMessage, I as PresenceUpdatedMessage, J as PrivateChannelAuthHandler, K as PublishEventInput, M as PublishEventResponse, N as PublishedMessage, S as ServerErrorMessage, O as ServerMessage, Q as SubscribeOptions, R as SubscribedMessage, U as UnsubscribedMessage, T as UpdateApplicationInput, V as User, W as UserRole, X as configureArkNotify, Y as isPrivateChannel, Z as resolveBaseUrl, _ as resolveValue, $ as toWebSocketUrl } from './utils-Cw2SnD6p.js';
1
+ import { C as ConnectionTokenInput, A as AppCredentials, a as ConnectionTokenResponse } from './utils-Zj1Ees3H.js';
2
+ export { b as AdminChannel, c as AdminChannelsResponse, d as AdminConnection, e as ApiError, f as Application, g as ArkNotifyClient, h as ArkNotifyClientConfig, i as ArkNotifyConnection, j as ArkNotifyConnectionConfig, k as ArkNotifyError, l as ArkNotifyGlobalConfig, m as ArkNotifySSE, n as ArkNotifySSEConfig, o as AuthResponse, p as ChannelAuthInput, q as ChannelAuthResponse, r as ChannelEventHandler, s as ChannelHandlers, t as ConnectedMessage, u as ConnectionCapabilities, v as ConnectionState, w as CreateApplicationInput, D as DEFAULT_BASE_URL, E as EventMessage, H as HealthResponse, L as LoginInput, P as PingMessage, x as PongMessage, y as PresenceAction, z as PresenceLeftMessage, B as PresenceMember, F as PresenceMemberInfo, G as PresenceMessage, I as PresenceUpdatedMessage, J as PrivateChannelAuthHandler, K as PublishEventInput, M as PublishEventResponse, N as PublishedMessage, S as ServerErrorMessage, O as ServerMessage, Q as SubscribeOptions, R as SubscribedMessage, U as UnsubscribedMessage, T as UpdateApplicationInput, V as User, W as UserRole, X as configureArkNotify, Y as isPrivateChannel, Z as resolveBaseUrl, _ as resolveValue, $ as toWebSocketUrl } from './utils-Zj1Ees3H.js';
3
3
 
4
4
  interface FetchConnectionTokenOptions extends ConnectionTokenInput {
5
5
  baseUrl?: string;
6
6
  appKey: string;
7
- credentials: AppCredentials;
7
+ /** Required unless the application has a serverAuthUrl (or one is passed in the request). */
8
+ credentials?: AppCredentials;
8
9
  fetch?: typeof fetch;
9
10
  }
10
11
  /**
11
12
  * Request a signed connection token from the Ark Notify API.
12
- * Requires app credentials — use from your backend, not in browser code.
13
+ *
14
+ * Authentication depends on server auth configuration:
15
+ * - Application or request has a `serverAuthUrl`: public `appKey` only (frontend-safe).
16
+ * - No `serverAuthUrl`: `credentials` with app key + secret (backend-only).
13
17
  */
14
18
  declare function fetchConnectionToken(options: FetchConnectionTokenOptions): Promise<ConnectionTokenResponse>;
15
19
 
package/dist/index.js CHANGED
@@ -33,6 +33,85 @@ function isPrivateChannel(channel) {
33
33
  return channel.startsWith("private-");
34
34
  }
35
35
 
36
+ // src/connection-token.ts
37
+ function requiresAppSecret(options) {
38
+ if ("serverAuthUrl" in options) {
39
+ const value = options.serverAuthUrl;
40
+ return value === null || value === "";
41
+ }
42
+ if ("server_auth_url" in options) {
43
+ const value = options.server_auth_url;
44
+ return value === null || value === "";
45
+ }
46
+ return false;
47
+ }
48
+ function buildConnectionTokenRequest(options) {
49
+ const {
50
+ baseUrl,
51
+ appKey,
52
+ credentials,
53
+ client_id,
54
+ clientId,
55
+ user_data,
56
+ userData,
57
+ ttl,
58
+ capabilities,
59
+ serverAuthUrl,
60
+ server_auth_url
61
+ } = options;
62
+ const resolvedClientId = client_id ?? clientId;
63
+ if (!resolvedClientId) {
64
+ throw new Error("client_id is required to fetch a connection token");
65
+ }
66
+ if (requiresAppSecret(options) && !credentials) {
67
+ throw new Error(
68
+ "credentials are required when serverAuthUrl is explicitly set to null"
69
+ );
70
+ }
71
+ const body = {
72
+ client_id: resolvedClientId,
73
+ user_data: user_data ?? userData,
74
+ ttl,
75
+ capabilities
76
+ };
77
+ if ("serverAuthUrl" in options) {
78
+ body.serverAuthUrl = serverAuthUrl;
79
+ } else if ("server_auth_url" in options) {
80
+ body.server_auth_url = server_auth_url;
81
+ }
82
+ const headers = {
83
+ "Content-Type": "application/json"
84
+ };
85
+ if (credentials) {
86
+ headers["X-App-Key"] = credentials.appKey;
87
+ headers["X-App-Secret"] = credentials.secret;
88
+ }
89
+ return {
90
+ url: `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`,
91
+ headers,
92
+ body
93
+ };
94
+ }
95
+ async function fetchConnectionToken(options) {
96
+ const { fetch: fetchFn = globalThis.fetch.bind(globalThis) } = options;
97
+ const { url, headers, body } = buildConnectionTokenRequest(options);
98
+ const response = await fetchFn(url, {
99
+ method: "POST",
100
+ headers,
101
+ body: JSON.stringify(body)
102
+ });
103
+ if (!response.ok) {
104
+ let errorBody;
105
+ try {
106
+ errorBody = await response.json();
107
+ } catch {
108
+ errorBody = { error: "request_failed", message: response.statusText };
109
+ }
110
+ throw new ArkNotifyError(response.status, errorBody);
111
+ }
112
+ return response.json();
113
+ }
114
+
36
115
  // src/client.ts
37
116
  var ArkNotifyClient = class {
38
117
  constructor(config) {
@@ -130,63 +209,17 @@ var ArkNotifyClient = class {
130
209
  credentials
131
210
  });
132
211
  }
133
- issueConnectionToken(appKey, credentials, input) {
134
- return this.request(`/api/v1/apps/${appKey}/connection-token`, {
135
- method: "POST",
136
- body: input,
137
- credentials
212
+ issueConnectionToken(appKey, input, credentials) {
213
+ return fetchConnectionToken({
214
+ baseUrl: this.baseUrl,
215
+ appKey,
216
+ credentials,
217
+ ...input,
218
+ fetch: this.fetchFn
138
219
  });
139
220
  }
140
221
  };
141
222
 
142
- // src/connection-token.ts
143
- async function fetchConnectionToken(options) {
144
- const {
145
- baseUrl,
146
- appKey,
147
- credentials,
148
- fetch: fetchFn = globalThis.fetch.bind(globalThis),
149
- client_id,
150
- clientId,
151
- user_data,
152
- userData,
153
- ttl,
154
- capabilities,
155
- serverAuthUrl
156
- } = options;
157
- const resolvedClientId = client_id ?? clientId;
158
- if (!resolvedClientId) {
159
- throw new Error("client_id is required to fetch a connection token");
160
- }
161
- const body = {
162
- client_id: resolvedClientId,
163
- user_data: user_data ?? userData,
164
- ttl,
165
- capabilities,
166
- serverAuthUrl
167
- };
168
- const url = `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`;
169
- const response = await fetchFn(url, {
170
- method: "POST",
171
- headers: {
172
- "Content-Type": "application/json",
173
- "X-App-Key": credentials.appKey,
174
- "X-App-Secret": credentials.secret
175
- },
176
- body: JSON.stringify(body)
177
- });
178
- if (!response.ok) {
179
- let errorBody;
180
- try {
181
- errorBody = await response.json();
182
- } catch {
183
- errorBody = { error: "request_failed", message: response.statusText };
184
- }
185
- throw new ArkNotifyError(response.status, errorBody);
186
- }
187
- return response.json();
188
- }
189
-
190
223
  // src/connection.ts
191
224
  var ArkNotifyConnection = class {
192
225
  constructor(config) {
@@ -267,13 +300,14 @@ var ArkNotifyConnection = class {
267
300
  toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)
268
301
  );
269
302
  let token = resolveValue(this.config.token);
270
- if (!token && this.config.clientId && this.config.credentials) {
303
+ if (!token && this.config.clientId) {
271
304
  const result = await fetchConnectionToken({
272
305
  baseUrl: this.config.baseUrl,
273
306
  appKey: this.config.appKey,
274
307
  credentials: this.config.credentials,
275
308
  client_id: this.config.clientId,
276
309
  user_data: this.config.user_data,
310
+ serverAuthUrl: this.config.serverAuthUrl,
277
311
  fetch: this.config.fetch
278
312
  });
279
313
  token = result.token;
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/config.ts","../src/utils.ts","../src/client.ts","../src/connection-token.ts","../src/connection.ts","../src/sse.ts"],"names":[],"mappings":"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","file":"index.js","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 url = new URL(path, baseUrl)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'\n return url.toString()\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 { ArkNotifyError } from './utils'\nimport type {\n AdminChannelsResponse,\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'\nimport { resolveValue } from './utils'\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: 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(\n id: string,\n input: UpdateApplicationInput\n ): 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 // ── System admin ────────────────────────────────────────────────────────\n\n adminChannels(): Promise<AdminChannelsResponse> {\n return this.request('/api/v1/admin/channels')\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 credentials: AppCredentials,\n input: ConnectionTokenInput\n ): Promise<ConnectionTokenResponse> {\n return this.request(`/api/v1/apps/${appKey}/connection-token`, {\n method: 'POST',\n body: input,\n credentials,\n })\n }\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 credentials: AppCredentials\n fetch?: typeof fetch\n}\n\n/**\n * Request a signed connection token from the Ark Notify API.\n * Requires app credentials — use from your backend, not in browser code.\n */\nexport async function fetchConnectionToken(\n options: FetchConnectionTokenOptions\n): Promise<ConnectionTokenResponse> {\n const {\n baseUrl,\n appKey,\n credentials,\n fetch: fetchFn = globalThis.fetch.bind(globalThis),\n client_id,\n clientId,\n user_data,\n userData,\n ttl,\n capabilities,\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 const body: ConnectionTokenInput = {\n client_id: resolvedClientId,\n user_data: user_data ?? userData,\n ttl,\n capabilities,\n serverAuthUrl,\n }\n\n const url = `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`\n const response = await fetchFn(url, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'X-App-Key': credentials.appKey,\n 'X-App-Secret': credentials.secret,\n },\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 type {\n ArkNotifyConnectionConfig,\n ChannelEventHandler,\n ConnectedMessage,\n ConnectionState,\n EventMessage,\n PresenceMessage,\n ServerMessage,\n SubscribeOptions,\n} from './types'\nimport { isPrivateChannel, 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 subscribedChannels = new Set<string>()\n private pendingSubscriptions = new Map<string, SubscribeOptions>()\n private 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 as EventMap[EventName])\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 as EventMap[EventName])\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 const url = new URL(\n toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)\n )\n\n let token = resolveValue(this.config.token)\n if (!token && this.config.clientId && this.config.credentials) {\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.user_data,\n fetch: this.config.fetch,\n })\n token = result.token\n }\n\n if (token) {\n url.searchParams.set('token', token)\n } else if (this.config.clientId) {\n url.searchParams.set('clientId', this.config.clientId)\n }\n\n this.ws = new this.WebSocketCtor(url.toString())\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, 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 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 as SSEEventMap[SSEEventName])\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 as SSEEventMap[SSEEventName])\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 url = new URL(`${base}/app/${this.config.appKey}/stream`)\n url.searchParams.set('channels', this.config.channels.join(','))\n\n const token = resolveValue(this.config.token)\n if (token) {\n url.searchParams.set('token', token)\n } else if (this.config.clientId) {\n url.searchParams.set('clientId', this.config.clientId)\n }\n\n if (this.config.history) {\n url.searchParams.set('history', 'true')\n }\n\n if (this.config.user_data) {\n url.searchParams.set('user_data', JSON.stringify(this.config.user_data))\n }\n\n let 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 if (Object.keys(authMap).length > 0) {\n url.searchParams.set('auth', JSON.stringify(authMap))\n }\n\n this.es = new this.EventSourceCtor(url.toString())\n\n this.es.addEventListener('connected', (e) => {\n const message = JSON.parse((e as MessageEvent).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 as MessageEvent).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 as MessageEvent).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(channel: string, event: string, handler: (data: unknown, message: EventMessage) => void): () => 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"],"names":[],"mappings":"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","file":"index.js","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 url = new URL(path, baseUrl)\n url.protocol = url.protocol === 'https:' ? 'wss:' : 'ws:'\n return url.toString()\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(options: FetchConnectionTokenOptions): {\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 serverAuthUrl,\n server_auth_url,\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(\n 'credentials are required when serverAuthUrl is explicitly set to null'\n )\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 AdminChannelsResponse,\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: 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(\n id: string,\n input: UpdateApplicationInput\n ): 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 // ── System admin ────────────────────────────────────────────────────────\n\n adminChannels(): Promise<AdminChannelsResponse> {\n return this.request('/api/v1/admin/channels')\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, 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 subscribedChannels = new Set<string>()\n private pendingSubscriptions = new Map<string, SubscribeOptions>()\n private 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 as EventMap[EventName])\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 as EventMap[EventName])\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 const url = new URL(\n toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)\n )\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.user_data,\n serverAuthUrl: this.config.serverAuthUrl,\n fetch: this.config.fetch,\n })\n token = result.token\n }\n\n if (token) {\n url.searchParams.set('token', token)\n } else if (this.config.clientId) {\n url.searchParams.set('clientId', this.config.clientId)\n }\n\n this.ws = new this.WebSocketCtor(url.toString())\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, 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 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 as SSEEventMap[SSEEventName])\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 as SSEEventMap[SSEEventName])\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 url = new URL(`${base}/app/${this.config.appKey}/stream`)\n url.searchParams.set('channels', this.config.channels.join(','))\n\n const token = resolveValue(this.config.token)\n if (token) {\n url.searchParams.set('token', token)\n } else if (this.config.clientId) {\n url.searchParams.set('clientId', this.config.clientId)\n }\n\n if (this.config.history) {\n url.searchParams.set('history', 'true')\n }\n\n if (this.config.user_data) {\n url.searchParams.set('user_data', JSON.stringify(this.config.user_data))\n }\n\n let 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 if (Object.keys(authMap).length > 0) {\n url.searchParams.set('auth', JSON.stringify(authMap))\n }\n\n this.es = new this.EventSourceCtor(url.toString())\n\n this.es.addEventListener('connected', (e) => {\n const message = JSON.parse((e as MessageEvent).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 as MessageEvent).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 as MessageEvent).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(channel: string, event: string, handler: (data: unknown, message: EventMessage) => void): () => 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"]}
@@ -38,6 +38,85 @@ function isPrivateChannel(channel) {
38
38
  return channel.startsWith("private-");
39
39
  }
40
40
 
41
+ // src/connection-token.ts
42
+ function requiresAppSecret(options) {
43
+ if ("serverAuthUrl" in options) {
44
+ const value = options.serverAuthUrl;
45
+ return value === null || value === "";
46
+ }
47
+ if ("server_auth_url" in options) {
48
+ const value = options.server_auth_url;
49
+ return value === null || value === "";
50
+ }
51
+ return false;
52
+ }
53
+ function buildConnectionTokenRequest(options) {
54
+ const {
55
+ baseUrl,
56
+ appKey,
57
+ credentials,
58
+ client_id,
59
+ clientId,
60
+ user_data,
61
+ userData,
62
+ ttl,
63
+ capabilities,
64
+ serverAuthUrl,
65
+ server_auth_url
66
+ } = options;
67
+ const resolvedClientId = client_id ?? clientId;
68
+ if (!resolvedClientId) {
69
+ throw new Error("client_id is required to fetch a connection token");
70
+ }
71
+ if (requiresAppSecret(options) && !credentials) {
72
+ throw new Error(
73
+ "credentials are required when serverAuthUrl is explicitly set to null"
74
+ );
75
+ }
76
+ const body = {
77
+ client_id: resolvedClientId,
78
+ user_data: user_data ?? userData,
79
+ ttl,
80
+ capabilities
81
+ };
82
+ if ("serverAuthUrl" in options) {
83
+ body.serverAuthUrl = serverAuthUrl;
84
+ } else if ("server_auth_url" in options) {
85
+ body.server_auth_url = server_auth_url;
86
+ }
87
+ const headers = {
88
+ "Content-Type": "application/json"
89
+ };
90
+ if (credentials) {
91
+ headers["X-App-Key"] = credentials.appKey;
92
+ headers["X-App-Secret"] = credentials.secret;
93
+ }
94
+ return {
95
+ url: `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`,
96
+ headers,
97
+ body
98
+ };
99
+ }
100
+ async function fetchConnectionToken(options) {
101
+ const { fetch: fetchFn = globalThis.fetch.bind(globalThis) } = options;
102
+ const { url, headers, body } = buildConnectionTokenRequest(options);
103
+ const response = await fetchFn(url, {
104
+ method: "POST",
105
+ headers,
106
+ body: JSON.stringify(body)
107
+ });
108
+ if (!response.ok) {
109
+ let errorBody;
110
+ try {
111
+ errorBody = await response.json();
112
+ } catch {
113
+ errorBody = { error: "request_failed", message: response.statusText };
114
+ }
115
+ throw new ArkNotifyError(response.status, errorBody);
116
+ }
117
+ return response.json();
118
+ }
119
+
41
120
  // src/client.ts
42
121
  var ArkNotifyClient = class {
43
122
  constructor(config) {
@@ -135,63 +214,17 @@ var ArkNotifyClient = class {
135
214
  credentials
136
215
  });
137
216
  }
138
- issueConnectionToken(appKey, credentials, input) {
139
- return this.request(`/api/v1/apps/${appKey}/connection-token`, {
140
- method: "POST",
141
- body: input,
142
- credentials
217
+ issueConnectionToken(appKey, input, credentials) {
218
+ return fetchConnectionToken({
219
+ baseUrl: this.baseUrl,
220
+ appKey,
221
+ credentials,
222
+ ...input,
223
+ fetch: this.fetchFn
143
224
  });
144
225
  }
145
226
  };
146
227
 
147
- // src/connection-token.ts
148
- async function fetchConnectionToken(options) {
149
- const {
150
- baseUrl,
151
- appKey,
152
- credentials,
153
- fetch: fetchFn = globalThis.fetch.bind(globalThis),
154
- client_id,
155
- clientId,
156
- user_data,
157
- userData,
158
- ttl,
159
- capabilities,
160
- serverAuthUrl
161
- } = options;
162
- const resolvedClientId = client_id ?? clientId;
163
- if (!resolvedClientId) {
164
- throw new Error("client_id is required to fetch a connection token");
165
- }
166
- const body = {
167
- client_id: resolvedClientId,
168
- user_data: user_data ?? userData,
169
- ttl,
170
- capabilities,
171
- serverAuthUrl
172
- };
173
- const url = `${resolveBaseUrl(baseUrl)}/api/v1/apps/${appKey}/connection-token`;
174
- const response = await fetchFn(url, {
175
- method: "POST",
176
- headers: {
177
- "Content-Type": "application/json",
178
- "X-App-Key": credentials.appKey,
179
- "X-App-Secret": credentials.secret
180
- },
181
- body: JSON.stringify(body)
182
- });
183
- if (!response.ok) {
184
- let errorBody;
185
- try {
186
- errorBody = await response.json();
187
- } catch {
188
- errorBody = { error: "request_failed", message: response.statusText };
189
- }
190
- throw new ArkNotifyError(response.status, errorBody);
191
- }
192
- return response.json();
193
- }
194
-
195
228
  // src/connection.ts
196
229
  var ArkNotifyConnection = class {
197
230
  constructor(config) {
@@ -272,13 +305,14 @@ var ArkNotifyConnection = class {
272
305
  toWebSocketUrl(this.config.baseUrl, `/app/${this.config.appKey}`)
273
306
  );
274
307
  let token = resolveValue(this.config.token);
275
- if (!token && this.config.clientId && this.config.credentials) {
308
+ if (!token && this.config.clientId) {
276
309
  const result = await fetchConnectionToken({
277
310
  baseUrl: this.config.baseUrl,
278
311
  appKey: this.config.appKey,
279
312
  credentials: this.config.credentials,
280
313
  client_id: this.config.clientId,
281
314
  user_data: this.config.user_data,
315
+ serverAuthUrl: this.config.serverAuthUrl,
282
316
  fetch: this.config.fetch
283
317
  });
284
318
  token = result.token;
@@ -567,7 +601,7 @@ function ArkNotifyProvider({
567
601
  }) {
568
602
  const resolvedBaseUrl = react.useMemo(() => resolveBaseUrl(baseUrl), [baseUrl]);
569
603
  const clientRef = react.useRef(null);
570
- clientRef.current ?? (clientRef.current = new ArkNotifyClient({ baseUrl: resolvedBaseUrl, token, fetch: fetchFn }));
604
+ clientRef.current ?? (clientRef.current = new ArkNotifyClient({ baseUrl, token, fetch: fetchFn }));
571
605
  const client = clientRef.current;
572
606
  react.useEffect(() => {
573
607
  if (token === void 0) return;