spectrum-ts 1.9.2 → 1.12.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-TN54TDTQ.js → chunk-4TXLNBGE.js} +1 -1
- package/dist/{chunk-N3ZKMTSG.js → chunk-7Z3QGRGI.js} +8 -6
- package/dist/chunk-E7AXYNOZ.js +524 -0
- package/dist/{chunk-7O5BCLGQ.js → chunk-FPYXHZZA.js} +191 -97
- package/dist/chunk-KO67KDBD.js +61 -0
- package/dist/chunk-L3VXHUVY.js +457 -0
- package/dist/{chunk-5NHNMN4H.js → chunk-UFJZIZDO.js} +1 -1
- package/dist/{chunk-OR3VGVML.js → chunk-VQOW7X7U.js} +8 -4
- package/dist/{chunk-XZSBR26X.js → chunk-YDHES53X.js} +189 -500
- package/dist/{chunk-HWADNTQF.js → chunk-YKWKZ2PZ.js} +4 -59
- package/dist/index.d.ts +210 -85
- package/dist/index.js +17 -9
- package/dist/photo-content-BQF42prd.d.ts +13 -0
- package/dist/providers/imessage/index.d.ts +32 -5
- package/dist/providers/imessage/index.js +10 -6
- package/dist/providers/index.d.ts +4 -1
- package/dist/providers/index.js +13 -7
- package/dist/providers/slack/index.d.ts +47 -0
- package/dist/providers/slack/index.js +8 -0
- package/dist/providers/terminal/index.d.ts +46 -10
- package/dist/providers/terminal/index.js +4 -3
- package/dist/providers/whatsapp-business/index.d.ts +2 -2
- package/dist/providers/whatsapp-business/index.js +5 -3
- package/dist/{types-lUyzRurY.d.ts → types-BzW4gInA.d.ts} +231 -104
- package/package.json +12 -1
|
@@ -93,458 +93,79 @@ function attachment(input, options) {
|
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
// src/
|
|
97
|
-
import
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
var
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
};
|
|
117
|
-
var mapPhoneType = (prop) => {
|
|
118
|
-
const types = paramTypes(prop);
|
|
119
|
-
if (types.some((t) => t === "cell" || t === "mobile" || t === "iphone")) {
|
|
120
|
-
return "mobile";
|
|
121
|
-
}
|
|
122
|
-
if (types.includes("home")) {
|
|
123
|
-
return "home";
|
|
124
|
-
}
|
|
125
|
-
if (types.includes("work")) {
|
|
126
|
-
return "work";
|
|
127
|
-
}
|
|
128
|
-
if (types.length > 0) {
|
|
129
|
-
return "other";
|
|
130
|
-
}
|
|
131
|
-
return;
|
|
132
|
-
};
|
|
133
|
-
var mapSimpleType = (prop) => {
|
|
134
|
-
const types = paramTypes(prop);
|
|
135
|
-
if (types.includes("home")) {
|
|
136
|
-
return "home";
|
|
137
|
-
}
|
|
138
|
-
if (types.includes("work")) {
|
|
139
|
-
return "work";
|
|
140
|
-
}
|
|
141
|
-
if (types.length > 0) {
|
|
142
|
-
return "other";
|
|
143
|
-
}
|
|
144
|
-
return;
|
|
145
|
-
};
|
|
146
|
-
var splitStructured = (value) => value.split(";").map((part) => part.trim());
|
|
147
|
-
var extractName = (card) => {
|
|
148
|
-
const fn = propString(card.data.fn);
|
|
149
|
-
const n = propString(card.data.n);
|
|
150
|
-
if (!(fn || n)) {
|
|
151
|
-
return;
|
|
152
|
-
}
|
|
153
|
-
const result = {};
|
|
154
|
-
if (fn) {
|
|
155
|
-
result.formatted = fn;
|
|
156
|
-
}
|
|
157
|
-
if (n) {
|
|
158
|
-
const [last, first, middle, prefix, suffix] = splitStructured(n);
|
|
159
|
-
if (first) {
|
|
160
|
-
result.first = first;
|
|
161
|
-
}
|
|
162
|
-
if (last) {
|
|
163
|
-
result.last = last;
|
|
164
|
-
}
|
|
165
|
-
if (middle) {
|
|
166
|
-
result.middle = middle;
|
|
167
|
-
}
|
|
168
|
-
if (prefix) {
|
|
169
|
-
result.prefix = prefix;
|
|
170
|
-
}
|
|
171
|
-
if (suffix) {
|
|
172
|
-
result.suffix = suffix;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return result;
|
|
176
|
-
};
|
|
177
|
-
var extractPhones = (card) => {
|
|
178
|
-
const props = asPropertyArray(card.data.tel);
|
|
179
|
-
if (props.length === 0) {
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
return props.map((p) => {
|
|
183
|
-
const entry = { value: p.valueOf().trim() };
|
|
184
|
-
const type = mapPhoneType(p);
|
|
185
|
-
if (type) {
|
|
186
|
-
entry.type = type;
|
|
187
|
-
}
|
|
188
|
-
return entry;
|
|
189
|
-
});
|
|
190
|
-
};
|
|
191
|
-
var extractEmails = (card) => {
|
|
192
|
-
const props = asPropertyArray(card.data.email);
|
|
193
|
-
if (props.length === 0) {
|
|
194
|
-
return;
|
|
195
|
-
}
|
|
196
|
-
return props.map((p) => {
|
|
197
|
-
const entry = { value: p.valueOf().trim() };
|
|
198
|
-
const type = mapSimpleType(p);
|
|
199
|
-
if (type) {
|
|
200
|
-
entry.type = type;
|
|
201
|
-
}
|
|
202
|
-
return entry;
|
|
203
|
-
});
|
|
204
|
-
};
|
|
205
|
-
var extractAddresses = (card) => {
|
|
206
|
-
const props = asPropertyArray(card.data.adr);
|
|
207
|
-
if (props.length === 0) {
|
|
208
|
-
return;
|
|
209
|
-
}
|
|
210
|
-
return props.map((p) => {
|
|
211
|
-
const [, , street, city, region, postalCode, country] = splitStructured(
|
|
212
|
-
p.valueOf()
|
|
213
|
-
);
|
|
214
|
-
const entry = {};
|
|
215
|
-
if (street) {
|
|
216
|
-
entry.street = street;
|
|
217
|
-
}
|
|
218
|
-
if (city) {
|
|
219
|
-
entry.city = city;
|
|
220
|
-
}
|
|
221
|
-
if (region) {
|
|
222
|
-
entry.region = region;
|
|
223
|
-
}
|
|
224
|
-
if (postalCode) {
|
|
225
|
-
entry.postalCode = postalCode;
|
|
226
|
-
}
|
|
227
|
-
if (country) {
|
|
228
|
-
entry.country = country;
|
|
229
|
-
}
|
|
230
|
-
const type = mapSimpleType(p);
|
|
231
|
-
if (type) {
|
|
232
|
-
entry.type = type;
|
|
233
|
-
}
|
|
234
|
-
return entry;
|
|
235
|
-
});
|
|
236
|
-
};
|
|
237
|
-
var extractOrg = (card) => {
|
|
238
|
-
const orgStr = propString(card.data.org);
|
|
239
|
-
const title = propString(card.data.title);
|
|
240
|
-
if (!(orgStr || title)) {
|
|
241
|
-
return;
|
|
96
|
+
// src/content/avatar.ts
|
|
97
|
+
import z4 from "zod";
|
|
98
|
+
|
|
99
|
+
// src/utils/photo-content.ts
|
|
100
|
+
import { readFile as readFile2 } from "fs/promises";
|
|
101
|
+
import { basename as basename2 } from "path";
|
|
102
|
+
import { lookup as lookupMimeType2 } from "mime-types";
|
|
103
|
+
import z3 from "zod";
|
|
104
|
+
var CLEAR_SENTINEL = "clear";
|
|
105
|
+
var photoActionSchema = z3.discriminatedUnion("kind", [
|
|
106
|
+
z3.object({
|
|
107
|
+
kind: z3.literal("set"),
|
|
108
|
+
read: readSchema,
|
|
109
|
+
mimeType: z3.string().nonempty()
|
|
110
|
+
}),
|
|
111
|
+
z3.object({ kind: z3.literal("clear") })
|
|
112
|
+
]);
|
|
113
|
+
var resolveMimeType = (input, mimeType, contentLabel) => {
|
|
114
|
+
if (mimeType) {
|
|
115
|
+
return mimeType;
|
|
242
116
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
result.name = name;
|
|
248
|
-
}
|
|
249
|
-
if (department) {
|
|
250
|
-
result.department = department;
|
|
117
|
+
if (typeof input === "string") {
|
|
118
|
+
const resolved = lookupMimeType2(basename2(input));
|
|
119
|
+
if (resolved) {
|
|
120
|
+
return resolved;
|
|
251
121
|
}
|
|
252
122
|
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
}
|
|
256
|
-
return result;
|
|
257
|
-
};
|
|
258
|
-
var extractUrls = (card) => {
|
|
259
|
-
const props = asPropertyArray(card.data.url);
|
|
260
|
-
if (props.length === 0) {
|
|
261
|
-
return;
|
|
262
|
-
}
|
|
263
|
-
return props.map((p) => p.valueOf().trim());
|
|
264
|
-
};
|
|
265
|
-
var photoMimeFromType = (type) => {
|
|
266
|
-
if (!type) {
|
|
267
|
-
return "image/jpeg";
|
|
268
|
-
}
|
|
269
|
-
const lower = type.toLowerCase();
|
|
270
|
-
if (lower.startsWith("image/")) {
|
|
271
|
-
return lower;
|
|
272
|
-
}
|
|
273
|
-
return `image/${lower}`;
|
|
274
|
-
};
|
|
275
|
-
var DATA_URI_PATTERN = /^data:([^;,]+);base64,(.*)$/i;
|
|
276
|
-
var extractPhoto = (card) => {
|
|
277
|
-
const [prop] = asPropertyArray(card.data.photo);
|
|
278
|
-
if (!prop) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
const value = prop.valueOf();
|
|
282
|
-
const dataUriMatch = DATA_URI_PATTERN.exec(value);
|
|
283
|
-
if (dataUriMatch) {
|
|
284
|
-
const [, mimeType, base64] = dataUriMatch;
|
|
285
|
-
const buf2 = Buffer.from(base64 ?? "", "base64");
|
|
286
|
-
return {
|
|
287
|
-
mimeType: mimeType ?? "image/jpeg",
|
|
288
|
-
read: async () => buf2
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
const type = Array.isArray(prop.type) ? prop.type[0] : prop.type;
|
|
292
|
-
const buf = Buffer.from(value, "base64");
|
|
293
|
-
return {
|
|
294
|
-
mimeType: photoMimeFromType(type),
|
|
295
|
-
read: async () => buf
|
|
296
|
-
};
|
|
297
|
-
};
|
|
298
|
-
var normalizeVCardInput = (vcf) => {
|
|
299
|
-
const withoutBom = vcf.charCodeAt(0) === 65279 ? vcf.slice(1) : vcf;
|
|
300
|
-
return withoutBom.replace(/\r\n|\r|\n/g, "\r\n");
|
|
301
|
-
};
|
|
302
|
-
var fromVCard = (vcf) => {
|
|
303
|
-
const [card] = vCard.parse(normalizeVCardInput(vcf));
|
|
304
|
-
if (!card) {
|
|
305
|
-
throw new Error("Invalid vCard: no cards parsed");
|
|
306
|
-
}
|
|
307
|
-
const input = { raw: vcf };
|
|
308
|
-
const name = extractName(card);
|
|
309
|
-
if (name) {
|
|
310
|
-
input.name = name;
|
|
311
|
-
}
|
|
312
|
-
const phones = extractPhones(card);
|
|
313
|
-
if (phones) {
|
|
314
|
-
input.phones = phones;
|
|
315
|
-
}
|
|
316
|
-
const emails = extractEmails(card);
|
|
317
|
-
if (emails) {
|
|
318
|
-
input.emails = emails;
|
|
319
|
-
}
|
|
320
|
-
const addresses = extractAddresses(card);
|
|
321
|
-
if (addresses) {
|
|
322
|
-
input.addresses = addresses;
|
|
323
|
-
}
|
|
324
|
-
const org = extractOrg(card);
|
|
325
|
-
if (org) {
|
|
326
|
-
input.org = org;
|
|
327
|
-
}
|
|
328
|
-
const urls = extractUrls(card);
|
|
329
|
-
if (urls) {
|
|
330
|
-
input.urls = urls;
|
|
331
|
-
}
|
|
332
|
-
const birthday = propString(card.data.bday);
|
|
333
|
-
if (birthday) {
|
|
334
|
-
input.birthday = birthday;
|
|
335
|
-
}
|
|
336
|
-
const note = propString(card.data.note);
|
|
337
|
-
if (note) {
|
|
338
|
-
input.note = note;
|
|
339
|
-
}
|
|
340
|
-
const photo = extractPhoto(card);
|
|
341
|
-
if (photo) {
|
|
342
|
-
input.photo = photo;
|
|
343
|
-
}
|
|
344
|
-
return input;
|
|
345
|
-
};
|
|
346
|
-
var formattedNameFor = (name) => {
|
|
347
|
-
if (name?.formatted) {
|
|
348
|
-
return name.formatted;
|
|
349
|
-
}
|
|
350
|
-
const parts = [name?.first, name?.middle, name?.last].filter(
|
|
351
|
-
(p) => Boolean(p)
|
|
123
|
+
throw new Error(
|
|
124
|
+
`Unable to resolve MIME type for ${contentLabel}. Pass options.mimeType explicitly.`
|
|
352
125
|
);
|
|
353
|
-
if (parts.length > 0) {
|
|
354
|
-
return parts.join(" ");
|
|
355
|
-
}
|
|
356
|
-
return "Unknown";
|
|
357
|
-
};
|
|
358
|
-
var phoneTypeParam = (type) => {
|
|
359
|
-
if (type === "mobile") {
|
|
360
|
-
return "CELL";
|
|
361
|
-
}
|
|
362
|
-
if (type === "home" || type === "work" || type === "other") {
|
|
363
|
-
return type.toUpperCase();
|
|
364
|
-
}
|
|
365
|
-
return;
|
|
366
|
-
};
|
|
367
|
-
var simpleTypeParam = (type) => type ? type.toUpperCase() : void 0;
|
|
368
|
-
var photoTypeParam = (mimeType) => {
|
|
369
|
-
const sub = mimeType.split("/")[1] ?? "jpeg";
|
|
370
|
-
return sub.toUpperCase();
|
|
371
|
-
};
|
|
372
|
-
var writeName = (card, name) => {
|
|
373
|
-
card.set("fn", formattedNameFor(name));
|
|
374
|
-
if (!name) {
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
if (name.first || name.last || name.middle || name.prefix || name.suffix) {
|
|
378
|
-
card.set(
|
|
379
|
-
"n",
|
|
380
|
-
[
|
|
381
|
-
name.last ?? "",
|
|
382
|
-
name.first ?? "",
|
|
383
|
-
name.middle ?? "",
|
|
384
|
-
name.prefix ?? "",
|
|
385
|
-
name.suffix ?? ""
|
|
386
|
-
].join(";")
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
};
|
|
390
|
-
var writePhones = (card, phones) => {
|
|
391
|
-
for (const phone of phones ?? []) {
|
|
392
|
-
const type = phoneTypeParam(phone.type);
|
|
393
|
-
card.add("tel", phone.value, type ? { type } : void 0);
|
|
394
|
-
}
|
|
395
126
|
};
|
|
396
|
-
var
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
"",
|
|
406
|
-
"",
|
|
407
|
-
addr.street ?? "",
|
|
408
|
-
addr.city ?? "",
|
|
409
|
-
addr.region ?? "",
|
|
410
|
-
addr.postalCode ?? "",
|
|
411
|
-
addr.country ?? ""
|
|
412
|
-
].join(";");
|
|
413
|
-
const type = simpleTypeParam(addr.type);
|
|
414
|
-
card.add("adr", value, type ? { type } : void 0);
|
|
415
|
-
}
|
|
416
|
-
};
|
|
417
|
-
var writeOrg = (card, org) => {
|
|
418
|
-
if (!org) {
|
|
419
|
-
return;
|
|
420
|
-
}
|
|
421
|
-
if (org.name || org.department) {
|
|
422
|
-
card.set("org", [org.name ?? "", org.department ?? ""].join(";"));
|
|
423
|
-
}
|
|
424
|
-
if (org.title) {
|
|
425
|
-
card.set("title", org.title);
|
|
426
|
-
}
|
|
427
|
-
};
|
|
428
|
-
var writeUrls = (card, urls) => {
|
|
429
|
-
for (const url of urls ?? []) {
|
|
430
|
-
card.add("url", url);
|
|
431
|
-
}
|
|
432
|
-
};
|
|
433
|
-
var writePhoto = async (card, photo) => {
|
|
434
|
-
if (!photo) {
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
const buf = await photo.read();
|
|
438
|
-
card.set("photo", buf.toString("base64"), {
|
|
439
|
-
encoding: "b",
|
|
440
|
-
type: photoTypeParam(photo.mimeType)
|
|
441
|
-
});
|
|
127
|
+
var cachedRead = (read) => {
|
|
128
|
+
let cached;
|
|
129
|
+
return () => {
|
|
130
|
+
cached ??= read().catch((err) => {
|
|
131
|
+
cached = void 0;
|
|
132
|
+
throw err;
|
|
133
|
+
});
|
|
134
|
+
return cached;
|
|
135
|
+
};
|
|
442
136
|
};
|
|
443
|
-
var
|
|
444
|
-
if (
|
|
445
|
-
return
|
|
446
|
-
}
|
|
447
|
-
const
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
}
|
|
457
|
-
if (contact2.note) {
|
|
458
|
-
card.set("note", contact2.note);
|
|
459
|
-
}
|
|
460
|
-
await writePhoto(card, contact2.photo);
|
|
461
|
-
return card.toString();
|
|
137
|
+
var buildPhotoAction = (input, options, contentLabel) => {
|
|
138
|
+
if (input === CLEAR_SENTINEL) {
|
|
139
|
+
return { kind: "clear" };
|
|
140
|
+
}
|
|
141
|
+
const mimeType = resolveMimeType(input, options?.mimeType, contentLabel);
|
|
142
|
+
let read;
|
|
143
|
+
if (typeof input === "string") {
|
|
144
|
+
read = cachedRead(() => readFile2(input));
|
|
145
|
+
} else {
|
|
146
|
+
const snapshot = Buffer.from(input);
|
|
147
|
+
read = cachedRead(async () => snapshot);
|
|
148
|
+
}
|
|
149
|
+
return { kind: "set", read, mimeType };
|
|
462
150
|
};
|
|
463
151
|
|
|
464
|
-
// src/content/
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
__platform: z3.string(),
|
|
469
|
-
id: z3.string()
|
|
152
|
+
// src/content/avatar.ts
|
|
153
|
+
var avatarSchema = z4.object({
|
|
154
|
+
type: z4.literal("avatar"),
|
|
155
|
+
action: photoActionSchema
|
|
470
156
|
});
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
first: z3.string().optional(),
|
|
474
|
-
last: z3.string().optional(),
|
|
475
|
-
middle: z3.string().optional(),
|
|
476
|
-
prefix: z3.string().optional(),
|
|
477
|
-
suffix: z3.string().optional()
|
|
478
|
-
});
|
|
479
|
-
var phoneTypeSchema = z3.enum(["mobile", "home", "work", "other"]);
|
|
480
|
-
var emailTypeSchema = z3.enum(["home", "work", "other"]);
|
|
481
|
-
var addressTypeSchema = z3.enum(["home", "work", "other"]);
|
|
482
|
-
var phoneSchema = z3.object({
|
|
483
|
-
value: z3.string(),
|
|
484
|
-
type: phoneTypeSchema.optional()
|
|
485
|
-
});
|
|
486
|
-
var emailSchema = z3.object({
|
|
487
|
-
value: z3.string(),
|
|
488
|
-
type: emailTypeSchema.optional()
|
|
489
|
-
});
|
|
490
|
-
var addressSchema = z3.object({
|
|
491
|
-
street: z3.string().optional(),
|
|
492
|
-
city: z3.string().optional(),
|
|
493
|
-
region: z3.string().optional(),
|
|
494
|
-
postalCode: z3.string().optional(),
|
|
495
|
-
country: z3.string().optional(),
|
|
496
|
-
type: addressTypeSchema.optional()
|
|
497
|
-
});
|
|
498
|
-
var orgSchema = z3.object({
|
|
499
|
-
name: z3.string().optional(),
|
|
500
|
-
title: z3.string().optional(),
|
|
501
|
-
department: z3.string().optional()
|
|
502
|
-
});
|
|
503
|
-
var photoSchema = z3.object({
|
|
504
|
-
mimeType: z3.string(),
|
|
505
|
-
read: readSchema
|
|
506
|
-
});
|
|
507
|
-
var contactSchema = z3.object({
|
|
508
|
-
type: z3.literal("contact"),
|
|
509
|
-
user: userRefSchema.optional(),
|
|
510
|
-
name: nameSchema.optional(),
|
|
511
|
-
phones: z3.array(phoneSchema).optional(),
|
|
512
|
-
emails: z3.array(emailSchema).optional(),
|
|
513
|
-
addresses: z3.array(addressSchema).optional(),
|
|
514
|
-
org: orgSchema.optional(),
|
|
515
|
-
urls: z3.array(z3.string()).optional(),
|
|
516
|
-
birthday: z3.string().optional(),
|
|
517
|
-
note: z3.string().optional(),
|
|
518
|
-
photo: photoSchema.optional(),
|
|
519
|
-
raw: z3.unknown().optional()
|
|
520
|
-
});
|
|
521
|
-
var asContact = (input) => contactSchema.parse({ type: "contact", ...input });
|
|
522
|
-
var isUser = (value) => typeof value === "object" && value !== null && "__platform" in value && "id" in value && typeof value.__platform === "string" && typeof value.id === "string";
|
|
523
|
-
function contact(input, details) {
|
|
157
|
+
function avatar(input, options) {
|
|
158
|
+
const action = buildPhotoAction(input, options, "avatar");
|
|
524
159
|
return {
|
|
525
|
-
build: async () => {
|
|
526
|
-
if (typeof input === "string") {
|
|
527
|
-
return asContact(fromVCard(input));
|
|
528
|
-
}
|
|
529
|
-
if (input instanceof vCard2) {
|
|
530
|
-
return asContact(fromVCard(input.toString()));
|
|
531
|
-
}
|
|
532
|
-
if (isUser(input)) {
|
|
533
|
-
return asContact({
|
|
534
|
-
user: { __platform: input.__platform, id: input.id },
|
|
535
|
-
...details
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
return asContact(input);
|
|
539
|
-
}
|
|
160
|
+
build: async () => avatarSchema.parse({ type: "avatar", action })
|
|
540
161
|
};
|
|
541
162
|
}
|
|
542
163
|
|
|
543
164
|
// src/content/custom.ts
|
|
544
|
-
import
|
|
545
|
-
var customSchema =
|
|
546
|
-
type:
|
|
547
|
-
raw:
|
|
165
|
+
import z5 from "zod";
|
|
166
|
+
var customSchema = z5.object({
|
|
167
|
+
type: z5.literal("custom"),
|
|
168
|
+
raw: z5.unknown()
|
|
548
169
|
});
|
|
549
170
|
var asCustom = (raw) => customSchema.parse({ type: "custom", raw });
|
|
550
171
|
function custom(raw) {
|
|
@@ -554,10 +175,10 @@ function custom(raw) {
|
|
|
554
175
|
}
|
|
555
176
|
|
|
556
177
|
// src/content/text.ts
|
|
557
|
-
import
|
|
558
|
-
var textSchema =
|
|
559
|
-
type:
|
|
560
|
-
text:
|
|
178
|
+
import z6 from "zod";
|
|
179
|
+
var textSchema = z6.object({
|
|
180
|
+
type: z6.literal("text"),
|
|
181
|
+
text: z6.string().nonempty()
|
|
561
182
|
});
|
|
562
183
|
var asText = (text2) => textSchema.parse({ type: "text", text: text2 });
|
|
563
184
|
function text(text2) {
|
|
@@ -572,15 +193,15 @@ var resolveContents = (items) => Promise.all(
|
|
|
572
193
|
);
|
|
573
194
|
|
|
574
195
|
// src/content/edit.ts
|
|
575
|
-
import
|
|
196
|
+
import z7 from "zod";
|
|
576
197
|
var isMessage = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
577
198
|
var isContent = (v) => typeof v === "object" && v !== null && "type" in v && typeof v.type === "string";
|
|
578
|
-
var editSchema =
|
|
579
|
-
type:
|
|
580
|
-
content:
|
|
199
|
+
var editSchema = z7.object({
|
|
200
|
+
type: z7.literal("edit"),
|
|
201
|
+
content: z7.custom(isContent, {
|
|
581
202
|
message: "edit content must be a Content value"
|
|
582
203
|
}),
|
|
583
|
-
target:
|
|
204
|
+
target: z7.custom(isMessage, {
|
|
584
205
|
message: "edit target must be a Message"
|
|
585
206
|
})
|
|
586
207
|
});
|
|
@@ -588,11 +209,16 @@ var asEdit = (input) => editSchema.parse({ type: "edit", ...input });
|
|
|
588
209
|
function edit(content, target) {
|
|
589
210
|
return {
|
|
590
211
|
build: async () => {
|
|
212
|
+
if (target.direction !== "outbound") {
|
|
213
|
+
throw new Error(
|
|
214
|
+
`edit() target must be an outbound message (got direction "${target.direction}", message id "${target.id}")`
|
|
215
|
+
);
|
|
216
|
+
}
|
|
591
217
|
const [resolved] = await resolveContents([content]);
|
|
592
218
|
if (!resolved) {
|
|
593
219
|
throw new Error("edit() requires content");
|
|
594
220
|
}
|
|
595
|
-
if (resolved.type === "edit" || resolved.type === "reply" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing") {
|
|
221
|
+
if (resolved.type === "edit" || resolved.type === "reply" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar") {
|
|
596
222
|
throw new Error(`edit() cannot wrap "${resolved.type}" content`);
|
|
597
223
|
}
|
|
598
224
|
return asEdit({ content: resolved, target });
|
|
@@ -601,12 +227,12 @@ function edit(content, target) {
|
|
|
601
227
|
}
|
|
602
228
|
|
|
603
229
|
// src/content/reaction.ts
|
|
604
|
-
import
|
|
230
|
+
import z8 from "zod";
|
|
605
231
|
var isMessage2 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
606
|
-
var reactionSchema =
|
|
607
|
-
type:
|
|
608
|
-
emoji:
|
|
609
|
-
target:
|
|
232
|
+
var reactionSchema = z8.object({
|
|
233
|
+
type: z8.literal("reaction"),
|
|
234
|
+
emoji: z8.string().min(1),
|
|
235
|
+
target: z8.custom(isMessage2, {
|
|
610
236
|
message: "reaction target must be a Message"
|
|
611
237
|
})
|
|
612
238
|
});
|
|
@@ -622,16 +248,28 @@ function reaction(emoji, target) {
|
|
|
622
248
|
};
|
|
623
249
|
}
|
|
624
250
|
|
|
251
|
+
// src/content/rename.ts
|
|
252
|
+
import z9 from "zod";
|
|
253
|
+
var renameSchema = z9.object({
|
|
254
|
+
type: z9.literal("rename"),
|
|
255
|
+
displayName: z9.string().min(1, "rename() displayName must be non-empty")
|
|
256
|
+
});
|
|
257
|
+
function rename(displayName) {
|
|
258
|
+
return {
|
|
259
|
+
build: async () => renameSchema.parse({ type: "rename", displayName })
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
625
263
|
// src/content/reply.ts
|
|
626
|
-
import
|
|
264
|
+
import z10 from "zod";
|
|
627
265
|
var isMessage3 = (v) => typeof v === "object" && v !== null && "id" in v && "content" in v;
|
|
628
266
|
var isContent2 = (v) => typeof v === "object" && v !== null && "type" in v && typeof v.type === "string";
|
|
629
|
-
var replySchema =
|
|
630
|
-
type:
|
|
631
|
-
content:
|
|
267
|
+
var replySchema = z10.object({
|
|
268
|
+
type: z10.literal("reply"),
|
|
269
|
+
content: z10.custom(isContent2, {
|
|
632
270
|
message: "reply content must be a Content value"
|
|
633
271
|
}),
|
|
634
|
-
target:
|
|
272
|
+
target: z10.custom(isMessage3, {
|
|
635
273
|
message: "reply target must be a Message"
|
|
636
274
|
})
|
|
637
275
|
});
|
|
@@ -643,7 +281,7 @@ function reply(content, target) {
|
|
|
643
281
|
if (!resolved) {
|
|
644
282
|
throw new Error("reply() requires content");
|
|
645
283
|
}
|
|
646
|
-
if (resolved.type === "reply" || resolved.type === "edit" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing") {
|
|
284
|
+
if (resolved.type === "reply" || resolved.type === "edit" || resolved.type === "reaction" || resolved.type === "group" || resolved.type === "typing" || resolved.type === "rename" || resolved.type === "avatar") {
|
|
647
285
|
throw new Error(`reply() cannot wrap "${resolved.type}" content`);
|
|
648
286
|
}
|
|
649
287
|
return asReply({ content: resolved, target });
|
|
@@ -652,10 +290,10 @@ function reply(content, target) {
|
|
|
652
290
|
}
|
|
653
291
|
|
|
654
292
|
// src/content/typing.ts
|
|
655
|
-
import
|
|
656
|
-
var typingSchema =
|
|
657
|
-
type:
|
|
658
|
-
state:
|
|
293
|
+
import z11 from "zod";
|
|
294
|
+
var typingSchema = z11.object({
|
|
295
|
+
type: z11.literal("typing"),
|
|
296
|
+
state: z11.enum(["start", "stop"])
|
|
659
297
|
});
|
|
660
298
|
function typing(state = "start") {
|
|
661
299
|
return {
|
|
@@ -847,7 +485,9 @@ var supportsAnsiColor = () => {
|
|
|
847
485
|
var FIRE_AND_FORGET_TYPES = /* @__PURE__ */ new Set([
|
|
848
486
|
"reaction",
|
|
849
487
|
"typing",
|
|
850
|
-
"edit"
|
|
488
|
+
"edit",
|
|
489
|
+
"rename",
|
|
490
|
+
"avatar"
|
|
851
491
|
]);
|
|
852
492
|
var isFireAndForget = (item) => FIRE_AND_FORGET_TYPES.has(item.type) || item.__fireAndForget === true;
|
|
853
493
|
var RESERVED_SPACE_KEYS = /* @__PURE__ */ new Set([
|
|
@@ -856,12 +496,26 @@ var RESERVED_SPACE_KEYS = /* @__PURE__ */ new Set([
|
|
|
856
496
|
"send",
|
|
857
497
|
"edit",
|
|
858
498
|
"getMessage",
|
|
499
|
+
"rename",
|
|
500
|
+
"avatar",
|
|
859
501
|
"startTyping",
|
|
860
502
|
"stopTyping",
|
|
861
503
|
"responding"
|
|
862
504
|
]);
|
|
863
|
-
var
|
|
864
|
-
|
|
505
|
+
var RESERVED_MESSAGE_KEYS = /* @__PURE__ */ new Set([
|
|
506
|
+
"content",
|
|
507
|
+
"direction",
|
|
508
|
+
"edit",
|
|
509
|
+
"id",
|
|
510
|
+
"platform",
|
|
511
|
+
"react",
|
|
512
|
+
"reply",
|
|
513
|
+
"sender",
|
|
514
|
+
"space",
|
|
515
|
+
"timestamp"
|
|
516
|
+
]);
|
|
517
|
+
var warnReservedAction = (scope, name, platform) => {
|
|
518
|
+
const body = `[spectrum-ts] ${platform} declared ${scope} action "${name}" which collides with a reserved ${scope === "space" ? "Space" : "Message"} key; skipping.`;
|
|
865
519
|
console.warn(
|
|
866
520
|
supportsAnsiColor() ? `${ANSI_YELLOW}${body}${ANSI_RESET}` : body
|
|
867
521
|
);
|
|
@@ -1110,10 +764,12 @@ function buildSpace(params) {
|
|
|
1110
764
|
if (declaredActions) {
|
|
1111
765
|
for (const [name, factory] of Object.entries(declaredActions)) {
|
|
1112
766
|
if (RESERVED_SPACE_KEYS.has(name)) {
|
|
1113
|
-
warnReservedAction(name, definition.name);
|
|
767
|
+
warnReservedAction("space", name, definition.name);
|
|
1114
768
|
continue;
|
|
1115
769
|
}
|
|
1116
|
-
platformActions[name] = (...args) =>
|
|
770
|
+
platformActions[name] = async (...args) => {
|
|
771
|
+
await factory(space, ...args);
|
|
772
|
+
};
|
|
1117
773
|
}
|
|
1118
774
|
}
|
|
1119
775
|
space = {
|
|
@@ -1125,6 +781,21 @@ function buildSpace(params) {
|
|
|
1125
781
|
await space.send(edit(newContent, message));
|
|
1126
782
|
},
|
|
1127
783
|
getMessage: getMessageImpl,
|
|
784
|
+
rename: async (displayName) => {
|
|
785
|
+
await space.send(rename(displayName));
|
|
786
|
+
},
|
|
787
|
+
avatar: (async (input, options) => {
|
|
788
|
+
if (typeof input === "string") {
|
|
789
|
+
await space.send(avatar(input, options));
|
|
790
|
+
return;
|
|
791
|
+
}
|
|
792
|
+
if (!options?.mimeType) {
|
|
793
|
+
throw new Error(
|
|
794
|
+
"space.avatar(Buffer) requires options.mimeType \u2014 pass { mimeType: '...' }"
|
|
795
|
+
);
|
|
796
|
+
}
|
|
797
|
+
await space.send(avatar(input, { mimeType: options.mimeType }));
|
|
798
|
+
}),
|
|
1128
799
|
startTyping: async () => {
|
|
1129
800
|
await space.send(typing("start"));
|
|
1130
801
|
},
|
|
@@ -1146,10 +817,6 @@ function buildSpace(params) {
|
|
|
1146
817
|
function buildMessage(params) {
|
|
1147
818
|
const { definition, space } = params;
|
|
1148
819
|
let self;
|
|
1149
|
-
const react = async (emoji) => {
|
|
1150
|
-
const target = requireBuiltMessage("react");
|
|
1151
|
-
await space.send(reaction(emoji, target));
|
|
1152
|
-
};
|
|
1153
820
|
const requireBuiltMessage = (action) => {
|
|
1154
821
|
if (!self) {
|
|
1155
822
|
throw new Error(
|
|
@@ -1158,46 +825,68 @@ function buildMessage(params) {
|
|
|
1158
825
|
}
|
|
1159
826
|
return self;
|
|
1160
827
|
};
|
|
828
|
+
const react = async (emoji) => {
|
|
829
|
+
const target = requireBuiltMessage("react");
|
|
830
|
+
await space.send(reaction(emoji, target));
|
|
831
|
+
};
|
|
1161
832
|
async function reply2(...content) {
|
|
1162
833
|
const target = requireBuiltMessage("reply");
|
|
1163
834
|
const wrapped = content.map((c) => reply(c, target));
|
|
1164
835
|
return space.send(...wrapped);
|
|
1165
836
|
}
|
|
1166
|
-
const
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
837
|
+
const edit2 = async (newContent) => {
|
|
838
|
+
const target = requireBuiltMessage("edit");
|
|
839
|
+
if (target.direction !== "outbound") {
|
|
840
|
+
throw new Error(
|
|
841
|
+
`cannot edit message ${target.id}: only outbound messages can be edited (direction: "${target.direction}")`
|
|
842
|
+
);
|
|
843
|
+
}
|
|
844
|
+
await space.send(edit(newContent, target));
|
|
845
|
+
};
|
|
846
|
+
const buildSenderWithPlatform = () => {
|
|
847
|
+
if (params.sender === void 0) {
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
850
|
+
if (params.direction === "outbound") {
|
|
851
|
+
return {
|
|
852
|
+
...params.sender,
|
|
853
|
+
__platform: definition.name,
|
|
854
|
+
kind: "agent"
|
|
855
|
+
};
|
|
856
|
+
}
|
|
857
|
+
return { ...params.sender, __platform: definition.name };
|
|
858
|
+
};
|
|
859
|
+
const senderWithPlatform = buildSenderWithPlatform();
|
|
860
|
+
const messagePlatformActions = {};
|
|
861
|
+
const declaredMessageActions = definition.message?.actions;
|
|
862
|
+
if (declaredMessageActions) {
|
|
863
|
+
for (const [name, factory] of Object.entries(declaredMessageActions)) {
|
|
864
|
+
if (RESERVED_MESSAGE_KEYS.has(name)) {
|
|
865
|
+
warnReservedAction("message", name, definition.name);
|
|
866
|
+
continue;
|
|
867
|
+
}
|
|
868
|
+
messagePlatformActions[name] = async (...args) => {
|
|
869
|
+
const target = requireBuiltMessage(name);
|
|
870
|
+
await factory(target, ...args);
|
|
871
|
+
};
|
|
872
|
+
}
|
|
1186
873
|
}
|
|
1187
|
-
const
|
|
874
|
+
const message = {
|
|
1188
875
|
...params.extras,
|
|
876
|
+
...messagePlatformActions,
|
|
1189
877
|
id: params.id,
|
|
1190
878
|
content: params.content,
|
|
1191
|
-
direction:
|
|
879
|
+
direction: params.direction,
|
|
1192
880
|
platform: definition.name,
|
|
1193
881
|
react,
|
|
1194
882
|
reply: reply2,
|
|
883
|
+
edit: edit2,
|
|
1195
884
|
sender: senderWithPlatform,
|
|
1196
885
|
space,
|
|
1197
886
|
timestamp: params.timestamp
|
|
1198
887
|
};
|
|
1199
|
-
self =
|
|
1200
|
-
return
|
|
888
|
+
self = message;
|
|
889
|
+
return message;
|
|
1201
890
|
}
|
|
1202
891
|
|
|
1203
892
|
// src/platform/define.ts
|
|
@@ -1435,10 +1124,9 @@ export {
|
|
|
1435
1124
|
attachmentSchema,
|
|
1436
1125
|
asAttachment,
|
|
1437
1126
|
attachment,
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
contact,
|
|
1127
|
+
photoActionSchema,
|
|
1128
|
+
buildPhotoAction,
|
|
1129
|
+
avatar,
|
|
1442
1130
|
asCustom,
|
|
1443
1131
|
custom,
|
|
1444
1132
|
textSchema,
|
|
@@ -1449,6 +1137,7 @@ export {
|
|
|
1449
1137
|
reactionSchema,
|
|
1450
1138
|
asReaction,
|
|
1451
1139
|
reaction,
|
|
1140
|
+
rename,
|
|
1452
1141
|
reply,
|
|
1453
1142
|
typing,
|
|
1454
1143
|
UnsupportedError,
|