spectrum-ts 0.2.2 → 0.4.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.
@@ -1,9 +1,12 @@
1
1
  import {
2
+ asAttachment,
3
+ asCustom,
2
4
  stream
3
- } from "../../chunk-3TBRO2J7.js";
5
+ } from "../../chunk-5XW4CAWS.js";
4
6
  import {
7
+ asText,
5
8
  definePlatform
6
- } from "../../chunk-LIRM7SBA.js";
9
+ } from "../../chunk-XEEDIGVK.js";
7
10
 
8
11
  // src/providers/whatsapp-business/index.ts
9
12
  import {
@@ -11,107 +14,65 @@ import {
11
14
  } from "@photon-ai/whatsapp-business";
12
15
 
13
16
  // src/providers/whatsapp-business/messages.ts
14
- var toMessage = async (client, msg) => {
15
- const content = await mapContent(client, msg.content);
16
- return {
17
- id: msg.id,
18
- content,
19
- sender: { id: msg.from },
20
- space: { id: msg.from },
21
- timestamp: msg.timestamp
22
- };
23
- };
24
- var mapContent = async (client, content) => {
17
+ var toMessage = (client, msg) => ({
18
+ id: msg.id,
19
+ content: mapContent(client, msg.content),
20
+ sender: { id: msg.from },
21
+ space: { id: msg.from },
22
+ timestamp: msg.timestamp
23
+ });
24
+ var mapContent = (client, content) => {
25
25
  switch (content.type) {
26
26
  case "text":
27
- return [{ type: "plain_text", text: content.body }];
27
+ return asText(content.body);
28
28
  case "image":
29
29
  case "video":
30
30
  case "audio":
31
31
  case "document":
32
- return [await downloadMedia(client, content.media)];
32
+ return lazyMedia(client, content.media);
33
33
  case "sticker":
34
- return [
35
- {
36
- type: "custom",
37
- raw: { whatsapp_type: "sticker", ...content.sticker }
38
- }
39
- ];
34
+ return asCustom({ whatsapp_type: "sticker", ...content.sticker });
40
35
  case "location":
41
- return [
42
- {
43
- type: "custom",
44
- raw: { whatsapp_type: "location", ...content.location }
45
- }
46
- ];
36
+ return asCustom({ whatsapp_type: "location", ...content.location });
47
37
  case "contacts":
48
- return [
49
- {
50
- type: "custom",
51
- raw: { whatsapp_type: "contacts", contacts: content.contacts }
52
- }
53
- ];
38
+ return asCustom({
39
+ whatsapp_type: "contacts",
40
+ contacts: content.contacts
41
+ });
54
42
  case "reaction":
55
- return [
56
- {
57
- type: "custom",
58
- raw: { whatsapp_type: "reaction", ...content.reaction }
59
- }
60
- ];
43
+ return asCustom({ whatsapp_type: "reaction", ...content.reaction });
61
44
  case "interactive":
62
- return [
63
- {
64
- type: "custom",
65
- raw: { whatsapp_type: "interactive", ...content.interactive }
66
- }
67
- ];
45
+ return asCustom({ whatsapp_type: "interactive", ...content.interactive });
68
46
  case "button":
69
- return [
70
- {
71
- type: "custom",
72
- raw: { whatsapp_type: "button", ...content.button }
73
- }
74
- ];
47
+ return asCustom({ whatsapp_type: "button", ...content.button });
75
48
  case "order":
76
- return [
77
- { type: "custom", raw: { whatsapp_type: "order", ...content.order } }
78
- ];
49
+ return asCustom({ whatsapp_type: "order", ...content.order });
79
50
  case "system":
80
- return [
81
- {
82
- type: "custom",
83
- raw: { whatsapp_type: "system", ...content.system }
84
- }
85
- ];
51
+ return asCustom({ whatsapp_type: "system", ...content.system });
86
52
  default:
87
- return [{ type: "custom", raw: { whatsapp_type: "unknown" } }];
53
+ return asCustom({ whatsapp_type: "unknown" });
88
54
  }
89
55
  };
90
- var downloadMedia = async (client, media) => {
91
- try {
92
- const { url } = await client.media.getUrl(media.id);
93
- const response = await fetch(url);
94
- if (!response.ok) {
95
- throw new Error(`Media download failed: ${response.status}`);
96
- }
97
- const data = Buffer.from(await response.arrayBuffer());
98
- return {
99
- type: "attachment",
100
- data,
101
- mimeType: media.mimeType,
102
- name: media.filename ?? `media-${media.id}`
103
- };
104
- } catch {
105
- return {
106
- type: "custom",
107
- raw: {
108
- whatsapp_type: "media_error",
109
- mediaId: media.id,
110
- mimeType: media.mimeType
111
- }
112
- };
56
+ var fetchMedia = async (client, mediaId) => {
57
+ const { url } = await client.media.getUrl(mediaId);
58
+ const response = await fetch(url);
59
+ if (!response.ok) {
60
+ throw new Error(`Media download failed: ${response.status}`);
113
61
  }
62
+ return response;
114
63
  };
64
+ var lazyMedia = (client, media) => asAttachment({
65
+ name: media.filename ?? `media-${media.id}`,
66
+ mimeType: media.mimeType,
67
+ read: async () => Buffer.from(await (await fetchMedia(client, media.id)).arrayBuffer()),
68
+ stream: async () => {
69
+ const response = await fetchMedia(client, media.id);
70
+ if (!response.body) {
71
+ throw new Error("Media response missing body");
72
+ }
73
+ return response.body;
74
+ }
75
+ });
115
76
  var mimeToMediaType = (mimeType) => {
116
77
  if (mimeType.startsWith("image/")) {
117
78
  return "image";
@@ -132,8 +93,7 @@ var messages = (client) => {
132
93
  (async () => {
133
94
  try {
134
95
  for await (const event of eventStream) {
135
- const msg = await toMessage(client, event.message);
136
- emit(msg);
96
+ emit(toMessage(client, event.message));
137
97
  }
138
98
  end();
139
99
  } catch (e) {
@@ -145,12 +105,12 @@ var messages = (client) => {
145
105
  };
146
106
  var send = async (client, spaceId, content) => {
147
107
  switch (content.type) {
148
- case "plain_text":
108
+ case "text":
149
109
  await client.messages.send({ to: spaceId, text: content.text });
150
110
  break;
151
111
  case "attachment": {
152
112
  const { mediaId } = await client.media.upload({
153
- file: content.data,
113
+ file: await content.read(),
154
114
  mimeType: content.mimeType,
155
115
  filename: content.name
156
116
  });
@@ -174,7 +134,7 @@ var reactToMessage = async (client, spaceId, messageId, reaction) => {
174
134
  };
175
135
  var replyToMessage = async (client, spaceId, messageId, content) => {
176
136
  switch (content.type) {
177
- case "plain_text":
137
+ case "text":
178
138
  await client.messages.send({
179
139
  to: spaceId,
180
140
  replyTo: messageId,
@@ -183,7 +143,7 @@ var replyToMessage = async (client, spaceId, messageId, content) => {
183
143
  break;
184
144
  case "attachment": {
185
145
  const { mediaId } = await client.media.upload({
186
- file: content.data,
146
+ file: await content.read(),
187
147
  mimeType: content.mimeType,
188
148
  filename: content.name
189
149
  });
@@ -254,10 +214,7 @@ var whatsappBusiness = definePlatform("WhatsApp Business", {
254
214
  },
255
215
  actions: {
256
216
  send: async ({ space, content, client }) => {
257
- const wa = client;
258
- for (const item of content) {
259
- await send(wa, space.id, item);
260
- }
217
+ await send(client, space.id, content);
261
218
  },
262
219
  reactToMessage: async ({ space, messageId, reaction, client }) => {
263
220
  await reactToMessage(
@@ -268,10 +225,12 @@ var whatsappBusiness = definePlatform("WhatsApp Business", {
268
225
  );
269
226
  },
270
227
  replyToMessage: async ({ space, messageId, content, client }) => {
271
- const wa = client;
272
- for (const item of content) {
273
- await replyToMessage(wa, space.id, messageId, item);
274
- }
228
+ await replyToMessage(
229
+ client,
230
+ space.id,
231
+ messageId,
232
+ content
233
+ );
275
234
  }
276
235
  }
277
236
  });
@@ -2,33 +2,30 @@ import { Pipe, Tuples, Fn } from 'hotscript';
2
2
  import z__default from 'zod';
3
3
 
4
4
  declare const contentSchema: z__default.ZodDiscriminatedUnion<[z__default.ZodObject<{
5
- type: z__default.ZodLiteral<"plain_text">;
5
+ type: z__default.ZodLiteral<"text">;
6
6
  text: z__default.ZodString;
7
7
  }, z__default.core.$strip>, z__default.ZodObject<{
8
8
  type: z__default.ZodLiteral<"custom">;
9
- raw: z__default.ZodJSONSchema;
9
+ raw: z__default.ZodUnknown;
10
10
  }, z__default.core.$strip>, z__default.ZodObject<{
11
11
  type: z__default.ZodLiteral<"attachment">;
12
- data: z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>;
13
- mimeType: z__default.ZodString;
14
12
  name: z__default.ZodString;
13
+ mimeType: z__default.ZodString;
14
+ size: z__default.ZodOptional<z__default.ZodNumber>;
15
+ read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
16
+ stream: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
15
17
  }, z__default.core.$strip>], "type">;
16
18
  type Content = z__default.infer<typeof contentSchema>;
17
19
  interface ContentBuilder {
18
20
  build(): Promise<Content>;
19
21
  }
20
- declare function text(text: string): ContentBuilder;
21
- declare function custom(raw: z__default.infer<ReturnType<typeof z__default.json>>): ContentBuilder;
22
- declare function attachment(input: string | Buffer, options?: {
23
- mimeType?: string;
24
- name?: string;
25
- }): ContentBuilder;
22
+ type ContentInput = string | ContentBuilder;
26
23
 
27
24
  interface Space<_Def = unknown> {
28
25
  readonly __platform: string;
29
26
  readonly id: string;
30
27
  responding<T>(fn: () => T | Promise<T>): Promise<T>;
31
- send(...content: [ContentBuilder, ...ContentBuilder[]]): Promise<void>;
28
+ send(...content: [ContentInput, ...ContentInput[]]): Promise<void>;
32
29
  startTyping(): Promise<void>;
33
30
  stopTyping(): Promise<void>;
34
31
  }
@@ -39,11 +36,11 @@ interface User {
39
36
  }
40
37
 
41
38
  interface Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> {
42
- content: Content[];
39
+ content: Content;
43
40
  readonly id: string;
44
41
  platform: TPlatform;
45
42
  react(reaction: string): Promise<void>;
46
- reply(...content: [ContentBuilder, ...ContentBuilder[]]): Promise<void>;
43
+ reply(...content: [ContentInput, ...ContentInput[]]): Promise<void>;
47
44
  sender: TSender;
48
45
  space: TSpace;
49
46
  timestamp: Date;
@@ -65,7 +62,7 @@ type EventProducer<TPayload = unknown, TClient = unknown, TConfig = unknown> = (
65
62
  }) => AsyncIterable<TPayload>;
66
63
  type ProviderMessage<TSender extends ResolvedUser = ResolvedUser, TSpace extends ResolvedSpace = ResolvedSpace, TExtra extends object = Record<never, never>> = {
67
64
  id: string;
68
- content: Content[];
65
+ content: Content;
69
66
  sender: TSender;
70
67
  space: TSpace;
71
68
  timestamp?: Date;
@@ -82,7 +79,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
82
79
  actions: {
83
80
  send: (_: {
84
81
  space: _ResolvedSpace & SpaceRef;
85
- content: Content[];
82
+ content: Content;
86
83
  client: _Client;
87
84
  config: z__default.infer<_ConfigSchema>;
88
85
  }) => Promise<void>;
@@ -106,7 +103,7 @@ interface PlatformDef<_Name extends string = string, _ConfigSchema extends z__de
106
103
  replyToMessage?: (_: {
107
104
  space: _ResolvedSpace & SpaceRef;
108
105
  messageId: string;
109
- content: Content[];
106
+ content: Content;
110
107
  client: _Client;
111
108
  config: z__default.infer<_ConfigSchema>;
112
109
  }) => Promise<void>;
@@ -257,4 +254,4 @@ interface Platform<Def extends AnyPlatformDef> {
257
254
  (message: Message): PlatformMessage<Def>;
258
255
  }
259
256
 
260
- export { type AnyPlatformDef as A, type CustomEventStreams as C, type EventProducer as E, type Message as M, type ProviderMessage as P, type SpectrumLike as S, type User as U, type PlatformDef as a, type Platform as b, type PlatformProviderConfig as c, type Space as d, type ContentBuilder as e, type Content as f, type PlatformInstance as g, type PlatformMessage as h, type PlatformSpace as i, type PlatformUser as j, type SchemaMessage as k, attachment as l, custom as m, text as t };
257
+ export type { AnyPlatformDef as A, ContentBuilder as C, EventProducer as E, Message as M, 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 };
package/package.json CHANGED
@@ -1,56 +1,33 @@
1
1
  {
2
2
  "name": "spectrum-ts",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
8
8
  "files": [
9
- "dist",
10
- "src"
9
+ "dist"
11
10
  ],
12
11
  "exports": {
13
12
  ".": {
14
13
  "types": "./dist/index.d.ts",
15
- "bun": "./src/index.ts",
16
14
  "default": "./dist/index.js"
17
15
  },
18
- "./providers/imessage": {
19
- "types": "./dist/providers/imessage/index.d.ts",
20
- "bun": "./src/providers/imessage/index.ts",
21
- "default": "./dist/providers/imessage/index.js"
22
- },
23
- "./providers/terminal": {
24
- "types": "./dist/providers/terminal/index.d.ts",
25
- "bun": "./src/providers/terminal/index.ts",
26
- "default": "./dist/providers/terminal/index.js"
27
- },
28
- "./providers/whatsapp-business": {
29
- "types": "./dist/providers/whatsapp-business/index.d.ts",
30
- "bun": "./src/providers/whatsapp-business/index.ts",
31
- "default": "./dist/providers/whatsapp-business/index.js"
16
+ "./providers/*": {
17
+ "types": "./dist/providers/*/index.d.ts",
18
+ "default": "./dist/providers/*/index.js"
32
19
  }
33
20
  },
34
- "scripts": {
35
- "build": "tsup",
36
- "dev": "tsup --watch"
37
- },
38
21
  "dependencies": {
39
- "@photon-ai/advanced-imessage": "^0.4.2",
22
+ "@photon-ai/advanced-imessage": "^0.4.3",
40
23
  "@photon-ai/whatsapp-business": "^0.1.1",
41
- "@photon-ai/imessage-kit": "^2.1.2",
24
+ "@photon-ai/imessage-kit": "^3.0.0-rc.2",
42
25
  "@repeaterjs/repeater": "^3.0.6",
43
26
  "better-grpc": "^0.3.2",
44
27
  "mime-types": "^3.0.1",
45
28
  "type-fest": "^5.4.1",
46
29
  "zod": "^4.2.1"
47
30
  },
48
- "devDependencies": {
49
- "@types/bun": "latest",
50
- "@types/mime-types": "^3.0.1",
51
- "hotscript": "^1.0.13",
52
- "tsup": "^8.4.0"
53
- },
54
31
  "peerDependencies": {
55
32
  "typescript": "^5"
56
33
  },
@@ -1,58 +0,0 @@
1
- // src/utils/stream.ts
2
- import { Repeater } from "@repeaterjs/repeater";
3
- function stream(setup) {
4
- const repeater = new Repeater(async (push, stop) => {
5
- const emit = (value) => {
6
- Promise.resolve(push(value)).catch((error) => {
7
- stop(error);
8
- return void 0;
9
- });
10
- };
11
- const end = (error) => {
12
- stop(error);
13
- };
14
- const cleanup = await setup(emit, end);
15
- try {
16
- await stop;
17
- } finally {
18
- await cleanup?.();
19
- }
20
- });
21
- return Object.assign(repeater, {
22
- close: async () => {
23
- await repeater.return(void 0);
24
- }
25
- });
26
- }
27
- function mergeStreams(streams) {
28
- return stream((emit, end) => {
29
- if (streams.length === 0) {
30
- end();
31
- return;
32
- }
33
- let openStreams = streams.length;
34
- const workers = streams.map(async (source) => {
35
- try {
36
- for await (const value of source) {
37
- emit(value);
38
- }
39
- } catch (error) {
40
- end(error);
41
- } finally {
42
- openStreams -= 1;
43
- if (openStreams === 0) {
44
- end();
45
- }
46
- }
47
- });
48
- return async () => {
49
- await Promise.allSettled(streams.map((source) => source.close()));
50
- await Promise.allSettled(workers);
51
- };
52
- });
53
- }
54
-
55
- export {
56
- stream,
57
- mergeStreams
58
- };
package/src/index.ts DELETED
@@ -1,38 +0,0 @@
1
- // biome-ignore lint/performance/noBarrelFile: library entry point
2
- export { definePlatform } from "./platform/define";
3
- export type {
4
- AnyPlatformDef,
5
- EventProducer,
6
- Platform,
7
- PlatformDef,
8
- PlatformInstance,
9
- PlatformMessage,
10
- PlatformProviderConfig,
11
- PlatformSpace,
12
- PlatformUser,
13
- SchemaMessage,
14
- } from "./platform/types";
15
- export { Spectrum, type SpectrumInstance } from "./spectrum";
16
- export {
17
- attachment,
18
- type Content,
19
- type ContentBuilder,
20
- custom,
21
- text,
22
- } from "./types/content";
23
- export type { Message } from "./types/message";
24
- export type { Space } from "./types/space";
25
- export type { User } from "./types/user";
26
- export type {
27
- CloudPlatform,
28
- DedicatedTokenData,
29
- ImessageInfoData,
30
- PlatformStatus,
31
- PlatformsData,
32
- SharedTokenData,
33
- SubscriptionData,
34
- SubscriptionStatus,
35
- TokenData,
36
- } from "./utils/cloud";
37
- export { cloud, SpectrumCloudError } from "./utils/cloud";
38
- export { type ManagedStream, mergeStreams, stream } from "./utils/stream";