@pfm-platform/notifications-data-access 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +67 -33
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +61 -67
- package/dist/index.d.ts +61 -67
- package/dist/index.js +67 -30
- package/dist/index.js.map +1 -1
- package/package.json +7 -8
package/dist/index.cjs
CHANGED
|
@@ -2,25 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
var reactQuery = require('@tanstack/react-query');
|
|
4
4
|
var shared = require('@pfm-platform/shared');
|
|
5
|
-
var axios = require('axios');
|
|
6
|
-
|
|
7
|
-
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
-
|
|
9
|
-
var axios__default = /*#__PURE__*/_interopDefault(axios);
|
|
10
5
|
|
|
11
6
|
// src/queries/useNotifications.ts
|
|
12
|
-
var api = axios__default.default.create({
|
|
13
|
-
baseURL: "/api",
|
|
14
|
-
headers: {
|
|
15
|
-
"Content-Type": "application/json"
|
|
16
|
-
}
|
|
17
|
-
});
|
|
18
7
|
|
|
19
8
|
// src/keys.ts
|
|
20
9
|
var notificationKeys = {
|
|
21
10
|
all: ["notifications"],
|
|
22
11
|
lists: () => [...notificationKeys.all, "list"],
|
|
23
|
-
list: (userId) => [...notificationKeys.lists(), userId]
|
|
12
|
+
list: (userId) => [...notificationKeys.lists(), userId],
|
|
13
|
+
preferences: (userId) => [...notificationKeys.all, "preferences", userId]
|
|
24
14
|
};
|
|
25
15
|
|
|
26
16
|
// src/queries/useNotifications.ts
|
|
@@ -28,27 +18,45 @@ function useNotifications({ userId }, options) {
|
|
|
28
18
|
return reactQuery.useQuery({
|
|
29
19
|
queryKey: notificationKeys.list(userId),
|
|
30
20
|
queryFn: async () => {
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
return
|
|
21
|
+
const { data, error } = await shared.supabase.from("notifications").select("*").eq("user_id", userId).order("created_at", { ascending: false });
|
|
22
|
+
if (error) throw new Error(error.message);
|
|
23
|
+
return shared.NotificationsResponseSchema.parse(data);
|
|
34
24
|
},
|
|
35
25
|
staleTime: 1e3 * 60 * 2,
|
|
36
26
|
// 2 minutes (notifications change frequently)
|
|
37
27
|
...options
|
|
38
28
|
});
|
|
39
29
|
}
|
|
30
|
+
function useNotificationPreferences({ userId }, options) {
|
|
31
|
+
return reactQuery.useQuery({
|
|
32
|
+
queryKey: notificationKeys.preferences(userId),
|
|
33
|
+
queryFn: async () => {
|
|
34
|
+
const { data, error } = await shared.supabase.from("notification_preferences").select("*").eq("user_id", userId).single();
|
|
35
|
+
if (error) throw new Error(error.message);
|
|
36
|
+
const row = shared.NotificationPreferencesRowSchema.parse(data);
|
|
37
|
+
return {
|
|
38
|
+
emailNotifications: row.email_notifications,
|
|
39
|
+
pushNotifications: row.push_notifications,
|
|
40
|
+
frequency: row.frequency
|
|
41
|
+
};
|
|
42
|
+
},
|
|
43
|
+
staleTime: 1e3 * 60 * 5,
|
|
44
|
+
// 5 minutes (preferences change infrequently)
|
|
45
|
+
...options
|
|
46
|
+
});
|
|
47
|
+
}
|
|
40
48
|
function useCreateNotification(options) {
|
|
41
49
|
const queryClient = reactQuery.useQueryClient();
|
|
42
|
-
const { mode } = shared.useAppMode();
|
|
43
50
|
return reactQuery.useMutation({
|
|
44
51
|
mutationFn: async ({ userId, data }) => {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
);
|
|
51
|
-
|
|
52
|
+
const { data: row, error } = await shared.supabase.from("notifications").insert({
|
|
53
|
+
user_id: userId,
|
|
54
|
+
message: data.message,
|
|
55
|
+
alert_type: data.alert_type,
|
|
56
|
+
...data.created_at ? { created_at: data.created_at } : {}
|
|
57
|
+
}).select().single();
|
|
58
|
+
if (error) throw new Error(error.message);
|
|
59
|
+
return shared.NotificationRowSchema.parse(row);
|
|
52
60
|
},
|
|
53
61
|
onSuccess: (_, { userId }) => {
|
|
54
62
|
queryClient.invalidateQueries({
|
|
@@ -60,20 +68,15 @@ function useCreateNotification(options) {
|
|
|
60
68
|
}
|
|
61
69
|
function useUpdateNotification(options) {
|
|
62
70
|
const queryClient = reactQuery.useQueryClient();
|
|
63
|
-
const { mode } = shared.useAppMode();
|
|
64
71
|
return reactQuery.useMutation({
|
|
65
72
|
mutationFn: async ({
|
|
66
73
|
userId,
|
|
67
74
|
notificationId,
|
|
68
75
|
data
|
|
69
76
|
}) => {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
`/users/${userId}/alerts/notifications/${notificationId}`,
|
|
74
|
-
validated
|
|
75
|
-
);
|
|
76
|
-
return shared.NotificationSchema.parse(response.data);
|
|
77
|
+
const { data: row, error } = await shared.supabase.from("notifications").update(data).eq("id", notificationId).eq("user_id", userId).select().single();
|
|
78
|
+
if (error) throw new Error(error.message);
|
|
79
|
+
return shared.NotificationRowSchema.parse(row);
|
|
77
80
|
},
|
|
78
81
|
onSuccess: (_, { userId }) => {
|
|
79
82
|
queryClient.invalidateQueries({
|
|
@@ -87,7 +90,8 @@ function useDeleteNotification(options) {
|
|
|
87
90
|
const queryClient = reactQuery.useQueryClient();
|
|
88
91
|
return reactQuery.useMutation({
|
|
89
92
|
mutationFn: async ({ userId, notificationId }) => {
|
|
90
|
-
await
|
|
93
|
+
const { error } = await shared.supabase.from("notifications").delete().eq("id", notificationId).eq("user_id", userId);
|
|
94
|
+
if (error) throw new Error(error.message);
|
|
91
95
|
},
|
|
92
96
|
onSuccess: (_, { userId }) => {
|
|
93
97
|
queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });
|
|
@@ -95,12 +99,42 @@ function useDeleteNotification(options) {
|
|
|
95
99
|
...options
|
|
96
100
|
});
|
|
97
101
|
}
|
|
102
|
+
function useUpdateNotificationPreferences(options) {
|
|
103
|
+
const queryClient = reactQuery.useQueryClient();
|
|
104
|
+
return reactQuery.useMutation({
|
|
105
|
+
mutationFn: async ({ userId, data }) => {
|
|
106
|
+
const dbData = { user_id: userId };
|
|
107
|
+
if (data.emailNotifications !== void 0) {
|
|
108
|
+
dbData.email_notifications = data.emailNotifications;
|
|
109
|
+
}
|
|
110
|
+
if (data.pushNotifications !== void 0) {
|
|
111
|
+
dbData.push_notifications = data.pushNotifications;
|
|
112
|
+
}
|
|
113
|
+
if (data.frequency !== void 0) {
|
|
114
|
+
dbData.frequency = data.frequency;
|
|
115
|
+
}
|
|
116
|
+
const { data: row, error } = await shared.supabase.from("notification_preferences").upsert(dbData).select().single();
|
|
117
|
+
if (error) throw new Error(error.message);
|
|
118
|
+
const validated = shared.NotificationPreferencesRowSchema.parse(row);
|
|
119
|
+
return {
|
|
120
|
+
emailNotifications: validated.email_notifications,
|
|
121
|
+
pushNotifications: validated.push_notifications,
|
|
122
|
+
frequency: validated.frequency
|
|
123
|
+
};
|
|
124
|
+
},
|
|
125
|
+
onSuccess: (_, { userId }) => {
|
|
126
|
+
queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });
|
|
127
|
+
},
|
|
128
|
+
...options
|
|
129
|
+
});
|
|
130
|
+
}
|
|
98
131
|
|
|
99
|
-
exports.api = api;
|
|
100
132
|
exports.notificationKeys = notificationKeys;
|
|
101
133
|
exports.useCreateNotification = useCreateNotification;
|
|
102
134
|
exports.useDeleteNotification = useDeleteNotification;
|
|
135
|
+
exports.useNotificationPreferences = useNotificationPreferences;
|
|
103
136
|
exports.useNotifications = useNotifications;
|
|
104
137
|
exports.useUpdateNotification = useUpdateNotification;
|
|
138
|
+
exports.useUpdateNotificationPreferences = useUpdateNotificationPreferences;
|
|
105
139
|
//# sourceMappingURL=index.cjs.map
|
|
106
140
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/keys.ts","../src/queries/useNotifications.ts","../src/mutations/useCreateNotification.ts","../src/mutations/useUpdateNotification.ts","../src/mutations/useDeleteNotification.ts"],"names":["axios","useQuery","NotificationsResponseSchema","useQueryClient","useAppMode","useMutation","NotificationCreateSchemaAdmin","NotificationCreateSchemaUser","NotificationSchema","NotificationUpdateSchemaAdmin","NotificationUpdateSchemaUser"],"mappings":"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","file":"index.cjs","sourcesContent":["import axios from 'axios';\n\n/**\n * Axios instance for Notifications API\n * Base URL configured through environment variables or defaults to relative path\n */\nexport const api = axios.create({\n baseURL: '/api',\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n","/**\n * Query key factory for Notifications domain\n */\nexport const notificationKeys = {\n all: ['notifications'] as const,\n lists: () => [...notificationKeys.all, 'list'] as const,\n list: (userId: string) => [...notificationKeys.lists(), userId] as const,\n};\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { Notification, NotificationsResponseSchema } from '@pfm-platform/shared';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationsParams {\n userId: string;\n}\n\n/**\n * Fetch all notifications for a user\n * GET /users/:userId/alerts/notifications\n *\n * Notifications are system-generated based on alert configurations\n * Read-only domain (no create/update operations)\n */\nexport function useNotifications(\n { userId }: UseNotificationsParams,\n options?: Omit<UseQueryOptions<Notification[]>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.list(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/alerts/notifications`);\n const validated = NotificationsResponseSchema.parse(response.data);\n return validated.notifications;\n },\n staleTime: 1000 * 60 * 2, // 2 minutes (notifications change frequently)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationCreateSchemaAdmin,\n NotificationCreateSchemaUser,\n NotificationSchema,\n useAppMode,\n type AlertType,\n} from '@pfm-platform/shared';\nimport type { Notification } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { notificationKeys } from '../keys';\n\n/**\n * Notification create data interface\n */\nexport interface NotificationCreate {\n message: string;\n alert_type: AlertType;\n created_at?: string;\n}\n\n/**\n * Parameters for useCreateNotification mutation\n */\nexport interface CreateNotificationParams {\n userId: string;\n data: NotificationCreate;\n}\n\n/**\n * Mutation hook for creating a new notification\n *\n * Creates a notification manually for testing purposes.\n * Uses mode switching for validation:\n * - Admin mode: Allows manual notification creation for test data\n * - User mode: Blocked (notifications are system-generated)\n *\n * @example\n * ```tsx\n * const createNotification = useCreateNotification();\n *\n * createNotification.mutate({\n * userId: 'user123',\n * data: {\n * message: 'Test notification',\n * alert_type: 'AccountThresholdAlert',\n * created_at: new Date().toISOString() // Optional\n * }\n * });\n * ```\n */\nexport function useCreateNotification(\n options?: Omit<\n UseMutationOptions<Notification, Error, CreateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNotificationParams) => {\n // Select schema based on mode\n const schema =\n mode === 'admin'\n ? NotificationCreateSchemaAdmin\n : NotificationCreateSchemaUser;\n\n // Validate notification data\n const validated = schema.parse(data);\n\n // POST to create new notification\n const response = await api.post(\n `/users/${userId}/alerts/notifications`,\n validated\n );\n\n // Return created notification\n return NotificationSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications query to refetch updated list\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationUpdateSchemaAdmin,\n NotificationUpdateSchemaUser,\n NotificationSchema,\n useAppMode,\n type AlertType,\n} from '@pfm-platform/shared';\nimport type { Notification } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { notificationKeys } from '../keys';\n\n/**\n * Notification update data interface\n */\nexport interface NotificationUpdate {\n message?: string;\n alert_type?: AlertType;\n}\n\n/**\n * Parameters for useUpdateNotification mutation\n */\nexport interface UpdateNotificationParams {\n userId: string;\n notificationId: number;\n data: NotificationUpdate;\n}\n\n/**\n * Mutation hook for updating a notification\n *\n * Updates notification fields for testing purposes.\n * Uses mode switching for validation:\n * - Admin mode: Allows updating notifications for test scenarios\n * - User mode: Blocked (notifications are system-generated)\n *\n * @example\n * ```tsx\n * const updateNotification = useUpdateNotification();\n *\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: {\n * message: 'Updated test notification'\n * }\n * });\n * ```\n */\nexport function useUpdateNotification(\n options?: Omit<\n UseMutationOptions<Notification, Error, UpdateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({\n userId,\n notificationId,\n data,\n }: UpdateNotificationParams) => {\n // Select schema based on mode\n const schema =\n mode === 'admin'\n ? NotificationUpdateSchemaAdmin\n : NotificationUpdateSchemaUser;\n\n // Validate notification update data\n const validated = schema.parse(data);\n\n // PUT to update notification\n const response = await api.put(\n `/users/${userId}/alerts/notifications/${notificationId}`,\n validated\n );\n\n // Return updated notification\n return NotificationSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications query to refetch updated list\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface DeleteNotificationParams {\n userId: string;\n notificationId: number;\n}\n\n/**\n * Delete a notification\n * DELETE /users/:userId/alerts/notifications/:notificationId\n *\n * Notifications are system-generated, deletion only removes from view\n */\nexport function useDeleteNotification(\n options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, notificationId }: DeleteNotificationParams) => {\n await api.delete(`/users/${userId}/alerts/notifications/${notificationId}`);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications list to refetch without deleted item\n queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });\n },\n ...options,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/keys.ts","../src/queries/useNotifications.ts","../src/queries/useNotificationPreferences.ts","../src/mutations/useCreateNotification.ts","../src/mutations/useUpdateNotification.ts","../src/mutations/useDeleteNotification.ts","../src/mutations/useUpdateNotificationPreferences.ts"],"names":["useQuery","supabase","NotificationsResponseSchema","NotificationPreferencesRowSchema","useQueryClient","useMutation","NotificationRowSchema"],"mappings":";;;;;;;;AAGO,IAAM,gBAAA,GAAmB;AAAA,EAC9B,GAAA,EAAK,CAAC,eAAe,CAAA;AAAA,EACrB,OAAO,MAAM,CAAC,GAAG,gBAAA,CAAiB,KAAK,MAAM,CAAA;AAAA,EAC7C,IAAA,EAAM,CAAC,MAAA,KAAmB,CAAC,GAAG,gBAAA,CAAiB,KAAA,IAAS,MAAM,CAAA;AAAA,EAC9D,WAAA,EAAa,CAAC,MAAA,KAAmB,CAAC,GAAG,gBAAA,CAAiB,GAAA,EAAK,eAAe,MAAM;AAClF;;;ACKO,SAAS,gBAAA,CACd,EAAE,MAAA,EAAO,EACT,OAAA,EACA;AACA,EAAA,OAAOA,mBAAA,CAAS;AAAA,IACd,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,MAAM,CAAA;AAAA,IACtC,SAAS,YAAY;AACnB,MAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAMC,eAAA,CAC3B,IAAA,CAAK,eAAe,CAAA,CACpB,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,WAAW,MAAM,CAAA,CACpB,MAAM,YAAA,EAAc,EAAE,SAAA,EAAW,KAAA,EAAO,CAAA;AAE3C,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AACxC,MAAA,OAAOC,kCAAA,CAA4B,MAAM,IAAI,CAAA;AAAA,IAC/C,CAAA;AAAA,IACA,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;ACdO,SAAS,0BAAA,CACd,EAAE,MAAA,EAAO,EACT,OAAA,EACA;AACA,EAAA,OAAOF,mBAAAA,CAAS;AAAA,IACd,QAAA,EAAU,gBAAA,CAAiB,WAAA,CAAY,MAAM,CAAA;AAAA,IAC7C,SAAS,YAAY;AACnB,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAMC,gBAC3B,IAAA,CAAK,0BAA0B,CAAA,CAC/B,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,SAAA,EAAW,MAAM,EACpB,MAAA,EAAO;AAEV,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AAExC,MAAA,MAAM,GAAA,GAAME,uCAAA,CAAiC,KAAA,CAAM,IAAI,CAAA;AAGvD,MAAA,OAAO;AAAA,QACL,oBAAoB,GAAA,CAAI,mBAAA;AAAA,QACxB,mBAAmB,GAAA,CAAI,kBAAA;AAAA,QACvB,WAAW,GAAA,CAAI;AAAA,OACjB;AAAA,IACF,CAAA;AAAA,IACA,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;ACXO,SAAS,sBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcC,yBAAA,EAAe;AAEnC,EAAA,OAAOC,sBAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,MAAA,EAAQ,MAAK,KAAgC;AAChE,MAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAK,KAAA,EAAM,GAAI,MAAMJ,eAAA,CAChC,IAAA,CAAK,eAAe,CAAA,CACpB,MAAA,CAAO;AAAA,QACN,OAAA,EAAS,MAAA;AAAA,QACT,SAAS,IAAA,CAAK,OAAA;AAAA,QACd,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,GAAI,KAAK,UAAA,GAAa,EAAE,YAAY,IAAA,CAAK,UAAA,KAAe;AAAC,OACzB,CAAA,CACjC,MAAA,EAAO,CACP,MAAA,EAAO;AAEV,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AACxC,MAAA,OAAOK,4BAAA,CAAsB,MAAM,GAAG,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,MAAM;AAAA,OACvC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AC9BO,SAAS,sBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcF,yBAAAA,EAAe;AAEnC,EAAA,OAAOC,sBAAAA,CAAY;AAAA,IACjB,YAAY,OAAO;AAAA,MACjB,MAAA;AAAA,MACA,cAAA;AAAA,MACA;AAAA,KACF,KAAgC;AAC9B,MAAA,MAAM,EAAE,MAAM,GAAA,EAAK,KAAA,KAAU,MAAMJ,eAAA,CAChC,IAAA,CAAK,eAAe,CAAA,CACpB,MAAA,CAAO,IAAqC,CAAA,CAC5C,EAAA,CAAG,IAAA,EAAM,cAAc,CAAA,CACvB,EAAA,CAAG,WAAW,MAAM,CAAA,CACpB,MAAA,EAAO,CACP,MAAA,EAAO;AAEV,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AACxC,MAAA,OAAOK,4BAAAA,CAAsB,MAAM,GAAG,CAAA;AAAA,IACxC,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,gBAAA,CAAiB,IAAA,CAAK,MAAM;AAAA,OACvC,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;ACtDO,SAAS,sBACd,OAAA,EACA;AACA,EAAA,MAAM,cAAcF,yBAAAA,EAAe;AAEnC,EAAA,OAAOC,sBAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,MAAA,EAAQ,gBAAe,KAAgC;AAC1E,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAMJ,eAAA,CACrB,KAAK,eAAe,CAAA,CACpB,MAAA,EAAO,CACP,GAAG,IAAA,EAAM,cAAc,CAAA,CACvB,EAAA,CAAG,WAAW,MAAM,CAAA;AAEvB,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AAAA,IAC1C,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,iBAAiB,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IAC3E,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;ACZO,SAAS,iCACd,OAAA,EAKA;AACA,EAAA,MAAM,cAAcG,yBAAAA,EAAe;AAEnC,EAAA,OAAOC,sBAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,MAAA,EAAQ,MAAK,KAA2C;AAE3E,MAAA,MAAM,MAAA,GAAkC,EAAE,OAAA,EAAS,MAAA,EAAO;AAC1D,MAAA,IAAI,IAAA,CAAK,uBAAuB,MAAA,EAAW;AACzC,QAAA,MAAA,CAAO,sBAAsB,IAAA,CAAK,kBAAA;AAAA,MACpC;AACA,MAAA,IAAI,IAAA,CAAK,sBAAsB,MAAA,EAAW;AACxC,QAAA,MAAA,CAAO,qBAAqB,IAAA,CAAK,iBAAA;AAAA,MACnC;AACA,MAAA,IAAI,IAAA,CAAK,cAAc,MAAA,EAAW;AAChC,QAAA,MAAA,CAAO,YAAY,IAAA,CAAK,SAAA;AAAA,MAC1B;AAEA,MAAA,MAAM,EAAE,IAAA,EAAM,GAAA,EAAK,KAAA,KAAU,MAAMJ,eAAA,CAChC,IAAA,CAAK,0BAA0B,EAC/B,MAAA,CAAO,MAAkD,CAAA,CACzD,MAAA,GACA,MAAA,EAAO;AAEV,MAAA,IAAI,KAAA,EAAO,MAAM,IAAI,KAAA,CAAM,MAAM,OAAO,CAAA;AAExC,MAAA,MAAM,SAAA,GAAYE,uCAAAA,CAAiC,KAAA,CAAM,GAAG,CAAA;AAG5D,MAAA,OAAO;AAAA,QACL,oBAAoB,SAAA,CAAU,mBAAA;AAAA,QAC9B,mBAAmB,SAAA,CAAU,kBAAA;AAAA,QAC7B,WAAW,SAAA,CAAU;AAAA,OACvB;AAAA,IACF,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,kBAAkB,EAAE,QAAA,EAAU,iBAAiB,WAAA,CAAY,MAAM,GAAG,CAAA;AAAA,IAClF,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH","file":"index.cjs","sourcesContent":["/**\n * Query key factory for Notifications domain\n */\nexport const notificationKeys = {\n all: ['notifications'] as const,\n lists: () => [...notificationKeys.all, 'list'] as const,\n list: (userId: string) => [...notificationKeys.lists(), userId] as const,\n preferences: (userId: string) => [...notificationKeys.all, 'preferences', userId] as const,\n};\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { NotificationsResponseSchema, type NotificationRow } from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationsParams {\n userId: string;\n}\n\n/**\n * Fetch all notifications for a user\n * Supabase: SELECT * FROM notifications WHERE user_id = :userId ORDER BY created_at DESC\n */\nexport function useNotifications(\n { userId }: UseNotificationsParams,\n options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.list(userId),\n queryFn: async () => {\n const { data, error } = await supabase\n .from('notifications')\n .select('*')\n .eq('user_id', userId)\n .order('created_at', { ascending: false });\n\n if (error) throw new Error(error.message);\n return NotificationsResponseSchema.parse(data);\n },\n staleTime: 1000 * 60 * 2, // 2 minutes (notifications change frequently)\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport {\n NotificationPreferencesRowSchema,\n type NotificationPreferences,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationPreferencesParams {\n userId: string;\n}\n\n/**\n * Fetch user notification preferences\n * Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId\n *\n * Transforms snake_case DB columns to camelCase for feature/UI layers\n */\nexport function useNotificationPreferences(\n { userId }: UseNotificationPreferencesParams,\n options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.preferences(userId),\n queryFn: async () => {\n const { data, error } = await supabase\n .from('notification_preferences')\n .select('*')\n .eq('user_id', userId)\n .single();\n\n if (error) throw new Error(error.message);\n\n const row = NotificationPreferencesRowSchema.parse(data);\n\n // Transform snake_case → camelCase for feature/UI layers\n return {\n emailNotifications: row.email_notifications,\n pushNotifications: row.push_notifications,\n frequency: row.frequency,\n } as NotificationPreferences;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes (preferences change infrequently)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationRowSchema,\n type AlertType,\n type NotificationRow,\n type TablesInsert,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\n/**\n * Notification create data interface\n */\nexport interface NotificationCreate {\n message: string;\n alert_type: AlertType;\n created_at?: string;\n}\n\n/**\n * Parameters for useCreateNotification mutation\n */\nexport interface CreateNotificationParams {\n userId: string;\n data: NotificationCreate;\n}\n\n/**\n * Mutation hook for creating a new notification\n */\nexport function useCreateNotification(\n options?: Omit<\n UseMutationOptions<NotificationRow, Error, CreateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNotificationParams) => {\n const { data: row, error } = await supabase\n .from('notifications')\n .insert({\n user_id: userId,\n message: data.message,\n alert_type: data.alert_type,\n ...(data.created_at ? { created_at: data.created_at } : {}),\n } as TablesInsert<'notifications'>)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n return NotificationRowSchema.parse(row);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationRowSchema,\n type AlertType,\n type NotificationRow,\n type TablesUpdate,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\n/**\n * Notification update data interface\n */\nexport interface NotificationUpdate {\n message?: string;\n alert_type?: AlertType;\n is_read?: boolean;\n}\n\n/**\n * Parameters for useUpdateNotification mutation\n */\nexport interface UpdateNotificationParams {\n userId: string;\n notificationId: string;\n data: NotificationUpdate;\n}\n\n/**\n * Mutation hook for updating a notification\n */\nexport function useUpdateNotification(\n options?: Omit<\n UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({\n userId,\n notificationId,\n data,\n }: UpdateNotificationParams) => {\n const { data: row, error } = await supabase\n .from('notifications')\n .update(data as TablesUpdate<'notifications'>)\n .eq('id', notificationId)\n .eq('user_id', userId)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n return NotificationRowSchema.parse(row);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface DeleteNotificationParams {\n userId: string;\n notificationId: string;\n}\n\n/**\n * Delete a notification\n * Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId\n */\nexport function useDeleteNotification(\n options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, notificationId }: DeleteNotificationParams) => {\n const { error } = await supabase\n .from('notifications')\n .delete()\n .eq('id', notificationId)\n .eq('user_id', userId);\n\n if (error) throw new Error(error.message);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport {\n NotificationPreferencesRowSchema,\n type NotificationPreferences,\n type TablesInsert,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UpdateNotificationPreferencesParams {\n userId: string;\n data: Partial<NotificationPreferences>;\n}\n\n/**\n * Update user notification preferences\n * Supabase: UPSERT notification_preferences\n *\n * Transforms camelCase input → snake_case for Supabase,\n * then transforms response back to camelCase\n */\nexport function useUpdateNotificationPreferences(\n options?: UseMutationOptions<\n NotificationPreferences,\n Error,\n UpdateNotificationPreferencesParams\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: UpdateNotificationPreferencesParams) => {\n // Transform camelCase → snake_case for Supabase\n const dbData: Record<string, unknown> = { user_id: userId };\n if (data.emailNotifications !== undefined) {\n dbData.email_notifications = data.emailNotifications;\n }\n if (data.pushNotifications !== undefined) {\n dbData.push_notifications = data.pushNotifications;\n }\n if (data.frequency !== undefined) {\n dbData.frequency = data.frequency;\n }\n\n const { data: row, error } = await supabase\n .from('notification_preferences')\n .upsert(dbData as TablesInsert<'notification_preferences'>)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n\n const validated = NotificationPreferencesRowSchema.parse(row);\n\n // Transform snake_case → camelCase for feature/UI layers\n return {\n emailNotifications: validated.email_notifications,\n pushNotifications: validated.push_notifications,\n frequency: validated.frequency,\n } as NotificationPreferences;\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });\n },\n ...options,\n });\n}\n"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
2
|
import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
3
|
-
import {
|
|
4
|
-
import * as axios from 'axios';
|
|
3
|
+
import { NotificationRow, NotificationPreferences, AlertType } from '@pfm-platform/shared';
|
|
5
4
|
|
|
6
5
|
interface UseNotificationsParams {
|
|
7
6
|
userId: string;
|
|
8
7
|
}
|
|
9
8
|
/**
|
|
10
9
|
* Fetch all notifications for a user
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Notifications are system-generated based on alert configurations
|
|
14
|
-
* Read-only domain (no create/update operations)
|
|
10
|
+
* Supabase: SELECT * FROM notifications WHERE user_id = :userId ORDER BY created_at DESC
|
|
15
11
|
*/
|
|
16
|
-
declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<
|
|
17
|
-
id:
|
|
18
|
-
|
|
12
|
+
declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
|
|
13
|
+
id: string;
|
|
14
|
+
user_id: string;
|
|
15
|
+
alert_id: string | null;
|
|
19
16
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
20
|
-
|
|
17
|
+
message: string;
|
|
18
|
+
is_read: boolean;
|
|
19
|
+
created_at: string | null;
|
|
21
20
|
}[], Error>;
|
|
22
21
|
|
|
22
|
+
interface UseNotificationPreferencesParams {
|
|
23
|
+
userId: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch user notification preferences
|
|
27
|
+
* Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId
|
|
28
|
+
*
|
|
29
|
+
* Transforms snake_case DB columns to camelCase for feature/UI layers
|
|
30
|
+
*/
|
|
31
|
+
declare function useNotificationPreferences({ userId }: UseNotificationPreferencesParams, options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
|
|
32
|
+
emailNotifications: boolean;
|
|
33
|
+
pushNotifications: boolean;
|
|
34
|
+
frequency: "weekly" | "realtime" | "daily";
|
|
35
|
+
}, Error>;
|
|
36
|
+
|
|
23
37
|
/**
|
|
24
38
|
* Notification create data interface
|
|
25
39
|
*/
|
|
@@ -37,31 +51,15 @@ interface CreateNotificationParams {
|
|
|
37
51
|
}
|
|
38
52
|
/**
|
|
39
53
|
* Mutation hook for creating a new notification
|
|
40
|
-
*
|
|
41
|
-
* Creates a notification manually for testing purposes.
|
|
42
|
-
* Uses mode switching for validation:
|
|
43
|
-
* - Admin mode: Allows manual notification creation for test data
|
|
44
|
-
* - User mode: Blocked (notifications are system-generated)
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```tsx
|
|
48
|
-
* const createNotification = useCreateNotification();
|
|
49
|
-
*
|
|
50
|
-
* createNotification.mutate({
|
|
51
|
-
* userId: 'user123',
|
|
52
|
-
* data: {
|
|
53
|
-
* message: 'Test notification',
|
|
54
|
-
* alert_type: 'AccountThresholdAlert',
|
|
55
|
-
* created_at: new Date().toISOString() // Optional
|
|
56
|
-
* }
|
|
57
|
-
* });
|
|
58
|
-
* ```
|
|
59
54
|
*/
|
|
60
|
-
declare function useCreateNotification(options?: Omit<UseMutationOptions<
|
|
61
|
-
id:
|
|
62
|
-
|
|
55
|
+
declare function useCreateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
|
|
56
|
+
id: string;
|
|
57
|
+
user_id: string;
|
|
58
|
+
alert_id: string | null;
|
|
63
59
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
64
|
-
|
|
60
|
+
message: string;
|
|
61
|
+
is_read: boolean;
|
|
62
|
+
created_at: string | null;
|
|
65
63
|
}, Error, CreateNotificationParams, unknown>;
|
|
66
64
|
|
|
67
65
|
/**
|
|
@@ -70,55 +68,56 @@ declare function useCreateNotification(options?: Omit<UseMutationOptions<Notific
|
|
|
70
68
|
interface NotificationUpdate {
|
|
71
69
|
message?: string;
|
|
72
70
|
alert_type?: AlertType;
|
|
71
|
+
is_read?: boolean;
|
|
73
72
|
}
|
|
74
73
|
/**
|
|
75
74
|
* Parameters for useUpdateNotification mutation
|
|
76
75
|
*/
|
|
77
76
|
interface UpdateNotificationParams {
|
|
78
77
|
userId: string;
|
|
79
|
-
notificationId:
|
|
78
|
+
notificationId: string;
|
|
80
79
|
data: NotificationUpdate;
|
|
81
80
|
}
|
|
82
81
|
/**
|
|
83
82
|
* Mutation hook for updating a notification
|
|
84
|
-
*
|
|
85
|
-
* Updates notification fields for testing purposes.
|
|
86
|
-
* Uses mode switching for validation:
|
|
87
|
-
* - Admin mode: Allows updating notifications for test scenarios
|
|
88
|
-
* - User mode: Blocked (notifications are system-generated)
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```tsx
|
|
92
|
-
* const updateNotification = useUpdateNotification();
|
|
93
|
-
*
|
|
94
|
-
* updateNotification.mutate({
|
|
95
|
-
* userId: 'user123',
|
|
96
|
-
* notificationId: 1,
|
|
97
|
-
* data: {
|
|
98
|
-
* message: 'Updated test notification'
|
|
99
|
-
* }
|
|
100
|
-
* });
|
|
101
|
-
* ```
|
|
102
83
|
*/
|
|
103
|
-
declare function useUpdateNotification(options?: Omit<UseMutationOptions<
|
|
104
|
-
id:
|
|
105
|
-
|
|
84
|
+
declare function useUpdateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
|
|
85
|
+
id: string;
|
|
86
|
+
user_id: string;
|
|
87
|
+
alert_id: string | null;
|
|
106
88
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
107
|
-
|
|
89
|
+
message: string;
|
|
90
|
+
is_read: boolean;
|
|
91
|
+
created_at: string | null;
|
|
108
92
|
}, Error, UpdateNotificationParams, unknown>;
|
|
109
93
|
|
|
110
94
|
interface DeleteNotificationParams {
|
|
111
95
|
userId: string;
|
|
112
|
-
notificationId:
|
|
96
|
+
notificationId: string;
|
|
113
97
|
}
|
|
114
98
|
/**
|
|
115
99
|
* Delete a notification
|
|
116
|
-
* DELETE
|
|
117
|
-
*
|
|
118
|
-
* Notifications are system-generated, deletion only removes from view
|
|
100
|
+
* Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId
|
|
119
101
|
*/
|
|
120
102
|
declare function useDeleteNotification(options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<void, Error, DeleteNotificationParams, unknown>;
|
|
121
103
|
|
|
104
|
+
interface UpdateNotificationPreferencesParams {
|
|
105
|
+
userId: string;
|
|
106
|
+
data: Partial<NotificationPreferences>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update user notification preferences
|
|
110
|
+
* Supabase: UPSERT notification_preferences
|
|
111
|
+
*
|
|
112
|
+
* Transforms camelCase input → snake_case for Supabase,
|
|
113
|
+
* then transforms response back to camelCase
|
|
114
|
+
*/
|
|
115
|
+
declare function useUpdateNotificationPreferences(options?: UseMutationOptions<NotificationPreferences, Error, UpdateNotificationPreferencesParams>): _tanstack_react_query.UseMutationResult<{
|
|
116
|
+
emailNotifications: boolean;
|
|
117
|
+
pushNotifications: boolean;
|
|
118
|
+
frequency: "weekly" | "realtime" | "daily";
|
|
119
|
+
}, Error, UpdateNotificationPreferencesParams, unknown>;
|
|
120
|
+
|
|
122
121
|
/**
|
|
123
122
|
* Query key factory for Notifications domain
|
|
124
123
|
*/
|
|
@@ -126,12 +125,7 @@ declare const notificationKeys: {
|
|
|
126
125
|
all: readonly ["notifications"];
|
|
127
126
|
lists: () => readonly ["notifications", "list"];
|
|
128
127
|
list: (userId: string) => readonly ["notifications", "list", string];
|
|
128
|
+
preferences: (userId: string) => readonly ["notifications", "preferences", string];
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
* Axios instance for Notifications API
|
|
133
|
-
* Base URL configured through environment variables or defaults to relative path
|
|
134
|
-
*/
|
|
135
|
-
declare const api: axios.AxiosInstance;
|
|
136
|
-
|
|
137
|
-
export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UseNotificationsParams, api, notificationKeys, useCreateNotification, useDeleteNotification, useNotifications, useUpdateNotification };
|
|
131
|
+
export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UpdateNotificationPreferencesParams, type UseNotificationPreferencesParams, type UseNotificationsParams, notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,25 +1,39 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
2
|
import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
|
|
3
|
-
import {
|
|
4
|
-
import * as axios from 'axios';
|
|
3
|
+
import { NotificationRow, NotificationPreferences, AlertType } from '@pfm-platform/shared';
|
|
5
4
|
|
|
6
5
|
interface UseNotificationsParams {
|
|
7
6
|
userId: string;
|
|
8
7
|
}
|
|
9
8
|
/**
|
|
10
9
|
* Fetch all notifications for a user
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* Notifications are system-generated based on alert configurations
|
|
14
|
-
* Read-only domain (no create/update operations)
|
|
10
|
+
* Supabase: SELECT * FROM notifications WHERE user_id = :userId ORDER BY created_at DESC
|
|
15
11
|
*/
|
|
16
|
-
declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<
|
|
17
|
-
id:
|
|
18
|
-
|
|
12
|
+
declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
|
|
13
|
+
id: string;
|
|
14
|
+
user_id: string;
|
|
15
|
+
alert_id: string | null;
|
|
19
16
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
20
|
-
|
|
17
|
+
message: string;
|
|
18
|
+
is_read: boolean;
|
|
19
|
+
created_at: string | null;
|
|
21
20
|
}[], Error>;
|
|
22
21
|
|
|
22
|
+
interface UseNotificationPreferencesParams {
|
|
23
|
+
userId: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Fetch user notification preferences
|
|
27
|
+
* Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId
|
|
28
|
+
*
|
|
29
|
+
* Transforms snake_case DB columns to camelCase for feature/UI layers
|
|
30
|
+
*/
|
|
31
|
+
declare function useNotificationPreferences({ userId }: UseNotificationPreferencesParams, options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
|
|
32
|
+
emailNotifications: boolean;
|
|
33
|
+
pushNotifications: boolean;
|
|
34
|
+
frequency: "weekly" | "realtime" | "daily";
|
|
35
|
+
}, Error>;
|
|
36
|
+
|
|
23
37
|
/**
|
|
24
38
|
* Notification create data interface
|
|
25
39
|
*/
|
|
@@ -37,31 +51,15 @@ interface CreateNotificationParams {
|
|
|
37
51
|
}
|
|
38
52
|
/**
|
|
39
53
|
* Mutation hook for creating a new notification
|
|
40
|
-
*
|
|
41
|
-
* Creates a notification manually for testing purposes.
|
|
42
|
-
* Uses mode switching for validation:
|
|
43
|
-
* - Admin mode: Allows manual notification creation for test data
|
|
44
|
-
* - User mode: Blocked (notifications are system-generated)
|
|
45
|
-
*
|
|
46
|
-
* @example
|
|
47
|
-
* ```tsx
|
|
48
|
-
* const createNotification = useCreateNotification();
|
|
49
|
-
*
|
|
50
|
-
* createNotification.mutate({
|
|
51
|
-
* userId: 'user123',
|
|
52
|
-
* data: {
|
|
53
|
-
* message: 'Test notification',
|
|
54
|
-
* alert_type: 'AccountThresholdAlert',
|
|
55
|
-
* created_at: new Date().toISOString() // Optional
|
|
56
|
-
* }
|
|
57
|
-
* });
|
|
58
|
-
* ```
|
|
59
54
|
*/
|
|
60
|
-
declare function useCreateNotification(options?: Omit<UseMutationOptions<
|
|
61
|
-
id:
|
|
62
|
-
|
|
55
|
+
declare function useCreateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
|
|
56
|
+
id: string;
|
|
57
|
+
user_id: string;
|
|
58
|
+
alert_id: string | null;
|
|
63
59
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
64
|
-
|
|
60
|
+
message: string;
|
|
61
|
+
is_read: boolean;
|
|
62
|
+
created_at: string | null;
|
|
65
63
|
}, Error, CreateNotificationParams, unknown>;
|
|
66
64
|
|
|
67
65
|
/**
|
|
@@ -70,55 +68,56 @@ declare function useCreateNotification(options?: Omit<UseMutationOptions<Notific
|
|
|
70
68
|
interface NotificationUpdate {
|
|
71
69
|
message?: string;
|
|
72
70
|
alert_type?: AlertType;
|
|
71
|
+
is_read?: boolean;
|
|
73
72
|
}
|
|
74
73
|
/**
|
|
75
74
|
* Parameters for useUpdateNotification mutation
|
|
76
75
|
*/
|
|
77
76
|
interface UpdateNotificationParams {
|
|
78
77
|
userId: string;
|
|
79
|
-
notificationId:
|
|
78
|
+
notificationId: string;
|
|
80
79
|
data: NotificationUpdate;
|
|
81
80
|
}
|
|
82
81
|
/**
|
|
83
82
|
* Mutation hook for updating a notification
|
|
84
|
-
*
|
|
85
|
-
* Updates notification fields for testing purposes.
|
|
86
|
-
* Uses mode switching for validation:
|
|
87
|
-
* - Admin mode: Allows updating notifications for test scenarios
|
|
88
|
-
* - User mode: Blocked (notifications are system-generated)
|
|
89
|
-
*
|
|
90
|
-
* @example
|
|
91
|
-
* ```tsx
|
|
92
|
-
* const updateNotification = useUpdateNotification();
|
|
93
|
-
*
|
|
94
|
-
* updateNotification.mutate({
|
|
95
|
-
* userId: 'user123',
|
|
96
|
-
* notificationId: 1,
|
|
97
|
-
* data: {
|
|
98
|
-
* message: 'Updated test notification'
|
|
99
|
-
* }
|
|
100
|
-
* });
|
|
101
|
-
* ```
|
|
102
83
|
*/
|
|
103
|
-
declare function useUpdateNotification(options?: Omit<UseMutationOptions<
|
|
104
|
-
id:
|
|
105
|
-
|
|
84
|
+
declare function useUpdateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
|
|
85
|
+
id: string;
|
|
86
|
+
user_id: string;
|
|
87
|
+
alert_id: string | null;
|
|
106
88
|
alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
|
|
107
|
-
|
|
89
|
+
message: string;
|
|
90
|
+
is_read: boolean;
|
|
91
|
+
created_at: string | null;
|
|
108
92
|
}, Error, UpdateNotificationParams, unknown>;
|
|
109
93
|
|
|
110
94
|
interface DeleteNotificationParams {
|
|
111
95
|
userId: string;
|
|
112
|
-
notificationId:
|
|
96
|
+
notificationId: string;
|
|
113
97
|
}
|
|
114
98
|
/**
|
|
115
99
|
* Delete a notification
|
|
116
|
-
* DELETE
|
|
117
|
-
*
|
|
118
|
-
* Notifications are system-generated, deletion only removes from view
|
|
100
|
+
* Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId
|
|
119
101
|
*/
|
|
120
102
|
declare function useDeleteNotification(options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<void, Error, DeleteNotificationParams, unknown>;
|
|
121
103
|
|
|
104
|
+
interface UpdateNotificationPreferencesParams {
|
|
105
|
+
userId: string;
|
|
106
|
+
data: Partial<NotificationPreferences>;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update user notification preferences
|
|
110
|
+
* Supabase: UPSERT notification_preferences
|
|
111
|
+
*
|
|
112
|
+
* Transforms camelCase input → snake_case for Supabase,
|
|
113
|
+
* then transforms response back to camelCase
|
|
114
|
+
*/
|
|
115
|
+
declare function useUpdateNotificationPreferences(options?: UseMutationOptions<NotificationPreferences, Error, UpdateNotificationPreferencesParams>): _tanstack_react_query.UseMutationResult<{
|
|
116
|
+
emailNotifications: boolean;
|
|
117
|
+
pushNotifications: boolean;
|
|
118
|
+
frequency: "weekly" | "realtime" | "daily";
|
|
119
|
+
}, Error, UpdateNotificationPreferencesParams, unknown>;
|
|
120
|
+
|
|
122
121
|
/**
|
|
123
122
|
* Query key factory for Notifications domain
|
|
124
123
|
*/
|
|
@@ -126,12 +125,7 @@ declare const notificationKeys: {
|
|
|
126
125
|
all: readonly ["notifications"];
|
|
127
126
|
lists: () => readonly ["notifications", "list"];
|
|
128
127
|
list: (userId: string) => readonly ["notifications", "list", string];
|
|
128
|
+
preferences: (userId: string) => readonly ["notifications", "preferences", string];
|
|
129
129
|
};
|
|
130
130
|
|
|
131
|
-
|
|
132
|
-
* Axios instance for Notifications API
|
|
133
|
-
* Base URL configured through environment variables or defaults to relative path
|
|
134
|
-
*/
|
|
135
|
-
declare const api: axios.AxiosInstance;
|
|
136
|
-
|
|
137
|
-
export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UseNotificationsParams, api, notificationKeys, useCreateNotification, useDeleteNotification, useNotifications, useUpdateNotification };
|
|
131
|
+
export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UpdateNotificationPreferencesParams, type UseNotificationPreferencesParams, type UseNotificationsParams, notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
|
package/dist/index.js
CHANGED
|
@@ -1,20 +1,14 @@
|
|
|
1
1
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
2
|
-
import {
|
|
3
|
-
import axios from 'axios';
|
|
2
|
+
import { supabase, NotificationsResponseSchema, NotificationPreferencesRowSchema, NotificationRowSchema } from '@pfm-platform/shared';
|
|
4
3
|
|
|
5
4
|
// src/queries/useNotifications.ts
|
|
6
|
-
var api = axios.create({
|
|
7
|
-
baseURL: "/api",
|
|
8
|
-
headers: {
|
|
9
|
-
"Content-Type": "application/json"
|
|
10
|
-
}
|
|
11
|
-
});
|
|
12
5
|
|
|
13
6
|
// src/keys.ts
|
|
14
7
|
var notificationKeys = {
|
|
15
8
|
all: ["notifications"],
|
|
16
9
|
lists: () => [...notificationKeys.all, "list"],
|
|
17
|
-
list: (userId) => [...notificationKeys.lists(), userId]
|
|
10
|
+
list: (userId) => [...notificationKeys.lists(), userId],
|
|
11
|
+
preferences: (userId) => [...notificationKeys.all, "preferences", userId]
|
|
18
12
|
};
|
|
19
13
|
|
|
20
14
|
// src/queries/useNotifications.ts
|
|
@@ -22,27 +16,45 @@ function useNotifications({ userId }, options) {
|
|
|
22
16
|
return useQuery({
|
|
23
17
|
queryKey: notificationKeys.list(userId),
|
|
24
18
|
queryFn: async () => {
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
return
|
|
19
|
+
const { data, error } = await supabase.from("notifications").select("*").eq("user_id", userId).order("created_at", { ascending: false });
|
|
20
|
+
if (error) throw new Error(error.message);
|
|
21
|
+
return NotificationsResponseSchema.parse(data);
|
|
28
22
|
},
|
|
29
23
|
staleTime: 1e3 * 60 * 2,
|
|
30
24
|
// 2 minutes (notifications change frequently)
|
|
31
25
|
...options
|
|
32
26
|
});
|
|
33
27
|
}
|
|
28
|
+
function useNotificationPreferences({ userId }, options) {
|
|
29
|
+
return useQuery({
|
|
30
|
+
queryKey: notificationKeys.preferences(userId),
|
|
31
|
+
queryFn: async () => {
|
|
32
|
+
const { data, error } = await supabase.from("notification_preferences").select("*").eq("user_id", userId).single();
|
|
33
|
+
if (error) throw new Error(error.message);
|
|
34
|
+
const row = NotificationPreferencesRowSchema.parse(data);
|
|
35
|
+
return {
|
|
36
|
+
emailNotifications: row.email_notifications,
|
|
37
|
+
pushNotifications: row.push_notifications,
|
|
38
|
+
frequency: row.frequency
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
staleTime: 1e3 * 60 * 5,
|
|
42
|
+
// 5 minutes (preferences change infrequently)
|
|
43
|
+
...options
|
|
44
|
+
});
|
|
45
|
+
}
|
|
34
46
|
function useCreateNotification(options) {
|
|
35
47
|
const queryClient = useQueryClient();
|
|
36
|
-
const { mode } = useAppMode();
|
|
37
48
|
return useMutation({
|
|
38
49
|
mutationFn: async ({ userId, data }) => {
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
);
|
|
45
|
-
|
|
50
|
+
const { data: row, error } = await supabase.from("notifications").insert({
|
|
51
|
+
user_id: userId,
|
|
52
|
+
message: data.message,
|
|
53
|
+
alert_type: data.alert_type,
|
|
54
|
+
...data.created_at ? { created_at: data.created_at } : {}
|
|
55
|
+
}).select().single();
|
|
56
|
+
if (error) throw new Error(error.message);
|
|
57
|
+
return NotificationRowSchema.parse(row);
|
|
46
58
|
},
|
|
47
59
|
onSuccess: (_, { userId }) => {
|
|
48
60
|
queryClient.invalidateQueries({
|
|
@@ -54,20 +66,15 @@ function useCreateNotification(options) {
|
|
|
54
66
|
}
|
|
55
67
|
function useUpdateNotification(options) {
|
|
56
68
|
const queryClient = useQueryClient();
|
|
57
|
-
const { mode } = useAppMode();
|
|
58
69
|
return useMutation({
|
|
59
70
|
mutationFn: async ({
|
|
60
71
|
userId,
|
|
61
72
|
notificationId,
|
|
62
73
|
data
|
|
63
74
|
}) => {
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
`/users/${userId}/alerts/notifications/${notificationId}`,
|
|
68
|
-
validated
|
|
69
|
-
);
|
|
70
|
-
return NotificationSchema.parse(response.data);
|
|
75
|
+
const { data: row, error } = await supabase.from("notifications").update(data).eq("id", notificationId).eq("user_id", userId).select().single();
|
|
76
|
+
if (error) throw new Error(error.message);
|
|
77
|
+
return NotificationRowSchema.parse(row);
|
|
71
78
|
},
|
|
72
79
|
onSuccess: (_, { userId }) => {
|
|
73
80
|
queryClient.invalidateQueries({
|
|
@@ -81,7 +88,8 @@ function useDeleteNotification(options) {
|
|
|
81
88
|
const queryClient = useQueryClient();
|
|
82
89
|
return useMutation({
|
|
83
90
|
mutationFn: async ({ userId, notificationId }) => {
|
|
84
|
-
await
|
|
91
|
+
const { error } = await supabase.from("notifications").delete().eq("id", notificationId).eq("user_id", userId);
|
|
92
|
+
if (error) throw new Error(error.message);
|
|
85
93
|
},
|
|
86
94
|
onSuccess: (_, { userId }) => {
|
|
87
95
|
queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });
|
|
@@ -89,7 +97,36 @@ function useDeleteNotification(options) {
|
|
|
89
97
|
...options
|
|
90
98
|
});
|
|
91
99
|
}
|
|
100
|
+
function useUpdateNotificationPreferences(options) {
|
|
101
|
+
const queryClient = useQueryClient();
|
|
102
|
+
return useMutation({
|
|
103
|
+
mutationFn: async ({ userId, data }) => {
|
|
104
|
+
const dbData = { user_id: userId };
|
|
105
|
+
if (data.emailNotifications !== void 0) {
|
|
106
|
+
dbData.email_notifications = data.emailNotifications;
|
|
107
|
+
}
|
|
108
|
+
if (data.pushNotifications !== void 0) {
|
|
109
|
+
dbData.push_notifications = data.pushNotifications;
|
|
110
|
+
}
|
|
111
|
+
if (data.frequency !== void 0) {
|
|
112
|
+
dbData.frequency = data.frequency;
|
|
113
|
+
}
|
|
114
|
+
const { data: row, error } = await supabase.from("notification_preferences").upsert(dbData).select().single();
|
|
115
|
+
if (error) throw new Error(error.message);
|
|
116
|
+
const validated = NotificationPreferencesRowSchema.parse(row);
|
|
117
|
+
return {
|
|
118
|
+
emailNotifications: validated.email_notifications,
|
|
119
|
+
pushNotifications: validated.push_notifications,
|
|
120
|
+
frequency: validated.frequency
|
|
121
|
+
};
|
|
122
|
+
},
|
|
123
|
+
onSuccess: (_, { userId }) => {
|
|
124
|
+
queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });
|
|
125
|
+
},
|
|
126
|
+
...options
|
|
127
|
+
});
|
|
128
|
+
}
|
|
92
129
|
|
|
93
|
-
export {
|
|
130
|
+
export { notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
|
|
94
131
|
//# sourceMappingURL=index.js.map
|
|
95
132
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts","../src/keys.ts","../src/queries/useNotifications.ts","../src/mutations/useCreateNotification.ts","../src/mutations/useUpdateNotification.ts","../src/mutations/useDeleteNotification.ts"],"names":["useQueryClient","useAppMode","useMutation","NotificationSchema"],"mappings":"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","file":"index.js","sourcesContent":["import axios from 'axios';\n\n/**\n * Axios instance for Notifications API\n * Base URL configured through environment variables or defaults to relative path\n */\nexport const api = axios.create({\n baseURL: '/api',\n headers: {\n 'Content-Type': 'application/json',\n },\n});\n","/**\n * Query key factory for Notifications domain\n */\nexport const notificationKeys = {\n all: ['notifications'] as const,\n lists: () => [...notificationKeys.all, 'list'] as const,\n list: (userId: string) => [...notificationKeys.lists(), userId] as const,\n};\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { Notification, NotificationsResponseSchema } from '@pfm-platform/shared';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationsParams {\n userId: string;\n}\n\n/**\n * Fetch all notifications for a user\n * GET /users/:userId/alerts/notifications\n *\n * Notifications are system-generated based on alert configurations\n * Read-only domain (no create/update operations)\n */\nexport function useNotifications(\n { userId }: UseNotificationsParams,\n options?: Omit<UseQueryOptions<Notification[]>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.list(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/alerts/notifications`);\n const validated = NotificationsResponseSchema.parse(response.data);\n return validated.notifications;\n },\n staleTime: 1000 * 60 * 2, // 2 minutes (notifications change frequently)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationCreateSchemaAdmin,\n NotificationCreateSchemaUser,\n NotificationSchema,\n useAppMode,\n type AlertType,\n} from '@pfm-platform/shared';\nimport type { Notification } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { notificationKeys } from '../keys';\n\n/**\n * Notification create data interface\n */\nexport interface NotificationCreate {\n message: string;\n alert_type: AlertType;\n created_at?: string;\n}\n\n/**\n * Parameters for useCreateNotification mutation\n */\nexport interface CreateNotificationParams {\n userId: string;\n data: NotificationCreate;\n}\n\n/**\n * Mutation hook for creating a new notification\n *\n * Creates a notification manually for testing purposes.\n * Uses mode switching for validation:\n * - Admin mode: Allows manual notification creation for test data\n * - User mode: Blocked (notifications are system-generated)\n *\n * @example\n * ```tsx\n * const createNotification = useCreateNotification();\n *\n * createNotification.mutate({\n * userId: 'user123',\n * data: {\n * message: 'Test notification',\n * alert_type: 'AccountThresholdAlert',\n * created_at: new Date().toISOString() // Optional\n * }\n * });\n * ```\n */\nexport function useCreateNotification(\n options?: Omit<\n UseMutationOptions<Notification, Error, CreateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNotificationParams) => {\n // Select schema based on mode\n const schema =\n mode === 'admin'\n ? NotificationCreateSchemaAdmin\n : NotificationCreateSchemaUser;\n\n // Validate notification data\n const validated = schema.parse(data);\n\n // POST to create new notification\n const response = await api.post(\n `/users/${userId}/alerts/notifications`,\n validated\n );\n\n // Return created notification\n return NotificationSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications query to refetch updated list\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationUpdateSchemaAdmin,\n NotificationUpdateSchemaUser,\n NotificationSchema,\n useAppMode,\n type AlertType,\n} from '@pfm-platform/shared';\nimport type { Notification } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { notificationKeys } from '../keys';\n\n/**\n * Notification update data interface\n */\nexport interface NotificationUpdate {\n message?: string;\n alert_type?: AlertType;\n}\n\n/**\n * Parameters for useUpdateNotification mutation\n */\nexport interface UpdateNotificationParams {\n userId: string;\n notificationId: number;\n data: NotificationUpdate;\n}\n\n/**\n * Mutation hook for updating a notification\n *\n * Updates notification fields for testing purposes.\n * Uses mode switching for validation:\n * - Admin mode: Allows updating notifications for test scenarios\n * - User mode: Blocked (notifications are system-generated)\n *\n * @example\n * ```tsx\n * const updateNotification = useUpdateNotification();\n *\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: {\n * message: 'Updated test notification'\n * }\n * });\n * ```\n */\nexport function useUpdateNotification(\n options?: Omit<\n UseMutationOptions<Notification, Error, UpdateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({\n userId,\n notificationId,\n data,\n }: UpdateNotificationParams) => {\n // Select schema based on mode\n const schema =\n mode === 'admin'\n ? NotificationUpdateSchemaAdmin\n : NotificationUpdateSchemaUser;\n\n // Validate notification update data\n const validated = schema.parse(data);\n\n // PUT to update notification\n const response = await api.put(\n `/users/${userId}/alerts/notifications/${notificationId}`,\n validated\n );\n\n // Return updated notification\n return NotificationSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications query to refetch updated list\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface DeleteNotificationParams {\n userId: string;\n notificationId: number;\n}\n\n/**\n * Delete a notification\n * DELETE /users/:userId/alerts/notifications/:notificationId\n *\n * Notifications are system-generated, deletion only removes from view\n */\nexport function useDeleteNotification(\n options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, notificationId }: DeleteNotificationParams) => {\n await api.delete(`/users/${userId}/alerts/notifications/${notificationId}`);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate notifications list to refetch without deleted item\n queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });\n },\n ...options,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/keys.ts","../src/queries/useNotifications.ts","../src/queries/useNotificationPreferences.ts","../src/mutations/useCreateNotification.ts","../src/mutations/useUpdateNotification.ts","../src/mutations/useDeleteNotification.ts","../src/mutations/useUpdateNotificationPreferences.ts"],"names":["useQuery","useQueryClient","useMutation","NotificationRowSchema","NotificationPreferencesRowSchema"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Query key factory for Notifications domain\n */\nexport const notificationKeys = {\n all: ['notifications'] as const,\n lists: () => [...notificationKeys.all, 'list'] as const,\n list: (userId: string) => [...notificationKeys.lists(), userId] as const,\n preferences: (userId: string) => [...notificationKeys.all, 'preferences', userId] as const,\n};\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { NotificationsResponseSchema, type NotificationRow } from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationsParams {\n userId: string;\n}\n\n/**\n * Fetch all notifications for a user\n * Supabase: SELECT * FROM notifications WHERE user_id = :userId ORDER BY created_at DESC\n */\nexport function useNotifications(\n { userId }: UseNotificationsParams,\n options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.list(userId),\n queryFn: async () => {\n const { data, error } = await supabase\n .from('notifications')\n .select('*')\n .eq('user_id', userId)\n .order('created_at', { ascending: false });\n\n if (error) throw new Error(error.message);\n return NotificationsResponseSchema.parse(data);\n },\n staleTime: 1000 * 60 * 2, // 2 minutes (notifications change frequently)\n ...options,\n });\n}\n","import { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport {\n NotificationPreferencesRowSchema,\n type NotificationPreferences,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationPreferencesParams {\n userId: string;\n}\n\n/**\n * Fetch user notification preferences\n * Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId\n *\n * Transforms snake_case DB columns to camelCase for feature/UI layers\n */\nexport function useNotificationPreferences(\n { userId }: UseNotificationPreferencesParams,\n options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: notificationKeys.preferences(userId),\n queryFn: async () => {\n const { data, error } = await supabase\n .from('notification_preferences')\n .select('*')\n .eq('user_id', userId)\n .single();\n\n if (error) throw new Error(error.message);\n\n const row = NotificationPreferencesRowSchema.parse(data);\n\n // Transform snake_case → camelCase for feature/UI layers\n return {\n emailNotifications: row.email_notifications,\n pushNotifications: row.push_notifications,\n frequency: row.frequency,\n } as NotificationPreferences;\n },\n staleTime: 1000 * 60 * 5, // 5 minutes (preferences change infrequently)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationRowSchema,\n type AlertType,\n type NotificationRow,\n type TablesInsert,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\n/**\n * Notification create data interface\n */\nexport interface NotificationCreate {\n message: string;\n alert_type: AlertType;\n created_at?: string;\n}\n\n/**\n * Parameters for useCreateNotification mutation\n */\nexport interface CreateNotificationParams {\n userId: string;\n data: NotificationCreate;\n}\n\n/**\n * Mutation hook for creating a new notification\n */\nexport function useCreateNotification(\n options?: Omit<\n UseMutationOptions<NotificationRow, Error, CreateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNotificationParams) => {\n const { data: row, error } = await supabase\n .from('notifications')\n .insert({\n user_id: userId,\n message: data.message,\n alert_type: data.alert_type,\n ...(data.created_at ? { created_at: data.created_at } : {}),\n } as TablesInsert<'notifications'>)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n return NotificationRowSchema.parse(row);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NotificationRowSchema,\n type AlertType,\n type NotificationRow,\n type TablesUpdate,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\n/**\n * Notification update data interface\n */\nexport interface NotificationUpdate {\n message?: string;\n alert_type?: AlertType;\n is_read?: boolean;\n}\n\n/**\n * Parameters for useUpdateNotification mutation\n */\nexport interface UpdateNotificationParams {\n userId: string;\n notificationId: string;\n data: NotificationUpdate;\n}\n\n/**\n * Mutation hook for updating a notification\n */\nexport function useUpdateNotification(\n options?: Omit<\n UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({\n userId,\n notificationId,\n data,\n }: UpdateNotificationParams) => {\n const { data: row, error } = await supabase\n .from('notifications')\n .update(data as TablesUpdate<'notifications'>)\n .eq('id', notificationId)\n .eq('user_id', userId)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n return NotificationRowSchema.parse(row);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: notificationKeys.list(userId),\n });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface DeleteNotificationParams {\n userId: string;\n notificationId: string;\n}\n\n/**\n * Delete a notification\n * Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId\n */\nexport function useDeleteNotification(\n options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, notificationId }: DeleteNotificationParams) => {\n const { error } = await supabase\n .from('notifications')\n .delete()\n .eq('id', notificationId)\n .eq('user_id', userId);\n\n if (error) throw new Error(error.message);\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });\n },\n ...options,\n });\n}\n","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport {\n NotificationPreferencesRowSchema,\n type NotificationPreferences,\n type TablesInsert,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UpdateNotificationPreferencesParams {\n userId: string;\n data: Partial<NotificationPreferences>;\n}\n\n/**\n * Update user notification preferences\n * Supabase: UPSERT notification_preferences\n *\n * Transforms camelCase input → snake_case for Supabase,\n * then transforms response back to camelCase\n */\nexport function useUpdateNotificationPreferences(\n options?: UseMutationOptions<\n NotificationPreferences,\n Error,\n UpdateNotificationPreferencesParams\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: UpdateNotificationPreferencesParams) => {\n // Transform camelCase → snake_case for Supabase\n const dbData: Record<string, unknown> = { user_id: userId };\n if (data.emailNotifications !== undefined) {\n dbData.email_notifications = data.emailNotifications;\n }\n if (data.pushNotifications !== undefined) {\n dbData.push_notifications = data.pushNotifications;\n }\n if (data.frequency !== undefined) {\n dbData.frequency = data.frequency;\n }\n\n const { data: row, error } = await supabase\n .from('notification_preferences')\n .upsert(dbData as TablesInsert<'notification_preferences'>)\n .select()\n .single();\n\n if (error) throw new Error(error.message);\n\n const validated = NotificationPreferencesRowSchema.parse(row);\n\n // Transform snake_case → camelCase for feature/UI layers\n return {\n emailNotifications: validated.email_notifications,\n pushNotifications: validated.push_notifications,\n frequency: validated.frequency,\n } as NotificationPreferences;\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });\n },\n ...options,\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,21 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pfm-platform/notifications-data-access",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"axios": "^1.13.2",
|
|
8
7
|
"zod": "4.1.12",
|
|
9
|
-
"@pfm-platform/shared": "0.
|
|
8
|
+
"@pfm-platform/shared": "0.2.1"
|
|
10
9
|
},
|
|
11
10
|
"devDependencies": {
|
|
12
|
-
"@testing-library/react": "^16.3.
|
|
13
|
-
"@vitejs/plugin-react": "^5.1.
|
|
14
|
-
"@vitest/coverage-v8": "^4.0.
|
|
11
|
+
"@testing-library/react": "^16.3.2",
|
|
12
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
13
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
15
14
|
"jsdom": "^27.2.0",
|
|
16
|
-
"react-dom": "19.2.
|
|
15
|
+
"react-dom": "19.2.4",
|
|
17
16
|
"typescript": "5.9.3",
|
|
18
|
-
"vitest": "4.0.
|
|
17
|
+
"vitest": "4.0.18"
|
|
19
18
|
},
|
|
20
19
|
"module": "./dist/index.js",
|
|
21
20
|
"types": "./dist/index.d.ts",
|