Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] master from nodists:master #19

Merged
merged 7 commits into from
Dec 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
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
9 changes: 9 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ on:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+'
- 'v[0-9]+.[0-9]+.[0-9]+-*'
workflow_dispatch:


jobs:
run-build:
Expand All @@ -23,7 +25,14 @@ jobs:
run: Copy-Item (Get-Command node.exe | Select-Object -ExpandProperty Definition) .
- run: npm test
- run: npm run build
- name: Archive build artifact
if: github.ref_type == 'branch'
uses: actions/upload-artifact@v3
with:
name: Installer
path: "build/out/NodistSetup-*.exe"
- name: Create release draft
if: github.ref_type == 'tag'
uses: ncipollo/release-action@v1
with:
artifacts: "build/out/NodistSetup-*.exe"
Expand Down
8 changes: 3 additions & 5 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,11 +1,6 @@
name: run-tests

on:
push:
branches:
- '**'
tags-ignore:
- '**'
pull_request:

jobs:
Expand All @@ -27,3 +22,6 @@ jobs:
- name: Copy Node.exe to repository directory
run: Copy-Item (Get-Command node.exe | Select-Object -ExpandProperty Definition) .
- run: npm test
env:
NODIST_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -291,8 +291,12 @@ MIT License

## Changelog

v0.10.1
v0.10.3
* Fix installing of npm versions

v0.10.2
* Fix building shims (for newer go versions) by using go modules
* Fix npm shim to use correct node version
* Add npx shim (works only for npm versions that ship with npx)
* Fix getting latest npm version
* Use last available x86 version for building (first node 18 versions are not available for x86)
Expand Down
46 changes: 13 additions & 33 deletions build/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ var fs = require('fs');
var mkdirp = require('mkdirp');
var ncp = require('ncp');
var path = require('path');
var semver = require('semver');
var recursiveReaddir = require('recursive-readdir');
var request = require('request');
var rimraf = require('rimraf');
Expand Down Expand Up @@ -83,6 +84,7 @@ var npm = new (require('../lib/npm'))({nodistDir: stagingDir});
//default npm version to the latest at the time of writing
var npmVersion = '6.14.16';
var nodeVersion = '16.15.0';
var maxNodeMainVersion = '^20';

var versionPathx86 = '';
var versionPathx64 = '';
Expand All @@ -102,31 +104,14 @@ console.log('Welcome to the Nodist Builder');
console.log(' before going further we need to prep our staging folder');

