@holo-js/notifications 0.1.3

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.
@@ -0,0 +1,126 @@
1
+ // src/contracts.ts
2
+ import { defineNotificationsConfig } from "@holo-js/config";
3
+ var HOLO_NOTIFICATION_DEFINITION_MARKER = /* @__PURE__ */ Symbol.for("holo-js.notifications.definition");
4
+ var BUILT_IN_NOTIFICATION_CHANNELS = ["email", "database", "broadcast"];
5
+ function isObject(value) {
6
+ return !!value && typeof value === "object" && !Array.isArray(value);
7
+ }
8
+ function normalizeOptionalString(value, label) {
9
+ if (typeof value === "undefined") {
10
+ return void 0;
11
+ }
12
+ const normalized = value.trim();
13
+ if (!normalized) {
14
+ throw new Error(`[@holo-js/notifications] ${label} must be a non-empty string when provided.`);
15
+ }
16
+ return normalized;
17
+ }
18
+ function normalizeDelayValue(value, label) {
19
+ if (typeof value === "number") {
20
+ if (!Number.isFinite(value) || value < 0) {
21
+ throw new Error(`[@holo-js/notifications] ${label} must be a finite number greater than or equal to 0.`);
22
+ }
23
+ return value;
24
+ }
25
+ if (!(value instanceof Date) || Number.isNaN(value.getTime())) {
26
+ throw new Error(`[@holo-js/notifications] ${label} dates must be valid Date instances.`);
27
+ }
28
+ return value;
29
+ }
30
+ function normalizeOptionalBoolean(value, label) {
31
+ if (typeof value === "undefined") {
32
+ return void 0;
33
+ }
34
+ if (typeof value !== "boolean") {
35
+ throw new Error(`[@holo-js/notifications] ${label} must be a boolean when provided.`);
36
+ }
37
+ return value;
38
+ }
39
+ function isNotificationDefinition(value) {
40
+ return !!value && typeof value === "object" && "via" in value && typeof value.via === "function" && "build" in value && isObject(value.build);
41
+ }
42
+ function normalizeQueueOptions(value) {
43
+ if (typeof value === "undefined") {
44
+ return void 0;
45
+ }
46
+ return Object.freeze({
47
+ connection: normalizeOptionalString(value.connection, "Notification queue connection"),
48
+ queue: normalizeOptionalString(value.queue, "Notification queue name"),
49
+ ...typeof value.delay === "undefined" ? {} : { delay: normalizeDelayValue(value.delay, "Notification queue delay") },
50
+ ...typeof normalizeOptionalBoolean(value.afterCommit, "Notification queue afterCommit") === "undefined" ? {} : { afterCommit: value.afterCommit }
51
+ });
52
+ }
53
+ function normalizeDelayConfig(value) {
54
+ if (typeof value === "undefined" || typeof value === "function") {
55
+ return value;
56
+ }
57
+ if (typeof value === "number" || value instanceof Date) {
58
+ return normalizeDelayValue(value, "Notification delay");
59
+ }
60
+ if (!isObject(value)) {
61
+ throw new Error("[@holo-js/notifications] Notification delay must be a number, Date, plain object, or function.");
62
+ }
63
+ return Object.freeze(Object.fromEntries(Object.entries(value).map(([channel, delay]) => {
64
+ const normalizedChannel = normalizeOptionalString(channel, "Notification delay channel");
65
+ return [normalizedChannel, normalizeDelayValue(delay, `Notification delay for channel "${channel}"`)];
66
+ })));
67
+ }
68
+ function normalizeNotificationDefinition(definition) {
69
+ if (!isNotificationDefinition(definition)) {
70
+ throw new Error("[@holo-js/notifications] Notifications must define via() and build.");
71
+ }
72
+ const buildEntries = Object.entries(definition.build);
73
+ if (buildEntries.length === 0) {
74
+ throw new Error("[@holo-js/notifications] Notifications must define at least one channel payload builder.");
75
+ }
76
+ const build = Object.freeze(Object.fromEntries(buildEntries.map(([channel, factory]) => {
77
+ const normalizedChannel = normalizeOptionalString(channel, "Notification channel name");
78
+ if (typeof factory !== "function") {
79
+ throw new Error(`[@holo-js/notifications] Notification channel "${normalizedChannel}" must be a function.`);
80
+ }
81
+ return [normalizedChannel, factory];
82
+ })));
83
+ const queue = typeof definition.queue === "function" ? definition.queue : typeof definition.queue === "boolean" ? definition.queue : normalizeQueueOptions(definition.queue);
84
+ const normalized = {
85
+ ...definition,
86
+ ...typeof definition.type === "undefined" ? {} : { type: normalizeOptionalString(definition.type, "Notification type") },
87
+ build,
88
+ queue,
89
+ delay: normalizeDelayConfig(definition.delay)
90
+ };
91
+ Object.defineProperty(normalized, HOLO_NOTIFICATION_DEFINITION_MARKER, {
92
+ value: true,
93
+ enumerable: false
94
+ });
95
+ return Object.freeze(normalized);
96
+ }
97
+ function defineNotification(definition) {
98
+ return normalizeNotificationDefinition(definition);
99
+ }
100
+ function createAnonymousNotificationTarget(routes) {
101
+ return Object.freeze({
102
+ anonymous: true,
103
+ routes: Object.freeze({ ...routes })
104
+ });
105
+ }
106
+ var notificationsInternals = {
107
+ BUILT_IN_NOTIFICATION_CHANNELS,
108
+ HOLO_NOTIFICATION_DEFINITION_MARKER,
109
+ createAnonymousNotificationTarget,
110
+ isObject,
111
+ normalizeDelayConfig,
112
+ normalizeDelayValue,
113
+ normalizeNotificationDefinition,
114
+ normalizeOptionalBoolean,
115
+ normalizeOptionalString,
116
+ normalizeQueueOptions
117
+ };
118
+
119
+ export {
120
+ defineNotificationsConfig,
121
+ isNotificationDefinition,
122
+ normalizeNotificationDefinition,
123
+ defineNotification,
124
+ createAnonymousNotificationTarget,
125
+ notificationsInternals
126
+ };
@@ -0,0 +1,212 @@
1
+ import { NormalizedHoloNotificationsConfig } from '@holo-js/config';
2
+ export { defineNotificationsConfig } from '@holo-js/config';
3
+
4
+ type NotificationJsonPrimitive = string | number | boolean | null;
5
+ type NotificationJsonValue = NotificationJsonPrimitive | readonly NotificationJsonValue[] | {
6
+ readonly [key: string]: NotificationJsonValue;
7
+ };
8
+ type NotificationDelayValue = number | Date;
9
+ declare function isObject(value: unknown): value is Record<string, unknown>;
10
+ declare function normalizeOptionalString(value: string | undefined, label: string): string | undefined;
11
+ declare function normalizeDelayValue(value: NotificationDelayValue, label: string): NotificationDelayValue;
12
+ declare function normalizeOptionalBoolean(value: boolean | undefined, label: string): boolean | undefined;
13
+ interface NotificationMailMessage {
14
+ readonly subject: string;
15
+ readonly greeting?: string;
16
+ readonly lines?: readonly string[];
17
+ readonly action?: {
18
+ readonly label: string;
19
+ readonly url: string;
20
+ };
21
+ readonly html?: string;
22
+ readonly text?: string;
23
+ readonly metadata?: Readonly<Record<string, NotificationJsonValue>>;
24
+ }
25
+ interface NotificationDatabaseMessage<TData extends NotificationJsonValue = NotificationJsonValue> {
26
+ readonly data: TData;
27
+ }
28
+ interface NotificationBroadcastMessage<TData extends NotificationJsonValue = NotificationJsonValue> {
29
+ readonly event?: string;
30
+ readonly data: TData;
31
+ }
32
+ type NotificationEmailRoute = string | {
33
+ readonly email: string;
34
+ readonly name?: string;
35
+ };
36
+ interface NotificationDatabaseRoute {
37
+ readonly id: string | number;
38
+ readonly type: string;
39
+ }
40
+ type NotificationBroadcastRoute = string | readonly string[] | {
41
+ readonly channels: readonly string[];
42
+ };
43
+ interface NotificationContext {
44
+ readonly anonymous: boolean;
45
+ }
46
+ interface NotificationBuildContext<TChannel extends string = string> extends NotificationContext {
47
+ readonly channel: TChannel;
48
+ }
49
+ interface NotificationSendContext<TRoute = unknown, TPayload = unknown, TNotifiable = unknown, TChannel extends string = string> extends NotificationBuildContext<TChannel> {
50
+ readonly route?: TRoute;
51
+ readonly notifiable: TNotifiable;
52
+ readonly notificationType?: string;
53
+ readonly payload: TPayload;
54
+ readonly targetIndex: number;
55
+ }
56
+ interface NotificationChannel<TRoute = unknown, TPayload = unknown, TResult = unknown> {
57
+ validateRoute?(route: TRoute): TRoute;
58
+ send(input: NotificationSendContext<TRoute, TPayload>): TResult | Promise<TResult>;
59
+ }
60
+ interface BuiltInNotificationChannelRegistry {
61
+ readonly email: NotificationChannel<NotificationEmailRoute, NotificationMailMessage, void>;
62
+ readonly database: NotificationChannel<NotificationDatabaseRoute, NotificationDatabaseMessage, void>;
63
+ readonly broadcast: NotificationChannel<NotificationBroadcastRoute, NotificationBroadcastMessage, void>;
64
+ }
65
+ interface HoloNotificationChannelRegistry {
66
+ }
67
+ type NotificationChannelRegistry = BuiltInNotificationChannelRegistry & HoloNotificationChannelRegistry;
68
+ type NotificationChannelName = Extract<keyof NotificationChannelRegistry, string>;
69
+ type ResolveRegisteredChannel<TChannel extends string> = TChannel extends NotificationChannelName ? Extract<NotificationChannelRegistry[TChannel], NotificationChannel> extends never ? NotificationChannel : Extract<NotificationChannelRegistry[TChannel], NotificationChannel> : NotificationChannel;
70
+ type NotificationRouteFor<TChannel extends string> = ResolveRegisteredChannel<TChannel> extends NotificationChannel<infer TRoute, unknown, unknown> ? TRoute : never;
71
+ type NotificationPayloadFor<TChannel extends string> = ResolveRegisteredChannel<TChannel> extends NotificationChannel<unknown, infer TPayload, unknown> ? TPayload : never;
72
+ type NotificationResultFor<TChannel extends string> = ResolveRegisteredChannel<TChannel> extends NotificationChannel<unknown, unknown, infer TResult> ? TResult : unknown;
73
+ interface NotificationQueueOptions {
74
+ readonly connection?: string;
75
+ readonly queue?: string;
76
+ readonly delay?: NotificationDelayValue;
77
+ readonly afterCommit?: boolean;
78
+ }
79
+ type NotificationQueueResolver<TNotifiable, TChannel extends string> = (notifiable: TNotifiable, channel: TChannel, context: NotificationContext) => boolean | NotificationQueueOptions;
80
+ type NotificationDelayResolver<TNotifiable, TChannel extends string> = (notifiable: TNotifiable, channel: TChannel, context: NotificationContext) => NotificationDelayValue | undefined;
81
+ type NotificationBuildFactories<TNotifiable> = Partial<{
82
+ [TChannel in NotificationChannelName]: (notifiable: TNotifiable, context: NotificationBuildContext<TChannel>) => NotificationPayloadFor<TChannel>;
83
+ }>;
84
+ interface NotificationDefinition<TNotifiable = unknown, TBuild extends NotificationBuildFactories<TNotifiable> = NotificationBuildFactories<TNotifiable>> {
85
+ readonly type?: string;
86
+ via(notifiable: TNotifiable, context: NotificationContext): readonly Extract<keyof TBuild, string>[];
87
+ readonly build: TBuild;
88
+ readonly queue?: boolean | NotificationQueueOptions | NotificationQueueResolver<TNotifiable, string>;
89
+ readonly delay?: NotificationDelayValue | Partial<Record<Extract<keyof TBuild, string>, NotificationDelayValue>> | NotificationDelayResolver<TNotifiable, string>;
90
+ }
91
+ type InferNotificationNotifiable<TNotification> = TNotification extends NotificationDefinition<infer TNotifiable, NotificationBuildFactories<unknown>> ? TNotifiable : TNotification extends NotificationDefinition<infer TNotifiable, infer _TBuild> ? TNotifiable : never;
92
+ type InferNotificationChannels<TNotification> = TNotification extends NotificationDefinition<unknown, infer TBuild> ? Extract<keyof TBuild, string> : never;
93
+ interface AnonymousNotificationTarget<TRoutes extends Partial<{
94
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
95
+ }> = Partial<{
96
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
97
+ }>> {
98
+ readonly anonymous: true;
99
+ readonly routes: TRoutes;
100
+ }
101
+ type AnonymousRoutesWithChannel<TRoutes extends Partial<{
102
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
103
+ }>, TChannel extends NotificationChannelName> = Readonly<Omit<TRoutes, TChannel> & {
104
+ readonly [TKey in TChannel]: NotificationRouteFor<TChannel>;
105
+ }>;
106
+ interface NotificationChannelDispatchResult<TChannel extends string = string> {
107
+ readonly channel: TChannel;
108
+ readonly targetIndex: number;
109
+ readonly queued: boolean;
110
+ readonly success: boolean;
111
+ readonly deferred?: boolean;
112
+ readonly result?: NotificationResultFor<TChannel>;
113
+ readonly error?: unknown;
114
+ }
115
+ interface NotificationDispatchResult {
116
+ readonly totalTargets: number;
117
+ readonly channels: readonly NotificationChannelDispatchResult[];
118
+ readonly deferred?: boolean;
119
+ }
120
+ interface PendingNotificationDispatch<TResult = NotificationDispatchResult> extends PromiseLike<TResult> {
121
+ onConnection(name: string): PendingNotificationDispatch<TResult>;
122
+ onQueue(name: string): PendingNotificationDispatch<TResult>;
123
+ delay(value: NotificationDelayValue): PendingNotificationDispatch<TResult>;
124
+ delayFor<TChannel extends NotificationChannelName>(channel: TChannel, value: NotificationDelayValue): PendingNotificationDispatch<TResult>;
125
+ afterCommit(): PendingNotificationDispatch<TResult>;
126
+ then<TResult1 = TResult, TResult2 = never>(onfulfilled?: ((value: TResult) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
127
+ catch<TResult1 = never>(onrejected?: ((reason: unknown) => TResult1 | PromiseLike<TResult1>) | null): Promise<TResult | TResult1>;
128
+ finally(onfinally?: (() => void) | null): Promise<TResult>;
129
+ }
130
+ interface PendingAnonymousNotification<TRoutes extends Partial<{
131
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
132
+ }> = Record<never, never>> {
133
+ readonly target: AnonymousNotificationTarget<TRoutes>;
134
+ channel<TChannel extends NotificationChannelName>(channel: TChannel, route: NotificationRouteFor<TChannel>): PendingAnonymousNotification<AnonymousRoutesWithChannel<TRoutes, TChannel>>;
135
+ notify<TNotification extends NotificationDefinition<unknown, NotificationBuildFactories<unknown>>>(notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
136
+ }
137
+ interface NotificationMailSender {
138
+ send(message: NotificationMailMessage, context: NotificationSendContext<NotificationEmailRoute, NotificationMailMessage>): Promise<void> | void;
139
+ }
140
+ interface NotificationBroadcaster {
141
+ send(message: NotificationBroadcastMessage, context: NotificationSendContext<NotificationBroadcastRoute, NotificationBroadcastMessage>): Promise<void> | void;
142
+ }
143
+ interface NotificationRecord<TData extends NotificationJsonValue = NotificationJsonValue> {
144
+ readonly id: string;
145
+ readonly type?: string;
146
+ readonly notifiableType: string;
147
+ readonly notifiableId: string | number;
148
+ readonly data: TData;
149
+ readonly readAt?: Date | null;
150
+ readonly createdAt: Date;
151
+ readonly updatedAt: Date;
152
+ }
153
+ interface NotificationStore {
154
+ create(record: NotificationRecord): Promise<void>;
155
+ list(notifiable: NotificationDatabaseRoute): Promise<readonly NotificationRecord[]>;
156
+ unread(notifiable: NotificationDatabaseRoute): Promise<readonly NotificationRecord[]>;
157
+ markAsRead(ids: readonly string[]): Promise<number>;
158
+ markAsUnread(ids: readonly string[]): Promise<number>;
159
+ delete(ids: readonly string[]): Promise<number>;
160
+ }
161
+ interface NotificationDispatchTarget {
162
+ readonly kind: 'notifiable' | 'many' | 'anonymous';
163
+ readonly value: unknown;
164
+ }
165
+ interface NotificationDispatchOptions {
166
+ readonly connection?: string;
167
+ readonly queue?: string;
168
+ readonly delay?: NotificationDelayValue;
169
+ readonly delayByChannel?: Partial<Record<string, NotificationDelayValue>>;
170
+ readonly afterCommit?: boolean;
171
+ }
172
+ interface NotificationDispatchInput<TNotification extends NotificationDefinition = NotificationDefinition> {
173
+ readonly target: NotificationDispatchTarget;
174
+ readonly notification: TNotification;
175
+ readonly options: NotificationDispatchOptions;
176
+ }
177
+ interface NotificationRuntimeBindings {
178
+ readonly config?: NormalizedHoloNotificationsConfig;
179
+ readonly mailer?: NotificationMailSender;
180
+ readonly broadcaster?: NotificationBroadcaster;
181
+ readonly store?: NotificationStore;
182
+ dispatch?<TNotification extends NotificationDefinition = NotificationDefinition>(input: NotificationDispatchInput<TNotification>): Promise<NotificationDispatchResult>;
183
+ }
184
+ interface RegisterNotificationChannelOptions {
185
+ readonly replaceExisting?: boolean;
186
+ }
187
+ interface RegisteredNotificationChannel<TChannel extends string = string> {
188
+ readonly name: TChannel;
189
+ readonly channel: NotificationChannel;
190
+ }
191
+ declare function isNotificationDefinition(value: unknown): value is NotificationDefinition;
192
+ declare function normalizeQueueOptions(value: NotificationQueueOptions | undefined): NotificationQueueOptions | undefined;
193
+ declare function normalizeDelayConfig<TChannels extends string>(value: NotificationDefinition<unknown, NotificationBuildFactories<unknown>>['delay'] | undefined): NotificationDefinition<unknown, NotificationBuildFactories<unknown>>['delay'] | undefined;
194
+ declare function normalizeNotificationDefinition<TNotifiable, TBuild extends NotificationBuildFactories<TNotifiable>>(definition: NotificationDefinition<TNotifiable, TBuild>): NotificationDefinition<TNotifiable, TBuild>;
195
+ declare function defineNotification<TNotifiable, TBuild extends NotificationBuildFactories<TNotifiable>>(definition: NotificationDefinition<TNotifiable, TBuild>): NotificationDefinition<TNotifiable, TBuild>;
196
+ declare function createAnonymousNotificationTarget<TRoutes extends Partial<{
197
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
198
+ }>>(routes: TRoutes): AnonymousNotificationTarget<TRoutes>;
199
+ declare const notificationsInternals: {
200
+ BUILT_IN_NOTIFICATION_CHANNELS: readonly ["email", "database", "broadcast"];
201
+ HOLO_NOTIFICATION_DEFINITION_MARKER: symbol;
202
+ createAnonymousNotificationTarget: typeof createAnonymousNotificationTarget;
203
+ isObject: typeof isObject;
204
+ normalizeDelayConfig: typeof normalizeDelayConfig;
205
+ normalizeDelayValue: typeof normalizeDelayValue;
206
+ normalizeNotificationDefinition: typeof normalizeNotificationDefinition;
207
+ normalizeOptionalBoolean: typeof normalizeOptionalBoolean;
208
+ normalizeOptionalString: typeof normalizeOptionalString;
209
+ normalizeQueueOptions: typeof normalizeQueueOptions;
210
+ };
211
+
212
+ export { type AnonymousNotificationTarget, type BuiltInNotificationChannelRegistry, type HoloNotificationChannelRegistry, type InferNotificationChannels, type InferNotificationNotifiable, type NotificationBroadcastMessage, type NotificationBroadcastRoute, type NotificationBroadcaster, type NotificationBuildContext, type NotificationBuildFactories, type NotificationChannel, type NotificationChannelDispatchResult, type NotificationChannelName, type NotificationChannelRegistry, type NotificationContext, type NotificationDatabaseMessage, type NotificationDatabaseRoute, type NotificationDefinition, type NotificationDelayResolver, type NotificationDelayValue, type NotificationDispatchInput, type NotificationDispatchOptions, type NotificationDispatchResult, type NotificationDispatchTarget, type NotificationEmailRoute, type NotificationJsonValue, type NotificationMailMessage, type NotificationMailSender, type NotificationPayloadFor, type NotificationQueueOptions, type NotificationQueueResolver, type NotificationRecord, type NotificationResultFor, type NotificationRouteFor, type NotificationRuntimeBindings, type NotificationSendContext, type NotificationStore, type PendingAnonymousNotification, type PendingNotificationDispatch, type RegisterNotificationChannelOptions, type RegisteredNotificationChannel, createAnonymousNotificationTarget, defineNotification, isNotificationDefinition, normalizeNotificationDefinition, notificationsInternals };
@@ -0,0 +1,16 @@
1
+ import {
2
+ createAnonymousNotificationTarget,
3
+ defineNotification,
4
+ defineNotificationsConfig,
5
+ isNotificationDefinition,
6
+ normalizeNotificationDefinition,
7
+ notificationsInternals
8
+ } from "./chunk-INGM2JYY.mjs";
9
+ export {
10
+ createAnonymousNotificationTarget,
11
+ defineNotification,
12
+ defineNotificationsConfig,
13
+ isNotificationDefinition,
14
+ normalizeNotificationDefinition,
15
+ notificationsInternals
16
+ };
@@ -0,0 +1,226 @@
1
+ import { NotificationRuntimeBindings, NotificationDatabaseRoute, NotificationRecord, NotificationDefinition, InferNotificationNotifiable, PendingNotificationDispatch, NotificationDispatchResult, PendingAnonymousNotification, NotificationChannelName, NotificationRouteFor, AnonymousNotificationTarget, NotificationDispatchTarget, NotificationDelayValue, NotificationChannel, NotificationBuildContext, NotificationSendContext, NotificationDispatchInput, NotificationBroadcastRoute, NotificationEmailRoute, NotificationDatabaseMessage, NotificationDispatchOptions, RegisteredNotificationChannel, RegisterNotificationChannelOptions } from './contracts.js';
2
+ export { BuiltInNotificationChannelRegistry, HoloNotificationChannelRegistry, InferNotificationChannels, NotificationBroadcastMessage, NotificationBroadcaster, NotificationBuildFactories, NotificationChannelDispatchResult, NotificationContext, NotificationDelayResolver, NotificationJsonValue, NotificationMailMessage, NotificationMailSender, NotificationPayloadFor, NotificationQueueOptions, NotificationQueueResolver, NotificationResultFor, NotificationStore, defineNotification, isNotificationDefinition, normalizeNotificationDefinition, notificationsInternals } from './contracts.js';
3
+ import { HoloNotificationsConfig } from '@holo-js/config';
4
+ export { HoloNotificationsConfig, NormalizedHoloNotificationsConfig } from '@holo-js/config';
5
+
6
+ declare function normalizeOptionalString(value: string, label: string): string;
7
+ declare function normalizeDelayValue(value: NotificationDelayValue, label: string): NotificationDelayValue;
8
+ declare function isObject(value: unknown): value is Record<string, unknown>;
9
+ declare function isAnonymousTarget(value: unknown): value is AnonymousNotificationTarget;
10
+ declare function getRuntimeBindings(): NotificationRuntimeBindings;
11
+ type RuntimeState = {
12
+ bindings?: NotificationRuntimeBindings;
13
+ loadQueueModule?: () => Promise<QueueModule>;
14
+ loadDbModule?: () => Promise<DbModule | null>;
15
+ };
16
+ declare function getRuntimeState(): RuntimeState;
17
+ declare function getDispatchHandler(): typeof dispatchNotifications;
18
+ declare function loadQueueModule(): Promise<QueueModule>;
19
+ declare function loadDbModule(): Promise<DbModule | null>;
20
+ type MutableDispatchOptions = {
21
+ connection?: string;
22
+ queue?: string;
23
+ delay?: NotificationDelayValue;
24
+ delayByChannel?: Record<string, NotificationDelayValue>;
25
+ afterCommit?: boolean;
26
+ };
27
+ type DispatchTargetInput = NotificationDispatchTarget | (() => NotificationDispatchTarget);
28
+ type ResolvedTarget = {
29
+ readonly index: number;
30
+ readonly anonymous: boolean;
31
+ readonly notifiable: unknown;
32
+ readonly routes?: Record<string, unknown>;
33
+ };
34
+ type RouteResolver = (notifiable: unknown) => unknown;
35
+ type ResolvedChannelPlan = {
36
+ readonly channel: string;
37
+ readonly queued: boolean;
38
+ readonly connection?: string;
39
+ readonly queue?: string;
40
+ readonly delay?: NotificationDelayValue;
41
+ readonly afterCommit: boolean;
42
+ };
43
+ type DispatchExecutionOptions = {
44
+ readonly allowAfterCommitDeferral?: boolean;
45
+ };
46
+ type QueueDispatchChain = {
47
+ onConnection(name: string): QueueDispatchChain;
48
+ onQueue(name: string): QueueDispatchChain;
49
+ delay(value: number | Date): QueueDispatchChain;
50
+ dispatch(): Promise<unknown>;
51
+ };
52
+ type QueueModule = {
53
+ defineJob(definition: {
54
+ handle(payload: QueuedNotificationDeliveryPayload): Promise<unknown> | unknown;
55
+ }): unknown;
56
+ dispatch(jobName: string, payload: QueuedNotificationDeliveryPayload): QueueDispatchChain;
57
+ getRegisteredQueueJob(name: string): unknown;
58
+ registerQueueJob(definition: unknown, options: {
59
+ name: string;
60
+ }): void;
61
+ };
62
+ type DbModule = {
63
+ connectionAsyncContext: {
64
+ getActive(): {
65
+ connection: {
66
+ getScope(): {
67
+ kind: string;
68
+ };
69
+ afterCommit(callback: () => Promise<void>): void;
70
+ };
71
+ } | undefined;
72
+ };
73
+ };
74
+ type QueuedNotificationDeliveryPayload = Readonly<{
75
+ readonly channel: string;
76
+ readonly anonymous: boolean;
77
+ readonly notifiable: unknown;
78
+ readonly route?: unknown;
79
+ readonly notificationType?: string;
80
+ readonly payload: unknown;
81
+ readonly targetIndex: number;
82
+ }>;
83
+ type BuiltInChannelDefinition = NotificationChannel & {
84
+ readonly resolveRoute?: RouteResolver;
85
+ };
86
+ declare function createNotificationContext(anonymous: boolean): {
87
+ readonly anonymous: boolean;
88
+ };
89
+ declare function createBuildContext<TChannel extends string>(channel: TChannel, anonymous: boolean): NotificationBuildContext<TChannel>;
90
+ declare function normalizeEmailRouteFromValue(value: unknown): NotificationEmailRoute;
91
+ declare function resolveEmailRouteFromNotifiable(notifiable: unknown): NotificationEmailRoute;
92
+ declare function normalizeDatabaseRouteFromValue(value: unknown): NotificationDatabaseRoute;
93
+ declare function resolveDatabaseRouteFromNotifiable(notifiable: unknown): NotificationDatabaseRoute;
94
+ declare function normalizeBroadcastRouteFromValue(value: unknown): NotificationBroadcastRoute;
95
+ declare function resolveBroadcastRouteFromNotifiable(notifiable: unknown): NotificationBroadcastRoute;
96
+ declare function normalizeNotificationRecord(route: NotificationDatabaseRoute, payload: NotificationDatabaseMessage, notificationType: string | undefined): NotificationRecord;
97
+ declare function normalizeNotificationRecordIds(ids: readonly string[]): readonly string[];
98
+ declare function getNotificationChannel(name: string): NotificationChannel | BuiltInChannelDefinition | undefined;
99
+ declare function resolveTargets(target: NotificationDispatchTarget): readonly ResolvedTarget[];
100
+ declare function resolveChannels(notification: NotificationDefinition, target: ResolvedTarget): readonly string[];
101
+ declare function resolvePayload(notification: NotificationDefinition, channel: string, target: ResolvedTarget): unknown;
102
+ declare function resolveNotificationQueueOptions(notification: NotificationDefinition, target: ResolvedTarget, channel: string): boolean | NotificationDispatchOptions;
103
+ declare function resolveNotificationDelay(notification: NotificationDefinition, target: ResolvedTarget, channel: string): NotificationDelayValue | undefined;
104
+ declare function resolveRoute(channel: string, target: ResolvedTarget): unknown;
105
+ declare function resolveChannelDispatchPlan(notification: NotificationDefinition, target: ResolvedTarget, channel: string, options: NotificationDispatchOptions): ResolvedChannelPlan;
106
+ declare function deliverResolvedNotificationChannel(context: NotificationSendContext): Promise<unknown>;
107
+ declare function createQueuedDeliveryPayload(context: NotificationSendContext): QueuedNotificationDeliveryPayload;
108
+ declare function runQueuedNotificationDelivery(payload: QueuedNotificationDeliveryPayload): Promise<unknown>;
109
+ declare function ensureNotificationsQueueJobRegistered(queueModule?: QueueModule): Promise<QueueModule>;
110
+ declare function dispatchQueuedNotificationChannel(context: NotificationSendContext, plan: ResolvedChannelPlan): Promise<void>;
111
+ declare function deferDispatchUntilCommit(input: NotificationDispatchInput, targets: readonly ResolvedTarget[], notification: NotificationDefinition): Promise<NotificationDispatchResult | null>;
112
+ declare function dispatchNotifications(input: NotificationDispatchInput, execution?: DispatchExecutionOptions): Promise<NotificationDispatchResult>;
113
+ declare class PendingDispatch<TResult = NotificationDispatchResult> implements PendingNotificationDispatch<TResult> {
114
+ #private;
115
+ private readonly target;
116
+ private readonly notification;
117
+ private readonly options;
118
+ constructor(target: DispatchTargetInput, notification: NotificationDefinition<any, any>, options?: MutableDispatchOptions);
119
+ onConnection(name: string): PendingNotificationDispatch<TResult>;
120
+ onQueue(name: string): PendingNotificationDispatch<TResult>;
121
+ delay(value: NotificationDelayValue): PendingNotificationDispatch<TResult>;
122
+ delayFor<TChannel extends NotificationChannelName>(channel: TChannel, value: NotificationDelayValue): PendingNotificationDispatch<TResult>;
123
+ afterCommit(): PendingNotificationDispatch<TResult>;
124
+ then<TResult1 = TResult, TResult2 = never>(onfulfilled?: ((value: TResult) => TResult1 | PromiseLike<TResult1>) | null, onrejected?: ((reason: unknown) => TResult2 | PromiseLike<TResult2>) | null): Promise<TResult1 | TResult2>;
125
+ catch<TResult1 = never>(onrejected?: ((reason: unknown) => TResult1 | PromiseLike<TResult1>) | null): Promise<TResult | TResult1>;
126
+ finally(onfinally?: (() => void) | null): Promise<TResult>;
127
+ }
128
+ declare class AnonymousNotificationBuilder<TRoutes extends Partial<{
129
+ readonly [TChannel in NotificationChannelName]: NotificationRouteFor<TChannel>;
130
+ }> = Record<never, never>> implements PendingAnonymousNotification<TRoutes> {
131
+ readonly target: AnonymousNotificationTarget<TRoutes>;
132
+ constructor(routes?: TRoutes);
133
+ channel<TChannel extends NotificationChannelName>(channel: TChannel, route: NotificationRouteFor<TChannel>): PendingAnonymousNotification<Readonly<Omit<TRoutes, TChannel> & {
134
+ readonly [TKey in TChannel]: NotificationRouteFor<TChannel>;
135
+ }>>;
136
+ notify<TNotification extends NotificationDefinition<any, any>>(notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
137
+ }
138
+ interface NotificationRuntimeFacade {
139
+ notify<TNotification extends NotificationDefinition<any, any>>(notifiable: InferNotificationNotifiable<TNotification>, notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
140
+ notifyMany<TNotification extends NotificationDefinition<any, any>>(notifiables: readonly InferNotificationNotifiable<TNotification>[] | Iterable<InferNotificationNotifiable<TNotification>>, notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
141
+ notifyUsing(): PendingAnonymousNotification;
142
+ listNotifications(notifiable: NotificationDatabaseRoute | Record<string, unknown>): Promise<readonly NotificationRecord[]>;
143
+ unreadNotifications(notifiable: NotificationDatabaseRoute | Record<string, unknown>): Promise<readonly NotificationRecord[]>;
144
+ markNotificationsAsRead(ids: readonly string[]): Promise<number>;
145
+ markNotificationsAsUnread(ids: readonly string[]): Promise<number>;
146
+ deleteNotifications(ids: readonly string[]): Promise<number>;
147
+ }
148
+ declare function configureNotificationsRuntime(bindings?: NotificationRuntimeBindings): void;
149
+ declare function getNotificationsRuntimeBindings(): NotificationRuntimeBindings;
150
+ declare function resetNotificationsRuntime(): void;
151
+ declare function notify<TNotification extends NotificationDefinition<any, any>>(notifiable: InferNotificationNotifiable<TNotification>, notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
152
+ declare function notifyMany<TNotification extends NotificationDefinition<any, any>>(notifiables: readonly InferNotificationNotifiable<TNotification>[] | Iterable<InferNotificationNotifiable<TNotification>>, notification: TNotification): PendingNotificationDispatch<NotificationDispatchResult>;
153
+ declare function notifyUsing(): PendingAnonymousNotification;
154
+ declare function listNotifications(notifiable: NotificationDatabaseRoute | Record<string, unknown>): Promise<readonly NotificationRecord[]>;
155
+ declare function unreadNotifications(notifiable: NotificationDatabaseRoute | Record<string, unknown>): Promise<readonly NotificationRecord[]>;
156
+ declare function markNotificationsAsRead(ids: readonly string[]): Promise<number>;
157
+ declare function markNotificationsAsUnread(ids: readonly string[]): Promise<number>;
158
+ declare function deleteNotifications(ids: readonly string[]): Promise<number>;
159
+ declare function getNotificationsRuntime(): NotificationRuntimeFacade;
160
+ declare const notificationsRuntimeInternals: {
161
+ HOLO_NOTIFICATIONS_DELIVER_JOB: string;
162
+ AnonymousNotificationBuilder: typeof AnonymousNotificationBuilder;
163
+ PendingDispatch: typeof PendingDispatch;
164
+ builtInChannels: Readonly<Record<"email" | "database" | "broadcast", BuiltInChannelDefinition>>;
165
+ createBuildContext: typeof createBuildContext;
166
+ createNotificationContext: typeof createNotificationContext;
167
+ createQueuedDeliveryPayload: typeof createQueuedDeliveryPayload;
168
+ deferDispatchUntilCommit: typeof deferDispatchUntilCommit;
169
+ deliverResolvedNotificationChannel: typeof deliverResolvedNotificationChannel;
170
+ dispatchNotifications: typeof dispatchNotifications;
171
+ dispatchQueuedNotificationChannel: typeof dispatchQueuedNotificationChannel;
172
+ ensureNotificationsQueueJobRegistered: typeof ensureNotificationsQueueJobRegistered;
173
+ getDispatchHandler: typeof getDispatchHandler;
174
+ getRuntimeBindings: typeof getRuntimeBindings;
175
+ getRuntimeState: typeof getRuntimeState;
176
+ getNotificationChannel: typeof getNotificationChannel;
177
+ isAnonymousTarget: typeof isAnonymousTarget;
178
+ isObject: typeof isObject;
179
+ loadDbModule: typeof loadDbModule;
180
+ loadQueueModule: typeof loadQueueModule;
181
+ normalizeBroadcastRouteFromValue: typeof normalizeBroadcastRouteFromValue;
182
+ normalizeDatabaseRouteFromValue: typeof normalizeDatabaseRouteFromValue;
183
+ normalizeDelayValue: typeof normalizeDelayValue;
184
+ normalizeEmailRouteFromValue: typeof normalizeEmailRouteFromValue;
185
+ normalizeNotificationRecord: typeof normalizeNotificationRecord;
186
+ normalizeNotificationRecordIds: typeof normalizeNotificationRecordIds;
187
+ normalizeOptionalString: typeof normalizeOptionalString;
188
+ resolveBroadcastRouteFromNotifiable: typeof resolveBroadcastRouteFromNotifiable;
189
+ resolveChannelDispatchPlan: typeof resolveChannelDispatchPlan;
190
+ resolveChannels: typeof resolveChannels;
191
+ resolveDatabaseRouteFromNotifiable: typeof resolveDatabaseRouteFromNotifiable;
192
+ resolveEmailRouteFromNotifiable: typeof resolveEmailRouteFromNotifiable;
193
+ resolveNotificationDelay: typeof resolveNotificationDelay;
194
+ resolveNotificationQueueOptions: typeof resolveNotificationQueueOptions;
195
+ resolvePayload: typeof resolvePayload;
196
+ resolveRoute: typeof resolveRoute;
197
+ runQueuedNotificationDelivery: typeof runQueuedNotificationDelivery;
198
+ resolveTargets: typeof resolveTargets;
199
+ setDbModuleLoader(loader: (() => Promise<DbModule | null>) | undefined): void;
200
+ setQueueModuleLoader(loader: (() => Promise<QueueModule>) | undefined): void;
201
+ };
202
+
203
+ declare function normalizeChannelName(value: string): string;
204
+ declare function getRegistry(): Map<string, RegisteredNotificationChannel>;
205
+ declare function registerNotificationChannel<TChannel extends string>(name: TChannel, channel: NotificationChannel, options?: RegisterNotificationChannelOptions): void;
206
+ declare function getRegisteredNotificationChannel<TChannel extends string>(name: TChannel): RegisteredNotificationChannel<TChannel> | undefined;
207
+ declare function listRegisteredNotificationChannels(): readonly RegisteredNotificationChannel[];
208
+ declare function resetNotificationChannelRegistry(): void;
209
+ declare const notificationRegistryInternals: {
210
+ getRegistry: typeof getRegistry;
211
+ normalizeChannelName: typeof normalizeChannelName;
212
+ };
213
+
214
+ declare function defineNotificationsConfig<const TConfig extends HoloNotificationsConfig>(config: TConfig): Readonly<TConfig>;
215
+ declare const notifications: Readonly<{
216
+ deleteNotifications: typeof deleteNotifications;
217
+ listNotifications: typeof listNotifications;
218
+ markNotificationsAsRead: typeof markNotificationsAsRead;
219
+ markNotificationsAsUnread: typeof markNotificationsAsUnread;
220
+ notify: typeof notify;
221
+ notifyMany: typeof notifyMany;
222
+ notifyUsing: typeof notifyUsing;
223
+ unreadNotifications: typeof unreadNotifications;
224
+ }>;
225
+
226
+ export { AnonymousNotificationTarget, InferNotificationNotifiable, NotificationBroadcastRoute, NotificationBuildContext, NotificationChannel, NotificationChannelName, NotificationDatabaseMessage, NotificationDatabaseRoute, NotificationDefinition, NotificationDelayValue, NotificationDispatchInput, NotificationDispatchOptions, NotificationDispatchResult, NotificationDispatchTarget, NotificationEmailRoute, NotificationRecord, NotificationRouteFor, NotificationRuntimeBindings, NotificationSendContext, PendingAnonymousNotification, PendingNotificationDispatch, RegisterNotificationChannelOptions, RegisteredNotificationChannel, configureNotificationsRuntime, notifications as default, defineNotificationsConfig, deleteNotifications, getNotificationsRuntime, getNotificationsRuntimeBindings, getRegisteredNotificationChannel, listNotifications, listRegisteredNotificationChannels, markNotificationsAsRead, markNotificationsAsUnread, notificationRegistryInternals, notificationsRuntimeInternals, notify, notifyMany, notifyUsing, registerNotificationChannel, resetNotificationChannelRegistry, resetNotificationsRuntime, unreadNotifications };