spectrum-ts 0.6.1 → 0.8.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.
@@ -16,7 +16,78 @@ var resolveContents = (items) => Promise.all(
16
16
  items.map((c) => typeof c === "string" ? text(c).build() : c.build())
17
17
  );
18
18
 
19
+ // src/utils/errors.ts
20
+ var composeMessage = (opts) => {
21
+ const platform = opts.platform ?? "platform";
22
+ const subject = opts.kind === "content" ? `content type "${opts.contentType ?? "unknown"}"` : `action "${opts.action ?? "unknown"}"`;
23
+ const detail = opts.detail ? `: ${opts.detail}` : "";
24
+ return `${platform} does not support ${subject}${detail}`;
25
+ };
26
+ var UnsupportedError = class _UnsupportedError extends Error {
27
+ kind;
28
+ platform;
29
+ contentType;
30
+ action;
31
+ detail;
32
+ constructor(opts) {
33
+ super(composeMessage(opts));
34
+ this.name = "UnsupportedError";
35
+ this.kind = opts.kind;
36
+ this.platform = opts.platform;
37
+ this.contentType = opts.contentType;
38
+ this.action = opts.action;
39
+ this.detail = opts.detail;
40
+ }
41
+ static content(contentType, platform, detail) {
42
+ return new _UnsupportedError({
43
+ kind: "content",
44
+ contentType,
45
+ platform,
46
+ detail
47
+ });
48
+ }
49
+ static action(action, platform, detail) {
50
+ return new _UnsupportedError({ kind: "action", action, platform, detail });
51
+ }
52
+ withPlatform(platform) {
53
+ if (this.platform) {
54
+ return this;
55
+ }
56
+ return new _UnsupportedError({
57
+ kind: this.kind,
58
+ platform,
59
+ contentType: this.contentType,
60
+ action: this.action,
61
+ detail: this.detail
62
+ });
63
+ }
64
+ };
65
+
19
66
  // src/platform/build.ts
