bulltrackers-module 1.0.698 → 1.0.699

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.
@@ -11,7 +11,13 @@ const INDEX_COLLECTION = process.env.ROOT_DATA_AVAILABILITY_COLLECTION || 'syste
11
11
  // CONFIGURATION: Dependency Mappings
12
12
  // =============================================================================
13
13
 
14
- // Dependencies that map directly to a single status flag
14
+ // Global dependencies that are NOT date-specific and are always considered available.
15
+ // These are stored at fixed paths and don't rely on daily availability index.
16
+ const GLOBAL_DEPS = new Set([
17
+ 'piMasterList' // Stored at /system_state/popular_investor_master_list (global CID->username mapping)
18
+ ]);
19
+
20
+ // Dependencies that map directly to a single status flag (date-specific)
15
21
  const SIMPLE_DEP_MAP = {
16
22
  rankings: 'piRankings',
17
23
  verification: 'signedInUserVerification',
@@ -21,7 +27,7 @@ const SIMPLE_DEP_MAP = {
21
27
  pageViews: 'piPageViews',
22
28
  watchlist: 'watchlistMembership',
23
29
  alerts: 'piAlertHistory',
24
- piMasterList: 'piMasterList' // <--- ADD THIS LINE
30
+ piMasterList: 'piMasterList' // Kept for normalizeStatus compatibility, but checked via GLOBAL_DEPS
25
31
  };
26
32
 
27
33
  // Dependencies that vary based on the userType of the calculation
@@ -68,8 +74,12 @@ function checkRootDependencies(calcManifest, rootDataStatus) {
68
74
  let isAvailable = false;
69
75
  let missingKey = dep;
70
76
 
71
- // 1. Resolve Status Key
72
- if (SIMPLE_DEP_MAP[dep]) {
77
+ // 0. Check for Global Dependencies (always available, not date-specific)
78
+ if (GLOBAL_DEPS.has(dep)) {
79
+ isAvailable = true;
80
+ }
81
+ // 1. Resolve Status Key for date-specific dependencies
82
+ else if (SIMPLE_DEP_MAP[dep]) {
73
83
  const key = SIMPLE_DEP_MAP[dep];
74
84
  if (rootDataStatus[key]) isAvailable = true;
75
85
  else missingKey = key;
@@ -211,7 +211,7 @@ async function loadVariableRootData(loader, dateStr, calcs, logger) {
211
211
  */
212
212
  async function loadSeriesData(loader, dateStr, calcs, manifestLookup, config, deps) {
213
213
  const rootRequests = {};
214
- const depRequests = {};
214
+ const depRequests = {}; // norm -> { days, originalName }
215
215
 
216
216
  // 1. Aggregate Lookback Depths
217
217
  for (const c of calcs) {
@@ -225,7 +225,10 @@ async function loadSeriesData(loader, dateStr, calcs, manifestLookup, config, de
225
225
  Object.entries(c.dependencySeries).forEach(([name, val]) => {
226
226
  const days = typeof val === 'object' ? val.lookback : val;
227
227
  const norm = normalizeName(name);
228
- depRequests[norm] = Math.max(depRequests[norm] || 0, days);
228
+ // [FIX] Track BOTH normalized name (for dedup) AND original name (for Firestore lookup)
229
+ if (!depRequests[norm] || depRequests[norm].days < days) {
230
+ depRequests[norm] = { days, originalName: name };
231
+ }
229
232
  });
230
233
  }
231
234
  }
@@ -250,11 +253,13 @@ async function loadSeriesData(loader, dateStr, calcs, manifestLookup, config, de
250
253
  });
251
254
 
252
255
  // 3. Fetch Dependency Series
253
- const depNames = Object.keys(depRequests);
254
- if (depNames.length > 0) {
255
- const maxDays = Math.max(...Object.values(depRequests));
256
- deps.logger.log('INFO', `[MetaExecutor] Loading up to ${maxDays}-day series for Dependencies: ${depNames.join(', ')}`);
257
- seriesData.results = await fetchResultSeries(dateStr, depNames, manifestLookup, config, deps, maxDays);
256
+ // [FIX] Use ORIGINAL names for Firestore document lookup (case-sensitive)
257
+ const depEntries = Object.values(depRequests);
258
+ if (depEntries.length > 0) {
259
+ const depOriginalNames = depEntries.map(e => e.originalName);
260
+ const maxDays = Math.max(...depEntries.map(e => e.days));
261
+ deps.logger.log('INFO', `[MetaExecutor] Loading up to ${maxDays}-day series for Dependencies: ${depOriginalNames.join(', ')}`);
262
+ seriesData.results = await fetchResultSeries(dateStr, depOriginalNames, manifestLookup, config, deps, maxDays);
258
263
  }
259
264
 
260
265
  await Promise.all(rootPromises);
@@ -383,14 +383,21 @@ async function loadGlobalRoots(loader, dateStr, calcs, deps) {
383
383
 
384
384
  async function loadSeriesData(loader, dateStr, calcs, config, deps) {
385
385
  const rootReqs = {};
386
- const depReqs = {};
386
+ const depReqs = {}; // norm -> { days, originalName }
387
387
 
388
388
  calcs.forEach(c => {
389
389
  if (c.manifest.rootDataSeries) {
390
390
  Object.entries(c.manifest.rootDataSeries).forEach(([k, v]) => rootReqs[k] = Math.max(rootReqs[k]||0, v.lookback||v));
391
391
  }
392
392
  if (c.manifest.dependencySeries) {
393
- Object.entries(c.manifest.dependencySeries).forEach(([k, v]) => depReqs[normalizeName(k)] = Math.max(depReqs[normalizeName(k)]||0, v.lookback||v));
393
+ // [FIX] Track BOTH normalized name (for dedup) AND original name (for Firestore lookup)
394
+ Object.entries(c.manifest.dependencySeries).forEach(([k, v]) => {
395
+ const norm = normalizeName(k);
396
+ const days = v.lookback || v;
397
+ if (!depReqs[norm] || depReqs[norm].days < days) {
398
+ depReqs[norm] = { days, originalName: k };
399
+ }
400
+ });
394
401
  }
395
402
  });
396
403
 
@@ -404,12 +411,15 @@ async function loadSeriesData(loader, dateStr, calcs, config, deps) {
404
411
  if (rootMap[key]) series.root[key] = (await loader.loadSeries(rootMap[key], dateStr, days)).data;
405
412
  }));
406
413
 
407
- const depNames = Object.keys(depReqs);
408
- if (depNames.length) {
414
+ // [FIX] Use ORIGINAL names for Firestore document lookup (case-sensitive)
415
+ const depEntries = Object.values(depReqs);
416
+ if (depEntries.length) {
417
+ const depOriginalNames = depEntries.map(e => e.originalName);
418
+ const maxDays = Math.max(...depEntries.map(e => e.days));
409
419
  // Construct manifest lookup on the fly for fetched names
410
420
  const allManifests = getManifest(config.productLines, config.calculationsDirectory, deps);
411
421
  const lookup = Object.fromEntries(allManifests.map(m => [normalizeName(m.name), m.category]));
412
- series.results = await fetchResultSeries(dateStr, depNames, lookup, config, deps, Math.max(...Object.values(depReqs)));
422
+ series.results = await fetchResultSeries(dateStr, depOriginalNames, lookup, config, deps, maxDays);
413
423
  }
414
424
 
415
425
  return series;
@@ -189,6 +189,12 @@ function checkRootDependencies(calcManifest, rootDataStatus) {
189
189
  }
190
190
  }
191
191
  }
192
+ // [GLOBAL] piMasterList is always available (not date-specific)
193
+ // Stored at /system_state/popular_investor_master_list
194
+ else if (dep === 'piMasterList') {
195
+ isAvailable = true;
196
+ available.push('piMasterList');
197
+ }
192
198
  }
193
199
 
194
200
  // [NEW] Enforce Mandatory Roots (defined by computation)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.698",
3
+ "version": "1.0.699",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [