Skip to content

Commit 21fea22

Browse files
committed
deduplicated reports
1 parent 19ac150 commit 21fea22

15 files changed

+331
-775
lines changed

package-lock.json

Lines changed: 6 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

src/controllers/adoptionController.js

Lines changed: 0 additions & 111 deletions
This file was deleted.
Lines changed: 27 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,52 @@
11
import { firestore } from '../utils/db.js';
2-
import {
3-
applyArrayFilter,
4-
generateQueryCacheKey,
5-
getCachedQueryResult,
6-
setCachedQueryResult
7-
} from '../utils/controllerHelpers.js';
2+
import { executeQuery, validateArrayParameter } from '../utils/controllerHelpers.js';
83

94
/**
10-
* List categories with optional filtering and field selection - Optimized version
5+
* List categories with optional filtering and field selection
116
*/
127
const listCategories = async (req, res) => {
13-
try {
14-
const params = req.query;
8+
const queryBuilder = async (params) => {
159
const isOnlyNames = params.onlyname || typeof params.onlyname === 'string';
1610
const hasCustomFields = params.fields && !isOnlyNames;
1711

18-
// Create cache key for this specific query
19-
const queryFilters = {
20-
category: params.category,
21-
onlyname: isOnlyNames,
22-
fields: params.fields
23-
};
24-
const cacheKey = generateQueryCacheKey('categories', queryFilters);
25-
26-
// Check cache first
27-
const cachedResult = getCachedQueryResult(cacheKey);
28-
if (cachedResult) {
29-
res.statusCode = 200;
30-
res.end(JSON.stringify(cachedResult));
31-
return;
32-
}
33-
3412
let query = firestore.collection('categories').orderBy('category', 'asc');
3513

36-
// Apply category filter using shared utility
37-
query = applyArrayFilter(query, 'category', params.category);
14+
// Apply category filter with validation
15+
if (params.category) {
16+
const categories = validateArrayParameter(params.category, 'category');
17+
if (categories.length > 0) {
18+
query = query.where('category', 'in', categories);
19+
}
20+
}
3821

22+
// Apply field selection
3923
if (isOnlyNames) {
40-
// Only select category field for names-only queries
4124
query = query.select('category');
4225
} else if (hasCustomFields) {
43-
// Select only requested fields
4426
const requestedFields = params.fields.split(',').map(f => f.trim());
4527
query = query.select(...requestedFields);
4628
}
4729

48-
// Execute query
49-
const snapshot = await query.get();
50-
const data = [];
30+
return query;
31+
};
5132

52-
// Process results based on response type
53-
snapshot.forEach(doc => {
54-
const docData = doc.data();
33+
const dataProcessor = (data, params) => {
34+
const isOnlyNames = params.onlyname || typeof params.onlyname === 'string';
5535

56-
if (isOnlyNames) {
57-
data.push(docData.category);
58-
} else {
59-
// Data already filtered by select(), just return it
60-
data.push(docData);
61-
}
62-
});
36+
if (isOnlyNames) {
37+
return data.map(item => item.category);
38+
}
39+
40+
return data;
41+
};
6342

64-
// Cache the result
65-
setCachedQueryResult(cacheKey, data);
43+
// Include onlyname and fields in cache key calculation
44+
const customCacheKeyData = {
45+
onlyname: req.query.onlyname || false,
46+
fields: req.query.fields
47+
};
6648

67-
// Direct response
68-
res.statusCode = 200;
69-
res.end(JSON.stringify(data));
70-
} catch (error) {
71-
console.error('Error fetching categories:', error);
72-
res.statusCode = 500;
73-
res.end(JSON.stringify({
74-
errors: [{ error: 'Failed to fetch categories' }]
75-
}));
76-
}
49+
await executeQuery(req, res, 'categories', queryBuilder, dataProcessor, customCacheKeyData);
7750
};
7851

7952
export { listCategories };

src/controllers/cwvtechController.js

Lines changed: 0 additions & 112 deletions
This file was deleted.

src/controllers/geosController.js

Lines changed: 5 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,15 @@
11
import { firestore } from '../utils/db.js';
2-
import { handleControllerError, generateQueryCacheKey, getCachedQueryResult, setCachedQueryResult } from '../utils/controllerHelpers.js';
2+
import { executeQuery } from '../utils/controllerHelpers.js';
33

44
/**
55
* List all geographic locations from database
66
*/
77
const listGeos = async (req, res) => {
8-
try {
9-
// Generate cache key for this query
10-
const cacheKey = generateQueryCacheKey('geos', { orderBy: 'mobile_origins' });
8+
const queryBuilder = async () => {
9+
return firestore.collection('geos').orderBy('mobile_origins', 'desc').select('geo');
10+
};
1111

12-
// Check cache first
13-
const cachedResult = getCachedQueryResult(cacheKey);
14-
if (cachedResult) {
15-
res.statusCode = 200;
16-
res.end(JSON.stringify(cachedResult));
17-
return;
18-
}
19-
20-
const snapshot = await firestore.collection('geos').orderBy('mobile_origins', 'desc').select('geo').get();
21-
const data = [];
22-
23-
// Extract only the 'geo' property from each document
24-
snapshot.forEach(doc => {
25-
data.push(doc.data());
26-
});
27-
28-
// Cache the result
29-
setCachedQueryResult(cacheKey, data);
30-
31-
res.statusCode = 200;
32-
res.end(JSON.stringify(data));
33-
} catch (error) {
34-
handleControllerError(res, error, 'fetching geographic locations');
35-
}
12+
await executeQuery(req, res, 'geos', queryBuilder);
3613
};
3714

3815
export {

0 commit comments

Comments
 (0)