@classytic/arc-notifications 0.8.0 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +66 -2
- package/dist/index.mjs +82 -15
- package/package.json +5 -5
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseChannel, ChannelConfig, DeliveryLog, DeliveryLogEntry, NotificationPayload, NotificationService, NotificationServiceConfig, QueueAdapter, Recipient, SendResult, TemplateResolver } from "@classytic/notifications";
|
|
2
2
|
import { JobDefinition, JobDispatcher } from "@classytic/arc/integrations/jobs";
|
|
3
|
-
import { ArcModule } from "@classytic/arc/factory";
|
|
3
|
+
import { ArcModule, EventHandlerDefinition } from "@classytic/arc/factory";
|
|
4
4
|
import { PermissionCheck } from "@classytic/arc/permissions";
|
|
5
5
|
import { FastifyInstance, FastifyRequest } from "fastify";
|
|
6
6
|
import { DomainEvent } from "@classytic/primitives/events";
|
|
@@ -339,6 +339,18 @@ interface NotificationTriggerOverrideDoc {
|
|
|
339
339
|
* answer is a host-supplied predicate, never an expression DSL.
|
|
340
340
|
*/
|
|
341
341
|
sourceChannels?: string[] | null;
|
|
342
|
+
/**
|
|
343
|
+
* Literal addresses to notify IN ADDITION to the role recipients.
|
|
344
|
+
*
|
|
345
|
+
* `recipients` holds ROLES, which only reaches people who hold an account.
|
|
346
|
+
* The person who wants order mail — an owner, an accountant, a shared
|
|
347
|
+
* ops@ inbox — often has no dashboard login at all, so a role list cannot
|
|
348
|
+
* express them.
|
|
349
|
+
*
|
|
350
|
+
* ADDITIVE, never a replacement: adding an address must not silence the staff
|
|
351
|
+
* feed, which is what substituting for `recipients` would do.
|
|
352
|
+
*/
|
|
353
|
+
recipientEmails?: string[] | null;
|
|
342
354
|
/** Copy overrides. Unset fields fall back to the code template. */
|
|
343
355
|
title?: string | null;
|
|
344
356
|
message?: string | null;
|
|
@@ -395,6 +407,8 @@ interface EffectiveTriggerSettings {
|
|
|
395
407
|
channels: NotificationChannel[];
|
|
396
408
|
/** `null` = unrestricted. See {@link NotificationTriggerOverrideDoc.sourceChannels}. */
|
|
397
409
|
sourceChannels: string[] | null;
|
|
410
|
+
/** Extra literal addresses, ADDED to the role recipients. `[]` when none. */
|
|
411
|
+
recipientEmails: string[];
|
|
398
412
|
title: string;
|
|
399
413
|
message: string;
|
|
400
414
|
priority?: "low" | "normal" | "high" | undefined;
|
|
@@ -405,6 +419,21 @@ interface CodeTriggerDefaults {
|
|
|
405
419
|
title: string;
|
|
406
420
|
message: string;
|
|
407
421
|
priority?: "low" | "normal" | "high" | undefined;
|
|
422
|
+
/**
|
|
423
|
+
* The trigger's OWN origin restriction — `null`/absent means unrestricted.
|
|
424
|
+
*
|
|
425
|
+
* Every other field here is a code default an operator's row REPLACES. This
|
|
426
|
+
* one was the exception: the merge below hardcoded `?? null`, so a deployment
|
|
427
|
+
* could not state "a new-order alert is for web orders, not for the till" and
|
|
428
|
+
* every deployment shipped unscoped until someone hand-configured the UI.
|
|
429
|
+
*
|
|
430
|
+
* That matters most where it is least visible. A branch runs several
|
|
431
|
+
* registers, and unscoped means every counter sale fans out to every staff
|
|
432
|
+
* role on every one of them — resolved, written to the feed, and attempted on
|
|
433
|
+
* each connector, all before the response. The cashier who rang the sale is
|
|
434
|
+
* already looking at it.
|
|
435
|
+
*/
|
|
436
|
+
sourceChannels?: readonly string[] | undefined;
|
|
408
437
|
}
|
|
409
438
|
declare function resolveEffectiveSettings(triggerType: string, organizationId: string | null, rows: readonly NotificationTriggerOverrideDoc[], defaults: CodeTriggerDefaults): EffectiveTriggerSettings;
|
|
410
439
|
/**
|
|
@@ -700,6 +729,18 @@ declare module "fastify" {
|
|
|
700
729
|
}
|
|
701
730
|
}
|
|
702
731
|
declare function notificationsModule(config: NotificationsModuleConfig): ArcModule<NotificationService>;
|
|
732
|
+
/**
|
|
733
|
+
* Triggers as arc `eventHandlers` — what `notifyOn` subscribes, exported so a BRIDGE module can own
|
|
734
|
+
* the triggers for one producer (`dependsOn: [producer, "notifications"]`) and vanish with it.
|
|
735
|
+
* `service` is read per dispatch, so a bridge can resolve it from the notifications module's export.
|
|
736
|
+
*/
|
|
737
|
+
declare function notifyTriggerHandlers(options: {
|
|
738
|
+
/** Handler-name prefix; arc rejects duplicate handler names across the module graph. */
|
|
739
|
+
readonly name: string;
|
|
740
|
+
readonly service: () => NotificationService;
|
|
741
|
+
readonly triggers: readonly NotifyTrigger[];
|
|
742
|
+
readonly recipientResolver?: RecipientResolver;
|
|
743
|
+
}): EventHandlerDefinition[];
|
|
703
744
|
/** One event → N sends. Exported for direct unit testing. */
|
|
704
745
|
declare function dispatchTrigger(service: NotificationService, trigger: NotifyTrigger, event: DomainEvent, opts?: {
|
|
705
746
|
recipientResolver?: RecipientResolver;
|
|
@@ -719,6 +760,11 @@ interface DeliveryLogDoc {
|
|
|
719
760
|
readonly status: EntryStatus;
|
|
720
761
|
readonly duration: number;
|
|
721
762
|
readonly metadata?: Record<string, unknown>;
|
|
763
|
+
/**
|
|
764
|
+
* The organization the delivery belongs to — top-level so a store can index it and a
|
|
765
|
+
* reader can scope on it. `null` = company-wide (no organization named).
|
|
766
|
+
*/
|
|
767
|
+
readonly organizationId?: string | null;
|
|
722
768
|
/**
|
|
723
769
|
* The business document this delivery concerned. A STORE MUST INDEX IT —
|
|
724
770
|
* this field exists precisely so "every message about invoice X" is a keyed
|
|
@@ -872,6 +918,24 @@ interface NotificationTrigger {
|
|
|
872
918
|
* boot.
|
|
873
919
|
*/
|
|
874
920
|
channels?: readonly NotificationChannel[];
|
|
921
|
+
/**
|
|
922
|
+
* Restrict this trigger to events ORIGINATING from these sources — the
|
|
923
|
+
* deployment's own sales channels (`web` / `pos` / `marketplace`), NOT the
|
|
924
|
+
* delivery channels above. Two adjacent fields, two vocabularies.
|
|
925
|
+
*
|
|
926
|
+
* Absent = unrestricted, which is the historical behaviour and stays the
|
|
927
|
+
* default. An operator's stored setting REPLACES this, so declaring one
|
|
928
|
+
* narrows the out-of-the-box noise without taking the choice away.
|
|
929
|
+
*
|
|
930
|
+
* State it for any staff alert whose event can originate at a till: a branch
|
|
931
|
+
* runs several registers, and unscoped means every counter sale is resolved,
|
|
932
|
+
* written to the feed and attempted on every connector — before the response —
|
|
933
|
+
* to tell staff about a sale the cashier is already looking at.
|
|
934
|
+
*
|
|
935
|
+
* Never `[]`. Empty means "match nothing", which silences the trigger while
|
|
936
|
+
* looking like a filter; `enabled: false` is how you say that.
|
|
937
|
+
*/
|
|
938
|
+
sourceChannels?: readonly string[];
|
|
875
939
|
/**
|
|
876
940
|
* Pull dispatch variables out of the event payload.
|
|
877
941
|
*
|
|
@@ -1058,4 +1122,4 @@ interface TriggerCatalogEntry {
|
|
|
1058
1122
|
*/
|
|
1059
1123
|
type TriggerCatalogPort = () => ReadonlyArray<TriggerCatalogEntry> | Promise<ReadonlyArray<TriggerCatalogEntry>>;
|
|
1060
1124
|
//#endregion
|
|
1061
|
-
export { type CodeTemplates, type CodeTriggerDefaults, type CreateCachedTriggerOverrideStoreOptions, type CreateUnreadCountCacheOptions, DEFAULT_ENTITY_ID_VARS, type DbFirstResolverOptions, type DbFirstTemplateResolver, type DeliveryLogDoc, type EffectiveTriggerSettings, INAPP_DATA_KEY, IN_APP_CHANNEL, type InAppBackfill, type InAppBackfillOptions, InAppChannel, type InAppChannelConfig, type InAppContent, type InAppFeedListOptions, type InAppFeedPage, type InAppFeedRepository, type InAppFeedResourceOptions, type InAppFeedRow, type InAppFeedScope, type InAppPriority, type InAppTemplate, type NotificationAudienceType, type NotificationChannel, type NotificationChannelCatalog, type NotificationDecision, type NotificationExtractResult, type NotificationRecipientContact, type NotificationSkipReason, type NotificationTrigger, type NotificationTriggerOverrideDoc, type NotificationsJob, type NotificationsJobOptions, type NotificationsModuleConfig, type NotifyTrigger, type RealtimePushPort, type RecipientResolver, type RepositoryDeliveryLogOptions, SseChannel, type SseChannelConfig, type StoredTemplate, type TemplateStore, type TemplatesResourceOptions, type TriggerAdapterOptions, type TriggerCatalogEntry, type TriggerCatalogPort, type TriggerOverrideLoader, type TriggerOverrideResolution, type TriggerOverrideStore, type UnreadCountCache, createCachedTriggerOverrideStore, createDbFirstResolver, createInAppBackfill, createNotificationChannelCatalog, createRepositoryDeliveryLog, createUnreadCountCache, dispatchTrigger, evaluateSourceChannel, getRecipientMatrix, getRegisteredEvents, getTriggerByEvent, getTriggersByEvent, inAppFeedResource, notificationsJob, notificationsModule, readInAppContent, renderInApp, resolveEffectiveSettings, templatesResource, toNotifyTrigger, toNotifyTriggers };
|
|
1125
|
+
export { type CodeTemplates, type CodeTriggerDefaults, type CreateCachedTriggerOverrideStoreOptions, type CreateUnreadCountCacheOptions, DEFAULT_ENTITY_ID_VARS, type DbFirstResolverOptions, type DbFirstTemplateResolver, type DeliveryLogDoc, type EffectiveTriggerSettings, INAPP_DATA_KEY, IN_APP_CHANNEL, type InAppBackfill, type InAppBackfillOptions, InAppChannel, type InAppChannelConfig, type InAppContent, type InAppFeedListOptions, type InAppFeedPage, type InAppFeedRepository, type InAppFeedResourceOptions, type InAppFeedRow, type InAppFeedScope, type InAppPriority, type InAppTemplate, type NotificationAudienceType, type NotificationChannel, type NotificationChannelCatalog, type NotificationDecision, type NotificationExtractResult, type NotificationRecipientContact, type NotificationSkipReason, type NotificationTrigger, type NotificationTriggerOverrideDoc, type NotificationsJob, type NotificationsJobOptions, type NotificationsModuleConfig, type NotifyTrigger, type RealtimePushPort, type RecipientResolver, type RepositoryDeliveryLogOptions, SseChannel, type SseChannelConfig, type StoredTemplate, type TemplateStore, type TemplatesResourceOptions, type TriggerAdapterOptions, type TriggerCatalogEntry, type TriggerCatalogPort, type TriggerOverrideLoader, type TriggerOverrideResolution, type TriggerOverrideStore, type UnreadCountCache, createCachedTriggerOverrideStore, createDbFirstResolver, createInAppBackfill, createNotificationChannelCatalog, createRepositoryDeliveryLog, createUnreadCountCache, dispatchTrigger, evaluateSourceChannel, getRecipientMatrix, getRegisteredEvents, getTriggerByEvent, getTriggersByEvent, inAppFeedResource, notificationsJob, notificationsModule, notifyTriggerHandlers, readInAppContent, renderInApp, resolveEffectiveSettings, templatesResource, toNotifyTrigger, toNotifyTriggers };
|
package/dist/index.mjs
CHANGED
|
@@ -164,11 +164,36 @@ function resolveEffectiveSettings(triggerType, organizationId, rows, defaults) {
|
|
|
164
164
|
const title = pick("title") ?? defaults.title;
|
|
165
165
|
const message = pick("message") ?? defaults.message;
|
|
166
166
|
const priority = pick("priority") ?? defaults.priority;
|
|
167
|
+
/**
|
|
168
|
+
* Operator row, then the trigger's own default, then unrestricted — the same
|
|
169
|
+
* ladder every field above uses. It used to stop at `?? null`, discarding a
|
|
170
|
+
* code default that therefore could not be written at all.
|
|
171
|
+
*
|
|
172
|
+
* `?? null`, never `?? []` — the two must stay distinguishable all the way
|
|
173
|
+
* through. `null` means unrestricted; `[]` would mean "match nothing", and
|
|
174
|
+
* collapsing one into the other is exactly the widening this field prevents.
|
|
175
|
+
* A `null` stored by an operator is a deliberate "every source", and it wins
|
|
176
|
+
* over the code default precisely because they set it.
|
|
177
|
+
*/
|
|
178
|
+
/**
|
|
179
|
+
* PRESENCE, not `??` — the one field where a stored `null` is a decision.
|
|
180
|
+
*
|
|
181
|
+
* `pick` collapses `null` into "absent", which is right for every other
|
|
182
|
+
* setting and wrong here: `null` means "every source", and an operator who
|
|
183
|
+
* opens a filter must not have it re-narrowed by the code default on the next
|
|
184
|
+
* read. That is Rule 1 — a default is the fallback for an UNSET value, never
|
|
185
|
+
* an override of an explicit one.
|
|
186
|
+
*
|
|
187
|
+
* Scoped row wins over app-wide, same precedence as `pick`.
|
|
188
|
+
*/
|
|
189
|
+
const rowWithField = [scoped, appWide].find((r) => r && "sourceChannels" in r);
|
|
190
|
+
const sourceChannels = rowWithField ? rowWithField.sourceChannels ?? null : defaults.sourceChannels ? [...defaults.sourceChannels] : null;
|
|
167
191
|
return {
|
|
168
192
|
enabled,
|
|
169
193
|
recipients,
|
|
194
|
+
recipientEmails: pick("recipientEmails") ?? [],
|
|
170
195
|
channels,
|
|
171
|
-
sourceChannels
|
|
196
|
+
sourceChannels,
|
|
172
197
|
title,
|
|
173
198
|
message,
|
|
174
199
|
...priority ? { priority } : {}
|
|
@@ -838,18 +863,31 @@ function notificationsModule(config) {
|
|
|
838
863
|
return service;
|
|
839
864
|
},
|
|
840
865
|
eventHandlers: (fastify) => {
|
|
841
|
-
const
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
}));
|
|
866
|
+
const handlers = notifyTriggerHandlers({
|
|
867
|
+
name,
|
|
868
|
+
service: () => service,
|
|
869
|
+
triggers: notifyOn,
|
|
870
|
+
...recipientResolver ? { recipientResolver } : {}
|
|
871
|
+
});
|
|
872
|
+
if (handlers.length > 0) fastify.log.debug(`[arc-notifications] ${handlers.length} trigger(s) subscribed`);
|
|
873
|
+
return handlers;
|
|
850
874
|
}
|
|
851
875
|
});
|
|
852
876
|
}
|
|
877
|
+
/**
|
|
878
|
+
* Triggers as arc `eventHandlers` — what `notifyOn` subscribes, exported so a BRIDGE module can own
|
|
879
|
+
* the triggers for one producer (`dependsOn: [producer, "notifications"]`) and vanish with it.
|
|
880
|
+
* `service` is read per dispatch, so a bridge can resolve it from the notifications module's export.
|
|
881
|
+
*/
|
|
882
|
+
function notifyTriggerHandlers(options) {
|
|
883
|
+
const { name, service, recipientResolver } = options;
|
|
884
|
+
return options.triggers.filter((t) => t.enabled !== false).map((trigger, index) => ({
|
|
885
|
+
name: `${name}:${trigger.event}#${index}`,
|
|
886
|
+
event: trigger.event,
|
|
887
|
+
boundary: true,
|
|
888
|
+
handler: async (event) => dispatchTrigger(service(), trigger, event, recipientResolver ? { recipientResolver } : {})
|
|
889
|
+
}));
|
|
890
|
+
}
|
|
853
891
|
const audienceSlot = Symbol("arc-notifications.resolvedAudience");
|
|
854
892
|
/** Content key for an audience — key order must not fragment the memo. */
|
|
855
893
|
function audienceKey(audience) {
|
|
@@ -875,13 +913,21 @@ function resolveAudience(resolver, audience, event) {
|
|
|
875
913
|
created.catch(() => memo.delete(key));
|
|
876
914
|
return created;
|
|
877
915
|
}
|
|
916
|
+
/** The `organizationId` an audience names (`{ roles, organizationId, … }`), when it names one. */
|
|
917
|
+
function audienceOrganization(audience) {
|
|
918
|
+
if (audience === null || typeof audience !== "object") return void 0;
|
|
919
|
+
const org = audience.organizationId;
|
|
920
|
+
return typeof org === "string" && org !== "" ? org : void 0;
|
|
921
|
+
}
|
|
878
922
|
/** One event → N sends. Exported for direct unit testing. */
|
|
879
923
|
async function dispatchTrigger(service, trigger, event, opts) {
|
|
880
924
|
let resolved;
|
|
925
|
+
let organizationId;
|
|
881
926
|
if (trigger.recipient) resolved = await trigger.recipient(event);
|
|
882
927
|
else if (trigger.audience) {
|
|
883
928
|
const audience = await trigger.audience(event);
|
|
884
929
|
if (audience === null || audience === void 0) return;
|
|
930
|
+
organizationId = audienceOrganization(audience);
|
|
885
931
|
resolved = opts?.recipientResolver ? await resolveAudience(opts.recipientResolver, audience, event) : void 0;
|
|
886
932
|
}
|
|
887
933
|
if (!resolved) return;
|
|
@@ -908,6 +954,7 @@ async function dispatchTrigger(service, trigger, event, opts) {
|
|
|
908
954
|
metadata: {
|
|
909
955
|
source: "arc-notifications",
|
|
910
956
|
eventId: event.meta.id,
|
|
957
|
+
...organizationId !== void 0 ? { organizationId } : {},
|
|
911
958
|
/**
|
|
912
959
|
* The NOTIFICATION OCCURRENCE — `baseKey` BEFORE the per-recipient suffix.
|
|
913
960
|
*
|
|
@@ -947,9 +994,17 @@ function toEntry(doc) {
|
|
|
947
994
|
status: doc.status,
|
|
948
995
|
duration: doc.duration ?? 0,
|
|
949
996
|
...doc.metadata ? { metadata: doc.metadata } : {},
|
|
950
|
-
...doc.subject ? { subject: { ...doc.subject } } : {}
|
|
997
|
+
...doc.subject ? { subject: { ...doc.subject } } : {},
|
|
998
|
+
...doc.organizationId ? { organizationId: doc.organizationId } : {}
|
|
951
999
|
};
|
|
952
1000
|
}
|
|
1001
|
+
/** The payload's organization: its own metadata first, then the recipient's resolver stamp. */
|
|
1002
|
+
function organizationOf(payload) {
|
|
1003
|
+
const fromPayload = payload.metadata?.organizationId;
|
|
1004
|
+
if (typeof fromPayload === "string" && fromPayload !== "") return fromPayload;
|
|
1005
|
+
const fromRecipient = payload.recipient.metadata?.organizationId;
|
|
1006
|
+
return typeof fromRecipient === "string" && fromRecipient !== "" ? fromRecipient : null;
|
|
1007
|
+
}
|
|
953
1008
|
function createRepositoryDeliveryLog(repository, options = {}) {
|
|
954
1009
|
const { defaultLimit = 100 } = options;
|
|
955
1010
|
return {
|
|
@@ -964,7 +1019,8 @@ function createRepositoryDeliveryLog(repository, options = {}) {
|
|
|
964
1019
|
status: deriveStatus(dispatch),
|
|
965
1020
|
duration: dispatch.duration,
|
|
966
1021
|
...payload.metadata ? { metadata: payload.metadata } : {},
|
|
967
|
-
...payload.subject ? { subject: payload.subject } : {}
|
|
1022
|
+
...payload.subject ? { subject: payload.subject } : {},
|
|
1023
|
+
organizationId: organizationOf(payload)
|
|
968
1024
|
};
|
|
969
1025
|
await repository.create(doc);
|
|
970
1026
|
},
|
|
@@ -1398,7 +1454,8 @@ function toGatedNotifyTriggers(t, options, overrides) {
|
|
|
1398
1454
|
channels: declaredChannels(t),
|
|
1399
1455
|
title: t.template.title,
|
|
1400
1456
|
message: t.template.message,
|
|
1401
|
-
...t.priority ? { priority: t.priority } : {}
|
|
1457
|
+
...t.priority ? { priority: t.priority } : {},
|
|
1458
|
+
...t.sourceChannels ? { sourceChannels: t.sourceChannels } : {}
|
|
1402
1459
|
};
|
|
1403
1460
|
/**
|
|
1404
1461
|
* The effective settings resolve ONCE per event per trigger, shared by every
|
|
@@ -1473,10 +1530,20 @@ function toGatedNotifyTriggers(t, options, overrides) {
|
|
|
1473
1530
|
organizationId: ex.organizationId
|
|
1474
1531
|
};
|
|
1475
1532
|
}
|
|
1476
|
-
|
|
1533
|
+
/**
|
|
1534
|
+
* An operator who cleared the list means nobody — skip rather than
|
|
1535
|
+
* dispatching to an empty audience the resolver would widen.
|
|
1536
|
+
*
|
|
1537
|
+
* Literal addresses count as an audience. Someone who wants order mail at
|
|
1538
|
+
* `ops@` and nowhere else clears the roles and types the address; treating
|
|
1539
|
+
* that as "no recipients" would silence exactly the configuration they
|
|
1540
|
+
* just built, and report it as their own doing.
|
|
1541
|
+
*/
|
|
1542
|
+
if (eff.recipients.length === 0 && eff.recipientEmails.length === 0) return skip("no_recipients");
|
|
1477
1543
|
return {
|
|
1478
1544
|
roles: eff.recipients,
|
|
1479
1545
|
organizationId: ex.organizationId,
|
|
1546
|
+
...eff.recipientEmails.length > 0 ? { recipientEmails: eff.recipientEmails } : {},
|
|
1480
1547
|
...ex.triggeredBy ? { excludeUserId: ex.triggeredBy } : {}
|
|
1481
1548
|
};
|
|
1482
1549
|
}
|
|
@@ -1524,4 +1591,4 @@ function getRecipientMatrix(triggers) {
|
|
|
1524
1591
|
return matrix;
|
|
1525
1592
|
}
|
|
1526
1593
|
//#endregion
|
|
1527
|
-
export { DEFAULT_ENTITY_ID_VARS, INAPP_DATA_KEY, IN_APP_CHANNEL, InAppChannel, SseChannel, createCachedTriggerOverrideStore, createDbFirstResolver, createInAppBackfill, createNotificationChannelCatalog, createRepositoryDeliveryLog, createUnreadCountCache, dispatchTrigger, evaluateSourceChannel, getRecipientMatrix, getRegisteredEvents, getTriggerByEvent, getTriggersByEvent, inAppFeedResource, notificationsJob, notificationsModule, readInAppContent, renderInApp, resolveEffectiveSettings, templatesResource, toNotifyTrigger, toNotifyTriggers };
|
|
1594
|
+
export { DEFAULT_ENTITY_ID_VARS, INAPP_DATA_KEY, IN_APP_CHANNEL, InAppChannel, SseChannel, createCachedTriggerOverrideStore, createDbFirstResolver, createInAppBackfill, createNotificationChannelCatalog, createRepositoryDeliveryLog, createUnreadCountCache, dispatchTrigger, evaluateSourceChannel, getRecipientMatrix, getRegisteredEvents, getTriggerByEvent, getTriggersByEvent, inAppFeedResource, notificationsJob, notificationsModule, notifyTriggerHandlers, readInAppContent, renderInApp, resolveEffectiveSettings, templatesResource, toNotifyTrigger, toNotifyTriggers };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/arc-notifications",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"description": "Notifications module for @classytic/arc — domain events → multi-channel notifications via @classytic/notifications, with DB-draftable templates, repo-backed delivery log, and a templates resource",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -29,10 +29,10 @@
|
|
|
29
29
|
"prepublishOnly": "node ../../scripts/prepublish-gate.mjs"
|
|
30
30
|
},
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@classytic/arc": ">=2.
|
|
33
|
-
"@classytic/notifications": ">=2.
|
|
34
|
-
"@classytic/primitives": ">=0.
|
|
35
|
-
"@classytic/repo-core": ">=0.
|
|
32
|
+
"@classytic/arc": ">=2.43.0",
|
|
33
|
+
"@classytic/notifications": ">=2.6.0",
|
|
34
|
+
"@classytic/primitives": ">=0.31.0",
|
|
35
|
+
"@classytic/repo-core": ">=0.31.0"
|
|
36
36
|
},
|
|
37
37
|
"keywords": [
|
|
38
38
|
"arc",
|