🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

@nodevu/core

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@nodevu/core - npm Package Compare versions

Comparing version
0.1.0
to
0.2.0
+189
-193
index.js

@@ -1,224 +0,218 @@

const { fetch: defaultFetch } = require('undici')
const { DateTime } = require('luxon')
const semver = require('semver')
const parsefiles = require('@nodevu/parsefiles')
const { DateTime } = require('luxon');
const semver = require('semver');
const parsefiles = require('@nodevu/parsefiles');
const optionsParser = require('./util/prod/optionsParser');
const versionFetcher = require('./util/prod/versions');
const scheduleFetcher = require('./util/prod/schedule');
async function core (options) {
// parse our user's options and set up our fetch/DateTime implementations
const parsedOptions = await parseOptions(options)
async function core(options) {
// parse our user's options and set up our fetch/DateTime implementations
const parsedOptions = optionsParser(options);
const fetch = parsedOptions.fetch
const now = DateTime.fromISO(parsedOptions.now)
const nodejsIndexURL = parsedOptions.urls.index
const nodejsScheduleURL = parsedOptions.urls.schedule
const now = DateTime.fromISO(parsedOptions.now);
// collect and configure our data sources
const rawVersions = await fetch(nodejsIndexURL)
const rawSchedule = await fetch(nodejsScheduleURL)
const versions = await rawVersions.json()
const schedule = await rawSchedule.json()
const data = {}
// collect and configure our data sources
const versions = await versionFetcher(parsedOptions);
const schedule = await scheduleFetcher(parsedOptions);
Object.keys(versions).map(async (version) => {
const versionSemver = semver.coerce(versions[version].version)
const name = versionSemver.major !== 0 ? `v${versionSemver.major}` : `v${versionSemver.major}.${versionSemver.minor}`
// instantiate our data object, to be expanded upon
const data = {};
// define the shape of the object we're going to use
if (!data[name]) {
data[name] = {}
}
Object.keys(versions).map(async (version) => {
const versionSemver = semver.coerce(versions[version].version);
const name =
versionSemver.major !== 0
? `v${versionSemver.major}`
: `v${versionSemver.major}.${versionSemver.minor}`;
if (!data[name].releases) {
data[name].releases = {}
}
// define the shape of the object we're going to use
if (!data[name]) {
data[name] = {};
}
data[name].releases[`v${versionSemver.version}`] = {}
if (!data[name].releases) {
data[name].releases = {};
}
// define semver object
const semverToReturn = {
raw: versionSemver.raw,
major: versionSemver.major,
minor: versionSemver.minor,
patch: versionSemver.patch,
line: name
}
data[name].releases[`v${versionSemver.version}`] = {};
data[name].releases[`v${versionSemver.version}`].semver = semverToReturn
// define semver object
const semverToReturn = {
raw: versionSemver.raw,
major: versionSemver.major,
minor: versionSemver.minor,
patch: versionSemver.patch,
line: name,
};
data[name].releases[`v${versionSemver.version}`].releaseDate = versions[version].date ?? undefined
data[name].releases[`v${versionSemver.version}`].semver = semverToReturn;
const modules = {
version: versions[version].modules ?? undefined
}
data[name].releases[`v${versionSemver.version}`].releaseDate =
versions[version].date ?? undefined;
data[name].releases[`v${versionSemver.version}`].modules = modules
const modules = {
version: versions[version].modules ?? undefined,
};
// define the dependencies object
data[name].releases[`v${versionSemver.version}`].dependencies = {}
data[name].releases[`v${versionSemver.version}`].modules = modules;
data[name].releases[`v${versionSemver.version}`].dependencies.npm = versions[version].npm ?? undefined
data[name].releases[`v${versionSemver.version}`].dependencies.v8 = versions[version].v8 ?? undefined
data[name].releases[`v${versionSemver.version}`].dependencies.uv = versions[version].uv ?? undefined
data[name].releases[`v${versionSemver.version}`].dependencies.zlib = versions[version].zlib ?? undefined
data[name].releases[`v${versionSemver.version}`].dependencies.openssl = versions[version].openssl ?? undefined
// define the dependencies object
data[name].releases[`v${versionSemver.version}`].dependencies = {};
// surface file information
data[name].releases[`v${versionSemver.version}`].files = {}
data[name].releases[`v${versionSemver.version}`].dependencies.npm =
versions[version].npm ?? undefined;
data[name].releases[`v${versionSemver.version}`].dependencies.v8 =
versions[version].v8 ?? undefined;
data[name].releases[`v${versionSemver.version}`].dependencies.uv =
versions[version].uv ?? undefined;
data[name].releases[`v${versionSemver.version}`].dependencies.zlib =
versions[version].zlib ?? undefined;
data[name].releases[`v${versionSemver.version}`].dependencies.openssl =
versions[version].openssl ?? undefined;
// TODO: parse versions[version].files and convert them to URLs that can be directly accessed
data[name].releases[`v${versionSemver.version}`].files.available = versions[version].files ?? undefined
const availableShorthand = data[name].releases[`v${versionSemver.version}`].files.available // since we're going to be writing this a lot for assignments, it's nice to have shorthand for readability
// surface file information
data[name].releases[`v${versionSemver.version}`].files = {};
data[name].releases[`v${versionSemver.version}`].files.links = {}
const linksShorthand = data[name].releases[`v${versionSemver.version}`].files.links // since we're going to be writing this a lot for assignments, it's nice to have shorthand for readability
// TODO: parse versions[version].files and convert them to URLs that can be directly accessed
data[name].releases[`v${versionSemver.version}`].files.available =
versions[version].files ?? undefined;
const availableShorthand =
data[name].releases[`v${versionSemver.version}`].files.available; // since we're going to be writing this a lot for assignments, it's nice to have shorthand for readability
Object.keys(availableShorthand).forEach(filename => {
const id = data[name].releases[`v${versionSemver.version}`].files.available[filename]
const parsedFile = parsefiles(id, versionSemver.version)
data[name].releases[`v${versionSemver.version}`].files.links = {};
const linksShorthand =
data[name].releases[`v${versionSemver.version}`].files.links; // since we're going to be writing this a lot for assignments, it's nice to have shorthand for readability
if (!linksShorthand[parsedFile.type]) {
linksShorthand[parsedFile.type] = []
}
for (const filename of Object.keys(availableShorthand)) {
const id =
data[name].releases[`v${versionSemver.version}`].files.available[
filename
];
const parsedFile = parsefiles(id, versionSemver.version);
linksShorthand[parsedFile.type].push({
id: parsedFile.id,
files: parsedFile.files,
architecture: parsedFile.architecture
})
})
if (!linksShorthand[parsedFile.type]) {
linksShorthand[parsedFile.type] = [];
}
// # LTS
// ## define the release-line specific support objec`t
if (schedule[name]?.start !== undefined) { // hack-y way to skip this logic on releases that don't have a listed start
if (!data[name].support) { // check to see if we've already written it. if we have, we don't need to waste time on it.
data[name].support = {}
data[name].support.codename = schedule[name]?.codename ?? undefined
data[name].support.lts = schedule[name]?.lts ? {} : undefined
linksShorthand[parsedFile.type].push({
id: parsedFile.id,
files: parsedFile.files,
architecture: parsedFile.architecture,
});
}
// run this the first time we start working on the support object,
// since that will be the newest version
if (versions[version].lts) {
data[name].support.lts.newest = versionSemver.version
}
// # LTS
// ## define the release-line specific support objec`t
if (schedule[name]?.start !== undefined) {
// hack-y way to skip this logic on releases that don't have a listed start
if (!data[name].support) {
// check to see if we've already written it. if we have, we don't need to waste time on it.
data[name].support = {};
data[name].support.codename = schedule[name]?.codename ?? undefined;
data[name].support.lts = schedule[name]?.lts ? {} : undefined;
data[name].support.phases = {}
data[name].support.phases.dates = {}
data[name].support.phases.dates.start = schedule[name]?.start ?? undefined
data[name].support.phases.dates.lts = schedule[name]?.lts ?? undefined
data[name].support.phases.dates.maintenance = schedule[name]?.maintenance ?? undefined
data[name].support.phases.dates.end = schedule[name]?.end ?? undefined
}
data[name].support.phases.current = await determineCurrentReleasePhase(now, data[name].support.phases.dates) ?? {}
}
// run this the first time we start working on the support object,
// since that will be the newest version
if (versions[version].lts) {
data[name].support.lts.newest = versionSemver.version;
}
// this is a slightly inefficient way to do this but it's also easy
//
// tl;dr we're just assigning this every single iteration and the last
// iteration will be the oldest version, since we're going from newest
// to oldest
if (versions[version].lts) {
data[name].support.lts.oldest = versionSemver.version
}
data[name].support.phases = {};
data[name].support.phases.dates = {};
data[name].support.phases.dates.start =
schedule[name]?.start ?? undefined;
data[name].support.phases.dates.lts = schedule[name]?.lts ?? undefined;
data[name].support.phases.dates.maintenance =
schedule[name]?.maintenance ?? undefined;
data[name].support.phases.dates.end = schedule[name]?.end ?? undefined;
}
data[name].support.phases.current =
(await determineCurrentReleasePhase(
now,
data[name].support.phases.dates,
)) ?? {};
}
// ## define the lts object in each specific version
data[name].releases[`v${versionSemver.version}`].lts = {}
// this is a slightly inefficient way to do this but it's also easy
//
// tl;dr we're just assigning this every single iteration and the last
// iteration will be the oldest version, since we're going from newest
// to oldest
if (versions[version].lts) {
data[name].support.lts.oldest = versionSemver.version;
}
data[name].releases[`v${versionSemver.version}`].lts.isLts = !!versions[version].lts
// ## define the lts object in each specific version
data[name].releases[`v${versionSemver.version}`].lts = {};
// # Security
// ## define the release-line specific security object
if (!data[name].security) { // check to see if we've already written it. if we have, we don't need to waste time on it.
data[name].security = {}
data[name].security.all = []
}
data[name].releases[`v${versionSemver.version}`].lts.isLts =
!!versions[version].lts;
// the newest security release, which can be populated on the first run
if (!data[name].security.newest) {
if (versions[version].security === true) {
data[name].security.newest = versionSemver.version
}
}
// # Security
// ## define the release-line specific security object
if (!data[name].security) {
// check to see if we've already written it. if we have, we don't need to waste time on it.
data[name].security = {};
data[name].security.all = [];
}
// same inefficient hack as we do in the LTS 'oldest' logic. ineffecient but gets the job done.
if (versions[version].security === true) {
data[name].security.oldest = versionSemver.version
}
// the newest security release, which can be populated on the first run
if (!data[name].security.newest) {
if (versions[version].security === true) {
data[name].security.newest = versionSemver.version;
}
}
// throw the current loop's iteration into the security.all array if it's a security release
if (versions[version].security === true) {
data[name].security.all.push(versionSemver.version)
}
// same inefficient hack as we do in the LTS 'oldest' logic. ineffecient but gets the job done.
if (versions[version].security === true) {
data[name].security.oldest = versionSemver.version;
}
// ## define the security object in each specfic version
data[name].releases[`v${versionSemver.version}`].security = {}
// throw the current loop's iteration into the security.all array if it's a security release
if (versions[version].security === true) {
data[name].security.all.push(versionSemver.version);
}
data[name].releases[`v${versionSemver.version}`].security.isSecurity = versions[version].security ?? false
})
// ## define the security object in each specfic version
data[name].releases[`v${versionSemver.version}`].security = {};
return data
}
data[name].releases[`v${versionSemver.version}`].security.isSecurity =
versions[version].security ?? false;
});
async function determineCurrentReleasePhase (now, dates = {}) {
// we set set this up to enable custom `now` passing, since passing an ISO
// const usableNow = DateTime.fromISO(now)
// here we figure out if the dates for each release line passed is in the past or future
// `true` is in the past
// `false` is in the future
const isoified = {
start: isInPast(DateTime.fromISO(dates.start).diff(now).toMillis()) ?? undefined,
lts: isInPast(DateTime.fromISO(dates.lts).diff(now).toMillis()) ?? undefined,
maintenance: isInPast(DateTime.fromISO(dates.maintenance).diff(now).toMillis()) ?? undefined,
end: isInPast(DateTime.fromISO(dates.end).diff(now).toMillis()) ?? undefined
}
// set up our result to return
let result
// iterate over the past/future object and set the above variable to whatever the first date is in the future.
Object.keys(isoified).forEach(async (phase) => {
// since we're looping, the last true is the current phase
// since the start date will always be in the past
if (isoified[phase] === true) {
result = phase
}
})
return result
return data;
}
// this function allows us to parse user-passed options.
//
// this is particularly useful for tests so we can reduce variables
// and ensure that our test suite is able to be consistent.
async function parseOptions (options) {
// set up our defaults
const parsedOptions = {
fetch: await defaultFetch,
now: DateTime.now(),
urls: {
index: 'https://nodejs.org/dist/index.json',
schedule: 'https://raw.githubusercontent.com/nodejs/Release/master/schedule.json'
}
}
async function determineCurrentReleasePhase(now, dates = {}) {
// we set set this up to enable custom `now` passing, since passing an ISO
// const usableNow = DateTime.fromISO(now)
// allow the end-user to replace our fetch implementation with another one of their precernece.
if (options?.fetch) {
parsedOptions.fetch = options.fetch
}
// here we figure out if the dates for each release line passed is in the past or future
// `true` is in the past
// `false` is in the future
const isoified = {
start:
isInPast(DateTime.fromISO(dates.start).diff(now).toMillis()) ?? undefined,
lts:
isInPast(DateTime.fromISO(dates.lts).diff(now).toMillis()) ?? undefined,
maintenance:
isInPast(DateTime.fromISO(dates.maintenance).diff(now).toMillis()) ??
undefined,
end:
isInPast(DateTime.fromISO(dates.end).diff(now).toMillis()) ?? undefined,
};
// allow the end-user to provide a custom DateTime. This is particularly useful for tests.
if (options?.now) {
parsedOptions.now = options.now
}
// set up our result to return
let result;
if (options?.urls?.index) {
parsedOptions.urls.index = options.urls.index
}
// iterate over the past/future object and set the above variable to whatever the first date is in the future.
for (const phase of Object.keys(isoified)) {
// since we're looping, the last true is the current phase
// since the start date will always be in the past
if (isoified[phase] === true) {
result = phase;
}
}
if (options?.urls?.schedule) {
parsedOptions.urls.schedule = options.urls.schedule
}
return parsedOptions
return result;
}

@@ -232,13 +226,15 @@

// where DATE is your date value
function isInPast (number) {
const sign = Math.sign(number)
if (sign === -1 || sign === 0) {
return true
} else if (sign === 1) {
return false
} else {
return undefined
}
function isInPast(number) {
const sign = Math.sign(number);
if (sign === -1 || sign === 0) {
return true;
}
if (sign === 1) {
return false;
}
return undefined;
}
module.exports = core
module.exports = core;
{
"name": "@nodevu/core",
"version": "0.1.0",
"description": "nodevu core API: comprehensive node.js version tooling",
"main": "index.js",
"scripts": {
"lint": "standard --env mocha",
"lint:fix": "standard --fix --env mocha",
"test": "node--test",
"test:update": "npm run test:update:static && npm run test:update:now",
"test:update:static": "node ./util/dev/updateStaticData.js",
"test:update:now": "node ./util/dev/updateStaticNow.js",
"coverage": "nyc node--test",
"updates:check": "npx npm-check-updates",
"updates:update": "npx npm-check-updates -u"
},
"author": "Tierney Cyren <hello@bnb.im> (https://bnb.im/)",
"license": "MIT",
"files": [
"index.js",
"LICENSE"
],
"dependencies": {
"@nodevu/parsefiles": "^0.0.3",
"luxon": "^3.3.0",
"semver": "^7.5.1",
"undici": "^5.22.1"
},
"devDependencies": {
"nyc": "^15.1.0",
"standard": "^17.0.0",
"test": "^3.3.0"
}
"name": "@nodevu/core",
"version": "0.2.0",
"description": "nodevu core API: comprehensive node.js version tooling",
"main": "index.js",
"scripts": {
"lint": "biome check ./",
"lint:write": "biome check ./ --write",
"test": "node--test",
"test:update": "npm run test:update:static && npm run test:update:now",
"test:update:static": "node ./util/dev/updateStaticData.js",
"test:update:now": "node ./util/dev/updateStaticNow.js",
"coverage": "nyc node--test",
"updates:check": "npx npm-check-updates",
"updates:update": "npx npm-check-updates -u"
},
"author": "Tierney Cyren <hello@bnb.im> (https://bnb.im/)",
"license": "MIT",
"files": [
"index.js",
"LICENSE"
],
"dependencies": {
"@nodevu/parsefiles": "^0.0.3",
"luxon": "^3.5.0",
"semver": "^7.6.3"
},
"devDependencies": {
"@biomejs/biome": "1.9.4",
"nyc": "^17.1.0",
"test": "^3.3.0",
"undici": "^6.20.1"
}
}