@finatic/client 0.0.142 → 0.9.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.
Files changed (64) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +39 -0
  3. package/README.md +54 -425
  4. package/dist/index.d.ts +7329 -1579
  5. package/dist/index.js +8110 -6114
  6. package/dist/index.js.map +1 -1
  7. package/dist/index.mjs +8047 -6085
  8. package/dist/index.mjs.map +1 -1
  9. package/package.json +77 -33
  10. package/dist/types/core/client/ApiClient.d.ts +0 -270
  11. package/dist/types/core/client/FinaticConnect.d.ts +0 -332
  12. package/dist/types/core/portal/PortalUI.d.ts +0 -37
  13. package/dist/types/index.d.ts +0 -12
  14. package/dist/types/lib/logger/index.d.ts +0 -2
  15. package/dist/types/lib/logger/logger.d.ts +0 -4
  16. package/dist/types/lib/logger/logger.types.d.ts +0 -28
  17. package/dist/types/mocks/MockApiClient.d.ts +0 -171
  18. package/dist/types/mocks/MockDataProvider.d.ts +0 -139
  19. package/dist/types/mocks/MockFactory.d.ts +0 -53
  20. package/dist/types/mocks/utils.d.ts +0 -24
  21. package/dist/types/themes/portalPresets.d.ts +0 -9
  22. package/dist/types/types/api/auth.d.ts +0 -93
  23. package/dist/types/types/api/broker.d.ts +0 -421
  24. package/dist/types/types/api/core.d.ts +0 -46
  25. package/dist/types/types/api/errors.d.ts +0 -31
  26. package/dist/types/types/api/orders.d.ts +0 -39
  27. package/dist/types/types/api/portfolio.d.ts +0 -55
  28. package/dist/types/types/common/pagination.d.ts +0 -33
  29. package/dist/types/types/connect.d.ts +0 -58
  30. package/dist/types/types/index.d.ts +0 -13
  31. package/dist/types/types/portal.d.ts +0 -204
  32. package/dist/types/types/ui/theme.d.ts +0 -104
  33. package/dist/types/utils/brokerUtils.d.ts +0 -30
  34. package/dist/types/utils/errors.d.ts +0 -45
  35. package/dist/types/utils/events.d.ts +0 -12
  36. package/dist/types/utils/themeUtils.d.ts +0 -34
  37. package/src/core/client/ApiClient.ts +0 -2004
  38. package/src/core/client/FinaticConnect.ts +0 -1606
  39. package/src/core/portal/PortalUI.ts +0 -335
  40. package/src/index.d.ts +0 -23
  41. package/src/index.ts +0 -100
  42. package/src/lib/logger/index.ts +0 -3
  43. package/src/lib/logger/logger.ts +0 -332
  44. package/src/lib/logger/logger.types.ts +0 -34
  45. package/src/mocks/MockApiClient.ts +0 -1058
  46. package/src/mocks/MockDataProvider.ts +0 -986
  47. package/src/mocks/MockFactory.ts +0 -97
  48. package/src/mocks/utils.ts +0 -133
  49. package/src/themes/portalPresets.ts +0 -1307
  50. package/src/types/api/auth.ts +0 -112
  51. package/src/types/api/broker.ts +0 -461
  52. package/src/types/api/core.ts +0 -53
  53. package/src/types/api/errors.ts +0 -35
  54. package/src/types/api/orders.ts +0 -45
  55. package/src/types/api/portfolio.ts +0 -59
  56. package/src/types/common/pagination.ts +0 -164
  57. package/src/types/connect.ts +0 -56
  58. package/src/types/index.ts +0 -25
  59. package/src/types/portal.ts +0 -214
  60. package/src/types/ui/theme.ts +0 -105
  61. package/src/utils/brokerUtils.ts +0 -104
  62. package/src/utils/errors.ts +0 -104
  63. package/src/utils/events.ts +0 -66
  64. package/src/utils/themeUtils.ts +0 -165
