spectrum-ts 1.1.1 → 1.2.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.
@@ -3,7 +3,7 @@ import {
3
3
  cloud,
4
4
  mergeStreams,
5
5
  stream
6
- } from "../../chunk-PXX7ISZ6.js";
6
+ } from "../../chunk-FF2R4EP3.js";
7
7
  import {
8
8
  UnsupportedError,
9
9
  asAttachment,
@@ -12,7 +12,7 @@ import {
12
12
  asReaction,
13
13
  asText,
14
14
  definePlatform
15
- } from "../../chunk-7D6FHYKT.js";
15
+ } from "../../chunk-UQPIWAHH.js";
16
16
 
17
17
  // src/providers/whatsapp-business/index.ts
18
18
  import { createClient as createClient2 } from "@photon-ai/whatsapp-business";
@@ -266,8 +266,11 @@ var primary = (clients) => {
266
266
  }
267
267
  return client;
268
268
  };
269
- var toSendResult = (result) => ({
270
- id: result.messageId
269
+ var toRecord = (result, spaceId, content) => ({
270
+ id: result.messageId,
271
+ content,
272
+ space: { id: spaceId },
273
+ timestamp: /* @__PURE__ */ new Date()
271
274
  });
272
275
  var MAX_POLL_CACHE_SIZE = 1e3;
273
276
  var OPTION_ID_PREFIX = "opt_";
@@ -622,8 +625,10 @@ var send = async (clients, spaceId, content) => {
622
625
  const client = primary(clients);
623
626
  switch (content.type) {
624
627
  case "text":
625
- return toSendResult(
626
- await client.messages.send({ to: spaceId, text: content.text })
628
+ return toRecord(
629
+ await client.messages.send({ to: spaceId, text: content.text }),
630
+ spaceId,
631
+ content
627
632
  );
628
633
  case "attachment": {
629
634
  const { mediaId } = await client.media.upload({
@@ -633,19 +638,23 @@ var send = async (clients, spaceId, content) => {
633
638
  });
634
639
  const mediaType = mimeToMediaType(content.mimeType);
635
640
  const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
636
- return toSendResult(
641
+ return toRecord(
637
642
  await client.messages.send({
638
643
  to: spaceId,
639
644
  [mediaType]: mediaPayload
640
- })
645
+ }),
646
+ spaceId,
647
+ content
641
648
  );
642
649
  }
643
650
  case "contact":
644
- return toSendResult(
651
+ return toRecord(
645
652
  await client.messages.send({
646
653
  to: spaceId,
647
654
  contacts: [contactToWa(content)]
648
- })
655
+ }),
656
+ spaceId,
657
+ content
649
658
  );
650
659
  case "voice": {
651
660
  const { mediaId } = await client.media.upload({
@@ -653,11 +662,13 @@ var send = async (clients, spaceId, content) => {
653
662
  mimeType: content.mimeType,
654
663
  filename: voiceFilename(content)
655
664
  });
656
- return toSendResult(
665
+ return toRecord(
657
666
  await client.messages.send({
658
667
  to: spaceId,
659
668
  audio: { id: mediaId }
660
- })
669
+ }),
670
+ spaceId,
671
+ content
661
672
  );
662
673
  }
663
674
  case "poll": {
@@ -666,7 +677,7 @@ var send = async (clients, spaceId, content) => {
666
677
  interactive: pollToInteractive(content)
667
678
  });
668
679
  cachePoll(client, result.messageId, content);
669
- return toSendResult(result);
680
+ return toRecord(result, spaceId, content);
670
681
  }
671
682
  default:
672
683
  throw UnsupportedError.content(content.type);
@@ -682,12 +693,14 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
682
693
  const client = primary(clients);
683
694
  switch (content.type) {
684
695
  case "text":
685
- return toSendResult(
696
+ return toRecord(
686
697
  await client.messages.send({
687
698
  to: spaceId,
688
699
  replyTo: messageId,
689
700
  text: content.text
690
- })
701
+ }),
702
+ spaceId,
703
+ content
691
704
  );
692
705
  case "attachment": {
693
706
  const { mediaId } = await client.media.upload({
@@ -697,21 +710,25 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
697
710
  });
698
711
  const mediaType = mimeToMediaType(content.mimeType);
699
712
  const mediaPayload = mediaType === "document" ? { id: mediaId, filename: content.name } : { id: mediaId };
700
- return toSendResult(
713
+ return toRecord(
701
714
  await client.messages.send({
702
715
  to: spaceId,
703
716
  replyTo: messageId,
704
717
  [mediaType]: mediaPayload
705
- })
718
+ }),
719
+ spaceId,
720
+ content
706
721
  );
707
722
  }
708
723
  case "contact":
709
- return toSendResult(
724
+ return toRecord(
710
725
  await client.messages.send({
711
726
  to: spaceId,
712
727
  replyTo: messageId,
713
728
  contacts: [contactToWa(content)]
714
- })
729
+ }),
730
+ spaceId,
731
+ content
715
732
  );
716
733
  case "voice": {
717
734
  const { mediaId } = await client.media.upload({
@@ -719,12 +736,14 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
719
736
  mimeType: content.mimeType,
720
737
  filename: voiceFilename(content)
721
738
  });
722
- return toSendResult(
739
+ return toRecord(
723
740
  await client.messages.send({
724
741
  to: spaceId,
725
742
  replyTo: messageId,
726
743
  audio: { id: mediaId }
727
- })
744
+ }),
745
+ spaceId,
746
+ content
728
747
  );
729
748
  }
