statocysts 0.10.0 → 0.10.2
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 +1 -2
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +2 -2
- package/dist/browser.js.map +1 -1
- package/dist/index-Tf7eZY-O.d.ts +122 -0
- package/dist/index-Tf7eZY-O.d.ts.map +1 -0
- package/dist/index.d.ts +17 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +13 -2
- package/dist/index.js.map +1 -1
- package/dist/{json-DZ3LADFU.js → server-chan-UPO915jk.js} +154 -5
- package/dist/server-chan-UPO915jk.js.map +1 -0
- package/package.json +3 -3
- package/dist/core-C9zs8cU2.js +0 -355
- package/dist/core-C9zs8cU2.js.map +0 -1
- package/dist/index-BX5WDWZH.d.ts +0 -59
- package/dist/index-BX5WDWZH.d.ts.map +0 -1
- package/dist/json-DZ3LADFU.js.map +0 -1
package/dist/browser.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { a as slack, i as telegram, o as discord, r as bark, t as json } from "./index-BX5WDWZH.js";
|
|
1
|
+
import { _ as Transport, a as slack, c as http, d as SenderUrl, f as buildSenderRegistry, g as defineProvider, h as ServiceProvider, i as telegram, l as Sender, m as DefineProviderOptions, o as discord, p as DefineProviderContext, r as bark, s as HttpPayload, t as json, u as SenderRegistry, v as defineTransport } from "./index-Tf7eZY-O.js";
|
|
3
2
|
|
|
4
3
|
//#region src/browser.d.ts
|
|
5
4
|
declare const senderRegistry: SenderRegistry;
|
package/dist/browser.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.d.ts","names":[],"sources":["../src/browser.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"browser.d.ts","names":[],"sources":["../src/browser.ts"],"mappings":";;;cAUa,cAAA,EAA+F,cAAA;AAAA,iBAE5F,YAAA,CAAa,IAAA,EAAM,SAAA,KAAc,MAAA;AAAA,iBAI3B,IAAA,CACpB,GAAA,WAAc,GAAA,EACd,KAAA,UACA,IAAA,YACC,OAAA"}
|
package/dist/browser.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as slack, i as telegram, n as jsons, o as discord, r as bark, t as json } from "./json-DZ3LADFU.js";
|
|
1
|
+
import { a as buildSenderRegistry, c as discord, d as defineProvider, f as assert, i as bark, l as http, n as json, o as telegram, r as jsons, s as slack, t as serverChan, u as defineTransport } from "./server-chan-UPO915jk.js";
|
|
3
2
|
|
|
4
3
|
//#region src/browser.ts
|
|
5
4
|
const senderRegistry = buildSenderRegistry([
|
|
6
5
|
bark,
|
|
7
6
|
json,
|
|
7
|
+
serverChan,
|
|
8
8
|
jsons,
|
|
9
9
|
slack,
|
|
10
10
|
telegram,
|
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser.js","names":[],"sources":["../src/browser.ts"],"sourcesContent":["import type { Sender, SenderUrl } from '#/shared'\nimport { discord } from '#/services/chat/discord'\nimport { slack } from '#/services/chat/slack'\nimport { telegram } from '#/services/chat/telegram'\nimport { bark } from '#/services/push/bark'\nimport { json, jsons } from '#/services/specialized/json'\nimport { buildSenderRegistry } from '#/shared'\
|
|
1
|
+
{"version":3,"file":"browser.js","names":[],"sources":["../src/browser.ts"],"sourcesContent":["import type { Sender, SenderUrl } from '#/shared'\nimport { discord } from '#/services/chat/discord'\nimport { slack } from '#/services/chat/slack'\nimport { telegram } from '#/services/chat/telegram'\nimport { bark } from '#/services/push/bark'\nimport { json, jsons } from '#/services/specialized/json'\nimport { buildSenderRegistry } from '#/shared'\nimport { assert } from '#/utils'\nimport { serverChan } from './services/push/server-chan'\n\nexport const senderRegistry = buildSenderRegistry([bark, json, serverChan, jsons, slack, telegram, discord])\n\nexport function createSender(urls: SenderUrl[]): Sender {\n return senderRegistry(urls)\n}\n\nexport async function send(\n url: string | URL,\n title: string,\n body?: string,\n): Promise<void> {\n const _url = typeof url === 'string' ? new URL(url) : url\n const provider = senderRegistry.resolveProvider(_url)\n assert(provider, `Unsupported protocol ${_url.protocol}`)\n const messageObj = { title, body }\n await provider.send(_url.toString(), messageObj)\n}\n\nexport { bark, discord, json, slack, telegram }\nexport * from './shared'\n"],"mappings":";;;AAUA,MAAa,iBAAiB,oBAAoB;CAAC;CAAM;CAAM;CAAY;CAAO;CAAO;CAAU;CAAQ,CAAC;AAE5G,SAAgB,aAAa,MAA2B;AACtD,QAAO,eAAe,KAAK;;AAG7B,eAAsB,KACpB,KACA,OACA,MACe;CACf,MAAM,OAAO,OAAO,QAAQ,WAAW,IAAI,IAAI,IAAI,GAAG;CACtD,MAAM,WAAW,eAAe,gBAAgB,KAAK;AACrD,QAAO,UAAU,wBAAwB,KAAK,WAAW;CACzD,MAAM,aAAa;EAAE;EAAO;EAAM;AAClC,OAAM,SAAS,KAAK,KAAK,UAAU,EAAE,WAAW"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as ofetch0 from "ofetch";
|
|
2
|
+
import { FetchOptions } from "ofetch";
|
|
3
|
+
import z from "zod";
|
|
4
|
+
|
|
5
|
+
//#region src/core/transport.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* Transport interface for protocol-specific network communication
|
|
8
|
+
* Each transport handles the actual sending of data over a specific protocol
|
|
9
|
+
*/
|
|
10
|
+
interface Transport<Payload = unknown> {
|
|
11
|
+
/**
|
|
12
|
+
* Send data using the transport's protocol
|
|
13
|
+
* @param payload Protocol-specific payload to send
|
|
14
|
+
*/
|
|
15
|
+
send: (payload: Payload) => Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
declare function defineTransport<Payload>(transport: Transport<Payload>): Transport<Payload>;
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/core/provider.d.ts
|
|
20
|
+
type InferTransportPayload<T> = T extends Transport<infer P> ? P : never;
|
|
21
|
+
interface ServiceProvider<Protocol extends string, Payload, Options = void> {
|
|
22
|
+
readonly $transport: Transport<Payload>;
|
|
23
|
+
readonly protocol: Protocol;
|
|
24
|
+
defaultOptions: Options | undefined;
|
|
25
|
+
send: (url: string, message: {
|
|
26
|
+
title: string;
|
|
27
|
+
body?: string;
|
|
28
|
+
}, options?: Options) => Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
interface DefineProviderContext {
|
|
31
|
+
url: URL;
|
|
32
|
+
message: {
|
|
33
|
+
title: string;
|
|
34
|
+
body?: string;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
interface DefineProviderOptions<T extends Transport, Options> {
|
|
38
|
+
defaultOptions?: Options;
|
|
39
|
+
transport: T;
|
|
40
|
+
prepare: (this: DefineProviderContext, ctx: DefineProviderContext, options: Options) => Promise<InferTransportPayload<T>>;
|
|
41
|
+
}
|
|
42
|
+
declare function defineProvider<const Protocol extends string, T extends Transport<any>, Options = void>(protocol: Protocol, createOptions: DefineProviderOptions<T, Options>): ServiceProvider<Protocol, InferTransportPayload<T>, Options>;
|
|
43
|
+
//#endregion
|
|
44
|
+
//#region src/core/sender.d.ts
|
|
45
|
+
interface Sender {
|
|
46
|
+
send: (title: string, body?: string) => Promise<void>;
|
|
47
|
+
}
|
|
48
|
+
type SenderUrl = string | URL;
|
|
49
|
+
interface SenderRegistry {
|
|
50
|
+
(urls: SenderUrl[]): Sender;
|
|
51
|
+
resolveProvider: (url: string | URL) => ServiceProvider<string, any, any> | undefined;
|
|
52
|
+
}
|
|
53
|
+
declare function buildSenderRegistry(providers: ServiceProvider<string, any, any>[]): SenderRegistry;
|
|
54
|
+
//#endregion
|
|
55
|
+
//#region src/core/transports/http.d.ts
|
|
56
|
+
/**
|
|
57
|
+
* HTTP payload for HTTP transport
|
|
58
|
+
*/
|
|
59
|
+
interface HttpPayload {
|
|
60
|
+
request: Request;
|
|
61
|
+
fetchOptions?: FetchOptions;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* HTTP transport implementation
|
|
65
|
+
* Handles sending data over HTTP/HTTPS protocols
|
|
66
|
+
*/
|
|
67
|
+
declare const http: Transport<HttpPayload>;
|
|
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
|
|
75
|
+
//#region src/services/chat/slack/index.d.ts
|
|
76
|
+
interface SlackOptions {
|
|
77
|
+
/**
|
|
78
|
+
* The base URL for webhook services
|
|
79
|
+
*
|
|
80
|
+
* @default `https://hooks.slack.com/services`
|
|
81
|
+
*/
|
|
82
|
+
hookBaseUrl?: string;
|
|
83
|
+
/**
|
|
84
|
+
* The base URL for bot API services
|
|
85
|
+
*
|
|
86
|
+
* @default `https://slack.com/api`
|
|
87
|
+
*/
|
|
88
|
+
botApiBaseUrl?: string;
|
|
89
|
+
/**
|
|
90
|
+
* The body of the request
|
|
91
|
+
*
|
|
92
|
+
* NOTICE*: This will override the body of the request. You should known what you are doing.
|
|
93
|
+
*/
|
|
94
|
+
body?: Record<string, any>;
|
|
95
|
+
fetchOptions?: FetchOptions;
|
|
96
|
+
}
|
|
97
|
+
declare const slack: ServiceProvider<"slack:", HttpPayload, SlackOptions>;
|
|
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
|
|
117
|
+
//#region src/services/specialized/json/index.d.ts
|
|
118
|
+
declare const json: ServiceProvider<"json:", HttpPayload, FetchOptions<ofetch0.ResponseType, any>>;
|
|
119
|
+
declare const jsons: ServiceProvider<"jsons:", HttpPayload, FetchOptions<ofetch0.ResponseType, any>>;
|
|
120
|
+
//#endregion
|
|
121
|
+
export { Transport as _, slack as a, http as c, SenderUrl as d, buildSenderRegistry as f, defineProvider as g, ServiceProvider as h, telegram as i, Sender as l, DefineProviderOptions as m, jsons as n, discord as o, DefineProviderContext as p, bark as r, HttpPayload as s, json as t, SenderRegistry as u, defineTransport as v };
|
|
122
|
+
//# sourceMappingURL=index-Tf7eZY-O.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Tf7eZY-O.d.ts","names":[],"sources":["../src/core/transport.ts","../src/core/provider.ts","../src/core/sender.ts","../src/core/transports/http.ts","../src/services/chat/discord/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts"],"mappings":";;;;;;;;;UAIiB,SAAA;EAAA;;;;EAKf,IAAA,GAAO,OAAA,EAAS,OAAA,KAAY,OAAA;AAAA;AAAA,iBAGd,eAAA,SAAA,CACd,SAAA,EAAW,SAAA,CAAU,OAAA,IACpB,SAAA,CAAU,OAAA;;;KCTR,qBAAA,MAA2B,CAAA,SAAU,SAAA,YAAqB,CAAA;AAAA,UAE9C,eAAA;EAAA,SAKN,UAAA,EAAY,SAAA,CAAU,OAAA;EAAA,SACtB,QAAA,EAAU,QAAA;EACnB,cAAA,EAAgB,OAAA;EAChB,IAAA,GAAO,GAAA,UAAa,OAAA;IAAW,KAAA;IAAe,IAAA;EAAA,GAAiB,OAAA,GAAU,OAAA,KAAY,OAAA;AAAA;AAAA,UAGtE,qBAAA;EACf,GAAA,EAAK,GAAA;EACL,OAAA;IAAW,KAAA;IAAe,IAAA;EAAA;AAAA;AAAA,UAGX,qBAAA,WAAgC,SAAA;EAC/C,cAAA,GAAiB,OAAA;EACjB,SAAA,EAAW,CAAA;EACX,OAAA,GACE,IAAA,EAAM,qBAAA,EACN,GAAA,EAAK,qBAAA,EACL,OAAA,EAAS,OAAA,KACN,OAAA,CAAQ,qBAAA,CAAsB,CAAA;AAAA;AAAA,iBAGrB,cAAA,0CAAwD,SAAA,sBAAA,CACtE,QAAA,EAAU,QAAA,EACV,aAAA,EAAe,qBAAA,CAAsB,CAAA,EAAG,OAAA,IACvC,eAAA,CAAgB,QAAA,EAAU,qBAAA,CAAsB,CAAA,GAAI,OAAA;;;UClCtC,MAAA;EACf,IAAA,GAAO,KAAA,UAAe,IAAA,cAAkB,OAAA;AAAA;AAAA,KAG9B,SAAA,YAAqB,GAAA;AAAA,UAEhB,cAAA;EAAA,CACd,IAAA,EAAM,SAAA,KAAc,MAAA;EACrB,eAAA,GAAkB,GAAA,WAAc,GAAA,KAAQ,eAAA;AAAA;AAAA,iBAG1B,mBAAA,CACd,SAAA,EAAW,eAAA,uBACV,cAAA;;;;;;UCRc,WAAA;EACf,OAAA,EAAS,OAAA;EACT,YAAA,GAAe,YAAA;AAAA;;;;;cAOJ,IAAA,EAAI,SAAA,CAAA,WAAA;;;UCTP,cAAA;EACR,YAAA,GAAe,YAAA;AAAA;AAAA,cAeJ,OAAA,EAAO,eAAA,aA2ClB,WAAA,EA3CkB,cAAA;;;UCjBH,YAAA;;;;ALFjB;;EKQE,WAAA;ELHmC;;;;;EKSnC,aAAA;ELTmC;;AAGrC;;;EKaE,IAAA,GAAO,MAAA;EAEP,YAAA,GAAe,YAAA;AAAA;AAAA,cAGJ,KAAA,EAAK,eAAA,WAsFhB,WAAA,EAtFgB,YAAA;;;UCnBD,eAAA;ENFf;;;;;EMQA,UAAA;EAEA,YAAA,GAAe,YAAA;AAAA;AAAA,cAGJ,QAAA,EAAQ,eAAA,cAgGnB,WAAA,EAhGmB,eAAA;;;UCfJ,WAAA;EACf,YAAA,GAAe,YAAA;AAAA;AAAA,cAoBJ,IAAA,EAAI,eAAA,UAyCf,WAAA,EAzCe,WAAA;;;cC4BJ,IAAA,EAAI,eAAA,UAMf,WAAA,EANe,YAAA,CAAA,OAAA,CAAA,YAAA;AAAA,cASJ,KAAA,EAAK,eAAA,WAMhB,WAAA,EANgB,YAAA,CAAA,OAAA,CAAA,YAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import {
|
|
3
|
-
import { SMTPConnectionOptions } from "emailjs";
|
|
1
|
+
import { _ as Transport, a as slack, c as http, d as SenderUrl, f as buildSenderRegistry, g as defineProvider, h as ServiceProvider, i as telegram, l as Sender, m as DefineProviderOptions, n as jsons, o as discord, p as DefineProviderContext, r as bark, s as HttpPayload, t as json, u as SenderRegistry, v as defineTransport } from "./index-Tf7eZY-O.js";
|
|
2
|
+
import { Message, MessageHeaders, SMTPConnectionOptions } from "emailjs";
|
|
4
3
|
|
|
4
|
+
//#region src/core/transports/smtp.d.ts
|
|
5
|
+
/**
|
|
6
|
+
* SMTP payload for SMTP transport
|
|
7
|
+
*/
|
|
8
|
+
interface SmtpPayload {
|
|
9
|
+
/**
|
|
10
|
+
* SMTP client configuration
|
|
11
|
+
*/
|
|
12
|
+
client: Partial<SMTPConnectionOptions>;
|
|
13
|
+
/**
|
|
14
|
+
* Email message to send
|
|
15
|
+
*/
|
|
16
|
+
message: Message | MessageHeaders;
|
|
17
|
+
}
|
|
18
|
+
//#endregion
|
|
5
19
|
//#region src/services/specialized/email/index.d.ts
|
|
6
20
|
interface EmailOptions {
|
|
7
21
|
defaultFrom?: string;
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/services/specialized/email/index.ts","../src/index.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../src/core/transports/smtp.ts","../src/services/specialized/email/index.ts","../src/index.ts"],"mappings":";;;;;;;UAOiB,WAAA;EAAW;;;EAI1B,MAAA,EAAQ,OAAA,CAAQ,qBAAA;EAIP;;;EAAT,OAAA,EAAS,OAAA,GAAU,cAAA;AAAA;;;UCRJ,YAAA;EAEf,WAAA;EAEA,UAAA,GAAa,OAAA,CAAQ,qBAAA;AAAA;AAAA,cAWV,KAAA,EAAK,eAAA,WAAA,WAAA,EAAA,YAAA;;;cCXL,cAAA,EAAsG,cAAA;AAAA,iBAEnG,YAAA,CAAa,IAAA,EAAM,SAAA,KAAc,MAAA;AAAA,iBAI3B,IAAA,CACpB,GAAA,WAAc,GAAA,EACd,KAAA,UACA,IAAA,YACC,OAAA"}
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as slack, i as telegram, n as jsons, o as discord, r as bark, t as json } from "./json-DZ3LADFU.js";
|
|
1
|
+
import { a as buildSenderRegistry, c as discord, d as defineProvider, f as assert, i as bark, l as http, n as json, o as telegram, r as jsons, s as slack, t as serverChan, u as defineTransport } from "./server-chan-UPO915jk.js";
|
|
3
2
|
import z from "zod";
|
|
3
|
+
import { SMTPClient } from "emailjs";
|
|
4
4
|
|
|
5
|
+
//#region src/core/transports/smtp.ts
|
|
6
|
+
/**
|
|
7
|
+
* SMTP transport implementation
|
|
8
|
+
* Handles sending emails over SMTP protocol using emailjs
|
|
9
|
+
*/
|
|
10
|
+
const smtp = defineTransport({ async send(payload) {
|
|
11
|
+
await new SMTPClient(payload.client).sendAsync(payload.message);
|
|
12
|
+
} });
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
5
15
|
//#region src/services/specialized/email/index.ts
|
|
6
16
|
const queryParamSchema = z.object({
|
|
7
17
|
from: z.string().email().optional(),
|
|
@@ -70,6 +80,7 @@ const senderRegistry = buildSenderRegistry([
|
|
|
70
80
|
email,
|
|
71
81
|
json,
|
|
72
82
|
jsons,
|
|
83
|
+
serverChan,
|
|
73
84
|
slack,
|
|
74
85
|
telegram,
|
|
75
86
|
discord
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/services/specialized/email/index.ts","../src/index.ts"],"sourcesContent":["import type { SmtpPayload } from '#/core/transports/smtp'\nimport type { SMTPConnectionOptions } from 'emailjs'\nimport { defineProvider } from '#/core/provider'\nimport { smtp } from '#/core/transports/smtp'\nimport { assert } from '#/utils'\nimport z from 'zod'\n\nexport interface EmailOptions {\n // Optional default sender email address\n defaultFrom?: string\n // Optional default SMTP configuration\n smtpConfig?: Partial<SMTPConnectionOptions>\n}\n\n// Zod schema for validating single-value query parameters\nconst queryParamSchema = z.object({\n from: z.string().email().optional(),\n subject: z.string().optional(),\n ssl: z.string().transform(val => val === 'true').optional(),\n tls: z.string().transform(val => val !== 'false').optional(),\n})\n\nexport const email = defineProvider('email:', {\n transport: smtp,\n defaultOptions: {} as EmailOptions,\n async prepare(ctx, options) {\n const { url, message } = ctx\n\n // Parse query parameters (use getAll for multi-value parameters)\n const to = url.searchParams.getAll('to')\n const cc = url.searchParams.getAll('cc')\n const bcc = url.searchParams.getAll('bcc')\n\n // Parse single-value parameters\n const from = url.searchParams.get('from')\n const subject = url.searchParams.get('subject')\n const sslParam = url.searchParams.get('ssl')\n const tlsParam = url.searchParams.get('tls')\n\n // Validate single-value parameters\n const queryResult = queryParamSchema.safeParse({\n from: from || undefined,\n subject: subject || undefined,\n ssl: sslParam || undefined,\n tls: tlsParam || undefined,\n })\n\n if (!queryResult.success) {\n throw new Error(`Invalid email query parameters: ${queryResult.error.message}`)\n }\n\n const query = queryResult.data\n\n // Build SMTP client configuration\n const host = url.hostname\n assert(host, 'SMTP host is required')\n\n const port = url.port ? Number.parseInt(url.port, 10) : 587\n const user = decodeURIComponent(url.username || '')\n const password = decodeURIComponent(url.password || '')\n\n // Determine sender address\n const fromAddress = query.from || options.defaultFrom || user\n assert(fromAddress, 'Sender email address (from) is required')\n\n // Ensure at least one recipient is provided\n assert(to.length > 0, 'At least one recipient email address (to) is required')\n\n // Build email message\n const emailSubject = query.subject || message.title\n const text = message.body\n ? `${message.title}\\n\\n${message.body}`\n : message.title\n\n // Build SMTP payload\n const smtpPayload: SmtpPayload = {\n client: {\n host,\n port,\n // Only include auth if both user and password are provided\n ...(user && password ? { user, password } : {}),\n ssl: query.ssl ?? false,\n tls: query.tls ?? (port === 587),\n ...options.smtpConfig,\n },\n message: {\n from: fromAddress,\n to: to.join(', '), // emailjs accepts comma-separated string\n cc: cc.length > 0 ? cc.join(', ') : undefined,\n bcc: bcc.length > 0 ? bcc.join(', ') : undefined,\n subject: emailSubject,\n text,\n },\n }\n\n return smtpPayload\n },\n})\n","import type { Sender, SenderUrl } from '#/shared'\nimport { discord } from '#/services/chat/discord'\nimport { slack } from '#/services/chat/slack'\nimport { telegram } from '#/services/chat/telegram'\nimport { bark } from '#/services/push/bark'\nimport { email } from '#/services/specialized/email'\nimport { json, jsons } from '#/services/specialized/json'\nimport { buildSenderRegistry } from '#/shared'\
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/core/transports/smtp.ts","../src/services/specialized/email/index.ts","../src/index.ts"],"sourcesContent":["import type { Message, MessageHeaders, SMTPConnectionOptions } from 'emailjs'\nimport { SMTPClient } from 'emailjs'\nimport { defineTransport } from '../transport'\n\n/**\n * SMTP payload for SMTP transport\n */\nexport interface SmtpPayload {\n /**\n * SMTP client configuration\n */\n client: Partial<SMTPConnectionOptions>\n /**\n * Email message to send\n */\n message: Message | MessageHeaders\n}\n\n/**\n * SMTP transport implementation\n * Handles sending emails over SMTP protocol using emailjs\n */\nexport const smtp = defineTransport({\n async send(payload: SmtpPayload) {\n const client = new SMTPClient(payload.client)\n await client.sendAsync(payload.message)\n },\n})\n","import type { SmtpPayload } from '#/core/transports/smtp'\nimport type { SMTPConnectionOptions } from 'emailjs'\nimport { defineProvider } from '#/core/provider'\nimport { smtp } from '#/core/transports/smtp'\nimport { assert } from '#/utils'\nimport z from 'zod'\n\nexport interface EmailOptions {\n // Optional default sender email address\n defaultFrom?: string\n // Optional default SMTP configuration\n smtpConfig?: Partial<SMTPConnectionOptions>\n}\n\n// Zod schema for validating single-value query parameters\nconst queryParamSchema = z.object({\n from: z.string().email().optional(),\n subject: z.string().optional(),\n ssl: z.string().transform(val => val === 'true').optional(),\n tls: z.string().transform(val => val !== 'false').optional(),\n})\n\nexport const email = defineProvider('email:', {\n transport: smtp,\n defaultOptions: {} as EmailOptions,\n async prepare(ctx, options) {\n const { url, message } = ctx\n\n // Parse query parameters (use getAll for multi-value parameters)\n const to = url.searchParams.getAll('to')\n const cc = url.searchParams.getAll('cc')\n const bcc = url.searchParams.getAll('bcc')\n\n // Parse single-value parameters\n const from = url.searchParams.get('from')\n const subject = url.searchParams.get('subject')\n const sslParam = url.searchParams.get('ssl')\n const tlsParam = url.searchParams.get('tls')\n\n // Validate single-value parameters\n const queryResult = queryParamSchema.safeParse({\n from: from || undefined,\n subject: subject || undefined,\n ssl: sslParam || undefined,\n tls: tlsParam || undefined,\n })\n\n if (!queryResult.success) {\n throw new Error(`Invalid email query parameters: ${queryResult.error.message}`)\n }\n\n const query = queryResult.data\n\n // Build SMTP client configuration\n const host = url.hostname\n assert(host, 'SMTP host is required')\n\n const port = url.port ? Number.parseInt(url.port, 10) : 587\n const user = decodeURIComponent(url.username || '')\n const password = decodeURIComponent(url.password || '')\n\n // Determine sender address\n const fromAddress = query.from || options.defaultFrom || user\n assert(fromAddress, 'Sender email address (from) is required')\n\n // Ensure at least one recipient is provided\n assert(to.length > 0, 'At least one recipient email address (to) is required')\n\n // Build email message\n const emailSubject = query.subject || message.title\n const text = message.body\n ? `${message.title}\\n\\n${message.body}`\n : message.title\n\n // Build SMTP payload\n const smtpPayload: SmtpPayload = {\n client: {\n host,\n port,\n // Only include auth if both user and password are provided\n ...(user && password ? { user, password } : {}),\n ssl: query.ssl ?? false,\n tls: query.tls ?? (port === 587),\n ...options.smtpConfig,\n },\n message: {\n from: fromAddress,\n to: to.join(', '), // emailjs accepts comma-separated string\n cc: cc.length > 0 ? cc.join(', ') : undefined,\n bcc: bcc.length > 0 ? bcc.join(', ') : undefined,\n subject: emailSubject,\n text,\n },\n }\n\n return smtpPayload\n },\n})\n","import type { Sender, SenderUrl } from '#/shared'\nimport { discord } from '#/services/chat/discord'\nimport { slack } from '#/services/chat/slack'\nimport { telegram } from '#/services/chat/telegram'\nimport { bark } from '#/services/push/bark'\nimport { email } from '#/services/specialized/email'\nimport { json, jsons } from '#/services/specialized/json'\nimport { buildSenderRegistry } from '#/shared'\nimport { assert } from '#/utils'\nimport { serverChan } from './services/push/server-chan'\n\nexport const senderRegistry = buildSenderRegistry([bark, email, json, jsons, serverChan, slack, telegram, discord])\n\nexport function createSender(urls: SenderUrl[]): Sender {\n return senderRegistry(urls)\n}\n\nexport async function send(\n url: string | URL,\n title: string,\n body?: string,\n): Promise<void> {\n const _url = typeof url === 'string' ? new URL(url) : url\n const provider = senderRegistry.resolveProvider(_url)\n assert(provider, `Unsupported protocol ${_url.protocol}`)\n const messageObj = { title, body }\n await provider.send(_url.toString(), messageObj)\n}\n\nexport { bark, discord, email, json, jsons, slack, telegram }\nexport * from './shared'\n"],"mappings":";;;;;;;;;AAsBA,MAAa,OAAO,gBAAgB,EAClC,MAAM,KAAK,SAAsB;AAE/B,OADe,IAAI,WAAW,QAAQ,OAAO,CAChC,UAAU,QAAQ,QAAQ;GAE1C,CAAC;;;;ACZF,MAAM,mBAAmB,EAAE,OAAO;CAChC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,UAAU;CACnC,SAAS,EAAE,QAAQ,CAAC,UAAU;CAC9B,KAAK,EAAE,QAAQ,CAAC,WAAU,QAAO,QAAQ,OAAO,CAAC,UAAU;CAC3D,KAAK,EAAE,QAAQ,CAAC,WAAU,QAAO,QAAQ,QAAQ,CAAC,UAAU;CAC7D,CAAC;AAEF,MAAa,QAAQ,eAAe,UAAU;CAC5C,WAAW;CACX,gBAAgB,EAAE;CAClB,MAAM,QAAQ,KAAK,SAAS;EAC1B,MAAM,EAAE,KAAK,YAAY;EAGzB,MAAM,KAAK,IAAI,aAAa,OAAO,KAAK;EACxC,MAAM,KAAK,IAAI,aAAa,OAAO,KAAK;EACxC,MAAM,MAAM,IAAI,aAAa,OAAO,MAAM;EAG1C,MAAM,OAAO,IAAI,aAAa,IAAI,OAAO;EACzC,MAAM,UAAU,IAAI,aAAa,IAAI,UAAU;EAC/C,MAAM,WAAW,IAAI,aAAa,IAAI,MAAM;EAC5C,MAAM,WAAW,IAAI,aAAa,IAAI,MAAM;EAG5C,MAAM,cAAc,iBAAiB,UAAU;GAC7C,MAAM,QAAQ;GACd,SAAS,WAAW;GACpB,KAAK,YAAY;GACjB,KAAK,YAAY;GAClB,CAAC;AAEF,MAAI,CAAC,YAAY,QACf,OAAM,IAAI,MAAM,mCAAmC,YAAY,MAAM,UAAU;EAGjF,MAAM,QAAQ,YAAY;EAG1B,MAAM,OAAO,IAAI;AACjB,SAAO,MAAM,wBAAwB;EAErC,MAAM,OAAO,IAAI,OAAO,OAAO,SAAS,IAAI,MAAM,GAAG,GAAG;EACxD,MAAM,OAAO,mBAAmB,IAAI,YAAY,GAAG;EACnD,MAAM,WAAW,mBAAmB,IAAI,YAAY,GAAG;EAGvD,MAAM,cAAc,MAAM,QAAQ,QAAQ,eAAe;AACzD,SAAO,aAAa,0CAA0C;AAG9D,SAAO,GAAG,SAAS,GAAG,wDAAwD;EAG9E,MAAM,eAAe,MAAM,WAAW,QAAQ;EAC9C,MAAM,OAAO,QAAQ,OACjB,GAAG,QAAQ,MAAM,MAAM,QAAQ,SAC/B,QAAQ;AAuBZ,SApBiC;GAC/B,QAAQ;IACN;IACA;IAEA,GAAI,QAAQ,WAAW;KAAE;KAAM;KAAU,GAAG,EAAE;IAC9C,KAAK,MAAM,OAAO;IAClB,KAAK,MAAM,OAAQ,SAAS;IAC5B,GAAG,QAAQ;IACZ;GACD,SAAS;IACP,MAAM;IACN,IAAI,GAAG,KAAK,KAAK;IACjB,IAAI,GAAG,SAAS,IAAI,GAAG,KAAK,KAAK,GAAG;IACpC,KAAK,IAAI,SAAS,IAAI,IAAI,KAAK,KAAK,GAAG;IACvC,SAAS;IACT;IACD;GACF;;CAIJ,CAAC;;;;ACtFF,MAAa,iBAAiB,oBAAoB;CAAC;CAAM;CAAO;CAAM;CAAO;CAAY;CAAO;CAAU;CAAQ,CAAC;AAEnH,SAAgB,aAAa,MAA2B;AACtD,QAAO,eAAe,KAAK;;AAG7B,eAAsB,KACpB,KACA,OACA,MACe;CACf,MAAM,OAAO,OAAO,QAAQ,WAAW,IAAI,IAAI,IAAI,GAAG;CACtD,MAAM,WAAW,eAAe,gBAAgB,KAAK;AACrD,QAAO,UAAU,wBAAwB,KAAK,WAAW;CACzD,MAAM,aAAa;EAAE;EAAO;EAAM;AAClC,OAAM,SAAS,KAAK,KAAK,UAAU,EAAE,WAAW"}
|
|
@@ -1,8 +1,78 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { withProtocol, withoutLeadingSlash } from "ufo";
|
|
1
|
+
import { getQuery, withProtocol, withoutLeadingSlash } from "ufo";
|
|
3
2
|
import defu from "defu";
|
|
3
|
+
import { ofetch } from "ofetch";
|
|
4
4
|
import z from "zod";
|
|
5
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
|
|
6
76
|
//#region src/services/chat/discord/index.ts
|
|
7
77
|
const querySchema$1 = z.object({
|
|
8
78
|
avatar_url: z.string().optional(),
|
|
@@ -150,6 +220,39 @@ const telegram = defineProvider("telegram:", {
|
|
|
150
220
|
}
|
|
151
221
|
});
|
|
152
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(title, body) {
|
|
244
|
+
for (const registry of registries) {
|
|
245
|
+
const messageObj = {
|
|
246
|
+
title,
|
|
247
|
+
body
|
|
248
|
+
};
|
|
249
|
+
await registry.provider.send(registry.url.toString(), messageObj);
|
|
250
|
+
}
|
|
251
|
+
} };
|
|
252
|
+
}
|
|
253
|
+
return Object.assign(createSender, { resolveProvider });
|
|
254
|
+
}
|
|
255
|
+
|
|
153
256
|
//#endregion
|
|
154
257
|
//#region src/services/push/bark/index.ts
|
|
155
258
|
const querySchema = z.object({
|
|
@@ -205,7 +308,7 @@ const bark = defineProvider("bark:", {
|
|
|
205
308
|
|
|
206
309
|
//#endregion
|
|
207
310
|
//#region src/services/specialized/json/index.ts
|
|
208
|
-
async function prepareJsonRequest(
|
|
311
|
+
async function prepareJsonRequest(_ctx, defaultProtocol, options) {
|
|
209
312
|
const url = new URL(this.url);
|
|
210
313
|
const protocol = defaultProtocol;
|
|
211
314
|
const headers = new Headers([["Content-Type", "application/json"]]);
|
|
@@ -249,5 +352,51 @@ const jsons = defineProvider("jsons:", {
|
|
|
249
352
|
});
|
|
250
353
|
|
|
251
354
|
//#endregion
|
|
252
|
-
|
|
253
|
-
|
|
355
|
+
//#region src/services/push/server-chan/index.ts
|
|
356
|
+
const serverChan = defineProvider("server-chan:", {
|
|
357
|
+
transport: http,
|
|
358
|
+
defaultOptions: {},
|
|
359
|
+
async prepare(_, options) {
|
|
360
|
+
const { url } = this;
|
|
361
|
+
assert(url.hostname === "v3" || url.hostname === "turbo", `Invalid server-chan URL: hostname must be 'v3' or 'turbo', got '${url.hostname}'`);
|
|
362
|
+
const version = url.hostname;
|
|
363
|
+
let requestUrl;
|
|
364
|
+
const headers = new Headers([["Content-Type", "application/json"]]);
|
|
365
|
+
const body = { title: this.message.title };
|
|
366
|
+
if (this.message.body) body.desp = this.message.body;
|
|
367
|
+
if (version === "v3") {
|
|
368
|
+
const { username: uid, password: sendKey, searchParams } = url;
|
|
369
|
+
assert(uid, "UID is required for Server Chan 3");
|
|
370
|
+
assert(sendKey, "SendKey is required for Server Chan 3");
|
|
371
|
+
requestUrl = new URL(`https://${uid}.push.ft07.com/send/${sendKey}.send`);
|
|
372
|
+
const tags = [];
|
|
373
|
+
searchParams.forEach((value, key) => {
|
|
374
|
+
if (key === "tags") tags.push(value);
|
|
375
|
+
else if (key === "short") body.short = value;
|
|
376
|
+
});
|
|
377
|
+
if (tags.length > 0) body.tags = tags.join("|");
|
|
378
|
+
} else {
|
|
379
|
+
const { password: sendKey, searchParams } = url;
|
|
380
|
+
assert(sendKey, "SendKey is required for Server Chan Turbo");
|
|
381
|
+
requestUrl = new URL(`https://sctapi.ftqq.com/${sendKey}.send`);
|
|
382
|
+
searchParams.forEach((value, key) => {
|
|
383
|
+
if (key === "short") body.short = value;
|
|
384
|
+
else if (key === "noip") body.noip = value === "1" || value === "true" ? 1 : 0;
|
|
385
|
+
else if (key === "channel") body.channel = value;
|
|
386
|
+
else if (key === "openid") body.openid = value;
|
|
387
|
+
});
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
request: new Request(requestUrl, {
|
|
391
|
+
method: "POST",
|
|
392
|
+
headers,
|
|
393
|
+
body: JSON.stringify(body)
|
|
394
|
+
}),
|
|
395
|
+
fetchOptions: options.fetchOptions
|
|
396
|
+
};
|
|
397
|
+
}
|
|
398
|
+
});
|
|
399
|
+
|
|
400
|
+
//#endregion
|
|
401
|
+
export { buildSenderRegistry as a, discord as c, defineProvider as d, assert as f, bark as i, http as l, json as n, telegram as o, jsons as r, slack as s, serverChan as t, defineTransport as u };
|
|
402
|
+
//# sourceMappingURL=server-chan-UPO915jk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-chan-UPO915jk.js","names":["querySchema"],"sources":["../src/utils/assert.ts","../src/utils/markdown.ts","../src/utils/url.ts","../src/core/provider.ts","../src/core/transport.ts","../src/core/transports/http.ts","../src/services/chat/discord/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/core/sender.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts","../src/services/push/server-chan/index.ts"],"sourcesContent":["export function assert(condition: any, message: string | Error): asserts condition {\n if (!condition) {\n throw typeof message === 'string' ? new Error(message) : message\n }\n}\n","/**\n * Escape special characters: _*[]()~`>#+-=|{}.!\n */\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!])/g, '\\\\$1')\n}\n","import { getQuery } from 'ufo'\n\nexport function getValidateQuery<T>(\n url: URL | string,\n parser: (params: unknown) => T,\n): T {\n const query = getQuery(url.toString())\n return parser(query)\n}\n\nexport function withoutPathname(input: string): string {\n const _url = new URL(input)\n _url.pathname = ''\n return _url.toString()\n}\n","import type { Transport } from './transport'\nimport { assert } from '#/utils'\nimport defu from 'defu'\n\n// Utility type to infer Payload from Transport\ntype InferTransportPayload<T> = T extends Transport<infer P> ? P : never\n\nexport interface ServiceProvider<\n Protocol extends string,\n Payload,\n Options = void,\n> {\n readonly $transport: Transport<Payload>\n readonly protocol: Protocol\n defaultOptions: Options | undefined\n send: (url: string, message: { title: string, body?: string }, options?: Options) => Promise<void>\n}\n\nexport interface DefineProviderContext {\n url: URL\n message: { title: string, body?: string }\n}\n\nexport interface DefineProviderOptions<T extends Transport, Options> {\n defaultOptions?: Options\n transport: T\n prepare: (\n this: DefineProviderContext,\n ctx: DefineProviderContext,\n options: Options,\n ) => Promise<InferTransportPayload<T>>\n}\n\nexport function defineProvider<const Protocol extends string, T extends Transport<any>, Options = void>(\n protocol: Protocol,\n createOptions: DefineProviderOptions<T, Options>,\n): ServiceProvider<Protocol, InferTransportPayload<T>, Options> {\n const send: ServiceProvider<Protocol, InferTransportPayload<T>, Options>['send'] = async (\n protocolUrl,\n message,\n options,\n ): Promise<void> => {\n const url = new URL(protocolUrl)\n\n assert(url.protocol === protocol, `Unexpected protocol \"${url.protocol}\"`)\n\n const ctx: DefineProviderContext = {\n url,\n message,\n }\n\n const opts = defu(options ?? {}, createOptions.defaultOptions ?? {}) as Options\n\n const payload = await createOptions.prepare.call(ctx, ctx, opts)\n\n await createOptions.transport.send(payload)\n }\n return {\n get protocol() {\n return protocol\n },\n get defaultOptions() {\n return createOptions.defaultOptions\n },\n get $transport() {\n return createOptions.transport\n },\n send,\n }\n}\n","/**\n * Transport interface for protocol-specific network communication\n * Each transport handles the actual sending of data over a specific protocol\n */\nexport interface Transport<Payload = unknown> {\n /**\n * Send data using the transport's protocol\n * @param payload Protocol-specific payload to send\n */\n send: (payload: Payload) => Promise<void>\n}\n\nexport function defineTransport<Payload>(\n transport: Transport<Payload>,\n): Transport<Payload> {\n return transport\n}\n","import type { FetchOptions } from 'ofetch'\nimport { ofetch } from 'ofetch'\nimport { defineTransport } from '../transport'\n\n/**\n * HTTP payload for HTTP transport\n */\nexport interface HttpPayload {\n request: Request\n fetchOptions?: FetchOptions\n}\n\n/**\n * HTTP transport implementation\n * Handles sending data over HTTP/HTTPS protocols\n */\nexport const http = defineTransport({\n async send(payload: HttpPayload) {\n await ofetch(payload.request, payload.fetchOptions)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert, getValidateQuery } from '#/utils'\nimport defu from 'defu'\nimport z from 'zod'\n\ninterface DiscordOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n avatar_url: z.string().optional(),\n username: z.string().optional(),\n\n wait: z.string().transform((val) => {\n if (val === 'false' || val === '0' || val === '') {\n return false\n }\n return true\n }).optional(),\n})\n\nexport const discord = defineProvider('discord:', {\n transport: http,\n defaultOptions: {} as DiscordOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid discord URL')\n assert(url.username, 'Webhook ID is required')\n assert(url.password, 'Webhook token is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid discord query')\n }\n\n const { wait, ...query } = queryResult.data\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const content = ctx.message.body ? `## ${ctx.message.title}\\n\\n${ctx.message.body}` : ctx.message.title\n\n const body = defu({ content }, query)\n\n const requestUrl = new URL(`/api/webhooks/${url.username}/${url.password}`, 'https://discord.com')\n\n if (wait) {\n requestUrl.searchParams.set('wait', 'true')\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\nimport { withoutLeadingSlash } from 'ufo'\n\nexport interface SlackOptions {\n /**\n * The base URL for webhook services\n *\n * @default `https://hooks.slack.com/services`\n */\n hookBaseUrl?: string\n /**\n * The base URL for bot API services\n *\n * @default `https://slack.com/api`\n */\n botApiBaseUrl?: string\n\n /**\n * The body of the request\n *\n * NOTICE*: This will override the body of the request. You should known what you are doing.\n */\n body?: Record<string, any>\n\n fetchOptions?: FetchOptions\n}\n\nexport const slack = defineProvider('slack:', {\n transport: http,\n defaultOptions: {\n hookBaseUrl: 'https://hooks.slack.com/',\n botApiBaseUrl: 'https://slack.com/',\n } as SlackOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot' || url.hostname === 'webhook', `Invalid slack URL: ${url.toString()}`)\n\n const type = url.hostname as 'bot' | 'webhook'\n\n if (type === 'bot') {\n assert(url.username, 'Channel ID is required')\n assert(url.password, 'Bot token is required')\n }\n else {\n const pathParts = url.pathname.split('/').filter(Boolean)\n assert(pathParts.length === 3, 'Webhook URL is invalid')\n }\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {}\n\n // Build message content based on title and body\n if (this.message.body) {\n // When body is present, use blocks for rich markdown formatting\n body.blocks = [\n {\n type: 'header',\n text: {\n type: 'plain_text',\n text: this.message.title,\n },\n },\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: this.message.body,\n },\n },\n ]\n // Fallback text for notifications\n body.text = this.message.title\n }\n else {\n // When only title is present, use simple text format\n body.text = this.message.title\n }\n\n if (type === 'bot') {\n const { username: channel, password: token, searchParams } = url\n requestUrl = new URL('/api/chat.postMessage', options.botApiBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n\n headers.set('Authorization', `Bearer ${token}`)\n\n body.channel = channel\n }\n else {\n const { searchParams } = url\n requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(options.body ?? body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { escapeMarkdown, getValidateQuery } from '#/utils'\nimport { assert } from '#/utils/assert'\nimport z from 'zod'\n\nexport const telegramQuerySchema = z.object({\n parse_mode: z.enum(['Markdown', 'MarkdownV2', 'HTML']).optional(),\n})\n\nexport interface TelegramOptions {\n /**\n * The base URL for Telegram Bot API\n *\n * @default `https://api.telegram.org`\n */\n apiBaseUrl?: string\n\n fetchOptions?: FetchOptions\n}\n\nexport const telegram = defineProvider('telegram:', {\n transport: http,\n defaultOptions: {\n apiBaseUrl: 'https://api.telegram.org',\n } as TelegramOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot', `Invalid telegram URL: ${url.toString()}`)\n assert(url.username, 'Bot token is required')\n\n // Extract chat IDs from pathname (e.g., /chat-1/chat-2)\n const pathSegments = url.pathname.split('/').filter(Boolean)\n assert(pathSegments.length > 0, 'At least one chat ID is required')\n\n const queryResult = getValidateQuery(url, telegramQuerySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid telegram query')\n }\n\n const query = queryResult.data\n\n // Bot token is in the username and password fields, because token contains `:` character\n const botToken = `${url.username}:${url.password}`\n\n // First chat ID from pathname (decode to handle @ symbols like @mychannel)\n // Support format: chat-id or chat-id:message-thread-id\n const chatPart = decodeURIComponent(pathSegments[0])\n const [chatId, messageThreadId] = chatPart.includes(':')\n ? chatPart.split(':', 2)\n : [chatPart, undefined]\n\n // Build API URL\n const requestUrl = new URL(`/bot${botToken}/sendMessage`, options.apiBaseUrl)\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n // Build message text based on parse_mode\n let text: string\n if (this.message.body) {\n // Title as h1, body as content\n const parseMode = query.parse_mode\n let titleFormatted: string\n\n if (parseMode === 'HTML') {\n titleFormatted = `<b>${this.message.title}</b>`\n }\n else if (parseMode === 'MarkdownV2') {\n // MarkdownV2 requires escaping special characters\n const escapedTitle = escapeMarkdown(this.message.title)\n titleFormatted = `*${escapedTitle}*`\n }\n else {\n // Markdown or default\n titleFormatted = `*${this.message.title}*`\n }\n\n text = `${titleFormatted}\\n\\n${this.message.body}`\n }\n else {\n // No body, title is the main content\n // Need to escape special characters in MarkdownV2 mode\n if (query.parse_mode === 'MarkdownV2') {\n text = escapeMarkdown(this.message.title)\n }\n else {\n text = this.message.title\n }\n }\n\n const body: Record<string, any> = {\n chat_id: chatId,\n text,\n parse_mode: query.parse_mode,\n }\n\n // Add message_thread_id if specified (for topic/forum groups)\n if (messageThreadId) {\n body.message_thread_id = Number.parseInt(messageThreadId, 10)\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { ServiceProvider } from '#/core/provider'\n\nexport interface Sender {\n send: (title: string, body?: string) => Promise<void>\n}\n\nexport type SenderUrl = string | URL\n\nexport interface SenderRegistry {\n (urls: SenderUrl[]): Sender\n resolveProvider: (url: string | URL) => ServiceProvider<string, any, any> | undefined\n}\n\nexport function buildSenderRegistry(\n providers: ServiceProvider<string, any, any>[],\n): SenderRegistry {\n const providersRegistry = new Map<string, ServiceProvider<string, any, any>>()\n providers.forEach((provider) => {\n providersRegistry.set(provider.protocol, provider)\n })\n\n function resolveProvider(\n url: string | URL,\n ): ServiceProvider<string, any, any> | undefined {\n const _url = typeof url === 'string' ? new URL(url) : url\n\n return providersRegistry.get(_url.protocol)\n }\n\n function createSender(urls: SenderUrl[]): Sender {\n const registries = urls.map((url) => {\n const provider = resolveProvider(url)\n if (!provider) {\n return undefined\n }\n return { provider, url }\n }).filter((p): p is { provider: ServiceProvider<string, any, any>, url: SenderUrl } => !!p)\n\n return {\n async send(title: string, body?: string) {\n for (const registry of registries) {\n // Convert message string to { title, body? } format\n const messageObj = { title, body }\n await registry.provider.send(\n registry.url.toString(),\n messageObj,\n )\n }\n },\n }\n }\n\n return Object.assign(createSender, { resolveProvider })\n}\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert, getValidateQuery, withoutPathname } from '#/utils'\nimport defu from 'defu'\nimport { withProtocol } from 'ufo'\nimport z from 'zod'\n\nexport interface BarkOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n subtitle: z.string().optional(),\n group: z.string().optional(),\n url: z.string().optional(),\n icon: z.string().optional(),\n sound: z.string().optional(),\n call: z.enum(['1']).optional(),\n ciphertext: z.string().optional(),\n level: z.enum(['active', 'timeSensitive', 'passive', 'critical']).optional(),\n volume: z.string().optional(),\n badge: z.coerce.number().optional(),\n autoCopy: z.enum(['1']).optional(),\n copy: z.string().optional(),\n action: z.enum(['none']).optional(),\n isArchive: z.enum(['1']).optional(),\n})\n\nexport const bark = defineProvider('bark:', {\n transport: http,\n defaultOptions: {} as BarkOptions,\n async prepare(ctx, options) {\n const { message, url } = ctx\n\n assert(url.hostname, 'Server URL hostname is required')\n assert(url.pathname, 'Device key is required')\n\n const deviceKeys = url.pathname.split('/').filter(Boolean)\n assert(deviceKeys.length > 0, 'At least one device key is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid Bark query parameters')\n }\n\n const query = queryResult.data\n\n const requestUrl = new URL(`/push`, withProtocol(withoutPathname(url.toString()), 'https:'))\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const contentData: { body: string, title?: string } = message.body ? { title: message.title, body: message.body } : { body: message.title }\n\n const body = defu({ device_keys: deviceKeys }, contentData, query)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { DefineProviderContext } from '#/core/provider'\nimport type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { withProtocol } from 'ufo'\n\nasync function prepareJsonRequest(this: DefineProviderContext, _ctx: DefineProviderContext, defaultProtocol: string, options: FetchOptions) {\n const url = new URL(this.url)\n\n const protocol = defaultProtocol\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const body: Record<string, string> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.body = this.message.body\n }\n\n Array.from(url.searchParams.entries()).forEach(([key, value]) => {\n if (key.startsWith(' ')) {\n url.searchParams.delete(key)\n const headerKey = key.slice(1)\n if (headers.has(headerKey)) {\n headers.set(headerKey, value)\n }\n else {\n headers.append(headerKey, value)\n }\n }\n else if (key.startsWith(':')) {\n url.searchParams.delete(key)\n const propertyKey = key.slice(1)\n body[propertyKey] = value\n }\n })\n\n const requestUrl = withProtocol(url.toString(), protocol)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n body: JSON.stringify(body),\n headers,\n })\n\n return {\n request,\n fetchOptions: options,\n }\n}\n\n// Supports json:// protocol (default to HTTP)\nexport const json = defineProvider('json:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'http:', options)\n },\n})\n\n// Supports jsons:// protocol (explicit HTTPS)\nexport const jsons = defineProvider('jsons:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'https:', options)\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert } from '#/utils'\n\nexport interface ServerChanOptions {\n fetchOptions?: FetchOptions\n}\n\nexport const serverChan = defineProvider('server-chan:', {\n transport: http,\n defaultOptions: {} as ServerChanOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL hostname to determine version\n assert(\n url.hostname === 'v3' || url.hostname === 'turbo',\n `Invalid server-chan URL: hostname must be 'v3' or 'turbo', got '${url.hostname}'`,\n )\n\n const version = url.hostname as 'v3' | 'turbo'\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.desp = this.message.body\n }\n\n if (version === 'v3') {\n // Server Chan 3: server-chan://uid:sendKey@v3?tags=<tag1>&tags=<tag2>&short=<short>\n const { username: uid, password: sendKey, searchParams } = url\n\n assert(uid, 'UID is required for Server Chan 3')\n assert(sendKey, 'SendKey is required for Server Chan 3')\n\n requestUrl = new URL(`https://${uid}.push.ft07.com/send/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n const tags: string[] = []\n searchParams.forEach((value, key) => {\n if (key === 'tags') {\n tags.push(value)\n }\n else if (key === 'short') {\n body.short = value\n }\n })\n\n if (tags.length > 0) {\n body.tags = tags.join('|')\n }\n }\n else {\n // Server Chan Turbo: server-chan://ftqq:SENDKEY@turbo?short=<short>&noip=<1|0|true|false>&channel=<channel>&openid=<openid>\n // Note: username (ftqq) is optional and not used in the API request\n const { password: sendKey, searchParams } = url\n\n assert(sendKey, 'SendKey is required for Server Chan Turbo')\n\n requestUrl = new URL(`https://sctapi.ftqq.com/${sendKey}.send`)\n\n // Add optional parameters from searchParams\n searchParams.forEach((value, key) => {\n if (key === 'short') {\n body.short = value\n }\n else if (key === 'noip') {\n body.noip = value === '1' || value === 'true' ? 1 : 0\n }\n else if (key === 'channel') {\n body.channel = value\n }\n else if (key === 'openid') {\n body.openid = value\n }\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "statocysts",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.10.
|
|
4
|
+
"version": "0.10.2",
|
|
5
5
|
"description": "Notification library for JavaScript",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/octoplorer/statocysts",
|
|
@@ -53,9 +53,9 @@
|
|
|
53
53
|
"zod": "^4.3.6"
|
|
54
54
|
},
|
|
55
55
|
"devDependencies": {
|
|
56
|
-
"@types/node": "^25.
|
|
56
|
+
"@types/node": "^25.2.0",
|
|
57
57
|
"@types/smtp-server": "^3.5.12",
|
|
58
|
-
"@vitest/coverage-v8": "4.0.
|
|
58
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
59
59
|
"smtp-server": "^3.18.1",
|
|
60
60
|
"tsdown": "^0.20.1",
|
|
61
61
|
"typescript": "^5.9.3",
|
package/dist/core-C9zs8cU2.js
DELETED
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
import { getQuery } from "ufo";
|
|
2
|
-
import defu from "defu";
|
|
3
|
-
import { FetchOptions, ofetch } from "ofetch";
|
|
4
|
-
import { Message, MessageHeaders, SMTPClient, SMTPConnectionOptions } from "emailjs";
|
|
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$1(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$1(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$1 = defineTransport$1({ async send(payload) {
|
|
72
|
-
await ofetch(payload.request, payload.fetchOptions);
|
|
73
|
-
} });
|
|
74
|
-
|
|
75
|
-
//#endregion
|
|
76
|
-
//#region src/core/sender.ts
|
|
77
|
-
function buildSenderRegistry$1(providers) {
|
|
78
|
-
const providersRegistry = /* @__PURE__ */ new Map();
|
|
79
|
-
providers.forEach((provider) => {
|
|
80
|
-
providersRegistry.set(provider.protocol, provider);
|
|
81
|
-
});
|
|
82
|
-
function resolveProvider(url) {
|
|
83
|
-
const _url = typeof url === "string" ? new URL(url) : url;
|
|
84
|
-
return providersRegistry.get(_url.protocol);
|
|
85
|
-
}
|
|
86
|
-
function createSender(urls) {
|
|
87
|
-
const registries = urls.map((url) => {
|
|
88
|
-
const provider = resolveProvider(url);
|
|
89
|
-
if (!provider) return;
|
|
90
|
-
return {
|
|
91
|
-
provider,
|
|
92
|
-
url
|
|
93
|
-
};
|
|
94
|
-
}).filter((p) => !!p);
|
|
95
|
-
return { async send(title, body) {
|
|
96
|
-
for (const registry of registries) {
|
|
97
|
-
const messageObj = {
|
|
98
|
-
title,
|
|
99
|
-
body
|
|
100
|
-
};
|
|
101
|
-
await registry.provider.send(registry.url.toString(), messageObj);
|
|
102
|
-
}
|
|
103
|
-
} };
|
|
104
|
-
}
|
|
105
|
-
return Object.assign(createSender, { resolveProvider });
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
//#endregion
|
|
109
|
-
//#region src/core/transports/smtp.ts
|
|
110
|
-
/**
|
|
111
|
-
* SMTP transport implementation
|
|
112
|
-
* Handles sending emails over SMTP protocol using emailjs
|
|
113
|
-
*/
|
|
114
|
-
const smtp = defineTransport$1({ async send(payload) {
|
|
115
|
-
await new SMTPClient(payload.client).sendAsync(payload.message);
|
|
116
|
-
} });
|
|
117
|
-
|
|
118
|
-
//#endregion
|
|
119
|
-
//#region src/core/transport.d.ts
|
|
120
|
-
var Transport = [
|
|
121
|
-
28,
|
|
122
|
-
(Payload) => [Payload, Promise],
|
|
123
|
-
[
|
|
124
|
-
"",
|
|
125
|
-
"",
|
|
126
|
-
"",
|
|
127
|
-
"",
|
|
128
|
-
""
|
|
129
|
-
]
|
|
130
|
-
];
|
|
131
|
-
var defineTransport = [
|
|
132
|
-
29,
|
|
133
|
-
(Payload) => [
|
|
134
|
-
Payload,
|
|
135
|
-
Transport,
|
|
136
|
-
Payload,
|
|
137
|
-
Transport
|
|
138
|
-
],
|
|
139
|
-
[
|
|
140
|
-
"",
|
|
141
|
-
"",
|
|
142
|
-
"",
|
|
143
|
-
"",
|
|
144
|
-
"",
|
|
145
|
-
""
|
|
146
|
-
]
|
|
147
|
-
];
|
|
148
|
-
|
|
149
|
-
//#endregion
|
|
150
|
-
//#region src/core/provider.d.ts
|
|
151
|
-
var InferTransportPayload = [
|
|
152
|
-
19,
|
|
153
|
-
(T) => [T, Transport],
|
|
154
|
-
[
|
|
155
|
-
"",
|
|
156
|
-
"",
|
|
157
|
-
"",
|
|
158
|
-
"",
|
|
159
|
-
""
|
|
160
|
-
]
|
|
161
|
-
];
|
|
162
|
-
var ServiceProvider = [
|
|
163
|
-
20,
|
|
164
|
-
(Protocol, Payload, Options) => [
|
|
165
|
-
Payload,
|
|
166
|
-
Transport,
|
|
167
|
-
Protocol,
|
|
168
|
-
Options,
|
|
169
|
-
Options,
|
|
170
|
-
Promise
|
|
171
|
-
],
|
|
172
|
-
[
|
|
173
|
-
"",
|
|
174
|
-
"",
|
|
175
|
-
"",
|
|
176
|
-
"",
|
|
177
|
-
"",
|
|
178
|
-
"",
|
|
179
|
-
"",
|
|
180
|
-
"",
|
|
181
|
-
"",
|
|
182
|
-
"",
|
|
183
|
-
"",
|
|
184
|
-
"",
|
|
185
|
-
"",
|
|
186
|
-
"",
|
|
187
|
-
"",
|
|
188
|
-
"",
|
|
189
|
-
"",
|
|
190
|
-
""
|
|
191
|
-
]
|
|
192
|
-
];
|
|
193
|
-
var DefineProviderContext = [
|
|
194
|
-
21,
|
|
195
|
-
() => [URL],
|
|
196
|
-
[
|
|
197
|
-
"",
|
|
198
|
-
"",
|
|
199
|
-
"",
|
|
200
|
-
"",
|
|
201
|
-
""
|
|
202
|
-
]
|
|
203
|
-
];
|
|
204
|
-
var DefineProviderOptions = [
|
|
205
|
-
22,
|
|
206
|
-
(T, Options) => [
|
|
207
|
-
Transport,
|
|
208
|
-
Options,
|
|
209
|
-
T,
|
|
210
|
-
DefineProviderContext,
|
|
211
|
-
DefineProviderContext,
|
|
212
|
-
Options,
|
|
213
|
-
T,
|
|
214
|
-
InferTransportPayload,
|
|
215
|
-
Promise
|
|
216
|
-
],
|
|
217
|
-
[
|
|
218
|
-
"",
|
|
219
|
-
"",
|
|
220
|
-
"",
|
|
221
|
-
"",
|
|
222
|
-
"",
|
|
223
|
-
"",
|
|
224
|
-
"",
|
|
225
|
-
"",
|
|
226
|
-
"",
|
|
227
|
-
"",
|
|
228
|
-
"",
|
|
229
|
-
"",
|
|
230
|
-
"",
|
|
231
|
-
"",
|
|
232
|
-
"",
|
|
233
|
-
"",
|
|
234
|
-
""
|
|
235
|
-
]
|
|
236
|
-
];
|
|
237
|
-
var defineProvider = [
|
|
238
|
-
23,
|
|
239
|
-
(Protocol, T, Options) => [
|
|
240
|
-
Transport,
|
|
241
|
-
Protocol,
|
|
242
|
-
T,
|
|
243
|
-
Options,
|
|
244
|
-
DefineProviderOptions,
|
|
245
|
-
Protocol,
|
|
246
|
-
T,
|
|
247
|
-
InferTransportPayload,
|
|
248
|
-
Options,
|
|
249
|
-
ServiceProvider
|
|
250
|
-
],
|
|
251
|
-
[
|
|
252
|
-
"",
|
|
253
|
-
"",
|
|
254
|
-
"",
|
|
255
|
-
"",
|
|
256
|
-
"",
|
|
257
|
-
"",
|
|
258
|
-
"",
|
|
259
|
-
"",
|
|
260
|
-
"",
|
|
261
|
-
"",
|
|
262
|
-
"",
|
|
263
|
-
"",
|
|
264
|
-
"",
|
|
265
|
-
"",
|
|
266
|
-
""
|
|
267
|
-
]
|
|
268
|
-
];
|
|
269
|
-
|
|
270
|
-
//#endregion
|
|
271
|
-
//#region src/core/sender.d.ts
|
|
272
|
-
var Sender = [
|
|
273
|
-
30,
|
|
274
|
-
() => [Promise],
|
|
275
|
-
[
|
|
276
|
-
"",
|
|
277
|
-
"",
|
|
278
|
-
"",
|
|
279
|
-
""
|
|
280
|
-
]
|
|
281
|
-
];
|
|
282
|
-
var SenderUrl = [
|
|
283
|
-
31,
|
|
284
|
-
() => [URL],
|
|
285
|
-
[""]
|
|
286
|
-
];
|
|
287
|
-
var SenderRegistry = [
|
|
288
|
-
32,
|
|
289
|
-
() => [
|
|
290
|
-
SenderUrl,
|
|
291
|
-
Sender,
|
|
292
|
-
URL,
|
|
293
|
-
ServiceProvider
|
|
294
|
-
],
|
|
295
|
-
[
|
|
296
|
-
"",
|
|
297
|
-
"",
|
|
298
|
-
"",
|
|
299
|
-
"",
|
|
300
|
-
"",
|
|
301
|
-
"",
|
|
302
|
-
""
|
|
303
|
-
]
|
|
304
|
-
];
|
|
305
|
-
var buildSenderRegistry = [
|
|
306
|
-
33,
|
|
307
|
-
() => [ServiceProvider, SenderRegistry],
|
|
308
|
-
[
|
|
309
|
-
"",
|
|
310
|
-
"",
|
|
311
|
-
""
|
|
312
|
-
]
|
|
313
|
-
];
|
|
314
|
-
|
|
315
|
-
//#endregion
|
|
316
|
-
//#region src/core/transports/http.d.ts
|
|
317
|
-
var HttpPayload = [
|
|
318
|
-
24,
|
|
319
|
-
() => [Request, FetchOptions],
|
|
320
|
-
[
|
|
321
|
-
"",
|
|
322
|
-
"",
|
|
323
|
-
"",
|
|
324
|
-
""
|
|
325
|
-
]
|
|
326
|
-
];
|
|
327
|
-
var http = [
|
|
328
|
-
25,
|
|
329
|
-
() => [HttpPayload, Transport],
|
|
330
|
-
["", ""]
|
|
331
|
-
];
|
|
332
|
-
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/core/transports/smtp.d.ts
|
|
335
|
-
var SmtpPayload = [
|
|
336
|
-
26,
|
|
337
|
-
() => [
|
|
338
|
-
SMTPConnectionOptions,
|
|
339
|
-
Partial,
|
|
340
|
-
Message,
|
|
341
|
-
MessageHeaders
|
|
342
|
-
],
|
|
343
|
-
[
|
|
344
|
-
"",
|
|
345
|
-
"",
|
|
346
|
-
"",
|
|
347
|
-
"",
|
|
348
|
-
"",
|
|
349
|
-
""
|
|
350
|
-
]
|
|
351
|
-
];
|
|
352
|
-
|
|
353
|
-
//#endregion
|
|
354
|
-
export { assert as S, defineTransport$1 as _, SenderRegistry as a, withoutPathname as b, DefineProviderContext as c, defineProvider as d, Transport as f, http$1 as g, buildSenderRegistry$1 as h, Sender as i, DefineProviderOptions as l, smtp as m, HttpPayload as n, SenderUrl as o, defineTransport as p, http as r, buildSenderRegistry as s, SmtpPayload as t, ServiceProvider as u, defineProvider$1 as v, escapeMarkdown as x, getValidateQuery as y };
|
|
355
|
-
//# sourceMappingURL=core-C9zs8cU2.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"core-C9zs8cU2.js","names":["defineProvider","defineTransport","http","defineTransport","buildSenderRegistry","defineTransport"],"sources":["../src/utils/assert.ts","../src/utils/markdown.ts","../src/utils/url.ts","../src/core/provider.ts","../src/core/transport.ts","../src/core/transports/http.ts","../src/core/sender.ts","../src/core/transports/smtp.ts","../src/core/transport.ts","../src/core/provider.ts","../src/core/sender.ts","../src/core/transports/http.ts","../src/core/transports/smtp.ts"],"sourcesContent":["export function assert(condition: any, message: string | Error): asserts condition {\n if (!condition) {\n throw typeof message === 'string' ? new Error(message) : message\n }\n}\n","/**\n * Escape special characters: _*[]()~`>#+-=|{}.!\n */\nexport function escapeMarkdown(text: string): string {\n return text.replace(/([_*[\\]()~`>#+\\-=|{}.!])/g, '\\\\$1')\n}\n","import { getQuery } from 'ufo'\n\nexport function getValidateQuery<T>(\n url: URL | string,\n parser: (params: unknown) => T,\n): T {\n const query = getQuery(url.toString())\n return parser(query)\n}\n\nexport function withoutPathname(input: string): string {\n const _url = new URL(input)\n _url.pathname = ''\n return _url.toString()\n}\n","import type { Transport } from './transport'\nimport { assert } from '#/utils'\nimport defu from 'defu'\n\n// Utility type to infer Payload from Transport\ntype InferTransportPayload<T> = T extends Transport<infer P> ? P : never\n\nexport interface ServiceProvider<\n Protocol extends string,\n Payload,\n Options = void,\n> {\n readonly $transport: Transport<Payload>\n readonly protocol: Protocol\n defaultOptions: Options | undefined\n send: (url: string, message: { title: string, body?: string }, options?: Options) => Promise<void>\n}\n\nexport interface DefineProviderContext {\n url: URL\n message: { title: string, body?: string }\n}\n\nexport interface DefineProviderOptions<T extends Transport, Options> {\n defaultOptions?: Options\n transport: T\n prepare: (\n this: DefineProviderContext,\n ctx: DefineProviderContext,\n options: Options,\n ) => Promise<InferTransportPayload<T>>\n}\n\nexport function defineProvider<const Protocol extends string, T extends Transport<any>, Options = void>(\n protocol: Protocol,\n createOptions: DefineProviderOptions<T, Options>,\n): ServiceProvider<Protocol, InferTransportPayload<T>, Options> {\n const send: ServiceProvider<Protocol, InferTransportPayload<T>, Options>['send'] = async (\n protocolUrl,\n message,\n options,\n ): Promise<void> => {\n const url = new URL(protocolUrl)\n\n assert(url.protocol === protocol, `Unexpected protocol \"${url.protocol}\"`)\n\n const ctx: DefineProviderContext = {\n url,\n message,\n }\n\n const opts = defu(options ?? {}, createOptions.defaultOptions ?? {}) as Options\n\n const payload = await createOptions.prepare.call(ctx, ctx, opts)\n\n await createOptions.transport.send(payload)\n }\n return {\n get protocol() {\n return protocol\n },\n get defaultOptions() {\n return createOptions.defaultOptions\n },\n get $transport() {\n return createOptions.transport\n },\n send,\n }\n}\n","/**\n * Transport interface for protocol-specific network communication\n * Each transport handles the actual sending of data over a specific protocol\n */\nexport interface Transport<Payload = unknown> {\n /**\n * Send data using the transport's protocol\n * @param payload Protocol-specific payload to send\n */\n send: (payload: Payload) => Promise<void>\n}\n\nexport function defineTransport<Payload>(\n transport: Transport<Payload>,\n): Transport<Payload> {\n return transport\n}\n","import type { FetchOptions } from 'ofetch'\nimport { ofetch } from 'ofetch'\nimport { defineTransport } from '../transport'\n\n/**\n * HTTP payload for HTTP transport\n */\nexport interface HttpPayload {\n request: Request\n fetchOptions?: FetchOptions\n}\n\n/**\n * HTTP transport implementation\n * Handles sending data over HTTP/HTTPS protocols\n */\nexport const http = defineTransport({\n async send(payload: HttpPayload) {\n await ofetch(payload.request, payload.fetchOptions)\n },\n})\n","import type { ServiceProvider } from '#/core/provider'\n\nexport interface Sender {\n send: (title: string, body?: string) => Promise<void>\n}\n\nexport type SenderUrl = string | URL\n\nexport interface SenderRegistry {\n (urls: SenderUrl[]): Sender\n resolveProvider: (url: string | URL) => ServiceProvider<string, any, any> | undefined\n}\n\nexport function buildSenderRegistry(\n providers: ServiceProvider<string, any, any>[],\n): SenderRegistry {\n const providersRegistry = new Map<string, ServiceProvider<string, any, any>>()\n providers.forEach((provider) => {\n providersRegistry.set(provider.protocol, provider)\n })\n\n function resolveProvider(\n url: string | URL,\n ): ServiceProvider<string, any, any> | undefined {\n const _url = typeof url === 'string' ? new URL(url) : url\n\n return providersRegistry.get(_url.protocol)\n }\n\n function createSender(urls: SenderUrl[]): Sender {\n const registries = urls.map((url) => {\n const provider = resolveProvider(url)\n if (!provider) {\n return undefined\n }\n return { provider, url }\n }).filter((p): p is { provider: ServiceProvider<string, any, any>, url: SenderUrl } => !!p)\n\n return {\n async send(title: string, body?: string) {\n for (const registry of registries) {\n // Convert message string to { title, body? } format\n const messageObj = { title, body }\n await registry.provider.send(\n registry.url.toString(),\n messageObj,\n )\n }\n },\n }\n }\n\n return Object.assign(createSender, { resolveProvider })\n}\n","import type { Message, MessageHeaders, SMTPConnectionOptions } from 'emailjs'\nimport { SMTPClient } from 'emailjs'\nimport { defineTransport } from '../transport'\n\n/**\n * SMTP payload for SMTP transport\n */\nexport interface SmtpPayload {\n /**\n * SMTP client configuration\n */\n client: Partial<SMTPConnectionOptions>\n /**\n * Email message to send\n */\n message: Message | MessageHeaders\n}\n\n/**\n * SMTP transport implementation\n * Handles sending emails over SMTP protocol using emailjs\n */\nexport const smtp = defineTransport({\n async send(payload: SmtpPayload) {\n const client = new SMTPClient(payload.client)\n await client.sendAsync(payload.message)\n },\n})\n"],"mappings":"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"}
|
package/dist/index-BX5WDWZH.d.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { n as HttpPayload, u as ServiceProvider } from "./core-C9zs8cU2.js";
|
|
2
|
-
import * as ofetch0 from "ofetch";
|
|
3
|
-
import { FetchOptions } from "ofetch";
|
|
4
|
-
import z from "zod";
|
|
5
|
-
|
|
6
|
-
//#region src/services/chat/discord/index.d.ts
|
|
7
|
-
interface DiscordOptions {
|
|
8
|
-
fetchOptions?: FetchOptions;
|
|
9
|
-
}
|
|
10
|
-
declare const discord: ServiceProvider<"discord:", HttpPayload, DiscordOptions>;
|
|
11
|
-
//#endregion
|
|
12
|
-
//#region src/services/chat/slack/index.d.ts
|
|
13
|
-
interface SlackOptions {
|
|
14
|
-
/**
|
|
15
|
-
* The base URL for webhook services
|
|
16
|
-
*
|
|
17
|
-
* @default `https://hooks.slack.com/services`
|
|
18
|
-
*/
|
|
19
|
-
hookBaseUrl?: string;
|
|
20
|
-
/**
|
|
21
|
-
* The base URL for bot API services
|
|
22
|
-
*
|
|
23
|
-
* @default `https://slack.com/api`
|
|
24
|
-
*/
|
|
25
|
-
botApiBaseUrl?: string;
|
|
26
|
-
/**
|
|
27
|
-
* The body of the request
|
|
28
|
-
*
|
|
29
|
-
* NOTICE*: This will override the body of the request. You should known what you are doing.
|
|
30
|
-
*/
|
|
31
|
-
body?: Record<string, any>;
|
|
32
|
-
fetchOptions?: FetchOptions;
|
|
33
|
-
}
|
|
34
|
-
declare const slack: ServiceProvider<"slack:", HttpPayload, SlackOptions>;
|
|
35
|
-
//#endregion
|
|
36
|
-
//#region src/services/chat/telegram/index.d.ts
|
|
37
|
-
interface TelegramOptions {
|
|
38
|
-
/**
|
|
39
|
-
* The base URL for Telegram Bot API
|
|
40
|
-
*
|
|
41
|
-
* @default `https://api.telegram.org`
|
|
42
|
-
*/
|
|
43
|
-
apiBaseUrl?: string;
|
|
44
|
-
fetchOptions?: FetchOptions;
|
|
45
|
-
}
|
|
46
|
-
declare const telegram: ServiceProvider<"telegram:", HttpPayload, TelegramOptions>;
|
|
47
|
-
//#endregion
|
|
48
|
-
//#region src/services/push/bark/index.d.ts
|
|
49
|
-
interface BarkOptions {
|
|
50
|
-
fetchOptions?: FetchOptions;
|
|
51
|
-
}
|
|
52
|
-
declare const bark: ServiceProvider<"bark:", HttpPayload, BarkOptions>;
|
|
53
|
-
//#endregion
|
|
54
|
-
//#region src/services/specialized/json/index.d.ts
|
|
55
|
-
declare const json: ServiceProvider<"json:", HttpPayload, FetchOptions<ofetch0.ResponseType, any>>;
|
|
56
|
-
declare const jsons: ServiceProvider<"jsons:", HttpPayload, FetchOptions<ofetch0.ResponseType, any>>;
|
|
57
|
-
//#endregion
|
|
58
|
-
export { slack as a, telegram as i, jsons as n, discord as o, bark as r, json as t };
|
|
59
|
-
//# sourceMappingURL=index-BX5WDWZH.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-BX5WDWZH.d.ts","names":[],"sources":["../src/services/chat/discord/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts"],"mappings":";;;;;;UAOU,cAAA;EACR,YAAA,GAAe,YAAA;AAAA;AAAA,cAeJ,OAAA,EAAO,eAAA,aA2ClB,WAAA,EA3CkB,cAAA;;;UCjBH,YAAA;;;;;ADNyB;ECYxC,WAAA;;;;ADWF;;ECLE,aAAA;EDgDA;;;;;ECzCA,IAAA,GAAO,MAAA;EAEP,YAAA,GAAe,YAAA;AAAA;AAAA,cAGJ,KAAA,EAAK,eAAA,WAsFhB,WAAA,EAtFgB,YAAA;;;UCnBD,eAAA;EFHY;AAe7B;;;;EENE,UAAA;EAEA,YAAA,GAAe,YAAA;AAAA;AAAA,cAGJ,QAAA,EAAQ,eAAA,cAgGnB,WAAA,EAhGmB,eAAA;;;UCfJ,WAAA;EACf,YAAA,GAAe,YAAA;AAAA;AAAA,cAoBJ,IAAA,EAAI,eAAA,UAyCf,WAAA,EAzCe,WAAA;;;cC2BJ,IAAA,EAAI,eAAA,UAMf,WAAA,EANe,YAAA,CAAA,OAAA,CAAA,YAAA;AAAA,cASJ,KAAA,EAAK,eAAA,WAMhB,WAAA,EANgB,YAAA,CAAA,OAAA,CAAA,YAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"json-DZ3LADFU.js","names":["querySchema"],"sources":["../src/services/chat/discord/index.ts","../src/services/chat/slack/index.ts","../src/services/chat/telegram/index.ts","../src/services/push/bark/index.ts","../src/services/specialized/json/index.ts"],"sourcesContent":["import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert, getValidateQuery } from '#/utils'\nimport defu from 'defu'\nimport z from 'zod'\n\ninterface DiscordOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n avatar_url: z.string().optional(),\n username: z.string().optional(),\n\n wait: z.string().transform((val) => {\n if (val === 'false' || val === '0' || val === '') {\n return false\n }\n return true\n }).optional(),\n})\n\nexport const discord = defineProvider('discord:', {\n transport: http,\n defaultOptions: {} as DiscordOptions,\n async prepare(ctx, options) {\n const { url } = ctx\n\n assert(url.hostname === 'webhook', 'Invalid discord URL')\n assert(url.username, 'Webhook ID is required')\n assert(url.password, 'Webhook token is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid discord query')\n }\n\n const { wait, ...query } = queryResult.data\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const content = ctx.message.body ? `## ${ctx.message.title}\\n\\n${ctx.message.body}` : ctx.message.title\n\n const body = defu({ content }, query)\n\n const requestUrl = new URL(`/api/webhooks/${url.username}/${url.password}`, 'https://discord.com')\n\n if (wait) {\n requestUrl.searchParams.set('wait', 'true')\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { assert } from '#/utils'\nimport { withoutLeadingSlash } from 'ufo'\n\nexport interface SlackOptions {\n /**\n * The base URL for webhook services\n *\n * @default `https://hooks.slack.com/services`\n */\n hookBaseUrl?: string\n /**\n * The base URL for bot API services\n *\n * @default `https://slack.com/api`\n */\n botApiBaseUrl?: string\n\n /**\n * The body of the request\n *\n * NOTICE*: This will override the body of the request. You should known what you are doing.\n */\n body?: Record<string, any>\n\n fetchOptions?: FetchOptions\n}\n\nexport const slack = defineProvider('slack:', {\n transport: http,\n defaultOptions: {\n hookBaseUrl: 'https://hooks.slack.com/',\n botApiBaseUrl: 'https://slack.com/',\n } as SlackOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot' || url.hostname === 'webhook', `Invalid slack URL: ${url.toString()}`)\n\n const type = url.hostname as 'bot' | 'webhook'\n\n if (type === 'bot') {\n assert(url.username, 'Channel ID is required')\n assert(url.password, 'Bot token is required')\n }\n else {\n const pathParts = url.pathname.split('/').filter(Boolean)\n assert(pathParts.length === 3, 'Webhook URL is invalid')\n }\n\n let requestUrl: URL\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n const body: Record<string, any> = {}\n\n // Build message content based on title and body\n if (this.message.body) {\n // When body is present, use blocks for rich markdown formatting\n body.blocks = [\n {\n type: 'header',\n text: {\n type: 'plain_text',\n text: this.message.title,\n },\n },\n {\n type: 'section',\n text: {\n type: 'mrkdwn',\n text: this.message.body,\n },\n },\n ]\n // Fallback text for notifications\n body.text = this.message.title\n }\n else {\n // When only title is present, use simple text format\n body.text = this.message.title\n }\n\n if (type === 'bot') {\n const { username: channel, password: token, searchParams } = url\n requestUrl = new URL('/api/chat.postMessage', options.botApiBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n\n headers.set('Authorization', `Bearer ${token}`)\n\n body.channel = channel\n }\n else {\n const { searchParams } = url\n requestUrl = new URL(`/services/${withoutLeadingSlash(url.pathname)}`, options.hookBaseUrl)\n searchParams.forEach((value, key) => {\n requestUrl.searchParams.set(key, value)\n })\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(options.body ?? body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { escapeMarkdown, getValidateQuery } from '#/utils'\nimport { assert } from '#/utils/assert'\nimport z from 'zod'\n\nexport const telegramQuerySchema = z.object({\n parse_mode: z.enum(['Markdown', 'MarkdownV2', 'HTML']).optional(),\n})\n\nexport interface TelegramOptions {\n /**\n * The base URL for Telegram Bot API\n *\n * @default `https://api.telegram.org`\n */\n apiBaseUrl?: string\n\n fetchOptions?: FetchOptions\n}\n\nexport const telegram = defineProvider('telegram:', {\n transport: http,\n defaultOptions: {\n apiBaseUrl: 'https://api.telegram.org',\n } as TelegramOptions,\n async prepare(_, options) {\n const { url } = this\n\n // Validate URL format\n assert(url.hostname === 'bot', `Invalid telegram URL: ${url.toString()}`)\n assert(url.username, 'Bot token is required')\n\n // Extract chat IDs from pathname (e.g., /chat-1/chat-2)\n const pathSegments = url.pathname.split('/').filter(Boolean)\n assert(pathSegments.length > 0, 'At least one chat ID is required')\n\n const queryResult = getValidateQuery(url, telegramQuerySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid telegram query')\n }\n\n const query = queryResult.data\n\n // Bot token is in the username and password fields, because token contains `:` character\n const botToken = `${url.username}:${url.password}`\n\n // First chat ID from pathname (decode to handle @ symbols like @mychannel)\n // Support format: chat-id or chat-id:message-thread-id\n const chatPart = decodeURIComponent(pathSegments[0])\n const [chatId, messageThreadId] = chatPart.includes(':')\n ? chatPart.split(':', 2)\n : [chatPart, undefined]\n\n // Build API URL\n const requestUrl = new URL(`/bot${botToken}/sendMessage`, options.apiBaseUrl)\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n // Build message text based on parse_mode\n let text: string\n if (this.message.body) {\n // Title as h1, body as content\n const parseMode = query.parse_mode\n let titleFormatted: string\n\n if (parseMode === 'HTML') {\n titleFormatted = `<b>${this.message.title}</b>`\n }\n else if (parseMode === 'MarkdownV2') {\n // MarkdownV2 requires escaping special characters\n const escapedTitle = escapeMarkdown(this.message.title)\n titleFormatted = `*${escapedTitle}*`\n }\n else {\n // Markdown or default\n titleFormatted = `*${this.message.title}*`\n }\n\n text = `${titleFormatted}\\n\\n${this.message.body}`\n }\n else {\n // No body, title is the main content\n // Need to escape special characters in MarkdownV2 mode\n if (query.parse_mode === 'MarkdownV2') {\n text = escapeMarkdown(this.message.title)\n }\n else {\n text = this.message.title\n }\n }\n\n const body: Record<string, any> = {\n chat_id: chatId,\n text,\n parse_mode: query.parse_mode,\n }\n\n // Add message_thread_id if specified (for topic/forum groups)\n if (messageThreadId) {\n body.message_thread_id = Number.parseInt(messageThreadId, 10)\n }\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider, http } from '#/shared'\nimport { assert, getValidateQuery, withoutPathname } from '#/utils'\nimport defu from 'defu'\nimport { withProtocol } from 'ufo'\nimport z from 'zod'\n\nexport interface BarkOptions {\n fetchOptions?: FetchOptions\n}\n\nconst querySchema = z.object({\n subtitle: z.string().optional(),\n group: z.string().optional(),\n url: z.string().optional(),\n icon: z.string().optional(),\n sound: z.string().optional(),\n call: z.enum(['1']).optional(),\n ciphertext: z.string().optional(),\n level: z.enum(['active', 'timeSensitive', 'passive', 'critical']).optional(),\n volume: z.string().optional(),\n badge: z.coerce.number().optional(),\n autoCopy: z.enum(['1']).optional(),\n copy: z.string().optional(),\n action: z.enum(['none']).optional(),\n isArchive: z.enum(['1']).optional(),\n})\n\nexport const bark = defineProvider('bark:', {\n transport: http,\n defaultOptions: {} as BarkOptions,\n async prepare(ctx, options) {\n const { message, url } = ctx\n\n assert(url.hostname, 'Server URL hostname is required')\n assert(url.pathname, 'Device key is required')\n\n const deviceKeys = url.pathname.split('/').filter(Boolean)\n assert(deviceKeys.length > 0, 'At least one device key is required')\n\n const queryResult = getValidateQuery(url, querySchema.safeParse)\n\n if (!queryResult.success) {\n throw new Error('Invalid Bark query parameters')\n }\n\n const query = queryResult.data\n\n const requestUrl = new URL(`/push`, withProtocol(withoutPathname(url.toString()), 'https:'))\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const contentData: { body: string, title?: string } = message.body ? { title: message.title, body: message.body } : { body: message.title }\n\n const body = defu({ device_keys: deviceKeys }, contentData, query)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n })\n\n return {\n request,\n fetchOptions: options.fetchOptions,\n }\n },\n})\n","import type { FetchOptions } from 'ofetch'\nimport { defineProvider } from '#/core/provider'\nimport { http } from '#/core/transports/http'\nimport { withProtocol } from 'ufo'\n\nasync function prepareJsonRequest(this: any, ctx: any, defaultProtocol: string, options: FetchOptions) {\n const url = new URL(this.url)\n\n const protocol = defaultProtocol\n\n const headers = new Headers([\n ['Content-Type', 'application/json'],\n ])\n\n const body: Record<string, string> = {\n title: this.message.title,\n }\n\n if (this.message.body) {\n body.body = this.message.body\n }\n\n Array.from(url.searchParams.entries()).forEach(([key, value]) => {\n if (key.startsWith(' ')) {\n url.searchParams.delete(key)\n const headerKey = key.slice(1)\n if (headers.has(headerKey)) {\n headers.set(headerKey, value)\n }\n else {\n headers.append(headerKey, value)\n }\n }\n else if (key.startsWith(':')) {\n url.searchParams.delete(key)\n const propertyKey = key.slice(1)\n body[propertyKey] = value\n }\n })\n\n const requestUrl = withProtocol(url.toString(), protocol)\n\n const request = new Request(requestUrl, {\n method: 'POST',\n body: JSON.stringify(body),\n headers,\n })\n\n return {\n request,\n fetchOptions: options,\n }\n}\n\n// Supports json:// protocol (default to HTTP)\nexport const json = defineProvider('json:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'http:', options)\n },\n})\n\n// Supports jsons:// protocol (explicit HTTPS)\nexport const jsons = defineProvider('jsons:', {\n transport: http,\n defaultOptions: {} as FetchOptions,\n prepare(ctx, options) {\n return prepareJsonRequest.call(this, ctx, 'https:', options)\n },\n})\n"],"mappings":"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"}
|