@pfm-platform/goals-data-access 0.1.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.js ADDED
@@ -0,0 +1,245 @@
1
+ import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
2
+ import { SavingsGoalsResponseSchema, SavingsGoalSchema, GoalImagesResponseSchema, GoalCreateSchema, GoalUpdateSchema, PayoffGoalsResponseSchema, PayoffGoalSchema } from '@pfm-platform/shared';
3
+ import axios from 'axios';
4
+
5
+ // src/queries/useSavingsGoals.ts
6
+ var api = axios.create({
7
+ baseURL: "/api",
8
+ headers: {
9
+ "Content-Type": "application/json"
10
+ }
11
+ });
12
+
13
+ // src/keys.ts
14
+ var goalKeys = {
15
+ all: ["goals"],
16
+ // Savings goals
17
+ savingsLists: () => [...goalKeys.all, "savings", "list"],
18
+ savingsList: (userId) => [...goalKeys.savingsLists(), userId],
19
+ savingsDetails: () => [...goalKeys.all, "savings", "detail"],
20
+ savingsDetail: (userId, goalId) => [...goalKeys.savingsDetails(), userId, goalId],
21
+ // Payoff goals
22
+ payoffLists: () => [...goalKeys.all, "payoff", "list"],
23
+ payoffList: (userId) => [...goalKeys.payoffLists(), userId],
24
+ payoffDetails: () => [...goalKeys.all, "payoff", "detail"],
25
+ payoffDetail: (userId, goalId) => [...goalKeys.payoffDetails(), userId, goalId],
26
+ // Image catalogs (no userId, global resources)
27
+ savingsImages: () => [...goalKeys.all, "savings", "images"],
28
+ payoffImages: () => [...goalKeys.all, "payoff", "images"]
29
+ };
30
+
31
+ // src/queries/useSavingsGoals.ts
32
+ function useSavingsGoals(params, options) {
33
+ const { userId } = params;
34
+ return useQuery({
35
+ queryKey: goalKeys.savingsList(userId),
36
+ queryFn: async () => {
37
+ const response = await api.get(`/users/${userId}/savings_goals`);
38
+ return SavingsGoalsResponseSchema.parse(response.data);
39
+ },
40
+ staleTime: 1e3 * 60 * 5,
41
+ // 5 minutes (same as budgets)
42
+ ...options
43
+ });
44
+ }
45
+ function useSavingsGoal(params, options) {
46
+ const { userId, goalId } = params;
47
+ return useQuery({
48
+ queryKey: goalKeys.savingsDetail(userId, goalId),
49
+ queryFn: async () => {
50
+ const response = await api.get(
51
+ `/users/${userId}/savings_goals/${goalId}`
52
+ );
53
+ return SavingsGoalSchema.parse(response.data);
54
+ },
55
+ staleTime: 1e3 * 60 * 5,
56
+ // 5 minutes
57
+ ...options
58
+ });
59
+ }
60
+ function useSavingsGoalImages(options) {
61
+ return useQuery({
62
+ queryKey: goalKeys.savingsImages(),
63
+ queryFn: async () => {
64
+ const response = await api.get("/savings_goals");
65
+ return GoalImagesResponseSchema.parse(response.data);
66
+ },
67
+ staleTime: 1e3 * 60 * 60 * 24,
68
+ // 24 hours (images rarely change)
69
+ ...options
70
+ });
71
+ }
72
+ function useCreateSavingsGoal(options) {
73
+ const queryClient = useQueryClient();
74
+ return useMutation({
75
+ mutationFn: async ({ userId, data }) => {
76
+ const validated = GoalCreateSchema.parse(data);
77
+ const response = await api.post(`/users/${userId}/savings_goals`, {
78
+ savings_goal: validated
79
+ });
80
+ return SavingsGoalSchema.parse(response.data);
81
+ },
82
+ onSuccess: (_, { userId }) => {
83
+ queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });
84
+ },
85
+ ...options
86
+ });
87
+ }
88
+ function useUpdateSavingsGoal(options) {
89
+ const queryClient = useQueryClient();
90
+ return useMutation({
91
+ mutationFn: async ({ userId, goalId, data }) => {
92
+ const validated = GoalUpdateSchema.parse(data);
93
+ const { id, ...payload } = validated;
94
+ const response = await api.put(`/users/${userId}/savings_goals/${goalId}`, {
95
+ savings_goal: payload
96
+ });
97
+ return SavingsGoalSchema.parse(response.data);
98
+ },
99
+ onSuccess: (_, { userId, goalId }) => {
100
+ queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });
101
+ queryClient.invalidateQueries({
102
+ queryKey: goalKeys.savingsDetail(userId, goalId)
103
+ });
104
+ },
105
+ ...options
106
+ });
107
+ }
108
+ function useArchiveSavingsGoal(options) {
109
+ const queryClient = useQueryClient();
110
+ return useMutation({
111
+ mutationFn: async ({ userId, goalId }) => {
112
+ await api.put(`/users/${userId}/savings_goals/${goalId}/archive`);
113
+ },
114
+ onSuccess: (_, { userId, goalId }) => {
115
+ queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });
116
+ queryClient.invalidateQueries({
117
+ queryKey: goalKeys.savingsDetail(userId, goalId)
118
+ });
119
+ },
120
+ ...options
121
+ });
122
+ }
123
+ function useDeleteSavingsGoal(options) {
124
+ const queryClient = useQueryClient();
125
+ return useMutation({
126
+ mutationFn: async ({ userId, goalId }) => {
127
+ await api.delete(`/users/${userId}/savings_goals/${goalId}`);
128
+ },
129
+ onSuccess: (_, { userId, goalId }) => {
130
+ queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });
131
+ queryClient.removeQueries({
132
+ queryKey: goalKeys.savingsDetail(userId, goalId)
133
+ });
134
+ },
135
+ ...options
136
+ });
137
+ }
138
+ function usePayoffGoals(params, options) {
139
+ const { userId } = params;
140
+ return useQuery({
141
+ queryKey: goalKeys.payoffList(userId),
142
+ queryFn: async () => {
143
+ const response = await api.get(`/users/${userId}/payoff_goals`);
144
+ return PayoffGoalsResponseSchema.parse(response.data);
145
+ },
146
+ staleTime: 1e3 * 60 * 5,
147
+ // 5 minutes (same as budgets)
148
+ ...options
149
+ });
150
+ }
151
+ function usePayoffGoal(params, options) {
152
+ const { userId, goalId } = params;
153
+ return useQuery({
154
+ queryKey: goalKeys.payoffDetail(userId, goalId),
155
+ queryFn: async () => {
156
+ const response = await api.get(`/users/${userId}/payoff_goals/${goalId}`);
157
+ return PayoffGoalSchema.parse(response.data);
158
+ },
159
+ staleTime: 1e3 * 60 * 5,
160
+ // 5 minutes
161
+ ...options
162
+ });
163
+ }
164
+ function usePayoffGoalImages(options) {
165
+ return useQuery({
166
+ queryKey: goalKeys.payoffImages(),
167
+ queryFn: async () => {
168
+ const response = await api.get("/payoff_goals");
169
+ return GoalImagesResponseSchema.parse(response.data);
170
+ },
171
+ staleTime: 1e3 * 60 * 60 * 24,
172
+ // 24 hours (images rarely change)
173
+ ...options
174
+ });
175
+ }
176
+ function useCreatePayoffGoal(options) {
177
+ const queryClient = useQueryClient();
178
+ return useMutation({
179
+ mutationFn: async ({ userId, data }) => {
180
+ const validated = GoalCreateSchema.parse(data);
181
+ const response = await api.post(`/users/${userId}/payoff_goals`, {
182
+ payoff_goal: validated
183
+ });
184
+ return PayoffGoalSchema.parse(response.data);
185
+ },
186
+ onSuccess: (_, { userId }) => {
187
+ queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });
188
+ },
189
+ ...options
190
+ });
191
+ }
192
+ function useUpdatePayoffGoal(options) {
193
+ const queryClient = useQueryClient();
194
+ return useMutation({
195
+ mutationFn: async ({ userId, goalId, data }) => {
196
+ const validated = GoalUpdateSchema.parse(data);
197
+ const { id, ...payload } = validated;
198
+ const response = await api.put(`/users/${userId}/payoff_goals/${goalId}`, {
199
+ payoff_goal: payload
200
+ });
201
+ return PayoffGoalSchema.parse(response.data);
202
+ },
203
+ onSuccess: (_, { userId, goalId }) => {
204
+ queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });
205
+ queryClient.invalidateQueries({
206
+ queryKey: goalKeys.payoffDetail(userId, goalId)
207
+ });
208
+ },
209
+ ...options
210
+ });
211
+ }
212
+ function useArchivePayoffGoal(options) {
213
+ const queryClient = useQueryClient();
214
+ return useMutation({
215
+ mutationFn: async ({ userId, goalId }) => {
216
+ await api.put(`/users/${userId}/payoff_goals/${goalId}/archive`);
217
+ },
218
+ onSuccess: (_, { userId, goalId }) => {
219
+ queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });
220
+ queryClient.invalidateQueries({
221
+ queryKey: goalKeys.payoffDetail(userId, goalId)
222
+ });
223
+ },
224
+ ...options
225
+ });
226
+ }
227
+ function useDeletePayoffGoal(options) {
228
+ const queryClient = useQueryClient();
229
+ return useMutation({
230
+ mutationFn: async ({ userId, goalId }) => {
231
+ await api.delete(`/users/${userId}/payoff_goals/${goalId}`);
232
+ },
233
+ onSuccess: (_, { userId, goalId }) => {
234
+ queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });
235
+ queryClient.removeQueries({
236
+ queryKey: goalKeys.payoffDetail(userId, goalId)
237
+ });
238
+ },
239
+ ...options
240
+ });
241
+ }
242
+
243
+ export { api, goalKeys, useArchivePayoffGoal, useArchiveSavingsGoal, useCreatePayoffGoal, useCreateSavingsGoal, useDeletePayoffGoal, useDeleteSavingsGoal, usePayoffGoal, usePayoffGoalImages, usePayoffGoals, useSavingsGoal, useSavingsGoalImages, useSavingsGoals, useUpdatePayoffGoal, useUpdateSavingsGoal };
244
+ //# sourceMappingURL=index.js.map
245
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts","../src/keys.ts","../src/queries/useSavingsGoals.ts","../src/queries/useSavingsGoal.ts","../src/queries/useSavingsGoalImages.ts","../src/mutations/useCreateSavingsGoal.ts","../src/mutations/useUpdateSavingsGoal.ts","../src/mutations/useArchiveSavingsGoal.ts","../src/mutations/useDeleteSavingsGoal.ts","../src/queries/usePayoffGoals.ts","../src/queries/usePayoffGoal.ts","../src/queries/usePayoffGoalImages.ts","../src/mutations/useCreatePayoffGoal.ts","../src/mutations/useUpdatePayoffGoal.ts","../src/mutations/useArchivePayoffGoal.ts","../src/mutations/useDeletePayoffGoal.ts"],"names":["useQuery","SavingsGoalSchema","useQueryClient","useMutation","GoalImagesResponseSchema","GoalCreateSchema","PayoffGoalSchema","GoalUpdateSchema"],"mappings":"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","file":"index.js","sourcesContent":["import axios from 'axios';\n\n/**\n * Axios instance for Goals 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 Goals domain\n * Handles both Savings goals and Payoff goals with shared structure\n */\n\nexport type GoalType = 'savings' | 'payoff';\n\nexport const goalKeys = {\n all: ['goals'] as const,\n\n // Savings goals\n savingsLists: () => [...goalKeys.all, 'savings', 'list'] as const,\n savingsList: (userId: string) =>\n [...goalKeys.savingsLists(), userId] as const,\n savingsDetails: () => [...goalKeys.all, 'savings', 'detail'] as const,\n savingsDetail: (userId: string, goalId: number) =>\n [...goalKeys.savingsDetails(), userId, goalId] as const,\n\n // Payoff goals\n payoffLists: () => [...goalKeys.all, 'payoff', 'list'] as const,\n payoffList: (userId: string) =>\n [...goalKeys.payoffLists(), userId] as const,\n payoffDetails: () => [...goalKeys.all, 'payoff', 'detail'] as const,\n payoffDetail: (userId: string, goalId: number) =>\n [...goalKeys.payoffDetails(), userId, goalId] as const,\n\n // Image catalogs (no userId, global resources)\n savingsImages: () => [...goalKeys.all, 'savings', 'images'] as const,\n payoffImages: () => [...goalKeys.all, 'payoff', 'images'] as const,\n};\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { SavingsGoalsResponseSchema, type SavingsGoalsResponse } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useSavingsGoals query hook\n */\nexport interface UseSavingsGoalsParams {\n userId: string;\n}\n\n/**\n * Query hook for fetching all savings goals for a user\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useSavingsGoals({ userId: 'user123' });\n * ```\n */\nexport function useSavingsGoals(\n params: UseSavingsGoalsParams,\n options?: Omit<UseQueryOptions<SavingsGoalsResponse>, 'queryKey' | 'queryFn'>\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: goalKeys.savingsList(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/savings_goals`);\n return SavingsGoalsResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes (same as budgets)\n ...options,\n });\n}\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { SavingsGoalSchema, type SavingsGoal } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useSavingsGoal query hook\n */\nexport interface UseSavingsGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Query hook for fetching a single savings goal by ID\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useSavingsGoal({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function useSavingsGoal(\n params: UseSavingsGoalParams,\n options?: Omit<UseQueryOptions<SavingsGoal>, 'queryKey' | 'queryFn'>\n) {\n const { userId, goalId } = params;\n\n return useQuery({\n queryKey: goalKeys.savingsDetail(userId, goalId),\n queryFn: async () => {\n const response = await api.get(\n `/users/${userId}/savings_goals/${goalId}`\n );\n return SavingsGoalSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n });\n}\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { GoalImagesResponseSchema, type GoalImagesResponse } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Query hook for fetching savings goal image catalog\n * This is a global resource (no userId required)\n *\n * @example\n * ```tsx\n * const { data, isLoading } = useSavingsGoalImages();\n * ```\n */\nexport function useSavingsGoalImages(\n options?: Omit<UseQueryOptions<GoalImagesResponse>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: goalKeys.savingsImages(),\n queryFn: async () => {\n const response = await api.get('/savings_goals');\n return GoalImagesResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 60 * 24, // 24 hours (images rarely change)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n GoalCreateSchema,\n SavingsGoalSchema,\n type GoalCreate,\n type SavingsGoal,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useCreateSavingsGoal mutation\n */\nexport interface CreateSavingsGoalParams {\n userId: string;\n data: GoalCreate;\n}\n\n/**\n * Mutation hook for creating a savings goal\n *\n * @example\n * ```tsx\n * const createSavingsGoal = useCreateSavingsGoal();\n *\n * createSavingsGoal.mutate({\n * userId: 'user123',\n * data: {\n * name: 'Emergency Fund',\n * image_name: 'piggy_bank',\n * target_value: '5000.00',\n * target_completion_on: '2026-12-31',\n * }\n * });\n * ```\n */\nexport function useCreateSavingsGoal(\n options?: Omit<\n UseMutationOptions<SavingsGoal, Error, CreateSavingsGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateSavingsGoalParams) => {\n const validated = GoalCreateSchema.parse(data);\n\n // Request body wrapping: { savings_goal: {...} }\n const response = await api.post(`/users/${userId}/savings_goals`, {\n savings_goal: validated,\n });\n\n return SavingsGoalSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate all savings goal lists\n queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n GoalUpdateSchema,\n SavingsGoalSchema,\n type GoalUpdate,\n type SavingsGoal,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useUpdateSavingsGoal mutation\n */\nexport interface UpdateSavingsGoalParams {\n userId: string;\n goalId: number;\n data: GoalUpdate;\n}\n\n/**\n * Mutation hook for updating a savings goal\n *\n * @example\n * ```tsx\n * const updateSavingsGoal = useUpdateSavingsGoal();\n *\n * updateSavingsGoal.mutate({\n * userId: 'user123',\n * goalId: 456,\n * data: {\n * id: 456,\n * name: 'Updated Emergency Fund',\n * image_name: 'piggy_bank',\n * target_value: '6000.00'\n * }\n * });\n * ```\n */\nexport function useUpdateSavingsGoal(\n options?: Omit<\n UseMutationOptions<SavingsGoal, Error, UpdateSavingsGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId, data }: UpdateSavingsGoalParams) => {\n const validated = GoalUpdateSchema.parse(data);\n\n // Request body wrapping: { savings_goal: {...} } (without id)\n const { id, ...payload } = validated;\n const response = await api.put(`/users/${userId}/savings_goals/${goalId}`, {\n savings_goal: payload,\n });\n\n return SavingsGoalSchema.parse(response.data);\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and specific detail\n queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });\n queryClient.invalidateQueries({\n queryKey: goalKeys.savingsDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useArchiveSavingsGoal mutation\n */\nexport interface ArchiveSavingsGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Mutation hook for archiving a savings goal\n * Archived goals remain in system but marked as inactive\n *\n * @example\n * ```tsx\n * const archiveSavingsGoal = useArchiveSavingsGoal();\n *\n * archiveSavingsGoal.mutate({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function useArchiveSavingsGoal(\n options?: Omit<\n UseMutationOptions<void, Error, ArchiveSavingsGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId }: ArchiveSavingsGoalParams) => {\n await api.put(`/users/${userId}/savings_goals/${goalId}/archive`);\n // No response body expected\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and specific detail\n queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });\n queryClient.invalidateQueries({\n queryKey: goalKeys.savingsDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useDeleteSavingsGoal mutation\n */\nexport interface DeleteSavingsGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Mutation hook for deleting a savings goal permanently\n *\n * @example\n * ```tsx\n * const deleteSavingsGoal = useDeleteSavingsGoal();\n *\n * deleteSavingsGoal.mutate({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function useDeleteSavingsGoal(\n options?: Omit<\n UseMutationOptions<void, Error, DeleteSavingsGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId }: DeleteSavingsGoalParams) => {\n await api.delete(`/users/${userId}/savings_goals/${goalId}`);\n // No response body expected (204 No Content)\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and remove specific detail from cache\n queryClient.invalidateQueries({ queryKey: goalKeys.savingsLists() });\n queryClient.removeQueries({\n queryKey: goalKeys.savingsDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { PayoffGoalsResponseSchema, type PayoffGoalsResponse } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for usePayoffGoals query hook\n */\nexport interface UsePayoffGoalsParams {\n userId: string;\n}\n\n/**\n * Query hook for fetching all payoff goals for a user\n *\n * @example\n * ```tsx\n * const { data, isLoading } = usePayoffGoals({ userId: 'user123' });\n * ```\n */\nexport function usePayoffGoals(\n params: UsePayoffGoalsParams,\n options?: Omit<UseQueryOptions<PayoffGoalsResponse>, 'queryKey' | 'queryFn'>\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: goalKeys.payoffList(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/payoff_goals`);\n return PayoffGoalsResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes (same as budgets)\n ...options,\n });\n}\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { PayoffGoalSchema, type PayoffGoal } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for usePayoffGoal query hook\n */\nexport interface UsePayoffGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Query hook for fetching a single payoff goal by ID\n *\n * @example\n * ```tsx\n * const { data, isLoading } = usePayoffGoal({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function usePayoffGoal(\n params: UsePayoffGoalParams,\n options?: Omit<UseQueryOptions<PayoffGoal>, 'queryKey' | 'queryFn'>\n) {\n const { userId, goalId } = params;\n\n return useQuery({\n queryKey: goalKeys.payoffDetail(userId, goalId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/payoff_goals/${goalId}`);\n return PayoffGoalSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n });\n}\n","import { useQuery, type UseQueryOptions } from '@tanstack/react-query';\nimport { GoalImagesResponseSchema, type GoalImagesResponse } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Query hook for fetching payoff goal image catalog\n * This is a global resource (no userId required)\n *\n * @example\n * ```tsx\n * const { data, isLoading } = usePayoffGoalImages();\n * ```\n */\nexport function usePayoffGoalImages(\n options?: Omit<UseQueryOptions<GoalImagesResponse>, 'queryKey' | 'queryFn'>\n) {\n return useQuery({\n queryKey: goalKeys.payoffImages(),\n queryFn: async () => {\n const response = await api.get('/payoff_goals');\n return GoalImagesResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 60 * 24, // 24 hours (images rarely change)\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n GoalCreateSchema,\n PayoffGoalSchema,\n type GoalCreate,\n type PayoffGoal,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useCreatePayoffGoal mutation\n */\nexport interface CreatePayoffGoalParams {\n userId: string;\n data: GoalCreate;\n}\n\n/**\n * Mutation hook for creating a payoff goal\n *\n * @example\n * ```tsx\n * const createPayoffGoal = useCreatePayoffGoal();\n *\n * createPayoffGoal.mutate({\n * userId: 'user123',\n * data: {\n * name: 'Credit Card Debt',\n * image_name: 'credit_card',\n * target_value: '3000.00',\n * target_completion_on: '2026-06-30',\n * }\n * });\n * ```\n */\nexport function useCreatePayoffGoal(\n options?: Omit<\n UseMutationOptions<PayoffGoal, Error, CreatePayoffGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreatePayoffGoalParams) => {\n const validated = GoalCreateSchema.parse(data);\n\n // Request body wrapping: { payoff_goal: {...} }\n const response = await api.post(`/users/${userId}/payoff_goals`, {\n payoff_goal: validated,\n });\n\n return PayoffGoalSchema.parse(response.data);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate all payoff goal lists\n queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n GoalUpdateSchema,\n PayoffGoalSchema,\n type GoalUpdate,\n type PayoffGoal,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useUpdatePayoffGoal mutation\n */\nexport interface UpdatePayoffGoalParams {\n userId: string;\n goalId: number;\n data: GoalUpdate;\n}\n\n/**\n * Mutation hook for updating a payoff goal\n *\n * @example\n * ```tsx\n * const updatePayoffGoal = useUpdatePayoffGoal();\n *\n * updatePayoffGoal.mutate({\n * userId: 'user123',\n * goalId: 456,\n * data: {\n * id: 456,\n * name: 'Updated Credit Card',\n * image_name: 'credit_card',\n * target_value: '2500.00'\n * }\n * });\n * ```\n */\nexport function useUpdatePayoffGoal(\n options?: Omit<\n UseMutationOptions<PayoffGoal, Error, UpdatePayoffGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId, data }: UpdatePayoffGoalParams) => {\n const validated = GoalUpdateSchema.parse(data);\n\n // Request body wrapping: { payoff_goal: {...} } (without id)\n const { id, ...payload } = validated;\n const response = await api.put(`/users/${userId}/payoff_goals/${goalId}`, {\n payoff_goal: payload,\n });\n\n return PayoffGoalSchema.parse(response.data);\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and specific detail\n queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });\n queryClient.invalidateQueries({\n queryKey: goalKeys.payoffDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useArchivePayoffGoal mutation\n */\nexport interface ArchivePayoffGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Mutation hook for archiving a payoff goal\n * Archived goals remain in system but marked as inactive\n *\n * @example\n * ```tsx\n * const archivePayoffGoal = useArchivePayoffGoal();\n *\n * archivePayoffGoal.mutate({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function useArchivePayoffGoal(\n options?: Omit<\n UseMutationOptions<void, Error, ArchivePayoffGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId }: ArchivePayoffGoalParams) => {\n await api.put(`/users/${userId}/payoff_goals/${goalId}/archive`);\n // No response body expected\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and specific detail\n queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });\n queryClient.invalidateQueries({\n queryKey: goalKeys.payoffDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport { api } from '../client';\nimport { goalKeys } from '../keys';\n\n/**\n * Parameters for useDeletePayoffGoal mutation\n */\nexport interface DeletePayoffGoalParams {\n userId: string;\n goalId: number;\n}\n\n/**\n * Mutation hook for deleting a payoff goal permanently\n *\n * @example\n * ```tsx\n * const deletePayoffGoal = useDeletePayoffGoal();\n *\n * deletePayoffGoal.mutate({\n * userId: 'user123',\n * goalId: 456\n * });\n * ```\n */\nexport function useDeletePayoffGoal(\n options?: Omit<\n UseMutationOptions<void, Error, DeletePayoffGoalParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, goalId }: DeletePayoffGoalParams) => {\n await api.delete(`/users/${userId}/payoff_goals/${goalId}`);\n // No response body expected (204 No Content)\n },\n onSuccess: (_, { userId, goalId }) => {\n // Invalidate lists and remove specific detail from cache\n queryClient.invalidateQueries({ queryKey: goalKeys.payoffLists() });\n queryClient.removeQueries({\n queryKey: goalKeys.payoffDetail(userId, goalId),\n });\n },\n ...options,\n });\n}\n"]}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "@pfm-platform/goals-data-access",
3
+ "version": "0.1.1",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "dependencies": {
8
+ "axios": "^1.13.2",
9
+ "zod": "4.1.12",
10
+ "@pfm-platform/shared": "0.0.1"
11
+ },
12
+ "devDependencies": {
13
+ "@testing-library/react": "^16.3.0",
14
+ "@vitejs/plugin-react": "^5.1.1",
15
+ "@vitest/coverage-v8": "^4.0.9",
16
+ "jsdom": "^27.2.0",
17
+ "react-dom": "19.2.0",
18
+ "typescript": "5.9.3",
19
+ "vitest": "4.0.9"
20
+ },
21
+ "module": "./dist/index.js",
22
+ "exports": {
23
+ ".": {
24
+ "types": "./dist/index.d.ts",
25
+ "import": "./dist/index.js",
26
+ "require": "./dist/index.cjs"
27
+ }
28
+ },
29
+ "files": [
30
+ "dist",
31
+ "README.md"
32
+ ],
33
+ "description": "Personal Finance Management - GOALS data-access layer",
34
+ "keywords": [
35
+ "pfm",
36
+ "finance",
37
+ "goals",
38
+ "data-access",
39
+ "react",
40
+ "typescript"
41
+ ],
42
+ "author": "Lenny Miller",
43
+ "license": "MIT",
44
+ "repository": {
45
+ "type": "git",
46
+ "url": "https://github.com/lennylmiller/pfm-research",
47
+ "directory": "packages/goals/data-access"
48
+ },
49
+ "bugs": "https://github.com/lennylmiller/pfm-research/issues",
50
+ "homepage": "https://github.com/lennylmiller/pfm-research#readme",
51
+ "peerDependencies": {
52
+ "@tanstack/react-query": "5.90.9",
53
+ "react": "19.2.0"
54
+ },
55
+ "scripts": {
56
+ "test": "vitest run",
57
+ "test:watch": "vitest",
58
+ "test:coverage": "vitest run --coverage",
59
+ "build": "tsup src/index.ts --format cjs,esm --dts --clean"
60
+ }
61
+ }