//defining helper functions
function getLatestNodeVersionFor(nodeVersions, fileType) {
function getLatestUsableNodeVersionFor(nodeVersions, fileType) {
for (var key in nodeVersions) {
if (nodeVersions[key].files.includes(fileType)) {
return nodeVersions[key].version;
if (nodeVersions[key].files.includes(fileType) && semver.satisfies(nodeVersions[key].version, maxNodeMainVersion)) {
return { nodeVersion: nodeVersions[key].version, npmVersion: nodeVersions[key].npm };
}
}
}

async function resolveLinkedWorkspaces(dirPath) {
let movedLinks = 0;
const files = await fs.readdirAsync(dirPath, { withFileTypes: true });
const dirPromises = [];
for (const file of files) {
const filePath = path.join(dirPath, file.name);
if (file.isSymbolicLink()) {
const linkTarget = await fs.readlinkAsync(filePath);
await fs.renameAsync(path.join(dirPath, linkTarget), filePath);
movedLinks++;
} else if (file.isDirectory()) {
dirPromises.push(resolveLinkedWorkspaces(filePath));
}
}
return (await Promise.all(dirPromises)).reduce((sum, num) => sum + num, movedLinks);
}

//start by clearing the staging and tmp folders
P.all([
rimraf(outDir),
Expand Down Expand Up @@ -193,19 +178,19 @@ P.all([
console.log('Finished copying static files');

console.log('Compiling node shim');
return exec('go build -o "'+stagingBin +'/node.exe" shim-node.go', { cwd: goSrcDir });
return exec('go build -o "'+stagingBin +'/node.exe" ./cmd/node', { cwd: goSrcDir });
})
.then(function(){
console.log('Done compiling node shim');

console.log('Compiling npm shim');
return exec('go build -o "'+stagingBin +'/npm.exe" shim-npm.go', { cwd: goSrcDir });
return exec('go build -o "'+stagingBin +'/npm.exe" ./cmd/npm', { cwd: goSrcDir });
})
.then(function(){
console.log('Done compiling npm shim');

console.log('Compiling npx shim');
return exec('go build -o "'+stagingBin +'/npx.exe" shim-npx.go', { cwd: goSrcDir });
return exec('go build -o "'+stagingBin +'/npx.exe" ./cmd/npx', { cwd: goSrcDir });
})
.then(function() {
console.log('Done compiling npx shim');
Expand All @@ -217,7 +202,7 @@ P.all([
});
})
.then(function(res){
nodeVersion = getLatestNodeVersionFor(res.body, 'win-x86-exe');
({ nodeVersion, npmVersion } = getLatestUsableNodeVersionFor(res.body, 'win-x86-exe'));
nodeLatestUrlx86 = nodeLatestUrlx86.replace('VERSION',nodeVersion);
nodeLatestUrlx64 = nodeLatestUrlx64.replace('VERSION',nodeVersion);
console.log('Latest version of Node ' + nodeVersion);
Expand Down Expand Up @@ -253,14 +238,9 @@ P.all([
);
})
.then(function(){
console.log('Figure out the latest version of NPM');
return npm.latestVersion();
})
.then(function(version){
npmVersion = version;
var downloadLink = npm.downloadUrl(version);
console.log('Determined latest NPM as ' + npmVersion);
console.log('Downloading latest NPM from ' + downloadLink);
var downloadLink = npm.downloadUrl(npmVersion);
console.log('Determined matching NPM as ' + npmVersion);
console.log('Downloading matching NPM from ' + downloadLink);
return Promise.resolve()
.then(() => mkdirp(stagingNpmDir+'/'+npmVersion.replace('v','')))
.then(() => {
Expand Down Expand Up @@ -291,7 +271,7 @@ P.all([
})
.then(function() {
console.log('Installation complete');
return resolveLinkedWorkspaces(path.join(stagingNpmDir, npmVersion.replace('v', ''), 'node_modules'));
return helper.resolveLinkedWorkspaces(path.join(stagingNpmDir, npmVersion.replace('v', '')), false);
})
.then(function(movedLinks) {
if (movedLinks) {
Expand Down
52 changes: 52 additions & 0 deletions lib/build.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ var path = require('path');
var promisePipe = require('promisepipe');
var ProgressBar = require('progress');
var request = require('request');
const P = require('bluebird');
var debug = require('debug')('nodist:build')

//make some promising APIs
P.promisifyAll(fs);

/**
* Copy File
* @param {string} source
Expand Down Expand Up @@ -141,3 +145,51 @@ exports.downloadFileStream = function downloadFileStream(url) {
});
return req
}

/**
* Npm version >= 18 using symlinks that do not work in windows and have to be fixed
* this function replace the broken symlinks with NTFS junction or move the directory if junctions are not supported
*
* @param {string} dirPath
* @param {boolean} preferSymlink
* @returns {Promise<number>} number of changed links
*/
exports.resolveLinkedWorkspaces = async function resolveLinkedWorkspaces(dirPath, preferSymlink = true) {
let fixedLinks = 0;
const packageLockJson = JSON.parse(fs.readFileSync(path.join(dirPath, 'package-lock.json')).toString());
await Promise.all(Object.entries(packageLockJson.packages)
.filter(([pkgPath, pkg]) => pkg.link === true)
.map(async ([pkgPath, pkg]) => {

const linkPath = path.join(dirPath, pkgPath);


if (await fs.accessAsync(linkPath, fs.constants.F_OK).then(() => true).catch(() => false)) {
await fs.unlinkAsync(linkPath);
}

let linkCreated = false;
if (preferSymlink) {
const linkTarget = path.join(
...pkgPath.split('/').slice(0, -1).map(() => '..'),
pkg.resolved
);
debug('Create symlink for ', linkPath, 'with target', linkTarget);
try {
await fs.symlinkAsync(linkTarget, linkPath, 'junction');
linkCreated = true;
} catch (e) {
debug('Link ', linkPath, 'could not be created');
}
}
if (!linkCreated) {
const from = path.join(dirPath, pkg.resolved);
debug('Move', from, 'to', linkPath);
await fs.renameAsync(from, linkPath);
}

fixedLinks++;
}));

return fixedLinks;
};
44 changes: 5 additions & 39 deletions lib/npm.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,40 +36,7 @@ module.exports = npmist

var NPMIST = npmist.prototype

/**
* Npm version >= 18 using symlinks that do not work in windows and have to be fixed
* this function replace the broken symlinks with NTFS junction or move the directory if junctions are not supported
*
* @param {string} dirPath
* @returns {Promise<number>} number of changed links
*/
async function resolveLinkedWorkspaces(dirPath) {
let fixedLinks = 0;
const packageLockJson = JSON.parse(fs.readFileSync(path.join(dirPath, 'package-lock.json')).toString());
await Promise.all(Object.entries(packageLockJson.packages)
.filter(([pkgPath, pkg]) => pkg.link === true)
.map(async ([pkgPath, pkg]) => {
const linkTarget = path.join(
...pkgPath.split('/').slice(0, -1).map(() => '..'),
pkg.resolved
);
const linkPath = path.join(dirPath, pkgPath);

debug('Create symlink for ', linkPath, 'with target', linkTarget);
if (await fs.accessAsync(linkPath, fs.constants.F_OK).then(() => true).catch(() => false)) {
await fs.unlinkAsync(linkPath);
}

try {
await fs.symlinkAsync(linkTarget, linkPath, 'junction');
} catch (e) {
await fs.renameAsync(path.join(dirPath, linkTarget), linkPath);
}
fixedLinks++;
}));

return fixedLinks;
}
const versionRegex = /^v\d+\.\d+\.\d+$/;

/**
* List available NPM versions
Expand All @@ -95,10 +62,9 @@ NPMIST.listAvailable = function(){
.then(([npm, cli]) => {
// The npm project has two kinds of releases: releases of npm,
// and releases of other utility libraries.
// Ignore the releases of libraries. They are named "package: version",
// Ignore the releases of libraries. They are named "library-version",
// while core npm releases are named just "version".
cli = cli.filter( release => release.name.indexOf(':') < 0 );

cli = cli.filter(release => versionRegex.test(release));
return npm.concat(cli);
});
};
Expand Down Expand Up @@ -146,7 +112,7 @@ function getNpmReleases(page) {
per_page: 50,
page,
}).then((response) => response.data.map(release => release.tag_name)
.filter((version) => /^v\d+\.\d+\.\d+$/.test(version))
.filter((version) => versionRegex.test(version))
.sort(semver.compare)
);
}
Expand Down Expand Up @@ -331,7 +297,7 @@ NPMIST.install = function(v,done){
.then(() => {
if (semver.gte(version, '8.0.0')) {
debug('Fix symlinks for npm version >= 8');
return resolveLinkedWorkspaces(path.join(archivePath))
return buildHelper.resolveLinkedWorkspaces(path.join(archivePath))
.then(fixedLinks => {
debug(`Fixed ${fixedLinks} symlinks for npm node_modules`);
});
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nodist",
"version": "0.10.1",
"version": "0.10.3",
"description": "Natural node version manager for windows",
"keywords": [
"node",
Expand Down
16 changes: 16 additions & 0 deletions src/cmd/node/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

import (
"os"
"os/exec"

nodist "github.com/nodists/nodist/internal"
)

func main() {
err, nodebin, _, _ := nodist.DetermineNodeExecutable("node")

// Run node!
cmd := exec.Command(nodebin, os.Args[1:]...)
nodist.ExecuteCommand(cmd, err)
}
23 changes: 23 additions & 0 deletions src/cmd/npm/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package main

import (
"os"
"os/exec"

nodist "github.com/nodists/nodist/internal"
)

func main() {
err, nodebin, dir, nodeVersion := nodist.DetermineNodeExecutable("node")

path, _ := nodist.DetermineNpmPath(dir, nodeVersion)

npmbin := path + "/bin/npm-cli.js"

args := []string{npmbin}
args = append(args, os.Args[1:]...)

// Run npm!
cmd := exec.Command(nodebin, args...)
nodist.ExecuteCommand(cmd, err)
}
30 changes: 30 additions & 0 deletions src/cmd/npx/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package main

import (
"errors"
"fmt"
"os"
"os/exec"

nodist "github.com/nodists/nodist/internal"
)

func main() {
err, nodebin, dir, nodeVersion := nodist.DetermineNodeExecutable("node")

path, npmVersion := nodist.DetermineNpmPath(dir, nodeVersion)

npxbin := path + "/bin/npx-cli.js"

if _, err := os.Stat(npxbin); errors.Is(err, os.ErrNotExist) {
fmt.Println("Npx not found for selected npm version:", npmVersion)
os.Exit(47)
}

args := []string{npxbin}
args = append(args, os.Args[1:]...)

// Run npx!
cmd := exec.Command(nodebin, args...)
nodist.ExecuteCommand(cmd, err)
}
Loading