imessage-sdk 0.1.0-beta.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,18 +3,19 @@
3
3
  A provider-neutral, type-safe TypeScript conversation layer for iMessage
4
4
  infrastructure.
5
5
 
6
- The normalized v0.1 client, Blooio v2 provider, and Photon Cloud provider are
7
- implemented.
6
+ The normalized v0.1 client is implemented here. Blooio v2 and Photon Cloud are
7
+ published as separate provider packages so applications install only the
8
+ provider dependencies they use.
8
9
 
9
10
  The package is ESM-only and ships JavaScript plus TypeScript declarations.
10
11
 
11
12
  > This is a beta release. Install the prerelease with `pnpm add
12
- > imessage-sdk@beta` while the public API is being validated.
13
+ imessage-sdk@beta` while the public API is being validated.
13
14
 
14
15
  ## Install
15
16
 
16
17
  ```bash
17
- pnpm add imessage-sdk@beta
18
+ pnpm add imessage-sdk@beta @imessage-sdk/blooio@beta
18
19
  ```
19
20
 
20
21
  ## Creating a client
@@ -23,8 +24,8 @@ Provider factories consume provider configuration and return a complete,
23
24
  concrete provider:
24
25
 
25
26
  ```ts
26
- import { createIMessageClient } from "imessage-sdk";
27
- import { blooio } from "imessage-sdk/providers/blooio";
27
+ import { blooio } from '@imessage-sdk/blooio';
28
+ import { createIMessageClient } from 'imessage-sdk';
28
29
 
