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 +56 -51
- package/dist/index.d.ts +278 -9
- package/dist/index.js +17 -69
- package/dist/index.js.map +1 -1
- package/package.json +7 -28
- package/dist/provider-CCW_6OWg.d.ts +0 -265
- package/dist/providers/blooio.d.ts +0 -76
- package/dist/providers/blooio.js +0 -655
- package/dist/providers/blooio.js.map +0 -1
- package/dist/providers/photon.d.ts +0 -66
- package/dist/providers/photon.js +0 -958
- package/dist/providers/photon.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -11,9 +11,7 @@ function createFallbackConversationId(message, timestamp) {
|
|
|
11
11
|
message,
|
|
12
12
|
timestamp: timestamp.toISOString()
|
|
13
13
|
};
|
|
14
|
-
const encoded = Buffer.from(JSON.stringify(payload), "utf8").toString(
|
|
15
|
-
"base64url"
|
|
16
|
-
);
|
|
14
|
+
const encoded = Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
17
15
|
return `${FALLBACK_CONVERSATION_ID_PREFIX}${encoded}`;
|
|
18
16
|
}
|
|
19
17
|
function isFallbackConversationId(value) {
|
|
@@ -92,11 +90,7 @@ function validateProvider(provider) {
|
|
|
92
90
|
[capabilities.messages.get, provider.messages.get, "messages.get"],
|
|
93
91
|
[capabilities.messages.edit, provider.messages.edit, "messages.edit"],
|
|
94
92
|
[capabilities.messages.delete, provider.messages.delete, "messages.delete"],
|
|
95
|
-
[
|
|
96
|
-
capabilities.conversations.get,
|
|
97
|
-
provider.conversations.get,
|
|
98
|
-
"conversations.get"
|
|
99
|
-
],
|
|
93
|
+
[capabilities.conversations.get, provider.conversations.get, "conversations.get"],
|
|
100
94
|
[
|
|
101
95
|
capabilities.conversations.markRead,
|
|
102
96
|
provider.conversations.markRead,
|
|
@@ -104,11 +98,7 @@ function validateProvider(provider) {
|
|
|
104
98
|
],
|
|
105
99
|
[capabilities.interactions.reactions, provider.reactions, "reactions"],
|
|
106
100
|
[capabilities.interactions.typingStart, provider.typing, "typing.start"],
|
|
107
|
-
[
|
|
108
|
-
capabilities.interactions.typingStop,
|
|
109
|
-
provider.typing?.stop,
|
|
110
|
-
"typing.stop"
|
|
111
|
-
],
|
|
101
|
+
[capabilities.interactions.typingStop, provider.typing?.stop, "typing.stop"],
|
|
112
102
|
[capabilities.events.webhooks, provider.webhooks, "webhooks"],
|
|
113
103
|
[capabilities.events.stream, provider.events, "events.subscribe"]
|
|
114
104
|
];
|
|
@@ -125,10 +115,7 @@ function decorateMessage(message, provider, connectionId) {
|
|
|
125
115
|
return {
|
|
126
116
|
...message,
|
|
127
117
|
id: message.providerMessageId,
|
|
128
|
-
conversationId: message.conversationId ?? createFallbackConversationId(
|
|
129
|
-
message.providerMessageId,
|
|
130
|
-
message.createdAt
|
|
131
|
-
),
|
|
118
|
+
conversationId: message.conversationId ?? createFallbackConversationId(message.providerMessageId, message.createdAt),
|
|
132
119
|
provider,
|
|
133
120
|
connectionId
|
|
134
121
|
};
|
|
@@ -252,10 +239,7 @@ function createIMessageClient(options) {
|
|
|
252
239
|
if (!provider.capabilities.messages.get) {
|
|
253
240
|
unsupported("messages.get");
|
|
254
241
|
}
|
|
255
|
-
const get = requireImplementation(
|
|
256
|
-
provider.messages.get,
|
|
257
|
-
"messages.get"
|
|
258
|
-
);
|
|
242
|
+
const get = requireImplementation(provider.messages.get, "messages.get");
|
|
259
243
|
const result = await get.call(provider.messages, message);
|
|
260
244
|
return result === null ? null : decorateMessage(result, provider.name, connectionId);
|
|
261
245
|
},
|
|
@@ -265,10 +249,7 @@ function createIMessageClient(options) {
|
|
|
265
249
|
if (!provider.capabilities.messages.edit) {
|
|
266
250
|
unsupported("messages.edit");
|
|
267
251
|
}
|
|
268
|
-
const edit = requireImplementation(
|
|
269
|
-
provider.messages.edit,
|
|
270
|
-
"messages.edit"
|
|
271
|
-
);
|
|
252
|
+
const edit = requireImplementation(provider.messages.edit, "messages.edit");
|
|
272
253
|
const result = await edit.call(provider.messages, message, input);
|
|
273
254
|
return decorateMessage(result, provider.name, connectionId);
|
|
274
255
|
},
|
|
@@ -278,10 +259,7 @@ function createIMessageClient(options) {
|
|
|
278
259
|
if (!provider.capabilities.messages.delete) {
|
|
279
260
|
unsupported("messages.delete");
|
|
280
261
|
}
|
|
281
|
-
const deleteMessage = requireImplementation(
|
|
282
|
-
provider.messages.delete,
|
|
283
|
-
"messages.delete"
|
|
284
|
-
);
|
|
262
|
+
const deleteMessage = requireImplementation(provider.messages.delete, "messages.delete");
|
|
285
263
|
await deleteMessage.call(provider.messages, message);
|
|
286
264
|
}
|
|
287
265
|
},
|
|
@@ -296,11 +274,7 @@ function createIMessageClient(options) {
|
|
|
296
274
|
unsupported("conversations.direct");
|
|
297
275
|
}
|
|
298
276
|
const conversation = await provider.conversations.open(input);
|
|
299
|
-
return decorateConversation(
|
|
300
|
-
conversation,
|
|
301
|
-
provider.name,
|
|
302
|
-
connectionId
|
|
303
|
-
);
|
|
277
|
+
return decorateConversation(conversation, provider.name, connectionId);
|
|
304
278
|
},
|
|
305
279
|
async get(conversationId) {
|
|
306
280
|
assertOpen();
|
|
@@ -308,14 +282,8 @@ function createIMessageClient(options) {
|
|
|
308
282
|
if (!provider.capabilities.conversations.get) {
|
|
309
283
|
unsupported("conversations.get");
|
|
310
284
|
}
|
|
311
|
-
const get = requireImplementation(
|
|
312
|
-
|
|
313
|
-
"conversations.get"
|
|
314
|
-
);
|
|
315
|
-
const conversation = await get.call(
|
|
316
|
-
provider.conversations,
|
|
317
|
-
conversationId
|
|
318
|
-
);
|
|
285
|
+
const get = requireImplementation(provider.conversations.get, "conversations.get");
|
|
286
|
+
const conversation = await get.call(provider.conversations, conversationId);
|
|
319
287
|
return conversation === null ? null : decorateConversation(conversation, provider.name, connectionId);
|
|
320
288
|
},
|
|
321
289
|
async markRead(conversationId) {
|
|
@@ -338,10 +306,7 @@ function createIMessageClient(options) {
|
|
|
338
306
|
if (!provider.capabilities.interactions.reactions) {
|
|
339
307
|
unsupported("reactions.add");
|
|
340
308
|
}
|
|
341
|
-
const reactions = requireImplementation(
|
|
342
|
-
provider.reactions,
|
|
343
|
-
"reactions.add"
|
|
344
|
-
);
|
|
309
|
+
const reactions = requireImplementation(provider.reactions, "reactions.add");
|
|
345
310
|
await reactions.add(input);
|
|
346
311
|
},
|
|
347
312
|
async remove(input) {
|
|
@@ -350,10 +315,7 @@ function createIMessageClient(options) {
|
|
|
350
315
|
if (!provider.capabilities.interactions.reactions) {
|
|
351
316
|
unsupported("reactions.remove");
|
|
352
317
|
}
|
|
353
|
-
const reactions = requireImplementation(
|
|
354
|
-
provider.reactions,
|
|
355
|
-
"reactions.remove"
|
|
356
|
-
);
|
|
318
|
+
const reactions = requireImplementation(provider.reactions, "reactions.remove");
|
|
357
319
|
await reactions.remove(input);
|
|
358
320
|
}
|
|
359
321
|
},
|
|
@@ -384,18 +346,13 @@ function createIMessageClient(options) {
|
|
|
384
346
|
if (!provider.capabilities.events.webhooks) {
|
|
385
347
|
unsupported("webhooks.handle");
|
|
386
348
|
}
|
|
387
|
-
const webhooks = requireImplementation(
|
|
388
|
-
provider.webhooks,
|
|
389
|
-
"webhooks.handle"
|
|
390
|
-
);
|
|
349
|
+
const webhooks = requireImplementation(provider.webhooks, "webhooks.handle");
|
|
391
350
|
const verified = await webhooks.verify(request.clone());
|
|
392
351
|
if (!verified) {
|
|
393
352
|
throw new WebhookVerificationError(errorContext);
|
|
394
353
|
}
|
|
395
354
|
const events = await webhooks.parse(request);
|
|
396
|
-
return events.map(
|
|
397
|
-
(event) => decorateEvent(event, provider.name, connectionId)
|
|
398
|
-
);
|
|
355
|
+
return events.map((event) => decorateEvent(event, provider.name, connectionId));
|
|
399
356
|
}
|
|
400
357
|
},
|
|
401
358
|
events: {
|
|
@@ -404,15 +361,8 @@ function createIMessageClient(options) {
|
|
|
404
361
|
if (!provider.capabilities.events.stream) {
|
|
405
362
|
unsupported("events.subscribe");
|
|
406
363
|
}
|
|
407
|
-
const events = requireImplementation(
|
|
408
|
-
|
|
409
|
-
"events.subscribe"
|
|
410
|
-
);
|
|
411
|
-
return mapEvents(
|
|
412
|
-
events.subscribe(options2),
|
|
413
|
-
provider.name,
|
|
414
|
-
connectionId
|
|
415
|
-
);
|
|
364
|
+
const events = requireImplementation(provider.events, "events.subscribe");
|
|
365
|
+
return mapEvents(events.subscribe(options2), provider.name, connectionId);
|
|
416
366
|
}
|
|
417
367
|
},
|
|
418
368
|
close() {
|
|
@@ -420,9 +370,7 @@ function createIMessageClient(options) {
|
|
|
420
370
|
return closePromise;
|
|
421
371
|
}
|
|
422
372
|
closed = true;
|
|
423
|
-
closePromise = Promise.resolve().then(
|
|
424
|
-
async () => await provider.close?.()
|
|
425
|
-
);
|
|
373
|
+
closePromise = Promise.resolve().then(async () => await provider.close?.());
|
|
426
374
|
return closePromise;
|
|
427
375
|
}
|
|
428
376
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/conversation-id.ts","../src/core/errors.ts","../src/core/client.ts","../src/core/provider.ts"],"names":["options"],"mappings":"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","file":"index.js","sourcesContent":["const FALLBACK_CONVERSATION_ID_PREFIX = \"imsg-sdk-v1-\";\n\ninterface FallbackConversationIdPayload {\n readonly message: string;\n readonly timestamp: string;\n}\n\n/**\n * Creates a diagnostic fallback when a provider message omits its native\n * conversation ID. Fallback IDs are stable for the same message and timestamp,\n * but are not provider-routable conversation handles.\n */\nexport function createFallbackConversationId(\n message: string,\n timestamp: Date,\n): string {\n if (message.length === 0) {\n throw new TypeError(\"Fallback conversation message must not be empty.\");\n }\n if (Number.isNaN(timestamp.getTime())) {\n throw new TypeError(\"Fallback conversation timestamp must be valid.\");\n }\n\n const payload: FallbackConversationIdPayload = {\n message,\n timestamp: timestamp.toISOString(),\n };\n const encoded = Buffer.from(JSON.stringify(payload), \"utf8\").toString(\n \"base64url\",\n );\n return `${FALLBACK_CONVERSATION_ID_PREFIX}${encoded}`;\n}\n\nexport function isFallbackConversationId(value: string): boolean {\n return value.startsWith(FALLBACK_CONVERSATION_ID_PREFIX);\n}\n","export interface IMessageSDKErrorOptions {\n readonly provider?: string;\n readonly connectionId?: string;\n readonly code?: string;\n readonly statusCode?: number;\n readonly retryable?: boolean;\n readonly retryAfter?: number;\n readonly traceId?: string;\n readonly raw?: unknown;\n}\n\nexport class IMessageSDKError extends Error {\n readonly provider: string | undefined;\n readonly connectionId: string | undefined;\n readonly code: string | undefined;\n readonly statusCode: number | undefined;\n readonly retryable: boolean;\n readonly retryAfter: number | undefined;\n readonly traceId: string | undefined;\n readonly raw: unknown;\n\n constructor(message: string, options: IMessageSDKErrorOptions = {}) {\n super(message);\n this.name = new.target.name;\n this.provider = options.provider;\n this.connectionId = options.connectionId;\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.retryable = options.retryable ?? false;\n this.retryAfter = options.retryAfter;\n this.traceId = options.traceId;\n this.raw = options.raw;\n }\n}\n\nexport class ValidationError extends IMessageSDKError {}\n\nexport class AuthenticationError extends IMessageSDKError {}\n\nexport class NotFoundError extends IMessageSDKError {}\n\nexport class ConflictError extends IMessageSDKError {}\n\nexport class RateLimitError extends IMessageSDKError {}\n\nexport class ProviderUnavailableError extends IMessageSDKError {}\n\n/** A send may have reached the provider, so blindly retrying could duplicate it. */\nexport class AmbiguousDeliveryError extends IMessageSDKError {}\n\nexport class UnsupportedCapabilityError extends IMessageSDKError {\n readonly capability: string;\n\n constructor(\n capability: string,\n options: Pick<IMessageSDKErrorOptions, \"provider\" | \"connectionId\"> = {},\n ) {\n super(`The selected provider does not support ${capability}.`, {\n ...options,\n code: \"unsupported_capability\",\n });\n this.capability = capability;\n }\n}\n\nexport class WebhookVerificationError extends IMessageSDKError {\n constructor(\n options: Pick<IMessageSDKErrorOptions, \"provider\" | \"connectionId\"> = {},\n ) {\n super(\"Webhook signature verification failed.\", {\n ...options,\n code: \"webhook_verification_failed\",\n });\n }\n}\n\nexport class ClientClosedError extends IMessageSDKError {\n constructor(\n options: Pick<IMessageSDKErrorOptions, \"provider\" | \"connectionId\"> = {},\n ) {\n super(\"This iMessage client has already been closed.\", {\n ...options,\n code: \"client_closed\",\n });\n }\n}\n","import {\n ClientClosedError,\n UnsupportedCapabilityError,\n ValidationError,\n WebhookVerificationError,\n} from \"./errors.js\";\nimport {\n createFallbackConversationId,\n isFallbackConversationId,\n} from \"./conversation-id.js\";\nimport type { IMessageEvent, ProviderEvent } from \"./events.js\";\nimport type { AnyIMessageProvider } from \"./provider.js\";\nimport type {\n AddReactionInput,\n Conversation,\n EditMessageInput,\n IMessageProviderName,\n Message,\n MessageLocator,\n OpenConversationInput,\n ProviderConversation,\n ProviderMessage,\n RemoveReactionInput,\n SendMessageInput,\n SentMessage,\n SubscribeOptions,\n} from \"./types.js\";\n\ntype ProviderNameOf<TProvider extends AnyIMessageProvider> = TProvider[\"name\"];\n\nexport const DEFAULT_CONNECTION_ID = \"default\" as const;\n\nexport type ClientProvider<TProvider extends AnyIMessageProvider> = TProvider;\n\nexport type ClientProviders<TProvider extends AnyIMessageProvider> = {\n readonly [TName in TProvider[\"name\"]]: ClientProvider<\n Extract<TProvider, { readonly name: TName }>\n >;\n};\n\nexport interface IMessageClient<\n TProvider extends AnyIMessageProvider = AnyIMessageProvider,\n TConnectionId extends string = string,\n> {\n readonly provider: ProviderNameOf<TProvider>;\n readonly connectionId: TConnectionId;\n readonly capabilities: TProvider[\"capabilities\"];\n readonly providers: ClientProviders<TProvider>;\n\n readonly messages: {\n send(\n input: SendMessageInput,\n ): Promise<SentMessage<ProviderNameOf<TProvider>, TConnectionId>>;\n get(message: MessageLocator): Promise<\n Message<ProviderNameOf<TProvider>, TConnectionId> | null\n >;\n edit(\n message: MessageLocator,\n input: EditMessageInput,\n ): Promise<Message<ProviderNameOf<TProvider>, TConnectionId>>;\n delete(message: MessageLocator): Promise<void>;\n };\n\n readonly conversations: {\n open(\n input: OpenConversationInput,\n ): Promise<Conversation<ProviderNameOf<TProvider>, TConnectionId>>;\n get(\n conversationId: string,\n ): Promise<Conversation<ProviderNameOf<TProvider>, TConnectionId> | null>;\n markRead(conversationId: string): Promise<void>;\n };\n\n readonly reactions: {\n add(input: AddReactionInput): Promise<void>;\n remove(input: RemoveReactionInput): Promise<void>;\n };\n\n readonly typing: {\n start(conversationId: string): Promise<void>;\n stop(conversationId: string): Promise<void>;\n };\n\n readonly webhooks: {\n handle(\n request: Request,\n ): Promise<\n readonly IMessageEvent<ProviderNameOf<TProvider>, TConnectionId>[]\n >;\n };\n\n readonly events: {\n subscribe(\n options?: SubscribeOptions,\n ): AsyncIterable<IMessageEvent<ProviderNameOf<TProvider>, TConnectionId>>;\n };\n\n close(): Promise<void>;\n}\n\nexport interface CreateIMessageClientOptions<\n TProvider extends AnyIMessageProvider,\n TConnectionId extends string = typeof DEFAULT_CONNECTION_ID,\n> {\n readonly connectionId?: TConnectionId;\n readonly provider: TProvider;\n}\n\nfunction validateProvider(provider: AnyIMessageProvider): void {\n const capabilities = provider.capabilities;\n\n const requirements: readonly [boolean, unknown, string][] = [\n [capabilities.messages.get, provider.messages.get, \"messages.get\"],\n [capabilities.messages.edit, provider.messages.edit, \"messages.edit\"],\n [capabilities.messages.delete, provider.messages.delete, \"messages.delete\"],\n [\n capabilities.conversations.get,\n provider.conversations.get,\n \"conversations.get\",\n ],\n [\n capabilities.conversations.markRead,\n provider.conversations.markRead,\n \"conversations.markRead\",\n ],\n [capabilities.interactions.reactions, provider.reactions, \"reactions\"],\n [capabilities.interactions.typingStart, provider.typing, \"typing.start\"],\n [\n capabilities.interactions.typingStop,\n provider.typing?.stop,\n \"typing.stop\",\n ],\n [capabilities.events.webhooks, provider.webhooks, \"webhooks\"],\n [capabilities.events.stream, provider.events, \"events.subscribe\"],\n ];\n\n for (const [enabled, implementation, capability] of requirements) {\n if (enabled && implementation === undefined) {\n throw new ValidationError(\n `Provider ${provider.name} declares ${capability} but does not implement it.`,\n { provider: provider.name, code: \"invalid_provider_contract\" },\n );\n }\n }\n}\n\nfunction decorateMessage<\n TProvider extends IMessageProviderName,\n TConnectionId extends string,\n>(\n message: ProviderMessage,\n provider: TProvider,\n connectionId: TConnectionId,\n): Message<TProvider, TConnectionId> {\n return {\n ...message,\n id: message.providerMessageId,\n conversationId:\n message.conversationId ??\n createFallbackConversationId(\n message.providerMessageId,\n message.createdAt,\n ),\n provider,\n connectionId,\n };\n}\n\nfunction decorateConversation<\n TProvider extends IMessageProviderName,\n TConnectionId extends string,\n>(\n conversation: ProviderConversation,\n provider: TProvider,\n connectionId: TConnectionId,\n): Conversation<TProvider, TConnectionId> {\n return {\n ...conversation,\n id: conversation.providerConversationId,\n provider,\n connectionId,\n };\n}\n\nfunction decorateEvent<\n TProvider extends IMessageProviderName,\n TConnectionId extends string,\n>(\n event: ProviderEvent,\n provider: TProvider,\n connectionId: TConnectionId,\n): IMessageEvent<TProvider, TConnectionId> {\n switch (event.type) {\n case \"message.received\":\n case \"message.sent\":\n case \"message.delivered\":\n case \"message.read\":\n case \"message.failed\":\n case \"message.edited\":\n return {\n ...event,\n provider,\n connectionId,\n message: decorateMessage(event.message, provider, connectionId),\n };\n case \"message.deleted\":\n case \"reaction.added\":\n case \"reaction.removed\":\n case \"typing.started\":\n case \"typing.stopped\":\n return { ...event, provider, connectionId };\n }\n}\n\nfunction mapEvents<\n TProvider extends IMessageProviderName,\n TConnectionId extends string,\n>(\n events: AsyncIterable<ProviderEvent>,\n provider: TProvider,\n connectionId: TConnectionId,\n): AsyncIterable<IMessageEvent<TProvider, TConnectionId>> {\n return {\n async *[Symbol.asyncIterator]() {\n for await (const event of events) {\n yield decorateEvent(event, provider, connectionId);\n }\n },\n };\n}\n\nexport function createIMessageClient<\n const TProvider extends AnyIMessageProvider,\n const TConnectionId extends string = typeof DEFAULT_CONNECTION_ID,\n>(\n options: CreateIMessageClientOptions<TProvider, TConnectionId>,\n): IMessageClient<TProvider, TConnectionId> {\n const { provider } = options;\n const connectionId = (options.connectionId ??\n DEFAULT_CONNECTION_ID) as TConnectionId;\n\n if (connectionId.trim().length === 0) {\n throw new ValidationError(\"connectionId must not be empty.\", {\n provider: provider.name,\n code: \"invalid_connection_id\",\n });\n }\n\n validateProvider(provider);\n\n let closed = false;\n let closePromise: Promise<void> | undefined;\n\n const errorContext = {\n provider: provider.name,\n connectionId,\n } as const;\n\n const assertOpen = (): void => {\n if (closed) {\n throw new ClientClosedError(errorContext);\n }\n };\n\n const unsupported = (capability: string): never => {\n throw new UnsupportedCapabilityError(capability, errorContext);\n };\n\n const assertRoutableConversationId = (conversationId: string): void => {\n if (isFallbackConversationId(conversationId)) {\n throw new ValidationError(\n \"SDK fallback conversation IDs are diagnostic and cannot be used for provider operations.\",\n { ...errorContext, code: \"non_routable_conversation_id\" },\n );\n }\n };\n\n const requireImplementation = <T>(\n implementation: T | undefined,\n capability: string,\n ): T => {\n if (implementation === undefined) {\n throw new UnsupportedCapabilityError(capability, errorContext);\n }\n\n return implementation;\n };\n\n const providers = Object.freeze({\n [provider.name]: provider,\n }) as ClientProviders<TProvider>;\n\n return {\n provider: provider.name,\n connectionId,\n capabilities: provider.capabilities,\n providers,\n messages: {\n async send(input) {\n assertOpen();\n\n if (input.conversationId !== undefined) {\n assertRoutableConversationId(input.conversationId);\n }\n\n if (input.text !== undefined && !provider.capabilities.messages.text) {\n unsupported(\"messages.text\");\n }\n\n if (\n input.attachments !== undefined &&\n input.attachments.length > 0 &&\n !provider.capabilities.messages.attachments\n ) {\n unsupported(\"messages.attachments\");\n }\n\n if (\n input.replyTo !== undefined &&\n !provider.capabilities.messages.replies\n ) {\n unsupported(\"messages.replies\");\n }\n\n if (input.to !== undefined) {\n const recipients = Array.isArray(input.to) ? input.to : [input.to];\n const isGroup = recipients.length > 1;\n\n if (isGroup && !provider.capabilities.conversations.groups) {\n unsupported(\"conversations.groups\");\n }\n\n if (!isGroup && !provider.capabilities.conversations.direct) {\n unsupported(\"conversations.direct\");\n }\n }\n\n const message = await provider.messages.send(input);\n return decorateMessage(message, provider.name, connectionId) as SentMessage<\n ProviderNameOf<TProvider>,\n TConnectionId\n >;\n },\n async get(message) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.get) {\n unsupported(\"messages.get\");\n }\n\n const get = requireImplementation(\n provider.messages.get,\n \"messages.get\",\n );\n\n const result = await get.call(provider.messages, message);\n return result === null\n ? null\n : decorateMessage(result, provider.name, connectionId);\n },\n async edit(message, input) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.edit) {\n unsupported(\"messages.edit\");\n }\n\n const edit = requireImplementation(\n provider.messages.edit,\n \"messages.edit\",\n );\n\n const result = await edit.call(provider.messages, message, input);\n return decorateMessage(result, provider.name, connectionId);\n },\n async delete(message) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.delete) {\n unsupported(\"messages.delete\");\n }\n\n const deleteMessage = requireImplementation(\n provider.messages.delete,\n \"messages.delete\",\n );\n\n await deleteMessage.call(provider.messages, message);\n },\n },\n conversations: {\n async open(input) {\n assertOpen();\n const isGroup = input.participants.length > 1;\n\n if (isGroup && !provider.capabilities.conversations.groups) {\n unsupported(\"conversations.groups\");\n }\n\n if (!isGroup && !provider.capabilities.conversations.direct) {\n unsupported(\"conversations.direct\");\n }\n\n const conversation = await provider.conversations.open(input);\n return decorateConversation(\n conversation,\n provider.name,\n connectionId,\n );\n },\n async get(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.conversations.get) {\n unsupported(\"conversations.get\");\n }\n\n const get = requireImplementation(\n provider.conversations.get,\n \"conversations.get\",\n );\n\n const conversation = await get.call(\n provider.conversations,\n conversationId,\n );\n return conversation === null\n ? null\n : decorateConversation(conversation, provider.name, connectionId);\n },\n async markRead(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.conversations.markRead) {\n unsupported(\"conversations.markRead\");\n }\n\n const markRead = requireImplementation(\n provider.conversations.markRead,\n \"conversations.markRead\",\n );\n await markRead.call(provider.conversations, conversationId);\n },\n },\n reactions: {\n async add(input) {\n assertOpen();\n assertRoutableConversationId(input.conversationId);\n\n if (!provider.capabilities.interactions.reactions) {\n unsupported(\"reactions.add\");\n }\n\n const reactions = requireImplementation(\n provider.reactions,\n \"reactions.add\",\n );\n\n await reactions.add(input);\n },\n async remove(input) {\n assertOpen();\n assertRoutableConversationId(input.conversationId);\n\n if (!provider.capabilities.interactions.reactions) {\n unsupported(\"reactions.remove\");\n }\n\n const reactions = requireImplementation(\n provider.reactions,\n \"reactions.remove\",\n );\n\n await reactions.remove(input);\n },\n },\n typing: {\n async start(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.interactions.typingStart) {\n unsupported(\"typing.start\");\n }\n\n const typing = requireImplementation(provider.typing, \"typing.start\");\n\n await typing.start(conversationId);\n },\n async stop(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.interactions.typingStop) {\n unsupported(\"typing.stop\");\n }\n\n const typing = requireImplementation(provider.typing, \"typing.stop\");\n const stop = requireImplementation(typing.stop, \"typing.stop\");\n\n await stop.call(typing, conversationId);\n },\n },\n webhooks: {\n async handle(request) {\n assertOpen();\n\n if (!provider.capabilities.events.webhooks) {\n unsupported(\"webhooks.handle\");\n }\n\n const webhooks = requireImplementation(\n provider.webhooks,\n \"webhooks.handle\",\n );\n\n const verified = await webhooks.verify(request.clone());\n if (!verified) {\n throw new WebhookVerificationError(errorContext);\n }\n\n const events = await webhooks.parse(request);\n return events.map((event) =>\n decorateEvent(event, provider.name, connectionId),\n );\n },\n },\n events: {\n subscribe(options) {\n assertOpen();\n\n if (!provider.capabilities.events.stream) {\n unsupported(\"events.subscribe\");\n }\n\n const events = requireImplementation(\n provider.events,\n \"events.subscribe\",\n );\n\n return mapEvents(\n events.subscribe(options),\n provider.name,\n connectionId,\n );\n },\n },\n close() {\n if (closePromise !== undefined) {\n return closePromise;\n }\n\n closed = true;\n closePromise = Promise.resolve().then(\n async () => await provider.close?.(),\n );\n return closePromise;\n },\n };\n}\n","import type { IMessageCapabilities } from \"./capabilities.js\";\nimport type { ProviderEvent } from \"./events.js\";\nimport type {\n AddReactionInput,\n EditMessageInput,\n IMessageProviderName,\n MessageLocator,\n OpenConversationInput,\n ProviderConversation,\n ProviderMessage,\n ProviderSentMessage,\n RemoveReactionInput,\n SendMessageInput,\n SubscribeOptions,\n} from \"./types.js\";\n\nexport interface ProviderMessages {\n send(input: SendMessageInput): Promise<ProviderSentMessage>;\n get?(message: MessageLocator): Promise<ProviderMessage | null>;\n edit?(\n message: MessageLocator,\n input: EditMessageInput,\n ): Promise<ProviderMessage>;\n delete?(message: MessageLocator): Promise<void>;\n}\n\nexport interface ProviderConversations {\n open(input: OpenConversationInput): Promise<ProviderConversation>;\n get?(conversationId: string): Promise<ProviderConversation | null>;\n markRead?(conversationId: string): Promise<void>;\n}\n\nexport interface ProviderReactions {\n add(input: AddReactionInput): Promise<void>;\n remove(input: RemoveReactionInput): Promise<void>;\n}\n\nexport interface ProviderTyping {\n start(conversationId: string): Promise<void>;\n stop?(conversationId: string): Promise<void>;\n}\n\nexport interface ProviderWebhooks {\n verify(request: Request): Promise<boolean>;\n parse(request: Request): Promise<readonly ProviderEvent[]>;\n}\n\nexport interface ProviderEvents {\n subscribe(options?: SubscribeOptions): AsyncIterable<ProviderEvent>;\n}\n\n/**\n * Contract implemented by a provider adapter.\n *\n * The complete adapter is exposed at `client.providers.<name>`, so\n * provider-specific APIs should be defined directly on the concrete provider.\n */\nexport interface IMessageProvider<\n TName extends IMessageProviderName = IMessageProviderName,\n TCapabilities extends IMessageCapabilities = IMessageCapabilities,\n> {\n readonly name: TName;\n readonly capabilities: TCapabilities;\n readonly messages: ProviderMessages;\n readonly conversations: ProviderConversations;\n readonly reactions?: ProviderReactions;\n readonly typing?: ProviderTyping;\n readonly webhooks?: ProviderWebhooks;\n readonly events?: ProviderEvents;\n close?(): Promise<void>;\n}\n\nexport type AnyIMessageProvider = IMessageProvider<\n IMessageProviderName,\n IMessageCapabilities\n>;\n\n/** Preserves the concrete name, capabilities, and methods of an adapter. */\nexport function defineProvider<const TProvider extends AnyIMessageProvider>(\n provider: TProvider,\n): TProvider {\n return provider;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/core/conversation-id.ts","../src/core/errors.ts","../src/core/client.ts","../src/core/provider.ts"],"names":["options"],"mappings":"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","file":"index.js","sourcesContent":["const FALLBACK_CONVERSATION_ID_PREFIX = 'imsg-sdk-v1-';\n\ninterface FallbackConversationIdPayload {\n readonly message: string;\n readonly timestamp: string;\n}\n\n/**\n * Creates a diagnostic fallback when a provider message omits its native\n * conversation ID. Fallback IDs are stable for the same message and timestamp,\n * but are not provider-routable conversation handles.\n */\nexport function createFallbackConversationId(message: string, timestamp: Date): string {\n if (message.length === 0) {\n throw new TypeError('Fallback conversation message must not be empty.');\n }\n if (Number.isNaN(timestamp.getTime())) {\n throw new TypeError('Fallback conversation timestamp must be valid.');\n }\n\n const payload: FallbackConversationIdPayload = {\n message,\n timestamp: timestamp.toISOString(),\n };\n const encoded = Buffer.from(JSON.stringify(payload), 'utf8').toString('base64url');\n return `${FALLBACK_CONVERSATION_ID_PREFIX}${encoded}`;\n}\n\nexport function isFallbackConversationId(value: string): boolean {\n return value.startsWith(FALLBACK_CONVERSATION_ID_PREFIX);\n}\n","export interface IMessageSDKErrorOptions {\n readonly provider?: string;\n readonly connectionId?: string;\n readonly code?: string;\n readonly statusCode?: number;\n readonly retryable?: boolean;\n readonly retryAfter?: number;\n readonly traceId?: string;\n readonly raw?: unknown;\n}\n\nexport class IMessageSDKError extends Error {\n readonly provider: string | undefined;\n readonly connectionId: string | undefined;\n readonly code: string | undefined;\n readonly statusCode: number | undefined;\n readonly retryable: boolean;\n readonly retryAfter: number | undefined;\n readonly traceId: string | undefined;\n readonly raw: unknown;\n\n constructor(message: string, options: IMessageSDKErrorOptions = {}) {\n super(message);\n this.name = new.target.name;\n this.provider = options.provider;\n this.connectionId = options.connectionId;\n this.code = options.code;\n this.statusCode = options.statusCode;\n this.retryable = options.retryable ?? false;\n this.retryAfter = options.retryAfter;\n this.traceId = options.traceId;\n this.raw = options.raw;\n }\n}\n\nexport class ValidationError extends IMessageSDKError {}\n\nexport class AuthenticationError extends IMessageSDKError {}\n\nexport class NotFoundError extends IMessageSDKError {}\n\nexport class ConflictError extends IMessageSDKError {}\n\nexport class RateLimitError extends IMessageSDKError {}\n\nexport class ProviderUnavailableError extends IMessageSDKError {}\n\n/** A send may have reached the provider, so blindly retrying could duplicate it. */\nexport class AmbiguousDeliveryError extends IMessageSDKError {}\n\nexport class UnsupportedCapabilityError extends IMessageSDKError {\n readonly capability: string;\n\n constructor(\n capability: string,\n options: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'> = {},\n ) {\n super(`The selected provider does not support ${capability}.`, {\n ...options,\n code: 'unsupported_capability',\n });\n this.capability = capability;\n }\n}\n\nexport class WebhookVerificationError extends IMessageSDKError {\n constructor(options: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'> = {}) {\n super('Webhook signature verification failed.', {\n ...options,\n code: 'webhook_verification_failed',\n });\n }\n}\n\nexport class ClientClosedError extends IMessageSDKError {\n constructor(options: Pick<IMessageSDKErrorOptions, 'provider' | 'connectionId'> = {}) {\n super('This iMessage client has already been closed.', {\n ...options,\n code: 'client_closed',\n });\n }\n}\n","import type { IMessageEvent, ProviderEvent } from './events.js';\nimport type { AnyIMessageProvider } from './provider.js';\nimport type {\n AddReactionInput,\n Conversation,\n EditMessageInput,\n IMessageProviderName,\n Message,\n MessageLocator,\n OpenConversationInput,\n ProviderConversation,\n ProviderMessage,\n RemoveReactionInput,\n SendMessageInput,\n SentMessage,\n SubscribeOptions,\n} from './types.js';\nimport { createFallbackConversationId, isFallbackConversationId } from './conversation-id.js';\nimport {\n ClientClosedError,\n UnsupportedCapabilityError,\n ValidationError,\n WebhookVerificationError,\n} from './errors.js';\n\ntype ProviderNameOf<TProvider extends AnyIMessageProvider> = TProvider['name'];\n\nexport const DEFAULT_CONNECTION_ID = 'default' as const;\n\nexport type ClientProvider<TProvider extends AnyIMessageProvider> = TProvider;\n\nexport type ClientProviders<TProvider extends AnyIMessageProvider> = {\n readonly [TName in TProvider['name']]: ClientProvider<\n Extract<TProvider, { readonly name: TName }>\n >;\n};\n\nexport interface IMessageClient<\n TProvider extends AnyIMessageProvider = AnyIMessageProvider,\n TConnectionId extends string = string,\n> {\n readonly provider: ProviderNameOf<TProvider>;\n readonly connectionId: TConnectionId;\n readonly capabilities: TProvider['capabilities'];\n readonly providers: ClientProviders<TProvider>;\n\n readonly messages: {\n send(input: SendMessageInput): Promise<SentMessage<ProviderNameOf<TProvider>, TConnectionId>>;\n get(message: MessageLocator): Promise<Message<ProviderNameOf<TProvider>, TConnectionId> | null>;\n edit(\n message: MessageLocator,\n input: EditMessageInput,\n ): Promise<Message<ProviderNameOf<TProvider>, TConnectionId>>;\n delete(message: MessageLocator): Promise<void>;\n };\n\n readonly conversations: {\n open(\n input: OpenConversationInput,\n ): Promise<Conversation<ProviderNameOf<TProvider>, TConnectionId>>;\n get(\n conversationId: string,\n ): Promise<Conversation<ProviderNameOf<TProvider>, TConnectionId> | null>;\n markRead(conversationId: string): Promise<void>;\n };\n\n readonly reactions: {\n add(input: AddReactionInput): Promise<void>;\n remove(input: RemoveReactionInput): Promise<void>;\n };\n\n readonly typing: {\n start(conversationId: string): Promise<void>;\n stop(conversationId: string): Promise<void>;\n };\n\n /** @experimental Webhook normalization may change before a future stable release. */\n readonly webhooks: {\n handle(\n request: Request,\n ): Promise<readonly IMessageEvent<ProviderNameOf<TProvider>, TConnectionId>[]>;\n };\n\n readonly events: {\n subscribe(\n options?: SubscribeOptions,\n ): AsyncIterable<IMessageEvent<ProviderNameOf<TProvider>, TConnectionId>>;\n };\n\n close(): Promise<void>;\n}\n\nexport interface CreateIMessageClientOptions<\n TProvider extends AnyIMessageProvider,\n TConnectionId extends string = typeof DEFAULT_CONNECTION_ID,\n> {\n readonly connectionId?: TConnectionId;\n readonly provider: TProvider;\n}\n\nfunction validateProvider(provider: AnyIMessageProvider): void {\n const capabilities = provider.capabilities;\n\n const requirements: readonly [boolean, unknown, string][] = [\n [capabilities.messages.get, provider.messages.get, 'messages.get'],\n [capabilities.messages.edit, provider.messages.edit, 'messages.edit'],\n [capabilities.messages.delete, provider.messages.delete, 'messages.delete'],\n [capabilities.conversations.get, provider.conversations.get, 'conversations.get'],\n [\n capabilities.conversations.markRead,\n provider.conversations.markRead,\n 'conversations.markRead',\n ],\n [capabilities.interactions.reactions, provider.reactions, 'reactions'],\n [capabilities.interactions.typingStart, provider.typing, 'typing.start'],\n [capabilities.interactions.typingStop, provider.typing?.stop, 'typing.stop'],\n [capabilities.events.webhooks, provider.webhooks, 'webhooks'],\n [capabilities.events.stream, provider.events, 'events.subscribe'],\n ];\n\n for (const [enabled, implementation, capability] of requirements) {\n if (enabled && implementation === undefined) {\n throw new ValidationError(\n `Provider ${provider.name} declares ${capability} but does not implement it.`,\n { provider: provider.name, code: 'invalid_provider_contract' },\n );\n }\n }\n}\n\nfunction decorateMessage<TProvider extends IMessageProviderName, TConnectionId extends string>(\n message: ProviderMessage,\n provider: TProvider,\n connectionId: TConnectionId,\n): Message<TProvider, TConnectionId> {\n return {\n ...message,\n id: message.providerMessageId,\n conversationId:\n message.conversationId ??\n createFallbackConversationId(message.providerMessageId, message.createdAt),\n provider,\n connectionId,\n };\n}\n\nfunction decorateConversation<TProvider extends IMessageProviderName, TConnectionId extends string>(\n conversation: ProviderConversation,\n provider: TProvider,\n connectionId: TConnectionId,\n): Conversation<TProvider, TConnectionId> {\n return {\n ...conversation,\n id: conversation.providerConversationId,\n provider,\n connectionId,\n };\n}\n\nfunction decorateEvent<TProvider extends IMessageProviderName, TConnectionId extends string>(\n event: ProviderEvent,\n provider: TProvider,\n connectionId: TConnectionId,\n): IMessageEvent<TProvider, TConnectionId> {\n switch (event.type) {\n case 'message.received':\n case 'message.sent':\n case 'message.delivered':\n case 'message.read':\n case 'message.failed':\n case 'message.edited':\n return {\n ...event,\n provider,\n connectionId,\n message: decorateMessage(event.message, provider, connectionId),\n };\n case 'message.deleted':\n case 'reaction.added':\n case 'reaction.removed':\n case 'typing.started':\n case 'typing.stopped':\n return { ...event, provider, connectionId };\n }\n}\n\nfunction mapEvents<TProvider extends IMessageProviderName, TConnectionId extends string>(\n events: AsyncIterable<ProviderEvent>,\n provider: TProvider,\n connectionId: TConnectionId,\n): AsyncIterable<IMessageEvent<TProvider, TConnectionId>> {\n return {\n async *[Symbol.asyncIterator]() {\n for await (const event of events) {\n yield decorateEvent(event, provider, connectionId);\n }\n },\n };\n}\n\nexport function createIMessageClient<\n const TProvider extends AnyIMessageProvider,\n const TConnectionId extends string = typeof DEFAULT_CONNECTION_ID,\n>(\n options: CreateIMessageClientOptions<TProvider, TConnectionId>,\n): IMessageClient<TProvider, TConnectionId> {\n const { provider } = options;\n const connectionId = (options.connectionId ?? DEFAULT_CONNECTION_ID) as TConnectionId;\n\n if (connectionId.trim().length === 0) {\n throw new ValidationError('connectionId must not be empty.', {\n provider: provider.name,\n code: 'invalid_connection_id',\n });\n }\n\n validateProvider(provider);\n\n let closed = false;\n let closePromise: Promise<void> | undefined;\n\n const errorContext = {\n provider: provider.name,\n connectionId,\n } as const;\n\n const assertOpen = (): void => {\n if (closed) {\n throw new ClientClosedError(errorContext);\n }\n };\n\n const unsupported = (capability: string): never => {\n throw new UnsupportedCapabilityError(capability, errorContext);\n };\n\n const assertRoutableConversationId = (conversationId: string): void => {\n if (isFallbackConversationId(conversationId)) {\n throw new ValidationError(\n 'SDK fallback conversation IDs are diagnostic and cannot be used for provider operations.',\n { ...errorContext, code: 'non_routable_conversation_id' },\n );\n }\n };\n\n const requireImplementation = <T>(implementation: T | undefined, capability: string): T => {\n if (implementation === undefined) {\n throw new UnsupportedCapabilityError(capability, errorContext);\n }\n\n return implementation;\n };\n\n const providers = Object.freeze({\n [provider.name]: provider,\n }) as ClientProviders<TProvider>;\n\n return {\n provider: provider.name,\n connectionId,\n capabilities: provider.capabilities,\n providers,\n messages: {\n async send(input) {\n assertOpen();\n\n if (input.conversationId !== undefined) {\n assertRoutableConversationId(input.conversationId);\n }\n\n if (input.text !== undefined && !provider.capabilities.messages.text) {\n unsupported('messages.text');\n }\n\n if (\n input.attachments !== undefined &&\n input.attachments.length > 0 &&\n !provider.capabilities.messages.attachments\n ) {\n unsupported('messages.attachments');\n }\n\n if (input.replyTo !== undefined && !provider.capabilities.messages.replies) {\n unsupported('messages.replies');\n }\n\n if (input.to !== undefined) {\n const recipients = Array.isArray(input.to) ? input.to : [input.to];\n const isGroup = recipients.length > 1;\n\n if (isGroup && !provider.capabilities.conversations.groups) {\n unsupported('conversations.groups');\n }\n\n if (!isGroup && !provider.capabilities.conversations.direct) {\n unsupported('conversations.direct');\n }\n }\n\n const message = await provider.messages.send(input);\n return decorateMessage(message, provider.name, connectionId) as SentMessage<\n ProviderNameOf<TProvider>,\n TConnectionId\n >;\n },\n async get(message) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.get) {\n unsupported('messages.get');\n }\n\n const get = requireImplementation(provider.messages.get, 'messages.get');\n\n const result = await get.call(provider.messages, message);\n return result === null ? null : decorateMessage(result, provider.name, connectionId);\n },\n async edit(message, input) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.edit) {\n unsupported('messages.edit');\n }\n\n const edit = requireImplementation(provider.messages.edit, 'messages.edit');\n\n const result = await edit.call(provider.messages, message, input);\n return decorateMessage(result, provider.name, connectionId);\n },\n async delete(message) {\n assertOpen();\n assertRoutableConversationId(message.conversationId);\n\n if (!provider.capabilities.messages.delete) {\n unsupported('messages.delete');\n }\n\n const deleteMessage = requireImplementation(provider.messages.delete, 'messages.delete');\n\n await deleteMessage.call(provider.messages, message);\n },\n },\n conversations: {\n async open(input) {\n assertOpen();\n const isGroup = input.participants.length > 1;\n\n if (isGroup && !provider.capabilities.conversations.groups) {\n unsupported('conversations.groups');\n }\n\n if (!isGroup && !provider.capabilities.conversations.direct) {\n unsupported('conversations.direct');\n }\n\n const conversation = await provider.conversations.open(input);\n return decorateConversation(conversation, provider.name, connectionId);\n },\n async get(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.conversations.get) {\n unsupported('conversations.get');\n }\n\n const get = requireImplementation(provider.conversations.get, 'conversations.get');\n\n const conversation = await get.call(provider.conversations, conversationId);\n return conversation === null\n ? null\n : decorateConversation(conversation, provider.name, connectionId);\n },\n async markRead(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.conversations.markRead) {\n unsupported('conversations.markRead');\n }\n\n const markRead = requireImplementation(\n provider.conversations.markRead,\n 'conversations.markRead',\n );\n await markRead.call(provider.conversations, conversationId);\n },\n },\n reactions: {\n async add(input) {\n assertOpen();\n assertRoutableConversationId(input.conversationId);\n\n if (!provider.capabilities.interactions.reactions) {\n unsupported('reactions.add');\n }\n\n const reactions = requireImplementation(provider.reactions, 'reactions.add');\n\n await reactions.add(input);\n },\n async remove(input) {\n assertOpen();\n assertRoutableConversationId(input.conversationId);\n\n if (!provider.capabilities.interactions.reactions) {\n unsupported('reactions.remove');\n }\n\n const reactions = requireImplementation(provider.reactions, 'reactions.remove');\n\n await reactions.remove(input);\n },\n },\n typing: {\n async start(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.interactions.typingStart) {\n unsupported('typing.start');\n }\n\n const typing = requireImplementation(provider.typing, 'typing.start');\n\n await typing.start(conversationId);\n },\n async stop(conversationId) {\n assertOpen();\n assertRoutableConversationId(conversationId);\n\n if (!provider.capabilities.interactions.typingStop) {\n unsupported('typing.stop');\n }\n\n const typing = requireImplementation(provider.typing, 'typing.stop');\n const stop = requireImplementation(typing.stop, 'typing.stop');\n\n await stop.call(typing, conversationId);\n },\n },\n webhooks: {\n async handle(request) {\n assertOpen();\n\n if (!provider.capabilities.events.webhooks) {\n unsupported('webhooks.handle');\n }\n\n const webhooks = requireImplementation(provider.webhooks, 'webhooks.handle');\n\n const verified = await webhooks.verify(request.clone());\n if (!verified) {\n throw new WebhookVerificationError(errorContext);\n }\n\n const events = await webhooks.parse(request);\n return events.map((event) => decorateEvent(event, provider.name, connectionId));\n },\n },\n events: {\n subscribe(options) {\n assertOpen();\n\n if (!provider.capabilities.events.stream) {\n unsupported('events.subscribe');\n }\n\n const events = requireImplementation(provider.events, 'events.subscribe');\n\n return mapEvents(events.subscribe(options), provider.name, connectionId);\n },\n },\n close() {\n if (closePromise !== undefined) {\n return closePromise;\n }\n\n closed = true;\n closePromise = Promise.resolve().then(async () => await provider.close?.());\n return closePromise;\n },\n };\n}\n","import type { IMessageCapabilities } from './capabilities.js';\nimport type { ProviderEvent } from './events.js';\nimport type {\n AddReactionInput,\n EditMessageInput,\n IMessageProviderName,\n MessageLocator,\n OpenConversationInput,\n ProviderConversation,\n ProviderMessage,\n ProviderSentMessage,\n RemoveReactionInput,\n SendMessageInput,\n SubscribeOptions,\n} from './types.js';\n\nexport interface ProviderMessages {\n send(input: SendMessageInput): Promise<ProviderSentMessage>;\n get?(message: MessageLocator): Promise<ProviderMessage | null>;\n edit?(message: MessageLocator, input: EditMessageInput): Promise<ProviderMessage>;\n delete?(message: MessageLocator): Promise<void>;\n}\n\nexport interface ProviderConversations {\n open(input: OpenConversationInput): Promise<ProviderConversation>;\n get?(conversationId: string): Promise<ProviderConversation | null>;\n markRead?(conversationId: string): Promise<void>;\n}\n\nexport interface ProviderReactions {\n add(input: AddReactionInput): Promise<void>;\n remove(input: RemoveReactionInput): Promise<void>;\n}\n\nexport interface ProviderTyping {\n start(conversationId: string): Promise<void>;\n stop?(conversationId: string): Promise<void>;\n}\n\n/**\n * Provider webhook verification and normalization contract.\n *\n * @experimental Webhook normalization may change before a future stable release.\n */\nexport interface ProviderWebhooks {\n verify(request: Request): Promise<boolean>;\n parse(request: Request): Promise<readonly ProviderEvent[]>;\n}\n\nexport interface ProviderEvents {\n subscribe(options?: SubscribeOptions): AsyncIterable<ProviderEvent>;\n}\n\n/**\n * Contract implemented by a provider adapter.\n *\n * The complete adapter is exposed at `client.providers.<name>`, so\n * provider-specific APIs should be defined directly on the concrete provider.\n */\nexport interface IMessageProvider<\n TName extends IMessageProviderName = IMessageProviderName,\n TCapabilities extends IMessageCapabilities = IMessageCapabilities,\n> {\n readonly name: TName;\n readonly capabilities: TCapabilities;\n readonly messages: ProviderMessages;\n readonly conversations: ProviderConversations;\n readonly reactions?: ProviderReactions;\n readonly typing?: ProviderTyping;\n /** @experimental Webhook normalization may change before a future stable release. */\n readonly webhooks?: ProviderWebhooks;\n readonly events?: ProviderEvents;\n close?(): Promise<void>;\n}\n\nexport type AnyIMessageProvider = IMessageProvider<IMessageProviderName, IMessageCapabilities>;\n\n/** Preserves the concrete name, capabilities, and methods of an adapter. */\nexport function defineProvider<const TProvider extends AnyIMessageProvider>(\n provider: TProvider,\n): TProvider {\n return provider;\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "imessage-sdk",
|
|
3
|
-
"version": "0.1.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "Provider-neutral TypeScript SDK for iMessage infrastructure",
|
|
5
5
|
"author": "jmisilo",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"imessage",
|
|
8
8
|
"messaging",
|
|
9
9
|
"sdk",
|
|
10
|
-
"typescript"
|
|
11
|
-
"blooio",
|
|
12
|
-
"photon"
|
|
10
|
+
"typescript"
|
|
13
11
|
],
|
|
14
12
|
"repository": {
|
|
15
13
|
"type": "git",
|
|
@@ -36,39 +34,20 @@
|
|
|
36
34
|
"import": "./dist/index.js",
|
|
37
35
|
"default": "./dist/index.js"
|
|
38
36
|
},
|
|
39
|
-
"./providers/blooio": {
|
|
40
|
-
"types": "./dist/providers/blooio.d.ts",
|
|
41
|
-
"import": "./dist/providers/blooio.js",
|
|
42
|
-
"default": "./dist/providers/blooio.js"
|
|
43
|
-
},
|
|
44
|
-
"./providers/photon": {
|
|
45
|
-
"types": "./dist/providers/photon.d.ts",
|
|
46
|
-
"import": "./dist/providers/photon.js",
|
|
47
|
-
"default": "./dist/providers/photon.js"
|
|
48
|
-
},
|
|
49
37
|
"./package.json": "./package.json"
|
|
50
38
|
},
|
|
51
39
|
"engines": {
|
|
52
40
|
"node": ">=20"
|
|
53
41
|
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"provenance": true
|
|
45
|
+
},
|
|
54
46
|
"scripts": {
|
|
55
47
|
"build": "tsup",
|
|
56
48
|
"dev": "tsup --watch",
|
|
57
|
-
"prepack": "pnpm build",
|
|
58
49
|
"test": "vitest run",
|
|
59
|
-
"test:integration:blooio": "BLOOIO_LIVE_TEST=1 vitest run test/blooio.integration.test.ts",
|
|
60
|
-
"test:integration:photon": "PHOTON_LIVE_TEST=1 vitest run test/photon.integration.test.ts",
|
|
61
|
-
"test:integration:photon-stream": "PHOTON_LIVE_STREAM_TEST=1 vitest run test/photon.integration.test.ts",
|
|
62
50
|
"test:watch": "vitest",
|
|
63
51
|
"typecheck": "tsc --project tsconfig.json --noEmit"
|
|
64
|
-
},
|
|
65
|
-
"publishConfig": {
|
|
66
|
-
"access": "public",
|
|
67
|
-
"provenance": true
|
|
68
|
-
},
|
|
69
|
-
"dependencies": {
|
|
70
|
-
"@photon-ai/advanced-imessage": "^1.0.0",
|
|
71
|
-
"@spectrum-ts/core": "^9.3.1",
|
|
72
|
-
"zod": "^4.4.3"
|
|
73
52
|
}
|
|
74
|
-
}
|
|
53
|
+
}
|