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 +3 -2
- package/dist/browser.js +9 -3
- package/dist/{index-I_frtEQ-.d.ts → index-DcoOHy7e.d.ts} +26 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.js +9 -3
- package/dist/json-DAUitIVf.js +341 -0
- package/package.json +3 -3
- package/dist/shared-vzO3pF63.js +0 -180
package/dist/browser.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { a as
|
|
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
|
|
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([
|
|
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 {
|
|
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
|
|
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
|
|
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([
|
|
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.
|
|
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.
|
|
55
|
+
"@types/node": "^25.0.3",
|
|
56
56
|
"@vitest/coverage-v8": "4.0.16",
|
|
57
|
-
"tsdown": "^0.18.
|
|
57
|
+
"tsdown": "^0.18.2",
|
|
58
58
|
"typescript": "^5.9.3",
|
|
59
59
|
"vitest": "^4.0.16"
|
|
60
60
|
},
|
package/dist/shared-vzO3pF63.js
DELETED
|
@@ -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 };
|