@visulima/notification 0.0.1 → 1.0.0-alpha.1

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 (134) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/LICENSE.md +434 -0
  3. package/README.md +296 -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/events/index.d.ts +37 -0
  9. package/dist/events/index.js +1 -0
  10. package/dist/index.d.ts +174 -0
  11. package/dist/index.js +1 -0
  12. package/dist/middleware/index.d.ts +382 -0
  13. package/dist/middleware/index.js +1 -0
  14. package/dist/packem_shared/MemoryEventStore-BGD_xRxu.js +1 -0
  15. package/dist/packem_shared/MemoryInAppStore-48qlrDCx.js +1 -0
  16. package/dist/packem_shared/MemoryQueue-CXgWoZoY.js +1 -0
  17. package/dist/packem_shared/Notification-D1YeYxrQ.js +1 -0
  18. package/dist/packem_shared/NotificationError-DVfMJQ1u.js +1 -0
  19. package/dist/packem_shared/NotificationMessageBuilder-Br_aZusY.js +1 -0
  20. package/dist/packem_shared/RequiredOptionError-CuL42XRq.js +1 -0
  21. package/dist/packem_shared/UnstorageInAppStore-Bq2LoDMO.js +1 -0
  22. package/dist/packem_shared/apnsProvider-C9WSv5sc.js +1 -0
  23. package/dist/packem_shared/circuitBreakerMiddleware-BlZN7SVT.js +1 -0
  24. package/dist/packem_shared/composeMiddleware-D6dR8DUS.js +1 -0
  25. package/dist/packem_shared/createQueueWorker-DjQBxjXc.js +1 -0
  26. package/dist/packem_shared/credentials-CG0zkn-W.js +1 -0
  27. package/dist/packem_shared/dedupeMiddleware-CQmPJd_h.js +1 -0
  28. package/dist/packem_shared/defineProvider-C9q-7iwt.js +1 -0
  29. package/dist/packem_shared/discordProvider-ewPfe-J7.js +1 -0
  30. package/dist/packem_shared/emailChannel-CNDlX96Q.js +1 -0
  31. package/dist/packem_shared/expoProvider-CXq101FD.js +1 -0
  32. package/dist/packem_shared/failoverProvider-D1dAmW8U.js +1 -0
  33. package/dist/packem_shared/fcmProvider-WdJGZ55l.js +1 -0
  34. package/dist/packem_shared/getHeader-C_gkdnMQ.js +1 -0
  35. package/dist/packem_shared/hmacBase64-BhhoX0uo.js +1 -0
  36. package/dist/packem_shared/http-BMYcUNBU.js +1 -0
  37. package/dist/packem_shared/id-C_FRCsUM.js +1 -0
  38. package/dist/packem_shared/inAppProvider-ElbahgSj.js +1 -0
  39. package/dist/packem_shared/loggingMiddleware-Cs6EDLcL.js +1 -0
  40. package/dist/packem_shared/messageBirdProvider-CHUFB0hd.js +1 -0
  41. package/dist/packem_shared/mockProvider-BLwTZlkw.js +1 -0
  42. package/dist/packem_shared/msTeamsProvider-DBhrmuSd.js +1 -0
  43. package/dist/packem_shared/notification.d-BBLyVuqi.d.ts +87 -0
  44. package/dist/packem_shared/otelProvider-b6LVo0BS.js +1 -0
  45. package/dist/packem_shared/plivoProvider-CIOl6DWw.js +1 -0
  46. package/dist/packem_shared/provider.d-BQAGriz6.d.ts +33 -0
  47. package/dist/packem_shared/rateLimitMiddleware-DWmEYq-m.js +1 -0
  48. package/dist/packem_shared/retryMiddleware-uUJDcUoP.js +1 -0
  49. package/dist/packem_shared/roundRobinProvider-BetXJUUm.js +1 -0
  50. package/dist/packem_shared/slackProvider-N1wNtAZ3.js +1 -0
  51. package/dist/packem_shared/slackWebhook-GEx_GdcV.js +1 -0
  52. package/dist/packem_shared/sms-CU-OZvNU.js +1 -0
  53. package/dist/packem_shared/snsProvider-KCciJ-nj.js +4 -0
  54. package/dist/packem_shared/snsWebhook-ChZnBBT3.js +1 -0
  55. package/dist/packem_shared/standardWebhook-B-LxP8U7.js +1 -0
  56. package/dist/packem_shared/suppressionMiddleware-CY-Qo1A_.js +1 -0
  57. package/dist/packem_shared/telegramProvider-jqR5BhJL.js +1 -0
  58. package/dist/packem_shared/telemetryMiddleware-B1N4k171.js +1 -0
  59. package/dist/packem_shared/telnyxProvider-C8TMPir1.js +1 -0
  60. package/dist/packem_shared/tracer.d-Co1s_NwG.d.ts +494 -0
  61. package/dist/packem_shared/twilioProvider-BxI0e6LX.js +1 -0
  62. package/dist/packem_shared/twilioWebhook-F0mTmGXD.js +1 -0
  63. package/dist/packem_shared/types.d-CximoA8M.d.ts +29 -0
  64. package/dist/packem_shared/types.d-DyM9JjL7.d.ts +33 -0
  65. package/dist/packem_shared/types.d-GUzX1jTk.d.ts +235 -0
  66. package/dist/packem_shared/types.d-td-F2Oh0.d.ts +10 -0
  67. package/dist/packem_shared/unstorage.DqlWKU2I.d-CogP3Etw.d.ts +120 -0
  68. package/dist/packem_shared/vonageProvider-BF76ca89.js +1 -0
  69. package/dist/packem_shared/webPushProvider-B962RwsA.js +1 -0
  70. package/dist/packem_shared/webcrypto-bY7wJCB5.js +1 -0
  71. package/dist/packem_shared/webhookProvider-BALSb2pc.js +1 -0
  72. package/dist/preferences/index.d.ts +49 -0
  73. package/dist/preferences/index.js +1 -0
  74. package/dist/providers/chat/discord/index.d.ts +14 -0
  75. package/dist/providers/chat/discord/index.js +1 -0
  76. package/dist/providers/chat/msteams/index.d.ts +14 -0
  77. package/dist/providers/chat/msteams/index.js +1 -0
  78. package/dist/providers/chat/slack/index.d.ts +19 -0
  79. package/dist/providers/chat/slack/index.js +1 -0
  80. package/dist/providers/chat/telegram/index.d.ts +18 -0
  81. package/dist/providers/chat/telegram/index.js +1 -0
  82. package/dist/providers/failover/index.d.ts +16 -0
  83. package/dist/providers/failover/index.js +1 -0
  84. package/dist/providers/mock/index.d.ts +29 -0
  85. package/dist/providers/mock/index.js +1 -0
  86. package/dist/providers/opentelemetry/index.d.ts +21 -0
  87. package/dist/providers/opentelemetry/index.js +1 -0
  88. package/dist/providers/push/apns/index.d.ts +24 -0
  89. package/dist/providers/push/apns/index.js +1 -0
  90. package/dist/providers/push/expo/index.d.ts +14 -0
  91. package/dist/providers/push/expo/index.js +1 -0
  92. package/dist/providers/push/fcm/index.d.ts +26 -0
  93. package/dist/providers/push/fcm/index.js +1 -0
  94. package/dist/providers/push/web-push/index.d.ts +36 -0
  95. package/dist/providers/push/web-push/index.js +1 -0
  96. package/dist/providers/roundrobin/index.d.ts +17 -0
  97. package/dist/providers/roundrobin/index.js +1 -0
  98. package/dist/providers/sms/messagebird/index.d.ts +16 -0
  99. package/dist/providers/sms/messagebird/index.js +1 -0
  100. package/dist/providers/sms/plivo/index.d.ts +18 -0
  101. package/dist/providers/sms/plivo/index.js +1 -0
  102. package/dist/providers/sms/sns/index.d.ts +21 -0
  103. package/dist/providers/sms/sns/index.js +1 -0
  104. package/dist/providers/sms/telnyx/index.d.ts +18 -0
  105. package/dist/providers/sms/telnyx/index.js +1 -0
  106. package/dist/providers/sms/twilio/index.d.ts +20 -0
  107. package/dist/providers/sms/twilio/index.js +1 -0
  108. package/dist/providers/sms/vonage/index.d.ts +18 -0
  109. package/dist/providers/sms/vonage/index.js +1 -0
  110. package/dist/providers/webhook/index.d.ts +18 -0
  111. package/dist/providers/webhook/index.js +1 -0
  112. package/dist/queue/bullmq-queue.d.ts +58 -0
  113. package/dist/queue/bullmq-queue.js +1 -0
  114. package/dist/queue/index.d.ts +50 -0
  115. package/dist/queue/index.js +1 -0
  116. package/dist/queue/pg-boss-queue.d.ts +66 -0
  117. package/dist/queue/pg-boss-queue.js +1 -0
  118. package/dist/queue/sqs-queue.d.ts +91 -0
  119. package/dist/queue/sqs-queue.js +1 -0
  120. package/dist/queue/unstorage-queue.d.ts +30 -0
  121. package/dist/queue/unstorage-queue.js +1 -0
  122. package/dist/routing/index.d.ts +35 -0
  123. package/dist/routing/index.js +1 -0
  124. package/dist/template-engines/handlebars.d.ts +16 -0
  125. package/dist/template-engines/handlebars.js +1 -0
  126. package/dist/template-engines/liquid.d.ts +16 -0
  127. package/dist/template-engines/liquid.js +1 -0
  128. package/dist/template-engines/string.d.ts +20 -0
  129. package/dist/template-engines/string.js +1 -0
  130. package/dist/utils/result.d.ts +54 -0
  131. package/dist/utils/result.js +1 -0
  132. package/dist/webhooks/index.d.ts +110 -0
  133. package/dist/webhooks/index.js +1 -0
  134. package/package.json +255 -43
