bulltrackers-module 1.0.644 → 1.0.646

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.
@@ -231,7 +231,8 @@ function buildManifest(productLinesToRun = [], calculations) {
231
231
  const manifestEntry = {
232
232
  name: normalizedName,
233
233
  class: Class,
234
- category: folderName === 'core' && metadata.category ? metadata.category : folderName,
234
+ // [CHANGED] Strictly use the folderName as the category.
235
+ category: folderName,
235
236
  sourcePackage: folderName,
236
237
  type: metadata.type,
237
238
  isPage: metadata.isPage === true,
@@ -84,6 +84,9 @@ class CachedDataLoader {
84
84
 
85
85
  async loadInsights(dateStr) {
86
86
  if (this.cache.insights.has(dateStr)) return this.cache.insights.get(dateStr);
87
+ const collectionName = this.config.insightsCollectionName || 'daily_instrument_insights';
88
+ const path = `${collectionName}/${dateStr}`;
89
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'insights' from: ${path}`);
87
90
  const promise = loadDailyInsights(this.config, this.deps, dateStr);
88
91
  this.cache.insights.set(dateStr, promise);
89
92
  return promise;
@@ -91,6 +94,9 @@ class CachedDataLoader {
91
94
 
92
95
  async loadSocial(dateStr) {
93
96
  if (this.cache.social.has(dateStr)) return this.cache.social.get(dateStr);
97
+ const collectionName = this.config.socialInsightsCollection || 'daily_social_insights';
98
+ const path = `${collectionName}/${dateStr}`;
99
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'social' from: ${path}`);
94
100
  const promise = loadDailySocialPostInsights(this.config, this.deps, dateStr);
95
101
  this.cache.social.set(dateStr, promise);
96
102
  return promise;
@@ -98,6 +104,9 @@ class CachedDataLoader {
98
104
 
99
105
  async loadVerifications() {
100
106
  if (this.cache.verifications) return this.cache.verifications;
107
+ const collectionName = this.config.verificationsCollection || 'verification_profiles';
108
+ const path = `${collectionName}`;
109
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'verifications' from: ${path}`);
101
110
  const verifications = await loadVerificationProfiles(this.config, this.deps);
102
111
  this.cache.verifications = verifications;
103
112
  return verifications;
@@ -105,6 +114,9 @@ class CachedDataLoader {
105
114
 
106
115
  async loadRankings(dateStr) {
107
116
  if (this.cache.rankings.has(dateStr)) return this.cache.rankings.get(dateStr);
117
+ const collectionName = this.config.popularInvestorRankingsCollection || 'popular_investor_rankings';
118
+ const path = `${collectionName}/${dateStr}`;
119
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'rankings' from: ${path}`);
108
120
  const promise = loadPopularInvestorRankings(this.config, this.deps, dateStr);
109
121
  this.cache.rankings.set(dateStr, promise);
110
122
  return promise;
@@ -112,6 +124,9 @@ class CachedDataLoader {
112
124
 
113
125
  async loadRatings(dateStr) {
114
126
  if (this.cache.ratings.has(dateStr)) return this.cache.ratings.get(dateStr);
127
+ const collectionName = this.config.piRatingsCollection || 'PIRatingsData';
128
+ const path = `${collectionName}/${dateStr}`;
129
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'ratings' from: ${path}`);
115
130
  const promise = loadPIRatings(this.config, this.deps, dateStr);
116
131
  this.cache.ratings.set(dateStr, promise);
117
132
  return promise;
@@ -119,6 +134,9 @@ class CachedDataLoader {
119
134
 
120
135
  async loadPageViews(dateStr) {
121
136
  if (this.cache.pageViews.has(dateStr)) return this.cache.pageViews.get(dateStr);
137
+ const collectionName = this.config.piPageViewsCollection || 'PIPageViewsData';
138
+ const path = `${collectionName}/${dateStr}`;
139
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'pageViews' from: ${path}`);
122
140
  const promise = loadPIPageViews(this.config, this.deps, dateStr);
123
141
  this.cache.pageViews.set(dateStr, promise);
124
142
  return promise;
@@ -126,6 +144,9 @@ class CachedDataLoader {
126
144
 
127
145
  async loadWatchlistMembership(dateStr) {
128
146
  if (this.cache.watchlistMembership.has(dateStr)) return this.cache.watchlistMembership.get(dateStr);
147
+ const collectionName = this.config.watchlistMembershipCollection || 'WatchlistMembershipData';
148
+ const path = `${collectionName}/${dateStr}`;
149
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'watchlistMembership' from: ${path}`);
129
150
  const promise = loadWatchlistMembershipData(this.config, this.deps, dateStr);
130
151
  this.cache.watchlistMembership.set(dateStr, promise);
131
152
  return promise;
@@ -133,6 +154,9 @@ class CachedDataLoader {
133
154
 
134
155
  async loadAlertHistory(dateStr) {
135
156
  if (this.cache.alertHistory.has(dateStr)) return this.cache.alertHistory.get(dateStr);
157
+ const collectionName = this.config.piAlertHistoryCollection || 'PIAlertHistoryData';
158
+ const path = `${collectionName}/${dateStr}`;
159
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Loading Root Data 'alertHistory' from: ${path}`);
136
160
  const promise = loadPIAlertHistory(this.config, this.deps, dateStr);
137
161
  this.cache.alertHistory.set(dateStr, promise);
138
162
  return promise;
@@ -243,6 +267,10 @@ class CachedDataLoader {
243
267
  let foundCount = 0;
244
268
 
245
269
  if (batchRefs.length > 0) {
270
+ // Log summary of all paths being loaded
271
+ const paths = batchRefs.map(ref => ref.path).join(', ');
272
+ this.deps.logger?.log('INFO', `[CachedDataLoader] 📂 Batch loading ${batchRefs.length} documents for '${loaderMethod}': ${paths}`);
273
+
246
274
  try {
247
275
  const snapshots = await this.deps.db.getAll(...batchRefs);
248
276
 
@@ -279,12 +307,16 @@ class CachedDataLoader {
279
307
  }
280
308
  }
281
309
 
282
- return {
310
+ const summary = {
283
311
  dates: Object.keys(results).sort(),
284
312
  data: results,
285
313
  found: foundCount,
286
314
  requested: lookbackDays
287
315
  };
316
+
317
+ this.deps.logger?.log('INFO', `[CachedDataLoader] ✅ Loaded ${foundCount}/${lookbackDays} dates for '${loaderMethod}' (found: ${summary.dates.join(', ') || 'none'})`);
318
+
319
+ return summary;
288
320
  }
289
321
 
290
322
  /**
@@ -300,6 +332,7 @@ class CachedDataLoader {
300
332
  d.setUTCDate(d.getUTCDate() - i);
301
333
  const dString = d.toISOString().slice(0, 10);
302
334
 
335
+ // Log path for legacy loader (will be logged by individual load methods)
303
336
  promises.push(
304
337
  this[loaderMethod](dString)
305
338
  .then(data => ({ date: dString, data }))
@@ -65,7 +65,8 @@ async function fetchDependencies(date, calcs, config, deps, manifestLookup = {})
65
65
 
66
66
  if (needed.size === 0) return {};
67
67
 
68
- logger.log('INFO', `[DependencyFetcher] Fetching ${needed.size} dependencies for ${dStr}`);
68
+ const calcNames = calcs.map(c => c.name || c.constructor?.name || 'unknown').join(', ');
69
+ logger.log('INFO', `[DependencyFetcher] Fetching ${needed.size} dependencies for computation(s): ${calcNames} (date: ${dStr})`);
69
70
 
70
71
  const results = {};
71
72
  // CHANGED: Iterate over the entries to access both normalized and original names
@@ -75,8 +76,11 @@ async function fetchDependencies(date, calcs, config, deps, manifestLookup = {})
75
76
  // Note: manifestLookup keys are expected to be normalized
76
77
  const category = manifestLookup[normName] || 'analytics';
77
78
 
79
+ // Pass logger in config for fetchSingleResult
80
+ const fetchConfig = { ...config, logger };
81
+
78
82
  // Fetch using the normalized name (system standard)
79
- const data = await fetchSingleResult(db, config, dStr, normName, category);
83
+ const data = await fetchSingleResult(db, fetchConfig, dStr, normName, category);
80
84
 
81
85
  // CHANGED: Store result using the ORIGINAL name so context.computed['CaseSensitive'] works
82
86
  if (data) results[originalName] = data;
@@ -110,7 +114,7 @@ async function fetchResultSeries(endDateStr, calcNames, manifestLookup, config,
110
114
  // Initialize structure
111
115
  calcNames.forEach(name => { results[normalizeName(name)] = {}; });
112
116
 
113
- logger.log('INFO', `[DependencyFetcher] Loading series for ${calcNames.length} calcs over ${lookbackDays} days.`);
117
+ logger.log('INFO', `[DependencyFetcher] Loading series for ${calcNames.length} computation dependencies over ${lookbackDays} days: ${calcNames.join(', ')}`);
114
118
 
115
119
  const fetchOps = [];
116
120
 
@@ -120,7 +124,8 @@ async function fetchResultSeries(endDateStr, calcNames, manifestLookup, config,
120
124
  const category = manifestLookup[normName] || 'analytics';
121
125
 
122
126
  fetchOps.push(async () => {
123
- const val = await fetchSingleResult(db, config, dateStr, rawName, category);
127
+ const fetchConfig = { ...config, logger };
128
+ const val = await fetchSingleResult(db, fetchConfig, dateStr, rawName, category);
124
129
  if (val) {
125
130
  if (!results[normName]) results[normName] = {};
126
131
  results[normName][dateStr] = val;
@@ -142,11 +147,24 @@ async function fetchResultSeries(endDateStr, calcNames, manifestLookup, config,
142
147
  * Core Helper: Fetches a single result, handles Sharding & Compression.
143
148
  */
144
149
  async function fetchSingleResult(db, config, dateStr, name, category) {
145
- const docRef = db.collection(config.resultsCollection)
150
+ const resultsCollection = config.resultsCollection || 'computation_results';
151
+ const resultsSubcollection = config.resultsSubcollection || 'results';
152
+ const computationsSubcollection = config.computationsSubcollection || 'computations';
153
+
154
+ const path = `${resultsCollection}/${dateStr}/${resultsSubcollection}/${category}/${computationsSubcollection}/${name}`;
155
+
156
+ // Log path - use console.log if logger not available (for backward compatibility)
157
+ if (config.logger) {
158
+ config.logger.log('INFO', `[DependencyFetcher] 📂 Loading Dependency '${name}' from: ${path}`);
159
+ } else {
160
+ console.log(`[DependencyFetcher] 📂 Loading Dependency '${name}' from: ${path}`);
161
+ }
162
+
163
+ const docRef = db.collection(resultsCollection)
146
164
  .doc(dateStr)
147
- .collection(config.resultsSubcollection)
165
+ .collection(resultsSubcollection)
148
166
  .doc(category)
149
- .collection(config.computationsSubcollection)
167
+ .collection(computationsSubcollection)
150
168
  .doc(name);
151
169
 
152
170
  const snap = await docRef.get();
@@ -172,12 +190,23 @@ async function fetchSingleResult(db, config, dateStr, name, category) {
172
190
 
173
191
  // 2. Handle Sharding
174
192
  if (data._sharded) {
193
+ const shardPath = `${path}/_shards`;
194
+ if (config.logger) {
195
+ config.logger.log('INFO', `[DependencyFetcher] 📂 Loading Shards for '${name}' from: ${shardPath}`);
196
+ } else {
197
+ console.log(`[DependencyFetcher] 📂 Loading Shards for '${name}' from: ${shardPath}`);
198
+ }
199
+
175
200
  const shardCol = docRef.collection('_shards');
176
201
  const shardSnaps = await shardCol.get();
177
202
 
178
203
  if (!shardSnaps.empty) {
179
204
  shardSnaps.forEach(shard => {
180
205
  const shardData = shard.data();
206
+ const shardId = shard.id;
207
+ if (config.logger) {
208
+ config.logger.log('TRACE', `[DependencyFetcher] 📂 Loading Shard '${shardId}' for '${name}' from: ${shardPath}/${shardId}`);
209
+ }
181
210
  // Merge shard contents, ignoring internal metadata if it clashes
182
211
  Object.entries(shardData).forEach(([k, v]) => {
183
212
  if (!k.startsWith('_')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.644",
3
+ "version": "1.0.646",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [