@cranberry-money/shared-services 1.0.1 → 1.2.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 (52) hide show
  1. package/dist/api/apiClient.d.ts +25 -0
  2. package/dist/api/apiClient.d.ts.map +1 -0
  3. package/dist/api/apiClient.js +35 -0
  4. package/dist/api/types.d.ts +51 -0
  5. package/dist/api/types.d.ts.map +1 -0
  6. package/dist/api/types.js +4 -0
  7. package/dist/index.d.ts +5 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +7 -1
  10. package/dist/services/accounts/constants.d.ts +24 -0
  11. package/dist/services/accounts/constants.d.ts.map +1 -0
  12. package/dist/services/accounts/constants.js +30 -0
  13. package/dist/services/accounts/index.d.ts +7 -0
  14. package/dist/services/accounts/index.d.ts.map +1 -0
  15. package/dist/services/accounts/index.js +6 -0
  16. package/dist/services/accounts/service.d.ts +11 -0
  17. package/dist/services/accounts/service.d.ts.map +1 -0
  18. package/dist/services/accounts/service.js +19 -0
  19. package/dist/services/accounts/types.d.ts +15 -0
  20. package/dist/services/accounts/types.d.ts.map +1 -0
  21. package/dist/services/accounts/types.js +4 -0
  22. package/dist/services/auth/constants.d.ts +30 -0
  23. package/dist/services/auth/constants.d.ts.map +1 -0
  24. package/dist/services/auth/constants.js +37 -0
  25. package/dist/services/auth/index.d.ts +8 -0
  26. package/dist/services/auth/index.d.ts.map +1 -0
  27. package/dist/services/auth/index.js +7 -0
  28. package/dist/services/auth/service.d.ts +8 -0
  29. package/dist/services/auth/service.d.ts.map +1 -0
  30. package/dist/services/auth/service.js +23 -0
  31. package/dist/services/auth/types.d.ts +38 -0
  32. package/dist/services/auth/types.d.ts.map +1 -0
  33. package/dist/services/auth/types.js +1 -0
  34. package/dist/services/auth/utils.d.ts +46 -0
  35. package/dist/services/auth/utils.d.ts.map +1 -0
  36. package/dist/services/auth/utils.js +113 -0
  37. package/dist/services/portfolios/constants.d.ts +45 -0
  38. package/dist/services/portfolios/constants.d.ts.map +1 -0
  39. package/dist/services/portfolios/constants.js +57 -0
  40. package/dist/services/portfolios/index.d.ts +8 -0
  41. package/dist/services/portfolios/index.d.ts.map +1 -0
  42. package/dist/services/portfolios/index.js +7 -0
  43. package/dist/services/portfolios/service.d.ts +7 -0
  44. package/dist/services/portfolios/service.d.ts.map +1 -0
  45. package/dist/services/portfolios/service.js +19 -0
  46. package/dist/services/portfolios/types.d.ts +29 -0
  47. package/dist/services/portfolios/types.d.ts.map +1 -0
  48. package/dist/services/portfolios/types.js +1 -0
  49. package/dist/services/portfolios/utils.d.ts +5 -0
  50. package/dist/services/portfolios/utils.d.ts.map +1 -0
  51. package/dist/services/portfolios/utils.js +26 -0
  52. package/package.json +3 -2
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Platform-agnostic API client factory
3
+ * Supports both web and mobile environments
4
+ */
5
+ export interface ApiClientConfig {
6
+ baseURL: string;
7
+ withCredentials?: boolean;
8
+ headers?: Record<string, string>;
9
+ }
10
+ export declare const createApiClient: (config: ApiClientConfig) => import("axios").AxiosInstance;
11
+ /**
12
+ * Web API client factory (for blueberry/strawberry)
13
+ */
14
+ export declare const createWebApiClient: (baseURL?: string) => import("axios").AxiosInstance;
15
+ /**
16
+ * Mobile API client factory (for blackberry)
17
+ */
18
+ export declare const createMobileApiClient: (baseURL: string) => import("axios").AxiosInstance;
19
+ /**
20
+ * Default web API client instance
21
+ * This maintains compatibility with existing blueberry services
22
+ */
23
+ export declare const webApiClient: import("axios").AxiosInstance;
24
+ export default webApiClient;
25
+ //# sourceMappingURL=apiClient.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apiClient.d.ts","sourceRoot":"","sources":["../../src/api/apiClient.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,eAAO,MAAM,eAAe,GAAI,QAAQ,eAAe,kCAStD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,kCAKlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,MAAM,kCAKpD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,YAAY,+BAAuB,CAAC;AAEjD,eAAe,YAAY,CAAC"}
@@ -0,0 +1,35 @@
1
+ import axios from 'axios';
2
+ export const createApiClient = (config) => {
3
+ return axios.create({
4
+ baseURL: config.baseURL,
5
+ headers: {
6
+ 'Content-Type': 'application/json',
7
+ ...config.headers,
8
+ },
9
+ withCredentials: config.withCredentials ?? true,
10
+ });
11
+ };
12
+ /**
13
+ * Web API client factory (for blueberry/strawberry)
14
+ */
15
+ export const createWebApiClient = (baseURL) => {
16
+ return createApiClient({
17
+ baseURL: baseURL || (typeof window !== 'undefined' && window.ENV?.VITE_API_URL) || '',
18
+ withCredentials: true,
19
+ });
20
+ };
21
+ /**
22
+ * Mobile API client factory (for blackberry)
23
+ */
24
+ export const createMobileApiClient = (baseURL) => {
25
+ return createApiClient({
26
+ baseURL,
27
+ withCredentials: false, // Mobile doesn't use cookies
28
+ });
29
+ };
30
+ /**
31
+ * Default web API client instance
32
+ * This maintains compatibility with existing blueberry services
33
+ */
34
+ export const webApiClient = createWebApiClient();
35
+ export default webApiClient;
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Common API types shared across all services
3
+ */
4
+ export interface FormErrors {
5
+ [key: string]: string[];
6
+ }
7
+ export interface PaginatedResponse<T> {
8
+ count: number;
9
+ next: string | null;
10
+ previous: string | null;
11
+ results: T[];
12
+ }
13
+ export interface PaginationParams {
14
+ page?: number;
15
+ page_size?: number;
16
+ }
17
+ export interface OrderingParams {
18
+ ordering?: string;
19
+ order_by?: string;
20
+ }
21
+ /**
22
+ * Base filters interface for API requests
23
+ */
24
+ export interface BaseListFilters extends PaginationParams, OrderingParams {
25
+ search?: string;
26
+ [key: string]: unknown;
27
+ }
28
+ /**
29
+ * Common date range filters
30
+ */
31
+ export interface DateRangeFilters {
32
+ date_from?: string;
33
+ date_to?: string;
34
+ }
35
+ /**
36
+ * Standard API response wrapper
37
+ */
38
+ export interface ApiResponse<T> {
39
+ data: T;
40
+ status: number;
41
+ statusText: string;
42
+ }
43
+ /**
44
+ * Error response structure
45
+ */
46
+ export interface ApiErrorResponse {
47
+ detail?: string;
48
+ errors?: FormErrors;
49
+ message?: string;
50
+ }
51
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/api/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,UAAU;IACzB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CACzB;AAED,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,MAAM,WAAW,gBAAgB;IAC/B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAgB,SAAQ,gBAAgB,EAAE,cAAc;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW,CAAC,CAAC;IAC5B,IAAI,EAAE,CAAC,CAAC;IACR,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,UAAU,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Common API types shared across all services
3
+ */
4
+ export {};
package/dist/index.d.ts CHANGED
@@ -7,9 +7,14 @@ export * from './adapters/WebTokenStorage';
7
7
  export * from './adapters/WebApiClient';