730
749
  case "poll": {
@@ -734,7 +753,7 @@ var replyToMessage = async (clients, spaceId, messageId, content) => {
734
753
  interactive: pollToInteractive(content)
735
754
  });
736
755
  cachePoll(client, result.messageId, content);
737
- return toSendResult(result);
756
+ return toRecord(result, spaceId, content);
738
757
  }
739
758
  default:
740
759
  throw UnsupportedError.content(content.type);
@@ -115,6 +115,20 @@ declare const contentSchema: z__default.ZodDiscriminatedUnion<[z__default.ZodObj
115
115
  }, z__default.core.$strip>;
116
116
  selected: z__default.ZodBoolean;
117
117
  title: z__default.ZodString;
118
+ }, z__default.core.$strip>, z__default.ZodObject<{
119
+ type: z__default.ZodLiteral<"effect">;
120
+ content: z__default.ZodDiscriminatedUnion<[z__default.ZodObject<{
121
+ type: z__default.ZodLiteral<"text">;
122
+ text: z__default.ZodString;
123
+ }, z__default.core.$strip>, z__default.ZodObject<{
124
+ type: z__default.ZodLiteral<"attachment">;
125
+ name: z__default.ZodString;
126
+ mimeType: z__default.ZodString;
127
+ size: z__default.ZodOptional<z__default.ZodNumber>;
128
+ read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
129
+ stream: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
130
+ }, z__default.core.$strip>], "type">;
131
+ effect: z__default.ZodString;
118
132
  }, z__default.core.$strip>], "type">;
119
133
  type Content = z__default.infer<typeof contentSchema>;
120
134
  interface ContentBuilder {
@@ -166,6 +180,18 @@ interface OutboundMessage<TPlatform extends string = string, TSender extends Use
166
180
  }
167
181
  type Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> = InboundMessage<TPlatform, TSender, TSpace> | OutboundMessage<TPlatform, TSender, TSpace>;
168
182
 
183
+ interface ManagedStream<T> extends AsyncIterable<T> {
184
+ close(): Promise<void>;
185
+ }
186
+ type StreamCleanup = void | (() => void | Promise<void>);
187
+ declare function stream<T>(setup: (emit: (value: T) => Promise<void>, end: (error?: unknown) => void) => StreamCleanup | Promise<StreamCleanup>): ManagedStream<T>;
188
+ declare function mergeStreams<T>(streams: readonly ManagedStream<T>[]): ManagedStream<T>;
189
+ interface Broadcaster<T> {
190
+ close(): Promise<void>;
191
+ subscribe(): ManagedStream<T>;
192
+ }
193
+ declare function broadcast<T>(source: ManagedStream<T>): Broadcaster<T>;
194
+
169
195
  type ResolvedSpace = Pick<Space, "id">;
170
196
  type SpaceRef = Pick<Space, "id" | "__platform">;
171
197
  type ResolvedUser = Pick<User, "id">;
@@ -187,19 +213,28 @@ type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends
187
213
  space: TSpace;
188
214
  timestamp?: Date;
189
215
  } & TExtra;