@@ -0,0 +1,382 @@
1
+ import { M as Middleware, S as SendContext } from "../packem_shared/types.d-CximoA8M.js";
2
+ export { type a as SendFunction, c as composeMiddleware } from "../packem_shared/types.d-CximoA8M.js";
3
+ import { C as ChannelType, B as BaseNotificationPayload } from "../packem_shared/types.d-GUzX1jTk.js";
4
+ import { A as Attributes, C as Context, T as Tracer } from "../packem_shared/tracer.d-Co1s_NwG.js";
5
+ interface CircuitBreakerMiddlewareOptions {
6
+ /** Time in ms the circuit stays open before a trial request (default 30000). */
7
+ resetTimeout?: number;
8
+ /** Consecutive failures before the circuit opens (default 5). */
9
+ threshold?: number;
10
+ }
11
+ /**
12
+ * Trips a circuit after consecutive failures, short-circuiting further sends until a
13
+ * cool-off elapses (then allows a single trial request).
14
+ * @param options Failure `threshold` and open-circuit `resetTimeout` (ms).
15
+ * @returns A middleware.
16
+ */
17
+ declare const circuitBreakerMiddleware: (options?: CircuitBreakerMiddlewareOptions) => Middleware;
18
+ interface DedupeMiddlewareOptions {
19
+ /** Derive the dedupe key (default: `payload.idempotencyKey`). */
20
+ keyFn?: (context: SendContext) => string | undefined;
21
+ /** How long a key is remembered, in ms (default 60000). */
22
+ ttl?: number;
23
+ }
24
+ /**
25
+ * Suppresses duplicate sends within a TTL window, keyed by idempotency key. A suppressed
26
+ * send resolves successfully with `sent: false` and a `deduped:` message id.
27
+ * @param options Custom `keyFn` and `ttl` (ms) controlling how keys are derived and expire.
28
+ * @returns A middleware.
29
+ */
30
+ declare const dedupeMiddleware: (options?: DedupeMiddlewareOptions) => Middleware;
31
+ interface LoggingMiddlewareOptions {
32
+ /** Console-like logger (default `console`). */
33
+ logger?: Console;
34
+ }
35
+ /**
36
+ * Logs each send attempt and its outcome.
37
+ * @param options Provide a custom console-like `logger` (defaults to the global console).
38
+ * @returns A middleware.
39
+ */
40
+ declare const loggingMiddleware: (options?: LoggingMiddlewareOptions) => Middleware;
41
+ interface RateLimitMiddlewareOptions {
42
+ /** Time window in ms over which `rate` tokens are available (default 1000). */
43
+ interval?: number;
44
+ /** Number of sends allowed per `interval` (token bucket capacity). */
45
+ rate: number;
46
+ }
47
+ /**
48
+ * Throttles sends with a token-bucket rate limiter.
49
+ * @param options Bucket `rate` (capacity) and refill `interval` (ms).
50
+ * @returns A middleware.
51
+ */
52
+ declare const rateLimitMiddleware: (options: RateLimitMiddlewareOptions) => Middleware;
53
+ interface RetryMiddlewareOptions {
54
+ /** Base backoff delay in ms (default 250). */
55
+ baseDelay?: number;
56
+ /** Maximum retry attempts after the first try (default 3). */
57
+ retries?: number;
58
+ /** Decide whether a failed result is retryable (default: always retry). */
59
+ shouldRetry?: (error: unknown) => boolean;
60
+ }
61
+ /**
62
+ * Retries failed sends with exponential backoff + jitter.
63
+ * @param options Attempt count (`retries`), `baseDelay` (ms) and a `shouldRetry` predicate.
64
+ * @returns A middleware.
65
+ */
66
+ declare const retryMiddleware: (options?: RetryMiddlewareOptions) => Middleware;
67
+ /**
68
+ * Options for {@link suppressionMiddleware}.
69
+ */
70
+ interface SuppressionMiddlewareOptions {
71
+ /** Returns whether a recipient is suppressed on a channel (unsubscribed, hard-bounced); may be async. */
72
+ isSuppressed: (recipient: string, channel: ChannelType) => boolean | Promise<boolean>;
73
+ /** Resolves the recipient identifier from a payload. Defaults to a stringified `payload.to`. */
74
+ resolveRecipient?: (payload: BaseNotificationPayload) => string | undefined;
75
+ }
76
+ /**
77
+ * Short-circuits sends to suppressed recipients (unsubscribed, hard-bounced, ...). When the resolved
78
+ * recipient is suppressed the send resolves successfully with `sent: false` and a `suppressed:` message
79
+ * id, mirroring how {@link import("./dedupe").dedupeMiddleware} returns a synthetic success.
80
+ *
81
+ * Edge-safe: pure logic with no Node built-ins, so it runs on Cloudflare Workers and other edge runtimes.
82
+ * @param options Suppression check and optional recipient resolver. See {@link SuppressionMiddlewareOptions}.
83
+ * @returns A middleware.
84
+ */
85
+ declare const suppressionMiddleware: (options: SuppressionMiddlewareOptions) => Middleware;
86
+ /**
87
+ * Advisory options influencing aggregation configuration parameters.
88
+ *
89
+ * @since 1.7.0
90
+ * @experimental
91
+ */
92
+ interface MetricAdvice {
93
+ /**
94
+ * Hint the explicit bucket boundaries for SDK if the metric is been
95
+ * aggregated with a HistogramAggregator.
96
+ */
97
+ explicitBucketBoundaries?: number[];
98
+ }
99
+ /**
100
+ * Options needed for metric creation
101
+ *
102
+ * @since 1.3.0
103
+ */
104
+ interface MetricOptions {
105
+ /**
106
+ * The description of the Metric.
107
+ * @default ''
108
+ */
109
+ description?: string;
110
+ /**
111
+ * The unit of the Metric values.
112
+ * @default ''
113
+ */
114
+ unit?: string;
115
+ /**
116
+ * Indicates the type of the recorded value.
117
+ * @default {@link ValueType.DOUBLE}
118
+ */
119
+ valueType?: ValueType;
120
+ /**
121
+ * The advice influencing aggregation configuration parameters.
122
+ * @experimental
123
+ * @since 1.7.0
124
+ */
125
+ advice?: MetricAdvice;
126
+ }
127
+ /**
128
+ * The Type of value. It describes how the data is reported.
129
+ *
130
+ * @since 1.3.0
131
+ */
132
+ declare enum ValueType {
133
+ INT = 0,
134
+ DOUBLE = 1,
135
+ }
136
+ /**
137
+ * Counter is the most common synchronous instrument. This instrument supports
138
+ * an `Add(increment)` function for reporting a sum, and is restricted to
139
+ * non-negative increments. The default aggregation is Sum, as for any additive
140
+ * instrument.
141
+ *
142
+ * Example uses for Counter:
143
+ * <ol>
144
+ * <li> count the number of bytes received. </li>
145
+ * <li> count the number of requests completed. </li>
146
+ * <li> count the number of accounts created. </li>
147
+ * <li> count the number of checkpoints run. </li>
148
+ * <li> count the number of 5xx errors. </li>
149
+ * <ol>
150
+ *
151
+ * @since 1.3.0
152
+ */
153
+ interface Counter<AttributesTypes extends MetricAttributes = MetricAttributes> {
154
+ /**
155
+ * Increment value of counter by the input. Inputs must not be negative.
156
+ */
157
+ add(value: number, attributes?: AttributesTypes, context?: Context): void;
158
+ }
159
+ /**
160
+ * @since 1.3.0
161
+ */
162
+ interface UpDownCounter<AttributesTypes extends MetricAttributes = MetricAttributes> {
163
+ /**
164
+ * Increment value of counter by the input. Inputs may be negative.
165
+ */
166
+ add(value: number, attributes?: AttributesTypes, context?: Context): void;
167
+ }
168
+ /**
169
+ * @since 1.9.0
170
+ */
171
+ interface Gauge<AttributesTypes extends MetricAttributes = MetricAttributes> {
172
+ /**
173
+ * Records a measurement.
174
+ */
175
+ record(value: number, attributes?: AttributesTypes, context?: Context): void;
176
+ }
177
+ /**
178
+ * @since 1.3.0
179
+ */
180
+ interface Histogram<AttributesTypes extends MetricAttributes = MetricAttributes> {
181
+ /**
182
+ * Records a measurement. Value of the measurement must not be negative.
183
+ */
184
+ record(value: number, attributes?: AttributesTypes, context?: Context): void;
185
+ }
186
+ /**
187
+ * @deprecated please use {@link Attributes}
188
+ * @since 1.3.0
189
+ */
190
+ type MetricAttributes = Attributes;
191
+ /**
192
+ * Interface that is being used in callback function for Observable Metric.
193
+ *
194
+ * @since 1.3.0
195
+ */
196
+ interface ObservableResult<AttributesTypes extends MetricAttributes = MetricAttributes> {
197
+ /**
198
+ * Observe a measurement of the value associated with the given attributes.
199
+ *
200
+ * @param value The value to be observed.
201
+ * @param attributes The attributes associated with the value. If more than
202
+ * one value is associated with the same attributes values, SDK may pick the
203
+ * last one or simply drop the entire observable result.
204
+ */
205
+ observe(this: ObservableResult<AttributesTypes>, value: number, attributes?: AttributesTypes): void;
206
+ }
207
+ /**
208
+ * Interface that is being used in batch observable callback function.
209
+ */
210
+ interface BatchObservableResult<AttributesTypes extends MetricAttributes = MetricAttributes> {
211
+ /**
212
+ * Observe a measurement of the value associated with the given attributes.
213
+ *
214
+ * @param metric The observable metric to be observed.
215
+ * @param value The value to be observed.
216
+ * @param attributes The attributes associated with the value. If more than
217
+ * one value is associated with the same attributes values, SDK may pick the
218
+ * last one or simply drop the entire observable result.
219
+ */
220
+ observe(this: BatchObservableResult<AttributesTypes>, metric: Observable<AttributesTypes>, value: number, attributes?: AttributesTypes): void;
221
+ }
222
+ /**
223
+ * The observable callback for Observable instruments.
224
+ *
225
+ * @since 1.3.0
226
+ */
227
+ type ObservableCallback<AttributesTypes extends MetricAttributes = MetricAttributes> = (observableResult: ObservableResult<AttributesTypes>) => void | Promise<void>;
228
+ /**
229
+ * The observable callback for a batch of Observable instruments.
230
+ *
231
+ * @since 1.3.0
232
+ */
233
+ type BatchObservableCallback<AttributesTypes extends MetricAttributes = MetricAttributes> = (observableResult: BatchObservableResult<AttributesTypes>) => void | Promise<void>;
234
+ /**
235
+ * @since 1.3.0
236
+ */
237
+ interface Observable<AttributesTypes extends MetricAttributes = MetricAttributes> {
238
+ /**
239
+ * Sets up a function that will be called whenever a metric collection is initiated.
240
+ *
241
+ * If the function is already in the list of callbacks for this Observable, the function is not added a second time.
242
+ */
243
+ addCallback(callback: ObservableCallback<AttributesTypes>): void;
244
+ /**
245
+ * Removes a callback previously registered with {@link Observable.addCallback}.
246
+ */
247
+ removeCallback(callback: ObservableCallback<AttributesTypes>): void;
248
+ }
249
+ /**
250
+ * @since 1.3.0
251
+ */
252
+ type ObservableCounter<AttributesTypes extends MetricAttributes = MetricAttributes> = Observable<AttributesTypes>;
253
+ /**
254
+ * @since 1.3.0
255
+ */
256
+ type ObservableUpDownCounter<AttributesTypes extends MetricAttributes = MetricAttributes> = Observable<AttributesTypes>;
257
+ /**
258
+ * @since 1.3.0
259
+ */
260
+ type ObservableGauge<AttributesTypes extends MetricAttributes = MetricAttributes> = Observable<AttributesTypes>;
261
+ /**
262
+ * An interface to allow the recording metrics.
263
+ *
264
+ * {@link Metric}s are used for recording pre-defined aggregation (`Counter`),
265
+ * or raw values (`Histogram`) in which the aggregation and attributes
266
+ * for the exported metric are deferred.
267
+ *
268
+ * @since 1.3.0
269
+ */
270
+ interface Meter {
271
+ /**
272
+ * Creates and returns a new `Gauge`.
273
+ * @param name the name of the metric.
274
+ * @param [options] the metric options.
275
+ */
276
+ createGauge<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): Gauge<AttributesTypes>;
277
+ /**
278
+ * Creates and returns a new `Histogram`.
279
+ * @param name the name of the metric.
280
+ * @param [options] the metric options.
281
+ */
282
+ createHistogram<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): Histogram<AttributesTypes>;
283
+ /**
284
+ * Creates a new `Counter` metric. Generally, this kind of metric when the
285
+ * value is a quantity, the sum is of primary interest, and the event count
286
+ * and value distribution are not of primary interest.
287
+ * @param name the name of the metric.
288
+ * @param [options] the metric options.
289
+ */
290
+ createCounter<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): Counter<AttributesTypes>;
291
+ /**
292
+ * Creates a new `UpDownCounter` metric. UpDownCounter is a synchronous
293
+ * instrument and very similar to Counter except that Add(increment)
294
+ * supports negative increments. It is generally useful for capturing changes
295
+ * in an amount of resources used, or any quantity that rises and falls
296
+ * during a request.
297
+ * Example uses for UpDownCounter:
298
+ * <ol>
299
+ * <li> count the number of active requests. </li>
300
+ * <li> count memory in use by instrumenting new and delete. </li>
301
+ * <li> count queue size by instrumenting enqueue and dequeue. </li>
302
+ * <li> count semaphore up and down operations. </li>
303
+ * </ol>
304
+ *
305
+ * @param name the name of the metric.
306
+ * @param [options] the metric options.
307
+ */
308
+ createUpDownCounter<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): UpDownCounter<AttributesTypes>;
309
+ /**
310
+ * Creates a new `ObservableGauge` metric.
311
+ *
312
+ * The callback SHOULD be safe to be invoked concurrently.
313
+ *
314
+ * @param name the name of the metric.
315
+ * @param [options] the metric options.
316
+ */
317
+ createObservableGauge<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): ObservableGauge<AttributesTypes>;
318
+ /**
319
+ * Creates a new `ObservableCounter` metric.
320
+ *
321
+ * The callback SHOULD be safe to be invoked concurrently.
322
+ *
323
+ * @param name the name of the metric.
324
+ * @param [options] the metric options.
325
+ */
326
+ createObservableCounter<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): ObservableCounter<AttributesTypes>;
327
+ /**
328
+ * Creates a new `ObservableUpDownCounter` metric.
329
+ *
330
+ * The callback SHOULD be safe to be invoked concurrently.
331
+ *
332
+ * @param name the name of the metric.
333
+ * @param [options] the metric options.
334
+ */
335
+ createObservableUpDownCounter<AttributesTypes extends MetricAttributes = MetricAttributes>(name: string, options?: MetricOptions): ObservableUpDownCounter<AttributesTypes>;
336
+ /**
337
+ * Sets up a function that will be called whenever a metric collection is
338
+ * initiated.
339
+ *
340
+ * If the function is already in the list of callbacks for this Observable,
341
+ * the function is not added a second time.
342
+ *
343
+ * Only the associated observables can be observed in the callback.
344
+ * Measurements of observables that are not associated observed in the
345
+ * callback are dropped.
346
+ *
347
+ * @param callback the batch observable callback
348
+ * @param observables the observables associated with this batch observable callback
349
+ */
350
+ addBatchObservableCallback<AttributesTypes extends MetricAttributes = MetricAttributes>(callback: BatchObservableCallback<AttributesTypes>, observables: Observable<AttributesTypes>[]): void;
351
+ /**
352
+ * Removes a callback previously registered with {@link Meter.addBatchObservableCallback}.
353
+ *
354
+ * The callback to be removed is identified using a combination of the callback itself,
355
+ * and the set of the observables associated with it.
356
+ *
357
+ * @param callback the batch observable callback
358
+ * @param observables the observables associated with this batch observable callback
359
+ */
360
+ removeBatchObservableCallback<AttributesTypes extends MetricAttributes = MetricAttributes>(callback: BatchObservableCallback<AttributesTypes>, observables: Observable<AttributesTypes>[]): void;
361
+ }
362
+ interface TelemetryMiddlewareOptions {
363
+ /**
364
+ * The OpenTelemetry {@link Meter} used to record a send counter and duration histogram.
365
+ * When omitted, no metrics are recorded.
366
+ */
367
+ meter?: Meter;
368
+ /**
369
+ * The OpenTelemetry {@link Tracer} used to create a span per send. When omitted, no span
370
+ * is recorded (keeping `@opentelemetry/api` an optional peer dependency).
371
+ */
372
+ tracer?: Tracer;
373
+ }
374
+ /**
375
+ * Records an OpenTelemetry span plus a send counter and duration histogram for each send.
376
+ * Edge-safe: `@opentelemetry/api` is runtime-agnostic and both the tracer and meter are
377
+ * injected, so nothing is emitted until the host application supplies them.
378
+ * @param options Provide a `tracer` and/or `meter` to enable tracing and metrics.
379
+ * @returns A middleware.
380
+ */
381
+ declare const telemetryMiddleware: (options?: TelemetryMiddlewareOptions) => Middleware;
382
+ export { type CircuitBreakerMiddlewareOptions, type DedupeMiddlewareOptions, type LoggingMiddlewareOptions, type Middleware, type RateLimitMiddlewareOptions, type RetryMiddlewareOptions, type SendContext, type SuppressionMiddlewareOptions, type TelemetryMiddlewareOptions, circuitBreakerMiddleware, dedupeMiddleware, loggingMiddleware, rateLimitMiddleware, retryMiddleware, suppressionMiddleware, telemetryMiddleware };
@@ -0,0 +1 @@
1
+ import{circuitBreakerMiddleware as o}from"../packem_shared/circuitBreakerMiddleware-BlZN7SVT.js";import{dedupeMiddleware as i}from"../packem_shared/dedupeMiddleware-CQmPJd_h.js";import{loggingMiddleware as p}from"../packem_shared/loggingMiddleware-Cs6EDLcL.js";import{rateLimitMiddleware as a}from"../packem_shared/rateLimitMiddleware-DWmEYq-m.js";import{retryMiddleware as f}from"../packem_shared/retryMiddleware-uUJDcUoP.js";import{suppressionMiddleware as x}from"../packem_shared/suppressionMiddleware-CY-Qo1A_.js";import{telemetryMiddleware as s}from"../packem_shared/telemetryMiddleware-B1N4k171.js";import{composeMiddleware as g}from"../packem_shared/composeMiddleware-D6dR8DUS.js";export{o as circuitBreakerMiddleware,g as composeMiddleware,i as dedupeMiddleware,p as loggingMiddleware,a as rateLimitMiddleware,f as retryMiddleware,x as suppressionMiddleware,s as telemetryMiddleware};
@@ -0,0 +1 @@
1
+ class a{#e=new Map;append(e){const s=this.#e.get(e.messageId)??[];s.push(e),this.#e.set(e.messageId,s)}timeline(e){return this.#e.get(e)??[]}}export{a as default};
@@ -0,0 +1 @@
1
+ import{n as i}from"./id-C_FRCsUM.js";class d{#e=new Map;add(r){const e={...r,createdAt:Date.now(),id:r.id??i("inapp"),read:!1};return this.#e.set(e.id,e),Promise.resolve(e)}list(r,e={}){let t=[...this.#e.values()].filter(s=>s.subscriberId===r);return e.unreadOnly&&(t=t.filter(s=>!s.read)),t.sort((s,o)=>o.createdAt-s.createdAt),Promise.resolve(e.limit?t.slice(0,e.limit):t)}markRead(r){const e=this.#e.get(r);return e&&(e.read=!0),Promise.resolve()}markAllRead(r){for(const e of this.#e.values())e.subscriberId===r&&(e.read=!0);return Promise.resolve()}unreadCount(r){let e=0;for(const t of this.#e.values())t.subscriberId===r&&!t.read&&(e+=1);return Promise.resolve(e)}remove(r){return this.#e.delete(r),Promise.resolve()}}export{d as MemoryInAppStore};
@@ -0,0 +1 @@
1
+ import{n}from"./id-C_FRCsUM.js";class r{#e=[];#t=new Map;enqueue(t,s){const e={attempts:0,id:n("job"),message:t,scheduledAt:s?.scheduledAt};return this.#e.push(e),e.id}reserve(){const t=Date.now(),s=this.#e.findIndex(i=>(i.scheduledAt??0)<=t);if(s===-1)return;const e=this.#e.splice(s,1)[0];return e.attempts+=1,this.#t.set(e.id,e),e}ack(t){this.#t.delete(t)}retry(t,s=0){const e=this.#t.get(t);e&&(this.#t.delete(t),e.scheduledAt=Date.now()+s,this.#e.push(e))}size(){return this.#e.length}}export{r as default};
@@ -0,0 +1 @@
1
+ import d from"./NotificationError-DVfMJQ1u.js";import{composeMiddleware as h}from"./composeMiddleware-D6dR8DUS.js";const c=(a,s,t)=>{if(a.success&&a.data)return{channel:s,messageId:a.data.messageId,provider:a.data.provider??t,response:a.data.response,successful:!0,timestamp:a.data.timestamp};const{error:e}=a;let n;return e instanceof Error?n=e.message:e==null?n="Unknown error":typeof e=="string"?n=e:n=JSON.stringify(e),{channel:s,errorMessages:[n],provider:t,successful:!1}};class u{#s;#e=[];#t=new Set;#a;constructor(s){this.#s=s}use(s){return this.#e.push(s),this}setLogger(s){return this.#a=s,this}getProvider(s){return this.#s[s]}async sendToChannel(s,t){const e=this.#s[s];if(!e)return{channel:s,errorMessages:[`No provider registered for channel "${s}"`],successful:!1};try{await this.#n(e)}catch(r){return c({error:r,success:!1},s,e.id)}const n=async r=>e.send(r.payload),i=await h(this.#e,n)({channel:s,payload:t,provider:e.id});return c(i,s,e.id)}async send(s){const t=Object.keys(s);if(t.length===0)throw new d("notification","send() called with an empty message");return Promise.all(t.map(async e=>this.sendToChannel(e,s[e])))}async*sendMany(s,t={}){const e=Math.max(1,t.concurrency??10),n=[...s];let i=0;for(;i<n.length;){const r=n.slice(i,i+e);i+=e;const l=await Promise.all(r.map(async o=>this.send(o)));for(const o of l)yield o}}async initialize(){await Promise.all(Object.values(this.#s).map(async s=>this.#n(s)))}async shutdown(){await Promise.all(Object.values(this.#s).map(async s=>{const{shutdown:t}=s;t&&await t()}))}async#n(s){this.#t.has(s.id)||(await s.initialize(),this.#a?.debug(`[@visulima/notification] initialized provider "${s.id}"`),this.#t.add(s.id))}}const p=a=>new u(a);export{u as Notification,p as createNotification};
@@ -0,0 +1 @@
1
+ import{createRequire as h}from"node:module";const d=h(import.meta.url),t=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,m=o=>{if(typeof t<"u"&&t.versions&&t.versions.node){const[e,r]=t.versions.node.split(".").map(Number);if(e>22||e===22&&r>=3||e===20&&r>=16)return t.getBuiltinModule(o)}return d(o)},{createRequire:c}=m("node:module"),f=new Map([["Error",Error],["EvalError",EvalError],["RangeError",RangeError],["ReferenceError",ReferenceError],["SyntaxError",SyntaxError],["TypeError",TypeError],["URIError",URIError]]);typeof AggregateError<"u"&&f.set("AggregateError",AggregateError);const E=c(import.meta.url),i=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,y=o=>{if(typeof i<"u"&&i.versions&&i.versions.node){const[e,r]=i.versions.node.split(".").map(Number);if(e>22||e===22&&r>=3||e===20&&r>=16)return i.getBuiltinModule(o)}return E(o)};y("node:util");class b extends Error{loc;title;hint;type="VisulimaError";constructor({cause:e,hint:r,location:s,message:l,name:u,stack:p,title:g}){super(l,{cause:e}),this.title=g,this.name=u,this.stack=p??this.stack,this.loc=s,this.hint=r}setLocation(e){this.loc=e}setName(e){this.name=e}setMessage(e){this.message=e}setHint(e){this.hint=e}}const v=c(import.meta.url),n=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,a=o=>{if(typeof n<"u"&&n.versions&&n.versions.node){const[e,r]=n.versions.node.split(".").map(Number);if(e>22||e===22&&r>=3||e===20&&r>=16)return n.getBuiltinModule(o)}return v(o)};a("node:fs");a("node:path");a("node:url");class T extends b{component;code;constructor(e,r,s){super({cause:s?.cause,hint:s?.hint,message:`[@visulima/notification] [${e}] ${r}`,name:"NotificationError",title:`Notification ${e} Error`}),this.component=e,this.code=s?.code}}export{T as default};
@@ -0,0 +1 @@
1
+ class r{#t={};#i;#s;sms(t){return this.#t.sms=t,this}push(t){return this.#t.push=t,this}chat(t){return this.#t.chat=t,this}inApp(t){return this.#t.inapp=t,this}webhook(t){return this.#t.webhook=t,this}email(t){return this.#t.email=t,this}metadata(t){return this.#i=t,this}idempotencyKey(t){return this.#s=t,this}build(){const t=this.#i,s=this.#s;if(t===void 0&&s===void 0)return{...this.#t};const e={},o=Object.keys(this.#t);for(const h of o){const n=this.#t[h];if(n!==void 0){const i={};t!==void 0&&(i.metadata=t),s!==void 0&&(i.idempotencyKey=s),Object.assign(i,n),e[h]=i}}return e}}const c=()=>new r;export{r as NotificationMessageBuilder,c as createNotificationMessage};
@@ -0,0 +1 @@
1
+ import s from"./NotificationError-DVfMJQ1u.js";class a extends s{constructor(o,e){const r=Array.isArray(e)?`Missing required options: ${e.map(i=>`'${i}'`).join(", ")}`:`Missing required option: '${e}'`;super(o,r,{hint:Array.isArray(e)?`Please provide the following required options: ${e.map(i=>`'${i}'`).join(", ")}`:`Please provide the required option: '${e}'`}),this.name="RequiredOptionError"}}export{a as default};
@@ -0,0 +1 @@
1
+ import{n as c}from"./id-C_FRCsUM.js";class h{#t;#s;constructor(t,a="notification:inapp"){this.#t=t,this.#s=a}async add(t){const a={...t,createdAt:Date.now(),id:t.id??c("inapp"),read:!1};return await this.#t.setItem(this.#a(a.id),a),await this.#n(a.subscriberId,a.id),a}async list(t,a={}){const i=await this.#r(t),s=(a.unreadOnly?i.filter(e=>!e.read):i).toSorted((e,n)=>n.createdAt-e.createdAt);return a.limit?s.slice(0,a.limit):s}async markRead(t){const a=await this.#t.getItem(this.#a(t));a&&(a.read=!0,await this.#t.setItem(this.#a(t),a))}async markAllRead(t){const a=await this.#i(t);await Promise.all(a.map(async i=>this.markRead(i)))}async unreadCount(t){return(await this.#r(t)).filter(a=>!a.read).length}async remove(t){const a=await this.#t.getItem(this.#a(t));await this.#t.removeItem(this.#a(t)),a&&await this.#c(a.subscriberId,t)}#a(t){return`${this.#s}:item:${t}`}#e(t){return`${this.#s}:index:${t}`}async#i(t){return await this.#t.getItem(this.#e(t))??[]}async#r(t){const a=await this.#i(t);return(await Promise.all(a.map(async i=>await this.#t.getItem(this.#a(i))))).filter(i=>i!==null)}async#n(t,a){const i=await this.#i(t);i.includes(a)||(i.push(a),await this.#t.setItem(this.#e(t),i))}async#c(t,a){const i=(await this.#i(t)).filter(s=>s!==a);await this.#t.setItem(this.#e(t),i)}}const d=(r,t)=>new h(r,t);export{h as UnstorageInAppStore,d as createUnstorageInAppStore};
@@ -0,0 +1 @@
1
+ import{createRequire as I}from"node:module";import g from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as j}from"./defineProvider-C9q-7iwt.js";import{t as k}from"./credentials-CG0zkn-W.js";import{a as N}from"./sms-CU-OZvNU.js";const S=I(import.meta.url),f=typeof globalThis<"u"&&typeof globalThis.process<"u"?globalThis.process:process,y=o=>{if(typeof f<"u"&&f.versions&&f.versions.node){const[t,r]=f.versions.node.split(".").map(Number);if(t>22||t===22&&r>=3||t===20&&r>=16)return f.getBuiltinModule(o)}return S(o)},{sign:T,createPrivateKey:$}=y("node:crypto"),{connect:P}=y("node:http2"),J="https://api.push.apple.com",K="https://api.sandbox.push.apple.com",O=3e3*1e3,R=200,h=o=>Buffer.from(o,"utf8").toString("base64url"),q=(o,t,r)=>{const l=h(JSON.stringify({alg:"ES256",kid:o.keyId,typ:"JWT"})),c=h(JSON.stringify({iat:r,iss:o.teamId})),u=`${l}.${c}`,n=T("sha256",Buffer.from(u,"utf8"),{dsaEncoding:"ieee-p1363",key:t}).toString("base64url");return`${u}.${n}`},z=j(o=>{const t=o??{};if(!t.teamId)throw new g("apns","teamId");if(!t.keyId)throw new g("apns","keyId");if(!t.signingKey)throw new g("apns","signingKey");if(!t.bundleId)throw new g("apns","bundleId");const r=t.production?J:K;let l,c,u=0,n;const b=()=>(l??=$({format:"pem",key:t.signingKey}),l),w=()=>{const e=Date.now();return(!c||e-u>O)&&(c=q(t,b(),Math.floor(e/1e3)),u=e),c},_=()=>((!n||n.closed||n.destroyed)&&(n=P(r),n.on("error",e=>{t.logger?.warn(`[@visulima/notification] [apns] HTTP/2 session error: ${e.message}`)})),n),v=async(e,m)=>new Promise(a=>{const i=_().request({":method":"POST",":path":`/3/device/${e}`,"apns-topic":t.bundleId,authorization:`bearer ${w()}`,"content-type":"application/json"});let d=0,p="";i.setEncoding("utf8"),i.on("response",s=>{d=s[":status"]??0}),i.on("data",s=>{p+=s}),i.on("error",s=>{a({error:s.message,id:e,status:"failed"})}),i.on("end",()=>{if(d===R){a({id:e,messageId:e,status:"sent"});return}let s=`HTTP ${String(d)}`;if(p)try{s=JSON.parse(p).reason??s}catch{s=p}a({error:s,id:e,status:"failed"})}),i.end(m)});return{channel:"push",endpoint:r,features:{batchSending:!1,media:!0,richContent:!0},id:"apns",initialize:()=>{},isAvailable:()=>!0,options:t,send:async e=>{const m=k(e.to),a={alert:{body:e.body,title:e.title}};e.sound!==void 0&&(a.sound=e.sound),e.badge!==void 0&&(a.badge=e.badge);const i=JSON.stringify({...e.data,aps:a}),d=[];for(const p of m)d.push(await v(p,i));return N("push","apns",d)},shutdown:()=>{n&&!n.closed&&n.close(),n=void 0}}});export{z as default};
@@ -0,0 +1 @@
1
+ import u from"./NotificationError-DVfMJQ1u.js";const p=(o={})=>{const i=o.threshold??5,n=o.resetTimeout??3e4;let r=0,s=0,e="closed";return async(t,a)=>{if(e==="open")if(Date.now()-s>=n)e="half-open";else return{error:new u("circuit-breaker",`Circuit open for "${t.provider}"`),success:!1};const c=await a(t);return c.success?(r=0,e="closed"):(r+=1,r>=i&&(e="open",s=Date.now())),c}};export{p as circuitBreakerMiddleware};
@@ -0,0 +1 @@
1
+ const n=(o,t)=>{let e=t;for(const r of o.toReversed()){const s=e;e=c=>r(c,s)}return e};export{n as composeMiddleware};
@@ -0,0 +1 @@
1
+ const l=async e=>new Promise(n=>{setTimeout(n,e)}),w=(e,n,s={})=>{const o=s.maxAttempts??5,i=s.pollInterval??1e3,u=s.backoff??(a=>Math.min(3e4,1e3*2**(a-1)));let t=!1;const r=async()=>{const a=await e.reserve();if(!a)return!1;const c=await n.send(a.message);return c.some(m=>!m.successful)?a.attempts>=o?(await e.ack(a.id),s.onDrop?.(a,c)):await e.retry(a.id,u(a.attempts)):await e.ack(a.id),!0},f=async()=>{for(;t;)await r()||await l(i)};return{drain:async()=>{for(;await r(););},start:()=>{t||(t=!0,f().catch(()=>{t=!1}))},stop:()=>{t=!1}}};export{w as createQueueWorker};
@@ -0,0 +1 @@
1
+ const s=(t,a)=>`Basic ${btoa(`${t}:${a}`)}`,i=t=>Array.isArray(t)?t:[t];export{s as b,i as t};
@@ -0,0 +1 @@
1
+ const i=(s={})=>{const r=s.ttl??6e4,t=new Map;return async(e,a)=>{const n=s.keyFn?s.keyFn(e):e.payload.idempotencyKey;if(!n)return a(e);const o=Date.now();for(const[d,p]of t)p<o&&t.delete(d);if(t.has(n))return{data:{channel:e.channel,messageId:`deduped:${n}`,provider:e.provider,sent:!1,timestamp:new Date},success:!0};const c=await a(e);return c.success&&t.set(n,o+r),c}};export{i as dedupeMiddleware};
@@ -0,0 +1 @@
1
+ const o=e=>e;export{o as defineProvider};
@@ -0,0 +1 @@
1
+ import s from"./NotificationError-DVfMJQ1u.js";import c from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as l}from"./defineProvider-C9q-7iwt.js";import{r as m}from"./http-BMYcUNBU.js";import{n as u}from"./id-C_FRCsUM.js";const k=l(a=>{const e=a??{};if(!e.webhookUrl)throw new c("discord","webhookUrl");const i=e.retries??3,d=e.timeout??3e4,n=e.webhookUrl.includes("?")?`${e.webhookUrl}&wait=true`:`${e.webhookUrl}?wait=true`;return{channel:"chat",endpoint:e.webhookUrl,features:{batchSending:!1,richContent:!0},id:"discord",initialize:()=>{},isAvailable:()=>!!e.webhookUrl,options:e,send:async r=>{const o={content:r.text,embeds:r.blocks,username:e.username};r.threadId&&(o.thread_id=r.threadId);const t=await m(n,{body:JSON.stringify(o),headers:{"Content-Type":"application/json"},method:"POST",timeout:d},i);return!t.success||!t.data?{error:new s("discord",t.error instanceof Error?t.error.message:"Request failed"),success:!1}:t.data.status>=400?{error:new s("discord",t.data.body.message??`HTTP ${String(t.data.status)}`),success:!1}:{data:{channel:"chat",messageId:t.data.body.id??u("discord"),provider:"discord",sent:!0,timestamp:new Date},success:!0}},validateCredentials:()=>!!e.webhookUrl}});export{k as default};
@@ -0,0 +1 @@
1
+ import n from"./NotificationError-DVfMJQ1u.js";const c=(t,r={})=>{const a=r.id??"email";return{channel:"email",features:{attachments:!0,batchSending:!0,richContent:!0,templates:!0,tracking:!0},id:a,initialize:()=>{},isAvailable:()=>!0,send:async s=>{const e=await t.send(s);return!e.success||!e.data?{error:new n(a,e.error instanceof Error?e.error.message:"Email send failed",{cause:e.error}),success:!1}:{data:{channel:"email",messageId:e.data.messageId,provider:e.data.provider??a,response:e.data.response,sent:e.data.sent??!0,timestamp:e.data.timestamp??new Date},success:!0}}}};export{c as emailChannel};
@@ -0,0 +1 @@
1
+ import d from"./NotificationError-DVfMJQ1u.js";import{defineProvider as x}from"./defineProvider-C9q-7iwt.js";import{t as T}from"./credentials-CG0zkn-W.js";import{r as w}from"./http-BMYcUNBU.js";import{n as A}from"./id-C_FRCsUM.js";const $="https://exp.host",R=x(l=>{const t=l??{},u=t.endpoint??$,f=t.retries??3,h=t.timeout??3e4,g=`${u}/--/api/v2/push/send`;return{channel:"push",endpoint:u,features:{batchSending:!0,media:!0,richContent:!0},id:"expo",initialize:()=>{},isAvailable:()=>!0,options:t,send:async s=>{const p=T(s.to),y=p.map(r=>({badge:s.badge,body:s.body,data:s.data,sound:s.sound??"default",title:s.title,to:r})),c={"Content-Type":"application/json"};t.accessToken&&(c.Authorization=`Bearer ${t.accessToken}`);const e=await w(g,{body:JSON.stringify(y),headers:c,method:"POST",timeout:h},f);if(!e.success||!e.data)return{error:new d("expo",e.error instanceof Error?e.error.message:"Request failed"),success:!1};if(e.data.status>=400)return{error:new d("expo",`HTTP ${String(e.data.status)}`),success:!1};const a=e.data.body.data;let n;Array.isArray(a)?n=a:n=a?[a]:[];const i=p.map((r,b)=>{const o=n[b];return o?.status==="error"?{error:o.details?.error??o.message??"error",id:r,status:"failed"}:{id:r,messageId:o?.id,status:"sent"}}),m=i.filter(r=>r.status==="sent");return m.length===0?{error:new d("expo",i[0]?.error??"All tokens failed"),success:!1}:{data:{channel:"push",messageId:m[0]?.messageId??A("expo"),provider:"expo",recipients:i,sent:!0,timestamp:new Date},success:!0}}}});export{R as default};
@@ -0,0 +1 @@
1
+ import l from"./NotificationError-DVfMJQ1u.js";const d=(r,o={})=>{if(r.length===0)throw new l("failover","At least one provider is required");const n=o.id??"failover";return{channel:r[0].channel,id:n,initialize:async()=>{await Promise.all(r.map(async e=>e.initialize()))},isAvailable:async()=>(await Promise.all(r.map(async e=>e.isAvailable()))).some(Boolean),send:async e=>{const s=[];for(const a of r){const i=await a.send(e);if(i.success)return i;const t=i.error instanceof Error?i.error.message:String(i.error);s.push(`${a.id}: ${t}`),o.logger?.warn(`[@visulima/notification] [${n}] provider "${a.id}" failed, trying next`)}return{error:new l(n,`All ${String(r.length)} providers failed: ${s.join("; ")}`),success:!1}}}};export{d as failoverProvider};
@@ -0,0 +1 @@
1
+ import c from"./NotificationError-DVfMJQ1u.js";import d from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as h}from"./defineProvider-C9q-7iwt.js";import{t as y}from"./credentials-CG0zkn-W.js";import{r as T}from"./http-BMYcUNBU.js";const I=h(m=>{const e=m??{};if(!e.projectId)throw new d("fcm","projectId");if(!e.accessToken&&!e.getAccessToken)throw new d("fcm",["accessToken","getAccessToken"]);const i=e.endpoint??"https://fcm.googleapis.com",f=e.retries??3,u=e.timeout??3e4,p=`${i}/v1/projects/${e.projectId}/messages:send`,l=s=>{if(s)return Object.fromEntries(Object.entries(s).map(([r,o])=>[r,typeof o=="string"?o:JSON.stringify(o)]))},g=async(s,r,o)=>{const a={data:l(r.data),notification:{body:r.body,image:r.imageUrl,title:r.title},token:s},t=await T(p,{body:JSON.stringify({message:a}),headers:{Authorization:`Bearer ${o}`,"Content-Type":"application/json"},method:"POST",timeout:u},f);return!t.success||!t.data?{error:t.error instanceof Error?t.error.message:"Request failed",id:s,status:"failed"}:t.data.status>=400?{error:t.data.body.error?.message??`HTTP ${String(t.data.status)}`,id:s,status:"failed"}:{id:s,messageId:t.data.body.name,status:"sent"}};return{channel:"push",endpoint:i,features:{batchSending:!1,media:!0,richContent:!0},id:"fcm",initialize:()=>{},isAvailable:()=>!!(e.projectId&&(e.accessToken??e.getAccessToken)),options:e,send:async s=>{let r;try{r=e.getAccessToken?await e.getAccessToken():e.accessToken}catch(n){return{error:new c("fcm","Failed to obtain access token",{cause:n}),success:!1}}const o=y(s.to),a=[];for(const n of o)a.push(await g(n,s,r));const t=a.filter(n=>n.status==="sent");return t.length===0?{error:new c("fcm",a[0]?.error??"All tokens failed"),success:!1}:{data:{channel:"push",messageId:t[0]?.messageId??"",provider:"fcm",recipients:a,sent:!0,timestamp:new Date},success:!0}}}});export{I as default};
@@ -0,0 +1 @@
1
+ const a=t=>{try{const r=JSON.parse(t);return typeof r=="object"&&r!==null&&!Array.isArray(r)?r:void 0}catch{return}},c=(t,r)=>{const s=r.toLowerCase();for(const o of Object.keys(t))if(o.toLowerCase()===s){const e=t[o];return Array.isArray(e)?e[0]:e}};export{c as getHeader,a as tryParseObject};
@@ -0,0 +1 @@
1
+ import{g as o,i as r,b as i}from"./webcrypto-bY7wJCB5.js";const l=300,c=async(a,t,e)=>i(await r(a,t,e)),f=async(a,t,e)=>o(await r(a,t,e)),h=(a,t)=>{if(a.length!==t.length)return!1;let e=0;for(let n=0;n<a.length;n+=1)e|=(a.codePointAt(n)??0)^(t.codePointAt(n)??0);return e===0},m=(a,t)=>{if(a===void 0)return!1;const e=Number.parseInt(a,10);if(Number.isNaN(e))return!1;const n=Math.floor(Date.now()/1e3);return Math.abs(n-e)<=t};export{l as REPLAY_WINDOW_SECONDS,f as hmacBase64,c as hmacHex,m as isWithinReplayWindow,h as timingSafeEqual};
@@ -0,0 +1 @@
1
+ const n=async(e,s={})=>{const u=new AbortController,c=s.timeout??3e4,a=setTimeout(()=>{u.abort()},c);try{const t=await fetch(e,{body:s.body,headers:s.headers,method:s.method??"GET",signal:u.signal}),r=await t.text();let o=r;if(r.length>0)try{o=JSON.parse(r)}catch{o=r}const i={};return t.headers.forEach((d,h)=>{i[h]=d}),{data:{body:o,headers:i,status:t.status,statusText:t.statusText},success:!0}}catch(t){return{error:t,success:!1}}finally{clearTimeout(a)}},l=e=>e===408||e===429||e>=500,m=async(e,s={},u=3,c=250)=>{let a=await n(e,s);for(let t=0;t<u;t+=1){if(!(!a.success||a.data!==void 0&&l(a.data.status)))return a;const r=c*2**t+Math.floor(Math.random()*c);await new Promise(o=>setTimeout(o,r)),a=await n(e,s)}return a};export{n as m,m as r};
@@ -0,0 +1 @@
1
+ let n=0;const t=o=>{n+=1;const r=globalThis.crypto;return r?.randomUUID?`${o}-${r.randomUUID()}`:`${o}-${String(n)}-${Math.floor(Math.random()*1e9).toString(36)}`};export{t as n};
@@ -0,0 +1 @@
1
+ import{MemoryInAppStore as r}from"./MemoryInAppStore-48qlrDCx.js";const o=(t={})=>{const a=t.id??"inapp",n=t.store??new r;return{channel:"inapp",features:{richContent:!0},getInstance:()=>n,id:a,initialize:()=>{},isAvailable:()=>!0,send:async e=>{const i=await n.add({actions:e.actions,body:e.body,data:e.data,subscriberId:e.to,title:e.title});return{data:{channel:"inapp",messageId:i.id,provider:a,sent:!0,timestamp:new Date(i.createdAt)},success:!0}}}};export{o as inAppProvider};
@@ -0,0 +1 @@
1
+ const s=(n={})=>{const i=n.logger??console;return async(r,o)=>{i.debug(`[@visulima/notification] sending via "${r.provider}" (${r.channel})`);const e=await o(r);if(e.success)i.debug(`[@visulima/notification] sent ${e.data?.messageId??""} via "${r.provider}"`);else{const a=e.error instanceof Error?e.error.message:String(e.error);i.warn(`[@visulima/notification] send failed via "${r.provider}": ${a}`)}return e}};export{s as loggingMiddleware};
@@ -0,0 +1 @@
1
+ import t from"./NotificationError-DVfMJQ1u.js";import g from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as l}from"./defineProvider-C9q-7iwt.js";import{t as y}from"./credentials-CG0zkn-W.js";import{r as b}from"./http-BMYcUNBU.js";import{b as h}from"./sms-CU-OZvNU.js";const v="https://rest.messagebird.com",$=l(n=>{const e=n??{};if(!e.accessKey)throw new g("messagebird","accessKey");const i=e.endpoint??v,d=e.retries??3,c=e.timeout??3e4,m=`${i}/messages`;return{channel:"sms",endpoint:i,features:{batchSending:!0,deliveryReceipts:!0,media:!1},id:"messagebird",initialize:()=>{},isAvailable:()=>!!e.accessKey,options:e,send:async r=>{const a=y(r.to),o=r.from??e.from;if(!o)return{error:new t("messagebird","Missing originator: provide `from` on the payload or provider config"),success:!1};const s=await b(m,{body:JSON.stringify({body:r.text,originator:o,recipients:a}),headers:{Authorization:`AccessKey ${e.accessKey}`,"Content-Type":"application/json"},method:"POST",timeout:c},d);if(!s.success||!s.data)return{error:new t("messagebird",s.error instanceof Error?s.error.message:"Request failed"),success:!1};if(s.data.status>=400)return{error:new t("messagebird",s.data.body.errors?.[0]?.description??`HTTP ${String(s.data.status)}`),success:!1};const f=s.data.body.id??"",p=a.map(u=>({id:u,messageId:f,status:"sent"}));return h("messagebird",p)},validateCredentials:()=>!!e.accessKey}});export{$ as default};
@@ -0,0 +1 @@
1
+ import c from"./NotificationError-DVfMJQ1u.js";import{defineProvider as d}from"./defineProvider-C9q-7iwt.js";let n=0;const p=d((e={})=>{const t=[],s=e.channel??"sms",r=e.id??"mock",o={clear:()=>{t.length=0},last:()=>t.at(-1),sent:t};return{channel:s,getInstance:()=>o,id:r,initialize:()=>{},isAvailable:()=>!0,send:l=>{if(e.failWith!==void 0)return{error:new c(r,e.failWith),success:!1};n+=1;const a=new Date,i=`mock-${String(n)}`;return t.push({messageId:i,payload:l,timestamp:a}),{data:{channel:s,messageId:i,provider:r,sent:!0,timestamp:a},success:!0}},validateCredentials:()=>!0}});export{p as mockProvider};
@@ -0,0 +1 @@
1
+ import r from"./NotificationError-DVfMJQ1u.js";import m from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as c}from"./defineProvider-C9q-7iwt.js";import{r as d}from"./http-BMYcUNBU.js";import{n as l}from"./id-C_FRCsUM.js";const b=c(a=>{const e=a??{};if(!e.webhookUrl)throw new m("msteams","webhookUrl");const o=e.retries??3,n=e.timeout??3e4;return{channel:"chat",endpoint:e.webhookUrl,features:{batchSending:!1,richContent:!0},id:"msteams",initialize:()=>{},isAvailable:()=>!!e.webhookUrl,options:e,send:async s=>{const i=s.blocks??{"@context":"https://schema.org/extensions","@type":"MessageCard",text:s.text},t=await d(e.webhookUrl,{body:JSON.stringify(i),headers:{"Content-Type":"application/json"},method:"POST",timeout:n},o);return!t.success||!t.data?{error:new r("msteams",t.error instanceof Error?t.error.message:"Request failed"),success:!1}:t.data.status>=400?{error:new r("msteams",`HTTP ${String(t.data.status)}: ${t.data.body}`),success:!1}:{data:{channel:"chat",messageId:l("msteams"),provider:"msteams",sent:!0,timestamp:new Date},success:!0}},validateCredentials:()=>!!e.webhookUrl}});export{b as default};
@@ -0,0 +1,87 @@
1
+ import { M as Middleware } from "./types.d-CximoA8M.js";
2
+ import { P as Provider } from "./provider.d-BQAGriz6.js";
3
+ import { b as ChatPayload, E as EmailChannelPayload, I as InAppPayload, P as PushPayload, S as SmsPayload, W as WebhookPayload, C as ChannelType, c as Receipt } from "./types.d-GUzX1jTk.js";
4
+ /**
5
+ * Maps each channel to its payload type.
6
+ */
7
+ interface ChannelPayloadMap {
8
+ chat: ChatPayload;
9
+ email: EmailChannelPayload;
10
+ inapp: InAppPayload;
11
+ push: PushPayload;
12
+ sms: SmsPayload;
13
+ webhook: WebhookPayload;
14
+ }
15
+ /**
16
+ * A multi-channel message: a payload per channel to deliver on.
17
+ */
18
+ type NotificationMessage = { [K in ChannelType]?: ChannelPayloadMap[K] };
19
+ /**
20
+ * Providers registered per channel.
21
+ */
22
+ type NotificationProviders = { [K in ChannelType]?: Provider<unknown, ChannelPayloadMap[K]> };
23
+ interface SendManyOptions {
24
+ /** Maximum number of messages delivered concurrently (default 10). */
25
+ concurrency?: number;
26
+ }
27
+ /**
28
+ * The high-level multi-channel notification facade. Holds a provider per channel,
29
+ * a shared middleware chain and dispatches messages across channels.
30
+ */
31
+ declare class Notification {
32
+ #private;
33
+ constructor(providers: NotificationProviders);
34
+ /**
35
+ * Registers a middleware. First registered runs outermost.
36
+ * @param middleware The middleware to add.
37
+ * @returns This instance for chaining.
38
+ */
39
+ use(middleware: Middleware): this;
40
+ /**
41
+ * Sets a logger used by the facade.
42
+ * @param logger The console-like logger.
43
+ * @returns This instance for chaining.
44
+ */
45
+ setLogger(logger: Console): this;
46
+ /**
47
+ * Returns the provider registered for a channel, if any.
48
+ * @param channel The channel whose registered provider should be looked up.
49
+ * @returns The provider or undefined.
50
+ */
51
+ getProvider(channel: ChannelType): Provider | undefined;
52
+ /**
53
+ * Sends a payload on a single channel.
54
+ * @param channel The target channel.
55
+ * @param payload The channel-specific payload to deliver.
56
+ * @returns A receipt describing the outcome.
57
+ */
58
+ sendToChannel<K extends ChannelType>(channel: K, payload: ChannelPayloadMap[K]): Promise<Receipt>;
59
+ /**
60
+ * Sends a multi-channel message, delivering each present channel in parallel.
61
+ * @param message The multi-channel message.
62
+ * @returns One receipt per attempted channel.
63
+ */
64
+ send(message: NotificationMessage): Promise<Receipt[]>;
65
+ /**
66
+ * Sends many messages with bounded concurrency, yielding the receipts for each.
67
+ * @param messages The messages to send.
68
+ * @param options Concurrency options.
69
+ * @yields The receipts for each message, in completion order.
70
+ */
71
+ sendMany(messages: Iterable<NotificationMessage>, options?: SendManyOptions): AsyncGenerator<Receipt[]>;
72
+ /**
73
+ * Initializes every registered provider.
74
+ */
75
+ initialize(): Promise<void>;
76
+ /**
77
+ * Shuts down every registered provider that supports it.
78
+ */
79
+ shutdown(): Promise<void>;
80
+ }
81
+ /**
82
+ * Creates a {@link Notification} facade from a map of channel providers.
83
+ * @param providers Providers keyed by channel.
84
+ * @returns A configured notification facade.
85
+ */
86
+ declare const createNotification: (providers: NotificationProviders) => Notification;
87
+ export { ChannelPayloadMap as C, Notification as N, SendManyOptions as S, NotificationMessage as a, NotificationProviders as b, createNotification as c };
@@ -0,0 +1 @@
1
+ const i="notification.send",a=(e,o={})=>{const{tracer:t}=o;return{...e,send:async s=>{if(!t)return e.send(s);const n=t.startSpan(i,{attributes:{"notification.channel":e.channel,"notification.provider":e.id}});try{const r=await e.send(s);if(!r.success){const c=r.error instanceof Error?r.error.message:String(r.error);n.setStatus({code:2,message:c})}return r}catch(r){throw n.recordException(r),n.setStatus({code:2,message:r instanceof Error?r.message:String(r)}),r}finally{n.end()}}}};export{a as otelProvider};
@@ -0,0 +1 @@
1
+ import o from"./NotificationError-DVfMJQ1u.js";import d from"./RequiredOptionError-CuL42XRq.js";import{defineProvider as w}from"./defineProvider-C9q-7iwt.js";import{b as y,t as T}from"./credentials-CG0zkn-W.js";import{r as b}from"./http-BMYcUNBU.js";import{b as I}from"./sms-CU-OZvNU.js";const S="https://api.plivo.com",q=w(p=>{const e=p??{};if(!e.authId)throw new d("plivo","authId");if(!e.authToken)throw new d("plivo","authToken");const a=e.endpoint??S,m=e.retries??3,c=e.timeout??3e4,f=`${a}/v1/Account/${e.authId}/Message/`,l=y(e.authId,e.authToken);return{channel:"sms",endpoint:a,features:{batchSending:!0,deliveryReceipts:!0,media:!0},id:"plivo",initialize:()=>{},isAvailable:()=>!!(e.authId&&e.authToken),options:e,send:async s=>{const r=T(s.to),i=s.from??e.from;if(!i)return{error:new o("plivo","Missing sender: provide `from` on the payload or provider config"),success:!1};const t=await b(f,{body:JSON.stringify({dst:r.join("<"),src:i,text:s.text}),headers:{Authorization:l,"Content-Type":"application/json"},method:"POST",timeout:c},m);if(!t.success||!t.data)return{error:new o("plivo",t.error instanceof Error?t.error.message:"Request failed"),success:!1};if(t.data.status>=400)return{error:new o("plivo",t.data.body.error??`HTTP ${String(t.data.status)}`),success:!1};const{body:n}=t.data,h=n.message_uuid?.[0]??"",u=r.map((v,g)=>({id:v,messageId:n.message_uuid?.[g],status:"sent"}));return I("plivo",u.length>0?u:[{id:r[0]??"",messageId:h,status:"sent"}])},validateCredentials:()=>!!(e.authId&&e.authToken)}});export{q as default};