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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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}
|
|
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
|
|
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
|
|
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(
|
|
165
|
+
.collection(resultsSubcollection)
|
|
148
166
|
.doc(category)
|
|
149
|
-
.collection(
|
|
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('_')) {
|