190
- interface SendResult<TSender extends ResolvedUser = ResolvedUser> {
191
- /**
192
- * Per-item send receipts returned when the dispatched content was a
193
- * `group`. Providers that iterate native sends to emulate a group
194
- * (e.g. iMessage) populate this so the platform build layer can
195
- * replace the outbound group's placeholder items with real Messages
196
- * that carry each item's own id.
197
- */
198
- groupMembers?: SendResult<TSender>[];
216
+ /**
217
+ * A message a provider produced — used for both inbound (`events.messages`,
218
+ * `getMessage`) and outbound (`send`, `replyToMessage`) flows. Providers
219
+ * return their native record shape (including platform extras like
220
+ * `partIndex`/`parentId` for iMessage) and the platform `wrapProviderMessage`
221
+ * pipeline turns it into a fully-built Message.
222
+ *
223
+ * `sender` is optional because outbound sends often can't synthesize one
224
+ * (the SDK doesn't surface the bot's own handle); inbound providers are
225
+ * expected to populate it.
226
+ */
227
+ type ProviderMessageRecord = {
199
228
  id: string;
200
- sender?: TSender;
229
+ content: Content;
230
+ sender?: {
231
+ id: string;
232
+ } & Record<string, unknown>;
233
+ space: {
234
+ id: string;
235
+ } & Record<string, unknown>;
201
236
  timestamp?: Date;
202
- }
237
+ } & Record<string, unknown>;
203
238
  type MergeSchema<TSchema extends z__default.ZodType | undefined, TBase extends object> = TSchema extends z__default.ZodType ? string extends keyof z__default.infer<TSchema> ? TBase : Omit<z__default.infer<TSchema>, keyof TBase> & TBase : TBase;
204
239
  type SchemaMessage<TUserSchema extends z__default.ZodType | undefined = undefined, TSpaceSchema extends z__default.ZodType | undefined = undefined> = ProviderMessage<MergeSchema<TUserSchema, ResolvedUser>, MergeSchema<TSpaceSchema, ResolvedSpace>>;
205
240
  type InferEventPayload<T> = T extends (ctx: never) => AsyncIterable<infer P> ? P : never;
@@ -215,7 +250,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
215
250
  content: Content;
216
251
  client: _Client;
217
252
  config: z__default.infer<_ConfigSchema>;