67
+ var ANSI_YELLOW = "\x1B[33m";
68
+ var ANSI_RESET = "\x1B[0m";
69
+ var supportsAnsiColor = () => {
70
+ if (typeof process === "undefined") {
71
+ return false;
72
+ }
73
+ if (process.env.NO_COLOR) {
74
+ return false;
75
+ }
76
+ const force = process.env.FORCE_COLOR;
77
+ if (force !== void 0) {
78
+ return force !== "" && force !== "0" && force !== "false";
79
+ }
80
+ return Boolean(process.stderr?.isTTY);
81
+ };
82
+ var warnUnsupported = (err, fallbackPlatform) => {
83
+ const platform = err.platform ?? fallbackPlatform;
84
+ const subject = err.kind === "content" ? `content type "${err.contentType ?? "unknown"}"` : `action "${err.action ?? "unknown"}"`;
85
+ const detail = err.detail ? `: ${err.detail}` : "";
86
+ const body = `[spectrum-ts] ${platform} does not support ${subject}${detail}; skipping.`;
87
+ console.warn(
88
+ supportsAnsiColor() ? `${ANSI_YELLOW}${body}${ANSI_RESET}` : body
89
+ );
90
+ };
20
91
  function buildSpace(params) {
21
92
  const { spaceRef, extras, typingCtx, definition, client, config } = params;
22
93
  let space;
@@ -24,10 +95,19 @@ function buildSpace(params) {
24
95
  const resolved = await resolveContents(content);
25
96
  const results = [];
26
97
  for (const item of resolved) {
27
- const sendResult = await definition.actions.send({
28
- ...typingCtx,
29
- content: item
30
- });
98
+ let sendResult;
99
+ try {
100
+ sendResult = await definition.actions.send({
101
+ ...typingCtx,
102
+ content: item
103
+ });
104
+ } catch (err) {
105
+ if (err instanceof UnsupportedError) {
106
+ warnUnsupported(err, definition.name);
107
+ continue;
108
+ }
109
+ throw err;
110
+ }
31
111
  if (!sendResult?.id) {
32
112
  throw new Error(
33
113
  `Platform "${definition.name}" send did not return a message id`
@@ -49,7 +129,10 @@ function buildSpace(params) {
49
129
  })
50
130
  );
51
131
  }
52
- return content.length === 1 && results[0] ? results[0] : results;
132
+ if (content.length === 1) {
133
+ return results[0];
134
+ }
135
+ return results;
53
136
  }
54
137
  space = {
55
138
  ...extras,
@@ -80,6 +163,10 @@ function buildMessage(params) {
80
163
  const { definition, client, config, spaceRef, space } = params;
81
164
  const react = async (reaction) => {
82
165
  if (!definition.actions.reactToMessage) {
166
+ warnUnsupported(
167
+ UnsupportedError.action("react", definition.name),
168
+ definition.name
169
+ );
83
170
  return;
84
171
  }
85
172
  await definition.actions.reactToMessage({
@@ -92,20 +179,31 @@ function buildMessage(params) {
92
179
  };
93
180
  async function reply(...content) {
94
181
  if (!definition.actions.replyToMessage) {
95
- throw new Error(
96
- `Platform "${definition.name}" does not support replying to messages`
182
+ warnUnsupported(
183
+ UnsupportedError.action("reply", definition.name),
184
+ definition.name
97
185
  );
186
+ return content.length === 1 ? void 0 : [];
98
187
  }
99
188
  const resolved = await resolveContents(content);
100
189
  const results = [];
101
190
  for (const item of resolved) {
102
- const sendResult = await definition.actions.replyToMessage({
103
- space: spaceRef,
104
- messageId: params.id,
105
- content: item,
106
- client,
107
- config
108
- });
191
+ let sendResult;
192
+ try {
193
+ sendResult = await definition.actions.replyToMessage({
194
+ space: spaceRef,
195
+ messageId: params.id,
196
+ content: item,
197
+ client,
198
+ config
199
+ });
200
+ } catch (err) {
201
+ if (err instanceof UnsupportedError) {
202
+ warnUnsupported(err, definition.name);
203
+ continue;
204
+ }
205
+ throw err;
206
+ }
109
207
  if (!sendResult?.id) {
110
208
  throw new Error(
111
209
  `Platform "${definition.name}" reply did not return a message id`
@@ -127,7 +225,10 @@ function buildMessage(params) {
127
225
  })
128
226
  );
129
227
  }
130
- return content.length === 1 && results[0] ? results[0] : results;
228
+ if (content.length === 1) {
229
+ return results[0];
230
+ }
231
+ return results;
131
232
  }
132
233
  const senderWithPlatform = params.sender === void 0 ? void 0 : { ...params.sender, __platform: definition.name };
133
234
  if (params.direction === "outbound") {
@@ -141,21 +242,31 @@ function buildMessage(params) {
141
242
  reply,
142
243
  edit: async (newContent) => {
143
244
  if (!definition.actions.editMessage) {
144
- throw new Error(
145
- `Platform "${definition.name}" does not support editing messages`
245
+ warnUnsupported(
246
+ UnsupportedError.action("edit", definition.name),
247
+ definition.name
146
248
  );
249
+ return;
147
250
  }
148
251
  const [resolved] = await resolveContents([newContent]);
149
252
  if (!resolved) {
150
253
  return;
151
254
  }
152
- await definition.actions.editMessage({
153
- space: spaceRef,
154
- messageId: params.id,
155
- content: resolved,
156
- client,
157
- config
158
- });
255
+ try {
256
+ await definition.actions.editMessage({
257
+ space: spaceRef,
258
+ messageId: params.id,
259
+ content: resolved,
260
+ client,
261
+ config
262
+ });
263
+ } catch (err) {
264
+ if (err instanceof UnsupportedError) {
265
+ warnUnsupported(err, definition.name);
266
+ return;
267
+ }
268
+ throw err;
269
+ }
159
270
  },
160
271
  sender: senderWithPlatform,
161
272
  space,
@@ -181,6 +292,29 @@ function createPlatformInstance(def, runtime) {
181
292
  const isPlatformUser = (value) => {
182
293
  return typeof value === "object" && value !== null && "__platform" in value && value.__platform === def.name;
183
294
  };
295
+ const resolveUserID = async (userID) => {
296
+ const resolved = await def.user.resolve({
297
+ input: { userID },
298
+ client: runtime.client,
299
+ config: runtime.config
300
+ });
301
+ return {
302
+ ...resolved,
303
+ __platform: def.name
304
+ };
305
+ };
306
+ const resolveStringUsers = async (args) => {
307
+ const convertArg = async (arg) => {
308
+ if (typeof arg === "string") {
309
+ return await resolveUserID(arg);
310
+ }
311
+ if (Array.isArray(arg)) {
312
+ return await Promise.all(arg.map(convertArg));
313
+ }
314
+ return arg;
315
+ };
316
+ return await Promise.all(args.map(convertArg));
317
+ };
184
318
  const normalizeSpaceArgs = (args) => {
185
319
  if (args.length === 0) {
186
320
  return { users: [], params: void 0 };
@@ -223,7 +357,8 @@ function createPlatformInstance(def, runtime) {
223
357
  };
224
358
  },
225
359
  async space(...args) {
226
- const { users, params } = normalizeSpaceArgs(args);
360
+ const convertedArgs = await resolveStringUsers(args);
361
+ const { users, params } = normalizeSpaceArgs(convertedArgs);
227
362
  let parsedParams = params;
228
363
  if (params !== void 0 && def.space.params) {
229
364
  parsedParams = def.space.params.parse(params);
@@ -335,6 +470,7 @@ export {
335
470
  asText,
336
471
  text,
337
472
  resolveContents,
473
+ UnsupportedError,
338
474
  buildSpace,
339
475
  buildMessage,
340
476
  definePlatform
@@ -0,0 +1,141 @@
1
+ import {
2
+ bufferToStream,
3
+ readSchema,
4
+ streamSchema
5
+ } from "./chunk-ZNUORCLB.js";
6
+
7
+ // src/content/richlink.ts
8
+ import z from "zod";
9
+
10
+ // src/utils/link-metadata.ts
11
+ import ogs from "open-graph-scraper";
12
+ var DEFAULT_TIMEOUT_MS = 5e3;
13
+ var USER_AGENT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_0) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Safari/605.1.15 spectrum-ts/richlink";
14
+ var normaliseImageUrl = (raw, base) => {
15
+ try {
16
+ return new URL(raw, base).toString();
17
+ } catch {
18
+ return;
19
+ }
20
+ };
21
+ var cleanString = (v) => {
22
+ if (typeof v !== "string") {
23
+ return;
24
+ }
25
+ const trimmed = v.trim();
26
+ return trimmed.length > 0 ? trimmed : void 0;
27
+ };
28
+ var fetchLinkMetadata = async (url) => {
29
+ try {
30
+ const result = await ogs({
31
+ url,
32
+ timeout: DEFAULT_TIMEOUT_MS,
33
+ fetchOptions: { headers: { "User-Agent": USER_AGENT } }
34
+ });
35
+ if (result.error) {
36
+ return {};
37
+ }
38
+ const {
39
+ ogTitle,
40
+ ogDescription,
41
+ ogImage,
42
+ twitterTitle,
43
+ twitterDescription,
44
+ twitterImage
45
+ } = result.result;
46
+ const title = cleanString(ogTitle) ?? cleanString(twitterTitle);
47
+ const summary = cleanString(ogDescription) ?? cleanString(twitterDescription);
48
+ const imageCandidate = ogImage?.[0] ?? twitterImage?.[0];
49
+ const resolved = imageCandidate ? normaliseImageUrl(imageCandidate.url, url) : void 0;
50
+ const image = imageCandidate && resolved ? {
51
+ url: resolved,
52
+ mimeType: "type" in imageCandidate && typeof imageCandidate.type === "string" ? imageCandidate.type : void 0
53
+ } : void 0;
54
+ return { title, summary, image };
55
+ } catch {
56
+ return {};
57
+ }
58
+ };
59
+ var fetchImage = async (url) => {
60
+ const controller = new AbortController();
61
+ const timer = setTimeout(() => controller.abort(), DEFAULT_TIMEOUT_MS);
62
+ try {
63
+ const res = await fetch(url, {
64
+ signal: controller.signal,
65
+ headers: { "User-Agent": USER_AGENT }
66
+ });
67
+ if (!res.ok) {
68
+ throw new Error(`image fetch ${url} returned ${res.status}`);
69
+ }
70
+ const data = Buffer.from(await res.arrayBuffer());
71
+ const mimeType = res.headers.get("content-type") ?? void 0;
72
+ return { data, mimeType };
73
+ } finally {
74
+ clearTimeout(timer);
75
+ }
76
+ };
77
+
78
+ // src/content/richlink.ts
79
+ var richlinkCoverSchema = z.object({
80
+ mimeType: z.string().min(1).optional(),
81
+ read: readSchema,
82
+ stream: streamSchema
83
+ });
84
+ var optionalStringAccessor = z.function({
85
+ input: [],
86
+ output: z.promise(z.string().min(1).optional())
87
+ });
88
+ var coverAccessor = z.function({
89
+ input: [],
90
+ output: z.promise(richlinkCoverSchema.optional())
91
+ });
92
+ var richlinkSchema = z.object({
93
+ type: z.literal("richlink"),
94
+ url: z.url(),
95
+ title: optionalStringAccessor,
96
+ summary: optionalStringAccessor,
97
+ cover: coverAccessor
98
+ });
99
+ var memoize = (factory) => {
100
+ let cached;
101
+ return () => {
102
+ cached ??= factory();
103
+ return cached;
104
+ };
105
+ };
106
+ var buildCover = (image) => {
107
+ const read = memoize(
108
+ () => fetchImage(image.url).then((r) => r.data).catch(() => Buffer.alloc(0))
109
+ );
110
+ return {
111
+ mimeType: image.mimeType,
112
+ read,
113
+ stream: async () => bufferToStream(await read())
114
+ };
115
+ };
116
+ var asRichlink = (input) => {
117
+ const getMetadata = memoize(() => fetchLinkMetadata(input.url));
118
+ const getCover = memoize(async () => {
119
+ const { image } = await getMetadata();
120
+ return image ? buildCover(image) : void 0;
121
+ });
122
+ const title = async () => (await getMetadata()).title;
123
+ const summary = async () => (await getMetadata()).summary;
124
+ return richlinkSchema.parse({
125
+ type: "richlink",
126
+ url: input.url,
127
+ title,
128
+ summary,
129
+ cover: getCover
130
+ });
131
+ };
132
+ function richlink(url) {
133
+ return {
134
+ build: async () => asRichlink({ url })
135
+ };
136
+ }
137
+
138
+ export {
139
+ asRichlink,
140
+ richlink
141
+ };
@@ -557,11 +557,13 @@ function custom(raw) {
557
557
  import { Repeater } from "@repeaterjs/repeater";
558
558
  function stream(setup) {
559
559
  const repeater = new Repeater(async (push, stop) => {
560
- const emit = (value) => {
561
- Promise.resolve(push(value)).catch((error) => {
560
+ const emit = async (value) => {
561
+ try {
562
+ await push(value);
563
+ } catch (error) {
562
564
  stop(error);
563
- return void 0;
564
- });
565
+ throw error;
566
+ }
565
567
  };
566
568
  const end = (error) => {
567
569
  stop(error);
@@ -589,7 +591,7 @@ function mergeStreams(streams) {
589
591
  const workers = streams.map(async (source) => {
590
592
  try {
591
593
  for await (const value of source) {
592
- emit(value);
594
+ await emit(value);
593
595
  }
594
596
  } catch (error) {
595
597
  end(error);
@@ -607,6 +609,73 @@ function mergeStreams(streams) {
607
609
  });
608
610
  }
609
611
 
612
+ // src/utils/cloud.ts
613
+ var SPECTRUM_CLOUD_URL = `https://${process.env.SPECTRUM_CLOUD_URL ?? "spectrum.photon.codes"}`;
614
+ var SpectrumCloudError = class extends Error {
615
+ status;
616
+ code;
617
+ constructor(status, code, message) {
618
+ super(message);
619
+ this.name = "SpectrumCloudError";
620
+ this.status = status;
621
+ this.code = code;
622
+ }
623
+ };
624
+ var request = async (path, init) => {
625
+ const response = await fetch(`${SPECTRUM_CLOUD_URL}${path}`, init);
626
+ if (!response.ok) {
627
+ const body = await response.text().catch(() => "");
628
+ try {
629
+ const parsed = JSON.parse(body);
630
+ throw new SpectrumCloudError(
631
+ response.status,
632
+ parsed.code,
633
+ parsed.message
634
+ );
635
+ } catch (error) {
636
+ if (error instanceof SpectrumCloudError) {
637
+ throw error;
638
+ }
639
+ throw new SpectrumCloudError(
640
+ response.status,
641
+ "UNKNOWN",
642
+ body || response.statusText
643
+ );
644
+ }
645
+ }
646
+ const json = await response.json();
647
+ if (!json.succeed) {
648
+ throw new SpectrumCloudError(
649
+ response.status,
650
+ "UNKNOWN",
651
+ "Server returned succeed=false"
652
+ );
653
+ }
654
+ return json.data;
655
+ };
656
+ var basicAuth = (projectId, projectSecret) => `Basic ${btoa(`${projectId}:${projectSecret}`)}`;
657
+ var cloud = {
658
+ getSubscription: (projectId) => request(`/projects/${projectId}/billing/subscription`),
659
+ issueImessageTokens: (projectId, projectSecret) => request(`/projects/${projectId}/imessage/tokens`, {
660
+ method: "POST",
661
+ headers: { Authorization: basicAuth(projectId, projectSecret) }
662
+ }),
663
+ getImessageInfo: (projectId) => request(`/projects/${projectId}/imessage/`),
664
+ issueWhatsappBusinessTokens: (projectId, projectSecret) => request(`/projects/${projectId}/whatsapp-business/tokens`, {
665
+ method: "POST",
666
+ headers: { Authorization: basicAuth(projectId, projectSecret) }
667
+ }),
668
+ getPlatforms: (projectId) => request(`/projects/${projectId}/platforms/`),
669
+ togglePlatform: (projectId, projectSecret, platform, enabled) => request(`/projects/${projectId}/platforms/`, {
670
+ method: "PATCH",
671
+ headers: {
672
+ Authorization: basicAuth(projectId, projectSecret),
673
+ "Content-Type": "application/json"
674
+ },
675
+ body: JSON.stringify({ platform, enabled })
676
+ })
677
+ };
678
+
610
679
  export {
611
680
  readSchema,
612
681
  streamSchema,
@@ -620,5 +689,7 @@ export {
620
689
  asCustom,
621
690
  custom,
622
691
  stream,
623
- mergeStreams
692
+ mergeStreams,
693
+ SpectrumCloudError,
694
+ cloud
624
695
  };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { C as ContentBuilder, U as User, a as ContentInput, b as Content, P as ProviderMessage, c as PlatformDef, d as Platform, e as PlatformProviderConfig, S as SpectrumLike, f as CustomEventStreams, g as Space, I as InboundMessage, O as OutboundMessage } from './types-DZMHfgYQ.js';
2
- export { A as AnyPlatformDef, E as EventProducer, M as Message, h as PlatformInstance, i as PlatformMessage, j as PlatformSpace, k as PlatformUser, l as SchemaMessage } from './types-DZMHfgYQ.js';
1
+ import { C as ContentBuilder, U as User, a as ContentInput, b as Content, P as ProviderMessage, c as PlatformDef, d as Platform, e as PlatformProviderConfig, S as SpectrumLike, f as CustomEventStreams, g as Space, I as InboundMessage, O as OutboundMessage } from './types-DLrsDzV-.js';
2
+ export { A as AnyPlatformDef, E as EventProducer, M as Message, h as PlatformInstance, i as PlatformMessage, j as PlatformSpace, k as PlatformUser, l as SchemaMessage } from './types-DLrsDzV-.js';
3
3
  import vCard from 'vcf';
4
4
  import z__default from 'zod';
5
- export { M as ManagedStream, m as mergeStreams, s as stream } from './stream-DGy4geUK.js';
5
+ export { M as ManagedStream, m as mergeStreams, s as stream } from './stream-B55k7W8-.js';
6
6
  import 'hotscript';
7
7
 
8
8
  declare function attachment(input: string | Buffer, options?: {
@@ -124,6 +124,20 @@ declare function custom(raw: unknown): ContentBuilder;
124
124
 
125
125
  declare const resolveContents: (items: readonly ContentInput[]) => Promise<Content[]>;
126
126
 
127
+ declare const richlinkSchema: z__default.ZodObject<{
128
+ type: z__default.ZodLiteral<"richlink">;
129
+ url: z__default.ZodURL;
130
+ title: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodOptional<z__default.ZodString>>>;
131
+ summary: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodOptional<z__default.ZodString>>>;
132
+ cover: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodOptional<z__default.ZodObject<{
133
+ mimeType: z__default.ZodOptional<z__default.ZodString>;
134
+ read: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<Buffer<ArrayBufferLike>, Buffer<ArrayBufferLike>>>>;
135
+ stream: z__default.ZodFunction<z__default.ZodTuple<readonly [], null>, z__default.ZodPromise<z__default.ZodCustom<ReadableStream<unknown>, ReadableStream<unknown>>>>;
136
+ }, z__default.core.$strip>>>>;
137
+ }, z__default.core.$strip>;
138
+ type Richlink = z__default.infer<typeof richlinkSchema>;
139
+ declare function richlink(url: string): ContentBuilder;
140
+
127
141
  declare function text(text: string): ContentBuilder;
128
142
 
129
143
  declare const voiceSchema: z__default.ZodObject<{
@@ -163,7 +177,7 @@ declare function definePlatform<_Name extends string, _ConfigSchema extends z__d
163
177
  type SpectrumInstance<Providers extends PlatformProviderConfig[] = PlatformProviderConfig[]> = SpectrumLike<Providers> & CustomEventStreams<Providers> & {
164
178
  readonly messages: AsyncIterable<[Space, InboundMessage]>;
165
179
  stop(): Promise<void>;
166
- send(space: Space, content: ContentInput): Promise<OutboundMessage>;
180
+ send(space: Space, content: ContentInput): Promise<OutboundMessage | undefined>;
167
181
  send(space: Space, ...content: [ContentInput, ContentInput, ...ContentInput[]]): Promise<OutboundMessage[]>;
168
182
  edit(message: OutboundMessage, newContent: ContentInput): Promise<void>;
169
183
  responding<T>(space: Space, fn: () => T | Promise<T>): Promise<T>;
@@ -202,6 +216,11 @@ type PlatformsData = Record<CloudPlatform, PlatformStatus>;
202
216
  interface ImessageInfoData {
203
217
  type: "shared" | "dedicated";
204
218
  }
219
+ interface WhatsappBusinessTokenData {
220
+ auth: Record<string, string>;
221
+ expiresIn: number;
222
+ numbers: Record<string, string | null>;
223
+ }
205
224
  declare class SpectrumCloudError extends Error {
206
225
  readonly status: number;
207
226
  readonly code: string;
@@ -211,11 +230,32 @@ declare const cloud: {
211
230
  getSubscription: (projectId: string) => Promise<SubscriptionData>;
212
231
  issueImessageTokens: (projectId: string, projectSecret: string) => Promise<TokenData>;
213
232
  getImessageInfo: (projectId: string) => Promise<ImessageInfoData>;
233
+ issueWhatsappBusinessTokens: (projectId: string, projectSecret: string) => Promise<WhatsappBusinessTokenData>;
214
234
  getPlatforms: (projectId: string) => Promise<PlatformsData>;
215
235
  togglePlatform: (projectId: string, projectSecret: string, platform: CloudPlatform, enabled: boolean) => Promise<PlatformsData>;
216
236
  };
217
237
 
238
+ type UnsupportedKind = "content" | "action";
239
+ interface UnsupportedErrorOptions {
240
+ action?: string;
241
+ contentType?: string;
242
+ detail?: string;
243
+ kind: UnsupportedKind;
244
+ platform?: string;
245
+ }
246
+ declare class UnsupportedError extends Error {
247
+ readonly kind: UnsupportedKind;
248
+ readonly platform?: string;
249
+ readonly contentType?: string;
250
+ readonly action?: string;
251
+ readonly detail?: string;
252
+ constructor(opts: UnsupportedErrorOptions);
253
+ static content(contentType: string, platform?: string, detail?: string): UnsupportedError;
254
+ static action(action: string, platform?: string, detail?: string): UnsupportedError;
255
+ withPlatform(platform: string): UnsupportedError;
256
+ }
257
+
218
258
  declare const fromVCard: (vcf: string) => ContactInput;
219
259
  declare const toVCard: (contact: Contact) => Promise<string>;
220
260
 
221
- export { type CloudPlatform, type Contact, type ContactAddress, type ContactDetails, type ContactEmail, type ContactInput, type ContactName, type ContactOrg, type ContactPhone, Content, ContentBuilder, ContentInput, type DedicatedTokenData, type ImessageInfoData, Platform, PlatformDef, PlatformProviderConfig, type PlatformStatus, type PlatformsData, type SharedTokenData, Space, Spectrum, SpectrumCloudError, type SpectrumInstance, type SubscriptionData, type SubscriptionStatus, type TokenData, User, type Voice, attachment, cloud, contact, custom, definePlatform, fromVCard, resolveContents, text, toVCard, voice };
261
+ export { type CloudPlatform, type Contact, type ContactAddress, type ContactDetails, type ContactEmail, type ContactInput, type ContactName, type ContactOrg, type ContactPhone, Content, ContentBuilder, ContentInput, type DedicatedTokenData, type ImessageInfoData, Platform, PlatformDef, PlatformProviderConfig, type PlatformStatus, type PlatformsData, type Richlink, type SharedTokenData, Space, Spectrum, SpectrumCloudError, type SpectrumInstance, type SubscriptionData, type SubscriptionStatus, type TokenData, UnsupportedError, type UnsupportedKind, User, type Voice, attachment, cloud, contact, custom, definePlatform, fromVCard, resolveContents, richlink, text, toVCard, voice };