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 CHANGED
@@ -1,5 +1,4 @@
1
- import { a as SenderRegistry, c as DefineProviderContext, d as defineProvider, f as Transport, i as Sender, l as DefineProviderOptions, n as HttpPayload, o as SenderUrl, p as defineTransport, r as http, s as buildSenderRegistry, u as ServiceProvider } from "./core-C9zs8cU2.js";
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;
@@ -1 +1 @@
1
- {"version":3,"file":"browser.d.ts","names":[],"sources":["../src/browser.ts"],"mappings":";;;;cAUa,cAAA,EAAmF,cAAA;AAAA,iBAEhF,YAAA,CAAa,IAAA,EAAM,SAAA,KAAc,MAAA;AAAA,iBAI3B,IAAA,CACpB,GAAA,WAAc,GAAA,EACd,KAAA,UACA,IAAA,YACC,OAAA"}
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 { S as assert, _ as defineTransport, g as http, h as buildSenderRegistry, v as defineProvider } from "./core-C9zs8cU2.js";
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,
@@ -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'\n\nimport { assert } from '#/utils'\n\nexport const senderRegistry = buildSenderRegistry([bark, json, 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;CAAO;CAAO;CAAU;CAAQ,CAAC;AAEhG,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
+ {"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 SenderRegistry, c as DefineProviderContext, d as defineProvider, f as Transport, i as Sender, l as DefineProviderOptions, n as HttpPayload, o as SenderUrl, p as defineTransport, r as http, s as buildSenderRegistry, t as SmtpPayload, u as ServiceProvider } from "./core-C9zs8cU2.js";
2
- import { a as slack, i as telegram, n as jsons, o as discord, r as bark, t as json } from "./index-BX5WDWZH.js";
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;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/services/specialized/email/index.ts","../src/index.ts"],"mappings":";;;;;UAOiB,YAAA;EAEf,WAAA;EAEA,UAAA,GAAa,OAAA,CAAQ,qBAAA;AAAA;AAAA,cAWV,KAAA,EAAK,eAAA,WAAA,WAAA,EAAA,YAAA;;;cCXL,cAAA,EAA0F,cAAA;AAAA,iBAEvF,YAAA,CAAa,IAAA,EAAM,SAAA,KAAc,MAAA;AAAA,iBAI3B,IAAA,CACpB,GAAA,WAAc,GAAA,EACd,KAAA,UACA,IAAA,YACC,OAAA"}
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 { S as assert, _ as defineTransport, g as http, h as buildSenderRegistry, m as smtp, v as defineProvider } from "./core-C9zs8cU2.js";
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'\n\nimport { assert } from '#/utils'\n\nexport const senderRegistry = buildSenderRegistry([bark, email, json, 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, email, json, jsons, slack, telegram }\nexport * from './shared'\n"],"mappings":";;;;;AAeA,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;CAAO;CAAU;CAAQ,CAAC;AAEvG,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
+ {"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 { S as assert, b as withoutPathname, g as http, v as defineProvider, x as escapeMarkdown, y as getValidateQuery } from "./core-C9zs8cU2.js";
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(ctx, defaultProtocol, options) {
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
- export { slack as a, telegram as i, jsons as n, discord as o, bark as r, json as t };
253
- //# sourceMappingURL=json-DZ3LADFU.js.map
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.0",
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.1.0",
56
+ "@types/node": "^25.2.0",
57
57
  "@types/smtp-server": "^3.5.12",
58
- "@vitest/coverage-v8": "4.0.16",
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",
@@ -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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"}
@@ -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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"}