@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.
Files changed (102) hide show
  1. package/dist/index.d.ts +1 -3
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +1 -2
  4. package/dist/index.js.map +1 -1
  5. package/dist/react/components/NotificationEmptyState.d.ts +6 -0
  6. package/dist/react/components/NotificationEmptyState.d.ts.map +1 -0
  7. package/dist/react/components/NotificationEmptyState.js +9 -0
  8. package/dist/react/components/NotificationEmptyState.js.map +1 -0
  9. package/dist/react/components/NotificationHistoryList.d.ts +7 -0
  10. package/dist/react/components/NotificationHistoryList.d.ts.map +1 -0
  11. package/dist/react/components/NotificationHistoryList.js +41 -0
  12. package/dist/react/components/NotificationHistoryList.js.map +1 -0
  13. package/dist/react/components/NotificationList.d.ts +6 -0
  14. package/dist/react/components/NotificationList.d.ts.map +1 -0
  15. package/dist/react/components/NotificationList.js +79 -0
  16. package/dist/react/components/NotificationList.js.map +1 -0
  17. package/dist/react/components/NotificationUnreadBadge.d.ts +8 -0
  18. package/dist/react/components/NotificationUnreadBadge.d.ts.map +1 -0
  19. package/dist/react/components/NotificationUnreadBadge.js +21 -0
  20. package/dist/react/components/NotificationUnreadBadge.js.map +1 -0
  21. package/dist/react/components/index.d.ts +5 -0
  22. package/dist/react/components/index.d.ts.map +1 -0
  23. package/dist/react/components/index.js +5 -0
  24. package/dist/react/components/index.js.map +1 -0
  25. package/dist/react/components/relative-time.d.ts +5 -0
  26. package/dist/react/components/relative-time.d.ts.map +1 -0
  27. package/dist/react/components/relative-time.js +23 -0
  28. package/dist/react/components/relative-time.js.map +1 -0
  29. package/dist/react/hooks/index.d.ts +6 -0
  30. package/dist/react/hooks/index.d.ts.map +1 -0
  31. package/dist/react/hooks/index.js +6 -0
  32. package/dist/react/hooks/index.js.map +1 -0
  33. package/dist/react/hooks/useActiveNotifications.d.ts +7 -0
  34. package/dist/react/hooks/useActiveNotifications.d.ts.map +1 -0
  35. package/dist/react/hooks/useActiveNotifications.js +30 -0
  36. package/dist/react/hooks/useActiveNotifications.js.map +1 -0
  37. package/dist/react/hooks/useArchiveAllNotifications.d.ts +24 -0
  38. package/dist/react/hooks/useArchiveAllNotifications.d.ts.map +1 -0
  39. package/dist/react/hooks/useArchiveAllNotifications.js +87 -0
  40. package/dist/react/hooks/useArchiveAllNotifications.js.map +1 -0
  41. package/dist/react/hooks/useArchiveNotification.d.ts +23 -0
  42. package/dist/react/hooks/useArchiveNotification.d.ts.map +1 -0
  43. package/dist/react/hooks/useArchiveNotification.js +68 -0
  44. package/dist/react/hooks/useArchiveNotification.js.map +1 -0
  45. package/dist/react/hooks/useNotificationHistory.d.ts +16 -0
  46. package/dist/react/hooks/useNotificationHistory.d.ts.map +1 -0
  47. package/dist/react/hooks/useNotificationHistory.js +35 -0
  48. package/dist/react/hooks/useNotificationHistory.js.map +1 -0
  49. package/dist/react/hooks/useUnreadCount.d.ts +184 -0
  50. package/dist/react/hooks/useUnreadCount.d.ts.map +1 -0
  51. package/dist/react/hooks/useUnreadCount.js +45 -0
  52. package/dist/react/hooks/useUnreadCount.js.map +1 -0
  53. package/dist/react/index.d.ts +3 -0
  54. package/dist/react/index.d.ts.map +1 -0
  55. package/dist/react/index.js +5 -0
  56. package/dist/react/index.js.map +1 -0
  57. package/dist/server/archiveNotificationHelper.d.ts +31 -0
  58. package/dist/server/archiveNotificationHelper.d.ts.map +1 -0
  59. package/dist/server/archiveNotificationHelper.js +83 -0
  60. package/dist/server/archiveNotificationHelper.js.map +1 -0
  61. package/dist/server/createNotificationHelper.d.ts +25 -0
  62. package/dist/server/createNotificationHelper.d.ts.map +1 -0
  63. package/dist/server/createNotificationHelper.js +118 -0
  64. package/dist/server/createNotificationHelper.js.map +1 -0
  65. package/dist/server/index.d.ts +5 -0
  66. package/dist/server/index.d.ts.map +1 -0
  67. package/dist/server/index.js +5 -0
  68. package/dist/server/index.js.map +1 -0
  69. package/dist/server/processBatchHelper.d.ts +29 -0
  70. package/dist/server/processBatchHelper.d.ts.map +1 -0
  71. package/dist/server/processBatchHelper.js +158 -0
  72. package/dist/server/processBatchHelper.js.map +1 -0
  73. package/dist/server/types.d.ts +81 -0
  74. package/dist/server/types.d.ts.map +1 -0
  75. package/dist/server/types.js +6 -0
  76. package/dist/server/types.js.map +1 -0
  77. package/dist/types.d.ts +159 -44
  78. package/dist/types.d.ts.map +1 -1
  79. package/dist/types.js +6 -0
  80. package/dist/types.js.map +1 -1
  81. package/package.json +10 -6
  82. package/src/styles/notifications.css +206 -0
  83. package/dist/hooks/index.d.ts +0 -9
  84. package/dist/hooks/index.d.ts.map +0 -1
  85. package/dist/hooks/index.js +0 -5
  86. package/dist/hooks/index.js.map +0 -1
  87. package/dist/hooks/useMarkAllAsRead.d.ts +0 -30
  88. package/dist/hooks/useMarkAllAsRead.d.ts.map +0 -1
  89. package/dist/hooks/useMarkAllAsRead.js +0 -44
  90. package/dist/hooks/useMarkAllAsRead.js.map +0 -1
  91. package/dist/hooks/useMarkAsRead.d.ts +0 -30
  92. package/dist/hooks/useMarkAsRead.d.ts.map +0 -1
  93. package/dist/hooks/useMarkAsRead.js +0 -40
  94. package/dist/hooks/useMarkAsRead.js.map +0 -1
  95. package/dist/hooks/useNotifications.d.ts +0 -25
  96. package/dist/hooks/useNotifications.d.ts.map +0 -1
  97. package/dist/hooks/useNotifications.js +0 -31
  98. package/dist/hooks/useNotifications.js.map +0 -1
  99. package/dist/hooks/useUnreadCount.d.ts +0 -24
  100. package/dist/hooks/useUnreadCount.d.ts.map +0 -1
  101. package/dist/hooks/useUnreadCount.js +0 -31
  102. 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,6 @@
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
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -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
- * Base notification type that can be extended per app.
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
- * Core notification document structure stored in Firestore.
8
+ * Active notification document stored in Firestore.
9
+ * Same shape for both user and admin collections.
8
10
  */
