@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 CHANGED
@@ -2,112 +2,19 @@
2
2
 
3
3
  var reactQuery = require('@tanstack/react-query');
4
4
  var shared = require('@pfm-platform/shared');
5
- var axios = require('axios');
6
-
7
- function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
-
9
- var axios__default = /*#__PURE__*/_interopDefault(axios);
10
5
 
11
6
  // src/queries/useAccounts.ts
12
7
 
13
8
  // src/keys.ts
14
9
  var accountKeys = {
15
- /**
16
- * Root key for all account-related queries
17
- */
18
10
  all: ["accounts"],
19
- /**
20
- * Key for all account list queries
21
- */
22
11
  lists: () => [...accountKeys.all, "list"],
23
- /**
24
- * Key for a specific user's account list
25
- * @param userId - User ID
26
- */
27
12
  list: (userId) => [...accountKeys.lists(), userId],
28
- /**
29
- * Key for all account detail queries
30
- */
31
13
  details: () => [...accountKeys.all, "detail"],
32
- /**
33
- * Key for a specific account detail
34
- * @param userId - User ID
35
- * @param accountId - Account ID
36
- */
37
14
  detail: (userId, accountId) => [...accountKeys.details(), userId, accountId],
38
- /**
39
- * Key for all account investment queries
40
- */
41
- investments: () => [...accountKeys.all, "investments"],
42
- /**
43
- * Key for a specific account's investments
44
- * @param userId - User ID
45
- * @param accountId - Account ID
46
- */
47
- investment: (userId, accountId) => [...accountKeys.investments(), userId, accountId],
48
- /**
49
- * Key for all account transaction queries
50
- */
51
- transactions: () => [...accountKeys.all, "transactions"],
52
- /**
53
- * Key for a specific account's transactions
54
- * @param userId - User ID
55
- * @param accountId - Account ID
56
- * @param page - Page number for pagination
57
- */
58
- transaction: (userId, accountId, page) => [...accountKeys.transactions(), userId, accountId, page],
59
- /**
60
- * Key for all net worth queries
61
- */
62
- networth: () => [...accountKeys.all, "networth"],
63
- /**
64
- * Key for a specific user's net worth summary
65
- * @param userId - User ID
66
- */
67
- networthSummary: (userId) => [...accountKeys.networth(), userId],
68
- /**
69
- * Key for all net worth account queries
70
- */
71
- networthAccounts: () => [...accountKeys.networth(), "accounts"],
72
- /**
73
- * Key for a specific net worth account
74
- * @param userId - User ID
75
- * @param accountId - Net worth account ID
76
- */
77
- networthAccount: (userId, accountId) => [...accountKeys.networthAccounts(), userId, accountId]
15
+ institutions: () => [...accountKeys.all, "institutions"],
16
+ institution: (userId) => [...accountKeys.institutions(), userId]
78
17
  };
79
- var api = axios__default.default.create({
80
- baseURL: "/api",
81
- headers: {
82
- "Content-Type": "application/json"
83
- },
84
- timeout: 1e4
85
- // 10 second timeout
86
- });
87
- api.interceptors.request.use(
88
- (config) => {
89
- const token = localStorage.getItem("auth_token");
90
- if (token) {
91
- config.headers.Authorization = `Bearer ${token}`;
92
- }
93
- return config;
94
- },
95
- (error) => {
96
- return Promise.reject(error);
97
- }
98
- );
99
- api.interceptors.response.use(
100
- (response) => response,
101
- (error) => {
102
- if (error.response?.status === 401) {
103
- localStorage.removeItem("auth_token");
104
- if (typeof window !== "undefined") {
105
- window.location.href = "/login";
106
- }
107
- }
108
- return Promise.reject(error);
109
- }
110
- );
111
18
 
112
19
  // src/queries/useAccounts.ts
