@suphark/notify 0.10.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +23 -0
- package/dist/{chunk-JN7P2CVF.js → chunk-SBQOHUW4.js} +423 -403
- package/dist/{chunk-NNMV7FZ3.js → chunk-WXINJXF4.js} +7 -1
- package/dist/index.d.ts +98 -57
- package/dist/index.js +54 -2
- package/dist/next.js +2 -2
- package/dist/{notify-D-PhiDzT.d.ts → notify-DA7BsQBD.d.ts} +27 -4
- package/dist/template.d.ts +6 -1
- package/dist/template.js +3 -1
- package/package.json +1 -1
|
@@ -158,6 +158,11 @@ function sampleData(variables) {
|
|
|
158
158
|
}
|
|
159
159
|
return out;
|
|
160
160
|
}
|
|
161
|
+
function htmlToText(html) {
|
|
162
|
+
return toPlainText(
|
|
163
|
+
html.replace(/<(head|style|script|title)\b[^>]*>[\s\S]*?<\/\1\s*>/gi, "").replace(/<\/(p|div|li|h[1-6]|tr|table|ul|ol)\s*>/gi, "$&\n")
|
|
164
|
+
).replace(/[ \t]+\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
165
|
+
}
|
|
161
166
|
function wrapEmailLayout(body, opts = {}) {
|
|
162
167
|
const footer = opts.appName ? `<p style="margin:24px 0 0;font-size:12px;color:#64748b">\u0E2A\u0E48\u0E07\u0E08\u0E32\u0E01 ${escapeHtml(opts.appName)}</p>` : "";
|
|
163
168
|
return `<!doctype html>
|
|
@@ -175,7 +180,7 @@ function renderEmailTemplate(t, data, opts = {}) {
|
|
|
175
180
|
const subject = renderTemplate(t.subject, data, { escape: false }).replace(/\s+/g, " ").trim();
|
|
176
181
|
const body = renderTemplate(t.html, data, { escape: true });
|
|
177
182
|
const html = /<html[\s>]/i.test(body) ? body : wrapEmailLayout(body, { ...opts, title: subject });
|
|
178
|
-
const text = t.text?.trim() ? renderTemplate(t.text, data, { escape: false }) :
|
|
183
|
+
const text = t.text?.trim() ? renderTemplate(t.text, data, { escape: false }) : htmlToText(body);
|
|
179
184
|
return { subject, html, text };
|
|
180
185
|
}
|
|
181
186
|
var BUILTIN_TEMPLATE_KEYS = [
|
|
@@ -275,6 +280,7 @@ export {
|
|
|
275
280
|
renderTemplate,
|
|
276
281
|
templateVariableNames,
|
|
277
282
|
sampleData,
|
|
283
|
+
htmlToText,
|
|
278
284
|
wrapEmailLayout,
|
|
279
285
|
renderEmailTemplate,
|
|
280
286
|
BUILTIN_TEMPLATE_KEYS,
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { P as ParsedAddress, A as Address, a as Provider, E as ErrorKind, Q as Quota, M as Message, S as SendResult,
|
|
2
|
-
export { k as Attachment,
|
|
1
|
+
import { P as ParsedAddress, A as Address, a as PushDevice, N as NotifyOptions, C as ChannelStatus, b as Provider, E as ErrorKind, Q as Quota, M as Message, S as SendResult, c as ProviderStatus, d as ProviderInfo, e as Store, f as MailerEvent, g as Attempt, h as NotifyResultItem, i as NotifyInput, j as NotifyTopicInput } from './notify-DA7BsQBD.js';
|
|
2
|
+
export { k as Attachment, l as NOTIFY_TIMEOUT_MS, m as NormalizedMessage, n as NotifyChannel, o as NotifyResult, p as PushSubscriptionJson, q as QuotaUsage, R as Recipient, r as RecipientChannelInfo, s as RecipientInfo, t as RequestStatus, u as SkipReason, v as absoluteLink, w as createLink, x as deletePushSubscription, y as getChannelStatus, z as getPushConfig, B as getRecipient, D as getRequestStatus, F as hasNotifyKey, G as listPushDevices, H as notify, I as notifyTopic, J as pauseChannel, K as savePushSubscription, L as toEmails } from './notify-DA7BsQBD.js';
|
|
3
3
|
import { TemplateVariable } from './template.js';
|
|
4
4
|
export { BUILTIN_TEMPLATE_KEYS, BuiltinTemplateKey, TemplateError, builtinFallback, isBuiltinTemplate, renderEmailTemplate } from './template.js';
|
|
5
5
|
|
|
@@ -13,6 +13,100 @@ declare function parseAddressList(input: Address | Address[] | undefined): Parse
|
|
|
13
13
|
/** { name, email } → "ชื่อ <a@b.com>" (สำหรับ API ที่รับ string) */
|
|
14
14
|
declare function formatAddress(a: ParsedAddress): string;
|
|
15
15
|
|
|
16
|
+
/** ผู้ใช้ที่ล็อกอินอยู่ในแอป — **ต้องมาจาก session ฝั่ง server เท่านั้น** ห้ามรับอีเมลจาก client */
|
|
17
|
+
interface PushUser {
|
|
18
|
+
email: string;
|
|
19
|
+
/** user id ใน Pi Auth (sub) — ให้ Pi Notify ลบ subscription ตามบัญชีที่ถูกลบ */
|
|
20
|
+
id?: string;
|
|
21
|
+
}
|
|
22
|
+
/** รูปที่ `PushSubscription.toJSON()` ของเบราว์เซอร์ส่งมา (field optional ตาม DOM type) */
|
|
23
|
+
interface BrowserPushSubscription {
|
|
24
|
+
endpoint?: string;
|
|
25
|
+
keys?: Record<string, string | undefined>;
|
|
26
|
+
}
|
|
27
|
+
interface PushHandlersOptions extends NotifyOptions {
|
|
28
|
+
/** ดึงผู้ใช้จาก session ของแอป — คืน null/undefined = ยังไม่ล็อกอิน */
|
|
29
|
+
getUser: () => PushUser | null | undefined | Promise<PushUser | null | undefined>;
|
|
30
|
+
}
|
|
31
|
+
interface PushHandlers {
|
|
32
|
+
/** VAPID public key สำหรับ `pushManager.subscribe({ applicationServerKey })` */
|
|
33
|
+
getPublicKey(): Promise<string>;
|
|
34
|
+
subscribe(subscription: BrowserPushSubscription, opts?: {
|
|
35
|
+
label?: string;
|
|
36
|
+
}): Promise<{
|
|
37
|
+
ok: true;
|
|
38
|
+
created: boolean;
|
|
39
|
+
}>;
|
|
40
|
+
unsubscribe(endpoint: string): Promise<{
|
|
41
|
+
ok: true;
|
|
42
|
+
deleted: number;
|
|
43
|
+
}>;
|
|
44
|
+
listDevices(): Promise<{
|
|
45
|
+
devices: PushDevice[];
|
|
46
|
+
}>;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* ชุดฟังก์ชันสำหรับ Server Actions ของ `<WebPushRow />` — แอปส่งแค่ `getUser`
|
|
50
|
+
* (ใน `"use server"` ห่อเป็น `export async function` ทีละตัว; ห้าม import SDK ใน Client Component)
|
|
51
|
+
*/
|
|
52
|
+
declare function createPushHandlers(options: PushHandlersOptions): PushHandlers;
|
|
53
|
+
interface PushServiceWorkerOptions {
|
|
54
|
+
/** ไอคอนของการแจ้งเตือน (path ในแอป) ค่าเริ่มต้น /icon-192.png */
|
|
55
|
+
icon?: string;
|
|
56
|
+
/** ลิงก์ที่เปิดเมื่อ payload ไม่มี link ค่าเริ่มต้น / */
|
|
57
|
+
defaultLink?: string;
|
|
58
|
+
}
|
|
59
|
+
/** ซอร์ส service worker ที่รับ push ของ Pi Notify (payload { title, body, link? }) — เปิดเฉพาะลิงก์ใน origin ของแอป */
|
|
60
|
+
declare function pushServiceWorkerSource(options?: PushServiceWorkerOptions): string;
|
|
61
|
+
/**
|
|
62
|
+
* Route Handler ที่เสิร์ฟ service worker จากตัวแพ็กเกจเอง (same-origin, ล็อกเวอร์ชันผ่าน npm)
|
|
63
|
+
* @example // app/sw.js/route.ts
|
|
64
|
+
* export const GET = pushServiceWorker();
|
|
65
|
+
* ไม่แนะนำให้ importScripts จากโดเมนอื่น: service worker คุมทั้ง origin ของแอปและดักทุก request
|
|
66
|
+
*/
|
|
67
|
+
declare function pushServiceWorker(options?: PushServiceWorkerOptions): () => Response;
|
|
68
|
+
|
|
69
|
+
/** ช่องทางแชทที่ผู้ใช้ผูกเองได้ */
|
|
70
|
+
type ChatLinkChannel = "telegram" | "line";
|
|
71
|
+
/** ลิงก์ผูกที่ส่งให้ UI (`ChatLinkRow` ของ @suphark/ui/pwa) */
|
|
72
|
+
interface ChatLink {
|
|
73
|
+
url: string;
|
|
74
|
+
code: string;
|
|
75
|
+
expiresAt: string;
|
|
76
|
+
/** ชื่อ bot/OA ให้ผู้ใช้ค้นเองเมื่อเปิดลิงก์ไม่ได้ (Telegram "@xxx_bot" · LINE "@xxx") */
|
|
77
|
+
botName?: string;
|
|
78
|
+
/** ข้อความที่ผู้ใช้พิมพ์เองได้ (Telegram `/start <code>` · LINE `ผูก Pi Notify <code>`) */
|
|
79
|
+
command: string;
|
|
80
|
+
}
|
|
81
|
+
interface ChatLinkHandlersOptions extends NotifyOptions {
|
|
82
|
+
/** ดึงผู้ใช้จาก session ของแอป (ฝั่ง server เท่านั้น) — คืน null/undefined = ยังไม่ล็อกอิน */
|
|
83
|
+
getUser: () => PushUser | null | undefined | Promise<PushUser | null | undefined>;
|
|
84
|
+
}
|
|
85
|
+
interface ChatLinkHandlers {
|
|
86
|
+
/** สถานะการผูกของผู้ใช้ที่ล็อกอินอยู่ — UI โพลทุก 3 วิหลังออกลิงก์ */
|
|
87
|
+
getStatus(channel: ChatLinkChannel): Promise<ChannelStatus>;
|
|
88
|
+
/** ออกลิงก์ผูก (หมดอายุ 10 นาที) */
|
|
89
|
+
createLink(channel: ChatLinkChannel): Promise<ChatLink>;
|
|
90
|
+
/**
|
|
91
|
+
* "ยกเลิกการผูก" = พักไว้ (ไม่ลบ) — การผูกใช้ร่วมทุกแอป จึงหยุดรับจากทุกแอป
|
|
92
|
+
* ผู้ใช้เปิดรับคืนได้ด้วยการกดผูกใหม่ หรือที่หน้า ช่องทางของฉัน ของ Pi Notify
|
|
93
|
+
*/
|
|
94
|
+
unlink(channel: ChatLinkChannel): Promise<{
|
|
95
|
+
paused: number;
|
|
96
|
+
}>;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* (0.11.0) ชุดฟังก์ชันสำหรับ Server Actions ของ `<ChatLinkRow />` (คู่ createPushHandlers) — แอปส่งแค่ `getUser`
|
|
100
|
+
* อีเมลมาจาก session ฝั่ง server เสมอ (ไม่รับจาก client) · ห่อเป็น `export async function` ทีละตัวในไฟล์ `"use server"`
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* const chat = createChatLinkHandlers({ getUser: async () => (await auth())?.user });
|
|
104
|
+
* export async function chatStatus(c: "telegram" | "line") { return chat.getStatus(c); }
|
|
105
|
+
* export async function chatCreateLink(c: "telegram" | "line") { return chat.createLink(c); }
|
|
106
|
+
* export async function chatUnlink(c: "telegram" | "line") { return chat.unlink(c); }
|
|
107
|
+
*/
|
|
108
|
+
declare function createChatLinkHandlers(options: ChatLinkHandlersOptions): ChatLinkHandlers;
|
|
109
|
+
|
|
16
110
|
interface ConsoleOptions {
|
|
17
111
|
name?: string;
|
|
18
112
|
from?: ParsedAddress;
|
|
@@ -330,59 +424,6 @@ declare function toPlainText(html: string): string;
|
|
|
330
424
|
/** เวลาพัก (วินาที) ต่อ error แต่ละแบบ ก่อนกลับมาลอง provider นั้นอีก — คูณสองทุกครั้งที่พังซ้ำ */
|
|
331
425
|
declare const DEFAULT_COOLDOWN: Record<ErrorKind, number>;
|
|
332
426
|
|
|
333
|
-
/** ผู้ใช้ที่ล็อกอินอยู่ในแอป — **ต้องมาจาก session ฝั่ง server เท่านั้น** ห้ามรับอีเมลจาก client */
|
|
334
|
-
interface PushUser {
|
|
335
|
-
email: string;
|
|
336
|
-
/** user id ใน Pi Auth (sub) — ให้ Pi Notify ลบ subscription ตามบัญชีที่ถูกลบ */
|
|
337
|
-
id?: string;
|
|
338
|
-
}
|
|
339
|
-
/** รูปที่ `PushSubscription.toJSON()` ของเบราว์เซอร์ส่งมา (field optional ตาม DOM type) */
|
|
340
|
-
interface BrowserPushSubscription {
|
|
341
|
-
endpoint?: string;
|
|
342
|
-
keys?: Record<string, string | undefined>;
|
|
343
|
-
}
|
|
344
|
-
interface PushHandlersOptions extends NotifyOptions {
|
|
345
|
-
/** ดึงผู้ใช้จาก session ของแอป — คืน null/undefined = ยังไม่ล็อกอิน */
|
|
346
|
-
getUser: () => PushUser | null | undefined | Promise<PushUser | null | undefined>;
|
|
347
|
-
}
|
|
348
|
-
interface PushHandlers {
|
|
349
|
-
/** VAPID public key สำหรับ `pushManager.subscribe({ applicationServerKey })` */
|
|
350
|
-
getPublicKey(): Promise<string>;
|
|
351
|
-
subscribe(subscription: BrowserPushSubscription, opts?: {
|
|
352
|
-
label?: string;
|
|
353
|
-
}): Promise<{
|
|
354
|
-
ok: true;
|
|
355
|
-
created: boolean;
|
|
356
|
-
}>;
|
|
357
|
-
unsubscribe(endpoint: string): Promise<{
|
|
358
|
-
ok: true;
|
|
359
|
-
deleted: number;
|
|
360
|
-
}>;
|
|
361
|
-
listDevices(): Promise<{
|
|
362
|
-
devices: PushDevice[];
|
|
363
|
-
}>;
|
|
364
|
-
}
|
|
365
|
-
/**
|
|
366
|
-
* ชุดฟังก์ชันสำหรับ Server Actions ของ `<WebPushRow />` — แอปส่งแค่ `getUser`
|
|
367
|
-
* (ใน `"use server"` ห่อเป็น `export async function` ทีละตัว; ห้าม import SDK ใน Client Component)
|
|
368
|
-
*/
|
|
369
|
-
declare function createPushHandlers(options: PushHandlersOptions): PushHandlers;
|
|
370
|
-
interface PushServiceWorkerOptions {
|
|
371
|
-
/** ไอคอนของการแจ้งเตือน (path ในแอป) ค่าเริ่มต้น /icon-192.png */
|
|
372
|
-
icon?: string;
|
|
373
|
-
/** ลิงก์ที่เปิดเมื่อ payload ไม่มี link ค่าเริ่มต้น / */
|
|
374
|
-
defaultLink?: string;
|
|
375
|
-
}
|
|
376
|
-
/** ซอร์ส service worker ที่รับ push ของ Pi Notify (payload { title, body, link? }) — เปิดเฉพาะลิงก์ใน origin ของแอป */
|
|
377
|
-
declare function pushServiceWorkerSource(options?: PushServiceWorkerOptions): string;
|
|
378
|
-
/**
|
|
379
|
-
* Route Handler ที่เสิร์ฟ service worker จากตัวแพ็กเกจเอง (same-origin, ล็อกเวอร์ชันผ่าน npm)
|
|
380
|
-
* @example // app/sw.js/route.ts
|
|
381
|
-
* export const GET = pushServiceWorker();
|
|
382
|
-
* ไม่แนะนำให้ importScripts จากโดเมนอื่น: service worker คุมทั้ง origin ของแอปและดักทุก request
|
|
383
|
-
*/
|
|
384
|
-
declare function pushServiceWorker(options?: PushServiceWorkerOptions): () => Response;
|
|
385
|
-
|
|
386
427
|
interface NotifyEmailInput {
|
|
387
428
|
title: string;
|
|
388
429
|
body: string;
|
|
@@ -517,5 +558,5 @@ declare function previewTemplate(key: string, input?: {
|
|
|
517
558
|
text: string;
|
|
518
559
|
}>;
|
|
519
560
|
|
|
520
|
-
export { Address, AllProvidersFailedError, Attempt, DEFAULT_COOLDOWN, DEFAULT_HUB_URL, ErrorKind, MailError, MailerEvent, Message, NotifyInput, NotifyOptions, NotifyResultItem, NotifyTopicInput, ParsedAddress, Provider, ProviderInfo, ProviderStatus, PushDevice, Quota, SMTP_PRESETS, SendResult, Store, TemplateVariable, classifyError, configureMailer, createConsoleProvider, createHubProvider, createMailer, createMemoryStore, createPresetSmtpProvider, createPushHandlers, createRedisStore, createResendProvider, createSmtpProvider, createZeptoMailProvider, deleteTemplate, formatAddress, getMailer, getTemplate, listProviders, listTemplates, looksLikeHtml, notifySafe, notifyTopicSafe, parseAddress, parseAddressList, previewTemplate, providersFromEnv, pushServiceWorker, pushServiceWorkerSource, renderNotifyEmail, requireFrom, resetMailer, resetSafeWarnings, resolveFormat, saveTemplate, sendMail, sendMailSafe, toPlainText };
|
|
521
|
-
export type { BodyFormat, BrowserPushSubscription, ConsoleOptions, EmailTemplateInfo, EmailTemplateInput, Env, HubErrorResponse, HubOptions, HubSendRequest, HubSendResponse, Mailer, MailerOptions, NotifyEmailInput, NotifySafeResult, ProviderConfig, PushHandlers, PushHandlersOptions, PushServiceWorkerOptions, PushUser, RedisLike, ResendOptions, SendMailSafeResult, SmtpOptions, SmtpPreset, ZeptoMailOptions };
|
|
561
|
+
export { Address, AllProvidersFailedError, Attempt, ChannelStatus, DEFAULT_COOLDOWN, DEFAULT_HUB_URL, ErrorKind, MailError, MailerEvent, Message, NotifyInput, NotifyOptions, NotifyResultItem, NotifyTopicInput, ParsedAddress, Provider, ProviderInfo, ProviderStatus, PushDevice, Quota, SMTP_PRESETS, SendResult, Store, TemplateVariable, classifyError, configureMailer, createChatLinkHandlers, createConsoleProvider, createHubProvider, createMailer, createMemoryStore, createPresetSmtpProvider, createPushHandlers, createRedisStore, createResendProvider, createSmtpProvider, createZeptoMailProvider, deleteTemplate, formatAddress, getMailer, getTemplate, listProviders, listTemplates, looksLikeHtml, notifySafe, notifyTopicSafe, parseAddress, parseAddressList, previewTemplate, providersFromEnv, pushServiceWorker, pushServiceWorkerSource, renderNotifyEmail, requireFrom, resetMailer, resetSafeWarnings, resolveFormat, saveTemplate, sendMail, sendMailSafe, toPlainText };
|
|
562
|
+
export type { BodyFormat, BrowserPushSubscription, ChatLink, ChatLinkChannel, ChatLinkHandlers, ChatLinkHandlersOptions, ConsoleOptions, EmailTemplateInfo, EmailTemplateInput, Env, HubErrorResponse, HubOptions, HubSendRequest, HubSendResponse, Mailer, MailerOptions, NotifyEmailInput, NotifySafeResult, ProviderConfig, PushHandlers, PushHandlersOptions, PushServiceWorkerOptions, PushUser, RedisLike, ResendOptions, SendMailSafeResult, SmtpOptions, SmtpPreset, ZeptoMailOptions };
|
package/dist/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
MailError,
|
|
6
6
|
NOTIFY_TIMEOUT_MS,
|
|
7
7
|
SMTP_PRESETS,
|
|
8
|
+
absoluteLink,
|
|
8
9
|
classifyError,
|
|
9
10
|
configureMailer,
|
|
10
11
|
createConsoleProvider,
|
|
@@ -33,6 +34,7 @@ import {
|
|
|
33
34
|
notifyTopicSafe,
|
|
34
35
|
parseAddress,
|
|
35
36
|
parseAddressList,
|
|
37
|
+
pauseChannel,
|
|
36
38
|
providersFromEnv,
|
|
37
39
|
requireFrom,
|
|
38
40
|
resetMailer,
|
|
@@ -41,7 +43,7 @@ import {
|
|
|
41
43
|
sendMail,
|
|
42
44
|
sendMailSafe,
|
|
43
45
|
toEmails
|
|
44
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-SBQOHUW4.js";
|
|
45
47
|
import {
|
|
46
48
|
BUILTIN_TEMPLATE_KEYS,
|
|
47
49
|
TemplateError,
|
|
@@ -51,7 +53,54 @@ import {
|
|
|
51
53
|
renderEmailTemplate,
|
|
52
54
|
resolveFormat,
|
|
53
55
|
toPlainText
|
|
54
|
-
} from "./chunk-
|
|
56
|
+
} from "./chunk-WXINJXF4.js";
|
|
57
|
+
|
|
58
|
+
// src/chat-link.ts
|
|
59
|
+
var COMMAND = {
|
|
60
|
+
telegram: (code) => `/start ${code}`,
|
|
61
|
+
line: (code) => `\u0E1C\u0E39\u0E01 Pi Notify ${code}`
|
|
62
|
+
};
|
|
63
|
+
function assertChannel(channel) {
|
|
64
|
+
if (channel !== "telegram" && channel !== "line")
|
|
65
|
+
throw new MailError("chat link: channel \u0E23\u0E2D\u0E07\u0E23\u0E31\u0E1A\u0E40\u0E09\u0E1E\u0E32\u0E30 telegram, line", {
|
|
66
|
+
kind: "invalid",
|
|
67
|
+
provider: "hub"
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
function createChatLinkHandlers(options) {
|
|
71
|
+
const { getUser, ...opts } = options;
|
|
72
|
+
const requireUser = async () => {
|
|
73
|
+
const user = await getUser();
|
|
74
|
+
if (!user?.email)
|
|
75
|
+
throw new MailError("chat link: \u0E22\u0E31\u0E07\u0E44\u0E21\u0E48\u0E44\u0E14\u0E49\u0E25\u0E47\u0E2D\u0E01\u0E2D\u0E34\u0E19", { kind: "auth", status: 401, provider: "hub" });
|
|
76
|
+
return user;
|
|
77
|
+
};
|
|
78
|
+
return {
|
|
79
|
+
async getStatus(channel) {
|
|
80
|
+
assertChannel(channel);
|
|
81
|
+
return getChannelStatus((await requireUser()).email, channel, opts);
|
|
82
|
+
},
|
|
83
|
+
async createLink(channel) {
|
|
84
|
+
assertChannel(channel);
|
|
85
|
+
const user = await requireUser();
|
|
86
|
+
const link = await createLink(user.email, channel, {
|
|
87
|
+
...opts,
|
|
88
|
+
...user.id ? { piUserId: user.id } : {}
|
|
89
|
+
});
|
|
90
|
+
return {
|
|
91
|
+
url: link.url,
|
|
92
|
+
code: link.code,
|
|
93
|
+
expiresAt: link.expiresAt,
|
|
94
|
+
...link.botName ? { botName: link.botName } : {},
|
|
95
|
+
command: COMMAND[channel](link.code)
|
|
96
|
+
};
|
|
97
|
+
},
|
|
98
|
+
async unlink(channel) {
|
|
99
|
+
assertChannel(channel);
|
|
100
|
+
return pauseChannel((await requireUser()).email, channel, opts);
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
55
104
|
|
|
56
105
|
// src/push.ts
|
|
57
106
|
function createPushHandlers(options) {
|
|
@@ -237,9 +286,11 @@ export {
|
|
|
237
286
|
NOTIFY_TIMEOUT_MS,
|
|
238
287
|
SMTP_PRESETS,
|
|
239
288
|
TemplateError,
|
|
289
|
+
absoluteLink,
|
|
240
290
|
builtinFallback,
|
|
241
291
|
classifyError,
|
|
242
292
|
configureMailer,
|
|
293
|
+
createChatLinkHandlers,
|
|
243
294
|
createConsoleProvider,
|
|
244
295
|
createHubProvider,
|
|
245
296
|
createLink,
|
|
@@ -272,6 +323,7 @@ export {
|
|
|
272
323
|
notifyTopicSafe,
|
|
273
324
|
parseAddress,
|
|
274
325
|
parseAddressList,
|
|
326
|
+
pauseChannel,
|
|
275
327
|
previewTemplate,
|
|
276
328
|
providersFromEnv,
|
|
277
329
|
pushServiceWorker,
|
package/dist/next.js
CHANGED
|
@@ -315,6 +315,11 @@ interface NotifyOptions {
|
|
|
315
315
|
* ค่าเริ่มต้น notify() 65000 (ยาวกว่า maxDuration 60 วิของ /api/v1/notify เล็กน้อย) · getRecipient()/createLink() 10000
|
|
316
316
|
*/
|
|
317
317
|
timeoutMs?: number;
|
|
318
|
+
/**
|
|
319
|
+
* (0.11.0) โดเมนของแอป ไว้เติมหน้าลิงก์แบบ relative ("/user/account") ใน notify/notifyTopic
|
|
320
|
+
* ค่าเริ่มต้น APP_URL หรือ NEXT_PUBLIC_APP_URL
|
|
321
|
+
*/
|
|
322
|
+
appUrl?: string;
|
|
318
323
|
}
|
|
319
324
|
/** เวลารอเริ่มต้นของแต่ละคำสั่ง (ms) */
|
|
320
325
|
declare const NOTIFY_TIMEOUT_MS: {
|
|
@@ -352,6 +357,11 @@ interface RecipientInfo {
|
|
|
352
357
|
}
|
|
353
358
|
/** มี PI_NOTIFY_KEY (ใน opts หรือ env) หรือไม่ — ให้ helper แบบ safe/later ใช้ตัดสินว่า "ปิดอยู่" */
|
|
354
359
|
declare function hasNotifyKey(opts?: NotifyOptions): boolean;
|
|
360
|
+
/**
|
|
361
|
+
* (0.11.0) ลิงก์ relative ("/memo/12") → URL เต็มจาก opts.appUrl / APP_URL / NEXT_PUBLIC_APP_URL
|
|
362
|
+
* (hub ต้องการ URL เต็ม เพราะลิงก์ถูกเปิดจาก Telegram/LINE/อีเมล ไม่ใช่จากในแอป) — ไม่มีโดเมน = MailError invalid
|
|
363
|
+
*/
|
|
364
|
+
declare function absoluteLink(link: string, opts?: NotifyOptions): string;
|
|
355
365
|
/**
|
|
356
366
|
* แจ้งเตือนผู้รับผ่าน Pi Notify hub — แชทที่ผู้รับผูกไว้ (Telegram / LINE / web push) หรืออีเมล
|
|
357
367
|
* ใช้ env เดียวกับ sendMail(): PI_NOTIFY_KEY (+ PI_NOTIFY_URL)
|
|
@@ -370,8 +380,11 @@ interface RequestStatus {
|
|
|
370
380
|
key: string;
|
|
371
381
|
/** mail = sendMail, notify = notify()/notifyTopic() */
|
|
372
382
|
type: "mail" | "notify";
|
|
373
|
-
/**
|
|
374
|
-
|
|
383
|
+
/**
|
|
384
|
+
* processing = ยังตอบคำขอแรกไม่เสร็จ · queued = ยังมีรายการรอส่งซ้ำ · partial = สำเร็จบางรายการ
|
|
385
|
+
* · skipped (0.10.2) = ไม่มีรายการไหนถูกส่ง (topic ไม่มีปลายทาง / ผู้รับไม่ได้ผูกช่องทาง)
|
|
386
|
+
*/
|
|
387
|
+
status: "processing" | "queued" | "sent" | "failed" | "partial" | "skipped";
|
|
375
388
|
/** รายการต่อผู้รับ/ช่องทาง — รายการที่เคย queued แสดงสถานะล่าสุดจริง (sent/failed/queued) */
|
|
376
389
|
results: NotifyResultItem[];
|
|
377
390
|
summary: {
|
|
@@ -407,10 +420,20 @@ declare function createLink(email: Recipient, channel?: Exclude<NotifyChannel, "
|
|
|
407
420
|
url: string;
|
|
408
421
|
code: string;
|
|
409
422
|
expiresAt: string;
|
|
423
|
+
botName?: string;
|
|
424
|
+
}>;
|
|
425
|
+
/**
|
|
426
|
+
* (0.11.0) "ยกเลิกการผูก" จากหน้าตั้งค่าของแอป = พักไว้ (ไม่ลบ) — การผูก Telegram/LINE ใช้ร่วมทุกแอป
|
|
427
|
+
* จึงหยุดรับจากทุกแอป ผู้ใช้เปิดรับคืนได้ที่หน้า ช่องทางของฉัน หรือกดผูกใหม่ · คืนจำนวนที่พัก
|
|
428
|
+
*/
|
|
429
|
+
declare function pauseChannel(email: Recipient, channel: Exclude<NotifyChannel, "email" | "push">, opts?: NotifyOptions): Promise<{
|
|
430
|
+
paused: number;
|
|
410
431
|
}>;
|
|
411
432
|
/** สถานะการผูกช่องทางหนึ่งของผู้รับ — แทนการ find ใน `getRecipient().channels` เองในแต่ละแอป */
|
|
412
433
|
interface ChannelStatus {
|
|
413
434
|
linked: boolean;
|
|
435
|
+
/** (0.11.0) ผูกไว้แต่พักอยู่ (ผู้ใช้กดยกเลิก/พักไว้) — กดผูกใหม่ = เปิดรับคืน */
|
|
436
|
+
paused?: boolean;
|
|
414
437
|
label: string | null;
|
|
415
438
|
linkedAt: string | null;
|
|
416
439
|
/** หน้า Pi Notify ที่ผู้รับจัดการช่องทางเอง */
|
|
@@ -446,5 +469,5 @@ declare function listPushDevices(email: string, opts?: NotifyOptions): Promise<{
|
|
|
446
469
|
devices: PushDevice[];
|
|
447
470
|
}>;
|
|
448
471
|
|
|
449
|
-
export {
|
|
450
|
-
export type { Address as A, ChannelStatus as C, ErrorKind as E, Message as M, NotifyOptions as N, ParsedAddress as P, Quota as Q, Recipient as R, SendResult as S,
|
|
472
|
+
export { getRecipient as B, getRequestStatus as D, hasNotifyKey as F, listPushDevices as G, notify as H, notifyTopic as I, pauseChannel as J, savePushSubscription as K, toEmails as L, NOTIFY_TIMEOUT_MS as l, absoluteLink as v, createLink as w, deletePushSubscription as x, getChannelStatus as y, getPushConfig as z };
|
|
473
|
+
export type { Address as A, ChannelStatus as C, ErrorKind as E, Message as M, NotifyOptions as N, ParsedAddress as P, Quota as Q, Recipient as R, SendResult as S, PushDevice as a, Provider as b, ProviderStatus as c, ProviderInfo as d, Store as e, MailerEvent as f, Attempt as g, NotifyResultItem as h, NotifyInput as i, NotifyTopicInput as j, Attachment as k, NormalizedMessage as m, NotifyChannel as n, NotifyResult as o, PushSubscriptionJson as p, QuotaUsage as q, RecipientChannelInfo as r, RecipientInfo as s, RequestStatus as t, SkipReason as u };
|
package/dist/template.d.ts
CHANGED
|
@@ -58,6 +58,11 @@ declare function renderTemplate(source: string, data: Data, opts: {
|
|
|
58
58
|
declare function templateVariableNames(...sources: string[]): string[];
|
|
59
59
|
/** ค่าตัวอย่างจากรายการตัวแปร (path a.b → ซ้อน object) */
|
|
60
60
|
declare function sampleData(variables: TemplateVariable[] | null | undefined): Data;
|
|
61
|
+
/**
|
|
62
|
+
* ข้อความล้วนจาก HTML ที่ render แล้ว — ตัด <head>/<style>/<script>/<title> ทั้งก้อนก่อน (เทมเพลต HTML เต็มฉบับ
|
|
63
|
+
* ไม่ให้ CSS หลุดเข้า text part) และขึ้นบรรทัดใหม่ตามบล็อก (p, div, li, h1–h6, tr) ให้อ่านได้
|
|
64
|
+
*/
|
|
65
|
+
declare function htmlToText(html: string): string;
|
|
61
66
|
/** layout มาตรฐานเมื่อ HTML ไม่มี <html> ของตัวเอง — กว้าง 600px อ่านง่ายทุกโปรแกรมอีเมล */
|
|
62
67
|
declare function wrapEmailLayout(body: string, opts?: {
|
|
63
68
|
appName?: string;
|
|
@@ -92,5 +97,5 @@ declare function builtinFallback(key: string, data: Record<string, unknown> | un
|
|
|
92
97
|
html: string;
|
|
93
98
|
} | null;
|
|
94
99
|
|
|
95
|
-
export { BUILTIN_TEMPLATES, BUILTIN_TEMPLATE_KEYS, TemplateError, builtinFallback, isBuiltinTemplate, parseTemplate, renderEmailTemplate, renderTemplate, sampleData, templateVariableNames, wrapEmailLayout };
|
|
100
|
+
export { BUILTIN_TEMPLATES, BUILTIN_TEMPLATE_KEYS, TemplateError, builtinFallback, htmlToText, isBuiltinTemplate, parseTemplate, renderEmailTemplate, renderTemplate, sampleData, templateVariableNames, wrapEmailLayout };
|
|
96
101
|
export type { BuiltinTemplateKey, EmailTemplateSource, TemplateVariable };
|
package/dist/template.js
CHANGED
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
BUILTIN_TEMPLATE_KEYS,
|
|
4
4
|
TemplateError,
|
|
5
5
|
builtinFallback,
|
|
6
|
+
htmlToText,
|
|
6
7
|
isBuiltinTemplate,
|
|
7
8
|
parseTemplate,
|
|
8
9
|
renderEmailTemplate,
|
|
@@ -10,12 +11,13 @@ import {
|
|
|
10
11
|
sampleData,
|
|
11
12
|
templateVariableNames,
|
|
12
13
|
wrapEmailLayout
|
|
13
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-WXINJXF4.js";
|
|
14
15
|
export {
|
|
15
16
|
BUILTIN_TEMPLATES,
|
|
16
17
|
BUILTIN_TEMPLATE_KEYS,
|
|
17
18
|
TemplateError,
|
|
18
19
|
builtinFallback,
|
|
20
|
+
htmlToText,
|
|
19
21
|
isBuiltinTemplate,
|
|
20
22
|
parseTemplate,
|
|
21
23
|
renderEmailTemplate,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@suphark/notify",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "ส่งอีเมล + แจ้งเตือน Telegram ผ่าน Pi Notify hub (notify.suphark.com) หรือส่งอีเมลตรงไป Resend/SMTP/Zoho/ZeptoMail ใน API เดียว พร้อม failover อัตโนมัติ",
|