9
- export interface Notification {
10
- /** Unique notification ID (usually Firestore doc ID) */
11
+ export interface NotificationDoc {
12
+ /** Firestore doc ID */
11
13
  id: string;
12
- /** Type of notification - app-specific (e.g., 'trophy_received', 'game_scheduled') */
13
- type: NotificationType;
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 message/body */
24
+ /** Notification body */
17
25
  message: string;
18
- /** Target path to navigate to when clicked (app-specific route) */
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
- /** Optional URL/route parameters for navigation */
21
- targetParams?: Record<string, any>;
22
- /** Whether the notification has been read */
23
- isRead: boolean;
24
- /** When the notification was created */
25
- createdAt: Timestamp;
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
- * Notification data without the ID (for creating new notifications).
42
+ * Archival audit trail stored on every history doc.
31
43
  */
32
- export type NotificationInput = Omit<Notification, 'id'>;
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
- * Options for marking notifications as read.
53
+ * History document extends active with archival info.
35
54
  */
36
- export interface MarkAsReadOptions {
37
- /** Single notification ID to mark as read */
38
- notificationId?: string;
39
- /** Mark all notifications as read */
40
- all?: boolean;
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
- * Options for deleting notifications.
62
+ * Pending notification — queue item for the batch processor.
44
63
  */
45
- export interface DeleteNotificationOptions {
46
- /** Single notification ID to delete */
47
- notificationId?: string;
48
- /** Delete all read notifications */
49
- allRead?: boolean;
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
- * Navigation handler function signature that apps must provide.
82
+ * Per-category configuration (user vs admin).
53
83
  */
54
- export type NavigationHandler = (path: string, params?: Record<string, any>) => void;
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
- * Notification configuration per type (app-specific).
93
+ * Per-type configuration for a notification type.
57
94
  */
58
95
  export interface NotificationTypeConfig {
59
- /** Icon or emoji to display */
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
- * App-specific notification configuration.
116
+ * Full notification system configuration — provided by each app.
68
117
  */
69
- export interface NotificationConfig {
70
- /** Map of notification types to their configurations */
71
- types: Record<NotificationType, NotificationTypeConfig>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAEpD;;GAEG;AACH,MAAM,MAAM,gBAAgB,GAAG,MAAM,CAAC;AAEtC;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,EAAE,EAAE,MAAM,CAAC;IACX,sFAAsF;IACtF,IAAI,EAAE,gBAAgB,CAAC;IACvB,yBAAyB;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,UAAU,EAAE,MAAM,CAAC;IACnB,mDAAmD;IACnD,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACnC,6CAA6C;IAC7C,MAAM,EAAE,OAAO,CAAC;IAChB,wCAAwC;IACxC,SAAS,EAAE,SAAS,CAAC;IACrB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;AAEzD;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,6CAA6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,qCAAqC;IACrC,GAAG,CAAC,EAAE,OAAO,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC,uCAAuC;IACvC,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oCAAoC;IACpC,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;AAErF;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,+BAA+B;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,uCAAuC;IACvC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,8CAA8C;IAC9C,UAAU,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;CACvD;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,wDAAwD;IACxD,KAAK,EAAE,MAAM,CAAC,gBAAgB,EAAE,sBAAsB,CAAC,CAAC;CACzD"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js CHANGED
@@ -1,2 +1,8 @@
1
+ /**
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.
6
+ */
1
7
  export {};
2
8
  //# sourceMappingURL=types.js.map
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.1",
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 clean && npm run build"
38
+ "prepublishOnly": "npm run build"
35
39
  },
36
40
  "peerDependencies": {
37
41
  "@tanstack/react-query": ">=5.0.0",
38
- "@ttt-productions/query-core": ">=0.3.0",
39
- "@ttt-productions/ui-core": ">=0.2.0",
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": "^0.3.7",
47
- "@ttt-productions/ui-core": "^0.2.22",
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",