Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
42 changes: 19 additions & 23 deletions apps/site/next-data/generators/supportersData.mjs
Original file line number Diff line number Diff line change
@@ -1,28 +1,24 @@
import { OPENCOLLECTIVE_MEMBERS_URL } from '#site/next.constants.mjs';

/**
* Fetches supporters data from Open Collective API, filters active backers,
* and maps it to the Supporters type.
*
* @returns {Promise<Array<import('#site/types/supporters')>>} Array of supporters
* @returns {Promise<Array<import('#site/types/supporters').OpenCollectiveSupporter>>} Array of supporters
*/
async function fetchOpenCollectiveData() {
const endpoint = 'https://opencollective.com/nodejs/members/all.json';

const response = await fetch(endpoint);

const payload = await response.json();

const members = payload
.filter(({ role, isActive }) => role === 'BACKER' && isActive)
.sort((a, b) => b.totalAmountDonated - a.totalAmountDonated)
.map(({ name, website, image, profile }) => ({
name,
image,
url: website,
profile,
source: 'opencollective',
}));

return members;
}

export default fetchOpenCollectiveData;
export default () =>
fetch(OPENCOLLECTIVE_MEMBERS_URL)
.then(response => response.json())
.then(payload =>
payload
.filter(({ role, isActive }) => role === 'BACKER' && isActive)
.sort((a, b) => b.totalAmountDonated - a.totalAmountDonated)
.map(({ name, website, image, profile }) => ({
name,
image,
url: website,
profile,
source: 'opencollective',
}))
)
.catch(() => []);
134 changes: 62 additions & 72 deletions apps/site/next-data/generators/vulnerabilities.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,86 +8,76 @@ const RANGE_REGEX = /([<>]=?)\s*(\d+)(?:\.(\d+))?/;
*
* @returns {Promise<import('#site/types/vulnerabilities').GroupedVulnerabilities>} Grouped vulnerabilities
*/
export default async function generateVulnerabilityData() {
const response = await fetch(VULNERABILITIES_URL);
export default () =>
fetch(VULNERABILITIES_URL)
.then(response => response.json())
.then(payload => {
/** @type {Array<import('#site/types/vulnerabilities').RawVulnerability>} */
const data = Object.values(payload);

/** @type {Promise<import('#site/types/vulnerabilities').GroupedVulnerabilities> */
const grouped = {};

// Helper function to add vulnerability to a major version group
const addToGroup = (majorVersion, vulnerability) => {
grouped[majorVersion] ??= [];
grouped[majorVersion].push(vulnerability);
};

// Helper function to process version patterns
const processVersion = (version, vulnerability) => {
// Handle 0.X versions (pre-semver)
if (/^0\.\d+(\.x)?$/.test(version)) {
addToGroup('0', vulnerability);

return;
}

// Handle simple major.x patterns (e.g., 12.x)
if (/^\d+\.x$/.test(version)) {
const majorVersion = version.split('.')[0];

/** @type {Array<import('#site/types/vulnerabilities').RawVulnerability>} */
const data = Object.values(await response.json());

/** @type {Promise<import('#site/types/vulnerabilities').GroupedVulnerabilities> */
const grouped = {};

// Helper function to add vulnerability to a major version group
const addToGroup = (majorVersion, vulnerability) => {
grouped[majorVersion] ??= [];
grouped[majorVersion].push(vulnerability);
};

// Helper function to process version patterns
const processVersion = (version, vulnerability) => {
// Handle 0.X versions (pre-semver)
if (/^0\.\d+(\.x)?$/.test(version)) {
addToGroup('0', vulnerability);

return;
}

// Handle simple major.x patterns (e.g., 12.x)
if (/^\d+\.x$/.test(version)) {
const majorVersion = version.split('.')[0];
addToGroup(majorVersion, vulnerability);

addToGroup(majorVersion, vulnerability);
return;
}

return;
}
// Handle version ranges (>, >=, <, <=)
const rangeMatch = RANGE_REGEX.exec(version);

// Handle version ranges (>, >=, <, <=)
const rangeMatch = RANGE_REGEX.exec(version);
if (rangeMatch) {
const [, operator, majorVersion] = rangeMatch;

if (rangeMatch) {
const [, operator, majorVersion] = rangeMatch;
const majorNum = parseInt(majorVersion, 10);

const majorNum = parseInt(majorVersion, 10);
switch (operator) {
case '>=':
case '>':
case '<=':
addToGroup(majorVersion, vulnerability);

switch (operator) {
case '>=':
case '>':
case '<=':
addToGroup(majorVersion, vulnerability);
break;
case '<':
// Add to all major versions below the specified version
for (let i = majorNum - 1; i >= 0; i--) {
addToGroup(i.toString(), vulnerability);
}

break;
case '<':
// Add to all major versions below the specified version
for (let i = majorNum - 1; i >= 0; i--) {
addToGroup(i.toString(), vulnerability);
break;
}
}
};

break;
for (const { ref, ...vulnerability } of Object.values(data)) {
vulnerability.url = ref;
// Process all potential versions from the vulnerable field
const versions = vulnerability.vulnerable.split(' || ').filter(Boolean);

for (const version of versions) {
processVersion(version, vulnerability);
}
}
}
};

for (const vulnerability of Object.values(data)) {
const parsedVulnerability = {
cve: vulnerability.cve,
url: vulnerability.ref,
vulnerable: vulnerability.vulnerable,
patched: vulnerability.patched,
description: vulnerability.description,
overview: vulnerability.overview,
affectedEnvironments: vulnerability.affectedEnvironments,
severity: vulnerability.severity,
};

// Process all potential versions from the vulnerable field
const versions = parsedVulnerability.vulnerable
.split(' || ')
.filter(Boolean);

for (const version of versions) {
processVersion(version, parsedVulnerability);
}
}

return grouped;
}

return grouped;
})
.catch(() => ({}));
6 changes: 6 additions & 0 deletions apps/site/next.constants.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -213,3 +213,9 @@ export const EOL_VERSION_IDENTIFIER = 'End-of-life';
*/
export const VULNERABILITIES_URL =
'https://raw.githubusercontent.com/nodejs/security-wg/main/vuln/core/index.json';

/**
* The location of the OpenCollective data
*/
export const OPENCOLLECTIVE_MEMBERS_URL =
'https://opencollective.com/nodejs/members/all.json';
1 change: 1 addition & 0 deletions apps/site/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ export * from './download';
export * from './userAgent';
export * from './vulnerabilities';
export * from './page';
export * from './supporters';
9 changes: 9 additions & 0 deletions apps/site/types/supporters.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export type Supporter = {
name: string;
image: string;
url: string;
profile: string;
source: string;
};

export type OpenCollectiveSupporter = Supporter & { source: 'opencollective' };
Loading