@@ -1,104 +0,0 @@
1
- /**
2
- * Broker filtering utility functions
3
- */
4
-
5
- import { setupLogger, buildLoggerExtra, LoggerExtra } from '../lib/logger';
6
-
7
- const brokerLogger = setupLogger('FinaticClientSDK.BrokerUtils', undefined, {
8
- codebase: 'FinaticClientSDK',
9
- });
10
-
11
- const buildBrokerExtra = (functionName: string, metadata?: Record<string, unknown>): LoggerExtra => ({
12
- module: 'BrokerUtils',
13
- function: functionName,
14
- ...(metadata ? buildLoggerExtra(metadata) : {}),
15
- });
16
-
17
- // Supported broker names and their corresponding IDs (including aliases)
18
- const SUPPORTED_BROKERS: Record<string, string> = {
19
- 'alpaca': 'alpaca',
20
- 'robinhood': 'robinhood',
21
- 'tasty_trade': 'tasty_trade',
22
- 'ninja_trader': 'ninja_trader',
23
- 'tradovate': 'tradovate', // Alias for ninja_trader
24
- 'interactive_brokers': 'interactive_brokers',
25
- };
26
-
27
- /**
28
- * Convert broker names to broker IDs, filtering out unsupported ones
29
- * @param brokerNames Array of broker names to convert
30
- * @returns Object containing valid broker IDs and any warnings about unsupported names
31
- */
32
- export function convertBrokerNamesToIds(brokerNames: string[]): {
33
- brokerIds: string[];
34
- warnings: string[];
35
- } {
36
- const brokerIds: string[] = [];
37
- const warnings: string[] = [];
38
-
39
- for (const brokerName of brokerNames) {
40
- const brokerId = SUPPORTED_BROKERS[brokerName.toLowerCase()];
41
- if (brokerId) {
42
- brokerIds.push(brokerId);
43
- } else {
44
- warnings.push(`Broker name '${brokerName}' is not supported. Supported brokers: ${Object.keys(SUPPORTED_BROKERS).join(', ')}`);
45
- }
46
- }
47
-
48
- return { brokerIds, warnings };
49
- }
50
-
51
- /**
52
- * Append broker filter parameters to a portal URL
53
- * @param baseUrl The base portal URL (may already have query parameters)
54
- * @param brokerNames Array of broker names to filter by
55
- * @returns The portal URL with broker filter parameters appended
56
- */
57
- export function appendBrokerFilterToURL(baseUrl: string, brokerNames?: string[]): string {
58
- if (!brokerNames || brokerNames.length === 0) {
59
- return baseUrl;
60
- }
61
-
62
- try {
63
- const url = new URL(baseUrl);
64
- const { brokerIds, warnings } = convertBrokerNamesToIds(brokerNames);
65
-
66
- // Log warnings for unsupported broker names
67
- warnings.forEach(warning =>
68
- brokerLogger.warn('Unsupported broker name provided', buildBrokerExtra('appendBrokerFilterToURL', {
69
- warning,
70
- })),
71
- );
72
-
73
- // Only add broker filter if we have valid broker IDs
74
- if (brokerIds.length > 0) {
75
- const encodedBrokers = btoa(JSON.stringify(brokerIds));
76
- url.searchParams.set('brokers', encodedBrokers);
77
- }
78
-
79
- return url.toString();
80
- } catch (error) {
81
- brokerLogger.exception('Failed to append broker filter to URL', error, buildBrokerExtra('appendBrokerFilterToURL', {
82
- base_url: baseUrl,
83
- brokers_count: brokerNames?.length ?? 0,
84
- }));
85
- return baseUrl;
86
- }
87
- }
88
-
89
- /**
90
- * Get list of supported broker names
91
- * @returns Array of supported broker names
92
- */
93
- export function getSupportedBrokerNames(): string[] {
94
- return Object.keys(SUPPORTED_BROKERS);
95
- }
96
-
97
- /**
98
- * Check if a broker name is supported
99
- * @param brokerName The broker name to check
100
- * @returns True if the broker is supported, false otherwise
101
- */
102
- export function isBrokerSupported(brokerName: string): boolean {
103
- return brokerName.toLowerCase() in SUPPORTED_BROKERS;
104
- }
@@ -1,104 +0,0 @@
1
- export class BaseError extends Error {
2
- constructor(
3
- message: string,
4
- public readonly code: string = 'UNKNOWN_ERROR'
5
- ) {
6
- super(message);
7
- this.name = this.constructor.name;
8
- }
9
- }
10
-
11
- export class ApiError extends BaseError {
12
- constructor(
13
- public readonly status: number,
14
- message: string,
15
- public readonly details?: Record<string, any>
16
- ) {
17
- super(message, `API_ERROR_${status}`);
18
- this.name = 'ApiError';
19
- }
20
- }
21
-
22
- export class SessionError extends ApiError {
23
- constructor(message: string, details?: Record<string, any>) {
24
- super(400, message, details);
25
- this.name = 'SessionError';
26
- }
27
- }
28
-
29
- export class AuthenticationError extends ApiError {
30
- constructor(message: string, details?: Record<string, any>) {
31
- super(401, message, details);
32
- this.name = 'AuthenticationError';
33
- }
34
- }
35
-
36
- export class AuthorizationError extends ApiError {
37
- constructor(message: string, details?: Record<string, any>) {
38
- super(403, message, details);
39
- this.name = 'AuthorizationError';
40
- }
41
- }
42
-
43
- export class RateLimitError extends ApiError {
44
- constructor(message: string, details?: Record<string, any>) {
45
- super(429, message, details);
46
- this.name = 'RateLimitError';
47
- }
48
- }
49
-
50
- export class TokenError extends BaseError {
51
- constructor(message: string) {
52
- super(message, 'TOKEN_ERROR');
53
- this.name = 'TokenError';
54
- }
55
- }
56
-
57
- export class ValidationError extends BaseError {
58
- constructor(message: string) {
59
- super(message, 'VALIDATION_ERROR');
60
- this.name = 'ValidationError';
61
- }
62
- }
63
-
64
- export class NetworkError extends BaseError {
65
- constructor(message: string) {
66
- super(message, 'NETWORK_ERROR');
67
- this.name = 'NetworkError';
68
- }
69
- }
70
-
71
- export class SecurityError extends BaseError {
72
- constructor(message: string) {
73
- super(message, 'SECURITY_ERROR');
74
- this.name = 'SecurityError';
75
- }
76
- }
77
-
78
- export class CompanyAccessError extends ApiError {
79
- constructor(message: string, details?: Record<string, any>) {
80
- super(403, message, details);
81
- this.name = 'CompanyAccessError';
82
- }
83
- }
84
-
85
- export class OrderError extends ApiError {
86
- constructor(message: string, details?: Record<string, any>) {
87
- super(500, message, details);
88
- this.name = 'OrderError';
89
- }
90
- }
91
-
92
- export class OrderValidationError extends ApiError {
93
- constructor(message: string, details?: Record<string, any>) {
94
- super(400, message, details);
95
- this.name = 'OrderValidationError';
96
- }
97
- }
98
-
99
- export class TradingNotEnabledError extends ApiError {
100
- constructor(message: string, details?: Record<string, any>) {
101
- super(403, message, details);
102
- this.name = 'TradingNotEnabledError';
103
- }
104
- }
@@ -1,66 +0,0 @@
1
- import { setupLogger, buildLoggerExtra } from '../lib/logger';
2
-
3
- type EventCallback = (...args: any[]) => void;
4
-
5
- const eventsLogger = setupLogger('FinaticClientSDK.Events', undefined, {
6
- codebase: 'FinaticClientSDK',
7
- });
8
-
9
- export class EventEmitter {
10
- private events: Map<string, Set<EventCallback>> = new Map();
11
-
12
- public on(event: string, callback: EventCallback): void {
13
- if (!this.events.has(event)) {
14
- this.events.set(event, new Set());
15
- }
16
- this.events.get(event)!.add(callback);
17
- }
18
-
19
- public off(event: string, callback: EventCallback): void {
20
- if (this.events.has(event)) {
21
- this.events.get(event)!.delete(callback);
22
- }
23
- }
24
-
25
- public once(event: string, callback: EventCallback): void {
26
- const onceCallback = (...args: any[]) => {
27
- callback(...args);
28
- this.off(event, onceCallback);
29
- };
30
- this.on(event, onceCallback);
31
- }
32
-
33
- public emit(event: string, ...args: any[]): void {
34
- if (this.events.has(event)) {
35
- this.events.get(event)!.forEach(callback => {
36
- try {
37
- callback(...args);
38
- } catch (error) {
39
- eventsLogger.exception('Error in event handler', error, {
40
- module: 'EventEmitter',
41
- function: 'emit',
42
- ...buildLoggerExtra({
43
- event_name: event,
44
- }),
45
- });
46
- }
47
- });
48
- }
49
- }
50
-
51
- public removeAllListeners(event?: string): void {
52
- if (event) {
53
- this.events.delete(event);
54
- } else {
55
- this.events.clear();
56
- }
57
- }
58
-
59
- public listenerCount(event: string): number {
60
- return this.events.get(event)?.size || 0;
61
- }
62
-
63
- public listeners(event: string): EventCallback[] {
64
- return Array.from(this.events.get(event) || []);
65
- }
66
- }
@@ -1,165 +0,0 @@
1
- import { PortalTheme, PortalThemeConfig } from '../types/portal';
2
- import { portalThemePresets } from '../themes/portalPresets';
3
- import { setupLogger, buildLoggerExtra, LoggerExtra } from '../lib/logger';
4
-
5
- const themeLogger = setupLogger('FinaticClientSDK.ThemeUtils', undefined, {
6
- codebase: 'FinaticClientSDK',
7
- });
8
-
9
- const buildThemeExtra = (functionName: string, metadata?: Record<string, unknown>): LoggerExtra => ({
10
- module: 'ThemeUtils',
11
- function: functionName,
12
- ...(metadata ? buildLoggerExtra(metadata) : {}),
13
- });
14
-
15
- /**
16
- * Generate a portal URL with theme parameters
17
- * @param baseUrl The base portal URL
18
- * @param theme The theme configuration
19
- * @returns The portal URL with theme parameters
20
- */
21
- export function generatePortalThemeURL(baseUrl: string, theme?: PortalTheme): string {
22
- if (!theme) {
23
- return baseUrl;
24
- }
25
-
26
- try {
27
- const url = new URL(baseUrl);
28
-
29
- if (theme.preset) {
30
- // Use preset theme
31
- url.searchParams.set('theme', theme.preset);
32
- } else if (theme.custom) {
33
- // Use custom theme
34
- const encodedTheme = btoa(JSON.stringify(theme.custom));
35
- url.searchParams.set('theme', 'custom');
36
- url.searchParams.set('themeObject', encodedTheme);
37
- }
38
-
39
- return url.toString();
40
- } catch (error) {
41
- themeLogger.exception('Failed to generate theme URL', error, buildThemeExtra('generatePortalThemeURL', {
42
- base_url: baseUrl,
43
- has_theme: Boolean(theme),
44
- }));
45
- return baseUrl;
46
- }
47
- }
48
-
49
- /**
50
- * Generate a portal URL with theme parameters, appending to existing query params
51
- * @param baseUrl The base portal URL (may already have query parameters)
52
- * @param theme The theme configuration
53
- * @returns The portal URL with theme parameters appended
54
- */
55
- export function appendThemeToURL(baseUrl: string, theme?: PortalTheme): string {
56
- if (!theme) {
57
- return baseUrl;
58
- }
59
-
60
- try {
61
- const url = new URL(baseUrl);
62
-
63
- if (theme.preset) {
64
- // Use preset theme
65
- url.searchParams.set('theme', theme.preset);
66
- } else if (theme.custom) {
67
- // Use custom theme
68
- const encodedTheme = btoa(JSON.stringify(theme.custom));
69
- url.searchParams.set('theme', 'custom');
70
- url.searchParams.set('themeObject', encodedTheme);
71
- }
72
-
73
- return url.toString();
74
- } catch (error) {
75
- themeLogger.exception('Failed to append theme to URL', error, buildThemeExtra('appendThemeToURL', {
76
- base_url: baseUrl,
77
- has_theme: Boolean(theme),
78
- }));
79
- return baseUrl;
80
- }
81
- }
82
-
83
- /**
84
- * Get a theme configuration by preset name
85
- * @param preset The preset theme name
86
- * @returns The theme configuration or undefined if not found
87
- */
88
- export function getThemePreset(preset: string): PortalThemeConfig | undefined {
89
- return portalThemePresets[preset];
90
- }
91
-
92
- /**
93
- * Validate a custom theme configuration
94
- * @param theme The theme configuration to validate
95
- * @returns True if valid, false otherwise
96
- */
97
- export function validateCustomTheme(theme: PortalThemeConfig): boolean {
98
- try {
99
- // Only validate what's provided - everything else gets defaults
100
- if (theme.mode && !['dark', 'light', 'auto'].includes(theme.mode)) {
101
- return false;
102
- }
103
-
104
- // If colors are provided, validate the structure
105
- if (theme.colors) {
106
- // Check that any provided color sections have valid structure
107
- const colorSections = ['background', 'status', 'text', 'border', 'input', 'button'];
108
- for (const section of colorSections) {
109
- const colorSection = theme.colors[section as keyof typeof theme.colors];
110
- if (colorSection && typeof colorSection !== 'object') {
111
- return false;
112
- }
113
- }
114
- }
115
-
116
- // If typography is provided, validate structure
117
- if (theme.typography) {
118
- if (theme.typography.fontSize && typeof theme.typography.fontSize !== 'object') {
119
- return false;
120
- }
121
- if (theme.typography.fontWeight && typeof theme.typography.fontWeight !== 'object') {
122
- return false;
123
- }
124
- }
125
-
126
- // If effects are provided, validate structure
127
- if (theme.effects) {
128
- if (theme.effects.animations && typeof theme.effects.animations !== 'object') {
129
- return false;
130
- }
131
- if (theme.effects.shadows && typeof theme.effects.shadows !== 'object') {
132
- return false;
133
- }
134
- }
135
-
136
- return true;
137
- } catch (error) {
138
- themeLogger.exception('Theme validation error', error, buildThemeExtra('validateCustomTheme'));
139
- return false;
140
- }
141
- }
142
-
143
- /**
144
- * Create a custom theme from a preset with modifications
145
- * @param preset The base preset theme
146
- * @param modifications Partial theme modifications
147
- * @returns The modified theme configuration
148
- */
149
- export function createCustomThemeFromPreset(
150
- preset: string,
151
- modifications: Partial<PortalThemeConfig>
152
- ): PortalThemeConfig | null {
153
- const baseTheme = getThemePreset(preset);
154
- if (!baseTheme) {
155
- themeLogger.warn('Preset theme not found', buildThemeExtra('createCustomThemeFromPreset', {
156
- preset,
157
- }));
158
- return null;
159
- }
160
-
161
- return {
162
- ...baseTheme,
163
- ...modifications,
164
- };
165
- }