8
8
  export * from './adapters/MobileTokenStorage';
9
9
  export * from './adapters/MobileApiClient';
10
+ export { createApiClient, createWebApiClient, createMobileApiClient, webApiClient } from './api/apiClient';
11
+ export type { FormErrors, PaginationParams, OrderingParams, DateRangeFilters, ApiErrorResponse } from './api/types';
10
12
  export * from './services/BaseService';
11
13
  export * from './services/AuthService';
12
14
  export * from './services/PortfolioService';
15
+ export * as AccountsService from './services/accounts';
16
+ export * as AuthService from './services/auth';
17
+ export * as PortfoliosService from './services/portfolios';
13
18
  export * from './query/QueryClient';
14
19
  export * from './query/useAuth';
15
20
  export * from './query/usePortfolios';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAG3C,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAG5C,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AAGrC,cAAc,4BAA4B,CAAC;AAC3C,cAAc,yBAAyB,CAAC;AACxC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,4BAA4B,CAAC;AAG3C,OAAO,EACL,eAAe,EACf,kBAAkB,EAClB,qBAAqB,EACrB,YAAY,EACb,MAAM,iBAAiB,CAAC;AAEzB,YAAY,EACV,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AAGrB,cAAc,wBAAwB,CAAC;AACvC,cAAc,wBAAwB,CAAC;AACvC,cAAc,6BAA6B,CAAC;AAG5C,OAAO,KAAK,eAAe,MAAM,qBAAqB,CAAC;AACvD,OAAO,KAAK,WAAW,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,iBAAiB,MAAM,uBAAuB,CAAC;AAG3D,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AAGtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,0BAA0B,CAAC;AACzC,cAAc,uBAAuB,CAAC"}
package/dist/index.js CHANGED
@@ -9,10 +9,16 @@ export * from './adapters/WebTokenStorage';
9
9
  export * from './adapters/WebApiClient';
10
10
  export * from './adapters/MobileTokenStorage';
11
11
  export * from './adapters/MobileApiClient';
12
- // Services
12
+ // New functional API client
13
+ export { createApiClient, createWebApiClient, createMobileApiClient, webApiClient } from './api/apiClient';
14
+ // Legacy class-based services (keep for backwards compatibility)
13
15
  export * from './services/BaseService';
14
16
  export * from './services/AuthService';
15
17
  export * from './services/PortfolioService';
18
+ // New functional domain services
19
+ export * as AccountsService from './services/accounts';
20
+ export * as AuthService from './services/auth';
21
+ export * as PortfoliosService from './services/portfolios';
16
22
  // React Query integration
17
23
  export * from './query/QueryClient';
