@fin.cx/opendata 3.0.0 → 3.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.
@@ -3,7 +3,7 @@
3
3
  */
4
4
  export const commitinfo = {
5
5
  name: '@fin.cx/opendata',
6
- version: '3.0.0',
6
+ version: '3.2.0',
7
7
  description: 'A comprehensive TypeScript library for accessing business data and real-time financial information. Features include German company data management with MongoDB integration, JSONL bulk processing, automated Handelsregister interactions, and real-time stock market data from multiple providers.'
8
8
  };
9
9
  //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSxrQkFBa0I7SUFDeEIsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHVTQUF1UztDQUNyVCxDQUFBIn0=
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Base provider entry for tracking provider state
3
+ */
4
+ export interface IBaseProviderEntry<TProvider> {
5
+ provider: TProvider;
6
+ config: IBaseProviderConfig;
7
+ lastError?: Error;
8
+ lastErrorTime?: Date;
9
+ successCount: number;
10
+ errorCount: number;
11
+ }
12
+ /**
13
+ * Base provider configuration
14
+ */
15
+ export interface IBaseProviderConfig {
16
+ enabled: boolean;
17
+ priority: number;
18
+ timeout?: number;
19
+ retryAttempts?: number;
20
+ retryDelay?: number;
21
+ cacheTTL?: number;
22
+ }
23
+ /**
24
+ * Base provider interface
25
+ */
26
+ export interface IBaseProvider {
27
+ name: string;
28
+ priority: number;
29
+ isAvailable(): Promise<boolean>;
30
+ readonly requiresAuth: boolean;
31
+ readonly rateLimit?: {
32
+ requestsPerMinute: number;
33
+ requestsPerDay?: number;
34
+ };
35
+ }
36
+ /**
37
+ * Cache entry for any data type
38
+ */
39
+ export interface IBaseCacheEntry<TData> {
40
+ data: TData;
41
+ timestamp: Date;
42
+ ttl: number;
43
+ }
44
+ /**
45
+ * Base service for managing data providers with caching
46
+ * Shared logic extracted from StockPriceService and FundamentalsService
47
+ */
48
+ export declare abstract class BaseProviderService<TProvider extends IBaseProvider, TData> {
49
+ protected providers: Map<string, IBaseProviderEntry<TProvider>>;
50
+ protected cache: Map<string, IBaseCacheEntry<TData>>;
51
+ protected logger: Console;
52
+ protected cacheConfig: {
53
+ ttl: number;
54
+ maxEntries: number;
55
+ };
56
+ constructor(cacheConfig?: {
57
+ ttl?: number;
58
+ maxEntries?: number;
59
+ });
60
+ /**
61
+ * Register a provider
62
+ */
63
+ register(provider: TProvider, config?: Partial<IBaseProviderConfig>): void;
64
+ /**
65
+ * Unregister a provider
66
+ */
67
+ unregister(providerName: string): void;
68
+ /**
69
+ * Get a specific provider by name
70
+ */
71
+ getProvider(name: string): TProvider | undefined;
72
+ /**
73
+ * Get all registered providers
74
+ */
75
+ getAllProviders(): TProvider[];
76
+ /**
77
+ * Get enabled providers sorted by priority
78
+ */
79
+ getEnabledProviders(): TProvider[];
80
+ /**
81
+ * Check health of all providers
82
+ */
83
+ checkProvidersHealth(): Promise<Map<string, boolean>>;
84
+ /**
85
+ * Get provider statistics
86
+ */
87
+ getProviderStats(): Map<string, {
88
+ successCount: number;
89
+ errorCount: number;
90
+ lastError?: string;
91
+ lastErrorTime?: Date;
92
+ }>;
93
+ /**
94
+ * Clear all cached data
95
+ */
96
+ clearCache(): void;
97
+ /**
98
+ * Set cache TTL
99
+ */
100
+ setCacheTTL(ttl: number): void;
101
+ /**
102
+ * Get cache statistics
103
+ */
104
+ getCacheStats(): {
105
+ size: number;
106
+ maxEntries: number;
107
+ ttl: number;
108
+ };
109
+ /**
110
+ * Fetch with retry logic
111
+ */
112
+ protected fetchWithRetry<T>(fetchFn: () => Promise<T>, config: IBaseProviderConfig): Promise<T>;
113
+ /**
114
+ * Get from cache if not expired
115
+ */
116
+ protected getFromCache(key: string): TData | null;
117
+ /**
118
+ * Add to cache with TTL
119
+ */
120
+ protected addToCache(key: string, data: TData, ttl?: number): void;
121
+ /**
122
+ * Track successful fetch for provider
123
+ */
124
+ protected trackSuccess(providerName: string): void;
125
+ /**
126
+ * Track failed fetch for provider
127
+ */
128
+ protected trackError(providerName: string, error: Error): void;
129
+ }
@@ -0,0 +1,204 @@
1
+ import * as plugins from '../plugins.js';
2
+ /**
3
+ * Base service for managing data providers with caching
4
+ * Shared logic extracted from StockPriceService and FundamentalsService
5
+ */
6
+ export class BaseProviderService {
7
+ constructor(cacheConfig) {
8
+ this.providers = new Map();
9
+ this.cache = new Map();
10
+ this.logger = console;
11
+ this.cacheConfig = {
12
+ ttl: 60000, // Default 60 seconds
13
+ maxEntries: 10000
14
+ };
15
+ if (cacheConfig) {
16
+ this.cacheConfig = { ...this.cacheConfig, ...cacheConfig };
17
+ }
18
+ }
19
+ /**
20
+ * Register a provider
21
+ */
22
+ register(provider, config) {
23
+ const defaultConfig = {
24
+ enabled: true,
25
+ priority: provider.priority,
26
+ timeout: 30000,
27
+ retryAttempts: 2,
28
+ retryDelay: 1000,
29
+ cacheTTL: this.cacheConfig.ttl
30
+ };
31
+ const mergedConfig = { ...defaultConfig, ...config };
32
+ this.providers.set(provider.name, {
33
+ provider,
34
+ config: mergedConfig,
35
+ successCount: 0,
36
+ errorCount: 0
37
+ });
38
+ console.log(`Registered provider: ${provider.name}`);
39
+ }
40
+ /**
41
+ * Unregister a provider
42
+ */
43
+ unregister(providerName) {
44
+ this.providers.delete(providerName);
45
+ console.log(`Unregistered provider: ${providerName}`);
46
+ }
47
+ /**
48
+ * Get a specific provider by name
49
+ */
50
+ getProvider(name) {
51
+ return this.providers.get(name)?.provider;
52
+ }
53
+ /**
54
+ * Get all registered providers
55
+ */
56
+ getAllProviders() {
57
+ return Array.from(this.providers.values()).map(entry => entry.provider);
58
+ }
59
+ /**
60
+ * Get enabled providers sorted by priority
61
+ */
62
+ getEnabledProviders() {
63
+ return Array.from(this.providers.values())
64
+ .filter(entry => entry.config.enabled)
65
+ .sort((a, b) => (b.config.priority || 0) - (a.config.priority || 0))
66
+ .map(entry => entry.provider);
67
+ }
68
+ /**
69
+ * Check health of all providers
70
+ */
71
+ async checkProvidersHealth() {
72
+ const health = new Map();
73
+ for (const [name, entry] of this.providers) {
74
+ if (!entry.config.enabled) {
75
+ health.set(name, false);
76
+ continue;
77
+ }
78
+ try {
79
+ const isAvailable = await entry.provider.isAvailable();
80
+ health.set(name, isAvailable);
81
+ }
82
+ catch (error) {
83
+ health.set(name, false);
84
+ console.error(`Health check failed for ${name}:`, error);
85
+ }
86
+ }
87
+ return health;
88
+ }
89
+ /**
90
+ * Get provider statistics
91
+ */
92
+ getProviderStats() {
93
+ const stats = new Map();
94
+ for (const [name, entry] of this.providers) {
95
+ stats.set(name, {
96
+ successCount: entry.successCount,
97
+ errorCount: entry.errorCount,
98
+ lastError: entry.lastError?.message,
99
+ lastErrorTime: entry.lastErrorTime
100
+ });
101
+ }
102
+ return stats;
103
+ }
104
+ /**
105
+ * Clear all cached data
106
+ */
107
+ clearCache() {
108
+ this.cache.clear();
109
+ console.log('Cache cleared');
110
+ }
111
+ /**
112
+ * Set cache TTL
113
+ */
114
+ setCacheTTL(ttl) {
115
+ this.cacheConfig.ttl = ttl;
116
+ console.log(`Cache TTL set to ${ttl}ms`);
117
+ }
118
+ /**
119
+ * Get cache statistics
120
+ */
121
+ getCacheStats() {
122
+ return {
123
+ size: this.cache.size,
124
+ maxEntries: this.cacheConfig.maxEntries,
125
+ ttl: this.cacheConfig.ttl
126
+ };
127
+ }
128
+ /**
129
+ * Fetch with retry logic
130
+ */
131
+ async fetchWithRetry(fetchFn, config) {
132
+ const maxAttempts = config.retryAttempts || 1;
133
+ let lastError;
134
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
135
+ try {
136
+ return await fetchFn();
137
+ }
138
+ catch (error) {
139
+ lastError = error;
140
+ if (attempt < maxAttempts) {
141
+ const delay = (config.retryDelay || 1000) * attempt;
142
+ console.log(`Retry attempt ${attempt} after ${delay}ms`);
143
+ await plugins.smartdelay.delayFor(delay);
144
+ }
145
+ }
146
+ }
147
+ throw lastError || new Error('Unknown error during fetch');
148
+ }
149
+ /**
150
+ * Get from cache if not expired
151
+ */
152
+ getFromCache(key) {
153
+ const entry = this.cache.get(key);
154
+ if (!entry) {
155
+ return null;
156
+ }
157
+ // Check if cache entry has expired
158
+ const age = Date.now() - entry.timestamp.getTime();
159
+ if (entry.ttl !== Infinity && age > entry.ttl) {
160
+ this.cache.delete(key);
161
+ return null;
162
+ }
163
+ return entry.data;
164
+ }
165
+ /**
166
+ * Add to cache with TTL
167
+ */
168
+ addToCache(key, data, ttl) {
169
+ // Enforce max entries limit
170
+ if (this.cache.size >= this.cacheConfig.maxEntries) {
171
+ // Remove oldest entry
172
+ const oldestKey = this.cache.keys().next().value;
173
+ if (oldestKey) {
174
+ this.cache.delete(oldestKey);
175
+ }
176
+ }
177
+ this.cache.set(key, {
178
+ data,
179
+ timestamp: new Date(),
180
+ ttl: ttl || this.cacheConfig.ttl
181
+ });
182
+ }
183
+ /**
184
+ * Track successful fetch for provider
185
+ */
186
+ trackSuccess(providerName) {
187
+ const entry = this.providers.get(providerName);
188
+ if (entry) {
189
+ entry.successCount++;
190
+ }
191
+ }
192
+ /**
193
+ * Track failed fetch for provider
194
+ */
195
+ trackError(providerName, error) {
196
+ const entry = this.providers.get(providerName);
197
+ if (entry) {
198
+ entry.errorCount++;
199
+ entry.lastError = error;
200
+ entry.lastErrorTime = new Date();
201
+ }
202
+ }
203
+ }
204
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5iYXNlcHJvdmlkZXJzZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vdHMvc3RvY2tzL2NsYXNzZXMuYmFzZXByb3ZpZGVyc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQWlEekM7OztHQUdHO0FBQ0gsTUFBTSxPQUFnQixtQkFBbUI7SUFVdkMsWUFBWSxXQUFtRDtRQVRyRCxjQUFTLEdBQUcsSUFBSSxHQUFHLEVBQXlDLENBQUM7UUFDN0QsVUFBSyxHQUFHLElBQUksR0FBRyxFQUFrQyxDQUFDO1FBQ2xELFdBQU0sR0FBRyxPQUFPLENBQUM7UUFFakIsZ0JBQVcsR0FBRztZQUN0QixHQUFHLEVBQUUsS0FBSyxFQUFFLHFCQUFxQjtZQUNqQyxVQUFVLEVBQUUsS0FBSztTQUNsQixDQUFDO1FBR0EsSUFBSSxXQUFXLEVBQUUsQ0FBQztZQUNoQixJQUFJLENBQUMsV0FBVyxHQUFHLEVBQUUsR0FBRyxJQUFJLENBQUMsV0FBVyxFQUFFLEdBQUcsV0FBVyxFQUFFLENBQUM7UUFDN0QsQ0FBQztJQUNILENBQUM7SUFFRDs7T0FFRztJQUNJLFFBQVEsQ0FBQyxRQUFtQixFQUFFLE1BQXFDO1FBQ3hFLE1BQU0sYUFBYSxHQUF3QjtZQUN6QyxPQUFPLEVBQUUsSUFBSTtZQUNiLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTtZQUMzQixPQUFPLEVBQUUsS0FBSztZQUNkLGFBQWEsRUFBRSxDQUFDO1lBQ2hCLFVBQVUsRUFBRSxJQUFJO1lBQ2hCLFFBQVEsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLEdBQUc7U0FDL0IsQ0FBQztRQUVGLE1BQU0sWUFBWSxHQUFHLEVBQUUsR0FBRyxhQUFhLEVBQUUsR0FBRyxNQUFNLEVBQUUsQ0FBQztRQUVyRCxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFO1lBQ2hDLFFB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
@@ -0,0 +1,104 @@
1
+ import type { IFundamentalsProvider, IFundamentalsProviderConfig, IFundamentalsProviderRegistry, IStockFundamentals, IFundamentalsRequest } from './interfaces/fundamentals.js';
2
+ /**
3
+ * Service for managing fundamental data providers and caching
4
+ * Parallel to StockPriceService but for fundamental data instead of prices
5
+ */
6
+ export declare class FundamentalsService implements IFundamentalsProviderRegistry {
7
+ private providers;
8
+ private cache;
9
+ private logger;
10
+ private cacheConfig;
11
+ constructor(cacheConfig?: {
12
+ ttl?: number;
13
+ maxEntries?: number;
14
+ });
15
+ /**
16
+ * Register a fundamentals provider
17
+ */
18
+ register(provider: IFundamentalsProvider, config?: IFundamentalsProviderConfig): void;
19
+ /**
20
+ * Unregister a provider
21
+ */
22
+ unregister(providerName: string): void;
23
+ /**
24
+ * Get a specific provider by name
25
+ */
26
+ getProvider(name: string): IFundamentalsProvider | undefined;
27
+ /**
28
+ * Get all registered providers
29
+ */
30
+ getAllProviders(): IFundamentalsProvider[];
31
+ /**
32
+ * Get enabled providers sorted by priority
33
+ */
34
+ getEnabledProviders(): IFundamentalsProvider[];
35
+ /**
36
+ * Get fundamental data for a single ticker
37
+ */
38
+ getFundamentals(ticker: string): Promise<IStockFundamentals>;
39
+ /**
40
+ * Get fundamental data for multiple tickers
41
+ */
42
+ getBatchFundamentals(tickers: string[]): Promise<IStockFundamentals[]>;
43
+ /**
44
+ * Unified data fetching method
45
+ */
46
+ getData(request: IFundamentalsRequest): Promise<IStockFundamentals | IStockFundamentals[]>;
47
+ /**
48
+ * Enrich fundamentals with calculated metrics using current price
49
+ */
50
+ enrichWithPrice(fundamentals: IStockFundamentals, price: number): Promise<IStockFundamentals>;
51
+ /**
52
+ * Enrich batch fundamentals with prices
53
+ */
54
+ enrichBatchWithPrices(fundamentalsList: IStockFundamentals[], priceMap: Map<string, number>): Promise<IStockFundamentals[]>;
55
+ /**
56
+ * Check health of all providers
57
+ */
58
+ checkProvidersHealth(): Promise<Map<string, boolean>>;
59
+ /**
60
+ * Get provider statistics
61
+ */
62
+ getProviderStats(): Map<string, {
63
+ successCount: number;
64
+ errorCount: number;
65
+ lastError?: string;
66
+ lastErrorTime?: Date;
67
+ }>;
68
+ /**
69
+ * Clear all cached data
70
+ */
71
+ clearCache(): void;
72
+ /**
73
+ * Set cache TTL
74
+ */
75
+ setCacheTTL(ttl: number): void;
76
+ /**
77
+ * Get cache statistics
78
+ */
79
+ getCacheStats(): {
80
+ size: number;
81
+ maxEntries: number;
82
+ ttl: number;
83
+ };
84
+ /**
85
+ * Fetch with retry logic
86
+ */
87
+ private fetchWithRetry;
88
+ /**
89
+ * Generate cache key for request
90
+ */
91
+ private getCacheKey;
92
+ /**
93
+ * Get from cache if not expired
94
+ */
95
+ private getFromCache;
96
+ /**
97
+ * Add to cache with TTL
98
+ */
99
+ private addToCache;
100
+ /**
101
+ * Get human-readable request description
102
+ */
103
+ private getRequestDescription;
104
+ }