@pfm-platform/accounts-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 +89 -160
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +124 -566
- package/dist/index.d.ts +124 -566
- package/dist/index.js +91 -157
- package/dist/index.js.map +1 -1
- package/package.json +7 -9
package/dist/index.js
CHANGED
|
@@ -1,107 +1,18 @@
|
|
|
1
1
|
import { useQuery, useQueryClient, useMutation } from '@tanstack/react-query';
|
|
2
|
-
import { AccountsResponseSchema, AccountSchema,
|
|
3
|
-
import axios from 'axios';
|
|
2
|
+
import { supabase, AccountsResponseSchema, AccountSchema, useAppMode, AccountCreateSchemaAdmin, AccountCreateSchemaUser, AccountUpdateSchema } from '@pfm-platform/shared';
|
|
4
3
|
|
|
5
4
|
// src/queries/useAccounts.ts
|
|
6
5
|
|
|
7
6
|
// src/keys.ts
|
|
8
7
|
var accountKeys = {
|
|
9
|
-
/**
|
|
10
|
-
* Root key for all account-related queries
|
|
11
|
-
*/
|
|
12
8
|
all: ["accounts"],
|
|
13
|
-
/**
|
|
14
|
-
* Key for all account list queries
|
|
15
|
-
*/
|
|
16
9
|
lists: () => [...accountKeys.all, "list"],
|
|
17
|
-
/**
|
|
18
|
-
* Key for a specific user's account list
|
|
19
|
-
* @param userId - User ID
|
|
20
|
-
*/
|
|
21
10
|
list: (userId) => [...accountKeys.lists(), userId],
|
|
22
|
-
/**
|
|
23
|
-
* Key for all account detail queries
|
|
24
|
-
*/
|
|
25
11
|
details: () => [...accountKeys.all, "detail"],
|
|
26
|
-
/**
|
|
27
|
-
* Key for a specific account detail
|
|
28
|
-
* @param userId - User ID
|
|
29
|
-
* @param accountId - Account ID
|
|
30
|
-
*/
|
|
31
12
|
detail: (userId, accountId) => [...accountKeys.details(), userId, accountId],
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
*/
|
|
35
|
-
investments: () => [...accountKeys.all, "investments"],
|
|
36
|
-
/**
|
|
37
|
-
* Key for a specific account's investments
|
|
38
|
-
* @param userId - User ID
|
|
39
|
-
* @param accountId - Account ID
|
|
40
|
-
*/
|
|
41
|
-
investment: (userId, accountId) => [...accountKeys.investments(), userId, accountId],
|
|
42
|
-
/**
|
|
43
|
-
* Key for all account transaction queries
|
|
44
|
-
*/
|
|
45
|
-
transactions: () => [...accountKeys.all, "transactions"],
|
|
46
|
-
/**
|
|
47
|
-
* Key for a specific account's transactions
|
|
48
|
-
* @param userId - User ID
|
|
49
|
-
* @param accountId - Account ID
|
|
50
|
-
* @param page - Page number for pagination
|
|
51
|
-
*/
|
|
52
|
-
transaction: (userId, accountId, page) => [...accountKeys.transactions(), userId, accountId, page],
|
|
53
|
-
/**
|
|
54
|
-
* Key for all net worth queries
|
|
55
|
-
*/
|
|
56
|
-
networth: () => [...accountKeys.all, "networth"],
|
|
57
|
-
/**
|
|
58
|
-
* Key for a specific user's net worth summary
|
|
59
|
-
* @param userId - User ID
|
|
60
|
-
*/
|
|
61
|
-
networthSummary: (userId) => [...accountKeys.networth(), userId],
|
|
62
|
-
/**
|
|
63
|
-
* Key for all net worth account queries
|
|
64
|
-
*/
|
|
65
|
-
networthAccounts: () => [...accountKeys.networth(), "accounts"],
|
|
66
|
-
/**
|
|
67
|
-
* Key for a specific net worth account
|
|
68
|
-
* @param userId - User ID
|
|
69
|
-
* @param accountId - Net worth account ID
|
|
70
|
-
*/
|
|
71
|
-
networthAccount: (userId, accountId) => [...accountKeys.networthAccounts(), userId, accountId]
|
|
13
|
+
institutions: () => [...accountKeys.all, "institutions"],
|
|
14
|
+
institution: (userId) => [...accountKeys.institutions(), userId]
|
|
72
15
|
};
|
|
73
|
-
var api = axios.create({
|
|
74
|
-
baseURL: "/api",
|
|
75
|
-
headers: {
|
|
76
|
-
"Content-Type": "application/json"
|
|
77
|
-
},
|
|
78
|
-
timeout: 1e4
|
|
79
|
-
// 10 second timeout
|
|
80
|
-
});
|
|
81
|
-
api.interceptors.request.use(
|
|
82
|
-
(config) => {
|
|
83
|
-
const token = localStorage.getItem("auth_token");
|
|
84
|
-
if (token) {
|
|
85
|
-
config.headers.Authorization = `Bearer ${token}`;
|
|
86
|
-
}
|
|
87
|
-
return config;
|
|
88
|
-
},
|
|
89
|
-
(error) => {
|
|
90
|
-
return Promise.reject(error);
|
|
91
|
-
}
|
|
92
|
-
);
|
|
93
|
-
api.interceptors.response.use(
|
|
94
|
-
(response) => response,
|
|
95
|
-
(error) => {
|
|
96
|
-
if (error.response?.status === 401) {
|
|
97
|
-
localStorage.removeItem("auth_token");
|
|
98
|
-
if (typeof window !== "undefined") {
|
|
99
|
-
window.location.href = "/login";
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
return Promise.reject(error);
|
|
103
|
-
}
|
|
104
|
-
);
|
|
105
16
|
|
|
106
17
|
// src/queries/useAccounts.ts
|
|
107
18
|
function useAccounts(params, options) {
|
|
@@ -109,11 +20,11 @@ function useAccounts(params, options) {
|
|
|
109
20
|
return useQuery({
|
|
110
21
|
queryKey: accountKeys.list(userId),
|
|
111
22
|
queryFn: async () => {
|
|
112
|
-
const
|
|
113
|
-
|
|
23
|
+
const { data, error } = await supabase.from("accounts").select("*").eq("user_id", userId).order("name");
|
|
24
|
+
if (error) throw error;
|
|
25
|
+
return { accounts: AccountsResponseSchema.parse(data) };
|
|
114
26
|
},
|
|
115
27
|
staleTime: 1e3 * 60 * 5,
|
|
116
|
-
// 5 minutes - accounts don't change frequently
|
|
117
28
|
...options
|
|
118
29
|
});
|
|
119
30
|
}
|
|
@@ -122,24 +33,61 @@ function useAccount(params, options) {
|
|
|
122
33
|
return useQuery({
|
|
123
34
|
queryKey: accountKeys.detail(userId, accountId),
|
|
124
35
|
queryFn: async () => {
|
|
125
|
-
const
|
|
126
|
-
|
|
36
|
+
const { data, error } = await supabase.from("accounts").select("*").eq("id", accountId).eq("user_id", userId).single();
|
|
37
|
+
if (error) throw error;
|
|
38
|
+
return AccountSchema.parse(data);
|
|
127
39
|
},
|
|
128
40
|
staleTime: 1e3 * 60 * 5,
|
|
129
|
-
// 5 minutes
|
|
130
41
|
...options
|
|
131
42
|
});
|
|
132
43
|
}
|
|
133
44
|
function useNetWorth(params, options) {
|
|
134
45
|
const { userId } = params;
|
|
135
46
|
return useQuery({
|
|
136
|
-
queryKey: accountKeys.
|
|
47
|
+
queryKey: [...accountKeys.all, "networth", userId],
|
|
137
48
|
queryFn: async () => {
|
|
138
|
-
const
|
|
139
|
-
|
|
49
|
+
const { data: accounts, error: accountsError } = await supabase.from("networth_accounts").select("*").eq("user_id", userId);
|
|
50
|
+
if (accountsError) throw accountsError;
|
|
51
|
+
const { data: histories, error: historiesError } = await supabase.from("networth_history").select("*").eq("user_id", userId).order("year", { ascending: true }).order("month", { ascending: true });
|
|
52
|
+
if (historiesError) throw historiesError;
|
|
53
|
+
const assets = (accounts || []).filter((a) => a.account_type === "asset").map((a) => ({
|
|
54
|
+
id: a.id,
|
|
55
|
+
name: a.name,
|
|
56
|
+
balance: String(a.balance),
|
|
57
|
+
account_type: a.account_type,
|
|
58
|
+
additional_networth_account: a.additional_networth_account
|
|
59
|
+
}));
|
|
60
|
+
const debts = (accounts || []).filter((a) => a.account_type === "debt").map((a) => ({
|
|
61
|
+
id: a.id,
|
|
62
|
+
name: a.name,
|
|
63
|
+
balance: String(a.balance),
|
|
64
|
+
account_type: a.account_type,
|
|
65
|
+
additional_networth_account: a.additional_networth_account
|
|
66
|
+
}));
|
|
67
|
+
const totalAssets = assets.reduce((sum, a) => sum + parseFloat(a.balance), 0);
|
|
68
|
+
const totalDebts = debts.reduce((sum, d) => sum + parseFloat(d.balance), 0);
|
|
69
|
+
const networthHistories = (histories || []).map((h) => ({
|
|
70
|
+
total: String(h.total),
|
|
71
|
+
total_asset: String(h.total_asset),
|
|
72
|
+
total_debt: String(h.total_debt),
|
|
73
|
+
month: String(h.month).padStart(2, "0"),
|
|
74
|
+
year: String(h.year),
|
|
75
|
+
since_last_month: String(h.since_last_month)
|
|
76
|
+
}));
|
|
77
|
+
return {
|
|
78
|
+
meta: {
|
|
79
|
+
net_worth: String(totalAssets - totalDebts),
|
|
80
|
+
net_worth_change: "0",
|
|
81
|
+
// TODO: compute from networth_history
|
|
82
|
+
total_assets: String(totalAssets),
|
|
83
|
+
total_debts: String(totalDebts)
|
|
84
|
+
},
|
|
85
|
+
assets,
|
|
86
|
+
debts,
|
|
87
|
+
networth_histories: networthHistories
|
|
88
|
+
};
|
|
140
89
|
},
|
|
141
90
|
staleTime: 1e3 * 60 * 5,
|
|
142
|
-
// 5 minutes - net worth doesn't change frequently
|
|
143
91
|
...options
|
|
144
92
|
});
|
|
145
93
|
}
|
|
@@ -147,27 +95,22 @@ function useCreateAccount(options) {
|
|
|
147
95
|
const queryClient = useQueryClient();
|
|
148
96
|
const { mode } = useAppMode();
|
|
149
97
|
return useMutation({
|
|
150
|
-
mutationFn: async ({
|
|
98
|
+
mutationFn: async ({ data }) => {
|
|
151
99
|
const schema = mode === "admin" ? AccountCreateSchemaAdmin : AccountCreateSchemaUser;
|
|
152
100
|
const validated = schema.parse(data);
|
|
153
|
-
const
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
);
|
|
157
|
-
return AccountSchema.parse(response.data);
|
|
101
|
+
const { data: created, error } = await supabase.from("accounts").insert(validated).select().single();
|
|
102
|
+
if (error) throw error;
|
|
103
|
+
return AccountSchema.parse(created);
|
|
158
104
|
},
|
|
159
|
-
onSuccess: (newAccount, variables,
|
|
105
|
+
onSuccess: (newAccount, variables, onMutateResult, context) => {
|
|
160
106
|
queryClient.setQueryData(
|
|
161
107
|
accountKeys.list(variables.userId),
|
|
162
108
|
(oldData) => {
|
|
163
|
-
if (!oldData
|
|
164
|
-
return {
|
|
165
|
-
...oldData,
|
|
166
|
-
accounts: [...oldData.accounts, newAccount]
|
|
167
|
-
};
|
|
109
|
+
if (!oldData) return { accounts: [newAccount] };
|
|
110
|
+
return { accounts: [...oldData.accounts, newAccount] };
|
|
168
111
|
}
|
|
169
112
|
);
|
|
170
|
-
options?.onSuccess?.(newAccount, variables,
|
|
113
|
+
options?.onSuccess?.(newAccount, variables, onMutateResult, context);
|
|
171
114
|
},
|
|
172
115
|
...options
|
|
173
116
|
});
|
|
@@ -175,13 +118,11 @@ function useCreateAccount(options) {
|
|
|
175
118
|
function useUpdateAccount(options) {
|
|
176
119
|
const queryClient = useQueryClient();
|
|
177
120
|
return useMutation({
|
|
178
|
-
mutationFn: async ({
|
|
121
|
+
mutationFn: async ({ accountId, data }) => {
|
|
179
122
|
const validated = AccountUpdateSchema.parse(data);
|
|
180
|
-
const
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
);
|
|
184
|
-
return AccountSchema.parse(response.data);
|
|
123
|
+
const { data: updated, error } = await supabase.from("accounts").update(validated).eq("id", accountId).select().single();
|
|
124
|
+
if (error) throw error;
|
|
125
|
+
return AccountSchema.parse(updated);
|
|
185
126
|
},
|
|
186
127
|
onSuccess: (_, { userId, accountId }) => {
|
|
187
128
|
queryClient.invalidateQueries({
|
|
@@ -197,8 +138,9 @@ function useUpdateAccount(options) {
|
|
|
197
138
|
function useDeleteAccount(options) {
|
|
198
139
|
const queryClient = useQueryClient();
|
|
199
140
|
return useMutation({
|
|
200
|
-
mutationFn: async ({
|
|
201
|
-
await
|
|
141
|
+
mutationFn: async ({ accountId }) => {
|
|
142
|
+
const { error } = await supabase.from("accounts").delete().eq("id", accountId);
|
|
143
|
+
if (error) throw error;
|
|
202
144
|
},
|
|
203
145
|
onSuccess: (_, { userId, accountId }) => {
|
|
204
146
|
queryClient.invalidateQueries({
|
|
@@ -214,11 +156,10 @@ function useDeleteAccount(options) {
|
|
|
214
156
|
function useArchiveAccount(options) {
|
|
215
157
|
const queryClient = useQueryClient();
|
|
216
158
|
return useMutation({
|
|
217
|
-
mutationFn: async ({
|
|
218
|
-
const
|
|
219
|
-
|
|
220
|
-
);
|
|
221
|
-
return AccountSchema.parse(response.data);
|
|
159
|
+
mutationFn: async ({ accountId }) => {
|
|
160
|
+
const { data, error } = await supabase.from("accounts").update({ is_active: false }).eq("id", accountId).select().single();
|
|
161
|
+
if (error) throw error;
|
|
162
|
+
return AccountSchema.parse(data);
|
|
222
163
|
},
|
|
223
164
|
onSuccess: (_, { userId, accountId }) => {
|
|
224
165
|
queryClient.invalidateQueries({
|
|
@@ -235,21 +176,18 @@ function useCreateNetWorthAccount(options) {
|
|
|
235
176
|
const queryClient = useQueryClient();
|
|
236
177
|
return useMutation({
|
|
237
178
|
mutationFn: async ({ userId, data }) => {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
} else {
|
|
247
|
-
return NetWorthDebtSchema.parse(response.data);
|
|
248
|
-
}
|
|
179
|
+
const { error } = await supabase.from("networth_accounts").insert({
|
|
180
|
+
user_id: userId,
|
|
181
|
+
name: data.networth_account.name,
|
|
182
|
+
balance: parseFloat(data.networth_account.balance),
|
|
183
|
+
account_type: data.networth_account.account_type,
|
|
184
|
+
additional_networth_account: true
|
|
185
|
+
});
|
|
186
|
+
if (error) throw error;
|
|
249
187
|
},
|
|
250
188
|
onSuccess: (_, { userId }) => {
|
|
251
189
|
queryClient.invalidateQueries({
|
|
252
|
-
queryKey: accountKeys.
|
|
190
|
+
queryKey: [...accountKeys.all, "networth", userId]
|
|
253
191
|
});
|
|
254
192
|
},
|
|
255
193
|
...options
|
|
@@ -258,21 +196,17 @@ function useCreateNetWorthAccount(options) {
|
|
|
258
196
|
function useUpdateNetWorthAccount(options) {
|
|
259
197
|
const queryClient = useQueryClient();
|
|
260
198
|
return useMutation({
|
|
261
|
-
mutationFn: async ({
|
|
262
|
-
const
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
);
|
|
267
|
-
|
|
268
|
-
return NetWorthAssetSchema.parse(response.data);
|
|
269
|
-
} catch {
|
|
270
|
-
return NetWorthDebtSchema.parse(response.data);
|
|
271
|
-
}
|
|
199
|
+
mutationFn: async ({ accountId, data }) => {
|
|
200
|
+
const { error } = await supabase.from("networth_accounts").update({
|
|
201
|
+
name: data.networth_account.name,
|
|
202
|
+
balance: parseFloat(data.networth_account.balance),
|
|
203
|
+
account_type: data.networth_account.account_type
|
|
204
|
+
}).eq("id", String(accountId));
|
|
205
|
+
if (error) throw error;
|
|
272
206
|
},
|
|
273
207
|
onSuccess: (_, { userId }) => {
|
|
274
208
|
queryClient.invalidateQueries({
|
|
275
|
-
queryKey: accountKeys.
|
|
209
|
+
queryKey: [...accountKeys.all, "networth", userId]
|
|
276
210
|
});
|
|
277
211
|
},
|
|
278
212
|
...options
|
|
@@ -281,19 +215,19 @@ function useUpdateNetWorthAccount(options) {
|
|
|
281
215
|
function useDeleteNetWorthAccount(options) {
|
|
282
216
|
const queryClient = useQueryClient();
|
|
283
217
|
return useMutation({
|
|
284
|
-
mutationFn: async ({
|
|
285
|
-
|
|
286
|
-
|
|
218
|
+
mutationFn: async ({ accountId }) => {
|
|
219
|
+
const { error } = await supabase.from("networth_accounts").delete().eq("id", String(accountId));
|
|
220
|
+
if (error) throw error;
|
|
287
221
|
},
|
|
288
222
|
onSuccess: (_, { userId }) => {
|
|
289
223
|
queryClient.invalidateQueries({
|
|
290
|
-
queryKey: accountKeys.
|
|
224
|
+
queryKey: [...accountKeys.all, "networth", userId]
|
|
291
225
|
});
|
|
292
226
|
},
|
|
293
227
|
...options
|
|
294
228
|
});
|
|
295
229
|
}
|
|
296
230
|
|
|
297
|
-
export { accountKeys,
|
|
231
|
+
export { accountKeys, useAccount, useAccounts, useArchiveAccount, useCreateAccount, useCreateNetWorthAccount, useDeleteAccount, useDeleteNetWorthAccount, useNetWorth, useUpdateAccount, useUpdateNetWorthAccount };
|
|
298
232
|
//# sourceMappingURL=index.js.map
|
|
299
233
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/keys.ts","../src/client.ts","../src/queries/useAccounts.ts","../src/queries/useAccount.ts","../src/queries/useNetWorth.ts","../src/mutations/useCreateAccount.ts","../src/mutations/useUpdateAccount.ts","../src/mutations/useDeleteAccount.ts","../src/mutations/useArchiveAccount.ts","../src/mutations/useCreateNetWorthAccount.ts","../src/mutations/useUpdateNetWorthAccount.ts","../src/mutations/useDeleteNetWorthAccount.ts"],"names":["useQuery","AccountSchema","useQueryClient","useMutation","NetWorthAssetSchema","NetWorthDebtSchema"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Query key factory for Accounts domain\n * Following TanStack Query best practices for hierarchical cache keys\n *\n * Key structure:\n * - ['accounts'] - Root key for all account queries\n * - ['accounts', 'list', userId] - List of accounts for a user\n * - ['accounts', 'detail', userId, accountId] - Single account detail\n * - ['accounts', 'investments', userId, accountId] - Account investments\n * - ['accounts', 'transactions', userId, accountId, page] - Account transactions\n */\n\nexport const accountKeys = {\n /**\n * Root key for all account-related queries\n */\n all: ['accounts'] as const,\n\n /**\n * Key for all account list queries\n */\n lists: () => [...accountKeys.all, 'list'] as const,\n\n /**\n * Key for a specific user's account list\n * @param userId - User ID\n */\n list: (userId: string) => [...accountKeys.lists(), userId] as const,\n\n /**\n * Key for all account detail queries\n */\n details: () => [...accountKeys.all, 'detail'] as const,\n\n /**\n * Key for a specific account detail\n * @param userId - User ID\n * @param accountId - Account ID\n */\n detail: (userId: string, accountId: number) =>\n [...accountKeys.details(), userId, accountId] as const,\n\n /**\n * Key for all account investment queries\n */\n investments: () => [...accountKeys.all, 'investments'] as const,\n\n /**\n * Key for a specific account's investments\n * @param userId - User ID\n * @param accountId - Account ID\n */\n investment: (userId: string, accountId: number) =>\n [...accountKeys.investments(), userId, accountId] as const,\n\n /**\n * Key for all account transaction queries\n */\n transactions: () => [...accountKeys.all, 'transactions'] as const,\n\n /**\n * Key for a specific account's transactions\n * @param userId - User ID\n * @param accountId - Account ID\n * @param page - Page number for pagination\n */\n transaction: (userId: string, accountId: number, page: number) =>\n [...accountKeys.transactions(), userId, accountId, page] as const,\n\n /**\n * Key for all net worth queries\n */\n networth: () => [...accountKeys.all, 'networth'] as const,\n\n /**\n * Key for a specific user's net worth summary\n * @param userId - User ID\n */\n networthSummary: (userId: string) =>\n [...accountKeys.networth(), userId] as const,\n\n /**\n * Key for all net worth account queries\n */\n networthAccounts: () => [...accountKeys.networth(), 'accounts'] as const,\n\n /**\n * Key for a specific net worth account\n * @param userId - User ID\n * @param accountId - Net worth account ID\n */\n networthAccount: (userId: string, accountId: number) =>\n [...accountKeys.networthAccounts(), userId, accountId] as const,\n};\n","/**\n * Base API client for Accounts domain\n * Uses axios with interceptors for auth and error handling\n */\n\nimport axios from 'axios';\n\n/**\n * Axios instance configured for PFM API\n * Base URL can be overridden via VITE_API_BASE_URL environment variable\n */\nexport const api = axios.create({\n baseURL: '/api',\n headers: {\n 'Content-Type': 'application/json',\n },\n timeout: 10000, // 10 second timeout\n});\n\n/**\n * Request interceptor to add authentication token\n * Reads token from localStorage and adds to Authorization header\n */\napi.interceptors.request.use(\n (config) => {\n const token = localStorage.getItem('auth_token');\n if (token) {\n config.headers.Authorization = `Bearer ${token}`;\n }\n return config;\n },\n (error) => {\n return Promise.reject(error);\n }\n);\n\n/**\n * Response interceptor for global error handling\n * - 401: Redirect to login\n * - 403: Access forbidden\n * - 5xx: Server errors\n */\napi.interceptors.response.use(\n (response) => response,\n (error) => {\n if (error.response?.status === 401) {\n // Unauthorized - clear token and redirect to login\n localStorage.removeItem('auth_token');\n if (typeof window !== 'undefined') {\n window.location.href = '/login';\n }\n }\n return Promise.reject(error);\n }\n);\n","/**\n * Query hook for fetching all accounts for a user\n * Legacy API: GET /users/{userId}/accounts/all\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { AccountsResponseSchema, AccountsResponse } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface UseAccountsParams {\n userId: string;\n}\n\n/**\n * Fetch all accounts for a user\n * Uses Zod validation to ensure API response matches expected schema\n *\n * @param params - Query parameters\n * @param options - TanStack Query options\n * @returns Query result with validated accounts data\n *\n * @example\n * ```tsx\n * function AccountsList() {\n * const { data, isLoading, error } = useAccounts({ userId: 'user123' });\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return (\n * <ul>\n * {data.accounts.map(account => (\n * <li key={account.id}>{account.name}</li>\n * ))}\n * </ul>\n * );\n * }\n * ```\n */\nexport function useAccounts(\n params: UseAccountsParams,\n options?: Omit<\n UseQueryOptions<AccountsResponse>,\n 'queryKey' | 'queryFn'\n >\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: accountKeys.list(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/accounts/all`);\n\n // Validate response with Zod schema from Mini-Arc 1\n // This ensures type safety and catches API contract changes\n return AccountsResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes - accounts don't change frequently\n ...options,\n });\n}\n","/**\n * Query hook for fetching a single account by ID\n * Legacy API: GET /users/{userId}/accounts/{id}\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { AccountSchema, Account } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface UseAccountParams {\n userId: string;\n accountId: number;\n}\n\n/**\n * Fetch a single account by ID\n * Uses Zod validation to ensure API response matches expected schema\n *\n * @param params - Query parameters\n * @param options - TanStack Query options\n * @returns Query result with validated account data\n *\n * @example\n * ```tsx\n * function AccountDetail({ accountId }: { accountId: number }) {\n * const { data, isLoading, error } = useAccount({\n * userId: 'user123',\n * accountId\n * });\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return (\n * <div>\n * <h2>{data.name}</h2>\n * <p>Balance: ${data.balance}</p>\n * <p>Type: {data.account_type}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useAccount(\n params: UseAccountParams,\n options?: Omit<UseQueryOptions<Account>, 'queryKey' | 'queryFn'>\n) {\n const { userId, accountId } = params;\n\n return useQuery({\n queryKey: accountKeys.detail(userId, accountId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/accounts/${accountId}`);\n\n // Validate response with Zod schema from Mini-Arc 1\n return AccountSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes\n ...options,\n });\n}\n","/**\n * Query hook for fetching net worth summary for a user\n * Legacy API: GET /users/{userId}/networth\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { NetWorthResponseSchema, NetWorth } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface UseNetWorthParams {\n userId: string;\n}\n\n/**\n * Fetch net worth summary for a user\n * Includes: assets, debts, history, and summary metadata\n * Uses Zod validation to ensure API response matches expected schema\n *\n * @param params - Query parameters\n * @param options - TanStack Query options\n * @returns Query result with validated net worth data\n *\n * @example\n * ```tsx\n * function NetWorthSummary() {\n * const { data, isLoading, error } = useNetWorth({ userId: 'user123' });\n *\n * if (isLoading) return <div>Loading...</div>;\n * if (error) return <div>Error: {error.message}</div>;\n *\n * return (\n * <div>\n * <h2>Net Worth: {data.meta.net_worth}</h2>\n * <p>Total Assets: {data.meta.total_assets}</p>\n * <p>Total Debts: {data.meta.total_debts}</p>\n * </div>\n * );\n * }\n * ```\n */\nexport function useNetWorth(\n params: UseNetWorthParams,\n options?: Omit<\n UseQueryOptions<NetWorth>,\n 'queryKey' | 'queryFn'\n >\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: accountKeys.networthSummary(userId),\n queryFn: async () => {\n const response = await api.get(`/users/${userId}/networth`);\n\n // Validate response with Zod schema\n // This ensures type safety and catches API contract changes\n return NetWorthResponseSchema.parse(response.data);\n },\n staleTime: 1000 * 60 * 5, // 5 minutes - net worth doesn't change frequently\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n AccountCreateSchemaAdmin,\n AccountCreateSchemaUser,\n AccountSchema,\n useAppMode,\n type AccountCreate,\n type Account,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { accountKeys } from '../keys';\n\n/**\n * Parameters for useCreateAccount mutation\n */\nexport interface CreateAccountParams {\n userId: string;\n data: AccountCreate;\n}\n\n/**\n * Mutation hook for creating a new account\n *\n * Creates an account manually for testing purposes.\n * Uses mode switching for validation:\n * - Admin mode: Minimal validation for test data creation\n * - User mode: Full validation with business rules\n *\n * @example\n * ```tsx\n * const createAccount = useCreateAccount();\n *\n * createAccount.mutate({\n * userId: 'user123',\n * data: {\n * name: 'Test Checking',\n * balance: '1000.00',\n * account_type: 'checking',\n * state: 'active',\n * aggregation_type: 'partner',\n * include_in_expenses: true,\n * include_in_budget: true,\n * include_in_cashflow: true,\n * include_in_dashboard: true,\n * include_in_goals: false,\n * include_in_networth: true\n * }\n * });\n * ```\n */\nexport function useCreateAccount(\n options?: Omit<UseMutationOptions<Account, Error, CreateAccountParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateAccountParams) => {\n // Select schema based on mode\n const schema =\n mode === 'admin'\n ? AccountCreateSchemaAdmin\n : AccountCreateSchemaUser;\n\n // Validate account data\n const validated = schema.parse(data);\n\n // POST to create new account\n const response = await api.post(\n `/users/${userId}/accounts`,\n validated\n );\n\n // Return created account\n return AccountSchema.parse(response.data);\n },\n onSuccess: (newAccount, variables, context, mutation) => {\n // Update the cache directly with the new account\n queryClient.setQueryData(\n accountKeys.list(variables.userId),\n (oldData: any) => {\n if (!oldData?.accounts) return oldData;\n return {\n ...oldData,\n accounts: [...oldData.accounts, newAccount],\n };\n }\n );\n\n // Call user-provided onSuccess callback if provided\n options?.onSuccess?.(newAccount, variables, context, mutation);\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for updating an account\n * Legacy API: PUT /users/{userId}/accounts/{id}\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport {\n AccountUpdateSchema,\n AccountSchema,\n Account,\n AccountUpdate,\n} from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface UpdateAccountParams {\n userId: string;\n accountId: number;\n data: AccountUpdate;\n}\n\n/**\n * Update an existing account\n * Validates input with Zod schema and invalidates related queries on success\n *\n * @param options - TanStack Mutation options\n * @returns Mutation result\n *\n * @example\n * ```tsx\n * function AccountEditForm({ account }: { account: Account }) {\n * const updateAccount = useUpdateAccount();\n *\n * const handleSubmit = (formData) => {\n * updateAccount.mutate({\n * userId: 'user123',\n * accountId: account.id,\n * data: {\n * nickname: formData.nickname,\n * goal_amount: formData.goalAmount,\n * }\n * }, {\n * onSuccess: () => {\n * toast.success('Account updated!');\n * },\n * onError: (error) => {\n * toast.error(`Failed to update: ${error.message}`);\n * }\n * });\n * };\n *\n * return <form onSubmit={handleSubmit}>...</form>;\n * }\n * ```\n */\nexport function useUpdateAccount(\n options?: Omit<\n UseMutationOptions<Account, Error, UpdateAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, accountId, data }: UpdateAccountParams) => {\n // Validate input with Zod schema from Mini-Arc 1\n // This ensures type safety before sending to API\n const validated = AccountUpdateSchema.parse(data);\n\n const response = await api.put(\n `/users/${userId}/accounts/${accountId}`,\n validated\n );\n\n // Validate response\n return AccountSchema.parse(response.data);\n },\n onSuccess: (_, { userId, accountId }) => {\n // Invalidate account list query to refetch updated data\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n\n // Invalidate specific account detail query\n queryClient.invalidateQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for deleting an account\n * Legacy API: DELETE /users/{userId}/accounts/{id}\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface DeleteAccountParams {\n userId: string;\n accountId: number;\n}\n\n/**\n * Delete an account\n * Removes account from user's account list\n * Invalidates related queries on success\n *\n * @param options - TanStack Mutation options\n * @returns Mutation result\n *\n * @example\n * ```tsx\n * function AccountDeleteButton({ accountId }: { accountId: number }) {\n * const deleteAccount = useDeleteAccount();\n *\n * const handleDelete = () => {\n * if (confirm('Are you sure you want to delete this account?')) {\n * deleteAccount.mutate({\n * userId: 'user123',\n * accountId\n * }, {\n * onSuccess: () => {\n * toast.success('Account deleted successfully');\n * navigate('/accounts');\n * },\n * onError: (error) => {\n * toast.error(`Failed to delete: ${error.message}`);\n * }\n * });\n * }\n * };\n *\n * return (\n * <button onClick={handleDelete} disabled={deleteAccount.isPending}>\n * {deleteAccount.isPending ? 'Deleting...' : 'Delete Account'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useDeleteAccount(\n options?: Omit<\n UseMutationOptions<void, Error, DeleteAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, accountId }: DeleteAccountParams) => {\n await api.delete(`/users/${userId}/accounts/${accountId}`);\n // DELETE returns 204 No Content - no response body to validate\n },\n onSuccess: (_, { userId, accountId }) => {\n // Invalidate account list to refetch without deleted account\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n\n // Remove specific account from cache\n queryClient.removeQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for archiving an account (soft delete)\n * Legacy API: PUT /users/{userId}/accounts/{id}/archive\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { AccountSchema, Account } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { api } from '../client';\n\nexport interface ArchiveAccountParams {\n userId: string;\n accountId: number;\n}\n\n/**\n * Archive an account (soft delete)\n * Changes account state to 'archived' instead of permanently deleting\n * Invalidates related queries on success\n *\n * @param options - TanStack Mutation options\n * @returns Mutation result\n *\n * @example\n * ```tsx\n * function AccountArchiveButton({ accountId }: { accountId: number }) {\n * const archiveAccount = useArchiveAccount();\n *\n * const handleArchive = () => {\n * archiveAccount.mutate({\n * userId: 'user123',\n * accountId\n * }, {\n * onSuccess: (archivedAccount) => {\n * toast.success(`${archivedAccount.name} archived`);\n * },\n * onError: (error) => {\n * toast.error(`Failed to archive: ${error.message}`);\n * }\n * });\n * };\n *\n * return (\n * <button onClick={handleArchive} disabled={archiveAccount.isPending}>\n * {archiveAccount.isPending ? 'Archiving...' : 'Archive Account'}\n * </button>\n * );\n * }\n * ```\n */\nexport function useArchiveAccount(\n options?: Omit<\n UseMutationOptions<Account, Error, ArchiveAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, accountId }: ArchiveAccountParams) => {\n const response = await api.put(\n `/users/${userId}/accounts/${accountId}/archive`\n );\n\n // Validate response - returns updated account with state='archived'\n return AccountSchema.parse(response.data);\n },\n onSuccess: (_, { userId, accountId }) => {\n // Invalidate account list to refetch with updated states\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n\n // Invalidate specific account detail\n queryClient.invalidateQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for creating a manual net worth account\n * Legacy API: POST /users/{userId}/networth/accounts\n */\n\nimport {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NetWorthAccountCreateSchema,\n NetWorthAssetSchema,\n NetWorthDebtSchema,\n type NetWorthAccountCreate,\n type NetWorthAsset,\n type NetWorthDebt,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { accountKeys } from '../keys';\n\n/**\n * Parameters for useCreateNetWorthAccount mutation\n */\nexport interface CreateNetWorthAccountParams {\n userId: string;\n data: NetWorthAccountCreate;\n}\n\n/**\n * Mutation hook for creating a manual net worth account\n *\n * Creates a manual asset or debt account for net worth tracking.\n * Returns either an asset or debt object depending on account_type.\n *\n * @example\n * ```tsx\n * const createAccount = useCreateNetWorthAccount();\n *\n * // Create asset\n * createAccount.mutate({\n * userId: 'user123',\n * data: {\n * networth_account: {\n * account_type: 'asset',\n * balance: '250000.00',\n * name: 'My House'\n * }\n * }\n * });\n *\n * // Create debt\n * createAccount.mutate({\n * userId: 'user123',\n * data: {\n * networth_account: {\n * account_type: 'debt',\n * balance: '15000.00',\n * name: 'Car Loan'\n * }\n * }\n * });\n * ```\n */\nexport function useCreateNetWorthAccount(\n options?: Omit<\n UseMutationOptions<NetWorthAsset | NetWorthDebt, Error, CreateNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNetWorthAccountParams) => {\n // Validate account data\n const validated = NetWorthAccountCreateSchema.parse(data);\n\n // POST to create new net worth account\n const response = await api.post(\n `/users/${userId}/networth/accounts`,\n validated\n );\n\n // Validate response based on account type\n const accountType = validated.networth_account.account_type;\n if (accountType === 'asset') {\n return NetWorthAssetSchema.parse(response.data);\n } else {\n return NetWorthDebtSchema.parse(response.data);\n }\n },\n onSuccess: (_, { userId }) => {\n // Invalidate net worth summary to refetch with new account\n queryClient.invalidateQueries({\n queryKey: accountKeys.networthSummary(userId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for updating a manual net worth account\n * Legacy API: PUT /users/{userId}/networth/accounts/{id}\n */\n\nimport {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n NetWorthAccountUpdateSchema,\n NetWorthAssetSchema,\n NetWorthDebtSchema,\n type NetWorthAccountUpdate,\n type NetWorthAsset,\n type NetWorthDebt,\n} from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { accountKeys } from '../keys';\n\n/**\n * Parameters for useUpdateNetWorthAccount mutation\n */\nexport interface UpdateNetWorthAccountParams {\n userId: string;\n accountId: number;\n data: NetWorthAccountUpdate;\n}\n\n/**\n * Mutation hook for updating a manual net worth account\n *\n * Updates name, balance, or account type for a manual net worth account.\n * All fields are optional - only provided fields will be updated.\n *\n * @example\n * ```tsx\n * const updateAccount = useUpdateNetWorthAccount();\n *\n * // Update only balance\n * updateAccount.mutate({\n * userId: 'user123',\n * accountId: 5,\n * data: {\n * networth_account: {\n * balance: '260000.00'\n * }\n * }\n * });\n *\n * // Update name and type\n * updateAccount.mutate({\n * userId: 'user123',\n * accountId: 5,\n * data: {\n * networth_account: {\n * name: 'Updated House Name',\n * account_type: 'debt'\n * }\n * }\n * });\n * ```\n */\nexport function useUpdateNetWorthAccount(\n options?: Omit<\n UseMutationOptions<NetWorthAsset | NetWorthDebt, Error, UpdateNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, accountId, data }: UpdateNetWorthAccountParams) => {\n // Validate update data\n const validated = NetWorthAccountUpdateSchema.parse(data);\n\n // PUT to update net worth account\n const response = await api.put(\n `/users/${userId}/networth/accounts/${accountId}`,\n validated\n );\n\n // Validate response - could be asset or debt\n // Try asset first, fall back to debt\n try {\n return NetWorthAssetSchema.parse(response.data);\n } catch {\n return NetWorthDebtSchema.parse(response.data);\n }\n },\n onSuccess: (_, { userId }) => {\n // Invalidate net worth summary to refetch with updated account\n queryClient.invalidateQueries({\n queryKey: accountKeys.networthSummary(userId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for deleting a manual net worth account\n * Legacy API: DELETE /users/{userId}/networth/accounts/{id}\n */\n\nimport {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport { NetWorthAccountDeleteSchema } from '@pfm-platform/shared';\nimport { api } from '../client';\nimport { accountKeys } from '../keys';\n\n/**\n * Parameters for useDeleteNetWorthAccount mutation\n */\nexport interface DeleteNetWorthAccountParams {\n userId: string;\n accountId: number;\n}\n\n/**\n * Mutation hook for deleting a manual net worth account\n *\n * Permanently deletes a manual asset or debt account from net worth tracking.\n * This operation cannot be undone.\n *\n * @example\n * ```tsx\n * const deleteAccount = useDeleteNetWorthAccount();\n *\n * deleteAccount.mutate({\n * userId: 'user123',\n * accountId: 5\n * }, {\n * onSuccess: () => {\n * console.log('Net worth account deleted successfully');\n * }\n * });\n * ```\n */\nexport function useDeleteNetWorthAccount(\n options?: Omit<\n UseMutationOptions<void, Error, DeleteNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, accountId }: DeleteNetWorthAccountParams) => {\n // Validate account ID\n NetWorthAccountDeleteSchema.parse({ id: accountId });\n\n // DELETE net worth account\n await api.delete(`/users/${userId}/networth/accounts/${accountId}`);\n },\n onSuccess: (_, { userId }) => {\n // Invalidate net worth summary to refetch without deleted account\n queryClient.invalidateQueries({\n queryKey: accountKeys.networthSummary(userId),\n });\n },\n ...options,\n });\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/keys.ts","../src/queries/useAccounts.ts","../src/queries/useAccount.ts","../src/queries/useNetWorth.ts","../src/mutations/useCreateAccount.ts","../src/mutations/useUpdateAccount.ts","../src/mutations/useDeleteAccount.ts","../src/mutations/useArchiveAccount.ts","../src/mutations/useCreateNetWorthAccount.ts","../src/mutations/useUpdateNetWorthAccount.ts","../src/mutations/useDeleteNetWorthAccount.ts"],"names":["useQuery","AccountSchema","useQueryClient","useMutation"],"mappings":";;;;;;AAUO,IAAM,WAAA,GAAc;AAAA,EACzB,GAAA,EAAK,CAAC,UAAU,CAAA;AAAA,EAEhB,OAAO,MAAM,CAAC,GAAG,WAAA,CAAY,KAAK,MAAM,CAAA;AAAA,EAExC,IAAA,EAAM,CAAC,MAAA,KAAmB,CAAC,GAAG,WAAA,CAAY,KAAA,IAAS,MAAM,CAAA;AAAA,EAEzD,SAAS,MAAM,CAAC,GAAG,WAAA,CAAY,KAAK,QAAQ,CAAA;AAAA,EAE5C,MAAA,EAAQ,CAAC,MAAA,EAAgB,SAAA,KACvB,CAAC,GAAG,WAAA,CAAY,OAAA,EAAQ,EAAG,MAAA,EAAQ,SAAS,CAAA;AAAA,EAE9C,cAAc,MAAM,CAAC,GAAG,WAAA,CAAY,KAAK,cAAc,CAAA;AAAA,EAEvD,WAAA,EAAa,CAAC,MAAA,KACZ,CAAC,GAAG,WAAA,CAAY,YAAA,IAAgB,MAAM;AAC1C;;;ACIO,SAAS,WAAA,CACd,QACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAO,GAAI,MAAA;AAEnB,EAAA,OAAO,QAAA,CAAS;AAAA,IACd,QAAA,EAAU,WAAA,CAAY,IAAA,CAAK,MAAM,CAAA;AAAA,IACjC,SAAS,YAAmC;AAC1C,MAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAM,GAAI,MAAM,SAC3B,IAAA,CAAK,UAAU,CAAA,CACf,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,WAAW,MAAM,CAAA,CACpB,MAAM,MAAM,CAAA;AAEf,MAAA,IAAI,OAAO,MAAM,KAAA;AAEjB,MAAA,OAAO,EAAE,QAAA,EAAU,sBAAA,CAAuB,KAAA,CAAM,IAAI,CAAA,EAAE;AAAA,IACxD,CAAA;AAAA,IACA,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;AC5BO,SAAS,UAAA,CACd,QACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,MAAA,EAAQ,SAAA,EAAU,GAAI,MAAA;AAE9B,EAAA,OAAOA,QAAAA,CAAS;AAAA,IACd,QAAA,EAAU,WAAA,CAAY,MAAA,CAAO,MAAA,EAAQ,SAAS,CAAA;AAAA,IAC9C,SAAS,YAAY;AACnB,MAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,QAAA,CAC3B,IAAA,CAAK,UAAU,CAAA,CACf,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,MAAM,SAAS,CAAA,CAClB,GAAG,SAAA,EAAW,MAAM,EACpB,MAAA,EAAO;AAEV,MAAA,IAAI,OAAO,MAAM,KAAA;AAEjB,MAAA,OAAO,aAAA,CAAc,MAAM,IAAI,CAAA;AAAA,IACjC,CAAA;AAAA,IACA,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;ACCO,SAAS,WAAA,CACd,QACA,OAAA,EACA;AACA,EAAA,MAAM,EAAE,QAAO,GAAI,MAAA;AAEnB,EAAA,OAAOA,QAAAA,CAAS;AAAA,IACd,UAAU,CAAC,GAAG,WAAA,CAAY,GAAA,EAAK,YAAY,MAAM,CAAA;AAAA,IACjD,SAAS,YAA0C;AAEjD,MAAA,MAAM,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,aAAA,KAAkB,MAAM,QAAA,CACpD,IAAA,CAAK,mBAAmB,EACxB,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,WAAW,MAAM,CAAA;AAEvB,MAAA,IAAI,eAAe,MAAM,aAAA;AAGzB,MAAA,MAAM,EAAE,IAAA,EAAM,SAAA,EAAW,KAAA,EAAO,cAAA,EAAe,GAAI,MAAM,QAAA,CACtD,IAAA,CAAK,kBAAkB,CAAA,CACvB,MAAA,CAAO,GAAG,CAAA,CACV,EAAA,CAAG,SAAA,EAAW,MAAM,CAAA,CACpB,KAAA,CAAM,MAAA,EAAQ,EAAE,SAAA,EAAW,IAAA,EAAM,CAAA,CACjC,KAAA,CAAM,OAAA,EAAS,EAAE,SAAA,EAAW,MAAM,CAAA;AAErC,MAAA,IAAI,gBAAgB,MAAM,cAAA;AAE1B,MAAA,MAAM,MAAA,GAAA,CAAU,QAAA,IAAY,EAAC,EAC1B,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,KAAiB,OAAO,CAAA,CACxC,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACX,IAAI,CAAA,CAAE,EAAA;AAAA,QACN,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,OAAA,EAAS,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA;AAAA,QACzB,cAAc,CAAA,CAAE,YAAA;AAAA,QAChB,6BAA6B,CAAA,CAAE;AAAA,OACjC,CAAE,CAAA;AAEJ,MAAA,MAAM,KAAA,GAAA,CAAS,QAAA,IAAY,EAAC,EACzB,MAAA,CAAO,CAAC,CAAA,KAAM,CAAA,CAAE,YAAA,KAAiB,MAAM,CAAA,CACvC,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QACX,IAAI,CAAA,CAAE,EAAA;AAAA,QACN,MAAM,CAAA,CAAE,IAAA;AAAA,QACR,OAAA,EAAS,MAAA,CAAO,CAAA,CAAE,OAAO,CAAA;AAAA,QACzB,cAAc,CAAA,CAAE,YAAA;AAAA,QAChB,6BAA6B,CAAA,CAAE;AAAA,OACjC,CAAE,CAAA;AAEJ,MAAA,MAAM,WAAA,GAAc,MAAA,CAAO,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,UAAA,CAAW,CAAA,CAAE,OAAO,CAAA,EAAG,CAAC,CAAA;AAC5E,MAAA,MAAM,UAAA,GAAa,KAAA,CAAM,MAAA,CAAO,CAAC,GAAA,EAAK,CAAA,KAAM,GAAA,GAAM,UAAA,CAAW,CAAA,CAAE,OAAO,CAAA,EAAG,CAAC,CAAA;AAE1E,MAAA,MAAM,qBAA6C,SAAA,IAAa,EAAC,EAAG,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,QAC9E,KAAA,EAAO,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA;AAAA,QACrB,WAAA,EAAa,MAAA,CAAO,CAAA,CAAE,WAAW,CAAA;AAAA,QACjC,UAAA,EAAY,MAAA,CAAO,CAAA,CAAE,UAAU,CAAA;AAAA,QAC/B,OAAO,MAAA,CAAO,CAAA,CAAE,KAAK,CAAA,CAAE,QAAA,CAAS,GAAG,GAAG,CAAA;AAAA,QACtC,IAAA,EAAM,MAAA,CAAO,CAAA,CAAE,IAAI,CAAA;AAAA,QACnB,gBAAA,EAAkB,MAAA,CAAO,CAAA,CAAE,gBAAgB;AAAA,OAC7C,CAAE,CAAA;AAEF,MAAA,OAAO;AAAA,QACL,IAAA,EAAM;AAAA,UACJ,SAAA,EAAW,MAAA,CAAO,WAAA,GAAc,UAAU,CAAA;AAAA,UAC1C,gBAAA,EAAkB,GAAA;AAAA;AAAA,UAClB,YAAA,EAAc,OAAO,WAAW,CAAA;AAAA,UAChC,WAAA,EAAa,OAAO,UAAU;AAAA,SAChC;AAAA,QACA,MAAA;AAAA,QACA,KAAA;AAAA,QACA,kBAAA,EAAoB;AAAA,OACtB;AAAA,IACF,CAAA;AAAA,IACA,SAAA,EAAW,MAAO,EAAA,GAAK,CAAA;AAAA,IACvB,GAAG;AAAA,GACJ,CAAA;AACH;AC7FO,SAAS,iBACd,OAAA,EACA;AACA,EAAA,MAAM,cAAc,cAAA,EAAe;AACnC,EAAA,MAAM,EAAE,IAAA,EAAK,GAAI,UAAA,EAAW;AAE5B,EAAA,OAAO,WAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,IAAA,EAAK,KAA2B;AACnD,MAAA,MAAM,MAAA,GACJ,IAAA,KAAS,OAAA,GACL,wBAAA,GACA,uBAAA;AAEN,MAAA,MAAM,SAAA,GAAY,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAEnC,MAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,KAAU,MAAM,QAAA,CACpC,IAAA,CAAK,UAAU,EACf,MAAA,CAAO,SAAS,CAAA,CAChB,MAAA,GACA,MAAA,EAAO;AAEV,MAAA,IAAI,OAAO,MAAM,KAAA;AAEjB,MAAA,OAAOC,aAAAA,CAAc,MAAM,OAAO,CAAA;AAAA,IACpC,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,UAAA,EAAY,SAAA,EAAW,gBAAgB,OAAA,KAAY;AAC7D,MAAA,WAAA,CAAY,YAAA;AAAA,QACV,WAAA,CAAY,IAAA,CAAK,SAAA,CAAU,MAAM,CAAA;AAAA,QACjC,CAAC,OAAA,KAAsC;AACrC,UAAA,IAAI,CAAC,OAAA,EAAS,OAAO,EAAE,QAAA,EAAU,CAAC,UAAU,CAAA,EAAE;AAC9C,UAAA,OAAO,EAAE,QAAA,EAAU,CAAC,GAAG,OAAA,CAAQ,QAAA,EAAU,UAAU,CAAA,EAAE;AAAA,QACvD;AAAA,OACF;AAEA,MAAA,OAAA,EAAS,SAAA,GAAY,UAAA,EAAY,SAAA,EAAW,cAAA,EAAgB,OAAO,CAAA;AAAA,IACrE,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;ACvCO,SAAS,iBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcC,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,MAAK,KAA2B;AAC9D,MAAA,MAAM,SAAA,GAAY,mBAAA,CAAoB,KAAA,CAAM,IAAI,CAAA;AAEhD,MAAA,MAAM,EAAE,IAAA,EAAM,OAAA,EAAS,OAAM,GAAI,MAAM,SACpC,IAAA,CAAK,UAAU,EACf,MAAA,CAAO,SAAS,EAChB,EAAA,CAAG,IAAA,EAAM,SAAS,CAAA,CAClB,MAAA,GACA,MAAA,EAAO;AAEV,MAAA,IAAI,OAAO,MAAM,KAAA;AAEjB,MAAA,OAAOF,aAAAA,CAAc,MAAM,OAAO,CAAA;AAAA,IACpC,CAAA;AAAA,IACA,WAAW,CAAC,CAAA,EAAG,EAAE,MAAA,EAAQ,WAAU,KAAM;AACvC,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,WAAA,CAAY,IAAA,CAAK,MAAM;AAAA,OAClC,CAAA;AACD,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,WAAA,CAAY,MAAA,CAAO,MAAA,EAAQ,SAAS;AAAA,OAC/C,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;ACxCO,SAAS,iBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcC,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,SAAA,EAAU,KAA2B;AACxD,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,QAAA,CACrB,IAAA,CAAK,UAAU,CAAA,CACf,MAAA,EAAO,CACP,EAAA,CAAG,IAAA,EAAM,SAAS,CAAA;AAErB,MAAA,IAAI,OAAO,MAAM,KAAA;AAAA,IACnB,CAAA;AAAA,IACA,WAAW,CAAC,CAAA,EAAG,EAAE,MAAA,EAAQ,WAAU,KAAM;AACvC,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,WAAA,CAAY,IAAA,CAAK,MAAM;AAAA,OAClC,CAAA;AACD,MAAA,WAAA,CAAY,aAAA,CAAc;AAAA,QACxB,QAAA,EAAU,WAAA,CAAY,MAAA,CAAO,MAAA,EAAQ,SAAS;AAAA,OAC/C,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AC1BO,SAAS,kBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcD,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,SAAA,EAAU,KAA4B;AACzD,MAAA,MAAM,EAAE,MAAM,KAAA,EAAM,GAAI,MAAM,QAAA,CAC3B,IAAA,CAAK,UAAU,CAAA,CACf,MAAA,CAAO,EAAE,SAAA,EAAW,KAAA,EAAO,CAAA,CAC3B,EAAA,CAAG,MAAM,SAAS,CAAA,CAClB,MAAA,EAAO,CACP,MAAA,EAAO;AAEV,MAAA,IAAI,OAAO,MAAM,KAAA;AAEjB,MAAA,OAAOF,aAAAA,CAAc,MAAM,IAAI,CAAA;AAAA,IACjC,CAAA;AAAA,IACA,WAAW,CAAC,CAAA,EAAG,EAAE,MAAA,EAAQ,WAAU,KAAM;AACvC,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,WAAA,CAAY,IAAA,CAAK,MAAM;AAAA,OAClC,CAAA;AACD,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,QAAA,EAAU,WAAA,CAAY,MAAA,CAAO,MAAA,EAAQ,SAAS;AAAA,OAC/C,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AC1BO,SAAS,yBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcC,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,MAAA,EAAQ,MAAK,KAAmC;AACnE,MAAA,MAAM,EAAE,OAAM,GAAI,MAAM,SAAS,IAAA,CAAK,mBAAmB,EAAE,MAAA,CAAO;AAAA,QAChE,OAAA,EAAS,MAAA;AAAA,QACT,IAAA,EAAM,KAAK,gBAAA,CAAiB,IAAA;AAAA,QAC5B,OAAA,EAAS,UAAA,CAAW,IAAA,CAAK,gBAAA,CAAiB,OAAO,CAAA;AAAA,QACjD,YAAA,EAAc,KAAK,gBAAA,CAAiB,YAAA;AAAA,QACpC,2BAAA,EAA6B;AAAA,OAC9B,CAAA;AAED,MAAA,IAAI,OAAO,MAAM,KAAA;AAAA,IACnB,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,UAAU,CAAC,GAAG,WAAA,CAAY,GAAA,EAAK,YAAY,MAAM;AAAA,OAClD,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;AC1BO,SAAS,yBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcD,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,SAAA,EAAW,MAAK,KAAmC;AACtE,MAAA,MAAM,EAAE,OAAM,GAAI,MAAM,SACrB,IAAA,CAAK,mBAAmB,EACxB,MAAA,CAAO;AAAA,QACN,IAAA,EAAM,KAAK,gBAAA,CAAiB,IAAA;AAAA,QAC5B,OAAA,EAAS,UAAA,CAAW,IAAA,CAAK,gBAAA,CAAiB,OAAO,CAAA;AAAA,QACjD,YAAA,EAAc,KAAK,gBAAA,CAAiB;AAAA,OACrC,CAAA,CACA,EAAA,CAAG,IAAA,EAAM,MAAA,CAAO,SAAS,CAAC,CAAA;AAE7B,MAAA,IAAI,OAAO,MAAM,KAAA;AAAA,IACnB,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,UAAU,CAAC,GAAG,WAAA,CAAY,GAAA,EAAK,YAAY,MAAM;AAAA,OAClD,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH;ACnCO,SAAS,yBACd,OAAA,EAIA;AACA,EAAA,MAAM,cAAcD,cAAAA,EAAe;AAEnC,EAAA,OAAOC,WAAAA,CAAY;AAAA,IACjB,UAAA,EAAY,OAAO,EAAE,SAAA,EAAU,KAAmC;AAChE,MAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,SACrB,IAAA,CAAK,mBAAmB,CAAA,CACxB,MAAA,EAAO,CACP,EAAA,CAAG,IAAA,EAAM,MAAA,CAAO,SAAS,CAAC,CAAA;AAE7B,MAAA,IAAI,OAAO,MAAM,KAAA;AAAA,IACnB,CAAA;AAAA,IACA,SAAA,EAAW,CAAC,CAAA,EAAG,EAAE,QAAO,KAAM;AAC5B,MAAA,WAAA,CAAY,iBAAA,CAAkB;AAAA,QAC5B,UAAU,CAAC,GAAG,WAAA,CAAY,GAAA,EAAK,YAAY,MAAM;AAAA,OAClD,CAAA;AAAA,IACH,CAAA;AAAA,IACA,GAAG;AAAA,GACJ,CAAA;AACH","file":"index.js","sourcesContent":["/**\n * Query key factory for Accounts domain\n * Following TanStack Query best practices for hierarchical cache keys\n *\n * Key structure:\n * - ['accounts'] - Root key for all account queries\n * - ['accounts', 'list', userId] - List of accounts for a user\n * - ['accounts', 'detail', userId, accountId] - Single account detail\n */\n\nexport const accountKeys = {\n all: ['accounts'] as const,\n\n lists: () => [...accountKeys.all, 'list'] as const,\n\n list: (userId: string) => [...accountKeys.lists(), userId] as const,\n\n details: () => [...accountKeys.all, 'detail'] as const,\n\n detail: (userId: string, accountId: string) =>\n [...accountKeys.details(), userId, accountId] as const,\n\n institutions: () => [...accountKeys.all, 'institutions'] as const,\n\n institution: (userId: string) =>\n [...accountKeys.institutions(), userId] as const,\n};\n","/**\n * Query hook for fetching all accounts for a user\n * Supabase: accounts table filtered by user_id\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { AccountsResponseSchema, type Account } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface UseAccountsParams {\n userId: string;\n}\n\nexport interface AccountsData {\n accounts: Account[];\n}\n\n/**\n * Fetch all accounts for a user from Supabase\n *\n * Returns `{ accounts: Account[] }` to match the shape expected by\n * feature hooks (useAccountFilters, useAccountTypes, useAccountSummary).\n *\n * @example\n * ```tsx\n * const { data } = useAccounts({ userId });\n * // data.accounts is Account[]\n * ```\n */\nexport function useAccounts(\n params: UseAccountsParams,\n options?: Omit<UseQueryOptions<AccountsData>, 'queryKey' | 'queryFn'>\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: accountKeys.list(userId),\n queryFn: async (): Promise<AccountsData> => {\n const { data, error } = await supabase\n .from('accounts')\n .select('*')\n .eq('user_id', userId)\n .order('name');\n\n if (error) throw error;\n\n return { accounts: AccountsResponseSchema.parse(data) };\n },\n staleTime: 1000 * 60 * 5,\n ...options,\n });\n}\n","/**\n * Query hook for fetching a single account by ID\n * Supabase: accounts table filtered by id\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { AccountSchema, type Account } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface UseAccountParams {\n userId: string;\n accountId: string;\n}\n\n/**\n * Fetch a single account by ID from Supabase\n *\n * @example\n * ```tsx\n * const { data } = useAccount({ userId, accountId });\n * // data is Account\n * ```\n */\nexport function useAccount(\n params: UseAccountParams,\n options?: Omit<UseQueryOptions<Account>, 'queryKey' | 'queryFn'>\n) {\n const { userId, accountId } = params;\n\n return useQuery({\n queryKey: accountKeys.detail(userId, accountId),\n queryFn: async () => {\n const { data, error } = await supabase\n .from('accounts')\n .select('*')\n .eq('id', accountId)\n .eq('user_id', userId)\n .single();\n\n if (error) throw error;\n\n return AccountSchema.parse(data);\n },\n staleTime: 1000 * 60 * 5,\n ...options,\n });\n}\n","/**\n * Query hook for fetching net worth data\n * TODO: Wire to Supabase networth_summary view + networth_accounts table\n */\n\nimport { useQuery, UseQueryOptions } from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface NetWorthAccount {\n id: string;\n name: string;\n balance: string;\n account_type: 'asset' | 'debt';\n additional_networth_account: boolean;\n}\n\nexport interface NetWorthMeta {\n net_worth: string;\n net_worth_change: string;\n total_assets: string;\n total_debts: string;\n}\n\nexport interface NetWorthHistoryEntry {\n total: string;\n total_asset: string;\n total_debt: string;\n month: string;\n year: string;\n since_last_month: string;\n}\n\nexport interface NetWorthData {\n meta: NetWorthMeta;\n assets: NetWorthAccount[];\n debts: NetWorthAccount[];\n networth_histories: NetWorthHistoryEntry[];\n}\n\nexport interface UseNetWorthParams {\n userId: string;\n}\n\n/**\n * Fetch net worth summary with manual accounts\n * Combines networth_summary view + networth_accounts table\n */\nexport function useNetWorth(\n params: UseNetWorthParams,\n options?: Omit<UseQueryOptions<NetWorthData | null>, 'queryKey' | 'queryFn'>\n) {\n const { userId } = params;\n\n return useQuery({\n queryKey: [...accountKeys.all, 'networth', userId],\n queryFn: async (): Promise<NetWorthData | null> => {\n // Fetch manual networth accounts\n const { data: accounts, error: accountsError } = await supabase\n .from('networth_accounts')\n .select('*')\n .eq('user_id', userId);\n\n if (accountsError) throw accountsError;\n\n // Fetch networth history\n const { data: histories, error: historiesError } = await supabase\n .from('networth_history')\n .select('*')\n .eq('user_id', userId)\n .order('year', { ascending: true })\n .order('month', { ascending: true });\n\n if (historiesError) throw historiesError;\n\n const assets = (accounts || [])\n .filter((a) => a.account_type === 'asset')\n .map((a) => ({\n id: a.id,\n name: a.name,\n balance: String(a.balance),\n account_type: a.account_type as 'asset' | 'debt',\n additional_networth_account: a.additional_networth_account,\n }));\n\n const debts = (accounts || [])\n .filter((a) => a.account_type === 'debt')\n .map((a) => ({\n id: a.id,\n name: a.name,\n balance: String(a.balance),\n account_type: a.account_type as 'asset' | 'debt',\n additional_networth_account: a.additional_networth_account,\n }));\n\n const totalAssets = assets.reduce((sum, a) => sum + parseFloat(a.balance), 0);\n const totalDebts = debts.reduce((sum, d) => sum + parseFloat(d.balance), 0);\n\n const networthHistories: NetWorthHistoryEntry[] = (histories || []).map((h) => ({\n total: String(h.total),\n total_asset: String(h.total_asset),\n total_debt: String(h.total_debt),\n month: String(h.month).padStart(2, '0'),\n year: String(h.year),\n since_last_month: String(h.since_last_month),\n }));\n\n return {\n meta: {\n net_worth: String(totalAssets - totalDebts),\n net_worth_change: '0', // TODO: compute from networth_history\n total_assets: String(totalAssets),\n total_debts: String(totalDebts),\n },\n assets,\n debts,\n networth_histories: networthHistories,\n };\n },\n staleTime: 1000 * 60 * 5,\n ...options,\n });\n}\n","import {\n useMutation,\n useQueryClient,\n type UseMutationOptions,\n} from '@tanstack/react-query';\nimport {\n AccountCreateSchemaAdmin,\n AccountCreateSchemaUser,\n AccountSchema,\n useAppMode,\n type AccountCreate,\n type Account,\n} from '@pfm-platform/shared';\nimport { supabase } from '../client';\nimport { accountKeys } from '../keys';\nimport type { AccountsData } from '../queries/useAccounts';\n\nexport interface CreateAccountParams {\n userId: string;\n data: AccountCreate;\n}\n\n/**\n * Mutation hook for creating a new account in Supabase\n *\n * Uses mode switching for validation:\n * - Admin mode: Minimal validation for test data creation\n * - User mode: Full validation with business rules\n */\nexport function useCreateAccount(\n options?: Omit<UseMutationOptions<Account, Error, CreateAccountParams>, 'mutationFn'>\n) {\n const queryClient = useQueryClient();\n const { mode } = useAppMode();\n\n return useMutation({\n mutationFn: async ({ data }: CreateAccountParams) => {\n const schema =\n mode === 'admin'\n ? AccountCreateSchemaAdmin\n : AccountCreateSchemaUser;\n\n const validated = schema.parse(data);\n\n const { data: created, error } = await supabase\n .from('accounts')\n .insert(validated)\n .select()\n .single();\n\n if (error) throw error;\n\n return AccountSchema.parse(created);\n },\n onSuccess: (newAccount, variables, onMutateResult, context) => {\n queryClient.setQueryData(\n accountKeys.list(variables.userId),\n (oldData: AccountsData | undefined) => {\n if (!oldData) return { accounts: [newAccount] };\n return { accounts: [...oldData.accounts, newAccount] };\n }\n );\n\n options?.onSuccess?.(newAccount, variables, onMutateResult, context);\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for updating an account\n * Supabase: UPDATE accounts SET ... WHERE id = ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport {\n AccountUpdateSchema,\n AccountSchema,\n Account,\n AccountUpdate,\n} from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface UpdateAccountParams {\n userId: string;\n accountId: string;\n data: AccountUpdate;\n}\n\n/**\n * Update an existing account in Supabase\n */\nexport function useUpdateAccount(\n options?: Omit<\n UseMutationOptions<Account, Error, UpdateAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ accountId, data }: UpdateAccountParams) => {\n const validated = AccountUpdateSchema.parse(data);\n\n const { data: updated, error } = await supabase\n .from('accounts')\n .update(validated)\n .eq('id', accountId)\n .select()\n .single();\n\n if (error) throw error;\n\n return AccountSchema.parse(updated);\n },\n onSuccess: (_, { userId, accountId }) => {\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n queryClient.invalidateQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for deleting an account\n * Supabase: DELETE FROM accounts WHERE id = ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface DeleteAccountParams {\n userId: string;\n accountId: string;\n}\n\n/**\n * Delete an account from Supabase (hard delete)\n */\nexport function useDeleteAccount(\n options?: Omit<\n UseMutationOptions<void, Error, DeleteAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ accountId }: DeleteAccountParams) => {\n const { error } = await supabase\n .from('accounts')\n .delete()\n .eq('id', accountId);\n\n if (error) throw error;\n },\n onSuccess: (_, { userId, accountId }) => {\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n queryClient.removeQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for archiving an account (soft delete)\n * Supabase: UPDATE accounts SET is_active = false WHERE id = ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { AccountSchema, Account } from '@pfm-platform/shared';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface ArchiveAccountParams {\n userId: string;\n accountId: string;\n}\n\n/**\n * Archive an account (soft delete via is_active = false)\n */\nexport function useArchiveAccount(\n options?: Omit<\n UseMutationOptions<Account, Error, ArchiveAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ accountId }: ArchiveAccountParams) => {\n const { data, error } = await supabase\n .from('accounts')\n .update({ is_active: false })\n .eq('id', accountId)\n .select()\n .single();\n\n if (error) throw error;\n\n return AccountSchema.parse(data);\n },\n onSuccess: (_, { userId, accountId }) => {\n queryClient.invalidateQueries({\n queryKey: accountKeys.list(userId),\n });\n queryClient.invalidateQueries({\n queryKey: accountKeys.detail(userId, accountId),\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for creating a net worth account\n * Supabase: INSERT INTO networth_accounts ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface CreateNetWorthAccountParams {\n userId: string;\n data: {\n networth_account: {\n name: string;\n balance: string;\n account_type: string;\n };\n };\n}\n\n/**\n * Create a net worth account in Supabase\n */\nexport function useCreateNetWorthAccount(\n options?: Omit<\n UseMutationOptions<void, Error, CreateNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ userId, data }: CreateNetWorthAccountParams) => {\n const { error } = await supabase.from('networth_accounts').insert({\n user_id: userId,\n name: data.networth_account.name,\n balance: parseFloat(data.networth_account.balance),\n account_type: data.networth_account.account_type,\n additional_networth_account: true,\n });\n\n if (error) throw error;\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: [...accountKeys.all, 'networth', userId],\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for updating a net worth account\n * Supabase: UPDATE networth_accounts SET ... WHERE id = ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface UpdateNetWorthAccountParams {\n userId: string;\n accountId: number | string;\n data: {\n networth_account: {\n name: string;\n balance: string;\n account_type: string;\n };\n };\n}\n\n/**\n * Update a net worth account in Supabase\n */\nexport function useUpdateNetWorthAccount(\n options?: Omit<\n UseMutationOptions<void, Error, UpdateNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ accountId, data }: UpdateNetWorthAccountParams) => {\n const { error } = await supabase\n .from('networth_accounts')\n .update({\n name: data.networth_account.name,\n balance: parseFloat(data.networth_account.balance),\n account_type: data.networth_account.account_type,\n })\n .eq('id', String(accountId));\n\n if (error) throw error;\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: [...accountKeys.all, 'networth', userId],\n });\n },\n ...options,\n });\n}\n","/**\n * Mutation hook for deleting a net worth account\n * Supabase: DELETE FROM networth_accounts WHERE id = ...\n */\n\nimport {\n useMutation,\n UseMutationOptions,\n useQueryClient,\n} from '@tanstack/react-query';\nimport { accountKeys } from '../keys';\nimport { supabase } from '../client';\n\nexport interface DeleteNetWorthAccountParams {\n userId: string;\n accountId: number | string;\n}\n\n/**\n * Delete a net worth account from Supabase\n */\nexport function useDeleteNetWorthAccount(\n options?: Omit<\n UseMutationOptions<void, Error, DeleteNetWorthAccountParams>,\n 'mutationFn'\n >\n) {\n const queryClient = useQueryClient();\n\n return useMutation({\n mutationFn: async ({ accountId }: DeleteNetWorthAccountParams) => {\n const { error } = await supabase\n .from('networth_accounts')\n .delete()\n .eq('id', String(accountId));\n\n if (error) throw error;\n },\n onSuccess: (_, { userId }) => {\n queryClient.invalidateQueries({\n queryKey: [...accountKeys.all, 'networth', userId],\n });\n },\n ...options,\n });\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pfm-platform/accounts-data-access",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -10,19 +10,17 @@
|
|
|
10
10
|
}
|
|
11
11
|
},
|
|
12
12
|
"dependencies": {
|
|
13
|
-
"axios": "^1.13.2",
|
|
14
13
|
"zod": "4.1.12",
|
|
15
|
-
"@pfm-platform/shared": "0.1
|
|
14
|
+
"@pfm-platform/shared": "0.2.1"
|
|
16
15
|
},
|
|
17
16
|
"devDependencies": {
|
|
18
|
-
"@testing-library/react": "^16.3.
|
|
19
|
-
"@vitejs/plugin-react": "^5.1.
|
|
20
|
-
"@vitest/coverage-v8": "^4.0.
|
|
17
|
+
"@testing-library/react": "^16.3.2",
|
|
18
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
19
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
21
20
|
"jsdom": "^27.2.0",
|
|
22
|
-
"
|
|
23
|
-
"react-dom": "19.2.0",
|
|
21
|
+
"react-dom": "19.2.4",
|
|
24
22
|
"typescript": "5.9.3",
|
|
25
|
-
"vitest": "4.0.
|
|
23
|
+
"vitest": "4.0.18"
|
|
26
24
|
},
|
|
27
25
|
"main": "./dist/index.js",
|
|
28
26
|
"module": "./dist/index.js",
|