@visulima/notification 0.0.1 → 1.0.0-alpha.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.
Files changed (149) hide show
  1. package/CHANGELOG.md +35 -0
  2. package/LICENSE.md +874 -0
  3. package/README.md +313 -6
  4. package/dist/channels/email/index.d.ts +46 -0
  5. package/dist/channels/email/index.js +1 -0
  6. package/dist/channels/inapp/index.d.ts +99 -0
  7. package/dist/channels/inapp/index.js +1 -0
  8. package/dist/digest/index.d.ts +128 -0
  9. package/dist/digest/index.js +1 -0
  10. package/dist/events/index.d.ts +37 -0
  11. package/dist/events/index.js +1 -0
  12. package/dist/i18n/index.d.ts +42 -0
  13. package/dist/i18n/index.js +1 -0
  14. package/dist/index.d.ts +174 -0
  15. package/dist/index.js +1 -0
  16. package/dist/layouts/index.d.ts +45 -0
  17. package/dist/layouts/index.js +1 -0
  18. package/dist/middleware/index.d.ts +382 -0
  19. package/dist/middleware/index.js +1 -0
  20. package/dist/packem_shared/MemoryDigestStore-Bw-sE5MI.js +1 -0
  21. package/dist/packem_shared/MemoryEventStore-BGD_xRxu.js +1 -0
  22. package/dist/packem_shared/MemoryInAppStore-48qlrDCx.js +1 -0
  23. package/dist/packem_shared/MemoryQueue-CXgWoZoY.js +1 -0
  24. package/dist/packem_shared/Notification-B22tuJPy.js +1 -0
  25. package/dist/packem_shared/NotificationError-DVfMJQ1u.js +1 -0
  26. package/dist/packem_shared/NotificationMessageBuilder-Br_aZusY.js +1 -0
  27. package/dist/packem_shared/RequiredOptionError-CuL42XRq.js +1 -0
  28. package/dist/packem_shared/UnstorageDigestStore-QAcO3Vb_.js +1 -0
  29. package/dist/packem_shared/UnstorageInAppStore-Bq2LoDMO.js +1 -0
  30. package/dist/packem_shared/apnsProvider-C9WSv5sc.js +1 -0
  31. package/dist/packem_shared/circuitBreakerMiddleware-BlZN7SVT.js +1 -0
  32. package/dist/packem_shared/composeMiddleware-D6dR8DUS.js +1 -0
  33. package/dist/packem_shared/createDigester-vMNPejGF.js +1 -0
  34. package/dist/packem_shared/createNotificationWorkflow-B70OgeED.js +1 -0
  35. package/dist/packem_shared/createQueueWorker-DjQBxjXc.js +1 -0
  36. package/dist/packem_shared/createTranslator-CY91C2eS.js +1 -0
  37. package/dist/packem_shared/credentials-CG0zkn-W.js +1 -0
  38. package/dist/packem_shared/dedupeMiddleware-CQmPJd_h.js +1 -0
  39. package/dist/packem_shared/defineLayout-73TNxYPq.js +1 -0
  40. package/dist/packem_shared/defineProvider-C9q-7iwt.js +1 -0
  41. package/dist/packem_shared/discordProvider-ewPfe-J7.js +1 -0
  42. package/dist/packem_shared/emailChannel-CNDlX96Q.js +1 -0
  43. package/dist/packem_shared/expoProvider-CXq101FD.js +1 -0
  44. package/dist/packem_shared/failoverProvider-D1dAmW8U.js +1 -0
  45. package/dist/packem_shared/fcmProvider-WdJGZ55l.js +1 -0
  46. package/dist/packem_shared/getHeader-C_gkdnMQ.js +1 -0
  47. package/dist/packem_shared/hmacBase64-BhhoX0uo.js +1 -0
  48. package/dist/packem_shared/http-BMYcUNBU.js +1 -0
  49. package/dist/packem_shared/id-C_FRCsUM.js +1 -0
  50. package/dist/packem_shared/inAppProvider-ElbahgSj.js +1 -0
  51. package/dist/packem_shared/loggingMiddleware-Cs6EDLcL.js +1 -0
  52. package/dist/packem_shared/messageBirdProvider-CHUFB0hd.js +1 -0
  53. package/dist/packem_shared/mockProvider-BLwTZlkw.js +1 -0
  54. package/dist/packem_shared/msTeamsProvider-DBhrmuSd.js +1 -0
  55. package/dist/packem_shared/notification.d-DFCVTods.d.ts +104 -0
  56. package/dist/packem_shared/otelProvider-b6LVo0BS.js +1 -0
  57. package/dist/packem_shared/plivoProvider-CIOl6DWw.js +1 -0
  58. package/dist/packem_shared/provider.d-BQAGriz6.d.ts +33 -0
  59. package/dist/packem_shared/rateLimitMiddleware-DWmEYq-m.js +1 -0
  60. package/dist/packem_shared/retryMiddleware-uUJDcUoP.js +1 -0
  61. package/dist/packem_shared/roundRobinProvider-BetXJUUm.js +1 -0
  62. package/dist/packem_shared/slackProvider-N1wNtAZ3.js +1 -0
  63. package/dist/packem_shared/slackWebhook-GEx_GdcV.js +1 -0
  64. package/dist/packem_shared/sms-CU-OZvNU.js +1 -0
  65. package/dist/packem_shared/snsProvider-KCciJ-nj.js +4 -0
  66. package/dist/packem_shared/snsWebhook-ChZnBBT3.js +1 -0
  67. package/dist/packem_shared/standardWebhook-B-LxP8U7.js +1 -0
  68. package/dist/packem_shared/suppressionMiddleware-CY-Qo1A_.js +1 -0
  69. package/dist/packem_shared/telegramProvider-jqR5BhJL.js +1 -0
  70. package/dist/packem_shared/telemetryMiddleware-B1N4k171.js +1 -0
  71. package/dist/packem_shared/telnyxProvider-C8TMPir1.js +1 -0
  72. package/dist/packem_shared/tracer.d-Co1s_NwG.d.ts +494 -0
  73. package/dist/packem_shared/twilioProvider-BxI0e6LX.js +1 -0
  74. package/dist/packem_shared/twilioWebhook-F0mTmGXD.js +1 -0
  75. package/dist/packem_shared/types.d-67TogK4k.d.ts +33 -0
  76. package/dist/packem_shared/types.d-C1GoEAlI.d-Bv3grfyD.d.ts +83 -0
  77. package/dist/packem_shared/types.d-CximoA8M.d.ts +29 -0
  78. package/dist/packem_shared/types.d-GUzX1jTk.d.ts +235 -0
  79. package/dist/packem_shared/types.d-td-F2Oh0.d.ts +10 -0
  80. package/dist/packem_shared/unstorage.DqlWKU2I.d-CogP3Etw.d.ts +120 -0
  81. package/dist/packem_shared/vonageProvider-BF76ca89.js +1 -0
  82. package/dist/packem_shared/webPushProvider-B962RwsA.js +1 -0
  83. package/dist/packem_shared/webcrypto-bY7wJCB5.js +1 -0
  84. package/dist/packem_shared/webhookProvider-BALSb2pc.js +1 -0
  85. package/dist/preferences/index.d.ts +49 -0
  86. package/dist/preferences/index.js +1 -0
  87. package/dist/providers/chat/discord/index.d.ts +14 -0
  88. package/dist/providers/chat/discord/index.js +1 -0
  89. package/dist/providers/chat/msteams/index.d.ts +14 -0
  90. package/dist/providers/chat/msteams/index.js +1 -0
  91. package/dist/providers/chat/slack/index.d.ts +19 -0
  92. package/dist/providers/chat/slack/index.js +1 -0
  93. package/dist/providers/chat/telegram/index.d.ts +18 -0
  94. package/dist/providers/chat/telegram/index.js +1 -0
  95. package/dist/providers/failover/index.d.ts +16 -0
  96. package/dist/providers/failover/index.js +1 -0
  97. package/dist/providers/mock/index.d.ts +29 -0
  98. package/dist/providers/mock/index.js +1 -0
  99. package/dist/providers/opentelemetry/index.d.ts +21 -0
  100. package/dist/providers/opentelemetry/index.js +1 -0
  101. package/dist/providers/push/apns/index.d.ts +24 -0
  102. package/dist/providers/push/apns/index.js +1 -0
  103. package/dist/providers/push/expo/index.d.ts +14 -0
  104. package/dist/providers/push/expo/index.js +1 -0
  105. package/dist/providers/push/fcm/index.d.ts +26 -0
  106. package/dist/providers/push/fcm/index.js +1 -0
  107. package/dist/providers/push/web-push/index.d.ts +36 -0
  108. package/dist/providers/push/web-push/index.js +1 -0
  109. package/dist/providers/roundrobin/index.d.ts +17 -0
  110. package/dist/providers/roundrobin/index.js +1 -0
  111. package/dist/providers/sms/messagebird/index.d.ts +16 -0
  112. package/dist/providers/sms/messagebird/index.js +1 -0
  113. package/dist/providers/sms/plivo/index.d.ts +18 -0
  114. package/dist/providers/sms/plivo/index.js +1 -0
  115. package/dist/providers/sms/sns/index.d.ts +21 -0
  116. package/dist/providers/sms/sns/index.js +1 -0
  117. package/dist/providers/sms/telnyx/index.d.ts +18 -0
  118. package/dist/providers/sms/telnyx/index.js +1 -0
  119. package/dist/providers/sms/twilio/index.d.ts +20 -0
  120. package/dist/providers/sms/twilio/index.js +1 -0
  121. package/dist/providers/sms/vonage/index.d.ts +18 -0
  122. package/dist/providers/sms/vonage/index.js +1 -0
  123. package/dist/providers/webhook/index.d.ts +18 -0
  124. package/dist/providers/webhook/index.js +1 -0
  125. package/dist/queue/bullmq-queue.d.ts +58 -0
  126. package/dist/queue/bullmq-queue.js +1 -0
  127. package/dist/queue/index.d.ts +50 -0
  128. package/dist/queue/index.js +1 -0
  129. package/dist/queue/pg-boss-queue.d.ts +66 -0
  130. package/dist/queue/pg-boss-queue.js +1 -0
  131. package/dist/queue/sqs-queue.d.ts +91 -0
  132. package/dist/queue/sqs-queue.js +1 -0
  133. package/dist/queue/unstorage-queue.d.ts +30 -0
  134. package/dist/queue/unstorage-queue.js +1 -0
  135. package/dist/routing/index.d.ts +35 -0
  136. package/dist/routing/index.js +1 -0
  137. package/dist/template-engines/handlebars.d.ts +16 -0
  138. package/dist/template-engines/handlebars.js +1 -0
  139. package/dist/template-engines/liquid.d.ts +16 -0
  140. package/dist/template-engines/liquid.js +1 -0
  141. package/dist/template-engines/string.d.ts +20 -0
  142. package/dist/template-engines/string.js +1 -0
  143. package/dist/utils/result.d.ts +54 -0
  144. package/dist/utils/result.js +1 -0
  145. package/dist/webhooks/index.d.ts +110 -0
  146. package/dist/webhooks/index.js +1 -0
  147. package/dist/workflow/index.d.ts +83 -0
  148. package/dist/workflow/index.js +1 -0
  149. package/package.json +283 -43