218
- }) => Promise<SendResult<_ResolvedUser>>;
253
+ }) => Promise<ProviderMessageRecord>;
219
254
  startTyping?: (_: {
220
255
  space: _ResolvedSpace & SpaceRef;
221
256
  client: _Client;
@@ -240,7 +275,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
240
275
  content: Content;
241
276
  client: _Client;
242
277
  config: z__default.infer<_ConfigSchema>;
243
- }) => Promise<SendResult<_ResolvedUser>>;
278
+ }) => Promise<ProviderMessageRecord>;
244
279
  editMessage?: (_: {
245
280
  space: _ResolvedSpace & SpaceRef;
246
281
  messageId: string;
@@ -298,11 +333,11 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
298
333
  }
299
334
  interface AnyPlatformDef {
300
335
  actions: {
301
- send: (_: any) => Promise<SendResult>;
336
+ send: (_: any) => Promise<ProviderMessageRecord>;
302
337
  startTyping?: (_: any) => Promise<void>;
303
338
  stopTyping?: (_: any) => Promise<void>;
304
339
  reactToMessage?: (_: any) => Promise<void>;
305
- replyToMessage?: (_: any) => Promise<SendResult>;
340
+ replyToMessage?: (_: any) => Promise<ProviderMessageRecord>;
306
341
  editMessage?: (_: any) => Promise<void>;
307
342
  getMessage?: (_: any) => Promise<any>;
308
343
  };
@@ -380,28 +415,38 @@ type SpaceVarargArgs<Def extends AnyPlatformDef> = [
380
415
  type SpaceArgs<Def extends AnyPlatformDef> = SpaceArrayArgs<Def> | SpaceVarargArgs<Def>;
381
416
  type PlatformSpace<Def extends AnyPlatformDef> = Omit<SpaceShapeOf<Def>, keyof Space> & Space;
382
417
  type PlatformMessage<Def extends AnyPlatformDef> = Omit<SchemaInfer<Def["message"]>, keyof Message> & Message<Def["name"], PlatformUser<Def>, PlatformSpace<Def>>;
418
+ type InboundPlatformMessage<Def extends AnyPlatformDef> = Omit<SchemaInfer<Def["message"]>, keyof InboundMessage> & InboundMessage<Def["name"], PlatformUser<Def>, PlatformSpace<Def>>;
383
419
  type PlatformUser<Def extends AnyPlatformDef> = Omit<ResolvedUserOf<Def>, keyof User> & User;
384
420
  type PlatformInstance<Def extends AnyPlatformDef> = {
421
+ readonly messages: AsyncIterable<[
422
+ PlatformSpace<Def>,
423
+ InboundPlatformMessage<Def>
424
+ ]>;
385
425
  space(...args: SpaceArgs<Def>): Promise<PlatformSpace<Def>>;
386
426
  user(userID: string): Promise<PlatformUser<Def>>;
387
427
  } & {
388
428
  [K in Exclude<keyof Def["events"], "messages" | symbol | number> as K extends ReservedNames ? never : K]: AsyncIterable<InferEventPayload<Def["events"][K]>>;
389
429
  };
430
+ interface PlatformRuntime {
431
+ client: unknown;
432
+ config: unknown;
433
+ definition: AnyPlatformDef;
434
+ subscribeMessages: () => ManagedStream<[Space, InboundMessage]>;
435
+ }
390
436
  interface SpectrumLike<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> {
391
437
  readonly __internal: {
392
- platforms: Map<string, {
393
- client: unknown;
394
- config: unknown;
395
- definition: AnyPlatformDef;
396
- }>;
438
+ platforms: Map<string, PlatformRuntime>;
397
439
  };
398
440
  readonly __providers: Providers;
399
441
  }
400
442
  interface Platform<Def extends AnyPlatformDef> {
401
443
  config(...args: Record<string, never> extends z__default.input<Def["config"]> ? [config?: z__default.input<Def["config"]>] : [config: z__default.input<Def["config"]>]): PlatformProviderConfig<Def>;
444
+ is(input: Message): input is PlatformMessage<Def>;
445
+ is(input: Space): input is PlatformSpace<Def>;
446
+ is(input: unknown): input is PlatformMessage<Def> | PlatformSpace<Def>;
402
447
  <Providers extends PlatformProviderConfig[]>(spectrum: SpectrumLike<Providers>): HasProvider<Providers, Def["name"]> extends true ? PlatformInstance<Def> : never;
403
448
  (space: Space): PlatformSpace<Def>;
404
449
  (message: Message): PlatformMessage<Def>;
405
450
  }
406
451
 
407
- export type { AnyPlatformDef as A, ContentBuilder as C, EventProducer as E, InboundMessage as I, Message as M, OutboundMessage as O, ProviderMessage as P, SpectrumLike as S, User as U, ContentInput as a, Content as b, PlatformDef as c, Platform as d, PlatformProviderConfig as e, CustomEventStreams as f, Space as g, PlatformInstance as h, PlatformMessage as i, PlatformSpace as j, PlatformUser as k, SchemaMessage as l };
452
+ export { type AnyPlatformDef as A, type Broadcaster as B, type ContentBuilder as C, type EventProducer as E, type InboundMessage as I, type Message as M, type OutboundMessage as O, type ProviderMessage as P, type SpectrumLike as S, type User as U, type ContentInput as a, type Content as b, type PlatformDef as c, type Platform as d, type PlatformProviderConfig as e, type CustomEventStreams as f, type Space as g, type InboundPlatformMessage as h, type ManagedStream as i, type PlatformInstance as j, type PlatformMessage as k, type PlatformRuntime as l, type PlatformSpace as m, type PlatformUser as n, type SchemaMessage as o, broadcast as p, mergeStreams as q, stream as s };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spectrum-ts",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -19,7 +19,7 @@
19
19
  }
20
20
  },
21
21
  "dependencies": {
22
- "@photon-ai/advanced-imessage": "^0.5.1",
22
+ "@photon-ai/advanced-imessage": "^0.6.0",
23
23
  "@photon-ai/imessage-kit": "^3.0.0",
24
24
  "@photon-ai/whatsapp-business": "^0.1.1",
25
25
  "@repeaterjs/repeater": "^3.0.6",
@@ -1,8 +0,0 @@
1
- interface ManagedStream<T> extends AsyncIterable<T> {
2
- close(): Promise<void>;
3
- }
4
- type StreamCleanup = void | (() => void | Promise<void>);
5
- declare function stream<T>(setup: (emit: (value: T) => Promise<void>, end: (error?: unknown) => void) => StreamCleanup | Promise<StreamCleanup>): ManagedStream<T>;
6
- declare function mergeStreams<T>(streams: readonly ManagedStream<T>[]): ManagedStream<T>;
7
-
8
- export { type ManagedStream as M, mergeStreams as m, stream as s };