statocysts 0.6.0 → 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.
package/dist/browser.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { a as Sender, c as buildSenderRegistry, d as ServiceProvider, f as defineProvider, i as http, l as DefineProviderContext, m as defineTransport, n as slack, o as SenderRegistry, p as Transport, r as HttpPayload, s as SenderUrl, t as json, u as DefineProviderOptions } from "./index-I_frtEQ-.js";
1
+ import { _ as defineTransport, a as discord, c as Sender, d as buildSenderRegistry, f as DefineProviderContext, g as Transport, h as defineProvider, i as slack, l as SenderRegistry, m as ServiceProvider, n as bark, o as HttpPayload, p as DefineProviderOptions, r as telegram, s as http, t as json, u as SenderUrl } from "./index-DcoOHy7e.js";
2
2
 
3
3
  //#region src/browser.d.ts
4
+
4
5
  declare const senderRegistry: SenderRegistry;
5
6
  declare function createSender(urls: SenderUrl[]): Sender;
6
7
  declare function send(url: string | URL, title: string, body?: string): Promise<void>;
7
8
  //#endregion
8
- export { DefineProviderContext, DefineProviderOptions, HttpPayload, Sender, SenderRegistry, SenderUrl, ServiceProvider, Transport, buildSenderRegistry, createSender, defineProvider, defineTransport, http, json, send, senderRegistry, slack };
9
+ export { DefineProviderContext, DefineProviderOptions, HttpPayload, Sender, SenderRegistry, SenderUrl, ServiceProvider, Transport, bark, buildSenderRegistry, createSender, defineProvider, defineTransport, discord, http, json, send, senderRegistry, slack, telegram };
package/dist/browser.js CHANGED
@@ -1,7 +1,13 @@
1
- import { a as defineTransport, i as http, n as json, o as defineProvider, r as slack, s as assert, t as buildSenderRegistry } from "./shared-vzO3pF63.js";
1
+ import { a as slack, c as defineTransport, i as telegram, l as defineProvider, n as bark, o as discord, r as buildSenderRegistry, s as http, t as json, u as assert } from "./json-DAUitIVf.js";
2
2
 
3
3
  //#region src/browser.ts
4
- const senderRegistry = buildSenderRegistry([json, slack]);
4
+ const senderRegistry = buildSenderRegistry([
5
+ bark,
6
+ json,
7
+ slack,
8
+ telegram,
9
+ discord
10
+ ]);
5
11
  function createSender(urls) {
6
12
  return senderRegistry(urls);
7
13
  }
@@ -17,4 +23,4 @@ async function send(url, title, body) {
17
23
  }
18
24
 
19
25
  //#endregion
20
- export { buildSenderRegistry, createSender, defineProvider, defineTransport, http, json, send, senderRegistry, slack };
26
+ export { bark, buildSenderRegistry, createSender, defineProvider, defineTransport, discord, http, json, send, senderRegistry, slack, telegram };
@@ -1,5 +1,6 @@
1
1
  import * as ofetch0 from "ofetch";
2
2
  import { FetchOptions } from "ofetch";
3
+ import z from "zod";
3
4
 
4
5
  //#region src/core/transport.d.ts
5
6
  /**
@@ -65,6 +66,12 @@ interface HttpPayload {
65
66
  */
66
67
  declare const http: Transport<HttpPayload>;
67
68
  //#endregion
69
+ //#region src/services/chat/discord/index.d.ts
70
+ interface DiscordOptions {
71
+ fetchOptions?: FetchOptions;
72
+ }
73
+ declare const discord: ServiceProvider<"discord:", HttpPayload, DiscordOptions>;
74
+ //#endregion
68
75
  //#region src/services/chat/slack/index.d.ts
