Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
702fcf4
dev DB
max-ostapenko Jun 30, 2025
1792820
selected fields
max-ostapenko Jun 30, 2025
94c66b9
Merge branch 'main' into development
max-ostapenko Jun 30, 2025
da93de6
cache key expanded
max-ostapenko Jun 30, 2025
ef362a7
Merge remote-tracking branch 'origin/main' into development
max-ostapenko Jul 1, 2025
f9023cc
versions endpoint
max-ostapenko Jul 7, 2025
8cab936
Add version parameter support to report data endpoints
max-ostapenko Jul 8, 2025
57a6ec5
Merge branch 'main' into development
max-ostapenko Jul 8, 2025
f284924
Merge branch 'main' into development
max-ostapenko Jul 12, 2025
09dae53
docker builds
max-ostapenko Jul 15, 2025
db0be01
fix paths
max-ostapenko Jul 15, 2025
c59fa3c
rename repo
max-ostapenko Jul 15, 2025
ad93b49
fix iam
max-ostapenko Jul 15, 2025
e3683a2
cleanup
max-ostapenko Jul 15, 2025
2b77b00
Merge branch 'main' into development
max-ostapenko Nov 22, 2025
b5bd7e0
Add /v1/versions endpoint to API with GET method
max-ostapenko Dec 6, 2025
13cb046
Fix field selection logic to handle missing fields parameter in listC…
max-ostapenko Dec 6, 2025
8df7c3a
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 13, 2025
c90362d
fix: rename function_name to service_name in endpoints module
max-ostapenko Dec 13, 2025
233925e
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 13, 2025
617f212
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 13, 2025
b5ae460
remove duplicate variable definition for service_name in variables.tf
max-ostapenko Dec 13, 2025
3413157
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 13, 2025
5e7e8f7
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 14, 2025
d61ae5a
Merge branch 'main' into tech-sort-and-versions
max-ostapenko Dec 14, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,15 @@ Lists available categories.
#### Categories Parameters

