@cranberry-money/shared-services 1.0.0

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.
Files changed (50) hide show
  1. package/README.md +288 -0
  2. package/dist/adapters/MobileApiClient.d.ts +68 -0
  3. package/dist/adapters/MobileApiClient.d.ts.map +1 -0
  4. package/dist/adapters/MobileApiClient.js +240 -0
  5. package/dist/adapters/MobileTokenStorage.d.ts +43 -0
  6. package/dist/adapters/MobileTokenStorage.d.ts.map +1 -0
  7. package/dist/adapters/MobileTokenStorage.js +128 -0
  8. package/dist/adapters/WebApiClient.d.ts +28 -0
  9. package/dist/adapters/WebApiClient.d.ts.map +1 -0
  10. package/dist/adapters/WebApiClient.js +119 -0
  11. package/dist/adapters/WebTokenStorage.d.ts +38 -0
  12. package/dist/adapters/WebTokenStorage.d.ts.map +1 -0
  13. package/dist/adapters/WebTokenStorage.js +86 -0
  14. package/dist/auth/AuthManager.d.ts +81 -0
  15. package/dist/auth/AuthManager.d.ts.map +1 -0
  16. package/dist/auth/AuthManager.js +223 -0
  17. package/dist/auth/createAuthManager.d.ts +63 -0
  18. package/dist/auth/createAuthManager.d.ts.map +1 -0
  19. package/dist/auth/createAuthManager.js +103 -0
  20. package/dist/auth/useAuthManager.d.ts +66 -0
  21. package/dist/auth/useAuthManager.d.ts.map +1 -0
  22. package/dist/auth/useAuthManager.js +133 -0
  23. package/dist/core/BaseApiClient.d.ts +82 -0
  24. package/dist/core/BaseApiClient.d.ts.map +1 -0
  25. package/dist/core/BaseApiClient.js +89 -0
  26. package/dist/core/TokenStorage.d.ts +45 -0
  27. package/dist/core/TokenStorage.d.ts.map +1 -0
  28. package/dist/core/TokenStorage.js +23 -0
  29. package/dist/index.d.ts +19 -0
  30. package/dist/index.d.ts.map +1 -0
  31. package/dist/index.js +23 -0
  32. package/dist/query/QueryClient.d.ts +82 -0
  33. package/dist/query/QueryClient.d.ts.map +1 -0
  34. package/dist/query/QueryClient.js +136 -0
  35. package/dist/query/useAuth.d.ts +64 -0
  36. package/dist/query/useAuth.d.ts.map +1 -0
  37. package/dist/query/useAuth.js +144 -0
  38. package/dist/query/usePortfolios.d.ts +79 -0
  39. package/dist/query/usePortfolios.d.ts.map +1 -0
  40. package/dist/query/usePortfolios.js +172 -0
  41. package/dist/services/AuthService.d.ts +75 -0
  42. package/dist/services/AuthService.d.ts.map +1 -0
  43. package/dist/services/AuthService.js +83 -0
  44. package/dist/services/BaseService.d.ts +48 -0
  45. package/dist/services/BaseService.d.ts.map +1 -0
  46. package/dist/services/BaseService.js +51 -0
  47. package/dist/services/PortfolioService.d.ts +100 -0
  48. package/dist/services/PortfolioService.d.ts.map +1 -0
  49. package/dist/services/PortfolioService.js +68 -0
  50. package/package.json +56 -0