113
20
  function useAccounts(params, options) {
@@ -115,11 +22,11 @@ function useAccounts(params, options) {
115
22
  return reactQuery.useQuery({
116
23
  queryKey: accountKeys.list(userId),
117
24
  queryFn: async () => {
118
- const response = await api.get(`/users/${userId}/accounts/all`);
119
- return shared.AccountsResponseSchema.parse(response.data);
25
+ const { data, error } = await shared.supabase.from("accounts").select("*").eq("user_id", userId).order("name");
26
+ if (error) throw error;
27
+ return { accounts: shared.AccountsResponseSchema.parse(data) };
120
28
  },
121
29
  staleTime: 1e3 * 60 * 5,
122
- // 5 minutes - accounts don't change frequently
123
30
  ...options
124
31
  });
125
32
  }
@@ -128,24 +35,61 @@ function useAccount(params, options) {
128
35
  return reactQuery.useQuery({
129
36
  queryKey: accountKeys.detail(userId, accountId),
130
37
  queryFn: async () => {
131
- const response = await api.get(`/users/${userId}/accounts/${accountId}`);
132
- return shared.AccountSchema.parse(response.data);
38
+ const { data, error } = await shared.supabase.from("accounts").select("*").eq("id", accountId).eq("user_id", userId).single();
39
+ if (error) throw error;
40
+ return shared.AccountSchema.parse(data);
133
41
  },
134
42
  staleTime: 1e3 * 60 * 5,
135
- // 5 minutes
136
43
  ...options
137
44
  });
138
45
  }
139
46
  function useNetWorth(params, options) {
140
47
  const { userId } = params;
141
48
  return reactQuery.useQuery({
142
- queryKey: accountKeys.networthSummary(userId),
49
+ queryKey: [...accountKeys.all, "networth", userId],
143
50
  queryFn: async () => {
144
- const response = await api.get(`/users/${userId}/networth`);
145
- return shared.NetWorthResponseSchema.parse(response.data);
51
+ const { data: accounts, error: accountsError } = await shared.supabase.from("networth_accounts").select("*").eq("user_id", userId);
52
+ if (accountsError) throw accountsError;
53
+ const { data: histories, error: historiesError } = await shared.supabase.from("networth_history").select("*").eq("user_id", userId).order("year", { ascending: true }).order("month", { ascending: true });
54
+ if (historiesError) throw historiesError;
55
+ const assets = (accounts || []).filter((a) => a.account_type === "asset").map((a) => ({
56
+ id: a.id,
57
+ name: a.name,
58
+ balance: String(a.balance),
59
+ account_type: a.account_type,
60
+ additional_networth_account: a.additional_networth_account
61
+ }));
62
+ const debts = (accounts || []).filter((a) => a.account_type === "debt").map((a) => ({
63
+ id: a.id,
64
+ name: a.name,
65
+ balance: String(a.balance),
66
+ account_type: a.account_type,
67
+ additional_networth_account: a.additional_networth_account
68
+ }));
69
+ const totalAssets = assets.reduce((sum, a) => sum + parseFloat(a.balance), 0);
70
+ const totalDebts = debts.reduce((sum, d) => sum + parseFloat(d.balance), 0);
71
+ const networthHistories = (histories || []).map((h) => ({
72
+ total: String(h.total),
73
+ total_asset: String(h.total_asset),
74
+ total_debt: String(h.total_debt),
75
+ month: String(h.month).padStart(2, "0"),
76
+ year: String(h.year),
77
+ since_last_month: String(h.since_last_month)
78
+ }));
79
+ return {
80
+ meta: {
81
+ net_worth: String(totalAssets - totalDebts),
82
+ net_worth_change: "0",
83
+ // TODO: compute from networth_history
84
+ total_assets: String(totalAssets),
85
+ total_debts: String(totalDebts)
86
+ },
87
+ assets,
88
+ debts,
89
+ networth_histories: networthHistories
90
+ };
146
91
  },
147
92
  staleTime: 1e3 * 60 * 5,
148
- // 5 minutes - net worth doesn't change frequently
149
93
  ...options
150
94
  });
151
95
  }
@@ -153,27 +97,22 @@ function useCreateAccount(options) {
153
97
  const queryClient = reactQuery.useQueryClient();
154
98
  const { mode } = shared.useAppMode();
155
99
  return reactQuery.useMutation({
156
- mutationFn: async ({ userId, data }) => {
100
+ mutationFn: async ({ data }) => {
157
101
  const schema = mode === "admin" ? shared.AccountCreateSchemaAdmin : shared.AccountCreateSchemaUser;
158
102
  const validated = schema.parse(data);
159
- const response = await api.post(
160
- `/users/${userId}/accounts`,
161
- validated
162
- );
163
- return shared.AccountSchema.parse(response.data);
103
+ const { data: created, error } = await shared.supabase.from("accounts").insert(validated).select().single();
104
+ if (error) throw error;
105
+ return shared.AccountSchema.parse(created);
164
106
  },
165
- onSuccess: (newAccount, variables, context, mutation) => {
107
+ onSuccess: (newAccount, variables, onMutateResult, context) => {
166
108
  queryClient.setQueryData(
167
109
  accountKeys.list(variables.userId),
168
110
  (oldData) => {
169
- if (!oldData?.accounts) return oldData;
170
- return {
171
- ...oldData,
172
- accounts: [...oldData.accounts, newAccount]
173
- };
111
+ if (!oldData) return { accounts: [newAccount] };
112
+ return { accounts: [...oldData.accounts, newAccount] };
174
113
  }
175
114
  );
176
- options?.onSuccess?.(newAccount, variables, context, mutation);
115
+ options?.onSuccess?.(newAccount, variables, onMutateResult, context);
177
116
  },
178
117
  ...options
179
118
  });
@@ -181,13 +120,11 @@ function useCreateAccount(options) {
181
120
  function useUpdateAccount(options) {
182
121
  const queryClient = reactQuery.useQueryClient();
183
122
  return reactQuery.useMutation({
184
- mutationFn: async ({ userId, accountId, data }) => {
123
+ mutationFn: async ({ accountId, data }) => {
185
124
  const validated = shared.AccountUpdateSchema.parse(data);
186
- const response = await api.put(
187
- `/users/${userId}/accounts/${accountId}`,
188
- validated
189
- );
190
- return shared.AccountSchema.parse(response.data);
125
+ const { data: updated, error } = await shared.supabase.from("accounts").update(validated).eq("id", accountId).select().single();
126
+ if (error) throw error;
127
+ return shared.AccountSchema.parse(updated);
191
128
  },
192
129
  onSuccess: (_, { userId, accountId }) => {
193
130
  queryClient.invalidateQueries({
@@ -203,8 +140,9 @@ function useUpdateAccount(options) {
203
140
  function useDeleteAccount(options) {
204
141
  const queryClient = reactQuery.useQueryClient();
205
142
  return reactQuery.useMutation({
206
- mutationFn: async ({ userId, accountId }) => {
207
- await api.delete(`/users/${userId}/accounts/${accountId}`);
143
+ mutationFn: async ({ accountId }) => {
144
+ const { error } = await shared.supabase.from("accounts").delete().eq("id", accountId);
145
+ if (error) throw error;
208
146
  },
209
147
  onSuccess: (_, { userId, accountId }) => {
210
148
  queryClient.invalidateQueries({
@@ -220,11 +158,10 @@ function useDeleteAccount(options) {
220
158
  function useArchiveAccount(options) {
221
159
  const queryClient = reactQuery.useQueryClient();
222
160
  return reactQuery.useMutation({
223
- mutationFn: async ({ userId, accountId }) => {
224
- const response = await api.put(
225
- `/users/${userId}/accounts/${accountId}/archive`
226
- );
227
- return shared.AccountSchema.parse(response.data);
161
+ mutationFn: async ({ accountId }) => {
162
+ const { data, error } = await shared.supabase.from("accounts").update({ is_active: false }).eq("id", accountId).select().single();
163
+ if (error) throw error;
164
+ return shared.AccountSchema.parse(data);
228
165
  },
229
166
  onSuccess: (_, { userId, accountId }) => {
230
167
  queryClient.invalidateQueries({
@@ -241,21 +178,18 @@ function useCreateNetWorthAccount(options) {
241
178
  const queryClient = reactQuery.useQueryClient();
242
179
  return reactQuery.useMutation({
243
180
  mutationFn: async ({ userId, data }) => {
244
- const validated = shared.NetWorthAccountCreateSchema.parse(data);
245
- const response = await api.post(
246
- `/users/${userId}/networth/accounts`,
247
- validated
248
- );
249
- const accountType = validated.networth_account.account_type;
250
- if (accountType === "asset") {
251
- return shared.NetWorthAssetSchema.parse(response.data);
252
- } else {
253
- return shared.NetWorthDebtSchema.parse(response.data);
254
- }
181
+ const { error } = await shared.supabase.from("networth_accounts").insert({
182
+ user_id: userId,
183
+ name: data.networth_account.name,
184
+ balance: parseFloat(data.networth_account.balance),
185
+ account_type: data.networth_account.account_type,
186
+ additional_networth_account: true
187
+ });
188
+ if (error) throw error;
255
189
  },
256
190
  onSuccess: (_, { userId }) => {
257
191
  queryClient.invalidateQueries({
258
- queryKey: accountKeys.networthSummary(userId)
192
+ queryKey: [...accountKeys.all, "networth", userId]
259
193
  });
260
194
  },
261
195
  ...options
@@ -264,21 +198,17 @@ function useCreateNetWorthAccount(options) {
264
198
  function useUpdateNetWorthAccount(options) {
265
199
  const queryClient = reactQuery.useQueryClient();
266
200
  return reactQuery.useMutation({
267
- mutationFn: async ({ userId, accountId, data }) => {
268
- const validated = shared.NetWorthAccountUpdateSchema.parse(data);
269
- const response = await api.put(
270
- `/users/${userId}/networth/accounts/${accountId}`,
271
- validated
272
- );
273
- try {
274
- return shared.NetWorthAssetSchema.parse(response.data);
275
- } catch {
276
- return shared.NetWorthDebtSchema.parse(response.data);
277
- }
201
+ mutationFn: async ({ accountId, data }) => {
202
+ const { error } = await shared.supabase.from("networth_accounts").update({
203
+ name: data.networth_account.name,
204
+ balance: parseFloat(data.networth_account.balance),
205
+ account_type: data.networth_account.account_type
206
+ }).eq("id", String(accountId));
207
+ if (error) throw error;
278
208
  },
279
209
  onSuccess: (_, { userId }) => {
280
210
  queryClient.invalidateQueries({
281
- queryKey: accountKeys.networthSummary(userId)
211
+ queryKey: [...accountKeys.all, "networth", userId]
282
212
  });
283
213
  },
284
214
  ...options
@@ -287,13 +217,13 @@ function useUpdateNetWorthAccount(options) {
287
217
  function useDeleteNetWorthAccount(options) {
288
218
  const queryClient = reactQuery.useQueryClient();
289
219
  return reactQuery.useMutation({
290
- mutationFn: async ({ userId, accountId }) => {
291
- shared.NetWorthAccountDeleteSchema.parse({ id: accountId });
292
- await api.delete(`/users/${userId}/networth/accounts/${accountId}`);
220
+ mutationFn: async ({ accountId }) => {
221
+ const { error } = await shared.supabase.from("networth_accounts").delete().eq("id", String(accountId));
222
+ if (error) throw error;
293
223
  },
294
224
  onSuccess: (_, { userId }) => {
295
225
  queryClient.invalidateQueries({
296
- queryKey: accountKeys.networthSummary(userId)
226
+ queryKey: [...accountKeys.all, "networth", userId]
297
227
  });
298
228
  },
299
229
  ...options
@@ -301,7 +231,6 @@ function useDeleteNetWorthAccount(options) {
301
231
  }
302
232
 
303
233
  exports.accountKeys = accountKeys;
304
- exports.api = api;
305
234
  exports.useAccount = useAccount;
306
235
  exports.useAccounts = useAccounts;
307
236
  exports.useArchiveAccount = useArchiveAccount;
@@ -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":["axios","useQuery","AccountsResponseSchema","AccountSchema","NetWorthResponseSchema","useQueryClient","useAppMode","useMutation","AccountCreateSchemaAdmin","AccountCreateSchemaUser","AccountUpdateSchema","NetWorthAccountCreateSchema","NetWorthAssetSchema","NetWorthDebtSchema","NetWorthAccountUpdateSchema","NetWorthAccountDeleteSchema"],"mappings":"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","file":"index.cjs","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","supabase","AccountsResponseSchema","AccountSchema","useQueryClient","useAppMode","useMutation","AccountCreateSchemaAdmin","AccountCreateSchemaUser","AccountUpdateSchema"],"mappings":"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","file":"index.cjs","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"]}