spectrum-ts 0.4.0 → 0.5.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/dist/chunk-UZWRB3FZ.js +624 -0
- package/dist/index.d.ts +133 -3
- package/dist/index.js +130 -13
- package/dist/providers/imessage/index.d.ts +1 -1
- package/dist/providers/imessage/index.js +297 -46
- package/dist/providers/terminal/index.d.ts +1 -1
- package/dist/providers/whatsapp-business/index.d.ts +1 -1
- package/dist/providers/whatsapp-business/index.js +257 -14
- package/dist/{types-BdWMydUJ.d.ts → types-CfiD_00g.d.ts} +69 -5
- package/package.json +9 -2
- package/dist/chunk-5XW4CAWS.js +0 -165
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
2
|
asAttachment,
|
|
3
|
+
asContact,
|
|
3
4
|
asCustom,
|
|
4
5
|
stream
|
|
5
|
-
} from "../../chunk-
|
|
6
|
+
} from "../../chunk-UZWRB3FZ.js";
|
|
6
7
|
import {
|
|
7
8
|
asText,
|
|
8
9
|
definePlatform
|
|
@@ -14,13 +15,152 @@ import {
|
|
|
14
15
|
} from "@photon-ai/whatsapp-business";
|
|
15
16
|
|
|
16
17
|
// src/providers/whatsapp-business/messages.ts
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
import { extension as mimeExtension } from "mime-types";
|
|
19
|
+
var mapWaPhoneType = (type) => {
|
|
20
|
+
if (!type) {
|
|
21
|
+
return void 0;
|
|
22
|
+
}
|
|
23
|
+
const upper = type.toUpperCase();
|
|
24
|
+
if (upper === "CELL" || upper === "MOBILE" || upper === "IPHONE") {
|
|
25
|
+
return "mobile";
|
|
26
|
+
}
|
|
27
|
+
if (upper === "HOME") {
|
|
28
|
+
return "home";
|
|
29
|
+
}
|
|
30
|
+
if (upper === "WORK" || upper === "BUSINESS") {
|
|
31
|
+
return "work";
|
|
32
|
+
}
|
|
33
|
+
return "other";
|
|
34
|
+
};
|
|
35
|
+
var mapWaSimpleType = (type) => {
|
|
36
|
+
if (!type) {
|
|
37
|
+
return void 0;
|
|
38
|
+
}
|
|
39
|
+
const upper = type.toUpperCase();
|
|
40
|
+
if (upper === "HOME") {
|
|
41
|
+
return "home";
|
|
42
|
+
}
|
|
43
|
+
if (upper === "WORK" || upper === "BUSINESS") {
|
|
44
|
+
return "work";
|
|
45
|
+
}
|
|
46
|
+
return "other";
|
|
47
|
+
};
|
|
48
|
+
var waNameToSpectrum = (name) => {
|
|
49
|
+
const result = { formatted: name.formattedName };
|
|
50
|
+
if (name.firstName) {
|
|
51
|
+
result.first = name.firstName;
|
|
52
|
+
}
|
|
53
|
+
if (name.lastName) {
|
|
54
|
+
result.last = name.lastName;
|
|
55
|
+
}
|
|
56
|
+
if (name.middleName) {
|
|
57
|
+
result.middle = name.middleName;
|
|
58
|
+
}
|
|
59
|
+
if (name.prefix) {
|
|
60
|
+
result.prefix = name.prefix;
|
|
61
|
+
}
|
|
62
|
+
if (name.suffix) {
|
|
63
|
+
result.suffix = name.suffix;
|
|
64
|
+
}
|
|
65
|
+
return result;
|
|
66
|
+
};
|
|
67
|
+
var waPhoneToSpectrum = (phone) => {
|
|
68
|
+
const entry = { value: phone.phone };
|
|
69
|
+
const type = mapWaPhoneType(phone.type);
|
|
70
|
+
if (type) {
|
|
71
|
+
entry.type = type;
|
|
72
|
+
}
|
|
73
|
+
return entry;
|
|
74
|
+
};
|
|
75
|
+
var waEmailToSpectrum = (email) => {
|
|
76
|
+
const entry = { value: email.email };
|
|
77
|
+
const type = mapWaSimpleType(email.type);
|
|
78
|
+
if (type) {
|
|
79
|
+
entry.type = type;
|
|
80
|
+
}
|
|
81
|
+
return entry;
|
|
82
|
+
};
|
|
83
|
+
var waAddressToSpectrum = (address) => {
|
|
84
|
+
const entry = {};
|
|
85
|
+
if (address.street) {
|
|
86
|
+
entry.street = address.street;
|
|
87
|
+
}
|
|
88
|
+
if (address.city) {
|
|
89
|
+
entry.city = address.city;
|
|
90
|
+
}
|
|
91
|
+
if (address.state) {
|
|
92
|
+
entry.region = address.state;
|
|
93
|
+
}
|
|
94
|
+
if (address.zip) {
|
|
95
|
+
entry.postalCode = address.zip;
|
|
96
|
+
}
|
|
97
|
+
if (address.country) {
|
|
98
|
+
entry.country = address.country;
|
|
99
|
+
}
|
|
100
|
+
const type = mapWaSimpleType(address.type);
|
|
101
|
+
if (type) {
|
|
102
|
+
entry.type = type;
|
|
103
|
+
}
|
|
104
|
+
return entry;
|
|
105
|
+
};
|
|
106
|
+
var waOrgToSpectrum = (org) => {
|
|
107
|
+
const entry = {};
|
|
108
|
+
if (org.company) {
|
|
109
|
+
entry.name = org.company;
|
|
110
|
+
}
|
|
111
|
+
if (org.title) {
|
|
112
|
+
entry.title = org.title;
|
|
113
|
+
}
|
|
114
|
+
if (org.department) {
|
|
115
|
+
entry.department = org.department;
|
|
116
|
+
}
|
|
117
|
+
return entry;
|
|
118
|
+
};
|
|
119
|
+
var waContactToSpectrum = (card) => {
|
|
120
|
+
const input = { raw: card };
|
|
121
|
+
input.name = waNameToSpectrum(card.name);
|
|
122
|
+
if (card.phones.length > 0) {
|
|
123
|
+
input.phones = card.phones.map(waPhoneToSpectrum);
|
|
124
|
+
}
|
|
125
|
+
if (card.emails.length > 0) {
|
|
126
|
+
input.emails = card.emails.map(waEmailToSpectrum);
|
|
127
|
+
}
|
|
128
|
+
if (card.addresses.length > 0) {
|
|
129
|
+
input.addresses = card.addresses.map(waAddressToSpectrum);
|
|
130
|
+
}
|
|
131
|
+
if (card.org) {
|
|
132
|
+
input.org = waOrgToSpectrum(card.org);
|
|
133
|
+
}
|
|
134
|
+
if (card.urls.length > 0) {
|
|
135
|
+
input.urls = card.urls.map((u) => u.url);
|
|
136
|
+
}
|
|
137
|
+
if (card.birthday) {
|
|
138
|
+
input.birthday = card.birthday;
|
|
139
|
+
}
|
|
140
|
+
return asContact(input);
|
|
141
|
+
};
|
|
142
|
+
var toMessages = (client, msg) => {
|
|
143
|
+
const base = {
|
|
144
|
+
sender: { id: msg.from },
|
|
145
|
+
space: { id: msg.from },
|
|
146
|
+
timestamp: msg.timestamp
|
|
147
|
+
};
|
|
148
|
+
if (msg.content.type === "contacts") {
|
|
149
|
+
const multi = msg.content.contacts.length > 1;
|
|
150
|
+
return msg.content.contacts.map((card, index) => ({
|
|
151
|
+
...base,
|
|
152
|
+
id: multi ? `${msg.id}:${index}` : msg.id,
|
|
153
|
+
content: waContactToSpectrum(card)
|
|
154
|
+
}));
|
|
155
|
+
}
|
|
156
|
+
return [
|
|
157
|
+
{
|
|
158
|
+
...base,
|
|
159
|
+
id: msg.id,
|
|
160
|
+
content: mapContent(client, msg.content)
|
|
161
|
+
}
|
|
162
|
+
];
|
|
163
|
+
};
|
|
24
164
|
var mapContent = (client, content) => {
|
|
25
165
|
switch (content.type) {
|
|
26
166
|
case "text":
|
|
@@ -34,11 +174,6 @@ var mapContent = (client, content) => {
|
|
|
34
174
|
return asCustom({ whatsapp_type: "sticker", ...content.sticker });
|
|
35
175
|
case "location":
|
|
36
176
|
return asCustom({ whatsapp_type: "location", ...content.location });
|
|
37
|
-
case "contacts":
|
|
38
|
-
return asCustom({
|
|
39
|
-
whatsapp_type: "contacts",
|
|
40
|
-
contacts: content.contacts
|
|
41
|
-
});
|
|
42
177
|
case "reaction":
|
|
43
178
|
return asCustom({ whatsapp_type: "reaction", ...content.reaction });
|
|
44
179
|
case "interactive":
|
|
@@ -85,6 +220,74 @@ var mimeToMediaType = (mimeType) => {
|
|
|
85
220
|
}
|
|
86
221
|
return "document";
|
|
87
222
|
};
|
|
223
|
+
var voiceFilename = (content) => {
|
|
224
|
+
if (content.name) {
|
|
225
|
+
return content.name;
|
|
226
|
+
}
|
|
227
|
+
const ext = mimeExtension(content.mimeType);
|
|
228
|
+
return ext ? `voice.${ext}` : "voice";
|
|
229
|
+
};
|
|
230
|
+
var spectrumPhoneTypeToWa = (type) => {
|
|
231
|
+
if (type === "mobile") {
|
|
232
|
+
return "CELL";
|
|
233
|
+
}
|
|
234
|
+
if (type === "home" || type === "work" || type === "other") {
|
|
235
|
+
return type.toUpperCase();
|
|
236
|
+
}
|
|
237
|
+
return void 0;
|
|
238
|
+
};
|
|
239
|
+
var spectrumSimpleTypeToWa = (type) => type ? type.toUpperCase() : void 0;
|
|
240
|
+
var spectrumNameToWa = (name) => ({
|
|
241
|
+
formattedName: name?.formatted ?? ([name?.first, name?.middle, name?.last].filter((p) => Boolean(p)).join(" ") || "Unknown"),
|
|
242
|
+
firstName: name?.first,
|
|
243
|
+
lastName: name?.last,
|
|
244
|
+
middleName: name?.middle,
|
|
245
|
+
prefix: name?.prefix,
|
|
246
|
+
suffix: name?.suffix
|
|
247
|
+
});
|
|
248
|
+
var isWhatsAppContactCard = (value) => {
|
|
249
|
+
if (!value || typeof value !== "object") {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
const raw = value;
|
|
253
|
+
const name = raw.name;
|
|
254
|
+
if (!name || typeof name !== "object" || typeof name.formattedName !== "string") {
|
|
255
|
+
return false;
|
|
256
|
+
}
|
|
257
|
+
return Array.isArray(raw.phones) && Array.isArray(raw.emails) && Array.isArray(raw.addresses) && Array.isArray(raw.urls);
|
|
258
|
+
};
|
|
259
|
+
var contactToWa = (contact) => {
|
|
260
|
+
if (isWhatsAppContactCard(contact.raw)) {
|
|
261
|
+
return contact.raw;
|
|
262
|
+
}
|
|
263
|
+
const card = {
|
|
264
|
+
name: spectrumNameToWa(contact.name),
|
|
265
|
+
phones: (contact.phones ?? []).map((p) => ({
|
|
266
|
+
phone: p.value,
|
|
267
|
+
type: spectrumPhoneTypeToWa(p.type)
|
|
268
|
+
})),
|
|
269
|
+
emails: (contact.emails ?? []).map((e) => ({
|
|
270
|
+
email: e.value,
|
|
271
|
+
type: spectrumSimpleTypeToWa(e.type)
|
|
272
|
+
})),
|
|
273
|
+
addresses: (contact.addresses ?? []).map((a) => ({
|
|
274
|
+
street: a.street,
|
|
275
|
+
city: a.city,
|
|
276
|
+
state: a.region,
|
|
277
|
+
zip: a.postalCode,
|
|
278
|
+
country: a.country,
|
|
279
|
+
type: spectrumSimpleTypeToWa(a.type)
|
|
280
|
+
})),
|
|
281
|
+
urls: (contact.urls ?? []).map((url) => ({ url })),
|
|
282
|
+
org: contact.org?.name || contact.org?.department || contact.org?.title ? {
|
|
283
|
+
company: contact.org.name,
|
|
284
|
+
department: contact.org.department,
|
|
285
|
+
title: contact.org.title
|
|
286
|
+
} : void 0,
|
|
287
|
+
birthday: contact.birthday
|
|
288
|
+
};
|
|
289
|
+
return card;
|
|
290
|
+
};
|
|
88
291
|
var messages = (client) => {
|
|
89
292
|
const eventStream = client.events.subscribe().filter(
|
|
90
293
|
(e) => e.type === "message"
|
|
@@ -93,7 +296,9 @@ var messages = (client) => {
|
|
|
93
296
|
(async () => {
|
|
94
297
|
try {
|
|
95
298
|
for await (const event of eventStream) {
|
|
96
|
-
|
|
299
|
+
for (const m of toMessages(client, event.message)) {
|
|
300
|
+
emit(m);
|
|
301
|
+
}
|
|
97
302
|
}
|
|
98
303
|
end();
|
|
99
304
|
} catch (e) {
|
|
@@ -122,6 +327,24 @@ var send = async (client, spaceId, content) => {
|
|
|
122
327
|
});
|
|
123
328
|
break;
|
|
124
329
|
}
|
|
330
|
+
case "contact":
|
|
331
|
+
await client.messages.send({
|
|
332
|
+
to: spaceId,
|
|
333
|
+
contacts: [contactToWa(content)]
|
|
334
|
+
});
|
|
335
|
+
break;
|
|
336
|
+
case "voice": {
|
|
337
|
+
const { mediaId } = await client.media.upload({
|
|
338
|
+
file: await content.read(),
|
|
339
|
+
mimeType: content.mimeType,
|
|
340
|
+
filename: voiceFilename(content)
|
|
341
|
+
});
|
|
342
|
+
await client.messages.send({
|
|
343
|
+
to: spaceId,
|
|
344
|
+
audio: { id: mediaId }
|
|
345
|
+
});
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
125
348
|
default:
|
|
126
349
|
break;
|
|
127
350
|
}
|
|
@@ -156,6 +379,26 @@ var replyToMessage = async (client, spaceId, messageId, content) => {
|
|
|
156
379
|
});
|
|
157
380
|
break;
|
|
158
381
|
}
|
|
382
|
+
case "contact":
|
|
383
|
+
await client.messages.send({
|
|
384
|
+
to: spaceId,
|
|
385
|
+
replyTo: messageId,
|
|
386
|
+
contacts: [contactToWa(content)]
|
|
387
|
+
});
|
|
388
|
+
break;
|
|
389
|
+
case "voice": {
|
|
390
|
+
const { mediaId } = await client.media.upload({
|
|
391
|
+
file: await content.read(),
|
|
392
|
+
mimeType: content.mimeType,
|
|
393
|
+
filename: voiceFilename(content)
|
|
394
|
+
});
|
|
395
|
+
await client.messages.send({
|
|
396
|
+
to: spaceId,
|
|
397
|
+
replyTo: messageId,
|
|
398
|
+
audio: { id: mediaId }
|
|
399
|
+
});
|
|
400
|
+
break;
|
|
401
|
+
}
|
|
159
402
|
default:
|
|
160
403
|
break;
|
|
161
404
|
}
|
|
@@ -14,6 +14,70 @@ declare const contentSchema: z__default.ZodDiscriminatedUnion<[z__default.ZodObj
|
|
|
14
14
|
size: z__default.ZodOptional<z__default.ZodNumber>;
|
|
15
15
|
read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
|
|
16
16
|
stream: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
|
|
17
|
+
}, z__default.core.$strip>, z__default.ZodObject<{
|
|
18
|
+
type: z__default.ZodLiteral<"contact">;
|
|
19
|
+
user: z__default.ZodOptional<z__default.ZodObject<{
|
|
20
|
+
__platform: z__default.ZodString;
|
|
21
|
+
id: z__default.ZodString;
|
|
22
|
+
}, z__default.core.$strip>>;
|
|
23
|
+
name: z__default.ZodOptional<z__default.ZodObject<{
|
|
24
|
+
formatted: z__default.ZodOptional<z__default.ZodString>;
|
|
25
|
+
first: z__default.ZodOptional<z__default.ZodString>;
|
|
26
|
+
last: z__default.ZodOptional<z__default.ZodString>;
|
|
27
|
+
middle: z__default.ZodOptional<z__default.ZodString>;
|
|
28
|
+
prefix: z__default.ZodOptional<z__default.ZodString>;
|
|
29
|
+
suffix: z__default.ZodOptional<z__default.ZodString>;
|
|
30
|
+
}, z__default.core.$strip>>;
|
|
31
|
+
phones: z__default.ZodOptional<z__default.ZodArray<z__default.ZodObject<{
|
|
32
|
+
value: z__default.ZodString;
|
|
33
|
+
type: z__default.ZodOptional<z__default.ZodEnum<{
|
|
34
|
+
mobile: "mobile";
|
|
35
|
+
home: "home";
|
|
36
|
+
work: "work";
|
|
37
|
+
other: "other";
|
|
38
|
+
}>>;
|
|
39
|
+
}, z__default.core.$strip>>>;
|
|
40
|
+
emails: z__default.ZodOptional<z__default.ZodArray<z__default.ZodObject<{
|
|
41
|
+
value: z__default.ZodString;
|
|
42
|
+
type: z__default.ZodOptional<z__default.ZodEnum<{
|
|
43
|
+
home: "home";
|
|
44
|
+
work: "work";
|
|
45
|
+
other: "other";
|
|
46
|
+
}>>;
|
|
47
|
+
}, z__default.core.$strip>>>;
|
|
48
|
+
addresses: z__default.ZodOptional<z__default.ZodArray<z__default.ZodObject<{
|
|
49
|
+
street: z__default.ZodOptional<z__default.ZodString>;
|
|
50
|
+
city: z__default.ZodOptional<z__default.ZodString>;
|
|
51
|
+
region: z__default.ZodOptional<z__default.ZodString>;
|
|
52
|
+
postalCode: z__default.ZodOptional<z__default.ZodString>;
|
|
53
|
+
country: z__default.ZodOptional<z__default.ZodString>;
|
|
54
|
+
type: z__default.ZodOptional<z__default.ZodEnum<{
|
|
55
|
+
home: "home";
|
|
56
|
+
work: "work";
|
|
57
|
+
other: "other";
|
|
58
|
+
}>>;
|
|
59
|
+
}, z__default.core.$strip>>>;
|
|
60
|
+
org: z__default.ZodOptional<z__default.ZodObject<{
|
|
61
|
+
name: z__default.ZodOptional<z__default.ZodString>;
|
|
62
|
+
title: z__default.ZodOptional<z__default.ZodString>;
|
|
63
|
+
department: z__default.ZodOptional<z__default.ZodString>;
|
|
64
|
+
}, z__default.core.$strip>>;
|
|
65
|
+
urls: z__default.ZodOptional<z__default.ZodArray<z__default.ZodString>>;
|
|
66
|
+
birthday: z__default.ZodOptional<z__default.ZodString>;
|
|
67
|
+
note: z__default.ZodOptional<z__default.ZodString>;
|
|
68
|
+
photo: z__default.ZodOptional<z__default.ZodObject<{
|
|
69
|
+
mimeType: z__default.ZodString;
|
|
70
|
+
read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
|
|
71
|
+
}, z__default.core.$strip>>;
|
|
72
|
+
raw: z__default.ZodOptional<z__default.ZodUnknown>;
|
|
73
|
+
}, z__default.core.$strip>, z__default.ZodObject<{
|
|
74
|
+
type: z__default.ZodLiteral<"voice">;
|
|
75
|
+
name: z__default.ZodOptional<z__default.ZodString>;
|
|
76
|
+
mimeType: z__default.ZodString;
|
|
77
|
+
duration: z__default.ZodOptional<z__default.ZodNumber>;
|
|
78
|
+
size: z__default.ZodOptional<z__default.ZodNumber>;
|
|
79
|
+
read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
|
|
80
|
+
stream: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
|
|
17
81
|
}, z__default.core.$strip>], "type">;
|
|
18
82
|
type Content = z__default.infer<typeof contentSchema>;
|
|
19
83
|
interface ContentBuilder {
|
|
@@ -21,6 +85,11 @@ interface ContentBuilder {
|
|
|
21
85
|
}
|
|
22
86
|
type ContentInput = string | ContentBuilder;
|
|
23
87
|
|
|
88
|
+
interface User {
|
|
89
|
+
readonly __platform: string;
|
|
90
|
+
readonly id: string;
|
|
91
|
+
}
|
|
92
|
+
|
|
24
93
|
interface Space<_Def = unknown> {
|
|
25
94
|
readonly __platform: string;
|
|
26
95
|
readonly id: string;
|
|
@@ -30,11 +99,6 @@ interface Space<_Def = unknown> {
|
|
|
30
99
|
stopTyping(): Promise<void>;
|
|
31
100
|
}
|
|
32
101
|
|
|
33
|
-
interface User {
|
|
34
|
-
readonly __platform: string;
|
|
35
|
-
readonly id: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
102
|
interface Message<TPlatform extends string = string, TSender extends User = User, TSpace extends Space = Space> {
|
|
39
103
|
content: Content;
|
|
40
104
|
readonly id: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "spectrum-ts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -20,16 +20,23 @@
|
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"@photon-ai/advanced-imessage": "^0.4.3",
|
|
23
|
-
"@photon-ai/whatsapp-business": "^0.1.1",
|
|
24
23
|
"@photon-ai/imessage-kit": "^3.0.0-rc.2",
|
|
24
|
+
"@photon-ai/whatsapp-business": "^0.1.1",
|
|
25
25
|
"@repeaterjs/repeater": "^3.0.6",
|
|
26
26
|
"better-grpc": "^0.3.2",
|
|
27
27
|
"mime-types": "^3.0.1",
|
|
28
28
|
"type-fest": "^5.4.1",
|
|
29
|
+
"vcf": "^2.1.2",
|
|
29
30
|
"zod": "^4.2.1"
|
|
30
31
|
},
|
|
31
32
|
"peerDependencies": {
|
|
33
|
+
"ffmpeg-static": "^5",
|
|
32
34
|
"typescript": "^5"
|
|
33
35
|
},
|
|
36
|
+
"peerDependenciesMeta": {
|
|
37
|
+
"ffmpeg-static": {
|
|
38
|
+
"optional": true
|
|
39
|
+
}
|
|
40
|
+
},
|
|
34
41
|
"license": "MIT"
|
|
35
42
|
}
|
package/dist/chunk-5XW4CAWS.js
DELETED
|
@@ -1,165 +0,0 @@
|
|
|
1
|
-
// src/content/attachment.ts
|
|
2
|
-
import { createReadStream } from "fs";
|
|
3
|
-
import { readFile, stat } from "fs/promises";
|
|
4
|
-
import { basename } from "path";
|
|
5
|
-
import { Readable } from "stream";
|
|
6
|
-
import { lookup as lookupMimeType } from "mime-types";
|
|
7
|
-
import z from "zod";
|
|
8
|
-
var DEFAULT_ATTACHMENT_NAME = "attachment";
|
|
9
|
-
var readSchema = z.function({
|
|
10
|
-
input: [],
|
|
11
|
-
output: z.promise(z.instanceof(Buffer))
|
|
12
|
-
});
|
|
13
|
-
var streamSchema = z.function({
|
|
14
|
-
input: [],
|
|
15
|
-
output: z.promise(z.instanceof(ReadableStream))
|
|
16
|
-
});
|
|
17
|
-
var attachmentSchema = z.object({
|
|
18
|
-
type: z.literal("attachment"),
|
|
19
|
-
name: z.string().nonempty(),
|
|
20
|
-
mimeType: z.string().nonempty(),
|
|
21
|
-
size: z.number().int().nonnegative().optional(),
|
|
22
|
-
read: readSchema,
|
|
23
|
-
stream: streamSchema
|
|
24
|
-
});
|
|
25
|
-
var resolveAttachmentName = (input, name) => name || (typeof input === "string" ? basename(input) : DEFAULT_ATTACHMENT_NAME);
|
|
26
|
-
var resolveAttachmentMimeType = (name, mimeType) => {
|
|
27
|
-
if (mimeType) {
|
|
28
|
-
return mimeType;
|
|
29
|
-
}
|
|
30
|
-
const resolvedMimeType = lookupMimeType(name);
|
|
31
|
-
if (!resolvedMimeType) {
|
|
32
|
-
throw new Error(
|
|
33
|
-
`Unable to resolve MIME type for attachment "${name}". Pass options.mimeType explicitly.`
|
|
34
|
-
);
|
|
35
|
-
}
|
|
36
|
-
return resolvedMimeType;
|
|
37
|
-
};
|
|
38
|
-
var bufferToStream = (buf) => new ReadableStream({
|
|
39
|
-
start(controller) {
|
|
40
|
-
controller.enqueue(buf);
|
|
41
|
-
controller.close();
|
|
42
|
-
}
|
|
43
|
-
});
|
|
44
|
-
var asAttachment = (input) => {
|
|
45
|
-
let cached;
|
|
46
|
-
const read = () => {
|
|
47
|
-
cached ??= input.read().catch((err) => {
|
|
48
|
-
cached = void 0;
|
|
49
|
-
throw err;
|
|
50
|
-
});
|
|
51
|
-
return cached;
|
|
52
|
-
};
|
|
53
|
-
const stream2 = input.stream ?? (async () => bufferToStream(await read()));
|
|
54
|
-
return attachmentSchema.parse({
|
|
55
|
-
type: "attachment",
|
|
56
|
-
name: input.name,
|
|
57
|
-
mimeType: input.mimeType,
|
|
58
|
-
size: input.size,
|
|
59
|
-
read,
|
|
60
|
-
stream: stream2
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
function attachment(input, options) {
|
|
64
|
-
return {
|
|
65
|
-
build: async () => {
|
|
66
|
-
const name = resolveAttachmentName(input, options?.name);
|
|
67
|
-
const mimeType = resolveAttachmentMimeType(name, options?.mimeType);
|
|
68
|
-
if (typeof input === "string") {
|
|
69
|
-
const stats = await stat(input);
|
|
70
|
-
return asAttachment({
|
|
71
|
-
name,
|
|
72
|
-
mimeType,
|
|
73
|
-
size: stats.size,
|
|
74
|
-
read: () => readFile(input),
|
|
75
|
-
stream: async () => Readable.toWeb(
|
|
76
|
-
createReadStream(input)
|
|
77
|
-
)
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
return asAttachment({
|
|
81
|
-
name,
|
|
82
|
-
mimeType,
|
|
83
|
-
size: input.byteLength,
|
|
84
|
-
read: async () => input,
|
|
85
|
-
stream: async () => bufferToStream(input)
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
// src/content/custom.ts
|
|
92
|
-
import z2 from "zod";
|
|
93
|
-
var customSchema = z2.object({
|
|
94
|
-
type: z2.literal("custom"),
|
|
95
|
-
raw: z2.unknown()
|
|
96
|
-
});
|
|
97
|
-
var asCustom = (raw) => customSchema.parse({ type: "custom", raw });
|
|
98
|
-
function custom(raw) {
|
|
99
|
-
return {
|
|
100
|
-
build: async () => asCustom(raw)
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// src/utils/stream.ts
|
|
105
|
-
import { Repeater } from "@repeaterjs/repeater";
|
|
106
|
-
function stream(setup) {
|
|
107
|
-
const repeater = new Repeater(async (push, stop) => {
|
|
108
|
-
const emit = (value) => {
|
|
109
|
-
Promise.resolve(push(value)).catch((error) => {
|
|
110
|
-
stop(error);
|
|
111
|
-
return void 0;
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
const end = (error) => {
|
|
115
|
-
stop(error);
|
|
116
|
-
};
|
|
117
|
-
const cleanup = await setup(emit, end);
|
|
118
|
-
try {
|
|
119
|
-
await stop;
|
|
120
|
-
} finally {
|
|
121
|
-
await cleanup?.();
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
return Object.assign(repeater, {
|
|
125
|
-
close: async () => {
|
|
126
|
-
await repeater.return(void 0);
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
function mergeStreams(streams) {
|
|
131
|
-
return stream((emit, end) => {
|
|
132
|
-
if (streams.length === 0) {
|
|
133
|
-
end();
|
|
134
|
-
return;
|
|
135
|
-
}
|
|
136
|
-
let openStreams = streams.length;
|
|
137
|
-
const workers = streams.map(async (source) => {
|
|
138
|
-
try {
|
|
139
|
-
for await (const value of source) {
|
|
140
|
-
emit(value);
|
|
141
|
-
}
|
|
142
|
-
} catch (error) {
|
|
143
|
-
end(error);
|
|
144
|
-
} finally {
|
|
145
|
-
openStreams -= 1;
|
|
146
|
-
if (openStreams === 0) {
|
|
147
|
-
end();
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
});
|
|
151
|
-
return async () => {
|
|
152
|
-
await Promise.allSettled(streams.map((source) => source.close()));
|
|
153
|
-
await Promise.allSettled(workers);
|
|
154
|
-
};
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
export {
|
|
159
|
-
asAttachment,
|
|
160
|
-
attachment,
|
|
161
|
-
asCustom,
|
|
162
|
-
custom,
|
|
163
|
-
stream,
|
|
164
|
-
mergeStreams
|
|
165
|
-
};
|