@@ -0,0 +1,16 @@
1
+ import { T as TemplateRenderer } from "../packem_shared/types.d-td-F2Oh0.js";
2
+ /**
3
+ * Renders a [LiquidJS](https://liquidjs.com/) template to a string.
4
+ *
5
+ * `liquidjs` is an optional peer, loaded lazily so a missing install surfaces here as
6
+ * a {@link NotificationError} rather than at import time. Pure JS — edge-safe and
7
+ * runnable on Cloudflare Workers.
8
+ * @param template The Liquid template string.
9
+ * @param data The data/variables exposed to the template.
10
+ * @param options LiquidJS engine options (passed to the `Liquid` constructor).
11
+ * @returns The rendered output.
12
+ * @throws {TypeError} When the template is not a string.
13
+ * @throws {NotificationError} When `liquidjs` is not installed or rendering fails.
14
+ */
15
+ declare const renderLiquid: TemplateRenderer;
16
+ export { renderLiquid as default, renderLiquid };
@@ -0,0 +1 @@
1
+ import r from"../packem_shared/NotificationError-DVfMJQ1u.js";const s=async(t,a,d)=>{if(typeof t!="string")throw new TypeError("Liquid template must be a string");let i;try{i=await import("liquidjs")}catch(e){throw new r("liquid","liquidjs is not installed. Please install it: pnpm add liquidjs",{cause:e})}try{return await new i.Liquid(d??{}).parseAndRender(t,a??{})}catch(e){throw new r("liquid",`Failed to render Liquid template: ${e.message}`,{cause:e})}};export{s as default,s as renderLiquid};
@@ -0,0 +1,20 @@
1
+ import { T as TemplateRenderer } from "../packem_shared/types.d-td-F2Oh0.js";
2
+ /**
3
+ * Zero-dependency `{{var}}` interpolation renderer. Edge-safe and peer-free.
4
+ *
5
+ * Replaces `{{ key }}` / `{{ a.b.c }}` placeholders with the matching value from
6
+ * `data`. Unmatched placeholders render as an empty string. Whitespace inside the
7
+ * braces is ignored. This is intentionally minimal — for conditionals/loops use the
8
+ * Handlebars or Liquid renderers.
9
+ * @param template The template string containing `{{var}}` placeholders.
10
+ * @param data The data/variables to interpolate.
11
+ * @returns The rendered string.
12
+ * @throws {TypeError} When the template is not a string.
13
+ * @example
14
+ * ```ts
15
+ * renderString("Hi {{ user.name }}, code {{code}}", { code: "123", user: { name: "Ada" } });
16
+ * // => "Hi Ada, code 123"
17
+ * ```
18
+ */
19
+ declare const renderString: TemplateRenderer;
20
+ export { renderString as default, renderString };
@@ -0,0 +1 @@
1
+ const i=(n,r)=>{const o=r.split(".");let e=n;for(const s of o){if(e===null||typeof e!="object")return;e=e[s]}return e},f=(n,r)=>{if(typeof n!="string")throw new TypeError("String template must be a string");const o=r??{};return n.replaceAll(/\{\{\s*([\w.]+)\s*\}\}/g,(e,s)=>{const t=i(o,s);return t==null?"":typeof t=="string"?t:typeof t=="number"||typeof t=="boolean"||typeof t=="bigint"?String(t):JSON.stringify(t)})};export{f as default,f as renderString};
@@ -0,0 +1,54 @@
1
+ import { R as Result } from "../packem_shared/types.d-GUzX1jTk.js";
2
+ /**
3
+ * A successful {@link Result} with its data narrowed to be present.
4
+ */
5
+ type OkResult<T> = Result<T> & {
6
+ data: T;
7
+ success: true;
8
+ };
9
+ /**
10
+ * A failed {@link Result}, narrowed to the failure case.
11
+ */
12
+ type FailResult<T> = Result<T> & {
13
+ success: false;
14
+ };
15
+ /**
16
+ * Returns whether a {@link Result} succeeded, narrowing `data` to be present.
17
+ * @param result The result to test.
18
+ * @returns `true` when the result is successful.
19
+ */
20
+ declare const isOk: <T>(result: Result<T>) => result is OkResult<T>;
21
+ /**
22
+ * Returns whether a {@link Result} failed.
23
+ * @param result The result to test.
24
+ * @returns `true` when the result is a failure.
25
+ */
26
+ declare const isErr: <T>(result: Result<T>) => result is FailResult<T>;
27
+ /**
28
+ * Returns the data of a successful {@link Result}, or throws its error.
29
+ * @param result The result to unwrap.
30
+ * @returns The contained data.
31
+ * @throws {NotificationError} The result's error (wrapped when it is not already an `Error`).
32
+ */
33
+ declare const unwrap: <T>(result: Result<T>) => T;
34
+ /**
35
+ * Returns the data of a successful {@link Result}, or a fallback when it failed.
36
+ * @param result The result to unwrap.
37
+ * @param fallback The value to return on failure.
38
+ * @returns The data, or the fallback.
39
+ */
40
+ declare const unwrapOr: <T>(result: Result<T>, fallback: T) => T;
41
+ /**
42
+ * Maps the data of a successful {@link Result}, passing failures through unchanged.
43
+ * @param result The result to map.
44
+ * @param function_ The mapper applied to the data on success.
45
+ * @returns A new result with the mapped data, or the original failure.
46
+ */
47
+ declare const mapOk: <T, U>(result: Result<T>, function_: (data: T) => U) => Result<U>;
48
+ /**
49
+ * Runs an async function and captures its outcome as a {@link Result}, never throwing.
50
+ * @param function_ The async function to run.
51
+ * @returns A successful result with the value, or a failed result with the thrown error.
52
+ */
53
+ declare const tryAsync: <T>(function_: () => Promise<T>) => Promise<Result<T>>;
54
+ export { FailResult, OkResult, isErr, isOk, mapOk, tryAsync, unwrap, unwrapOr };
@@ -0,0 +1 @@
1
+ import e from"../packem_shared/NotificationError-DVfMJQ1u.js";const c=r=>r.success,t=r=>!r.success,u=r=>{if(r.success)return r.data;throw r.error instanceof Error?r.error:new e("result","Called unwrap() on a failed result",{cause:r.error})},o=(r,s)=>r.success?r.data:s,n=(r,s)=>r.success?{data:s(r.data),success:!0}:{error:r.error,success:!1},d=async r=>{try{return{data:await r(),success:!0}}catch(s){return{error:s,success:!1}}};export{t as isErr,c as isOk,n as mapOk,d as tryAsync,u as unwrap,o as unwrapOr};
@@ -0,0 +1,110 @@
1
+ import { N as NotificationEvent } from "../packem_shared/types.d-GUzX1jTk.js";
2
+ /**
3
+ * Computes an HMAC over `message` and returns the lowercase hex digest.
4
+ * @param key The shared secret (UTF-8 string) or raw key bytes.
5
+ * @param message The message to sign.
6
+ * @param hash The hash algorithm (`"SHA-1"` or `"SHA-256"`).
7
+ * @returns The hex-encoded HMAC.
8
+ */
9
+ declare const hmacHex: (key: string | Uint8Array, message: string, hash: "SHA-1" | "SHA-256") => Promise<string>;
10
+ /**
11
+ * Computes an HMAC over `message` and returns the base64 digest.
12
+ * @param key The shared secret (UTF-8 string) or raw key bytes.
13
+ * @param message The message to sign.
14
+ * @param hash The hash algorithm (`"SHA-1"` or `"SHA-256"`).
15
+ * @returns The base64-encoded HMAC.
16
+ */
17
+ declare const hmacBase64: (key: string | Uint8Array, message: string, hash: "SHA-1" | "SHA-256") => Promise<string>;
18
+ /**
19
+ * Constant-time string comparison to avoid leaking match position via timing.
20
+ *
21
+ * Both inputs are compared in full; the function returns early only on length
22
+ * mismatch (which is not secret).
23
+ * @param a The first string.
24
+ * @param b The second string.
25
+ * @returns `true` when the strings are equal.
26
+ */
27
+ declare const timingSafeEqual: (a: string, b: string) => boolean;
28
+ /**
29
+ * Case-insensitive map of inbound request headers. Values may be a single string or
30
+ * an array (mirroring `node:http` and `Headers`); verifiers normalise both forms.
31
+ */
32
+ type WebhookHeaders = Record<string, string | string[] | undefined>;
33
+ /**
34
+ * A provider inbound-webhook verifier: validates the request signature and normalises
35
+ * the body into a {@link NotificationEvent}.
36
+ */
37
+ interface WebhookVerifier {
38
+ /**
39
+ * Normalises a verified webhook body into a {@link NotificationEvent}.
40
+ * @param body The raw request body (string).
41
+ * @returns The normalised event, or `undefined` when the body is not a delivery event.
42
+ */
43
+ parse: (body: string) => NotificationEvent | undefined;
44
+ /**
45
+ * Verifies the request signature against the shared secret.
46
+ * @param payload The raw request body (string).
47
+ * @param headers The inbound request headers.
48
+ * @param secret The provider signing secret / auth token.
49
+ * @returns `true` when the signature is valid.
50
+ */
51
+ verify: (payload: string, headers: WebhookHeaders, secret: string) => Promise<boolean>;
52
+ }
53
+ /**
54
+ * Reads a header value case-insensitively, coercing array values to their first entry.
55
+ * @param headers The inbound headers.
56
+ * @param name The header name to read.
57
+ * @returns The header value, or `undefined` when absent.
58
+ */
59
+ declare const getHeader: (headers: WebhookHeaders, name: string) => string | undefined;
60
+ /**
61
+ * Verifier + parser for Slack event/interaction webhooks.
62
+ *
63
+ * Verification follows Slack's v0 signing scheme: the signature is
64
+ * `v0=` + hex HMAC-SHA256 (keyed by the signing secret) of `v0:{timestamp}:{body}`.
65
+ * The request timestamp is checked against a 5-minute replay window. Edge-safe — uses
66
+ * Web Crypto only.
67
+ */
68
+ declare const slackWebhook: WebhookVerifier;
69
+ /**
70
+ * Verifier + parser for AWS SNS HTTP/S subscription deliveries.
71
+ *
72
+ * NOTE: signature verification is NOT yet implemented. Real verification requires
73
+ * fetching the X.509 certificate at `SigningCertURL`, validating its cert chain back to
74
+ * an Amazon root, and checking the RSA-SHA1/RSA-SHA256 signature over the canonical
75
+ * string-to-sign (SignatureVersion 1 and 2). Until that lands, {@link snsWebhook.verify}
76
+ * fails closed and always returns `false` — accepting a payload purely on its structure
77
+ * (a `Signature` field plus an `sns.*.amazonaws.com` `SigningCertURL`) is an auth bypass,
78
+ * since both are attacker-controllable. `parse` remains available for callers that have
79
+ * verified the message out-of-band. Callers handling `SubscriptionConfirmation` should
80
+ * confirm the subscription by requesting the `SubscribeURL` from the parsed metadata.
81
+ * Edge-safe — performs no `node:*` work.
82
+ *
83
+ * TODO: implement RSA-SHA1/RSA-SHA256 verification of the canonical string-to-sign
84
+ * against the fetched signing certificate (SignatureVersion 1 and 2).
85
+ */
86
+ declare const snsWebhook: WebhookVerifier;
87
+ /**
88
+ * Verifier + parser implementing the generic
89
+ * [Standard Webhooks](https://www.standardwebhooks.com/) HMAC scheme.
90
+ *
91
+ * The signed content is `{id}.{timestamp}.{body}`; the signature is the base64
92
+ * HMAC-SHA256 prefixed with `v1,`. The `webhook-signature` header may carry several
93
+ * space-separated signatures (key rotation) — verification passes when any matches.
94
+ * If the secret begins with `whsec_`, the base64 remainder is decoded to raw key bytes
95
+ * and the HMAC is keyed with those bytes (per the spec); otherwise the raw secret string
96
+ * is used directly. A hex digest is also accepted as a fallback for non-conformant
97
+ * senders. Edge-safe — uses Web Crypto only.
98
+ */
99
+ declare const standardWebhook: WebhookVerifier;
100
+ /**
101
+ * Verifier + parser for Twilio status-callback webhooks.
102
+ *
103
+ * Verification follows Twilio's scheme: `X-Twilio-Signature` is the base64 HMAC-SHA1
104
+ * (keyed by the auth token) of the request URL concatenated with the form parameters
105
+ * sorted by key. The full request URL must be provided via the
106
+ * `x-twilio-signature-url` header (the verifier cannot reconstruct it from the body).
107
+ * Edge-safe — uses Web Crypto only.
108
+ */
109
+ declare const twilioWebhook: WebhookVerifier;
110
+ export { type WebhookHeaders, type WebhookVerifier, getHeader, hmacBase64, hmacHex, slackWebhook, snsWebhook, standardWebhook, timingSafeEqual, twilioWebhook };
@@ -0,0 +1 @@
1
+ import{hmacBase64 as a,hmacHex as r,timingSafeEqual as t}from"../packem_shared/hmacBase64-BhhoX0uo.js";import{default as m}from"../packem_shared/slackWebhook-GEx_GdcV.js";import{default as d}from"../packem_shared/snsWebhook-ChZnBBT3.js";import{default as x}from"../packem_shared/standardWebhook-B-LxP8U7.js";import{default as p}from"../packem_shared/twilioWebhook-F0mTmGXD.js";import{getHeader as u}from"../packem_shared/getHeader-C_gkdnMQ.js";export{u as getHeader,a as hmacBase64,r as hmacHex,m as slackWebhook,d as snsWebhook,x as standardWebhook,t as timingSafeEqual,p as twilioWebhook};
@@ -0,0 +1,83 @@
1
+ import { M as MaybePromise, D as Duration, W as WorkflowConfig, a as WorkflowDefinition } from "../packem_shared/types.d-C1GoEAlI.d-Bv3grfyD.js";
2
+ import '@standard-schema/spec';
3
+ import { C as ChannelPayloadMap, N as Notification } from "../packem_shared/notification.d-DFCVTods.js";
4
+ import { C as ChannelType, c as Receipt } from "../packem_shared/types.d-GUzX1jTk.js";
5
+ import "../packem_shared/types.d-CximoA8M.js";
6
+ import "../packem_shared/provider.d-BQAGriz6.js";
7
+ /** The context handed to a step resolver / skip predicate. */
8
+ interface StepResolverContext<PayloadT> {
9
+ /** The validated trigger payload of the run. */
10
+ payload: PayloadT;
11
+ }
12
+ /** Resolves the payload sent by a channel step (or decides to skip it). */
13
+ type StepResolver<PayloadT, ResultT> = (context: StepResolverContext<PayloadT>) => MaybePromise<ResultT>;
14
+ /** Per-step options for a channel step. */
15
+ interface ChannelStepOptions<PayloadT> {
16
+ /** Skip the send when this returns `true`; the step records `undefined`. */
17
+ skip?: (context: StepResolverContext<PayloadT>) => MaybePromise<boolean>;
18
+ /**
19
+ * Treat a `FailureReceipt` as a thrown error so the run fails and the step
20
+ * re-runs on the next resume/sweep. Defaults to `false`.
21
+ */
22
+ throwOnFailure?: boolean;
23
+ }
24
+ /**
25
+ * A durable channel step. Resolves a channel payload and delivers it through the
26
+ * bound {@link Notification} facade exactly once; the receipt is recorded and
27
+ * returned on replay without re-sending. Returns `undefined` when `skip` matches.
28
+ *
29
+ * IMPORTANT: a delivery failure surfaces as a `FailureReceipt` (the facade does not
30
+ * throw), so by default a failed send is **recorded as a completed step and not
31
+ * retried** — inspect `receipt.successful`, or pass `throwOnFailure: true` to turn
32
+ * a failure into a thrown error that re-runs the step on the next activation.
33
+ */
34
+ type ChannelStep<ChannelT extends ChannelType, PayloadT> = (id: string, resolve: StepResolver<PayloadT, ChannelPayloadMap[ChannelT]>, options?: ChannelStepOptions<PayloadT>) => Promise<Receipt | undefined>;
35
+ /**
36
+ * The `step` object handed to a notification workflow body. Channel steps deliver
37
+ * exactly once; `delay` pauses durably; `custom` is an escape hatch to the raw
38
+ * engine step.
39
+ */
40
+ interface NotificationStep<PayloadT> {
41
+ chat: ChannelStep<"chat", PayloadT>;
42
+ custom: <T>(id: string, function_: () => MaybePromise<T>) => Promise<T>;
43
+ delay: (id: string, duration: Duration) => Promise<void>;
44
+ email: ChannelStep<"email", PayloadT>;
45
+ inApp: ChannelStep<"inapp", PayloadT>;
46
+ push: ChannelStep<"push", PayloadT>;
47
+ sms: ChannelStep<"sms", PayloadT>;
48
+ webhook: ChannelStep<"webhook", PayloadT>;
49
+ }
50
+ /** The body of a notification workflow, driven by {@link NotificationStep}. */
51
+ type NotificationWorkflowRun<PayloadT, OutputT> = (context: {
52
+ payload: PayloadT;
53
+ runId: string;
54
+ step: NotificationStep<PayloadT>;
55
+ }) => MaybePromise<OutputT>;
56
+ /** Config for {@link createNotificationWorkflow}: a {@link WorkflowConfig} whose `run` is notification-flavoured. */
57
+ interface NotificationWorkflowConfig<PayloadT, OutputT> extends Omit<WorkflowConfig<PayloadT, OutputT>, "run"> {
58
+ run: NotificationWorkflowRun<PayloadT, OutputT>;
59
+ }
60
+ /**
61
+ * Define a durable notification workflow on top of [`@visulima/workflow`](https://visulima.com/packages/workflow).
62
+ *
63
+ * The returned value is a plain `WorkflowDefinition`, so it plugs straight into a
64
+ * workflow runtime (`createRuntime({ workflows: [wf] })` → `runtime.trigger(wf, payload)`).
65
+ * Channel steps deliver through the bound `notification` facade exactly once.
66
+ * @param notification The multi-channel facade messages are delivered through.
67
+ * @param config The workflow id, optional payload schema, and notification-flavoured `run`.
68
+ * @returns A {@link WorkflowDefinition} ready to register/trigger on a runtime.
69
+ * @example
70
+ * ```ts
71
+ * const onComment = createNotificationWorkflow(notify, {
72
+ * id: "comment-posted",
73
+ * payload: z.object({ subscriberId: z.string(), author: z.string() }),
74
+ * run: async ({ step, payload }) => {
75
+ * await step.inApp("inbox", () => ({ to: payload.subscriberId, body: `${payload.author} commented` }));
76
+ * await step.delay("cooldown", { amount: 1, unit: "hours" });
77
+ * await step.email("nudge", () => ({ from: "x@y.com", to: payload.subscriberId, subject: "New comment", html: "<p>…</p>" }));
78
+ * },
79
+ * });
80
+ * ```
81
+ */
82
+ declare const createNotificationWorkflow: <PayloadT = unknown, OutputT = unknown>(notification: Notification, config: NotificationWorkflowConfig<PayloadT, OutputT>) => WorkflowDefinition<PayloadT, OutputT>;
83
+ export { type ChannelStep, type ChannelStepOptions, type NotificationStep, type NotificationWorkflowConfig, type NotificationWorkflowRun, type StepResolver, type StepResolverContext, createNotificationWorkflow };
@@ -0,0 +1 @@
1
+ import{default as a}from"../packem_shared/createNotificationWorkflow-B70OgeED.js";export{a as createNotificationWorkflow};
package/package.json CHANGED
@@ -1,45 +1,285 @@
1
1
  {
2
- "name": "@visulima/notification",
3
- "version": "0.0.1",
4
- "description": "A reusable, ESM-only, edge-ready multi-channel notification library placeholder, full release coming soon.",
5
- "keywords": [
6
- "notification",
7
- "notifications",
8
- "multi-channel",
9
- "visulima"
10
- ],
11
- "homepage": "https://visulima.com/packages/notification",
12
- "bugs": "https://github.com/visulima/visulima/issues",
13
- "repository": {
14
- "type": "git",
15
- "url": "git+https://github.com/visulima/visulima.git",
16
- "directory": "packages/notification/notification"
17
- },
18
- "funding": [
19
- {
20
- "type": "github",
21
- "url": "https://github.com/sponsors/prisis"
22
- },
23
- {
24
- "type": "consulting",
25
- "url": "https://anolilab.com/support"
26
- }
27
- ],
28
- "license": "MIT",
29
- "author": {
30
- "name": "Daniel Bannert",
31
- "email": "d.bannert@anolilab.de"
32
- },
33
- "sideEffects": false,
34
- "type": "module",
35
- "files": [
36
- "README.md"
37
- ],
38
- "engines": {
39
- "node": "^22.14.0 || >=24.10.0"
40
- },
41
- "publishConfig": {
42
- "access": "public",
43
- "provenance": false
2
+ "name": "@visulima/notification",
3
+ "version": "1.0.0-alpha.2",
4
+ "description": "A reusable, ESM-only, edge-ready multi-channel notification library with SMS, push, chat, in-app and webhook providers",
5
+ "keywords": [
6
+ "notification",
7
+ "notifications",
8
+ "multi-channel",
9
+ "sms",
10
+ "push",
11
+ "chat",
12
+ "in-app",
13
+ "webhook",
14
+ "twilio",
15
+ "vonage",
16
+ "plivo",
17
+ "aws-sns",
18
+ "sns",
19
+ "messagebird",
20
+ "fcm",
21
+ "apns",
22
+ "expo",
23
+ "web-push",
24
+ "vapid",
25
+ "opentelemetry",
26
+ "handlebars",
27
+ "liquid",
28
+ "slack",
29
+ "discord",
30
+ "ms-teams",
31
+ "telegram",
32
+ "failover",
33
+ "roundrobin",
34
+ "middleware",
35
+ "queue",
36
+ "visulima"
37
+ ],
38
+ "homepage": "https://visulima.com/packages/notification",
39
+ "bugs": "https://github.com/visulima/visulima/issues",
40
+ "repository": {
41
+ "type": "git",
42
+ "url": "git+https://github.com/visulima/visulima.git",
43
+ "directory": "packages/notification/notification"
44
+ },
45
+ "funding": [
46
+ {
47
+ "type": "github",
48
+ "url": "https://github.com/sponsors/prisis"
49
+ },
50
+ {
51
+ "type": "consulting",
52
+ "url": "https://anolilab.com/support"
53
+ }
54
+ ],
55
+ "license": "MIT",
56
+ "author": {
57
+ "name": "Daniel Bannert",
58
+ "email": "d.bannert@anolilab.de"
59
+ },
60
+ "sideEffects": false,
61
+ "type": "module",
62
+ "exports": {
63
+ ".": {
64
+ "types": "./dist/index.d.ts",
65
+ "default": "./dist/index.js"
66
+ },
67
+ "./providers/mock": {
68
+ "types": "./dist/providers/mock/index.d.ts",
69
+ "default": "./dist/providers/mock/index.js"
70
+ },
71
+ "./providers/twilio": {
72
+ "types": "./dist/providers/sms/twilio/index.d.ts",
73
+ "default": "./dist/providers/sms/twilio/index.js"
74
+ },
75
+ "./providers/vonage": {
76
+ "types": "./dist/providers/sms/vonage/index.d.ts",
77
+ "default": "./dist/providers/sms/vonage/index.js"
78
+ },
79
+ "./providers/plivo": {
80
+ "types": "./dist/providers/sms/plivo/index.d.ts",
81
+ "default": "./dist/providers/sms/plivo/index.js"
82
+ },
83
+ "./providers/messagebird": {
84
+ "types": "./dist/providers/sms/messagebird/index.d.ts",
85
+ "default": "./dist/providers/sms/messagebird/index.js"
86
+ },
87
+ "./providers/telnyx": {
88
+ "types": "./dist/providers/sms/telnyx/index.d.ts",
89
+ "default": "./dist/providers/sms/telnyx/index.js"
90
+ },
91
+ "./providers/slack": {
92
+ "types": "./dist/providers/chat/slack/index.d.ts",
93
+ "default": "./dist/providers/chat/slack/index.js"
94
+ },
95
+ "./providers/discord": {
96
+ "types": "./dist/providers/chat/discord/index.d.ts",
97
+ "default": "./dist/providers/chat/discord/index.js"
98
+ },
99
+ "./providers/msteams": {
100
+ "types": "./dist/providers/chat/msteams/index.d.ts",
101
+ "default": "./dist/providers/chat/msteams/index.js"
102
+ },
103
+ "./providers/telegram": {
104
+ "types": "./dist/providers/chat/telegram/index.d.ts",
105
+ "default": "./dist/providers/chat/telegram/index.js"
106
+ },
107
+ "./providers/expo": {
108
+ "types": "./dist/providers/push/expo/index.d.ts",
109
+ "default": "./dist/providers/push/expo/index.js"
110
+ },
111
+ "./providers/fcm": {
112
+ "types": "./dist/providers/push/fcm/index.d.ts",
113
+ "default": "./dist/providers/push/fcm/index.js"
114
+ },
115
+ "./providers/failover": {
116
+ "types": "./dist/providers/failover/index.d.ts",
117
+ "default": "./dist/providers/failover/index.js"
118
+ },
119
+ "./providers/roundrobin": {
120
+ "types": "./dist/providers/roundrobin/index.d.ts",
121
+ "default": "./dist/providers/roundrobin/index.js"
122
+ },
123
+ "./providers/webhook": {
124
+ "types": "./dist/providers/webhook/index.d.ts",
125
+ "default": "./dist/providers/webhook/index.js"
126
+ },
127
+ "./channels/email": {
128
+ "types": "./dist/channels/email/index.d.ts",
129
+ "default": "./dist/channels/email/index.js"
130
+ },
131
+ "./channels/inapp": {
132
+ "types": "./dist/channels/inapp/index.d.ts",
133
+ "default": "./dist/channels/inapp/index.js"
134
+ },
135
+ "./preferences": {
136
+ "types": "./dist/preferences/index.d.ts",
137
+ "default": "./dist/preferences/index.js"
138
+ },
139
+ "./middleware": {
140
+ "types": "./dist/middleware/index.d.ts",
141
+ "default": "./dist/middleware/index.js"
142
+ },
143
+ "./routing": {
144
+ "types": "./dist/routing/index.d.ts",
145
+ "default": "./dist/routing/index.js"
146
+ },
147
+ "./events": {
148
+ "types": "./dist/events/index.d.ts",
149
+ "default": "./dist/events/index.js"
150
+ },
151
+ "./queue": {
152
+ "types": "./dist/queue/index.d.ts",
153
+ "default": "./dist/queue/index.js"
154
+ },
155
+ "./queue/unstorage": {
156
+ "types": "./dist/queue/unstorage-queue.d.ts",
157
+ "default": "./dist/queue/unstorage-queue.js"
158
+ },
159
+ "./queue/bullmq": {
160
+ "types": "./dist/queue/bullmq-queue.d.ts",
161
+ "default": "./dist/queue/bullmq-queue.js"
162
+ },
163
+ "./queue/pg-boss": {
164
+ "types": "./dist/queue/pg-boss-queue.d.ts",
165
+ "default": "./dist/queue/pg-boss-queue.js"
166
+ },
167
+ "./queue/sqs": {
168
+ "types": "./dist/queue/sqs-queue.d.ts",
169
+ "default": "./dist/queue/sqs-queue.js"
170
+ },
171
+ "./providers/sns": {
172
+ "types": "./dist/providers/sms/sns/index.d.ts",
173
+ "default": "./dist/providers/sms/sns/index.js"
174
+ },
175
+ "./providers/web-push": {
176
+ "types": "./dist/providers/push/web-push/index.d.ts",
177
+ "default": "./dist/providers/push/web-push/index.js"
178
+ },
179
+ "./providers/apns": {
180
+ "types": "./dist/providers/push/apns/index.d.ts",
181
+ "default": "./dist/providers/push/apns/index.js"
182
+ },
183
+ "./providers/opentelemetry": {
184
+ "types": "./dist/providers/opentelemetry/index.d.ts",
185
+ "default": "./dist/providers/opentelemetry/index.js"
186
+ },
187
+ "./webhooks": {
188
+ "types": "./dist/webhooks/index.d.ts",
189
+ "default": "./dist/webhooks/index.js"
190
+ },
191
+ "./template/string": {
192
+ "types": "./dist/template-engines/string.d.ts",
193
+ "default": "./dist/template-engines/string.js"
194
+ },
195
+ "./template/handlebars": {
196
+ "types": "./dist/template-engines/handlebars.d.ts",
197
+ "default": "./dist/template-engines/handlebars.js"
198
+ },
199
+ "./template/liquid": {
200
+ "types": "./dist/template-engines/liquid.d.ts",
201
+ "default": "./dist/template-engines/liquid.js"
202
+ },
203
+ "./utils/result": {
204
+ "types": "./dist/utils/result.d.ts",
205
+ "default": "./dist/utils/result.js"
206
+ },
207
+ "./workflow": {
208
+ "types": "./dist/workflow/index.d.ts",
209
+ "default": "./dist/workflow/index.js"
210
+ },
211
+ "./digest": {
212
+ "types": "./dist/digest/index.d.ts",
213
+ "default": "./dist/digest/index.js"
214
+ },
215
+ "./layouts": {
216
+ "types": "./dist/layouts/index.d.ts",
217
+ "default": "./dist/layouts/index.js"
218
+ },
219
+ "./i18n": {
220
+ "types": "./dist/i18n/index.d.ts",
221
+ "default": "./dist/i18n/index.js"
222
+ },
223
+ "./package.json": "./package.json"
224
+ },
225
+ "files": [
226
+ "dist",
227
+ "README.md",
228
+ "CHANGELOG.md"
229
+ ],
230
+ "peerDependencies": {
231
+ "@aws-sdk/client-sqs": "^3.0.0",
232
+ "@opentelemetry/api": "^1.0.0 || ^2.0.0",
233
+ "@visulima/email": "1.0.0-alpha.42",
234
+ "@visulima/workflow": "1.0.0-alpha.1",
235
+ "bullmq": "^5.0.0",
236
+ "croner": "^10.0.1",
237
+ "handlebars": "4.7.9",
238
+ "intl-messageformat": "^11.0.0",
239
+ "liquidjs": "^10.0.0",
240
+ "pg-boss": "^10.0.0",
241
+ "unstorage": "^1.13.0"
242
+ },
243
+ "peerDependenciesMeta": {
244
+ "@aws-sdk/client-sqs": {
245
+ "optional": true
246
+ },
247
+ "@opentelemetry/api": {
248
+ "optional": true
249
+ },
250
+ "@visulima/email": {
251
+ "optional": true
252
+ },
253
+ "@visulima/workflow": {
254
+ "optional": true
255
+ },
256
+ "bullmq": {
257
+ "optional": true
258
+ },
259
+ "croner": {
260
+ "optional": true
261
+ },
262
+ "handlebars": {
263
+ "optional": true
264
+ },
265
+ "intl-messageformat": {
266
+ "optional": true
267
+ },
268
+ "liquidjs": {
269
+ "optional": true
270
+ },
271
+ "pg-boss": {
272
+ "optional": true
273
+ },
274
+ "unstorage": {
275
+ "optional": true
44
276
  }
45
- }
277
+ },
278
+ "engines": {
279
+ "node": "^22.14.0 || >=24.10.0"
280
+ },
281
+ "publishConfig": {
282
+ "access": "public",
283
+ "provenance": true
284
+ }
285
+ }