@ttt-productions/notification-core 0.2.1 → 0.2.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.
- package/dist/index.d.ts +1 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -2
- package/dist/index.js.map +1 -1
- package/dist/react/components/NotificationEmptyState.d.ts +6 -0
- package/dist/react/components/NotificationEmptyState.d.ts.map +1 -0
- package/dist/react/components/NotificationEmptyState.js +9 -0
- package/dist/react/components/NotificationEmptyState.js.map +1 -0
- package/dist/react/components/NotificationHistoryList.d.ts +7 -0
- package/dist/react/components/NotificationHistoryList.d.ts.map +1 -0
- package/dist/react/components/NotificationHistoryList.js +41 -0
- package/dist/react/components/NotificationHistoryList.js.map +1 -0
- package/dist/react/components/NotificationList.d.ts +6 -0
- package/dist/react/components/NotificationList.d.ts.map +1 -0
- package/dist/react/components/NotificationList.js +79 -0
- package/dist/react/components/NotificationList.js.map +1 -0
- package/dist/react/components/NotificationUnreadBadge.d.ts +8 -0
- package/dist/react/components/NotificationUnreadBadge.d.ts.map +1 -0
- package/dist/react/components/NotificationUnreadBadge.js +21 -0
- package/dist/react/components/NotificationUnreadBadge.js.map +1 -0
- package/dist/react/components/index.d.ts +5 -0
- package/dist/react/components/index.d.ts.map +1 -0
- package/dist/react/components/index.js +5 -0
- package/dist/react/components/index.js.map +1 -0
- package/dist/react/components/relative-time.d.ts +5 -0
- package/dist/react/components/relative-time.d.ts.map +1 -0
- package/dist/react/components/relative-time.js +23 -0
- package/dist/react/components/relative-time.js.map +1 -0
- package/dist/react/hooks/index.d.ts +6 -0
- package/dist/react/hooks/index.d.ts.map +1 -0
- package/dist/react/hooks/index.js +6 -0
- package/dist/react/hooks/index.js.map +1 -0
- package/dist/react/hooks/useActiveNotifications.d.ts +7 -0
- package/dist/react/hooks/useActiveNotifications.d.ts.map +1 -0
- package/dist/react/hooks/useActiveNotifications.js +30 -0
- package/dist/react/hooks/useActiveNotifications.js.map +1 -0
- package/dist/react/hooks/useArchiveAllNotifications.d.ts +24 -0
- package/dist/react/hooks/useArchiveAllNotifications.d.ts.map +1 -0
- package/dist/react/hooks/useArchiveAllNotifications.js +87 -0
- package/dist/react/hooks/useArchiveAllNotifications.js.map +1 -0
- package/dist/react/hooks/useArchiveNotification.d.ts +23 -0
- package/dist/react/hooks/useArchiveNotification.d.ts.map +1 -0
- package/dist/react/hooks/useArchiveNotification.js +68 -0
- package/dist/react/hooks/useArchiveNotification.js.map +1 -0
- package/dist/react/hooks/useNotificationHistory.d.ts +16 -0
- package/dist/react/hooks/useNotificationHistory.d.ts.map +1 -0
- package/dist/react/hooks/useNotificationHistory.js +35 -0
- package/dist/react/hooks/useNotificationHistory.js.map +1 -0
- package/dist/react/hooks/useUnreadCount.d.ts +184 -0
- package/dist/react/hooks/useUnreadCount.d.ts.map +1 -0
- package/dist/react/hooks/useUnreadCount.js +45 -0
- package/dist/react/hooks/useUnreadCount.js.map +1 -0
- package/dist/react/index.d.ts +3 -0
- package/dist/react/index.d.ts.map +1 -0
- package/dist/react/index.js +5 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/archiveNotificationHelper.d.ts +31 -0
- package/dist/server/archiveNotificationHelper.d.ts.map +1 -0
- package/dist/server/archiveNotificationHelper.js +83 -0
- package/dist/server/archiveNotificationHelper.js.map +1 -0
- package/dist/server/createNotificationHelper.d.ts +25 -0
- package/dist/server/createNotificationHelper.d.ts.map +1 -0
- package/dist/server/createNotificationHelper.js +118 -0
- package/dist/server/createNotificationHelper.js.map +1 -0
- package/dist/server/index.d.ts +5 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +5 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/processBatchHelper.d.ts +29 -0
- package/dist/server/processBatchHelper.d.ts.map +1 -0
- package/dist/server/processBatchHelper.js +158 -0
- package/dist/server/processBatchHelper.js.map +1 -0
- package/dist/server/types.d.ts +81 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/types.js +6 -0
- package/dist/server/types.js.map +1 -0
- package/dist/types.d.ts +159 -44
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -1
- package/package.json +10 -6
- package/src/styles/notifications.css +206 -0
- package/dist/hooks/index.d.ts +0 -9
- package/dist/hooks/index.d.ts.map +0 -1
- package/dist/hooks/index.js +0 -5
- package/dist/hooks/index.js.map +0 -1
- package/dist/hooks/useMarkAllAsRead.d.ts +0 -30
- package/dist/hooks/useMarkAllAsRead.d.ts.map +0 -1
- package/dist/hooks/useMarkAllAsRead.js +0 -44
- package/dist/hooks/useMarkAllAsRead.js.map +0 -1
- package/dist/hooks/useMarkAsRead.d.ts +0 -30
- package/dist/hooks/useMarkAsRead.d.ts.map +0 -1
- package/dist/hooks/useMarkAsRead.js +0 -40
- package/dist/hooks/useMarkAsRead.js.map +0 -1
- package/dist/hooks/useNotifications.d.ts +0 -25
- package/dist/hooks/useNotifications.d.ts.map +0 -1
- package/dist/hooks/useNotifications.js +0 -31
- package/dist/hooks/useNotifications.js.map +0 -1
- package/dist/hooks/useUnreadCount.d.ts +0 -24
- package/dist/hooks/useUnreadCount.d.ts.map +0 -1
- package/dist/hooks/useUnreadCount.js +0 -31
- package/dist/hooks/useUnreadCount.js.map +0 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch processor helper — called by the app's scheduled Cloud Function.
|
|
3
|
+
* Reads pending notifications, groups by dedupKey, creates/increments active docs.
|
|
4
|
+
*/
|
|
5
|
+
import type { NotificationSystemConfig } from '../types.js';
|
|
6
|
+
import type { ServerFirestore } from './types.js';
|
|
7
|
+
interface BatchProcessResult {
|
|
8
|
+
totalProcessed: number;
|
|
9
|
+
notificationsCreated: number;
|
|
10
|
+
notificationsUpdated: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Process the pending notifications queue.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* // In your scheduled Cloud Function:
|
|
18
|
+
* export const processNotificationBatch = onSchedule(
|
|
19
|
+
* { schedule: 'every 10 minutes' },
|
|
20
|
+
* async () => {
|
|
21
|
+
* const result = await processBatchHelper(db as any, TTT_NOTIFICATION_CONFIG);
|
|
22
|
+
* logger.info('Batch processed', result);
|
|
23
|
+
* }
|
|
24
|
+
* );
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function processBatchHelper(db: ServerFirestore, config: NotificationSystemConfig): Promise<BatchProcessResult>;
|
|
28
|
+
export {};
|
|
29
|
+
//# sourceMappingURL=processBatchHelper.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processBatchHelper.d.ts","sourceRoot":"","sources":["../../src/server/processBatchHelper.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,wBAAwB,EAAuB,MAAM,aAAa,CAAC;AACjF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAOlD,UAAU,kBAAkB;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,kBAAkB,CACtC,EAAE,EAAE,eAAe,EACnB,MAAM,EAAE,wBAAwB,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAmK7B"}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Batch processor helper — called by the app's scheduled Cloud Function.
|
|
3
|
+
* Reads pending notifications, groups by dedupKey, creates/increments active docs.
|
|
4
|
+
*/
|
|
5
|
+
const DEFAULT_COUNT_CAP = 5000;
|
|
6
|
+
const DEFAULT_ACTOR_CAP = 5;
|
|
7
|
+
const PROCESSING_BATCH_SIZE = 500;
|
|
8
|
+
const MAX_ITERATIONS = 20;
|
|
9
|
+
/**
|
|
10
|
+
* Process the pending notifications queue.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* // In your scheduled Cloud Function:
|
|
15
|
+
* export const processNotificationBatch = onSchedule(
|
|
16
|
+
* { schedule: 'every 10 minutes' },
|
|
17
|
+
* async () => {
|
|
18
|
+
* const result = await processBatchHelper(db as any, TTT_NOTIFICATION_CONFIG);
|
|
19
|
+
* logger.info('Batch processed', result);
|
|
20
|
+
* }
|
|
21
|
+
* );
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export async function processBatchHelper(db, config) {
|
|
25
|
+
const pendingPath = config.pendingCollectionPath ?? 'pendingNotifications';
|
|
26
|
+
const cutoff = Date.now() - 30_000; // Process items older than 30 seconds
|
|
27
|
+
let totalProcessed = 0;
|
|
28
|
+
let notificationsCreated = 0;
|
|
29
|
+
let notificationsUpdated = 0;
|
|
30
|
+
let iterations = 0;
|
|
31
|
+
let hasMore = true;
|
|
32
|
+
while (hasMore && iterations < MAX_ITERATIONS) {
|
|
33
|
+
iterations++;
|
|
34
|
+
const pendingQuery = db.collection(pendingPath)
|
|
35
|
+
.where('createdAt', '<=', cutoff)
|
|
36
|
+
.orderBy('createdAt', 'asc')
|
|
37
|
+
.limit(PROCESSING_BATCH_SIZE);
|
|
38
|
+
const snapshot = await pendingQuery.get();
|
|
39
|
+
if (snapshot.empty) {
|
|
40
|
+
hasMore = false;
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
// Group by dedupKey
|
|
44
|
+
const groups = new Map();
|
|
45
|
+
for (const docSnap of snapshot.docs) {
|
|
46
|
+
const data = docSnap.data();
|
|
47
|
+
const typeConfig = config.types[data.type];
|
|
48
|
+
if (!typeConfig)
|
|
49
|
+
continue;
|
|
50
|
+
const dedupKey = typeConfig.dedupKeyPattern(data.metadata);
|
|
51
|
+
const groupKey = `${data.category}::${dedupKey}`;
|
|
52
|
+
const existing = groups.get(groupKey);
|
|
53
|
+
if (existing) {
|
|
54
|
+
existing.count++;
|
|
55
|
+
// Add actor if not already present
|
|
56
|
+
if (!existing.actors.some((a) => a.id === data.actorId)) {
|
|
57
|
+
existing.actors.push({ id: data.actorId, name: data.actorName });
|
|
58
|
+
}
|
|
59
|
+
existing.docs.push(docSnap);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
groups.set(groupKey, {
|
|
63
|
+
type: data.type,
|
|
64
|
+
category: data.category,
|
|
65
|
+
targetUserId: data.targetUserId,
|
|
66
|
+
metadata: data.metadata,
|
|
67
|
+
actors: [{ id: data.actorId, name: data.actorName }],
|
|
68
|
+
count: 1,
|
|
69
|
+
docs: [docSnap],
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Process each group: dedup check against active, create or increment
|
|
74
|
+
for (const [, group] of groups) {
|
|
75
|
+
const typeConfig = config.types[group.type];
|
|
76
|
+
if (!typeConfig)
|
|
77
|
+
continue;
|
|
78
|
+
const categoryConfig = config.categories[group.category];
|
|
79
|
+
if (!categoryConfig)
|
|
80
|
+
continue;
|
|
81
|
+
const activePath = categoryConfig.activePath;
|
|
82
|
+
const dedupKey = typeConfig.dedupKeyPattern(group.metadata);
|
|
83
|
+
const countCap = typeConfig.countCap ?? DEFAULT_COUNT_CAP;
|
|
84
|
+
const actorCap = typeConfig.actorCap ?? DEFAULT_ACTOR_CAP;
|
|
85
|
+
// Check for existing active notification
|
|
86
|
+
const existingQuery = db.collection(activePath)
|
|
87
|
+
.where('dedupKey', '==', dedupKey)
|
|
88
|
+
.where('category', '==', group.category)
|
|
89
|
+
.limit(1);
|
|
90
|
+
const existingSnap = await existingQuery.get();
|
|
91
|
+
if (!existingSnap.empty) {
|
|
92
|
+
// Increment existing
|
|
93
|
+
const existingDoc = existingSnap.docs[0];
|
|
94
|
+
const existingData = existingDoc.data();
|
|
95
|
+
const currentCount = existingData.count || 1;
|
|
96
|
+
const currentActorIds = existingData.latestActorIds || [];
|
|
97
|
+
const currentActorNames = existingData.latestActorNames || [];
|
|
98
|
+
// Merge actors (new first, deduped, capped)
|
|
99
|
+
const newActors = group.actors.filter((a) => !currentActorIds.includes(a.id));
|
|
100
|
+
const mergedActorIds = [
|
|
101
|
+
...newActors.map((a) => a.id),
|
|
102
|
+
...currentActorIds,
|
|
103
|
+
].slice(0, actorCap);
|
|
104
|
+
const mergedActorNames = [
|
|
105
|
+
...newActors.map((a) => a.name),
|
|
106
|
+
...currentActorNames,
|
|
107
|
+
].slice(0, actorCap);
|
|
108
|
+
const newCount = Math.min(currentCount + group.count, countCap);
|
|
109
|
+
await existingDoc.ref.update({
|
|
110
|
+
count: newCount,
|
|
111
|
+
latestActorIds: mergedActorIds,
|
|
112
|
+
latestActorNames: mergedActorNames,
|
|
113
|
+
message: typeConfig.messagePattern(group.metadata, newCount),
|
|
114
|
+
updatedAt: Date.now(),
|
|
115
|
+
});
|
|
116
|
+
notificationsUpdated++;
|
|
117
|
+
}
|
|
118
|
+
else {
|
|
119
|
+
// Create new notification
|
|
120
|
+
const targetPath = typeof typeConfig.defaultTargetPath === 'function'
|
|
121
|
+
? typeConfig.defaultTargetPath(group.metadata)
|
|
122
|
+
: typeConfig.defaultTargetPath;
|
|
123
|
+
const now = Date.now();
|
|
124
|
+
const newDoc = {
|
|
125
|
+
type: group.type,
|
|
126
|
+
dedupKey,
|
|
127
|
+
category: group.category,
|
|
128
|
+
targetUserId: group.targetUserId,
|
|
129
|
+
title: typeConfig.titlePattern(group.metadata),
|
|
130
|
+
message: typeConfig.messagePattern(group.metadata, group.count),
|
|
131
|
+
count: group.count,
|
|
132
|
+
latestActorIds: group.actors.map((a) => a.id).slice(0, actorCap),
|
|
133
|
+
latestActorNames: group.actors.map((a) => a.name).slice(0, actorCap),
|
|
134
|
+
targetPath,
|
|
135
|
+
metadata: group.metadata,
|
|
136
|
+
createdAt: now,
|
|
137
|
+
updatedAt: now,
|
|
138
|
+
};
|
|
139
|
+
await db.collection(activePath).add(newDoc);
|
|
140
|
+
notificationsCreated++;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Delete processed pending docs in batches of 500
|
|
144
|
+
const allDocs = snapshot.docs;
|
|
145
|
+
for (let i = 0; i < allDocs.length; i += 500) {
|
|
146
|
+
const chunk = allDocs.slice(i, i + 500);
|
|
147
|
+
const batch = db.batch();
|
|
148
|
+
chunk.forEach((docSnap) => batch.delete(docSnap.ref));
|
|
149
|
+
await batch.commit();
|
|
150
|
+
}
|
|
151
|
+
totalProcessed += snapshot.size;
|
|
152
|
+
if (snapshot.size < PROCESSING_BATCH_SIZE) {
|
|
153
|
+
hasMore = false;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return { totalProcessed, notificationsCreated, notificationsUpdated };
|
|
157
|
+
}
|
|
158
|
+
//# sourceMappingURL=processBatchHelper.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processBatchHelper.js","sourceRoot":"","sources":["../../src/server/processBatchHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server-side types for notification-core backend helpers.
|
|
3
|
+
* These use firebase-admin Firestore types passed in by the calling app.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Firestore interface — matches firebase-admin's Firestore type.
|
|
7
|
+
* We accept this instead of importing firebase-admin directly.
|
|
8
|
+
*/
|
|
9
|
+
export interface ServerFirestore {
|
|
10
|
+
collection(path: string): ServerCollectionRef;
|
|
11
|
+
doc(path: string): ServerDocRef;
|
|
12
|
+
batch(): ServerWriteBatch;
|
|
13
|
+
}
|
|
14
|
+
export interface ServerCollectionRef {
|
|
15
|
+
doc(id?: string): ServerDocRef;
|
|
16
|
+
where(field: string, op: string, value: unknown): ServerQuery;
|
|
17
|
+
orderBy(field: string, direction?: 'asc' | 'desc'): ServerQuery;
|
|
18
|
+
limit(n: number): ServerQuery;
|
|
19
|
+
add(data: Record<string, unknown>): Promise<ServerDocRef>;
|
|
20
|
+
}
|
|
21
|
+
export interface ServerQuery {
|
|
22
|
+
where(field: string, op: string, value: unknown): ServerQuery;
|
|
23
|
+
orderBy(field: string, direction?: 'asc' | 'desc'): ServerQuery;
|
|
24
|
+
limit(n: number): ServerQuery;
|
|
25
|
+
get(): Promise<ServerQuerySnapshot>;
|
|
26
|
+
}
|
|
27
|
+
export interface ServerQuerySnapshot {
|
|
28
|
+
empty: boolean;
|
|
29
|
+
size: number;
|
|
30
|
+
docs: ServerDocSnapshot[];
|
|
31
|
+
}
|
|
32
|
+
export interface ServerDocSnapshot {
|
|
33
|
+
id: string;
|
|
34
|
+
exists: boolean;
|
|
35
|
+
data(): Record<string, unknown> | undefined;
|
|
36
|
+
ref: ServerDocRef;
|
|
37
|
+
}
|
|
38
|
+
export interface ServerDocRef {
|
|
39
|
+
id: string;
|
|
40
|
+
set(data: Record<string, unknown>, options?: {
|
|
41
|
+
merge?: boolean;
|
|
42
|
+
}): Promise<unknown>;
|
|
43
|
+
update(data: Record<string, unknown>): Promise<unknown>;
|
|
44
|
+
delete(): Promise<unknown>;
|
|
45
|
+
get(): Promise<ServerDocSnapshot>;
|
|
46
|
+
}
|
|
47
|
+
export interface ServerWriteBatch {
|
|
48
|
+
set(ref: ServerDocRef, data: Record<string, unknown>, options?: {
|
|
49
|
+
merge?: boolean;
|
|
50
|
+
}): ServerWriteBatch;
|
|
51
|
+
update(ref: ServerDocRef, data: Record<string, unknown>): ServerWriteBatch;
|
|
52
|
+
delete(ref: ServerDocRef): ServerWriteBatch;
|
|
53
|
+
commit(): Promise<unknown>;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Input for creating a notification via the helper.
|
|
57
|
+
*/
|
|
58
|
+
export interface CreateNotificationInput {
|
|
59
|
+
/** Notification type (must exist in config.types) */
|
|
60
|
+
type: string;
|
|
61
|
+
/** Actor who triggered this notification */
|
|
62
|
+
actorId: string;
|
|
63
|
+
/** Actor display name */
|
|
64
|
+
actorName: string;
|
|
65
|
+
/** Target user ID (required for 'personal' audience types) */
|
|
66
|
+
targetUserId?: string | null;
|
|
67
|
+
/** Type-specific metadata */
|
|
68
|
+
metadata: Record<string, unknown>;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Return type from createNotificationHelper factory.
|
|
72
|
+
*/
|
|
73
|
+
export interface NotificationHelper {
|
|
74
|
+
/** Send a notification using the configured delivery mode (realtime or queued) */
|
|
75
|
+
send(input: CreateNotificationInput): Promise<void>;
|
|
76
|
+
/** Send immediately (bypass queue, write directly to active collection) */
|
|
77
|
+
sendRealTime(input: CreateNotificationInput): Promise<void>;
|
|
78
|
+
/** Queue for batch processing */
|
|
79
|
+
queueForBatch(input: CreateNotificationInput): Promise<void>;
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,73 +1,188 @@
|
|
|
1
|
-
import type { Timestamp } from 'firebase/firestore';
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
2
|
+
* @ttt-productions/notification-core — Type definitions
|
|
3
|
+
*
|
|
4
|
+
* Two-tier notification system: active (unread) → history (archived).
|
|
5
|
+
* No `isRead` flag — existence in the active collection means unread.
|
|
4
6
|
*/
|
|
5
|
-
export type NotificationType = string;
|
|
6
7
|
/**
|
|
7
|
-
*
|
|
8
|
+
* Active notification document stored in Firestore.
|
|
9
|
+
* Same shape for both user and admin collections.
|
|
8
10
|
*/
|
|
9
|
-
export interface
|
|
10
|
-
/**
|
|
11
|
+
export interface NotificationDoc {
|
|
12
|
+
/** Firestore doc ID */
|
|
11
13
|
id: string;
|
|
12
|
-
/**
|
|
13
|
-
type:
|
|
14
|
+
/** Notification type (e.g. 'content_report', 'project_invite') */
|
|
15
|
+
type: string;
|
|
16
|
+
/** Dedup key (e.g. 'report_projectXYZ') — same key = same notification */
|
|
17
|
+
dedupKey: string;
|
|
18
|
+
/** Category: 'user' | 'admin' (extensible) */
|
|
19
|
+
category: string;
|
|
20
|
+
/** userId for 'user' category, null for 'admin' (shared) */
|
|
21
|
+
targetUserId: string | null;
|
|
14
22
|
/** Notification title */
|
|
15
23
|
title: string;
|
|
16
|
-
/** Notification
|
|
24
|
+
/** Notification body */
|
|
17
25
|
message: string;
|
|
18
|
-
/**
|
|
26
|
+
/** Incremented on duplicates */
|
|
27
|
+
count: number;
|
|
28
|
+
/** Last N actor user IDs (capped) */
|
|
29
|
+
latestActorIds: string[];
|
|
30
|
+
/** Display names matching latestActorIds */
|
|
31
|
+
latestActorNames: string[];
|
|
32
|
+
/** Route path when clicked (e.g. '/admin' or '/projects/abc') */
|
|
19
33
|
targetPath: string;
|
|
20
|
-
/**
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
/** Optional type-specific metadata */
|
|
27
|
-
metadata?: Record<string, any>;
|
|
34
|
+
/** Type-specific metadata (e.g. { projectId, reason }) */
|
|
35
|
+
metadata: Record<string, unknown>;
|
|
36
|
+
/** First occurrence */
|
|
37
|
+
createdAt: number;
|
|
38
|
+
/** Latest occurrence */
|
|
39
|
+
updatedAt: number;
|
|
28
40
|
}
|
|
29
41
|
/**
|
|
30
|
-
*
|
|
42
|
+
* Archival audit trail — stored on every history doc.
|
|
31
43
|
*/
|
|
32
|
-
export
|
|
44
|
+
export interface ArchivalInfo {
|
|
45
|
+
/** userId who clicked/dismissed */
|
|
46
|
+
archivedBy: string;
|
|
47
|
+
/** Epoch ms */
|
|
48
|
+
archivedAt: number;
|
|
49
|
+
/** Device context */
|
|
50
|
+
device: 'web' | 'mobile';
|
|
51
|
+
}
|
|
33
52
|
/**
|
|
34
|
-
*
|
|
53
|
+
* History document — extends active with archival info.
|
|
35
54
|
*/
|
|
36
|
-
export interface
|
|
37
|
-
/**
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
|
|
55
|
+
export interface NotificationHistoryDoc extends NotificationDoc {
|
|
56
|
+
/** Who/when/how it was archived */
|
|
57
|
+
archival: ArchivalInfo;
|
|
58
|
+
/** Admin userId (admin history only, quick-access field) */
|
|
59
|
+
handledBy?: string;
|
|
41
60
|
}
|
|
42
61
|
/**
|
|
43
|
-
*
|
|
62
|
+
* Pending notification — queue item for the batch processor.
|
|
44
63
|
*/
|
|
45
|
-
export interface
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
64
|
+
export interface PendingNotification {
|
|
65
|
+
id: string;
|
|
66
|
+
/** Notification type */
|
|
67
|
+
type: string;
|
|
68
|
+
/** Target category */
|
|
69
|
+
category: string;
|
|
70
|
+
/** Target userId (null for admin/shared) */
|
|
71
|
+
targetUserId: string | null;
|
|
72
|
+
/** Who triggered this */
|
|
73
|
+
actorId: string;
|
|
74
|
+
/** Actor display name */
|
|
75
|
+
actorName: string;
|
|
76
|
+
/** Type-specific data for building the notification */
|
|
77
|
+
metadata: Record<string, unknown>;
|
|
78
|
+
/** Epoch ms */
|
|
79
|
+
createdAt: number;
|
|
50
80
|
}
|
|
51
81
|
/**
|
|
52
|
-
*
|
|
82
|
+
* Per-category configuration (user vs admin).
|
|
53
83
|
*/
|
|
54
|
-
export
|
|
84
|
+
export interface NotificationCategoryConfig {
|
|
85
|
+
/** Firestore collection path for active notifications */
|
|
86
|
+
activePath: string;
|
|
87
|
+
/** Function that returns the history collection path */
|
|
88
|
+
historyPath: (userId?: string) => string;
|
|
89
|
+
/** 'personal' requires targetUserId, 'shared' = all members see everything */
|
|
90
|
+
audienceType: 'personal' | 'shared';
|
|
91
|
+
}
|
|
55
92
|
/**
|
|
56
|
-
*
|
|
93
|
+
* Per-type configuration for a notification type.
|
|
57
94
|
*/
|
|
58
95
|
export interface NotificationTypeConfig {
|
|
59
|
-
/**
|
|
96
|
+
/** Which category this type belongs to */
|
|
97
|
+
category: string;
|
|
98
|
+
/** Delivery mode */
|
|
99
|
+
delivery: 'realtime' | 'queued';
|
|
100
|
+
/** Function to build the dedupKey from metadata */
|
|
101
|
+
dedupKeyPattern: (metadata: Record<string, unknown>) => string;
|
|
102
|
+
/** Function to build the title from metadata */
|
|
103
|
+
titlePattern: (metadata: Record<string, unknown>) => string;
|
|
104
|
+
/** Function to build the message from metadata + count */
|
|
105
|
+
messagePattern: (metadata: Record<string, unknown>, count: number) => string;
|
|
106
|
+
/** Default target path, or function to build from metadata */
|
|
107
|
+
defaultTargetPath: string | ((metadata: Record<string, unknown>) => string);
|
|
108
|
+
/** Max count value (default 5000) */
|
|
109
|
+
countCap?: number;
|
|
110
|
+
/** Max latestActorIds array length (default 5) */
|
|
111
|
+
actorCap?: number;
|
|
112
|
+
/** Icon/emoji for display (optional) */
|
|
60
113
|
icon?: string;
|
|
61
|
-
/** Color theme for the notification */
|
|
62
|
-
color?: string;
|
|
63
|
-
/** Custom navigation handler for this type */
|
|
64
|
-
navigateTo?: (params?: Record<string, any>) => string;
|
|
65
114
|
}
|
|
66
115
|
/**
|
|
67
|
-
*
|
|
116
|
+
* Full notification system configuration — provided by each app.
|
|
68
117
|
*/
|
|
69
|
-
export interface
|
|
70
|
-
/**
|
|
71
|
-
|
|
118
|
+
export interface NotificationSystemConfig {
|
|
119
|
+
/** Category definitions */
|
|
120
|
+
categories: Record<string, NotificationCategoryConfig>;
|
|
121
|
+
/** Type definitions */
|
|
122
|
+
types: Record<string, NotificationTypeConfig>;
|
|
123
|
+
/** Batch processor interval in minutes (default 10) */
|
|
124
|
+
batchIntervalMinutes?: number;
|
|
125
|
+
/** Firestore collection for pending notifications (default 'pendingNotifications') */
|
|
126
|
+
pendingCollectionPath?: string;
|
|
127
|
+
}
|
|
128
|
+
export interface UseActiveNotificationsOptions {
|
|
129
|
+
config: NotificationSystemConfig;
|
|
130
|
+
userId: string;
|
|
131
|
+
category: string;
|
|
132
|
+
enabled?: boolean;
|
|
133
|
+
pageSize?: number;
|
|
134
|
+
refetchInterval?: number;
|
|
135
|
+
}
|
|
136
|
+
export interface UseUnreadCountOptions {
|
|
137
|
+
config: NotificationSystemConfig;
|
|
138
|
+
userId: string;
|
|
139
|
+
category: string;
|
|
140
|
+
enabled?: boolean;
|
|
141
|
+
refetchInterval?: number;
|
|
142
|
+
countLimit?: number;
|
|
143
|
+
}
|
|
144
|
+
export interface UseArchiveNotificationOptions {
|
|
145
|
+
config: NotificationSystemConfig;
|
|
146
|
+
userId: string;
|
|
147
|
+
category: string;
|
|
148
|
+
invalidateKeys?: readonly unknown[][];
|
|
149
|
+
}
|
|
150
|
+
export interface UseArchiveAllNotificationsOptions {
|
|
151
|
+
config: NotificationSystemConfig;
|
|
152
|
+
userId: string;
|
|
153
|
+
category: string;
|
|
154
|
+
invalidateKeys?: readonly unknown[][];
|
|
155
|
+
}
|
|
156
|
+
export interface UseNotificationHistoryOptions {
|
|
157
|
+
config: NotificationSystemConfig;
|
|
158
|
+
userId: string;
|
|
159
|
+
category: string;
|
|
160
|
+
enabled?: boolean;
|
|
161
|
+
pageSize?: number;
|
|
162
|
+
}
|
|
163
|
+
export interface NotificationListProps {
|
|
164
|
+
config: NotificationSystemConfig;
|
|
165
|
+
userId: string;
|
|
166
|
+
category: string;
|
|
167
|
+
onNotificationClick: (notification: NotificationDoc) => void;
|
|
168
|
+
onClearAll?: () => void;
|
|
169
|
+
refetchInterval?: number;
|
|
170
|
+
device?: 'web' | 'mobile';
|
|
171
|
+
emptyText?: string;
|
|
172
|
+
}
|
|
173
|
+
export interface NotificationEmptyStateProps {
|
|
174
|
+
text?: string;
|
|
175
|
+
}
|
|
176
|
+
export interface NotificationHistoryListProps {
|
|
177
|
+
config: NotificationSystemConfig;
|
|
178
|
+
userId: string;
|
|
179
|
+
category: string;
|
|
180
|
+
onNotificationClick?: (notification: NotificationHistoryDoc) => void;
|
|
181
|
+
}
|
|
182
|
+
export interface NotificationUnreadBadgeProps {
|
|
183
|
+
config: NotificationSystemConfig;
|
|
184
|
+
userId: string;
|
|
185
|
+
category: string;
|
|
186
|
+
refetchInterval?: number;
|
|
72
187
|
}
|
|
73
188
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,uBAAuB;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,kEAAkE;IAClE,IAAI,EAAE,MAAM,CAAC;IACb,0EAA0E;IAC1E,QAAQ,EAAE,MAAM,CAAC;IACjB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,CAAC;IAGjB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAG5B,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAC;IAGhB,gCAAgC;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,qCAAqC;IACrC,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,4CAA4C;IAC5C,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAG3B,iEAAiE;IACjE,UAAU,EAAE,MAAM,CAAC;IACnB,0DAA0D;IAC1D,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAGlC,uBAAuB;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,wBAAwB;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,qBAAqB;IACrB,MAAM,EAAE,KAAK,GAAG,QAAQ,CAAC;CAC1B;AAED;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,eAAe;IAC7D,mCAAmC;IACnC,QAAQ,EAAE,YAAY,CAAC;IACvB,4DAA4D;IAC5D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,wBAAwB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,sBAAsB;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,4CAA4C;IAC5C,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,yBAAyB;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,yBAAyB;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,eAAe;IACf,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC,yDAAyD;IACzD,UAAU,EAAE,MAAM,CAAC;IACnB,wDAAwD;IACxD,WAAW,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IACzC,8EAA8E;IAC9E,YAAY,EAAE,UAAU,GAAG,QAAQ,CAAC;CACrC;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;IACjB,oBAAoB;IACpB,QAAQ,EAAE,UAAU,GAAG,QAAQ,CAAC;IAChC,mDAAmD;IACnD,eAAe,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;IAC/D,gDAAgD;IAChD,YAAY,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC;IAC5D,0DAA0D;IAC1D,cAAc,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7E,8DAA8D;IAC9D,iBAAiB,EAAE,MAAM,GAAG,CAAC,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,MAAM,CAAC,CAAC;IAC5E,qCAAqC;IACrC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,2BAA2B;IAC3B,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,0BAA0B,CAAC,CAAC;IACvD,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,sBAAsB,CAAC,CAAC;IAC9C,uDAAuD;IACvD,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,sFAAsF;IACtF,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAChC;AAMD,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,OAAO,EAAE,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,iCAAiC;IAChD,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,CAAC,EAAE,SAAS,OAAO,EAAE,EAAE,CAAC;CACvC;AAED,MAAM,WAAW,6BAA6B;IAC5C,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAMD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,EAAE,CAAC,YAAY,EAAE,eAAe,KAAK,IAAI,CAAC;IAC7D,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,KAAK,GAAG,QAAQ,CAAC;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,2BAA2B;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,CAAC,YAAY,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACtE;AAED,MAAM,WAAW,4BAA4B;IAC3C,MAAM,EAAE,wBAAwB,CAAC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B"}
|
package/dist/types.js
CHANGED
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ttt-productions/notification-core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.3",
|
|
4
4
|
"description": "Shared notification system for TTT Productions apps — active/history two-tier architecture with dedup, batch processing, and themed UI components",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -21,6 +21,10 @@
|
|
|
21
21
|
"types": "./dist/index.d.ts",
|
|
22
22
|
"default": "./dist/index.js"
|
|
23
23
|
},
|
|
24
|
+
"./react": {
|
|
25
|
+
"types": "./dist/react/index.d.ts",
|
|
26
|
+
"default": "./dist/react/index.js"
|
|
27
|
+
},
|
|
24
28
|
"./server": {
|
|
25
29
|
"types": "./dist/server/index.d.ts",
|
|
26
30
|
"default": "./dist/server/index.js"
|
|
@@ -31,20 +35,20 @@
|
|
|
31
35
|
"build": "tsc",
|
|
32
36
|
"clean": "rm -rf dist *.tsbuildinfo",
|
|
33
37
|
"typecheck": "tsc --noEmit",
|
|
34
|
-
"prepublishOnly": "npm run
|
|
38
|
+
"prepublishOnly": "npm run build"
|
|
35
39
|
},
|
|
36
40
|
"peerDependencies": {
|
|
37
41
|
"@tanstack/react-query": ">=5.0.0",
|
|
38
|
-
"@ttt-productions/query-core": "
|
|
39
|
-
"@ttt-productions/ui-core": "
|
|
42
|
+
"@ttt-productions/query-core": "*",
|
|
43
|
+
"@ttt-productions/ui-core": "*",
|
|
40
44
|
"firebase": ">=10.0.0",
|
|
41
45
|
"react": ">=18.0.0",
|
|
42
46
|
"react-dom": ">=18.0.0"
|
|
43
47
|
},
|
|
44
48
|
"devDependencies": {
|
|
45
49
|
"@tanstack/react-query": "^5.0.0",
|
|
46
|
-
"@ttt-productions/query-core": "
|
|
47
|
-
"@ttt-productions/ui-core": "
|
|
50
|
+
"@ttt-productions/query-core": "*",
|
|
51
|
+
"@ttt-productions/ui-core": "*",
|
|
48
52
|
"@types/react": "^19.0.0",
|
|
49
53
|
"@types/react-dom": "^19.0.0",
|
|
50
54
|
"firebase": "^11.0.0",
|