18
24
  export * from './query/useAuth';
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Account-related constants for shared services.
3
+ *
4
+ * These constants should match the backend constants in bilberry/accounts/constants.py
5
+ * to ensure consistency across the application stack.
6
+ */
7
+ export declare const SOURCE_OF_FUNDS_SALARY = "salary";
8
+ export declare const SOURCE_OF_FUNDS_SAVINGS = "savings";
9
+ export declare const SOURCE_OF_FUNDS_INHERITANCE = "inheritance";
10
+ export declare const SOURCE_OF_FUNDS_GIFT = "gift";
11
+ export declare const SOURCE_OF_FUNDS_OTHER = "other";
12
+ export declare const SOURCE_OF_FUNDS_LABEL_SALARY = "Salary";
13
+ export declare const SOURCE_OF_FUNDS_LABEL_SAVINGS = "Savings";
14
+ export declare const SOURCE_OF_FUNDS_LABEL_INHERITANCE = "Inheritance";
15
+ export declare const SOURCE_OF_FUNDS_LABEL_GIFT = "Gift";
16
+ export declare const SOURCE_OF_FUNDS_LABEL_OTHER = "Other";
17
+ export declare const SOURCE_OF_FUNDS_OPTIONS: {
18
+ value: string;
19
+ label: string;
20
+ }[];
21
+ export declare const API_ENDPOINTS: {
22
+ readonly ACCOUNTS: "/api/accounts/";
23
+ };
24
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/services/accounts/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,eAAO,MAAM,sBAAsB,WAAW,CAAC;AAC/C,eAAO,MAAM,uBAAuB,YAAY,CAAC;AACjD,eAAO,MAAM,2BAA2B,gBAAgB,CAAC;AACzD,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,qBAAqB,UAAU,CAAC;AAG7C,eAAO,MAAM,4BAA4B,WAAW,CAAC;AACrD,eAAO,MAAM,6BAA6B,YAAY,CAAC;AACvD,eAAO,MAAM,iCAAiC,gBAAgB,CAAC;AAC/D,eAAO,MAAM,0BAA0B,SAAS,CAAC;AACjD,eAAO,MAAM,2BAA2B,UAAU,CAAC;AAGnD,eAAO,MAAM,uBAAuB;;;GAMnC,CAAC;AAGF,eAAO,MAAM,aAAa;;CAEhB,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Account-related constants for shared services.
3
+ *
4
+ * These constants should match the backend constants in bilberry/accounts/constants.py
5
+ * to ensure consistency across the application stack.
6
+ */
7
+ // Source of funds constants
8
+ export const SOURCE_OF_FUNDS_SALARY = 'salary';
9
+ export const SOURCE_OF_FUNDS_SAVINGS = 'savings';
10
+ export const SOURCE_OF_FUNDS_INHERITANCE = 'inheritance';
11
+ export const SOURCE_OF_FUNDS_GIFT = 'gift';
12
+ export const SOURCE_OF_FUNDS_OTHER = 'other';
13
+ // Source of funds label constants
14
+ export const SOURCE_OF_FUNDS_LABEL_SALARY = 'Salary';
15
+ export const SOURCE_OF_FUNDS_LABEL_SAVINGS = 'Savings';
16
+ export const SOURCE_OF_FUNDS_LABEL_INHERITANCE = 'Inheritance';
17
+ export const SOURCE_OF_FUNDS_LABEL_GIFT = 'Gift';
18
+ export const SOURCE_OF_FUNDS_LABEL_OTHER = 'Other';
19
+ // Source of funds options
20
+ export const SOURCE_OF_FUNDS_OPTIONS = [
21
+ { value: SOURCE_OF_FUNDS_SALARY, label: SOURCE_OF_FUNDS_LABEL_SALARY },
22
+ { value: SOURCE_OF_FUNDS_SAVINGS, label: SOURCE_OF_FUNDS_LABEL_SAVINGS },
23
+ { value: SOURCE_OF_FUNDS_INHERITANCE, label: SOURCE_OF_FUNDS_LABEL_INHERITANCE },
24
+ { value: SOURCE_OF_FUNDS_GIFT, label: SOURCE_OF_FUNDS_LABEL_GIFT },
25
+ { value: SOURCE_OF_FUNDS_OTHER, label: SOURCE_OF_FUNDS_LABEL_OTHER },
26
+ ];
27
+ // API Endpoints
28
+ export const API_ENDPOINTS = {
29
+ ACCOUNTS: '/api/accounts/',
30
+ };
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Accounts service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/accounts/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Accounts service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Account API service functions.
3
+ */
4
+ import type { PaginatedResponse } from '../../api/types';
5
+ import type { Account, AccountPayload } from './types';
6
+ export type PaginatedAccounts = PaginatedResponse<Account>;
7
+ export declare const getAccounts: () => Promise<import("axios").AxiosResponse<PaginatedAccounts, any>>;
8
+ export declare const createAccount: (data: AccountPayload) => Promise<import("axios").AxiosResponse<Account, any>>;
9
+ export declare const updateAccount: (uuid: string, data: Partial<AccountPayload>) => Promise<import("axios").AxiosResponse<Account, any>>;
10
+ export declare const getAccountByUuid: (uuid: string) => Promise<import("axios").AxiosResponse<Account, any>>;
11
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/services/accounts/service.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,OAAO,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGvD,MAAM,MAAM,iBAAiB,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;AAG3D,eAAO,MAAM,WAAW,sEAEvB,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,cAAc,yDAEjD,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,yDAExE,CAAC;AAGF,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,yDAE5C,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Account API service functions.
3
+ */
4
+ import { webApiClient } from '../../api/apiClient';
5
+ import { API_ENDPOINTS } from './constants';
6
+ // Fetch list of user accounts
7
+ export const getAccounts = () => {
8
+ return webApiClient.get(API_ENDPOINTS.ACCOUNTS);
9
+ };
10
+ export const createAccount = (data) => {
11
+ return webApiClient.post(API_ENDPOINTS.ACCOUNTS, data);
12
+ };
13
+ export const updateAccount = (uuid, data) => {
14
+ return webApiClient.patch(`${API_ENDPOINTS.ACCOUNTS}${uuid}/`, data);
15
+ };
16
+ // Get account by UUID
17
+ export const getAccountByUuid = (uuid) => {
18
+ return webApiClient.get(`${API_ENDPOINTS.ACCOUNTS}${uuid}/`);
19
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Account-related types and interfaces.
3
+ */
4
+ export interface Account {
5
+ uuid: string;
6
+ accountNumber: string | null;
7
+ accountType: string;
8
+ activationDate: string | null;
9
+ }
10
+ export interface AccountPayload {
11
+ accountType: string;
12
+ name: string;
13
+ userProfile: string;
14
+ }
15
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/accounts/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,MAAM,WAAW,OAAO;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;CAC/B;AAGD,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Account-related types and interfaces.
3
+ */
4
+ export {};
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Authentication API constants
3
+ */
4
+ export declare const API_ENDPOINTS: {
5
+ readonly SIGNIN: "/api/signin/";
6
+ readonly SIGNOUT: "/api/signout/";
7
+ readonly SIGNUP: "/api/signup/";
8
+ readonly EMAIL_VERIFICATION: "/api/email-verification/";
9
+ readonly RESEND_VERIFICATION: "/api/resend-verification/";
10
+ readonly TOKEN_REFRESH: "/api/token/refresh/";
11
+ };
12
+ export declare const DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES = 5;
13
+ export declare const MILLISECONDS_PER_MINUTE: number;
14
+ export declare const MINUTES_PER_HOUR = 60;
15
+ export declare const HOURS_PER_DAY = 24;
16
+ export declare const TIME_LABEL_EXPIRED = "Expired";
17
+ export declare const TIME_LABEL_MINUTE = "minute";
18
+ export declare const TIME_LABEL_MINUTES = "minutes";
19
+ export declare const TIME_LABEL_HOUR = "hour";
20
+ export declare const TIME_LABEL_HOURS = "hours";
21
+ export declare const TIME_LABEL_DAY = "day";
22
+ export declare const TIME_LABEL_DAYS = "days";
23
+ export declare const TIME_LABEL_HOUR_SHORT = "h";
24
+ export declare const TIME_LABEL_MINUTE_SHORT = "m";
25
+ export declare const TIME_LABEL_DAY_SHORT = "d";
26
+ export declare const DEFAULT_UNKNOWN_VALUE = "Unknown";
27
+ export declare const DEFAULT_ERROR_MESSAGE = "An error occurred";
28
+ export declare const TOKEN_STORAGE_KEY_ACCESS = "access_token";
29
+ export declare const TOKEN_STORAGE_KEY_REFRESH = "refresh_token";
30
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/services/auth/constants.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,eAAO,MAAM,aAAa;;;;;;;CAYhB,CAAC;AAGX,eAAO,MAAM,oCAAoC,IAAI,CAAC;AACtD,eAAO,MAAM,uBAAuB,QAAY,CAAC;AACjD,eAAO,MAAM,gBAAgB,KAAK,CAAC;AACnC,eAAO,MAAM,aAAa,KAAK,CAAC;AAGhC,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,iBAAiB,WAAW,CAAC;AAC1C,eAAO,MAAM,kBAAkB,YAAY,CAAC;AAC5C,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,gBAAgB,UAAU,CAAC;AACxC,eAAO,MAAM,cAAc,QAAQ,CAAC;AACpC,eAAO,MAAM,eAAe,SAAS,CAAC;AACtC,eAAO,MAAM,qBAAqB,MAAM,CAAC;AACzC,eAAO,MAAM,uBAAuB,MAAM,CAAC;AAC3C,eAAO,MAAM,oBAAoB,MAAM,CAAC;AAGxC,eAAO,MAAM,qBAAqB,YAAY,CAAC;AAC/C,eAAO,MAAM,qBAAqB,sBAAsB,CAAC;AAGzD,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD,eAAO,MAAM,yBAAyB,kBAAkB,CAAC"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Authentication API constants
3
+ */
4
+ // API Endpoints
5
+ export const API_ENDPOINTS = {
6
+ // Authentication
7
+ SIGNIN: '/api/signin/',
8
+ SIGNOUT: '/api/signout/',
9
+ SIGNUP: '/api/signup/',
10
+ // Verification
11
+ EMAIL_VERIFICATION: '/api/email-verification/',
12
+ RESEND_VERIFICATION: '/api/resend-verification/',
13
+ // Token management
14
+ TOKEN_REFRESH: '/api/token/refresh/',
15
+ };
16
+ // Token management constants
17
+ export const DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES = 5;
18
+ export const MILLISECONDS_PER_MINUTE = 60 * 1000;
19
+ export const MINUTES_PER_HOUR = 60;
20
+ export const HOURS_PER_DAY = 24;
21
+ // Time labels
22
+ export const TIME_LABEL_EXPIRED = 'Expired';
23
+ export const TIME_LABEL_MINUTE = 'minute';
24
+ export const TIME_LABEL_MINUTES = 'minutes';
25
+ export const TIME_LABEL_HOUR = 'hour';
26
+ export const TIME_LABEL_HOURS = 'hours';
27
+ export const TIME_LABEL_DAY = 'day';
28
+ export const TIME_LABEL_DAYS = 'days';
29
+ export const TIME_LABEL_HOUR_SHORT = 'h';
30
+ export const TIME_LABEL_MINUTE_SHORT = 'm';
31
+ export const TIME_LABEL_DAY_SHORT = 'd';
32
+ // Default values
33
+ export const DEFAULT_UNKNOWN_VALUE = 'Unknown';
34
+ export const DEFAULT_ERROR_MESSAGE = 'An error occurred';
35
+ // Storage keys
36
+ export const TOKEN_STORAGE_KEY_ACCESS = 'access_token';
37
+ export const TOKEN_STORAGE_KEY_REFRESH = 'refresh_token';
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Auth service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
7
+ export * from './utils';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/auth/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Auth service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
7
+ export * from './utils';
@@ -0,0 +1,8 @@
1
+ import type { SigninPayload, SignupPayload, EmailVerificationPayload, TokenRefreshResponse, TokenRefreshPayload } from './types';
2
+ export declare const signin: (data: SigninPayload) => Promise<import("axios").AxiosResponse<any, any>>;
3
+ export declare const signout: () => Promise<import("axios").AxiosResponse<any, any>>;
4
+ export declare const signup: (data: SignupPayload) => Promise<import("axios").AxiosResponse<any, any>>;
5
+ export declare const verifyEmail: (data: EmailVerificationPayload) => Promise<import("axios").AxiosResponse<any, any>>;
6
+ export declare const resendVerificationCode: () => Promise<import("axios").AxiosResponse<any, any>>;
7
+ export declare const refreshToken: (data: TokenRefreshPayload) => Promise<import("axios").AxiosResponse<TokenRefreshResponse, any>>;
8
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/services/auth/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,aAAa,EACb,aAAa,EACb,wBAAwB,EACxB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAGjB,eAAO,MAAM,MAAM,GAAI,MAAM,aAAa,qDAEzC,CAAC;AAEF,eAAO,MAAM,OAAO,wDAEnB,CAAC;AAEF,eAAO,MAAM,MAAM,GAAI,MAAM,aAAa,qDAEzC,CAAC;AAGF,eAAO,MAAM,WAAW,GAAI,MAAM,wBAAwB,qDAEzD,CAAC;AAEF,eAAO,MAAM,sBAAsB,wDAElC,CAAC;AAGF,eAAO,MAAM,YAAY,GAAI,MAAM,mBAAmB,sEAErD,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { webApiClient } from '../../api/apiClient';
2
+ import { API_ENDPOINTS } from './constants';
3
+ // Authentication services
4
+ export const signin = (data) => {
5
+ return webApiClient.post(API_ENDPOINTS.SIGNIN, data);
6
+ };
7
+ export const signout = () => {
8
+ return webApiClient.post(API_ENDPOINTS.SIGNOUT);
9
+ };
10
+ export const signup = (data) => {
11
+ return webApiClient.post(API_ENDPOINTS.SIGNUP, data);
12
+ };
13
+ // Email verification services
14
+ export const verifyEmail = (data) => {
15
+ return webApiClient.post(API_ENDPOINTS.EMAIL_VERIFICATION, data);
16
+ };
17
+ export const resendVerificationCode = () => {
18
+ return webApiClient.post(API_ENDPOINTS.RESEND_VERIFICATION);
19
+ };
20
+ // Token refresh services
21
+ export const refreshToken = (data) => {
22
+ return webApiClient.post(API_ENDPOINTS.TOKEN_REFRESH, data);
23
+ };
@@ -0,0 +1,38 @@
1
+ export interface SigninPayload {
2
+ email: string;
3
+ password: string;
4
+ }
5
+ export interface SignupPayload {
6
+ email: string;
7
+ password: string;
8
+ passwordConfirm: string;
9
+ }
10
+ export interface EmailVerificationPayload {
11
+ token: string;
12
+ }
13
+ export interface TokenRefreshResponse {
14
+ access: string;
15
+ refresh: string;
16
+ }
17
+ export interface TokenRefreshPayload {
18
+ refresh: string;
19
+ }
20
+ export interface TokenRefreshError {
21
+ response?: {
22
+ status: number;
23
+ data?: {
24
+ detail?: string;
25
+ message?: string;
26
+ };
27
+ };
28
+ message?: string;
29
+ }
30
+ export interface TokenInfo {
31
+ token: string | null;
32
+ payload: Record<string, unknown>;
33
+ isValid: boolean;
34
+ remainingTime: string;
35
+ isExpired: boolean;
36
+ expirationTime: Date | null;
37
+ }
38
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/auth/types.ts"],"names":[],"mappings":"AACA,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,eAAe,EAAE,MAAM,CAAC;CACzB;AAGD,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE;QACT,MAAM,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE;YACL,MAAM,CAAC,EAAE,MAAM,CAAC;YAChB,OAAO,CAAC,EAAE,MAAM,CAAC;SAClB,CAAC;KACH,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,OAAO,CAAC;IACnB,cAAc,EAAE,IAAI,GAAG,IAAI,CAAC;CAC7B"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,46 @@
1
+ import type { TokenRefreshError } from './types';
2
+ /**
3
+ * Check if a token has expired based on its expiration timestamp
4
+ */
5
+ export declare const isTokenExpired: (expiresAt: string) => boolean;
6
+ /**
7
+ * Check if a token will expire within a specified number of minutes
8
+ */
9
+ export declare const isTokenExpiringSoon: (expiresAt: string, minutesBeforeExpiry?: number) => boolean;
10
+ /**
11
+ * Get the remaining time until token expiry in minutes
12
+ */
13
+ export declare const getTimeUntilExpiry: (expiresAt: string) => number;
14
+ /**
15
+ * Format the time until expiry in a human-readable format
16
+ */
17
+ export declare const formatTimeUntilExpiry: (expiresAt: string) => string;
18
+ /**
19
+ * Parse device information from user agent string
20
+ */
21
+ export declare const parseDeviceInfo: (userAgent: string) => {
22
+ browser: string;
23
+ os: string;
24
+ };
25
+ /**
26
+ * Check if token refresh was successful
27
+ */
28
+ export declare const isRefreshSuccess: (response: {
29
+ status?: number;
30
+ data?: {
31
+ access?: string;
32
+ refresh?: string;
33
+ };
34
+ }) => boolean;
35
+ /**
36
+ * Get error message from token refresh error
37
+ */
38
+ export declare const getRefreshErrorMessage: (error: TokenRefreshError) => string;
39
+ /**
40
+ * Create an auto-refresh handler for tokens
41
+ */
42
+ export declare const createAutoRefreshHandler: (refreshCallback: () => Promise<void>, checkInterval?: number) => {
43
+ start: () => void;
44
+ stop: () => void;
45
+ };
46
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/auth/utils.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD;;GAEG;AACH,eAAO,MAAM,cAAc,GAAI,WAAW,MAAM,KAAG,OAIlD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAC9B,WAAW,MAAM,EACjB,sBAAqB,MAA6C,KACjE,OAMF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,WAAW,MAAM,KAAG,MAUtD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAI,WAAW,MAAM,KAAG,MAkBzD,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,WAAW,MAAM,KAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAwBhF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,UAAU;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC9C,KAAG,OAEH,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAI,OAAO,iBAAiB,KAAG,MAWjE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wBAAwB,GACnC,iBAAiB,MAAM,OAAO,CAAC,IAAI,CAAC,EACpC,gBAAe,MAAc;;;CAkB9B,CAAC"}
@@ -0,0 +1,113 @@
1
+ import { DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES, MILLISECONDS_PER_MINUTE, MINUTES_PER_HOUR, HOURS_PER_DAY, TIME_LABEL_EXPIRED, TIME_LABEL_MINUTE, TIME_LABEL_MINUTES, TIME_LABEL_HOUR, TIME_LABEL_HOURS, TIME_LABEL_DAY, TIME_LABEL_DAYS, DEFAULT_UNKNOWN_VALUE, DEFAULT_ERROR_MESSAGE, } from './constants';
2
+ /**
3
+ * Check if a token has expired based on its expiration timestamp
4
+ */
5
+ export const isTokenExpired = (expiresAt) => {
6
+ const expirationTime = new Date(expiresAt).getTime();
7
+ const currentTime = Date.now();
8
+ return currentTime >= expirationTime;
9
+ };
10
+ /**
11
+ * Check if a token will expire within a specified number of minutes
12
+ */
13
+ export const isTokenExpiringSoon = (expiresAt, minutesBeforeExpiry = DEFAULT_TOKEN_REFRESH_BUFFER_MINUTES) => {
14
+ const expirationTime = new Date(expiresAt).getTime();
15
+ const currentTime = Date.now();
16
+ const bufferTime = minutesBeforeExpiry * MILLISECONDS_PER_MINUTE;
17
+ return currentTime + bufferTime >= expirationTime;
18
+ };
19
+ /**
20
+ * Get the remaining time until token expiry in minutes
21
+ */
22
+ export const getTimeUntilExpiry = (expiresAt) => {
23
+ const expirationTime = new Date(expiresAt).getTime();
24
+ const currentTime = Date.now();
25
+ const remainingTime = expirationTime - currentTime;
26
+ if (remainingTime <= 0) {
27
+ return 0;
28
+ }
29
+ return Math.floor(remainingTime / MILLISECONDS_PER_MINUTE);
30
+ };
31
+ /**
32
+ * Format the time until expiry in a human-readable format
33
+ */
34
+ export const formatTimeUntilExpiry = (expiresAt) => {
35
+ const minutesRemaining = getTimeUntilExpiry(expiresAt);
36
+ if (minutesRemaining <= 0) {
37
+ return TIME_LABEL_EXPIRED;
38
+ }
39
+ if (minutesRemaining < MINUTES_PER_HOUR) {
40
+ return minutesRemaining === 1 ? `1 ${TIME_LABEL_MINUTE}` : `${minutesRemaining} ${TIME_LABEL_MINUTES}`;
41
+ }
42
+ const hoursRemaining = Math.floor(minutesRemaining / MINUTES_PER_HOUR);
43
+ if (hoursRemaining < HOURS_PER_DAY) {
44
+ return hoursRemaining === 1 ? `1 ${TIME_LABEL_HOUR}` : `${hoursRemaining} ${TIME_LABEL_HOURS}`;
45
+ }
46
+ const daysRemaining = Math.floor(hoursRemaining / HOURS_PER_DAY);
47
+ return daysRemaining === 1 ? `1 ${TIME_LABEL_DAY}` : `${daysRemaining} ${TIME_LABEL_DAYS}`;
48
+ };
49
+ /**
50
+ * Parse device information from user agent string
51
+ */
52
+ export const parseDeviceInfo = (userAgent) => {
53
+ const browser = userAgent.includes('Chrome')
54
+ ? 'Chrome'
55
+ : userAgent.includes('Firefox')
56
+ ? 'Firefox'
57
+ : userAgent.includes('Safari')
58
+ ? 'Safari'
59
+ : userAgent.includes('Edge')
60
+ ? 'Edge'
61
+ : DEFAULT_UNKNOWN_VALUE;
62
+ const os = userAgent.includes('Windows')
63
+ ? 'Windows'
64
+ : userAgent.includes('Mac')
65
+ ? 'macOS'
66
+ : userAgent.includes('Linux')
67
+ ? 'Linux'
68
+ : userAgent.includes('Android')
69
+ ? 'Android'
70
+ : userAgent.includes('iOS')
71
+ ? 'iOS'
72
+ : DEFAULT_UNKNOWN_VALUE;
73
+ return { browser, os };
74
+ };
75
+ /**
76
+ * Check if token refresh was successful
77
+ */
78
+ export const isRefreshSuccess = (response) => {
79
+ return !!(response?.status === 200 && response?.data?.access && response?.data?.refresh);
80
+ };
81
+ /**
82
+ * Get error message from token refresh error
83
+ */
84
+ export const getRefreshErrorMessage = (error) => {
85
+ if (error.response?.data?.detail) {
86
+ return error.response.data.detail;
87
+ }
88
+ if (error.response?.data?.message) {
89
+ return error.response.data.message;
90
+ }
91
+ if (error.message) {
92
+ return error.message;
93
+ }
94
+ return DEFAULT_ERROR_MESSAGE;
95
+ };
96
+ /**
97
+ * Create an auto-refresh handler for tokens
98
+ */
99
+ export const createAutoRefreshHandler = (refreshCallback, checkInterval = 60000) => {
100
+ let intervalId = null;
101
+ const start = () => {
102
+ if (intervalId)
103
+ return;
104
+ intervalId = setInterval(refreshCallback, checkInterval);
105
+ };
106
+ const stop = () => {
107
+ if (intervalId) {
108
+ clearInterval(intervalId);
109
+ intervalId = null;
110
+ }
111
+ };
112
+ return { start, stop };
113
+ };
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Portfolio-related constants for shared services.
3
+ *
4
+ * These constants should match the backend constants in bilberry/portfolios/constants.py
5
+ * to ensure consistency across the application stack.
6
+ */
7
+ export declare const INVESTMENT_HORIZON_SHORT = "short";
8
+ export declare const INVESTMENT_HORIZON_MEDIUM = "medium";
9
+ export declare const INVESTMENT_HORIZON_LONG = "long";
10
+ export declare const INVESTMENT_HORIZON_LABEL_SHORT = "Short-term (0\u20133 yrs)";
11
+ export declare const INVESTMENT_HORIZON_LABEL_MEDIUM = "Medium-term (3\u20137 yrs)";
12
+ export declare const INVESTMENT_HORIZON_LABEL_LONG = "Long-term (7+ yrs)";
13
+ export declare const INVESTMENT_HORIZON_OPTIONS: {
14
+ value: string;
15
+ label: string;
16
+ }[];
17
+ export declare const RISK_TOLERANCE_LOW = "low";
18
+ export declare const RISK_TOLERANCE_MEDIUM = "medium";
19
+ export declare const RISK_TOLERANCE_HIGH = "high";
20
+ export declare const RISK_TOLERANCE_LABEL_LOW = "Low";
21
+ export declare const RISK_TOLERANCE_LABEL_MEDIUM = "Medium";
22
+ export declare const RISK_TOLERANCE_LABEL_HIGH = "High";
23
+ export declare const RISK_TOLERANCE_OPTIONS: {
24
+ value: string;
25
+ label: string;
26
+ }[];
27
+ export declare const INVESTMENT_EXPERIENCE_NONE = "none";
28
+ export declare const INVESTMENT_EXPERIENCE_SOME = "some";
29
+ export declare const INVESTMENT_EXPERIENCE_EXTENSIVE = "extensive";
30
+ export declare const INVESTMENT_EXPERIENCE_LABEL_NONE = "No experience";
31
+ export declare const INVESTMENT_EXPERIENCE_LABEL_SOME = "Some experience";
32
+ export declare const INVESTMENT_EXPERIENCE_LABEL_EXTENSIVE = "Extensive";
33
+ export declare const INVESTMENT_EXPERIENCE_OPTIONS: {
34
+ value: string;
35
+ label: string;
36
+ }[];
37
+ export declare const API_ENDPOINTS: {
38
+ readonly PORTFOLIOS: "/api/portfolios/";
39
+ readonly PORTFOLIO_TEMPLATES: "/api/portfolio-templates/";
40
+ readonly PORTFOLIO_TEMPLATES_RECOMMENDED: "/api/portfolio-templates/recommended/";
41
+ readonly ASSET_ALLOCATIONS: "/api/asset-allocations/";
42
+ readonly ASSET_HOLDINGS: "/api/asset-holdings/";
43
+ readonly ASSET_HOLDING_SNAPSHOTS: "/api/asset-holding-snapshots/";
44
+ };
45
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/constants.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,eAAO,MAAM,wBAAwB,UAAU,CAAC;AAChD,eAAO,MAAM,yBAAyB,WAAW,CAAC;AAClD,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAG9C,eAAO,MAAM,8BAA8B,8BAAyB,CAAC;AACrE,eAAO,MAAM,+BAA+B,+BAA0B,CAAC;AACvE,eAAO,MAAM,6BAA6B,uBAAuB,CAAC;AAGlE,eAAO,MAAM,0BAA0B;;;GAItC,CAAC;AAGF,eAAO,MAAM,kBAAkB,QAAQ,CAAC;AACxC,eAAO,MAAM,qBAAqB,WAAW,CAAC;AAC9C,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAG1C,eAAO,MAAM,wBAAwB,QAAQ,CAAC;AAC9C,eAAO,MAAM,2BAA2B,WAAW,CAAC;AACpD,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAGhD,eAAO,MAAM,sBAAsB;;;GAIlC,CAAC;AAGF,eAAO,MAAM,0BAA0B,SAAS,CAAC;AACjD,eAAO,MAAM,0BAA0B,SAAS,CAAC;AACjD,eAAO,MAAM,+BAA+B,cAAc,CAAC;AAG3D,eAAO,MAAM,gCAAgC,kBAAkB,CAAC;AAChE,eAAO,MAAM,gCAAgC,oBAAoB,CAAC;AAClE,eAAO,MAAM,qCAAqC,cAAc,CAAC;AAGjE,eAAO,MAAM,6BAA6B;;;GAIzC,CAAC;AAGF,eAAO,MAAM,aAAa;;;;;;;CAOhB,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Portfolio-related constants for shared services.
3
+ *
4
+ * These constants should match the backend constants in bilberry/portfolios/constants.py
5
+ * to ensure consistency across the application stack.
6
+ */
7
+ // Investment horizon constants
8
+ export const INVESTMENT_HORIZON_SHORT = 'short';
9
+ export const INVESTMENT_HORIZON_MEDIUM = 'medium';
10
+ export const INVESTMENT_HORIZON_LONG = 'long';
11
+ // Investment horizon label constants
12
+ export const INVESTMENT_HORIZON_LABEL_SHORT = 'Short-term (0–3 yrs)';
13
+ export const INVESTMENT_HORIZON_LABEL_MEDIUM = 'Medium-term (3–7 yrs)';
14
+ export const INVESTMENT_HORIZON_LABEL_LONG = 'Long-term (7+ yrs)';
15
+ // Investment horizon options
16
+ export const INVESTMENT_HORIZON_OPTIONS = [
17
+ { value: INVESTMENT_HORIZON_SHORT, label: INVESTMENT_HORIZON_LABEL_SHORT },
18
+ { value: INVESTMENT_HORIZON_MEDIUM, label: INVESTMENT_HORIZON_LABEL_MEDIUM },
19
+ { value: INVESTMENT_HORIZON_LONG, label: INVESTMENT_HORIZON_LABEL_LONG },
20
+ ];
21
+ // Risk tolerance constants
22
+ export const RISK_TOLERANCE_LOW = 'low';
23
+ export const RISK_TOLERANCE_MEDIUM = 'medium';
24
+ export const RISK_TOLERANCE_HIGH = 'high';
25
+ // Risk tolerance label constants
26
+ export const RISK_TOLERANCE_LABEL_LOW = 'Low';
27
+ export const RISK_TOLERANCE_LABEL_MEDIUM = 'Medium';
28
+ export const RISK_TOLERANCE_LABEL_HIGH = 'High';
29
+ // Risk tolerance options
30
+ export const RISK_TOLERANCE_OPTIONS = [
31
+ { value: RISK_TOLERANCE_LOW, label: RISK_TOLERANCE_LABEL_LOW },
32
+ { value: RISK_TOLERANCE_MEDIUM, label: RISK_TOLERANCE_LABEL_MEDIUM },
33
+ { value: RISK_TOLERANCE_HIGH, label: RISK_TOLERANCE_LABEL_HIGH },
34
+ ];
35
+ // Investment experience constants
36
+ export const INVESTMENT_EXPERIENCE_NONE = 'none';
37
+ export const INVESTMENT_EXPERIENCE_SOME = 'some';
38
+ export const INVESTMENT_EXPERIENCE_EXTENSIVE = 'extensive';
39
+ // Investment experience label constants
40
+ export const INVESTMENT_EXPERIENCE_LABEL_NONE = 'No experience';
41
+ export const INVESTMENT_EXPERIENCE_LABEL_SOME = 'Some experience';
42
+ export const INVESTMENT_EXPERIENCE_LABEL_EXTENSIVE = 'Extensive';
43
+ // Investment experience options
44
+ export const INVESTMENT_EXPERIENCE_OPTIONS = [
45
+ { value: INVESTMENT_EXPERIENCE_NONE, label: INVESTMENT_EXPERIENCE_LABEL_NONE },
46
+ { value: INVESTMENT_EXPERIENCE_SOME, label: INVESTMENT_EXPERIENCE_LABEL_SOME },
47
+ { value: INVESTMENT_EXPERIENCE_EXTENSIVE, label: INVESTMENT_EXPERIENCE_LABEL_EXTENSIVE },
48
+ ];
49
+ // API Endpoints
50
+ export const API_ENDPOINTS = {
51
+ PORTFOLIOS: '/api/portfolios/',
52
+ PORTFOLIO_TEMPLATES: '/api/portfolio-templates/',
53
+ PORTFOLIO_TEMPLATES_RECOMMENDED: '/api/portfolio-templates/recommended/',
54
+ ASSET_ALLOCATIONS: '/api/asset-allocations/',
55
+ ASSET_HOLDINGS: '/api/asset-holdings/',
56
+ ASSET_HOLDING_SNAPSHOTS: '/api/asset-holding-snapshots/',
57
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Portfolios service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
7
+ export * from './utils';
8
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,aAAa,CAAC;AAC5B,cAAc,SAAS,CAAC;AACxB,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Portfolios service exports
3
+ */
4
+ export * from './constants';
5
+ export * from './types';
6
+ export * from './service';
7
+ export * from './utils';
@@ -0,0 +1,7 @@
1
+ import type { Portfolio, PaginatedPortfolios, PortfolioPayload, RebalancingTradesGenerationResponse } from './types';
2
+ export declare const getPortfolios: () => Promise<import("axios").AxiosResponse<PaginatedPortfolios, any>>;
3
+ export declare const createPortfolio: (data: PortfolioPayload) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
4
+ export declare const updatePortfolio: (uuid: string, data: Partial<PortfolioPayload>) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
5
+ export declare const getPortfolioByUuid: (uuid: string) => Promise<import("axios").AxiosResponse<Portfolio, any>>;
6
+ export declare const generateRebalancingTrades: (portfolioUuid: string) => Promise<import("axios").AxiosResponse<RebalancingTradesGenerationResponse, any>>;
7
+ //# sourceMappingURL=service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mCAAmC,EAAE,MAAM,SAAS,CAAC;AAGrH,eAAO,MAAM,aAAa,wEAEzB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,gBAAgB,2DAErD,CAAC;AAEF,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,2DAE5E,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,2DAE9C,CAAC;AAGF,eAAO,MAAM,yBAAyB,GAAI,eAAe,MAAM,qFAI9D,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { webApiClient } from '../../api/apiClient';
2
+ import { API_ENDPOINTS } from './constants';
3
+ // Portfolio CRUD operations
4
+ export const getPortfolios = () => {
5
+ return webApiClient.get(API_ENDPOINTS.PORTFOLIOS);
6
+ };
7
+ export const createPortfolio = (data) => {
8
+ return webApiClient.post(API_ENDPOINTS.PORTFOLIOS, data);
9
+ };
10
+ export const updatePortfolio = (uuid, data) => {
11
+ return webApiClient.patch(`${API_ENDPOINTS.PORTFOLIOS}${uuid}/`, data);
12
+ };
13
+ export const getPortfolioByUuid = (uuid) => {
14
+ return webApiClient.get(`${API_ENDPOINTS.PORTFOLIOS}${uuid}/`);
15
+ };
16
+ // Portfolio rebalancing operations
17
+ export const generateRebalancingTrades = (portfolioUuid) => {
18
+ return webApiClient.post(`${API_ENDPOINTS.PORTFOLIOS}${portfolioUuid}/generate-rebalancing-trades/`);
19
+ };
@@ -0,0 +1,29 @@
1
+ import type { PaginatedResponse } from '../../api/types';
2
+ export interface Portfolio {
3
+ uuid: string;
4
+ account: string;
5
+ name: string;
6
+ template: string | null;
7
+ marketValue: string;
8
+ createdAt?: string;
9
+ updatedAt?: string;
10
+ }
11
+ export type PaginatedPortfolios = PaginatedResponse<Portfolio>;
12
+ export interface PortfolioPayload {
13
+ account: string;
14
+ name: string;
15
+ template?: string | null;
16
+ }
17
+ export interface RebalancingTradesGenerationResponse {
18
+ status: string;
19
+ message: string;
20
+ tradeCount?: number;
21
+ buyTradeCount?: number;
22
+ sellTradeCount?: number;
23
+ totalTradeValue?: number;
24
+ netCashImpact?: number;
25
+ availableCash?: number;
26
+ requiredMinimum?: number;
27
+ errorType?: 'business_logic' | 'permission' | 'server';
28
+ }
29
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,mBAAmB,GAAG,iBAAiB,CAAC,SAAS,CAAC,CAAC;AAE/D,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,mCAAmC;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,gBAAgB,GAAG,YAAY,GAAG,QAAQ,CAAC;CACxD"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ export declare const formatPortfolioValue: (value: string | number) => string;
2
+ export declare const calculateTotalValue: (marketValue: string | number, cashBalance: string | number) => number;
3
+ export declare const getMarketAllocation: (marketValue: string | number, totalValue: string | number) => number;
4
+ export declare const getCashAllocation: (cashBalance: string | number, totalValue: string | number) => number;
5
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/services/portfolios/utils.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,oBAAoB,GAAI,OAAO,MAAM,GAAG,MAAM,KAAG,MAQ7D,CAAC;AAGF,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,aAAa,MAAM,GAAG,MAAM,KAAG,MAIhG,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,YAAY,MAAM,GAAG,MAAM,KAAG,MAI/F,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,aAAa,MAAM,GAAG,MAAM,EAAE,YAAY,MAAM,GAAG,MAAM,KAAG,MAI7F,CAAC"}
@@ -0,0 +1,26 @@
1
+ // Portfolio formatting utilities
2
+ export const formatPortfolioValue = (value) => {
3
+ const numValue = typeof value === 'string' ? parseFloat(value) : value;
4
+ return new Intl.NumberFormat('en-AU', {
5
+ style: 'currency',
6
+ currency: 'AUD',
7
+ minimumFractionDigits: 2,
8
+ maximumFractionDigits: 2,
9
+ }).format(numValue);
10
+ };
11
+ // Portfolio calculation utilities
12
+ export const calculateTotalValue = (marketValue, cashBalance) => {
13
+ const market = typeof marketValue === 'string' ? parseFloat(marketValue || '0') : marketValue;
14
+ const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || '0') : cashBalance;
15
+ return market + cash;
16
+ };
17
+ export const getMarketAllocation = (marketValue, totalValue) => {
18
+ const market = typeof marketValue === 'string' ? parseFloat(marketValue || '0') : marketValue;
19
+ const total = typeof totalValue === 'string' ? parseFloat(totalValue || '0') : totalValue;
20
+ return total > 0 ? (market / total) * 100 : 0;
21
+ };
22
+ export const getCashAllocation = (cashBalance, totalValue) => {
23
+ const cash = typeof cashBalance === 'string' ? parseFloat(cashBalance || '0') : cashBalance;
24
+ const total = typeof totalValue === 'string' ? parseFloat(totalValue || '0') : totalValue;
25
+ return total > 0 ? (cash / total) * 100 : 0;
26
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cranberry-money/shared-services",
3
- "version": "1.0.1",
3
+ "version": "1.2.0",
4
4
  "description": "Shared API services and client for MyPortfolio platform",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -22,7 +22,8 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@cranberry-money/shared-constants": "^1.0.1",
25
- "@cranberry-money/shared-types": "^1.0.1"
25
+ "@cranberry-money/shared-types": "^1.0.1",
26
+ "axios": "^1.7.0"
26
27
  },
27
28
  "peerDependencies": {
28
29
  "@tanstack/react-query": ">=5.0.0",