69
76
  interface SlackOptions {
70
77
  /**
@@ -89,7 +96,25 @@ interface SlackOptions {
89
96
  }
90
97
  declare const slack: ServiceProvider<"slack:", HttpPayload, SlackOptions>;
91
98
  //#endregion
99
+ //#region src/services/chat/telegram/index.d.ts
100
+ interface TelegramOptions {
101
+ /**
102
+ * The base URL for Telegram Bot API
103
+ *
104
+ * @default `https://api.telegram.org`
105
+ */
106
+ apiBaseUrl?: string;
107
+ fetchOptions?: FetchOptions;
108
+ }
109
+ declare const telegram: ServiceProvider<"telegram:", HttpPayload, TelegramOptions>;
110
+ //#endregion
111
+ //#region src/services/push/bark/index.d.ts
112
+ interface BarkOptions {
113
+ fetchOptions?: FetchOptions;
114
+ }
115
+ declare const bark: ServiceProvider<"bark:", HttpPayload, BarkOptions>;
116
+ //#endregion
92
117
  //#region src/services/specialized/json/index.d.ts
93
118
  declare const json: ServiceProvider<"json:", HttpPayload, FetchOptions<ofetch0.ResponseType, any>>;
94
119
  //#endregion
95
- export { Sender as a, buildSenderRegistry as c, ServiceProvider as d, defineProvider as f, http as i, DefineProviderContext as l, defineTransport as m, slack as n, SenderRegistry as o, Transport as p, HttpPayload as r, SenderUrl as s, json as t, DefineProviderOptions as u };
120
+ export { defineTransport as _, discord as a, Sender as c, buildSenderRegistry as d, DefineProviderContext as f, Transport as g, defineProvider as h, slack as i, SenderRegistry as l, ServiceProvider as m, bark as n, HttpPayload as o, DefineProviderOptions as p, telegram as r, http as s, json as t, SenderUrl as u };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { a as Sender, c as buildSenderRegistry, d as ServiceProvider, f as defineProvider, i as http, l as DefineProviderContext, m as defineTransport, n as slack, o as SenderRegistry, p as Transport, r as HttpPayload, s as SenderUrl, t as json, u as DefineProviderOptions } from "./index-I_frtEQ-.js";
1
+ import { _ as defineTransport, a as discord, c as Sender, d as buildSenderRegistry, f as DefineProviderContext, g as Transport, h as defineProvider, i as slack, l as SenderRegistry, m as ServiceProvider, n as bark, o as HttpPayload, p as DefineProviderOptions, r as telegram, s as http, t as json, u as SenderUrl } from "./index-DcoOHy7e.js";
2
2
 
3
3
  //#region src/index.d.ts
4
+
4
5
  declare const senderRegistry: SenderRegistry;
5
6
  declare function createSender(urls: SenderUrl[]): Sender;
6
7
  declare function send(url: string | URL, title: string, body?: string): Promise<void>;
7
8
  //#endregion
8
- export { DefineProviderContext, DefineProviderOptions, HttpPayload, Sender, SenderRegistry, SenderUrl, ServiceProvider, Transport, buildSenderRegistry, createSender, defineProvider, defineTransport, http, json, send, senderRegistry, slack };
9
+ export { DefineProviderContext, DefineProviderOptions, HttpPayload, Sender, SenderRegistry, SenderUrl, ServiceProvider, Transport, bark, buildSenderRegistry, createSender, defineProvider, defineTransport, discord, http, json, send, senderRegistry, slack, telegram };
package/dist/index.js CHANGED
@@ -1,7 +1,13 @@
1
- import { a as defineTransport, i as http, n as json, o as defineProvider, r as slack, s as assert, t as buildSenderRegistry } from "./shared-vzO3pF63.js";
1
+ import { a as slack, c as defineTransport, i as telegram, l as defineProvider, n as bark, o as discord, r as buildSenderRegistry, s as http, t as json, u as assert } from "./json-DAUitIVf.js";
2
2
 
3
3
  //#region src/index.ts
4
- const senderRegistry = buildSenderRegistry([json, slack]);
4
+ const senderRegistry = buildSenderRegistry([
5
+ bark,
6
+ json,
7
+ slack,
8
+ telegram,
9
+ discord
10
+ ]);
5
11
  function createSender(urls) {
6
12
  return senderRegistry(urls);
7
13
  }
@@ -17,4 +23,4 @@ async function send(url, title, body) {
17
23
  }
18
24
 
19
25
  //#endregion
