@pfm-platform/notifications-data-access 0.2.0 → 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 CHANGED
@@ -2,19 +2,8 @@
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: "http://localhost:3000/api",
14
- headers: {
15
- "Content-Type": "application/json"
16
- }
17
- });
18
7
 
19
8
  // src/keys.ts
20
9
  var notificationKeys = {
@@ -29,9 +18,9 @@ function useNotifications({ userId }, options) {
29
18
  return reactQuery.useQuery({
30
19
  queryKey: notificationKeys.list(userId),
31
20
  queryFn: async () => {
32
- const response = await api.get(`/users/${userId}/alerts/notifications`);
33
- const validated = shared.NotificationsResponseSchema.parse(response.data);
34
- return validated.notifications;
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);
35
24
  },
36
25
  staleTime: 1e3 * 60 * 2,
37
26
  // 2 minutes (notifications change frequently)
@@ -42,9 +31,14 @@ function useNotificationPreferences({ userId }, options) {
42
31
  return reactQuery.useQuery({
43
32
  queryKey: notificationKeys.preferences(userId),
44
33
  queryFn: async () => {
45
- const response = await api.get(`/users/${userId}/notifications/preferences`);
46
- const validated = shared.NotificationPreferencesSchema.parse(response.data);
47
- return validated;
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
+ };
48
42
  },
49
43
  staleTime: 1e3 * 60 * 5,
50
44
  // 5 minutes (preferences change infrequently)
@@ -53,16 +47,16 @@ function useNotificationPreferences({ userId }, options) {
53
47
  }
54
48
  function useCreateNotification(options) {
55
49
  const queryClient = reactQuery.useQueryClient();
56
- const { mode } = shared.useAppMode();
57
50
  return reactQuery.useMutation({
58
51
  mutationFn: async ({ userId, data }) => {
59
- const schema = mode === "admin" ? shared.NotificationCreateSchemaAdmin : shared.NotificationCreateSchemaUser;
60
- const validated = schema.parse(data);
61
- const response = await api.post(
62
- `/users/${userId}/alerts/notifications`,
63
- validated
64
- );
65
- return shared.NotificationSchema.parse(response.data);
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);
66
60
  },
67
61
  onSuccess: (_, { userId }) => {
68
62
  queryClient.invalidateQueries({
@@ -74,20 +68,15 @@ function useCreateNotification(options) {
74
68
  }
75
69
  function useUpdateNotification(options) {
76
70
  const queryClient = reactQuery.useQueryClient();
77
- const { mode } = shared.useAppMode();
78
71
  return reactQuery.useMutation({
79
72
  mutationFn: async ({
80
73
  userId,
81
74
  notificationId,
82
75
  data
83
76
  }) => {
84
- const schema = mode === "admin" ? shared.NotificationUpdateSchemaAdmin : shared.NotificationUpdateSchemaUser;
85
- const validated = schema.parse(data);
86
- const response = await api.put(
87
- `/users/${userId}/alerts/notifications/${notificationId}`,
88
- validated
89
- );
90
- 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);
91
80
  },
92
81
  onSuccess: (_, { userId }) => {
93
82
  queryClient.invalidateQueries({
@@ -101,7 +90,8 @@ function useDeleteNotification(options) {
101
90
  const queryClient = reactQuery.useQueryClient();
102
91
  return reactQuery.useMutation({
103
92
  mutationFn: async ({ userId, notificationId }) => {
104
- await api.delete(`/users/${userId}/alerts/notifications/${notificationId}`);
93
+ const { error } = await shared.supabase.from("notifications").delete().eq("id", notificationId).eq("user_id", userId);
94
+ if (error) throw new Error(error.message);
105
95
  },
106
96
  onSuccess: (_, { userId }) => {
107
97
  queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });
@@ -113,9 +103,24 @@ function useUpdateNotificationPreferences(options) {
113
103
  const queryClient = reactQuery.useQueryClient();
114
104
  return reactQuery.useMutation({
115
105
  mutationFn: async ({ userId, data }) => {
116
- const validated = shared.NotificationPreferencesUpdateSchema.parse(data);
117
- const response = await api.put(`/users/${userId}/notifications/preferences`, validated);
118
- return shared.NotificationPreferencesSchema.parse(response.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
+ };
119
124
  },
120
125
  onSuccess: (_, { userId }) => {
121
126
  queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });
@@ -124,7 +129,6 @@ function useUpdateNotificationPreferences(options) {
124
129
  });
125
130
  }
126
131
 
127
- exports.api = api;
128
132
  exports.notificationKeys = notificationKeys;
129
133
  exports.useCreateNotification = useCreateNotification;
130
134
  exports.useDeleteNotification = useDeleteNotification;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts","../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":["axios","useQuery","NotificationsResponseSchema","NotificationPreferencesSchema","useQueryClient","useAppMode","useMutation","NotificationCreateSchemaAdmin","NotificationCreateSchemaUser","NotificationSchema","NotificationUpdateSchemaAdmin","NotificationUpdateSchemaUser","NotificationPreferencesUpdateSchema"],"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 localhost for tests\n */\nexport const api = axios.create({\n baseURL: 'http://localhost:3000/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 preferences: (userId: string) => [...notificationKeys.all, 'preferences', 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 { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { NotificationPreferences, NotificationPreferencesSchema } from '@pfm-platform/shared';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationPreferencesParams {\n userId: string;\n}\n\n/**\n * Fetch user notification preferences\n * GET /users/:userId/notifications/preferences\n *\n * Returns user preferences for notification delivery and frequency\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 response = await api.get(`/users/${userId}/notifications/preferences`);\n const validated = NotificationPreferencesSchema.parse(response.data);\n return validated;\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 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 is_read?: boolean;\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 * Uses mode switching for validation:\n * - Admin mode: Allows updating message and alert_type for test scenarios\n * - User mode: Allows marking notifications as read/unread\n *\n * @example\n * ```tsx\n * const updateNotification = useUpdateNotification();\n *\n * // User mode: mark as read\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: { is_read: true }\n * });\n *\n * // Admin mode: update message\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: { message: 'Updated test notification' }\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","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport {\n NotificationPreferences,\n NotificationPreferencesSchema,\n NotificationPreferencesUpdateSchema,\n} from '@pfm-platform/shared';\nimport { api } 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 * PUT /users/:userId/notifications/preferences\n *\n * Updates delivery and frequency preferences for notifications\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 // Validate update data\n const validated = NotificationPreferencesUpdateSchema.parse(data);\n\n const response = await api.put(`/users/${userId}/notifications/preferences`, validated);\n return NotificationPreferencesSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate preferences query to refetch\n queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(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":"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","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,26 +1,22 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
3
- import { Notification, NotificationPreferences, AlertType } from '@pfm-platform/shared';
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
- * GET /users/:userId/alerts/notifications
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<Notification[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
17
- id: number;
12
+ declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
13
+ id: string;
18
14
  user_id: string;
19
- alert_id: number;
20
- message: string;
15
+ alert_id: string | null;
21
16
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
17
+ message: string;
22
18
  is_read: boolean;
23
- created_at: string;
19
+ created_at: string | null;
24
20
  }[], Error>;
25
21
 
26
22
  interface UseNotificationPreferencesParams {
@@ -28,9 +24,9 @@ interface UseNotificationPreferencesParams {
28
24
  }
29
25
  /**
30
26
  * Fetch user notification preferences
31
- * GET /users/:userId/notifications/preferences
27
+ * Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId
32
28
  *
33
- * Returns user preferences for notification delivery and frequency
29
+ * Transforms snake_case DB columns to camelCase for feature/UI layers
34
30
  */
35
31
  declare function useNotificationPreferences({ userId }: UseNotificationPreferencesParams, options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
36
32
  emailNotifications: boolean;
@@ -55,34 +51,15 @@ interface CreateNotificationParams {
55
51
  }
56
52
  /**
57
53
  * Mutation hook for creating a new notification
58
- *
59
- * Creates a notification manually for testing purposes.
60
- * Uses mode switching for validation:
61
- * - Admin mode: Allows manual notification creation for test data
62
- * - User mode: Blocked (notifications are system-generated)
63
- *
64
- * @example
65
- * ```tsx
66
- * const createNotification = useCreateNotification();
67
- *
68
- * createNotification.mutate({
69
- * userId: 'user123',
70
- * data: {
71
- * message: 'Test notification',
72
- * alert_type: 'AccountThresholdAlert',
73
- * created_at: new Date().toISOString() // Optional
74
- * }
75
- * });
76
- * ```
77
54
  */
78
- declare function useCreateNotification(options?: Omit<UseMutationOptions<Notification, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
79
- id: number;
55
+ declare function useCreateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
56
+ id: string;
80
57
  user_id: string;
81
- alert_id: number;
82
- message: string;
58
+ alert_id: string | null;
83
59
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
60
+ message: string;
84
61
  is_read: boolean;
85
- created_at: string;
62
+ created_at: string | null;
86
63
  }, Error, CreateNotificationParams, unknown>;
87
64
 
88
65
  /**
@@ -98,54 +75,29 @@ interface NotificationUpdate {
98
75
  */
99
76
  interface UpdateNotificationParams {
100
77
  userId: string;
101
- notificationId: number;
78
+ notificationId: string;
102
79
  data: NotificationUpdate;
103
80
  }
104
81
  /**
105
82
  * Mutation hook for updating a notification
106
- *
107
- * Uses mode switching for validation:
108
- * - Admin mode: Allows updating message and alert_type for test scenarios
109
- * - User mode: Allows marking notifications as read/unread
110
- *
111
- * @example
112
- * ```tsx
113
- * const updateNotification = useUpdateNotification();
114
- *
115
- * // User mode: mark as read
116
- * updateNotification.mutate({
117
- * userId: 'user123',
118
- * notificationId: 1,
119
- * data: { is_read: true }
120
- * });
121
- *
122
- * // Admin mode: update message
123
- * updateNotification.mutate({
124
- * userId: 'user123',
125
- * notificationId: 1,
126
- * data: { message: 'Updated test notification' }
127
- * });
128
- * ```
129
83
  */
130
- declare function useUpdateNotification(options?: Omit<UseMutationOptions<Notification, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
131
- id: number;
84
+ declare function useUpdateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
85
+ id: string;
132
86
  user_id: string;
133
- alert_id: number;
134
- message: string;
87
+ alert_id: string | null;
135
88
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
89
+ message: string;
136
90
  is_read: boolean;
137
- created_at: string;
91
+ created_at: string | null;
138
92
  }, Error, UpdateNotificationParams, unknown>;
139
93
 
140
94
  interface DeleteNotificationParams {
141
95
  userId: string;
142
- notificationId: number;
96
+ notificationId: string;
143
97
  }
144
98
  /**
145
99
  * Delete a notification
146
- * DELETE /users/:userId/alerts/notifications/:notificationId
147
- *
148
- * Notifications are system-generated, deletion only removes from view
100
+ * Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId
149
101
  */
150
102
  declare function useDeleteNotification(options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<void, Error, DeleteNotificationParams, unknown>;
151
103
 
@@ -155,9 +107,10 @@ interface UpdateNotificationPreferencesParams {
155
107
  }
156
108
  /**
157
109
  * Update user notification preferences
158
- * PUT /users/:userId/notifications/preferences
110
+ * Supabase: UPSERT notification_preferences
159
111
  *
160
- * Updates delivery and frequency preferences for notifications
112
+ * Transforms camelCase input snake_case for Supabase,
113
+ * then transforms response back to camelCase
161
114
  */
162
115
  declare function useUpdateNotificationPreferences(options?: UseMutationOptions<NotificationPreferences, Error, UpdateNotificationPreferencesParams>): _tanstack_react_query.UseMutationResult<{
163
116
  emailNotifications: boolean;
@@ -175,10 +128,4 @@ declare const notificationKeys: {
175
128
  preferences: (userId: string) => readonly ["notifications", "preferences", string];
176
129
  };
177
130
 
178
- /**
179
- * Axios instance for Notifications API
180
- * Base URL configured through environment variables or defaults to localhost for tests
181
- */
182
- declare const api: axios.AxiosInstance;
183
-
184
- export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UpdateNotificationPreferencesParams, type UseNotificationPreferencesParams, type UseNotificationsParams, api, notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
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,26 +1,22 @@
1
1
  import * as _tanstack_react_query from '@tanstack/react-query';
2
2
  import { UseQueryOptions, UseMutationOptions } from '@tanstack/react-query';
3
- import { Notification, NotificationPreferences, AlertType } from '@pfm-platform/shared';
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
- * GET /users/:userId/alerts/notifications
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<Notification[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
17
- id: number;
12
+ declare function useNotifications({ userId }: UseNotificationsParams, options?: Omit<UseQueryOptions<NotificationRow[]>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
13
+ id: string;
18
14
  user_id: string;
19
- alert_id: number;
20
- message: string;
15
+ alert_id: string | null;
21
16
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
17
+ message: string;
22
18
  is_read: boolean;
23
- created_at: string;
19
+ created_at: string | null;
24
20
  }[], Error>;
25
21
 
26
22
  interface UseNotificationPreferencesParams {
@@ -28,9 +24,9 @@ interface UseNotificationPreferencesParams {
28
24
  }
29
25
  /**
30
26
  * Fetch user notification preferences
31
- * GET /users/:userId/notifications/preferences
27
+ * Supabase: SELECT * FROM notification_preferences WHERE user_id = :userId
32
28
  *
33
- * Returns user preferences for notification delivery and frequency
29
+ * Transforms snake_case DB columns to camelCase for feature/UI layers
34
30
  */
35
31
  declare function useNotificationPreferences({ userId }: UseNotificationPreferencesParams, options?: Omit<UseQueryOptions<NotificationPreferences>, 'queryKey' | 'queryFn'>): _tanstack_react_query.UseQueryResult<{
36
32
  emailNotifications: boolean;
@@ -55,34 +51,15 @@ interface CreateNotificationParams {
55
51
  }
56
52
  /**
57
53
  * Mutation hook for creating a new notification
58
- *
59
- * Creates a notification manually for testing purposes.
60
- * Uses mode switching for validation:
61
- * - Admin mode: Allows manual notification creation for test data
62
- * - User mode: Blocked (notifications are system-generated)
63
- *
64
- * @example
65
- * ```tsx
66
- * const createNotification = useCreateNotification();
67
- *
68
- * createNotification.mutate({
69
- * userId: 'user123',
70
- * data: {
71
- * message: 'Test notification',
72
- * alert_type: 'AccountThresholdAlert',
73
- * created_at: new Date().toISOString() // Optional
74
- * }
75
- * });
76
- * ```
77
54
  */
78
- declare function useCreateNotification(options?: Omit<UseMutationOptions<Notification, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
79
- id: number;
55
+ declare function useCreateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, CreateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
56
+ id: string;
80
57
  user_id: string;
81
- alert_id: number;
82
- message: string;
58
+ alert_id: string | null;
83
59
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
60
+ message: string;
84
61
  is_read: boolean;
85
- created_at: string;
62
+ created_at: string | null;
86
63
  }, Error, CreateNotificationParams, unknown>;
87
64
 
88
65
  /**
@@ -98,54 +75,29 @@ interface NotificationUpdate {
98
75
  */
99
76
  interface UpdateNotificationParams {
100
77
  userId: string;
101
- notificationId: number;
78
+ notificationId: string;
102
79
  data: NotificationUpdate;
103
80
  }
104
81
  /**
105
82
  * Mutation hook for updating a notification
106
- *
107
- * Uses mode switching for validation:
108
- * - Admin mode: Allows updating message and alert_type for test scenarios
109
- * - User mode: Allows marking notifications as read/unread
110
- *
111
- * @example
112
- * ```tsx
113
- * const updateNotification = useUpdateNotification();
114
- *
115
- * // User mode: mark as read
116
- * updateNotification.mutate({
117
- * userId: 'user123',
118
- * notificationId: 1,
119
- * data: { is_read: true }
120
- * });
121
- *
122
- * // Admin mode: update message
123
- * updateNotification.mutate({
124
- * userId: 'user123',
125
- * notificationId: 1,
126
- * data: { message: 'Updated test notification' }
127
- * });
128
- * ```
129
83
  */
130
- declare function useUpdateNotification(options?: Omit<UseMutationOptions<Notification, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
131
- id: number;
84
+ declare function useUpdateNotification(options?: Omit<UseMutationOptions<NotificationRow, Error, UpdateNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<{
85
+ id: string;
132
86
  user_id: string;
133
- alert_id: number;
134
- message: string;
87
+ alert_id: string | null;
135
88
  alert_type: "AccountThresholdAlert" | "GoalAlert" | "MerchantNameAlert" | "SpendingTargetAlert" | "TransactionLimitAlert" | "UpcomingBillAlert";
89
+ message: string;
136
90
  is_read: boolean;
137
- created_at: string;
91
+ created_at: string | null;
138
92
  }, Error, UpdateNotificationParams, unknown>;
139
93
 
140
94
  interface DeleteNotificationParams {
141
95
  userId: string;
142
- notificationId: number;
96
+ notificationId: string;
143
97
  }
144
98
  /**
145
99
  * Delete a notification
146
- * DELETE /users/:userId/alerts/notifications/:notificationId
147
- *
148
- * Notifications are system-generated, deletion only removes from view
100
+ * Supabase: DELETE FROM notifications WHERE id = :notificationId AND user_id = :userId
149
101
  */
150
102
  declare function useDeleteNotification(options?: Omit<UseMutationOptions<void, Error, DeleteNotificationParams>, 'mutationFn'>): _tanstack_react_query.UseMutationResult<void, Error, DeleteNotificationParams, unknown>;
151
103
 
@@ -155,9 +107,10 @@ interface UpdateNotificationPreferencesParams {
155
107
  }
156
108
  /**
157
109
  * Update user notification preferences
158
- * PUT /users/:userId/notifications/preferences
110
+ * Supabase: UPSERT notification_preferences
159
111
  *
160
- * Updates delivery and frequency preferences for notifications
112
+ * Transforms camelCase input snake_case for Supabase,
113
+ * then transforms response back to camelCase
161
114
  */
162
115
  declare function useUpdateNotificationPreferences(options?: UseMutationOptions<NotificationPreferences, Error, UpdateNotificationPreferencesParams>): _tanstack_react_query.UseMutationResult<{
163
116
  emailNotifications: boolean;
@@ -175,10 +128,4 @@ declare const notificationKeys: {
175
128
  preferences: (userId: string) => readonly ["notifications", "preferences", string];
176
129
  };
177
130
 
178
- /**
179
- * Axios instance for Notifications API
180
- * Base URL configured through environment variables or defaults to localhost for tests
181
- */
182
- declare const api: axios.AxiosInstance;
183
-
184
- export { type CreateNotificationParams, type DeleteNotificationParams, type NotificationCreate, type NotificationUpdate, type UpdateNotificationParams, type UpdateNotificationPreferencesParams, type UseNotificationPreferencesParams, type UseNotificationsParams, api, notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
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,14 +1,7 @@
1
1
  import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
2
- import { NotificationsResponseSchema, NotificationPreferencesSchema, useAppMode, NotificationCreateSchemaAdmin, NotificationCreateSchemaUser, NotificationSchema, NotificationUpdateSchemaAdmin, NotificationUpdateSchemaUser, NotificationPreferencesUpdateSchema } from '@pfm-platform/shared';
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: "http://localhost:3000/api",
8
- headers: {
9
- "Content-Type": "application/json"
10
- }
11
- });
12
5
 
13
6
  // src/keys.ts
14
7
  var notificationKeys = {
@@ -23,9 +16,9 @@ function useNotifications({ userId }, options) {
23
16
  return useQuery({
24
17
  queryKey: notificationKeys.list(userId),
25
18
  queryFn: async () => {
26
- const response = await api.get(`/users/${userId}/alerts/notifications`);
27
- const validated = NotificationsResponseSchema.parse(response.data);
28
- return validated.notifications;
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);
29
22
  },
30
23
  staleTime: 1e3 * 60 * 2,
31
24
  // 2 minutes (notifications change frequently)
@@ -36,9 +29,14 @@ function useNotificationPreferences({ userId }, options) {
36
29
  return useQuery({
37
30
  queryKey: notificationKeys.preferences(userId),
38
31
  queryFn: async () => {
39
- const response = await api.get(`/users/${userId}/notifications/preferences`);
40
- const validated = NotificationPreferencesSchema.parse(response.data);
41
- return validated;
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
+ };
42
40
  },
43
41
  staleTime: 1e3 * 60 * 5,
44
42
  // 5 minutes (preferences change infrequently)
@@ -47,16 +45,16 @@ function useNotificationPreferences({ userId }, options) {
47
45
  }
48
46
  function useCreateNotification(options) {
49
47
  const queryClient = useQueryClient();
50
- const { mode } = useAppMode();
51
48
  return useMutation({
52
49
  mutationFn: async ({ userId, data }) => {
53
- const schema = mode === "admin" ? NotificationCreateSchemaAdmin : NotificationCreateSchemaUser;
54
- const validated = schema.parse(data);
55
- const response = await api.post(
56
- `/users/${userId}/alerts/notifications`,
57
- validated
58
- );
59
- return NotificationSchema.parse(response.data);
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);
60
58
  },
61
59
  onSuccess: (_, { userId }) => {
62
60
  queryClient.invalidateQueries({
@@ -68,20 +66,15 @@ function useCreateNotification(options) {
68
66
  }
69
67
  function useUpdateNotification(options) {
70
68
  const queryClient = useQueryClient();
71
- const { mode } = useAppMode();
72
69
  return useMutation({
73
70
  mutationFn: async ({
74
71
  userId,
75
72
  notificationId,
76
73
  data
77
74
  }) => {
78
- const schema = mode === "admin" ? NotificationUpdateSchemaAdmin : NotificationUpdateSchemaUser;
79
- const validated = schema.parse(data);
80
- const response = await api.put(
81
- `/users/${userId}/alerts/notifications/${notificationId}`,
82
- validated
83
- );
84
- 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);
85
78
  },
86
79
  onSuccess: (_, { userId }) => {
87
80
  queryClient.invalidateQueries({
@@ -95,7 +88,8 @@ function useDeleteNotification(options) {
95
88
  const queryClient = useQueryClient();
96
89
  return useMutation({
97
90
  mutationFn: async ({ userId, notificationId }) => {
98
- await api.delete(`/users/${userId}/alerts/notifications/${notificationId}`);
91
+ const { error } = await supabase.from("notifications").delete().eq("id", notificationId).eq("user_id", userId);
92
+ if (error) throw new Error(error.message);
99
93
  },
100
94
  onSuccess: (_, { userId }) => {
101
95
  queryClient.invalidateQueries({ queryKey: notificationKeys.list(userId) });
@@ -107,9 +101,24 @@ function useUpdateNotificationPreferences(options) {
107
101
  const queryClient = useQueryClient();
108
102
  return useMutation({
109
103
  mutationFn: async ({ userId, data }) => {
110
- const validated = NotificationPreferencesUpdateSchema.parse(data);
111
- const response = await api.put(`/users/${userId}/notifications/preferences`, validated);
112
- return NotificationPreferencesSchema.parse(response.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
+ };
113
122
  },
114
123
  onSuccess: (_, { userId }) => {
115
124
  queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(userId) });
@@ -118,6 +127,6 @@ function useUpdateNotificationPreferences(options) {
118
127
  });
119
128
  }
120
129
 
121
- export { api, notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
130
+ export { notificationKeys, useCreateNotification, useDeleteNotification, useNotificationPreferences, useNotifications, useUpdateNotification, useUpdateNotificationPreferences };
122
131
  //# sourceMappingURL=index.js.map
123
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/queries/useNotificationPreferences.ts","../src/mutations/useCreateNotification.ts","../src/mutations/useUpdateNotification.ts","../src/mutations/useDeleteNotification.ts","../src/mutations/useUpdateNotificationPreferences.ts"],"names":["useQuery","useQueryClient","useAppMode","useMutation","NotificationSchema","NotificationPreferencesSchema"],"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 localhost for tests\n */\nexport const api = axios.create({\n baseURL: 'http://localhost:3000/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 preferences: (userId: string) => [...notificationKeys.all, 'preferences', 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 { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { NotificationPreferences, NotificationPreferencesSchema } from '@pfm-platform/shared';\nimport { api } from '../client.js';\nimport { notificationKeys } from '../keys.js';\n\nexport interface UseNotificationPreferencesParams {\n userId: string;\n}\n\n/**\n * Fetch user notification preferences\n * GET /users/:userId/notifications/preferences\n *\n * Returns user preferences for notification delivery and frequency\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 response = await api.get(`/users/${userId}/notifications/preferences`);\n const validated = NotificationPreferencesSchema.parse(response.data);\n return validated;\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 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 is_read?: boolean;\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 * Uses mode switching for validation:\n * - Admin mode: Allows updating message and alert_type for test scenarios\n * - User mode: Allows marking notifications as read/unread\n *\n * @example\n * ```tsx\n * const updateNotification = useUpdateNotification();\n *\n * // User mode: mark as read\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: { is_read: true }\n * });\n *\n * // Admin mode: update message\n * updateNotification.mutate({\n * userId: 'user123',\n * notificationId: 1,\n * data: { message: 'Updated test notification' }\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","import { useMutation, UseMutationOptions, useQueryClient } from '@tanstack/react-query';\nimport {\n NotificationPreferences,\n NotificationPreferencesSchema,\n NotificationPreferencesUpdateSchema,\n} from '@pfm-platform/shared';\nimport { api } 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 * PUT /users/:userId/notifications/preferences\n *\n * Updates delivery and frequency preferences for notifications\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 // Validate update data\n const validated = NotificationPreferencesUpdateSchema.parse(data);\n\n const response = await api.put(`/users/${userId}/notifications/preferences`, validated);\n return NotificationPreferencesSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate preferences query to refetch\n queryClient.invalidateQueries({ queryKey: notificationKeys.preferences(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.2.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.1.0"
8
+ "@pfm-platform/shared": "0.2.1"
10
9
  },
11
10
  "devDependencies": {
12
- "@testing-library/react": "^16.3.0",
13
- "@vitejs/plugin-react": "^5.1.1",
14
- "@vitest/coverage-v8": "^4.0.9",
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.0",
15
+ "react-dom": "19.2.4",
17
16
  "typescript": "5.9.3",
18
- "vitest": "4.0.9"
17
+ "vitest": "4.0.18"
19
18
  },
20
19
  "module": "./dist/index.js",
21
20
  "types": "./dist/index.d.ts",