29
30
  const client = createIMessageClient({
30
31
  provider: blooio(),
@@ -39,7 +40,7 @@ when the application has multiple connections or sender lines:
39
40
 
40
41
  ```ts
41
42
  const namedClient = createIMessageClient({
42
- connectionId: "main-line",
43
+ connectionId: 'main-line',
43
44
  provider: blooio(),
44
45
  });
45
46
 
@@ -74,8 +75,8 @@ client.providers.blooio.name;
74
75
  client.providers.photon;
75
76
 
76
77
  const sent = await client.messages.send({
77
- to: { kind: "phone", value: "+15551234567" },
78
- text: "Hello from imessage-sdk",
78
+ to: { kind: 'phone', value: '+15551234567' },
79
+ text: 'Hello from imessage-sdk',
79
80
  });
80
81
 
81
82
  sent.provider;
@@ -93,26 +94,26 @@ public URLs, while Photon uploads all three source types:
93
94
 
94
95
  ```ts
95
96
  await client.messages.send({
96
- conversationId: "provider-conversation-id",
97
- text: "Three attachments",
97
+ conversationId: 'provider-conversation-id',
98
+ text: 'Three attachments',
98
99
  attachments: [
99
100
  {
100
- kind: "image",
101
+ kind: 'image',
101
102
  source: {
102
- type: "url",
103
- url: "https://example.com/photo.jpg",
103
+ type: 'url',
104
+ url: 'https://example.com/photo.jpg',
104
105
  },
105
- contentType: "image/jpeg",
106
+ contentType: 'image/jpeg',
106
107
  },
107
108
  {
108
- kind: "video",
109
- source: { type: "url", url: "https://example.com/clip.mp4" },
110
- filename: "clip.mp4",
109
+ kind: 'video',
110
+ source: { type: 'url', url: 'https://example.com/clip.mp4' },
111
+ filename: 'clip.mp4',
111
112
  },
112
113
  {
113
- kind: "file",
114
- source: { type: "url", url: "https://example.com/document.pdf" },
115
- filename: "document.pdf",
114
+ kind: 'file',
115
+ source: { type: 'url', url: 'https://example.com/document.pdf' },
116
+ filename: 'document.pdf',
116
117
  },
117
118
  ],
118
119
  });
@@ -122,10 +123,10 @@ Replies use the provider-native message ID and optional message-part index:
122
123
 
123
124
  ```ts
124
125
  await client.messages.send({
125
- conversationId: "provider-conversation-id",
126
- text: "Replying in this thread",
126
+ conversationId: 'provider-conversation-id',
127
+ text: 'Replying in this thread',
127
128
  replyTo: {
128
- messageId: "provider-message-id",
129
+ messageId: 'provider-message-id',
129
130
  partIndex: 0,
130
131
  },
131
132
  });
@@ -139,15 +140,15 @@ the exact same instance under its typed provider namespace:
139
140
  ```ts
140
141
  const provider = blooio();
141
142
  const client = createIMessageClient({
142
- connectionId: "main-line",
143
+ connectionId: 'main-line',
143
144
  provider,
144
145
  });
145
146
 
146
147
  client.providers.blooio === provider; // true
147
148
 
148
149
  await client.providers.blooio.messages.send({
149
- to: { kind: "phone", value: "+15551234567" },
150
- text: "Send directly through Blooio",
150
+ to: { kind: 'phone', value: '+15551234567' },
151
+ text: 'Send directly through Blooio',
151
152
  });
152
153
  ```
153
154
 
@@ -155,8 +156,8 @@ The normalized top-level methods remain available:
155
156
 
156
157
  ```ts
157
158
  await client.messages.send({
158
- to: { kind: "phone", value: "+15551234567" },
159
- text: "Send through the normalized client",
159
+ to: { kind: 'phone', value: '+15551234567' },
160
+ text: 'Send through the normalized client',
160
161
  });
161
162
  ```
162
163
 
@@ -185,11 +186,11 @@ literal name, capability values, and complete concrete provider type.
185
186
  Conceptually, provider factories are structured like this:
186
187
 
187
188
  ```ts
188
- import { defineProvider } from "imessage-sdk";
189
+ import { defineProvider } from 'imessage-sdk';
189
190
 
190
191
  function blooio(options = {}) {
191
192
  return defineProvider({
192
- name: "blooio" as const,
193
+ name: 'blooio' as const,
193
194
  capabilities: BLOOIO_CAPABILITIES,
194
195
  messages: {
195
196
  async send(input) {
@@ -237,7 +238,7 @@ methods:
237
238
 
238
239
  ```ts
239
240
  const custom = defineProvider({
240
- name: "my-provider" as const,
241
+ name: 'my-provider' as const,
241
242
  capabilities: MY_PROVIDER_CAPABILITIES,
242
243
  messages: {
243
244
  send: sendMessage,
@@ -255,9 +256,9 @@ customClient.provider;
255
256
  // ^? "my-provider"
256
257
 
257
258
  // Required because this concrete provider defines it as required.
258
- await customClient.providers["my-provider"].messages.edit(
259
- { conversationId: "conversation-id", messageId: "message-id" },
260
- { text: "Corrected" },
259
+ await customClient.providers['my-provider'].messages.edit(
260
+ { conversationId: 'conversation-id', messageId: 'message-id' },
261
+ { text: 'Corrected' },
261
262
  );
262
263
  ```
263
264
 
@@ -268,12 +269,12 @@ or sender lines, it creates multiple clients and selects one explicitly:
268
269
 
269
270
  ```ts
270
271
  const sales = createIMessageClient({
271
- connectionId: "sales-line",
272
+ connectionId: 'sales-line',
272
273
  provider: blooio(salesOptions),
273
274
  });
274
275
 
275
276
  const support = createIMessageClient({
276
- connectionId: "support-line",
277
+ connectionId: 'support-line',
277
278
  provider: photon(supportOptions),
278
279
  });
279
280
  ```
@@ -309,10 +310,10 @@ feature checks:
309
310
  if (client.capabilities.messages.edit) {
310
311
  await client.messages.edit(
311
312
  {
312
- conversationId: "provider-conversation-id",
313
- messageId: "provider-message-id",
313
+ conversationId: 'provider-conversation-id',
314
+ messageId: 'provider-message-id',
314
315
  },
315
- { text: "Corrected" },
316
+ { text: 'Corrected' },
316
317
  );
317
318
  }
318
319
  ```
@@ -326,6 +327,10 @@ construction, while stream providers connect lazily when subscribed.
326
327
  `client.close()` is always available and idempotent. It is a no-op when the
327
328
  provider has no cleanup and releases resources for stream or local transports.
328
329
 
330
+ All available normalized v0.1 operations are stable except webhook handling.
331
+ `client.webhooks`, `ProviderWebhooks`, and webhook event normalization are
332
+ marked experimental and may change incompatibly during the 0.1 release line.
333
+
329
334
  ## Blooio operations
330
335
 
331
336
  The v0.1 Blooio adapter supports text and public URL attachments, inline
@@ -340,15 +345,15 @@ const locator = {
340
345
  };
341
346
 
342
347
  await client.messages.get(locator);
343
- await client.reactions.add({ ...locator, reaction: "like" });
348
+ await client.reactions.add({ ...locator, reaction: 'like' });
344
349
  await client.typing.start(sent.conversationId);
345
350
  await client.typing.stop(sent.conversationId);
346
351
  await client.conversations.markRead(sent.conversationId);
347
352
  ```
348
353
 
349
- Webhook handling verifies `X-Blooio-Signature` before parsing and returns an
350
- array because one provider delivery can represent zero, one, or multiple
351
- normalized events:
354
+ Experimental webhook handling verifies `X-Blooio-Signature` before parsing and
355
+ returns an array because one provider delivery can represent zero, one, or
356
+ multiple normalized events:
352
357
 
353
358
  ```ts
354
359
  const events = await client.webhooks.handle(request);
@@ -367,7 +372,7 @@ export BLOOIO_TEST_IMAGE_URL="https://..."
367
372
  export BLOOIO_TEST_VIDEO_URL="https://..."
368
373
  export BLOOIO_TEST_FILE_URL="https://..."
369
374
 
370
- pnpm --filter imessage-sdk test:integration:blooio
375
+ pnpm --filter @imessage-sdk/blooio test:integration
371
376
  ```
372
377
 
373
378
  It sends three messages and exercises lookup/status, reactions, typing, and
@@ -380,11 +385,11 @@ Photon authenticates with Spectrum Cloud lazily. A dedicated phone is optional
380
385
  when the project owns exactly one line and required when it owns multiple:
381
386
 
382
387
  ```ts
383
- import { createIMessageClient } from "imessage-sdk";
384
- import { photon } from "imessage-sdk/providers/photon";
388
+ import { photon } from '@imessage-sdk/photon';
389
+ import { createIMessageClient } from 'imessage-sdk';
385
390
 
386
391
  const client = createIMessageClient({
387
- connectionId: "photon-main",
392
+ connectionId: 'photon-main',
388
393
  provider: photon(),
389
394
  });
390
395
 
@@ -407,7 +412,7 @@ Cursors are durable numeric event sequences represented as strings:
407
412
 
408
413
  ```ts
409
414
  for await (const event of client.providers.photon.events.subscribe({
410
- cursor: "123",
415
+ cursor: '123',
411
416
  })) {
412
417
  console.log(event.providerEventId, event.type);
413
418
  }
@@ -430,7 +435,7 @@ export PHOTON_TEST_IMAGE_URL="https://..."
430
435
  export PHOTON_TEST_VIDEO_URL="https://..."
431
436
  export PHOTON_TEST_FILE_URL="https://..."
432
437
 
433
- pnpm --filter imessage-sdk test:integration:photon
438
+ pnpm --filter @imessage-sdk/photon test:integration
434
439
  ```
435
440
 
436
441
  On Photon Free and Pro shared lines, add the recipient under the project's
@@ -444,7 +449,7 @@ persistent stream, run the command below and send an iMessage to the line
444
449
  within 60 seconds:
445
450
 
446
451
  ```bash
447
- pnpm --filter imessage-sdk test:integration:photon-stream
452
+ pnpm --filter @imessage-sdk/photon test:integration:stream
448
453
  ```
449
454
 
450
455
  ## v0.1 beta boundary
package/dist/index.d.ts CHANGED
@@ -1,5 +1,31 @@
1
- import { A as AnyIMessageProvider, S as SendMessageInput, a as SentMessage, M as MessageLocator, b as Message, E as EditMessageInput, O as OpenConversationInput, C as Conversation, c as AddReactionInput, R as RemoveReactionInput, I as IMessageEvent, d as SubscribeOptions } from './provider-CCW_6OWg.js';
2
- export { e as IMessageAddress, f as IMessageAddressKind, g as IMessageAttachment, h as IMessageAttachmentInput, i as IMessageAttachmentKind, j as IMessageAttachmentSource, k as IMessageCapabilities, l as IMessageDeletedEvent, m as IMessageDirection, n as IMessageEventBase, o as IMessageMessageEvent, p as IMessageProvider, q as IMessageProviderName, r as IMessageReaction, s as IMessageReactionEvent, t as IMessageService, u as IMessageStatus, v as IMessageTypingEvent, w as MessageReplyReference, N as NonEmptyReadonlyArray, P as ProviderConversation, x as ProviderConversations, y as ProviderEvent, z as ProviderEventBase, B as ProviderEvents, D as ProviderMessage, F as ProviderMessageDeletedEvent, G as ProviderMessageEvent, H as ProviderMessageEventType, J as ProviderMessages, K as ProviderReactionEvent, L as ProviderReactionEventType, Q as ProviderReactions, T as ProviderSentMessage, U as ProviderTyping, V as ProviderTypingEvent, W as ProviderTypingEventType, X as ProviderWebhooks, Y as defineProvider } from './provider-CCW_6OWg.js';
1
+ /** Runtime feature declaration for one configured provider connection. */
2
+ interface IMessageCapabilities {
3
+ readonly messages: {
4
+ readonly text: boolean;
5
+ readonly attachments: boolean;
6
+ readonly replies: boolean;
7
+ readonly get: boolean;
8
+ readonly edit: boolean;
9
+ readonly delete: boolean;
10
+ };
11
+ readonly conversations: {
12
+ readonly direct: boolean;
13
+ readonly groups: boolean;
14
+ readonly get: boolean;
15
+ readonly markRead: boolean;
16
+ };
17
+ readonly interactions: {
18
+ readonly reactions: boolean;
19
+ readonly typingStart: boolean;
20
+ readonly typingStop: boolean;
21
+ readonly readReceipts: boolean;
22
+ };
23
+ readonly events: {
24
+ /** @experimental Webhook normalization may change before a future stable release. */
25
+ readonly webhooks: boolean;
26
+ readonly stream: boolean;
27
+ };
28
+ }
3
29
 
4
30
  /**
5
31
  * Creates a diagnostic fallback when a provider message omits its native
@@ -47,27 +73,269 @@ declare class AmbiguousDeliveryError extends IMessageSDKError {
47
73
  }
48
74
  declare class UnsupportedCapabilityError extends IMessageSDKError {
49
75
  readonly capability: string;
50
- constructor(capability: string, options?: Pick<IMessageSDKErrorOptions, "provider" | "connectionId">);
76
+ constructor(capability: string, options?: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'>);
51
77
  }
52
78
  declare class WebhookVerificationError extends IMessageSDKError {
53
- constructor(options?: Pick<IMessageSDKErrorOptions, "provider" | "connectionId">);
79
+ constructor(options?: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'>);
54
80
  }
55
81
  declare class ClientClosedError extends IMessageSDKError {
56
- constructor(options?: Pick<IMessageSDKErrorOptions, "provider" | "connectionId">);
82
+ constructor(options?: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'>);
83
+ }
84
+
85
+ /** Provider names stay literal through generics but are open to custom adapters. */
86
+ type IMessageProviderName = string;
87
+ type IMessageAddressKind = 'phone' | 'email';
88
+ interface IMessageAddress {
89
+ readonly kind: IMessageAddressKind;
90
+ readonly value: string;
91
+ }
92
+ type NonEmptyReadonlyArray<T> = readonly [T, ...T[]];
93
+ type IMessageAttachmentKind = 'image' | 'video' | 'file';
94
+ type IMessageAttachmentSource = {
95
+ readonly type: 'url';
96
+ /** A URL that the selected provider can fetch. */
97
+ readonly url: string;
98
+ } | {
99
+ readonly type: 'blob';
100
+ readonly data: Blob;
101
+ } | {
102
+ readonly type: 'bytes';
103
+ readonly data: Uint8Array;
104
+ };
105
+ interface IMessageAttachmentInput {
106
+ readonly kind: IMessageAttachmentKind;
107
+ readonly source: IMessageAttachmentSource;
108
+ readonly filename?: string;
109
+ readonly contentType?: string;
110
+ }
111
+ interface IMessageAttachment {
112
+ readonly kind: IMessageAttachmentKind;
113
+ readonly id?: string;
114
+ readonly url?: string;
115
+ readonly filename?: string;
116
+ readonly contentType?: string;
117
+ readonly size?: number;
118
+ readonly raw: unknown;
119
+ }
120
+ interface MessageReplyReference {
121
+ /** Provider-native message identifier. */
122
+ readonly messageId: string;
123
+ readonly partIndex?: number;
124
+ }
125
+ /** Identifies a provider message within its native conversation. */
126
+ interface MessageLocator {
127
+ readonly conversationId: string;
128
+ readonly messageId: string;
129
+ }
130
+ type SendDestination = {
131
+ readonly conversationId: string;
132
+ readonly to?: never;
133
+ } | {
134
+ readonly conversationId?: never;
135
+ readonly to: IMessageAddress | NonEmptyReadonlyArray<IMessageAddress>;
136
+ };
137
+ type SendContent = {
138
+ readonly text: string;
139
+ readonly attachments?: readonly IMessageAttachmentInput[];
140
+ } | {
141
+ readonly text?: string;
142
+ readonly attachments: NonEmptyReadonlyArray<IMessageAttachmentInput>;
143
+ };
144
+ type SendMessageInput = SendDestination & SendContent & {
145
+ readonly replyTo?: MessageReplyReference;
146
+ readonly idempotencyKey?: string;
147
+ readonly metadata?: Readonly<Record<string, string>>;
148
+ };
149
+ interface EditMessageInput {
150
+ readonly text: string;
151
+ }
152
+ type IMessageDirection = 'inbound' | 'outbound';
153
+ type IMessageService = 'imessage' | 'sms' | 'rcs' | 'unknown';
154
+ type IMessageStatus = 'pending' | 'accepted' | 'sent' | 'delivered' | 'read' | 'failed';
155
+ /**
156
+ * A provider-normalized message before the client adds connection identity.
157
+ * Provider adapters return this shape.
158
+ */
159
+ interface ProviderMessage {
160
+ readonly providerMessageId: string;
161
+ /** Opaque provider-native ID, scoped to one provider connection. */
162
+ readonly conversationId?: string;
163
+ readonly direction: IMessageDirection;
164
+ readonly sender: IMessageAddress;
165
+ readonly recipients: readonly IMessageAddress[];
166
+ readonly text: string;
167
+ readonly attachments: readonly IMessageAttachment[];
168
+ readonly replyTo?: MessageReplyReference;
169
+ readonly service: IMessageService;
170
+ readonly status: IMessageStatus;
171
+ readonly providerStatus?: string;
172
+ readonly createdAt: Date;
173
+ readonly sentAt?: Date;
174
+ readonly deliveredAt?: Date;
175
+ readonly readAt?: Date;
176
+ readonly raw: unknown;
177
+ }
178
+ type ProviderSentMessage = ProviderMessage & {
179
+ readonly direction: 'outbound';
180
+ };
181
+ /** A message returned by a client bound to one provider connection. */
182
+ type Message<TProvider extends IMessageProviderName = IMessageProviderName, TConnectionId extends string = string> = Omit<ProviderMessage, 'conversationId'> & {
183
+ /** Equal to providerMessageId in v0.1. */
184
+ readonly id: string;
185
+ /** Provider-native when available; otherwise a non-routable imsg-sdk-v1 fallback. */
186
+ readonly conversationId: string;
187
+ readonly provider: TProvider;
188
+ readonly connectionId: TConnectionId;
189
+ };
190
+ type SentMessage<TProvider extends IMessageProviderName = IMessageProviderName, TConnectionId extends string = string> = Message<TProvider, TConnectionId> & {
191
+ readonly direction: 'outbound';
192
+ };
193
+ interface OpenConversationInput {
194
+ readonly participants: NonEmptyReadonlyArray<IMessageAddress>;
195
+ }
196
+ interface ProviderConversation {
197
+ /** Opaque provider-native ID, scoped to one provider connection. */
198
+ readonly providerConversationId: string;
199
+ readonly participants: readonly IMessageAddress[];
200
+ readonly createdAt?: Date;
201
+ readonly raw: unknown;
202
+ }
203
+ type Conversation<TProvider extends IMessageProviderName = IMessageProviderName, TConnectionId extends string = string> = ProviderConversation & {
204
+ /** Equal to providerConversationId in v0.1; scope with provider and connectionId. */
205
+ readonly id: string;
206
+ readonly provider: TProvider;
207
+ readonly connectionId: TConnectionId;
208
+ };
209
+ type IMessageReaction = 'love' | 'like' | 'dislike' | 'laugh' | 'emphasize' | 'question';
210
+ interface AddReactionInput extends MessageLocator {
211
+ readonly reaction: IMessageReaction;
212
+ readonly partIndex?: number;
213
+ }
214
+ type RemoveReactionInput = AddReactionInput;
215
+ interface SubscribeOptions {
216
+ readonly cursor?: string;
217
+ readonly signal?: AbortSignal;
218
+ }
219
+
220
+ interface ProviderEventBase<TType extends string> {
221
+ readonly id: string;
222
+ readonly providerEventId?: string;
223
+ readonly type: TType;
224
+ readonly timestamp: Date;
225
+ readonly raw: unknown;
226
+ }
227
+ type ProviderMessageEventType = 'message.received' | 'message.sent' | 'message.delivered' | 'message.read' | 'message.failed' | 'message.edited';
228
+ interface ProviderMessageEvent<TType extends ProviderMessageEventType = ProviderMessageEventType> extends ProviderEventBase<TType> {
229
+ readonly message: ProviderMessage;
230
+ }
231
+ interface ProviderMessageDeletedEvent extends ProviderEventBase<'message.deleted'> {
232
+ readonly conversationId: string;
233
+ readonly messageId: string;
234
+ }
235
+ type ProviderReactionEventType = 'reaction.added' | 'reaction.removed';
236
+ interface ProviderReactionEvent<TType extends ProviderReactionEventType = ProviderReactionEventType> extends ProviderEventBase<TType> {
237
+ readonly conversationId: string;
238
+ readonly messageId: string;
239
+ readonly actor: IMessageAddress;
240
+ readonly reaction: IMessageReaction;
241
+ readonly partIndex?: number;
242
+ }
243
+ type ProviderTypingEventType = 'typing.started' | 'typing.stopped';
244
+ interface ProviderTypingEvent<TType extends ProviderTypingEventType = ProviderTypingEventType> extends ProviderEventBase<TType> {
245
+ readonly conversationId: string;
246
+ /** Some group transports do not identify which participant is typing. */
247
+ readonly actor?: IMessageAddress;
248
+ }
249
+ type ProviderEvent = ProviderMessageEvent | ProviderMessageDeletedEvent | ProviderReactionEvent | ProviderTypingEvent;
250
+ interface IMessageEventBase<TProvider extends IMessageProviderName, TConnectionId extends string, TType extends string> extends ProviderEventBase<TType> {
251
+ readonly provider: TProvider;
252
+ readonly connectionId: TConnectionId;
253
+ }
254
+ interface IMessageMessageEvent<TProvider extends IMessageProviderName, TConnectionId extends string, TType extends ProviderMessageEventType = ProviderMessageEventType> extends IMessageEventBase<TProvider, TConnectionId, TType> {
255
+ readonly message: Message<TProvider, TConnectionId>;
256
+ }
257
+ interface IMessageDeletedEvent<TProvider extends IMessageProviderName, TConnectionId extends string> extends IMessageEventBase<TProvider, TConnectionId, 'message.deleted'> {
258
+ readonly conversationId: string;
259
+ readonly messageId: string;
260
+ }
261
+ interface IMessageReactionEvent<TProvider extends IMessageProviderName, TConnectionId extends string, TType extends ProviderReactionEventType = ProviderReactionEventType> extends IMessageEventBase<TProvider, TConnectionId, TType> {
262
+ readonly conversationId: string;
263
+ readonly messageId: string;
264
+ readonly actor: IMessageAddress;
265
+ readonly reaction: IMessageReaction;
266
+ readonly partIndex?: number;
267
+ }
268
+ interface IMessageTypingEvent<TProvider extends IMessageProviderName, TConnectionId extends string, TType extends ProviderTypingEventType = ProviderTypingEventType> extends IMessageEventBase<TProvider, TConnectionId, TType> {
269
+ readonly conversationId: string;
270
+ readonly actor?: IMessageAddress;
271
+ }
272
+ type IMessageEvent<TProvider extends IMessageProviderName = IMessageProviderName, TConnectionId extends string = string> = IMessageMessageEvent<TProvider, TConnectionId> | IMessageDeletedEvent<TProvider, TConnectionId> | IMessageReactionEvent<TProvider, TConnectionId> | IMessageTypingEvent<TProvider, TConnectionId>;
273
+
274
+ interface ProviderMessages {
275
+ send(input: SendMessageInput): Promise<ProviderSentMessage>;
276
+ get?(message: MessageLocator): Promise<ProviderMessage | null>;
277
+ edit?(message: MessageLocator, input: EditMessageInput): Promise<ProviderMessage>;
278
+ delete?(message: MessageLocator): Promise<void>;
279
+ }
280
+ interface ProviderConversations {
281
+ open(input: OpenConversationInput): Promise<ProviderConversation>;
282
+ get?(conversationId: string): Promise<ProviderConversation | null>;
283
+ markRead?(conversationId: string): Promise<void>;
284
+ }
285
+ interface ProviderReactions {
286
+ add(input: AddReactionInput): Promise<void>;
287
+ remove(input: RemoveReactionInput): Promise<void>;
288
+ }
289
+ interface ProviderTyping {
290
+ start(conversationId: string): Promise<void>;
291
+ stop?(conversationId: string): Promise<void>;
292
+ }
293
+ /**
294
+ * Provider webhook verification and normalization contract.
295
+ *
296
+ * @experimental Webhook normalization may change before a future stable release.
297
+ */
298
+ interface ProviderWebhooks {
299
+ verify(request: Request): Promise<boolean>;
300
+ parse(request: Request): Promise<readonly ProviderEvent[]>;
301
+ }
302
+ interface ProviderEvents {
303
+ subscribe(options?: SubscribeOptions): AsyncIterable<ProviderEvent>;
304
+ }
305
+ /**
306
+ * Contract implemented by a provider adapter.
307
+ *
308
+ * The complete adapter is exposed at `client.providers.<name>`, so
309
+ * provider-specific APIs should be defined directly on the concrete provider.
310
+ */
311
+ interface IMessageProvider<TName extends IMessageProviderName = IMessageProviderName, TCapabilities extends IMessageCapabilities = IMessageCapabilities> {
312
+ readonly name: TName;
313
+ readonly capabilities: TCapabilities;
314
+ readonly messages: ProviderMessages;
315
+ readonly conversations: ProviderConversations;
316
+ readonly reactions?: ProviderReactions;
317
+ readonly typing?: ProviderTyping;
318
+ /** @experimental Webhook normalization may change before a future stable release. */
319
+ readonly webhooks?: ProviderWebhooks;
320
+ readonly events?: ProviderEvents;
321
+ close?(): Promise<void>;
57
322
  }
323
+ type AnyIMessageProvider = IMessageProvider<IMessageProviderName, IMessageCapabilities>;
324
+ /** Preserves the concrete name, capabilities, and methods of an adapter. */
325
+ declare function defineProvider<const TProvider extends AnyIMessageProvider>(provider: TProvider): TProvider;
58
326
 
59
- type ProviderNameOf<TProvider extends AnyIMessageProvider> = TProvider["name"];
327
+ type ProviderNameOf<TProvider extends AnyIMessageProvider> = TProvider['name'];
60
328
  declare const DEFAULT_CONNECTION_ID: "default";
61
329
  type ClientProvider<TProvider extends AnyIMessageProvider> = TProvider;
62
330
  type ClientProviders<TProvider extends AnyIMessageProvider> = {
63
- readonly [TName in TProvider["name"]]: ClientProvider<Extract<TProvider, {
331
+ readonly [TName in TProvider['name']]: ClientProvider<Extract<TProvider, {
64
332
  readonly name: TName;
65
333
  }>>;
66
334
  };
67
335
  interface IMessageClient<TProvider extends AnyIMessageProvider = AnyIMessageProvider, TConnectionId extends string = string> {
68
336
  readonly provider: ProviderNameOf<TProvider>;
69
337
  readonly connectionId: TConnectionId;
70
- readonly capabilities: TProvider["capabilities"];
338
+ readonly capabilities: TProvider['capabilities'];
71
339
  readonly providers: ClientProviders<TProvider>;
72
340
  readonly messages: {
73
341
  send(input: SendMessageInput): Promise<SentMessage<ProviderNameOf<TProvider>, TConnectionId>>;
@@ -88,6 +356,7 @@ interface IMessageClient<TProvider extends AnyIMessageProvider = AnyIMessageProv
88
356
  start(conversationId: string): Promise<void>;
89
357
  stop(conversationId: string): Promise<void>;
90
358
  };
359
+ /** @experimental Webhook normalization may change before a future stable release. */
91
360
  readonly webhooks: {
92
361
  handle(request: Request): Promise<readonly IMessageEvent<ProviderNameOf<TProvider>, TConnectionId>[]>;
93
362
  };
@@ -102,4 +371,4 @@ interface CreateIMessageClientOptions<TProvider extends AnyIMessageProvider, TCo
102
371
  }
103
372
  declare function createIMessageClient<const TProvider extends AnyIMessageProvider, const TConnectionId extends string = typeof DEFAULT_CONNECTION_ID>(options: CreateIMessageClientOptions<TProvider, TConnectionId>): IMessageClient<TProvider, TConnectionId>;
104
373
 
105
- export { AddReactionInput, AmbiguousDeliveryError, AnyIMessageProvider, AuthenticationError, ClientClosedError, type ClientProvider, type ClientProviders, ConflictError, Conversation, type CreateIMessageClientOptions, DEFAULT_CONNECTION_ID, EditMessageInput, type IMessageClient, IMessageEvent, IMessageSDKError, type IMessageSDKErrorOptions, Message, MessageLocator, NotFoundError, OpenConversationInput, ProviderUnavailableError, RateLimitError, RemoveReactionInput, SendMessageInput, SentMessage, SubscribeOptions, UnsupportedCapabilityError, ValidationError, WebhookVerificationError, createFallbackConversationId, createIMessageClient, isFallbackConversationId };
374
+ export { type AddReactionInput, AmbiguousDeliveryError, type AnyIMessageProvider, AuthenticationError, ClientClosedError, type ClientProvider, type ClientProviders, ConflictError, type Conversation, type CreateIMessageClientOptions, DEFAULT_CONNECTION_ID, type EditMessageInput, type IMessageAddress, type IMessageAddressKind, type IMessageAttachment, type IMessageAttachmentInput, type IMessageAttachmentKind, type IMessageAttachmentSource, type IMessageCapabilities, type IMessageClient, type IMessageDeletedEvent, type IMessageDirection, type IMessageEvent, type IMessageEventBase, type IMessageMessageEvent, type IMessageProvider, type IMessageProviderName, type IMessageReaction, type IMessageReactionEvent, IMessageSDKError, type IMessageSDKErrorOptions, type IMessageService, type IMessageStatus, type IMessageTypingEvent, type Message, type MessageLocator, type MessageReplyReference, type NonEmptyReadonlyArray, NotFoundError, type OpenConversationInput, type ProviderConversation, type ProviderConversations, type ProviderEvent, type ProviderEventBase, type ProviderEvents, type ProviderMessage, type ProviderMessageDeletedEvent, type ProviderMessageEvent, type ProviderMessageEventType, type ProviderMessages, type ProviderReactionEvent, type ProviderReactionEventType, type ProviderReactions, type ProviderSentMessage, type ProviderTyping, type ProviderTypingEvent, type ProviderTypingEventType, ProviderUnavailableError, type ProviderWebhooks, RateLimitError, type RemoveReactionInput, type SendMessageInput, type SentMessage, type SubscribeOptions, UnsupportedCapabilityError, ValidationError, WebhookVerificationError, createFallbackConversationId, createIMessageClient, defineProvider, isFallbackConversationId };