20
- export { buildSenderRegistry, createSender, defineProvider, defineTransport, http, json, send, senderRegistry, slack };
26
+ export { bark, buildSenderRegistry, createSender, defineProvider, defineTransport, discord, http, json, send, senderRegistry, slack, telegram };
@@ -0,0 +1,341 @@
1
+ import { getQuery, withProtocol, withoutLeadingSlash } from "ufo";
2
+ import defu from "defu";
3
+ import { ofetch } from "ofetch";
4
+ import z from "zod";
5
+
6
+ //#region src/utils/assert.ts
7
+ function assert(condition, message) {
8
+ if (!condition) throw typeof message === "string" ? new Error(message) : message;
9
+ }
10
+
11
+ //#endregion
12
+ //#region src/utils/markdown.ts
13
+ /**
14
+ * Escape special characters: _*[]()~`>#+-=|{}.!
15
+ */
16
+ function escapeMarkdown(text) {
17
+ return text.replace(/([_*[\]()~`>#+\-=|{}.!])/g, "\\$1");
18
+ }
19
+
20
+ //#endregion
21
+ //#region src/utils/url.ts
22
+ function getValidateQuery(url, parser) {
23
+ return parser(getQuery(url.toString()));
24
+ }
25
+ function withoutPathname(input) {
26
+ const _url = new URL(input);
27
+ _url.pathname = "";
28
+ return _url.toString();
29
+ }
30
+
31
+ //#endregion
32
+ //#region src/core/provider.ts
33
+ function defineProvider(protocol, createOptions) {
34
+ const send = async (protocolUrl, message, options) => {
35
+ const url = new URL(protocolUrl);
36
+ assert(url.protocol === protocol, `Unexpected protocol "${url.protocol}"`);
37
+ const ctx = {
38
+ url,
39
+ message
40
+ };
41
+ const opts = defu(options ?? {}, createOptions.defaultOptions ?? {});
42
+ const payload = await createOptions.prepare.call(ctx, ctx, opts);
43
+ await createOptions.transport.send(payload);
44
+ };
45
+ return {
46
+ get protocol() {
47
+ return protocol;
48
+ },
49
+ get defaultOptions() {
50
+ return createOptions.defaultOptions;
51
+ },
52
+ get $transport() {
53
+ return createOptions.transport;
54
+ },
55
+ send
56
+ };
57
+ }
58
+
59
+ //#endregion
60
+ //#region src/core/transport.ts
61
+ function defineTransport(transport) {
62
+ return transport;
63
+ }
64
+
65
+ //#endregion
66
+ //#region src/core/transports/http.ts
67
+ /**
68
+ * HTTP transport implementation
69
+ * Handles sending data over HTTP/HTTPS protocols
70
+ */
71
+ const http = defineTransport({ async send(payload) {
72
+ await ofetch(payload.request, payload.fetchOptions);
73
+ } });
74
+
75
+ //#endregion
76
+ //#region src/services/chat/discord/index.ts
77
+ const querySchema$1 = z.object({
78
+ avatar_url: z.string().optional(),
79
+ username: z.string().optional(),
80
+ wait: z.string().transform((val) => {
81
+ if (val === "false" || val === "0" || val === "") return false;
82
+ return true;
83
+ }).optional()
84
+ });
85
+ const discord = defineProvider("discord:", {
86
+ transport: http,
87
+ defaultOptions: {},
88
+ async prepare(ctx, options) {
89
+ const { url } = ctx;
90
+ assert(url.hostname === "webhook", "Invalid discord URL");
91
+ assert(url.username, "Webhook ID is required");
92
+ assert(url.password, "Webhook token is required");
93
+ const queryResult = getValidateQuery(url, querySchema$1.safeParse);
94
+ if (!queryResult.success) throw new Error("Invalid discord query");
95
+ const { wait, ...query } = queryResult.data;
96
+ const headers = new Headers([["Content-Type", "application/json"]]);
97
+ const body = defu({ content: ctx.message.body ? `## ${ctx.message.title}\n\n${ctx.message.body}` : ctx.message.title }, query);
98
+ const requestUrl = new URL(`/api/webhooks/${url.username}/${url.password}`, "https://discord.com");
99
+ if (wait) requestUrl.searchParams.set("wait", "true");
100
+ return {
101
+ request: new Request(requestUrl, {
102
+ method: "POST",
103
+ headers,
104
+ body: JSON.stringify(body)
105
+ }),
106
+ fetchOptions: options.fetchOptions
107
+ };
108
+ }
109
+ });
110
+
111
+ //#endregion
112
+ //#region src/services/chat/slack/index.ts
113
+ const slack = defineProvider("slack:", {
114
+ transport: http,
115
+ defaultOptions: {
116
+ hookBaseUrl: "https://hooks.slack.com/",
117
+ botApiBaseUrl: "https://slack.com/"
118
+ },
119
+ async prepare(_, options) {
120
+ const { url } = this;
121
+ assert(url.hostname === "bot" || url.hostname === "webhook", `Invalid slack URL: ${url.toString()}`);
122
+ const type = url.hostname;
123
+ if (type === "bot") {
124
+ assert(url.username, "Channel ID is required");
125
+ assert(url.password, "Bot token is required");
126
+ } else assert(url.pathname.split("/").filter(Boolean).length === 3, "Webhook URL is invalid");
127
+ let requestUrl;
128
+ const headers = new Headers([["Content-Type", "application/json"]]);
129
+ const body = {};
130
+ if (this.message.body) {
131
+ body.blocks = [{
132
+ type: "header",
133
+ text: {
134
+ type: "plain_text",
135
+ text: this.message.title
136
+ }
137
+ }, {
138
+ type: "section",
139
+ text: {
140
+ type: "mrkdwn",
141
+ text: this.message.body
142
+ }
143
+ }];
144
+ body.text = this.message.title;
145
+ } else body.text = this.message.title;
146
+ if (type === "bot") {
147
+ const { username: channel, password: token, searchParams } = url;
148
+ requestUrl = new URL("/api/chat.postMessage", options.botApiBaseUrl);
149
+ searchParams.forEach((value, key) => {
150
+ requestUrl.searchParams.set(key, value);
151
+ });
152
+ headers.set("Authorization", `Bearer ${token}`);
153
+ body.channel = channel;
154
+ } else {
155
+ const { searchParams } = url;
156
+ requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl);
157
+ searchParams.forEach((value, key) => {
158
+ requestUrl.searchParams.set(key, value);
159
+ });
160
+ }
161
+ return {
162
+ request: new Request(requestUrl, {
163
+ method: "POST",
164
+ headers,
165
+ body: JSON.stringify(options.body ?? body)
166
+ }),
167
+ fetchOptions: options.fetchOptions
168
+ };
169
+ }
170
+ });
171
+
172
+ //#endregion
173
+ //#region src/services/chat/telegram/index.ts
174
+ const telegramQuerySchema = z.object({ parse_mode: z.enum([
175
+ "Markdown",
176
+ "MarkdownV2",
177
+ "HTML"
178
+ ]).optional() });
179
+ const telegram = defineProvider("telegram:", {
180
+ transport: http,
181
+ defaultOptions: { apiBaseUrl: "https://api.telegram.org" },
182
+ async prepare(_, options) {
183
+ const { url } = this;
184
+ assert(url.hostname === "bot", `Invalid telegram URL: ${url.toString()}`);
185
+ assert(url.username, "Bot token is required");
186
+ const pathSegments = url.pathname.split("/").filter(Boolean);
187
+ assert(pathSegments.length > 0, "At least one chat ID is required");
188
+ const queryResult = getValidateQuery(url, telegramQuerySchema.safeParse);
189
+ if (!queryResult.success) throw new Error("Invalid telegram query");
190
+ const query = queryResult.data;
191
+ const botToken = `${url.username}:${url.password}`;
192
+ const chatPart = decodeURIComponent(pathSegments[0]);
193
+ const [chatId, messageThreadId] = chatPart.includes(":") ? chatPart.split(":", 2) : [chatPart, void 0];
194
+ const requestUrl = new URL(`/bot${botToken}/sendMessage`, options.apiBaseUrl);
195
+ const headers = new Headers([["Content-Type", "application/json"]]);
196
+ let text;
197
+ if (this.message.body) {
198
+ const parseMode = query.parse_mode;
199
+ let titleFormatted;
200
+ if (parseMode === "HTML") titleFormatted = `<b>${this.message.title}</b>`;
201
+ else if (parseMode === "MarkdownV2") titleFormatted = `*${escapeMarkdown(this.message.title)}*`;
202
+ else titleFormatted = `*${this.message.title}*`;
203
+ text = `${titleFormatted}\n\n${this.message.body}`;
204
+ } else if (query.parse_mode === "MarkdownV2") text = escapeMarkdown(this.message.title);
205
+ else text = this.message.title;
206
+ const body = {
207
+ chat_id: chatId,
208
+ text,
209
+ parse_mode: query.parse_mode
210
+ };
211
+ if (messageThreadId) body.message_thread_id = Number.parseInt(messageThreadId, 10);
212
+ return {
213
+ request: new Request(requestUrl, {
214
+ method: "POST",
215
+ headers,
216
+ body: JSON.stringify(body)
217
+ }),
218
+ fetchOptions: options.fetchOptions
219
+ };
220
+ }
221
+ });
222
+
223
+ //#endregion
224
+ //#region src/core/sender.ts
225
+ function buildSenderRegistry(providers) {
226
+ const providersRegistry = /* @__PURE__ */ new Map();
227
+ providers.forEach((provider) => {
228
+ providersRegistry.set(provider.protocol, provider);
229
+ });
230
+ function resolveProvider(url) {
231
+ const _url = typeof url === "string" ? new URL(url) : url;
232
+ return providersRegistry.get(_url.protocol);
233
+ }
234
+ function createSender(urls) {
235
+ const registries = urls.map((url) => {
236
+ const provider = resolveProvider(url);
237
+ if (!provider) return;
238
+ return {
239
+ provider,
240
+ url
241
+ };
242
+ }).filter((p) => !!p);
243
+ return { async send(message, options) {
244
+ for (const registry of registries) {
245
+ const messageObj = { title: message };
246
+ await registry.provider.send(registry.url.toString(), messageObj, options);
247
+ }
248
+ } };
249
+ }
250
+ return Object.assign(createSender, { resolveProvider });
251
+ }
252
+
253
+ //#endregion
254
+ //#region src/services/push/bark/index.ts
255
+ const querySchema = z.object({
256
+ subtitle: z.string().optional(),
257
+ group: z.string().optional(),
258
+ url: z.string().optional(),
259
+ icon: z.string().optional(),
260
+ sound: z.string().optional(),
261
+ call: z.enum(["1"]).optional(),
262
+ ciphertext: z.string().optional(),
263
+ level: z.enum([
264
+ "active",
265
+ "timeSensitive",
266
+ "passive",
267
+ "critical"
268
+ ]).optional(),
269
+ volume: z.string().optional(),
270
+ badge: z.coerce.number().optional(),
271
+ autoCopy: z.enum(["1"]).optional(),
272
+ copy: z.string().optional(),
273
+ action: z.enum(["none"]).optional(),
274
+ isArchive: z.enum(["1"]).optional()
275
+ });
276
+ const bark = defineProvider("bark:", {
277
+ transport: http,
278
+ defaultOptions: {},
279
+ async prepare(ctx, options) {
280
+ const { message, url } = ctx;
281
+ assert(url.hostname, "Server URL hostname is required");
282
+ assert(url.pathname, "Device key is required");
283
+ const deviceKeys = url.pathname.split("/").filter(Boolean);
284
+ assert(deviceKeys.length > 0, "At least one device key is required");
285
+ const queryResult = getValidateQuery(url, querySchema.safeParse);
286
+ if (!queryResult.success) throw new Error("Invalid Bark query parameters");
287
+ const query = queryResult.data;
288
+ const requestUrl = new URL(`/push`, withProtocol(withoutPathname(url.toString()), "https:"));
289
+ const headers = new Headers([["Content-Type", "application/json"]]);
290
+ const contentData = message.body ? {
291
+ title: message.title,
292
+ body: message.body
293
+ } : { body: message.title };
294
+ const body = defu({ device_keys: deviceKeys }, contentData, query);
295
+ return {
296
+ request: new Request(requestUrl, {
297
+ method: "POST",
298
+ headers,
299
+ body: JSON.stringify(body)
300
+ }),
301
+ fetchOptions: options.fetchOptions
302
+ };
303
+ }
304
+ });
305
+
306
+ //#endregion
307
+ //#region src/services/specialized/json/index.ts
308
+ const json = defineProvider("json:", {
309
+ transport: http,
310
+ defaultOptions: {},
311
+ async prepare(_, options) {
312
+ const url = new URL(this.url);
313
+ const headers = new Headers([["Content-Type", "application/json"]]);
314
+ const body = { title: this.message.title };
315
+ if (this.message.body) body.body = this.message.body;
316
+ Array.from(url.searchParams.entries()).forEach(([key, value]) => {
317
+ if (key.startsWith(" ")) {
318
+ url.searchParams.delete(key);
319
+ const headerKey = key.slice(1);
320
+ if (headers.has(headerKey)) headers.set(headerKey, value);
321
+ else headers.append(headerKey, value);
322
+ } else if (key.startsWith(":")) {
323
+ url.searchParams.delete(key);
324
+ const propertyKey = key.slice(1);
325
+ body[propertyKey] = value;
326
+ }
327
+ });
328
+ const requestUrl = withProtocol(url.toString(), "https:");
329
+ return {
330
+ request: new Request(requestUrl, {
331
+ method: "POST",
332
+ body: JSON.stringify(body),
333
+ headers
334
+ }),
335
+ fetchOptions: options
336
+ };
337
+ }
338
+ });
339
+
340
+ //#endregion
341
+ export { slack as a, defineTransport as c, telegram as i, defineProvider as l, bark as n, discord as o, buildSenderRegistry as r, http as s, json as t, assert as u };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "statocysts",
3
3
  "type": "module",