- `category` (optional): Filter by category name(s) - comma-separated list
- `client` (optional): Filter by client type (e.g., `mobile`, `desktop`) - defaults to `mobile`
- `onlyname` (optional): If present, returns only category names
- `fields` (optional): Comma-separated list of fields to include in the response (see [Field Selection API Documentation](#field-selection-api-documentation) for details)

#### Categories Response

```bash
curl --request GET \
--url 'https://d{{HOST}}/v1/categories?category=Domain%20parking%2CCI'
--url 'https://{{HOST}}/v1/categories?category=Domain%20parking%2CCI&client=desktop'
```

```json
Expand All @@ -73,10 +74,7 @@ curl --request GET \
"Jenkins",
"TeamCity"
],
"origins": {
"mobile": 22,
"desktop": 35
},
"origins": 22,
"category": "CI"
},
{
Expand All @@ -85,10 +83,7 @@ curl --request GET \
"Cloudflare",
"Arsys Domain Parking"
],
"origins": {
"mobile": 14,
"desktop": 8
},
"origins": 14,
"category": "Domain parking"
}
]
Expand Down Expand Up @@ -212,6 +207,7 @@ Provides technology adoption data.
- `rank` (required): Filter by rank
- `start` (optional): Filter by date range start (YYYY-MM-DD or 'latest')
- `end` (optional): Filter by date range end (YYYY-MM-DD)
- `version` (optional): Filter by version name(s) - comma-separated list (only when single technology is specified)

#### Adoption Response

Expand Down Expand Up @@ -247,6 +243,7 @@ Provides Core Web Vitals metrics for technologies.
- `rank` (required): Filter by rank
- `start` (optional): Filter by date range start (YYYY-MM-DD or 'latest')
- `end` (optional): Filter by date range end (YYYY-MM-DD)
- `version` (optional): Filter by version name(s) - comma-separated list (only when single technology is specified)

#### CWV Response

Expand Down Expand Up @@ -290,6 +287,7 @@ Provides Lighthouse scores for technologies.
- `rank` (required): Filter by rank
- `start` (optional): Filter by date range start (YYYY-MM-DD or 'latest')
- `end` (optional): Filter by date range end (YYYY-MM-DD)
- `version` (optional): Filter by version name(s) - comma-separated list (only when single technology is specified)

#### Lighthouse Response

Expand Down Expand Up @@ -337,6 +335,7 @@ Provides Page Weight metrics for technologies.
- `rank` (required): Filter by rank
- `start` (optional): Filter by date range start (YYYY-MM-DD or 'latest')
- `end` (optional): Filter by date range end (YYYY-MM-DD)
- `version` (optional): Filter by version name(s) - comma-separated list (only when single technology is specified)

#### Page Weight Response

Expand Down Expand Up @@ -398,6 +397,7 @@ Provides Lighthouse audits for technologies.
- `rank` (required): Filter by rank
- `start` (optional): Filter by date range start (YYYY-MM-DD or 'latest')
- `end` (optional): Filter by date range end (YYYY-MM-DD)
- `version` (optional): Filter by version name(s) - comma-separated list (only when single technology is specified)

#### Audits Response

Expand Down Expand Up @@ -585,7 +585,7 @@ The categories and technologies endpoints now support custom field selection, al
- `category` - Category name
- `description` - Category description
- `technologies` - Array of technology names in the category
- `origins` - Array of origin companies/organizations
- `origins` - Number of origins

Get only category names:

Expand All @@ -605,7 +605,7 @@ GET /v1/categories?fields=category,description
- `category` - Category name
- `description` - Technology description
- `icon` - Icon filename
- `origins` - Array of origin companies/organizations
- `origins` - Dictionary with origins per client

Get only technology names and categories:

Expand Down Expand Up @@ -640,7 +640,7 @@ GET /v1/technologies?category=JavaScript%20Frameworks&fields=technology,icon

- `technology` - Technology name
- `version` - Version name
- `origins` - Mobile and desktop origins
- `origins` - Dictionary with origins per client

Get only technology and version names:

Expand Down
6 changes: 6 additions & 0 deletions src/__tests__/routes.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ describe('API Routes', () => {
expect(Array.isArray(res.body)).toBe(true);
});

it('should return adoption data with version parameter', async () => {
const res = await request(app).get('/v1/adoption?technology=WordPress&geo=ALL&rank=ALL&start=latest&version=5.0');
expect(res.statusCode).toEqual(200);
expect(Array.isArray(res.body)).toBe(true);
});

it('should handle missing required parameters', async () => {
const res = await request(app).get('/v1/adoption');
expect(res.statusCode).toEqual(400);
Expand Down
10 changes: 8 additions & 2 deletions src/controllers/categoriesController.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const listCategories = async (req, res) => {
const queryBuilder = async (params) => {
/*
// Validate parameters
const supportedParams = ['category', 'onlyname', 'fields'];
const supportedParams = ['category', 'onlyname', 'fields', 'client'];
const providedParams = Object.keys(params);
const unsupportedParams = providedParams.filter(param => !supportedParams.includes(param));

Expand All @@ -20,6 +20,7 @@ const listCategories = async (req, res) => {
*/

const isOnlyNames = params.onlyname || typeof params.onlyname === 'string';
const client = params.client || 'mobile'; // Default client if not provided
const hasCustomFields = params.fields && !isOnlyNames;

let query = firestore.collection('categories').orderBy('category', 'asc');
Expand All @@ -32,11 +33,16 @@ const listCategories = async (req, res) => {
}
}

// Apply client filter
if (client) {
query = query.where('client', '==', client);
}

// Apply field selection
if (isOnlyNames) {
query = query.select('category');
} else if (hasCustomFields) {
const requestedFields = params.fields.split(',').map(f => f.trim());
const requestedFields = params.fields ? params.fields.split(',').map(f => f.trim()) : ['category', 'description', 'technologies', 'origins'];
query = query.select(...requestedFields);
}

Expand Down
32 changes: 19 additions & 13 deletions src/controllers/reportController.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { firestoreOld } from '../utils/db.js';
const firestore = firestoreOld;
import { firestore } from '../utils/db.js';

import {
REQUIRED_PARAMS,
Expand Down Expand Up @@ -52,7 +51,7 @@ const createReportController = (reportType) => {

/*
// Validate supported parameters
const supportedParams = ['technology', 'geo', 'rank', 'start', 'end'];
const supportedParams = ['technology', 'geo', 'rank', 'start', 'end', 'version'];
const providedParams = Object.keys(params);
const unsupportedParams = providedParams.filter(param => !supportedParams.includes(param));

Expand All @@ -75,8 +74,15 @@ const createReportController = (reportType) => {
return;
}

// Validate and process technology array
const techArray = validateArrayParameter(params.technology, 'technology');
// Validate and process technologies
const technologiesArray = validateArrayParameter(params.technology, 'technology');

// Validate and process versions
// Apply version filter with special handling for 'ALL' case
let versionsArray = ['ALL'];
if (technologiesArray.length === 1 && params.version) {
versionsArray = validateArrayParameter(params.version, 'version');
}

// Handle 'latest' date substitution
let startDate = params.start;
Expand All @@ -92,21 +98,21 @@ const createReportController = (reportType) => {
query = query.where('rank', '==', params.rank);

// Apply technology filter with batch processing
query = query.where('technology', 'in', techArray);
query = query.where('technology', 'in', technologiesArray);

// Apply version filter with special handling for 'ALL' case
if (params.version && techArray.length === 1) {
//query = query.where('version', '==', params.version); // TODO: Uncomment when migrating to a new data schema
} else {
//query = query.where('version', '==', 'ALL');
}
// Apply version filter with batch processing
query = query.where('version', 'in', versionsArray);

// Apply date filters
if (startDate) query = query.where('date', '>=', startDate);
if (params.end) query = query.where('date', '<=', params.end);

// Apply field projection to optimize query
query = query.select('date', 'technology', config.dataField);
const selectFields = ['date', 'technology', config.dataField];
if (!(versionsArray.length === 1 && versionsArray[0] === 'ALL')) {
selectFields.push('version');
}
query = query.select(...selectFields);

// Execute query
const snapshot = await query.get();
Expand Down
2 changes: 1 addition & 1 deletion terraform/dev/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ variable "environment" {
variable "project_database" {
type = string
description = "The database name"
default = "tech-report-api-prod" // TODO: Update this to the DEV database name
default = "tech-report-api-dev"
}
1 change: 1 addition & 0 deletions terraform/modules/run-service/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ variable "region" {
variable "environment" {
description = "The 'Environment' that is being created/deployed. Applied as a suffix to many resources."
type = string
default = "dev"
}
variable "service_name" {
description = "Optional: Can be used to create more than function from the same package"
Expand Down