@@ -0,0 +1,79 @@
1
+ /**
2
+ * Shared portfolio React Query hooks
3
+ *
4
+ * Provides consistent portfolio data management and operations
5
+ * with optimized caching and invalidation patterns.
6
+ */
7
+ import { type UseMutationOptions } from '@tanstack/react-query';
8
+ import type { PortfolioService, Portfolio, CreatePortfolioPayload, UpdatePortfolioPayload, PortfolioListFilters } from '../services/PortfolioService';
9
+ export interface UsePortfolioServiceOptions {
10
+ portfolioService: PortfolioService;
11
+ }
12
+ export interface PortfolioMutationOptions<TData, TVariables> extends Omit<UseMutationOptions<TData, Error, TVariables>, 'mutationFn'> {
13
+ portfolioService: PortfolioService;
14
+ }
15
+ /**
16
+ * Get all portfolios with filtering
17
+ */
18
+ export declare function usePortfolios({ portfolioService }: UsePortfolioServiceOptions, filters?: PortfolioListFilters, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("..").PaginatedResponse<Portfolio>, Error>;
19
+ /**
20
+ * Get specific portfolio by ID
21
+ */
22
+ export declare function usePortfolio({ portfolioService }: UsePortfolioServiceOptions, portfolioId: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<Portfolio, Error>;
23
+ /**
24
+ * Get portfolio holdings
25
+ */
26
+ export declare function usePortfolioHoldings({ portfolioService }: UsePortfolioServiceOptions, portfolioId: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("..").AssetHolding[], Error>;
27
+ /**
28
+ * Get portfolio allocations
29
+ */
30
+ export declare function usePortfolioAllocations({ portfolioService }: UsePortfolioServiceOptions, portfolioId: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("..").AssetAllocation[], Error>;
31
+ /**
32
+ * Get portfolio performance data
33
+ */
34
+ export declare function usePortfolioPerformance({ portfolioService }: UsePortfolioServiceOptions, portfolioId: string, timeRange?: string, enabled?: boolean): import("@tanstack/react-query").UseQueryResult<import("..").PerformanceData, Error>;
35
+ /**
36
+ * Create portfolio mutation
37
+ */
38
+ export declare function useCreatePortfolio(options: PortfolioMutationOptions<Portfolio, CreatePortfolioPayload>): import("@tanstack/react-query").UseMutationResult<Portfolio, Error, CreatePortfolioPayload, unknown>;
39
+ /**
40
+ * Update portfolio mutation
41
+ */
42
+ export declare function useUpdatePortfolio(options: PortfolioMutationOptions<Portfolio, {
43
+ id: string;
44
+ data: UpdatePortfolioPayload;
45
+ }>): import("@tanstack/react-query").UseMutationResult<Portfolio, Error, {
46
+ id: string;
47
+ data: UpdatePortfolioPayload;
48
+ }, unknown>;
49
+ /**
50
+ * Delete portfolio mutation
51
+ */
52
+ export declare function useDeletePortfolio(options: PortfolioMutationOptions<void, string>): import("@tanstack/react-query").UseMutationResult<void, Error, string, unknown>;
53
+ /**
54
+ * Infinite query for portfolios (useful for large lists)
55
+ */
56
+ export declare function useInfinitePortfolios({ portfolioService }: UsePortfolioServiceOptions, filters?: PortfolioListFilters): import("@tanstack/react-query").UseInfiniteQueryResult<import("@tanstack/query-core").InfiniteData<import("..").PaginatedResponse<Portfolio>, unknown>, Error>;
57
+ /**
58
+ * Composite hook for complete portfolio management
59
+ */
60
+ export declare function usePortfolioManagement(serviceOptions: UsePortfolioServiceOptions, portfolioId?: string): {
61
+ portfolios: Portfolio[];
62
+ portfolio: Portfolio | undefined;
63
+ holdings: import("..").AssetHolding[];
64
+ allocations: import("..").AssetAllocation[];
65
+ isLoadingPortfolios: boolean;
66
+ isLoadingPortfolio: boolean;
67
+ isLoadingHoldings: boolean;
68
+ isLoadingAllocations: boolean;
69
+ isLoading: boolean;
70
+ portfoliosError: Error | null;
71
+ portfolioError: Error | null;
72
+ holdingsError: Error | null;
73
+ allocationsError: Error | null;
74
+ refetchPortfolios: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("..").PaginatedResponse<Portfolio>, Error>>;
75
+ refetchPortfolio: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<Portfolio, Error>>;
76
+ refetchHoldings: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("..").AssetHolding[], Error>>;
77
+ refetchAllocations: (options?: import("@tanstack/query-core").RefetchOptions) => Promise<import("@tanstack/query-core").QueryObserverResult<import("..").AssetAllocation[], Error>>;
78
+ };
79
+ //# sourceMappingURL=usePortfolios.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"usePortfolios.d.ts","sourceRoot":"","sources":["../../src/query/usePortfolios.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAA2D,KAAK,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AACzH,OAAO,KAAK,EACV,gBAAgB,EAChB,SAAS,EACT,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAGtC,MAAM,WAAW,0BAA0B;IACzC,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED,MAAM,WAAW,wBAAwB,CAAC,KAAK,EAAE,UAAU,CAAE,SAC3D,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,KAAK,EAAE,UAAU,CAAC,EAAE,YAAY,CAAC;IAChE,gBAAgB,EAAE,gBAAgB,CAAC;CACpC;AAED;;GAEG;AACH,wBAAgB,aAAa,CAC3B,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,OAAO,GAAE,oBAAyB,EAClC,OAAO,GAAE,OAAc,oGAQxB;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAc,oEAQxB;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAc,sFAQxB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,OAAc,yFAQxB;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,MAAa,EACxB,OAAO,GAAE,OAAc,uFAQxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,CAAC,SAAS,EAAE,sBAAsB,CAAC,wGAqBtG;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,CAAC,SAAS,EAAE;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,sBAAsB,CAAA;CAAE,CAAC;QAAvC,MAAM;UAAQ,sBAAsB;YAsBzH;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,wBAAwB,CAAC,IAAI,EAAE,MAAM,CAAC,mFAoBjF;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,EAAE,gBAAgB,EAAE,EAAE,0BAA0B,EAChD,OAAO,GAAE,oBAAyB,kKAgBnC;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,cAAc,EAAE,0BAA0B,EAC1C,WAAW,CAAC,EAAE,MAAM;;;;;;;;;;;;;;;;;;EAiCrB"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * Shared portfolio React Query hooks
3
+ *
4
+ * Provides consistent portfolio data management and operations
5
+ * with optimized caching and invalidation patterns.
6
+ */
7
+ import { useQuery, useMutation, useQueryClient, useInfiniteQuery } from '@tanstack/react-query';
8
+ import { queryKeys, createQueryOptions } from './QueryClient';
9
+ /**
10
+ * Get all portfolios with filtering
11
+ */
12
+ export function usePortfolios({ portfolioService }, filters = {}, enabled = true) {
13
+ return useQuery({
14
+ queryKey: queryKeys.portfolios.all(),
15
+ queryFn: () => portfolioService.getPortfolios(filters),
16
+ enabled,
17
+ ...createQueryOptions.user('web'), // Adjust based on platform
18
+ });
19
+ }
20
+ /**
21
+ * Get specific portfolio by ID
22
+ */
23
+ export function usePortfolio({ portfolioService }, portfolioId, enabled = true) {
24
+ return useQuery({
25
+ queryKey: queryKeys.portfolios.detail(portfolioId),
26
+ queryFn: () => portfolioService.getPortfolio(portfolioId),
27
+ enabled: enabled && !!portfolioId,
28
+ ...createQueryOptions.user('web'),
29
+ });
30
+ }
31
+ /**
32
+ * Get portfolio holdings
33
+ */
34
+ export function usePortfolioHoldings({ portfolioService }, portfolioId, enabled = true) {
35
+ return useQuery({
36
+ queryKey: queryKeys.portfolios.holdings(portfolioId),
37
+ queryFn: () => portfolioService.getHoldings(portfolioId),
38
+ enabled: enabled && !!portfolioId,
39
+ ...createQueryOptions.realtime('web'), // Holdings update frequently
40
+ });
41
+ }
42
+ /**
43
+ * Get portfolio allocations
44
+ */
45
+ export function usePortfolioAllocations({ portfolioService }, portfolioId, enabled = true) {
46
+ return useQuery({
47
+ queryKey: queryKeys.portfolios.allocations(portfolioId),
48
+ queryFn: () => portfolioService.getAllocations(portfolioId),
49
+ enabled: enabled && !!portfolioId,
50
+ ...createQueryOptions.user('web'),
51
+ });
52
+ }
53
+ /**
54
+ * Get portfolio performance data
55
+ */
56
+ export function usePortfolioPerformance({ portfolioService }, portfolioId, timeRange = '1Y', enabled = true) {
57
+ return useQuery({
58
+ queryKey: ['portfolios', portfolioId, 'performance', timeRange],
59
+ queryFn: () => portfolioService.getPerformance(portfolioId, timeRange),
60
+ enabled: enabled && !!portfolioId,
61
+ staleTime: 5 * 60 * 1000, // 5 minutes - performance data doesn't change frequently
62
+ });
63
+ }
64
+ /**
65
+ * Create portfolio mutation
66
+ */
67
+ export function useCreatePortfolio(options) {
68
+ const queryClient = useQueryClient();
69
+ const { portfolioService, ...mutationOptions } = options;
70
+ return useMutation({
71
+ mutationFn: (data) => portfolioService.createPortfolio(data),
72
+ onSuccess: (newPortfolio, ...args) => {
73
+ // Add new portfolio to the cache
74
+ queryClient.setQueryData(queryKeys.portfolios.detail(newPortfolio.id), newPortfolio);
75
+ // Invalidate portfolios list to include new portfolio
76
+ queryClient.invalidateQueries({ queryKey: queryKeys.portfolios.all() });
77
+ // Call user's onSuccess if provided
78
+ mutationOptions.onSuccess?.(newPortfolio, ...args);
79
+ },
80
+ ...mutationOptions,
81
+ });
82
+ }
83
+ /**
84
+ * Update portfolio mutation
85
+ */
86
+ export function useUpdatePortfolio(options) {
87
+ const queryClient = useQueryClient();
88
+ const { portfolioService, ...mutationOptions } = options;
89
+ return useMutation({
90
+ mutationFn: ({ id, data }) => portfolioService.updatePortfolio(id, data),
91
+ onSuccess: (updatedPortfolio, { id }, ...args) => {
92
+ // Update portfolio in cache
93
+ queryClient.setQueryData(queryKeys.portfolios.detail(id), updatedPortfolio);
94
+ // Invalidate portfolios list to reflect changes
95
+ queryClient.invalidateQueries({ queryKey: queryKeys.portfolios.all() });
96
+ // Call user's onSuccess if provided
97
+ mutationOptions.onSuccess?.(updatedPortfolio, { id, data: { name: updatedPortfolio.name } }, ...args);
98
+ },
99
+ ...mutationOptions,
100
+ });
101
+ }
102
+ /**
103
+ * Delete portfolio mutation
104
+ */
105
+ export function useDeletePortfolio(options) {
106
+ const queryClient = useQueryClient();
107
+ const { portfolioService, ...mutationOptions } = options;
108
+ return useMutation({
109
+ mutationFn: (id) => portfolioService.deletePortfolio(id),
110
+ onSuccess: (_, portfolioId, ...args) => {
111
+ // Remove portfolio from cache
112
+ queryClient.removeQueries({ queryKey: queryKeys.portfolios.detail(portfolioId) });
113
+ queryClient.removeQueries({ queryKey: queryKeys.portfolios.holdings(portfolioId) });
114
+ queryClient.removeQueries({ queryKey: queryKeys.portfolios.allocations(portfolioId) });
115
+ // Invalidate portfolios list to reflect deletion
116
+ queryClient.invalidateQueries({ queryKey: queryKeys.portfolios.all() });
117
+ // Call user's onSuccess if provided
118
+ mutationOptions.onSuccess?.(_, portfolioId, ...args);
119
+ },
120
+ ...mutationOptions,
121
+ });
122
+ }
123
+ /**
124
+ * Infinite query for portfolios (useful for large lists)
125
+ */
126
+ export function useInfinitePortfolios({ portfolioService }, filters = {}) {
127
+ return useInfiniteQuery({
128
+ queryKey: ['portfolios', 'infinite', filters],
129
+ queryFn: ({ pageParam = 1 }) => portfolioService.getPortfolios({ ...filters, page: pageParam }),
130
+ initialPageParam: 1,
131
+ getNextPageParam: (lastPage) => {
132
+ if (lastPage.next) {
133
+ const url = new URL(lastPage.next);
134
+ return Number(url.searchParams.get('page'));
135
+ }
136
+ return undefined;
137
+ },
138
+ ...createQueryOptions.user('web'),
139
+ });
140
+ }
141
+ /**
142
+ * Composite hook for complete portfolio management
143
+ */
144
+ export function usePortfolioManagement(serviceOptions, portfolioId) {
145
+ const portfoliosQuery = usePortfolios(serviceOptions);
146
+ const portfolioQuery = usePortfolio(serviceOptions, portfolioId || '', !!portfolioId);
147
+ const holdingsQuery = usePortfolioHoldings(serviceOptions, portfolioId || '', !!portfolioId);
148
+ const allocationsQuery = usePortfolioAllocations(serviceOptions, portfolioId || '', !!portfolioId);
149
+ return {
150
+ // Data
151
+ portfolios: portfoliosQuery.data?.results || [],
152
+ portfolio: portfolioQuery.data,
153
+ holdings: holdingsQuery.data || [],
154
+ allocations: allocationsQuery.data || [],
155
+ // Loading states
156
+ isLoadingPortfolios: portfoliosQuery.isLoading,
157
+ isLoadingPortfolio: portfolioQuery.isLoading,
158
+ isLoadingHoldings: holdingsQuery.isLoading,
159
+ isLoadingAllocations: allocationsQuery.isLoading,
160
+ isLoading: portfoliosQuery.isLoading || portfolioQuery.isLoading,
161
+ // Error states
162
+ portfoliosError: portfoliosQuery.error,
163
+ portfolioError: portfolioQuery.error,
164
+ holdingsError: holdingsQuery.error,
165
+ allocationsError: allocationsQuery.error,
166
+ // Refetch functions
167
+ refetchPortfolios: portfoliosQuery.refetch,
168
+ refetchPortfolio: portfolioQuery.refetch,
169
+ refetchHoldings: holdingsQuery.refetch,
170
+ refetchAllocations: allocationsQuery.refetch,
171
+ };
172
+ }
@@ -0,0 +1,75 @@
1
+ /**
2
+ * Authentication service with React Query integration
3
+ *
4
+ * Provides authentication operations with proper query invalidation
5
+ * and state management across platforms.
6
+ */
7
+ import type { BaseApiClient } from '../core/BaseApiClient';
8
+ import { BaseService } from './BaseService';
9
+ export interface SigninPayload {
10
+ email: string;
11
+ password: string;
12
+ }
13
+ export interface SignupPayload {
14
+ email: string;
15
+ password: string;
16
+ first_name: string;
17
+ last_name: string;
18
+ }
19
+ export interface EmailVerificationPayload {
20
+ email: string;
21
+ verification_code: string;
22
+ }
23
+ export interface TokenRefreshPayload {
24
+ refresh: string;
25
+ }
26
+ export interface TokenRefreshResponse {
27
+ access: string;
28
+ refresh: string;
29
+ }
30
+ export interface UserProfile {
31
+ id: string;
32
+ email: string;
33
+ first_name: string;
34
+ last_name: string;
35
+ is_verified: boolean;
36
+ is_signup_completed: boolean;
37
+ }
38
+ export declare class AuthService extends BaseService {
39
+ constructor(apiClient: BaseApiClient);
40
+ /**
41
+ * Sign in user
42
+ */
43
+ signin(data: SigninPayload): Promise<unknown>;
44
+ /**
45
+ * Sign out user
46
+ */
47
+ signout(): Promise<unknown>;
48
+ /**
49
+ * Sign up new user
50
+ */
51
+ signup(data: SignupPayload): Promise<unknown>;
52
+ /**
53
+ * Verify email address
54
+ */
55
+ verifyEmail(data: EmailVerificationPayload): Promise<unknown>;
56
+ /**
57
+ * Resend verification code
58
+ */
59
+ resendVerificationCode(): Promise<unknown>;
60
+ /**
61
+ * Refresh authentication tokens
62
+ */
63
+ refreshToken(data: TokenRefreshPayload): Promise<TokenRefreshResponse>;
64
+ /**
65
+ * Get current user profile
66
+ */
67
+ getProfile(): Promise<UserProfile>;
68
+ /**
69
+ * Check authentication status
70
+ */
71
+ checkStatus(): Promise<{
72
+ authenticated: boolean;
73
+ }>;
74
+ }
75
+ //# sourceMappingURL=AuthService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthService.d.ts","sourceRoot":"","sources":["../../src/services/AuthService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,OAAO,CAAC;IACrB,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED,qBAAa,WAAY,SAAQ,WAAW;gBAC9B,SAAS,EAAE,aAAa;IAIpC;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,aAAa;IAKhC;;OAEG;IACG,OAAO;IAKb;;OAEG;IACG,MAAM,CAAC,IAAI,EAAE,aAAa;IAKhC;;OAEG;IACG,WAAW,CAAC,IAAI,EAAE,wBAAwB;IAKhD;;OAEG;IACG,sBAAsB;IAK5B;;OAEG;IACG,YAAY,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAQ5E;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,WAAW,CAAC;IAcxC;;OAEG;IACG,WAAW;;;CASlB"}
@@ -0,0 +1,83 @@
1
+ /**
2
+ * Authentication service with React Query integration
3
+ *
4
+ * Provides authentication operations with proper query invalidation
5
+ * and state management across platforms.
6
+ */
7
+ import { BaseService } from './BaseService';
8
+ export class AuthService extends BaseService {
9
+ constructor(apiClient) {
10
+ super(apiClient, '/api');
11
+ }
12
+ /**
13
+ * Sign in user
14
+ */
15
+ async signin(data) {
16
+ const response = await this.apiClient.post(this.buildEndpoint('signin/'), data);
17
+ return this.extractData(response);
18
+ }
19
+ /**
20
+ * Sign out user
21
+ */
22
+ async signout() {
23
+ const response = await this.apiClient.post(this.buildEndpoint('signout/'));
24
+ return this.extractData(response);
25
+ }
26
+ /**
27
+ * Sign up new user
28
+ */
29
+ async signup(data) {
30
+ const response = await this.apiClient.post(this.buildEndpoint('signup/'), data);
31
+ return this.extractData(response);
32
+ }
33
+ /**
34
+ * Verify email address
35
+ */
36
+ async verifyEmail(data) {
37
+ const response = await this.apiClient.post(this.buildEndpoint('email-verification/'), data);
38
+ return this.extractData(response);
39
+ }
40
+ /**
41
+ * Resend verification code
42
+ */
43
+ async resendVerificationCode() {
44
+ const response = await this.apiClient.post(this.buildEndpoint('resend-verification/'));
45
+ return this.extractData(response);
46
+ }
47
+ /**
48
+ * Refresh authentication tokens
49
+ */
50
+ async refreshToken(data) {
51
+ const response = await this.apiClient.post(this.buildEndpoint('token/refresh/'), data);
52
+ return this.extractData(response);
53
+ }
54
+ /**
55
+ * Get current user profile
56
+ */
57
+ async getProfile() {
58
+ // Get the first user profile (current user's profile)
59
+ const response = await this.apiClient.get(this.buildEndpoint('user-profiles/'));
60
+ const profiles = this.extractData(response);
61
+ if (!profiles.results || profiles.results.length === 0) {
62
+ throw new Error('No user profile found');
63
+ }
64
+ const profile = profiles.results[0];
65
+ if (!profile) {
66
+ throw new Error('No user profile found');
67
+ }
68
+ return profile;
69
+ }
70
+ /**
71
+ * Check authentication status
72
+ */
73
+ async checkStatus() {
74
+ // Use the profile endpoint to check auth status
75
+ try {
76
+ await this.getProfile();
77
+ return { authenticated: true };
78
+ }
79
+ catch (error) {
80
+ return { authenticated: false };
81
+ }
82
+ }
83
+ }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Base service class for all API services
3
+ *
4
+ * Provides common functionality and patterns for API interaction
5
+ * that can be shared across all domain services.
6
+ */
7
+ import type { BaseApiClient, ApiResponse } from '../core/BaseApiClient';
8
+ export declare abstract class BaseService {
9
+ protected apiClient: BaseApiClient;
10
+ protected baseEndpoint: string;
11
+ constructor(apiClient: BaseApiClient, baseEndpoint: string);
12
+ /**
13
+ * Build endpoint URL relative to service base
14
+ */
15
+ protected buildEndpoint(path?: string): string;
16
+ /**
17
+ * Extract data from API response
18
+ */
19
+ protected extractData<T>(response: ApiResponse<T>): T;
20
+ /**
21
+ * Handle paginated responses
22
+ */
23
+ protected handlePaginatedResponse<T>(response: ApiResponse<PaginatedResponse<T>>): PaginatedResponse<T>;
24
+ /**
25
+ * Build query parameters from filters
26
+ */
27
+ protected buildQueryParams(filters: Record<string, unknown>): Record<string, string>;
28
+ }
29
+ /**
30
+ * Common paginated response interface
31
+ */
32
+ export interface PaginatedResponse<T> {
33
+ count: number;
34
+ next: string | null;
35
+ previous: string | null;
36
+ results: T[];
37
+ }
38
+ /**
39
+ * Common list filters interface
40
+ */
41
+ export interface BaseListFilters {
42
+ page?: number;
43
+ page_size?: number;
44
+ ordering?: string;
45
+ search?: string;
46
+ [key: string]: unknown;
47
+ }
48
+ //# sourceMappingURL=BaseService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseService.d.ts","sourceRoot":"","sources":["../../src/services/BaseService.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAExE,8BAAsB,WAAW;IAC/B,SAAS,CAAC,SAAS,EAAE,aAAa,CAAC;IACnC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC;gBAEnB,SAAS,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM;IAK1D;;OAEG;IACH,SAAS,CAAC,aAAa,CAAC,IAAI,GAAE,MAAW,GAAG,MAAM;IAMlD;;OAEG;IACH,SAAS,CAAC,WAAW,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC;IAIrD;;OAEG;IACH,SAAS,CAAC,uBAAuB,CAAC,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC;IAIvG;;OAEG;IACH,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAiBrF;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB,CAAC,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,OAAO,EAAE,CAAC,EAAE,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Base service class for all API services
3
+ *
4
+ * Provides common functionality and patterns for API interaction
5
+ * that can be shared across all domain services.
6
+ */
7
+ export class BaseService {
8
+ constructor(apiClient, baseEndpoint) {
9
+ this.apiClient = apiClient;
10
+ this.baseEndpoint = baseEndpoint;
11
+ }
12
+ /**
13
+ * Build endpoint URL relative to service base
14
+ */
15
+ buildEndpoint(path = '') {
16
+ const cleanBase = this.baseEndpoint.replace(/\/$/, '');
17
+ const cleanPath = path.replace(/^\//, '');
18
+ return cleanPath ? `${cleanBase}/${cleanPath}` : cleanBase;
19
+ }
20
+ /**
21
+ * Extract data from API response
22
+ */
23
+ extractData(response) {
24
+ return response.data;
25
+ }
26
+ /**
27
+ * Handle paginated responses
28
+ */
29
+ handlePaginatedResponse(response) {
30
+ return response.data;
31
+ }
32
+ /**
33
+ * Build query parameters from filters
34
+ */
35
+ buildQueryParams(filters) {
36
+ const params = {};
37
+ Object.entries(filters).forEach(([key, value]) => {
38
+ if (value !== undefined && value !== null && value !== '') {
39
+ if (Array.isArray(value)) {
40
+ if (value.length > 0) {
41
+ params[key] = value.join(',');
42
+ }
43
+ }
44
+ else {
45
+ params[key] = String(value);
46
+ }
47
+ }
48
+ });
49
+ return params;
50
+ }
51
+ }
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Portfolio service with comprehensive CRUD operations
3
+ *
4
+ * Demonstrates the service pattern for domain-specific API operations
5
+ * with proper typing and error handling.
6
+ */
7
+ import type { BaseApiClient } from '../core/BaseApiClient';
8
+ import { BaseService, type PaginatedResponse, type BaseListFilters } from './BaseService';
9
+ export interface Portfolio {
10
+ id: string;
11
+ name: string;
12
+ description?: string;
13
+ total_value: number;
14
+ cash_balance: number;
15
+ created_at: string;
16
+ updated_at: string;
17
+ is_active: boolean;
18
+ }
19
+ export interface CreatePortfolioPayload {
20
+ name: string;
21
+ description?: string;
22
+ }
23
+ export interface UpdatePortfolioPayload {
24
+ name?: string;
25
+ description?: string;
26
+ is_active?: boolean;
27
+ }
28
+ export interface PortfolioListFilters extends BaseListFilters {
29
+ is_active?: boolean;
30
+ min_value?: number;
31
+ max_value?: number;
32
+ }
33
+ export interface AssetHolding {
34
+ id: string;
35
+ instrument_id: string;
36
+ instrument_name: string;
37
+ instrument_symbol: string;
38
+ quantity: number;
39
+ market_value: number;
40
+ average_cost: number;
41
+ unrealized_pnl: number;
42
+ weight: number;
43
+ }
44
+ export interface AssetAllocation {
45
+ sector: string;
46
+ allocation: number;
47
+ market_value: number;
48
+ target_allocation?: number;
49
+ }
50
+ export declare class PortfolioService extends BaseService {
51
+ constructor(apiClient: BaseApiClient);
52
+ /**
53
+ * Get all portfolios with optional filtering
54
+ */
55
+ getPortfolios(filters?: PortfolioListFilters): Promise<PaginatedResponse<Portfolio>>;
56
+ /**
57
+ * Get specific portfolio by ID
58
+ */
59
+ getPortfolio(id: string): Promise<Portfolio>;
60
+ /**
61
+ * Create new portfolio
62
+ */
63
+ createPortfolio(data: CreatePortfolioPayload): Promise<Portfolio>;
64
+ /**
65
+ * Update existing portfolio
66
+ */
67
+ updatePortfolio(id: string, data: UpdatePortfolioPayload): Promise<Portfolio>;
68
+ /**
69
+ * Delete portfolio
70
+ */
71
+ deletePortfolio(id: string): Promise<void>;
72
+ /**
73
+ * Get portfolio asset holdings
74
+ */
75
+ getHoldings(portfolioId: string): Promise<AssetHolding[]>;
76
+ /**
77
+ * Get portfolio asset allocation
78
+ */
79
+ getAllocations(portfolioId: string): Promise<AssetAllocation[]>;
80
+ /**
81
+ * Get portfolio performance data
82
+ */
83
+ getPerformance(portfolioId: string, timeRange?: string): Promise<PerformanceData>;
84
+ }
85
+ export interface PerformanceData {
86
+ total_return: number;
87
+ total_return_percentage: number;
88
+ daily_returns: Array<{
89
+ date: string;
90
+ value: number;
91
+ return_percentage: number;
92
+ }>;
93
+ benchmark_comparison?: {
94
+ benchmark_name: string;
95
+ benchmark_return: number;
96
+ alpha: number;
97
+ beta: number;
98
+ };
99
+ }
100
+ //# sourceMappingURL=PortfolioService.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PortfolioService.d.ts","sourceRoot":"","sources":["../../src/services/PortfolioService.ts"],"names":[],"mappings":"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"}