4
- "version": "0.6.0",
4
+ "version": "0.8.0",
5
5
  "description": "Notification library for JavaScript",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/octoplorer/statocysts",
@@ -52,9 +52,9 @@
52
52
  "zod": "^4.2.1"
53
53
  },
54
54
  "devDependencies": {
55
- "@types/node": "^25.0.2",
55
+ "@types/node": "^25.0.3",
56
56
  "@vitest/coverage-v8": "4.0.16",
57
- "tsdown": "^0.18.1",
57
+ "tsdown": "^0.18.2",
58
58
  "typescript": "^5.9.3",
59
59
  "vitest": "^4.0.16"
60
60
  },
@@ -1,180 +0,0 @@
1
- import defu from "defu";
2
- import { ofetch } from "ofetch";
3
- import { withProtocol, withoutLeadingSlash } from "ufo";
4
-
5
- //#region src/utils/assert.ts
6
- function assert(condition, message) {
7
- if (!condition) throw typeof message === "string" ? new Error(message) : message;
8
- }
9
-
10
- //#endregion
11
- //#region src/core/provider.ts
12
- function defineProvider(protocol, createOptions) {
13
- const send = async (protocolUrl, message, options) => {
14
- const url = new URL(protocolUrl);
15
- assert(url.protocol === protocol, `Unexpected protocol "${url.protocol}"`);
16
- const ctx = {
17
- url,
18
- message
19
- };
20
- const opts = defu(createOptions.defaultOptions ?? {}, options ?? {});
21
- const payload = await createOptions.prepare.call(ctx, ctx, opts);
22
- await createOptions.transport.send(payload);
23
- };
24
- return {
25
- get protocol() {
26
- return protocol;
27
- },
28
- get defaultOptions() {
29
- return createOptions.defaultOptions;
30
- },
31
- get $transport() {
32
- return createOptions.transport;
33
- },
34
- send
35
- };
36
- }
37
-
38
- //#endregion
39
- //#region src/core/transport.ts
40
- function defineTransport(transport) {
41
- return transport;
42
- }
43
-
44
- //#endregion
45
- //#region src/core/transports/http.ts
46
- /**
47
- * HTTP transport implementation
48
- * Handles sending data over HTTP/HTTPS protocols
49
- */
50
- const http = defineTransport({ async send(payload) {
51
- await ofetch(payload.request, payload.fetchOptions);
52
- } });
53
-
54
- //#endregion
55
- //#region src/services/chat/slack/index.ts
56
- const slack = defineProvider("slack:", {
57
- transport: http,
58
- defaultOptions: {
59
- hookBaseUrl: "https://hooks.slack.com/",
60
- botApiBaseUrl: "https://slack.com/"
61
- },
62
- async prepare(_, options) {
63
- const { url } = this;
64
- assert(url.hostname === "bot" || url.hostname === "webhook", `Invalid slack URL: ${url.toString()}`);
65
- const type = url.hostname;
66
- if (type === "bot") {
67
- assert(url.username, "Channel ID is required");
68
- assert(url.password, "Bot token is required");
69
- } else assert(url.pathname.split("/").filter(Boolean).length === 3, "Webhook URL is invalid");
70
- let requestUrl;
71
- const headers = new Headers([["Content-Type", "application/json"]]);
72
- const body = {};
73
- if (this.message.body) {
74
- body.blocks = [{
75
- type: "header",
76
- text: {
77
- type: "plain_text",
78
- text: this.message.title
79
- }
80
- }, {
81
- type: "section",
82
- text: {
83
- type: "mrkdwn",
84
- text: this.message.body
85
- }
86
- }];
87
- body.text = this.message.title;
88
- } else body.text = this.message.title;
89
- if (type === "bot") {
90
- const { username: channel, password: token, searchParams } = url;
91
- requestUrl = new URL("/api/chat.postMessage", options.botApiBaseUrl);
92
- searchParams.forEach((value, key) => {
93
- requestUrl.searchParams.set(key, value);
94
- });
95
- headers.set("Authorization", `Bearer ${token}`);
96
- body.channel = channel;
97
- } else {
98
- const { searchParams } = url;
99
- requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl);
100
- searchParams.forEach((value, key) => {
101
- requestUrl.searchParams.set(key, value);
102
- });
103
- }
104
- return {
105
- request: new Request(requestUrl, {
106
- method: "POST",
107
- headers,
108
- body: JSON.stringify(options.body ?? body)
109
- }),
110
- fetchOptions: options.fetchOptions
111
- };
112
- }
113
- });
114
-
115
- //#endregion
116
- //#region src/services/specialized/json/index.ts
117
- const json = defineProvider("json:", {
118
- transport: http,
119
- defaultOptions: {},
120
- async prepare(_, options) {
121
- const url = new URL(this.url);
122
- const headers = new Headers([["Content-Type", "application/json"]]);
123
- const body = { title: this.message.title };
124
- if (this.message.body) body.body = this.message.body;
125
- Array.from(url.searchParams.entries()).forEach(([key, value]) => {
126
- if (key.startsWith(" ")) {
127
- url.searchParams.delete(key);
128
- const headerKey = key.slice(1);
129
- if (headers.has(headerKey)) headers.set(headerKey, value);
130
- else headers.append(headerKey, value);
131
- } else if (key.startsWith(":")) {
132
- url.searchParams.delete(key);
133
- const propertyKey = key.slice(1);
134
- body[propertyKey] = value;
135
- }
136
- });
137
- const requestUrl = withProtocol(url.toString(), "https:");
138
- return {
139
- request: new Request(requestUrl, {
140
- method: "POST",
141
- body: JSON.stringify(body),
142
- headers
143
- }),
144
- fetchOptions: options
145
- };
146
- }
147
- });
148
-
149
- //#endregion
150
- //#region src/core/sender.ts
151
- function buildSenderRegistry(providers) {
152
- const providersRegistry = /* @__PURE__ */ new Map();
153
- providers.forEach((provider) => {
154
- providersRegistry.set(provider.protocol, provider);
155
- });
156
- function resolveProvider(url) {
157
- const _url = typeof url === "string" ? new URL(url) : url;
158
- return providersRegistry.get(_url.protocol);
159
- }
160
- function createSender(urls) {
161
- const registries = urls.map((url) => {
162
- const provider = resolveProvider(url);
163
- if (!provider) return;
164
- return {
165
- provider,
166
- url
167
- };
168
- }).filter((p) => !!p);
169
- return { async send(message, options) {
170
- for (const registry of registries) {
171
- const messageObj = { title: message };
172
- await registry.provider.send(registry.url.toString(), messageObj, options);
173
- }
174
- } };
175
- }
176
- return Object.assign(createSender, { resolveProvider });
177
- }
178
-
179
- //#endregion
180
- export { defineTransport as a, http as i, json as n, defineProvider as o, slack as r, assert as s, buildSenderRegistry as t };