bulltrackers-module 1.0.32 → 1.0.33
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.
- package/functions/generic-api/index.js +22 -10
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
|
|
6
6
|
const express = require('express');
|
|
7
7
|
const cors = require('cors');
|
|
8
|
-
// FieldPath is needed to query by document ID
|
|
8
|
+
// FieldPath is needed to query by document ID and dynamic paths
|
|
9
9
|
const { FieldPath } = require('@google-cloud/firestore');
|
|
10
10
|
const { buildCalculationMap, createApiHandler } = require('./helpers/api_helpers.js');
|
|
11
11
|
|
|
@@ -36,7 +36,7 @@ function createStructureSnippet(data, maxKeys = 20) {
|
|
|
36
36
|
|
|
37
37
|
// If it's a large map (e.g., user IDs), just show one example
|
|
38
38
|
if (keys.length > maxKeys) {
|
|
39
|
-
const firstKey = keys[0];
|
|
39
|
+
const firstKey = keys[0] || "example_key";
|
|
40
40
|
newObj[firstKey] = createStructureSnippet(data[firstKey], maxKeys);
|
|
41
41
|
newObj[`... (${keys.length - 1} more keys)`] = "<object>";
|
|
42
42
|
} else {
|
|
@@ -90,7 +90,7 @@ function createApiApp(config, dependencies, unifiedCalculations) {
|
|
|
90
90
|
}
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
-
// --- REVISED: Debug Endpoint to get the structure from Firestore ---
|
|
93
|
+
// --- REVISED V3: Debug Endpoint to get the structure from Firestore ---
|
|
94
94
|
app.get('/structure/:computationName', async (req, res) => {
|
|
95
95
|
const { computationName } = req.params;
|
|
96
96
|
try {
|
|
@@ -106,30 +106,37 @@ function createApiApp(config, dependencies, unifiedCalculations) {
|
|
|
106
106
|
const resultsSub = config.resultsSubcollection || 'results';
|
|
107
107
|
const compsSub = config.computationsSubcollection || 'computations';
|
|
108
108
|
|
|
109
|
-
// 3. Find the most recent date
|
|
109
|
+
// 3. Find the most recent date *that contains this computation*
|
|
110
|
+
// This relies on the summary flags set by orchestration_helpers.js
|
|
111
|
+
const computationQueryPath = `${category}.${computationName}`;
|
|
110
112
|
const dateQuery = firestore.collection(insightsCollection)
|
|
111
|
-
.
|
|
113
|
+
.where(computationQueryPath, '==', true) // Find docs with the summary flag
|
|
114
|
+
.orderBy(FieldPath.documentId(), 'desc') // Get the latest date
|
|
112
115
|
.limit(1);
|
|
113
116
|
|
|
114
117
|
const dateSnapshot = await dateQuery.get();
|
|
115
118
|
|
|
116
119
|
if (dateSnapshot.empty) {
|
|
117
|
-
return res.status(404).send({
|
|
120
|
+
return res.status(404).send({
|
|
121
|
+
status: 'error',
|
|
122
|
+
message: `No computed data found for '${computationName}'. (Query path: ${computationQueryPath})`
|
|
123
|
+
});
|
|
118
124
|
}
|
|
119
125
|
|
|
120
|
-
const
|
|
126
|
+
const latestDateForThisComp = dateSnapshot.docs[0].id;
|
|
121
127
|
|
|
122
128
|
// 4. Construct the path to the actual computation document
|
|
123
|
-
const docRef = firestore.collection(insightsCollection).doc(
|
|
129
|
+
const docRef = firestore.collection(insightsCollection).doc(latestDateForThisComp)
|
|
124
130
|
.collection(resultsSub).doc(category)
|
|
125
131
|
.collection(compsSub).doc(computationName);
|
|
126
132
|
|
|
127
133
|
const doc = await docRef.get();
|
|
128
134
|
|
|
129
135
|
if (!doc.exists) {
|
|
136
|
+
// This is unlikely if the summary flag is true, but good to check
|
|
130
137
|
return res.status(404).send({
|
|
131
138
|
status: 'error',
|
|
132
|
-
message: `Data for '${computationName}' not found for
|
|
139
|
+
message: `Data for '${computationName}' not found for its latest date (${latestDateForThisComp}). Summary flag was present but doc is missing.`,
|
|
133
140
|
checkedPath: docRef.path
|
|
134
141
|
});
|
|
135
142
|
}
|
|
@@ -142,11 +149,16 @@ function createApiApp(config, dependencies, unifiedCalculations) {
|
|
|
142
149
|
status: 'success',
|
|
143
150
|
computation: computationName,
|
|
144
151
|
category: category,
|
|
145
|
-
|
|
152
|
+
latestStoredDate: latestDateForThisComp,
|
|
146
153
|
structureSnippet: snippet,
|
|
147
154
|
});
|
|
148
155
|
|
|
149
156
|
} catch (error) {
|
|
157
|
+
// Handle errors, including bad query paths
|
|
158
|
+
if (error.message && error.message.includes('Invalid argument')) {
|
|
159
|
+
logger.log('ERROR', `API /structure/${computationName} failed, likely due to invalid query path.`, { queryPath: `${category}.${computationName}`, stack: error.stack });
|
|
160
|
+
return res.status(500).send({ status: 'error', message: `Internal query error. The path '${category}.${computationName}' might be invalid.` });
|
|
161
|
+
}
|
|
150
162
|
logger.log('ERROR', `API /structure/${computationName} failed.`, { errorMessage: error.message, stack: error.stack });
|
|
151
163
|
res.status(500).send({ status: 'error', message: `An internal error occurred while processing '${computationName}'.` });
|
|
152
164
|
}
|