From ce42d1506f6bb74b3504a4b88d2bd6a18dfeccd3 Mon Sep 17 00:00:00 2001 From: haro ashida Date: Tue, 21 Sep 2021 13:42:34 +0900 Subject: [PATCH 01/12] Revert "fix(npm ls): resolve to correct version" This reverts commit 710c27cfa0e0a0693f608dd6d5b949f7170ce771. --- src/lib/nodist/nodist.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/nodist/nodist.go b/src/lib/nodist/nodist.go index bac9cbe8..036c2812 100644 --- a/src/lib/nodist/nodist.go +++ b/src/lib/nodist/nodist.go @@ -131,7 +131,7 @@ func resolveVersion(spec string, installed []*semver.Version) (version string, e } if spec == "latest" { - version = installed[len(installed)-1].String() + version = installed[0].String() }else{ for _, v := range installed { debug("checking %s against %s", v.String(), spec) From 947299eab8b042a56cb2d071e729994fc63969ab Mon Sep 17 00:00:00 2001 From: haro ashida Date: Tue, 21 Sep 2021 13:54:02 +0900 Subject: [PATCH 02/12] fix Handling latest in npm --- lib/npm.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/npm.js b/lib/npm.js index 16ef5cca..3e9cd023 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -139,7 +139,7 @@ NPMIST.downloadUrl = function(version){ NPMIST.resolveVersionLocally = function(spec, done) { if (!spec) return done() this.listInstalled((er, installed) => { - if (spec === 'latest') return done(null, installed[0]) + if (spec === 'latest') return done(null, installed[installed.length - 1]) if (spec === 'match') { this.nodist.getCurrentVersion((er, nodeVersion) => { @@ -364,4 +364,3 @@ NPMIST.getEnv = function getEnv(cb) { if(!this.envVersion) return cb(); cb(null, this.envVersion); }; - From f4c997bbbc0a7da414421ec9ae87da915c0be09f Mon Sep 17 00:00:00 2001 From: Yavor Georgiev Date: Wed, 12 Jan 2022 16:48:57 +0100 Subject: [PATCH 03/12] Use the Octokit client for GitHub This replaces the old `github` package with the latest Octokit REST client which makes authentication work again. Additionally, the `NODIST_GITHUB_TOKEN` environment variable can now be used to supply a token for authenticating GitHub requests (and overcoming the unauthenticated request rate limit). --- README.md | 6 ++ build/build.js | 5 +- lib/github.js | 24 ------- lib/npm.js | 36 +++++----- lib/octokit.js | 14 ++++ package-lock.json | 170 ++++++++++++++++++++++++++++++++++++++++++---- package.json | 2 +- 7 files changed, 197 insertions(+), 60 deletions(-) delete mode 100644 lib/github.js create mode 100644 lib/octokit.js diff --git a/README.md b/README.md index a423e861..2323b50a 100644 --- a/README.md +++ b/README.md @@ -223,6 +223,12 @@ call nodist env 4.x # Enable package.json inspection: Nodist will check the engines field of the package.json file of scripts to be executed and use the node version specified there. Turned off by default as of v0.8.5. ``` +``` +> set NODIST_GITHUB_TOKEN=your_github_personal_access_token +# By default Nodist makes request to the GitHub API to list npm releases without any authentication, which is subject to [rate limiting](https://docs.github.com/en/rest/overview/resources-in-the-rest-api#rate-limiting). By using your own [Personal Access Token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token) Nodist will be able to make more requests per hour. +# Note: for security purposes it's best to use a token just for Nodist. The `repo:public_repo` scope should be more than sufficient. +``` + ## Details Node executables are stored in `NODIST_PREFIX\v` and `NODIST_PREFIX\v-x64`, npm versions in `NODIST_PREFIX\npmv. The global `node.exe` is a shim and chooses the right node version to run based on the various version settings. The same applies for npm. diff --git a/build/build.js b/build/build.js index 90fb6a44..61bbea2f 100644 --- a/build/build.js +++ b/build/build.js @@ -11,7 +11,6 @@ var rimraf = require('rimraf'); var tar = require('tar'); var zlib = require('zlib'); -var github = require('../lib/github'); var helper = require('../lib/build'); var pkg = require('../package.json'); @@ -19,8 +18,6 @@ var pkg = require('../package.json'); //make some promises P.promisifyAll(fs); -P.promisifyAll(github); -P.promisifyAll(github.releases); P.promisifyAll(helper); P.promisifyAll(request); exec = P.promisify(exec); @@ -143,7 +140,7 @@ P.all([ helper.copyFileAsync( nodistLib + '/build.js',stagingLib + '/build.js'), helper.copyFileAsync( - nodistLib + '/github.js',stagingLib + '/github.js'), + nodistLib + '/octokit.js',stagingLib + '/octokit.js'), helper.copyFileAsync( nodistLib + '/nodist.js',stagingLib + '/nodist.js'), helper.copyFileAsync( diff --git a/lib/github.js b/lib/github.js deleted file mode 100644 index 663926bd..00000000 --- a/lib/github.js +++ /dev/null @@ -1,24 +0,0 @@ -'use strict'; -var GithubApi = require('github'); - -var github = new GithubApi({ - version: '3.0.0' -}); - -// ------------------------- -// Github Authentication -//------------------------- -var githubCredentials = { - type: 'oauth', - // in order to raise your API limits place a token here generated from github - // then remove the comment below - token: 'xxx' -}; -// remove the comment at the beginning of the line below to activate auth -// github.authenticate(githubCredentials); - -/** - * Github API instance - * @type {module.exports|exports} - */ -module.exports = github; diff --git a/lib/npm.js b/lib/npm.js index 16ef5cca..56190925 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -11,14 +11,11 @@ var zlib = require('zlib') var buildHelper = require('./build'); -var github = require('./github'); +var octokit = require('./octokit'); var vermanager = require('./versions') //make some promising APIs P.promisifyAll(fs); -P.promisifyAll(github); -P.promisifyAll(github.releases); -P.promisifyAll(github.repos); mkdirp = P.promisify(mkdirp); ncp = P.promisify(ncp); rimraf = P.promisify(rimraf); @@ -46,15 +43,19 @@ var NPMIST = npmist.prototype */ NPMIST.listAvailable = function(){ return Promise.all([ - github.releases.listReleasesAsync({ + octokit.paginate(octokit.rest.repos.listReleases, { owner: 'npm', repo: 'npm', - per_page: '100' + per_page: 100 + }, function(response) { + return response.data.map(function(release) { return release.tag_name; }); }), - github.releases.listReleasesAsync({ + octokit.paginate(octokit.rest.repos.listReleases, { owner: 'npm', repo: 'cli', - per_page: '100' + per_page: 100 + }, function(response) { + return response.data.map(function(release) { return release.tag_name; }); }) ]) .then(([npm, cli]) => npm.concat(cli)); @@ -101,13 +102,13 @@ NPMIST.listInstalled = function listInstalled(cb) { * @return {string} */ NPMIST.latestVersion = function(){ - return github.releases.getLatestReleaseAsync({ - owner: 'npm', - repo: 'cli' - }) - .then(function(result){ - return result.tag_name; - }); + return octokit.repos.getLatestRelease({ + owner: 'npm', + repo: 'cli' + }) + .then(function(result){ + return result.data.tag_name; + }); }; /** @@ -188,10 +189,7 @@ NPMIST.resolveVersion = function(v,done){ } this.listAvailable() - .then(function(results){ - var available = results.map(function(v){ - return v.tag_name; - }); + .then(function(available){ //try to get a version if its explicit var version = semver.clean(v); //support version ranges diff --git a/lib/octokit.js b/lib/octokit.js new file mode 100644 index 00000000..c3ee0b12 --- /dev/null +++ b/lib/octokit.js @@ -0,0 +1,14 @@ +'use strict'; +const { Octokit } = require('@octokit/rest'); +const nodistPackage = require('../package.json') + +var octokit = new Octokit({ + auth: process.env.NODIST_GITHUB_TOKEN, + userAgent: `nodist v${nodistPackage.version}`, +}); + +/** + * Github API instance + * @type {module.exports|exports} + */ +module.exports = octokit; diff --git a/package-lock.json b/package-lock.json index d8ff00f8..beefd0cd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,117 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", + "requires": { + "@octokit/types": "^6.0.3" + } + }, + "@octokit/core": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.5.1.tgz", + "integrity": "sha512-omncwpLVxMP+GLpLPgeGJBF6IWJFjXDS5flY5VbppePYX9XehevbDykRH9PdCdvqt9TS5AOTiDide7h0qrkHjw==", + "requires": { + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.0", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", + "requires": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", + "requires": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/openapi-types": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-11.2.0.tgz", + "integrity": "sha512-PBsVO+15KSlGmiI8QAzaqvsNlZlrDlyAJYcrXBCvVUxCp7VnXjkwPoFHgjEJXx3WF9BAwkA6nfCUA7i9sODzKA==" + }, + "@octokit/plugin-paginate-rest": { + "version": "2.17.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.17.0.tgz", + "integrity": "sha512-tzMbrbnam2Mt4AhuyCHvpRkS0oZ5MvwwcQPYGtMv4tUa5kkzG58SVB0fcsLulOZQeRnOgdkZWkRUiyBlh0Bkyw==", + "requires": { + "@octokit/types": "^6.34.0" + } + }, + "@octokit/plugin-request-log": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz", + "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==" + }, + "@octokit/plugin-rest-endpoint-methods": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.13.0.tgz", + "integrity": "sha512-uJjMTkN1KaOIgNtUPMtIXDOjx6dGYysdIFhgA52x4xSadQCz3b/zJexvITDVpANnfKPW/+E0xkOvLntqMYpviA==", + "requires": { + "@octokit/types": "^6.34.0", + "deprecation": "^2.3.1" + } + }, + "@octokit/request": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.2.tgz", + "integrity": "sha512-je66CvSEVf0jCpRISxkUcCa0UkxmFs6eGDRSbfJtAVwbLH5ceqF+YEyC8lj8ystKyZTy8adWr0qmkY52EfOeLA==", + "requires": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.1", + "universal-user-agent": "^6.0.0" + } + }, + "@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", + "requires": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" + } + }, + "@octokit/rest": { + "version": "18.12.0", + "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-18.12.0.tgz", + "integrity": "sha512-gDPiOHlyGavxr72y0guQEhLsemgVjwRePayJ+FcKc2SJqKUbxbkvf5kAZEWA/MKvsfYlQAMVzNJE3ezQcxMJ2Q==", + "requires": { + "@octokit/core": "^3.5.1", + "@octokit/plugin-paginate-rest": "^2.16.8", + "@octokit/plugin-request-log": "^1.0.4", + "@octokit/plugin-rest-endpoint-methods": "^5.12.0" + } + }, + "@octokit/types": { + "version": "6.34.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.34.0.tgz", + "integrity": "sha512-s1zLBjWhdEI2zwaoSgyOFoKSl109CUcVBCc7biPJ3aAf6LGLU6szDvi31JPU7bxfla2lqfhjbbg/5DdFNxOwHw==", + "requires": { + "@octokit/openapi-types": "^11.2.0" + } + }, "ajv": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz", @@ -56,6 +167,11 @@ "tweetnacl": "^0.14.3" } }, + "before-after-hook": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", + "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" + }, "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", @@ -119,6 +235,11 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==" + }, "diff": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", @@ -196,13 +317,6 @@ "assert-plus": "^1.0.0" } }, - "github": { - "version": "github:nullivex/node-github#d11c575df67a226837e147aca13279eddc070015", - "from": "github:nullivex/node-github", - "requires": { - "mime": "^1.2.11" - } - }, "glob": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", @@ -264,6 +378,11 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" }, + "is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==" + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -305,11 +424,6 @@ "verror": "1.10.0" } }, - "mime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", - "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" - }, "mime-db": { "version": "1.38.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", @@ -371,6 +485,14 @@ "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=" }, + "node-fetch": { + "version": "2.6.6", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.6.tgz", + "integrity": "sha512-Z8/6vRlTUChSdIgMa51jxQ4lrw/Jy5SOW10ObaA47/RElsAN2c5Pn8bTgFGWn/ibwzXTE8qwr1Yzx28vsecXEA==", + "requires": { + "whatwg-url": "^5.0.0" + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -538,6 +660,11 @@ } } }, + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", @@ -551,6 +678,11 @@ "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" }, + "universal-user-agent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.0.tgz", + "integrity": "sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==" + }, "uri-js": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", @@ -585,6 +717,20 @@ "glob": "^7.1.2" } }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/package.json b/package.json index 6b4a3982..62d24cb6 100644 --- a/package.json +++ b/package.json @@ -20,9 +20,9 @@ "url": "http://github.com/marcelklehr/nodist.git" }, "dependencies": { + "@octokit/rest": "^18.12.0", "bluebird": "^3.5.3", "debug": "^4.1.1", - "github": "nullivex/node-github", "mkdirp": "~0.5", "ncp": "^2.0.0", "progress": "2.x", From 2ebed897cb9e8d3792b89b44dbb635e099d62227 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Thu, 12 May 2022 11:45:35 +0200 Subject: [PATCH 04/12] fix(building shims): use go modules and an existing fork of go-debug --- .gitignore | 1 + README.md | 4 +++- build/build.js | 5 +++-- src/go.mod | 8 ++++++++ src/go.sum | 4 ++++ src/lib/{nodist => }/nodist.go | 4 ++-- src/shim-node.go | 4 ++-- src/shim-npm.go | 4 ++-- 8 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/go.mod create mode 100644 src/go.sum rename src/lib/{nodist => }/nodist.go (99%) diff --git a/.gitignore b/.gitignore index 0bbc183e..ffa8805a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ node_modules /.idea /build/out /npmv +/pkg diff --git a/README.md b/README.md index 2323b50a..e1ebdf30 100644 --- a/README.md +++ b/README.md @@ -272,7 +272,6 @@ Building nodist requires * NSIS Plugin: [AccessControl](http://nsis.sourceforge.net/AccessControl_plug-in) * node.js for running the build script * and npm for installing nodist's dependencies - * Finally you need to `go get github.com/marcelklehr/semver github.com/computes/go-debug` If you have met all requirements, run the build command: @@ -288,6 +287,9 @@ MIT License ## Changelog +v0.10.0 +* Fix building shims (for newer go versions) by using go modules + v0.9.1 * Fix issue with deprecated call to Tar.Extract in the NPM handler. diff --git a/build/build.js b/build/build.js index 61bbea2f..9534801a 100644 --- a/build/build.js +++ b/build/build.js @@ -77,6 +77,7 @@ var stagingLib = path.join(stagingDir,'lib'); var nodistDir = path.resolve(path.dirname(__dirname)); var nodistBin = path.join(nodistDir,'bin'); var nodistLib = path.join(nodistDir,'lib'); +var goSrcDir = path.join(nodistDir,'src'); var npm = new (require('../lib/npm'))({nodistDir: stagingDir}); @@ -162,13 +163,13 @@ P.all([ console.log('Finished copying static files'); console.log('Compiling node shim'); - return exec('go build -o "'+stagingBin +'/node.exe" src/shim-node.go'); + return exec('go build -o "'+stagingBin +'/node.exe" shim-node.go', { cwd: goSrcDir }); }) .then(function(){ console.log('Done compiling node shim'); console.log('Compiling shim'); - return exec('go build -o "'+stagingBin +'/npm.exe" src/shim-npm.go'); + return exec('go build -o "'+stagingBin +'/npm.exe" shim-npm.go', { cwd: goSrcDir }); }) .then(function() { console.log('Done compiling npm shim'); diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 00000000..6d312fa5 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,8 @@ +module github.com/nullivex/nodist + +go 1.12 + +require ( + github.com/marcelklehr/semver v0.0.0-20160716173943-4590ea5640ed // indirect + github.com/visionmedia/go-debug v0.0.0-20180109164601-bfacf9d8a444 // indirect +) diff --git a/src/go.sum b/src/go.sum new file mode 100644 index 00000000..ee2f0810 --- /dev/null +++ b/src/go.sum @@ -0,0 +1,4 @@ +github.com/marcelklehr/semver v0.0.0-20160716173943-4590ea5640ed h1:VZykzf0AXHbHB5seNQ1cTmAIY3fYjx7ZnSN51R1hkMA= +github.com/marcelklehr/semver v0.0.0-20160716173943-4590ea5640ed/go.mod h1:f47/BgTZMEzS7Jz9fM/3uH/kNpv3l9mUq3HgP3p6Mh8= +github.com/visionmedia/go-debug v0.0.0-20180109164601-bfacf9d8a444 h1:omAc9LPzvfCMXi9UuEB9gbnSVXvz3Bft2zlKZn5Ww7Y= +github.com/visionmedia/go-debug v0.0.0-20180109164601-bfacf9d8a444/go.mod h1:7f/NuZ7w/RrrDGVKvezeak02MX7QbLs4Njo/I+GPxe0= diff --git a/src/lib/nodist/nodist.go b/src/lib/nodist.go similarity index 99% rename from src/lib/nodist/nodist.go rename to src/lib/nodist.go index 036c2812..c43f7616 100644 --- a/src/lib/nodist/nodist.go +++ b/src/lib/nodist.go @@ -1,4 +1,4 @@ -package nodist +package lib import ( "errors" @@ -10,7 +10,7 @@ import ( "github.com/marcelklehr/semver" ) -import . "github.com/computes/go-debug" +import . "github.com/visionmedia/go-debug" var debug = Debug("nodist:shim") const pathSep = string(os.PathSeparator) diff --git a/src/shim-node.go b/src/shim-node.go index f133a642..3764bb18 100644 --- a/src/shim-node.go +++ b/src/shim-node.go @@ -7,10 +7,10 @@ import ( "os/exec" "os/signal" "syscall" - "./lib/nodist" + nodist "github.com/nullivex/nodist/lib" ) -import . "github.com/computes/go-debug" +import . "github.com/visionmedia/go-debug" var debug = Debug("nodist:shim-node") diff --git a/src/shim-npm.go b/src/shim-npm.go index 57326d4b..5134cb24 100644 --- a/src/shim-npm.go +++ b/src/shim-npm.go @@ -6,10 +6,10 @@ import ( "os/exec" "os/signal" "syscall" - "./lib/nodist" + nodist "github.com/nullivex/nodist/lib" ) -import . "github.com/computes/go-debug" +import . "github.com/visionmedia/go-debug" var debug = Debug("nodist:shim-npm") From e29fcd9dd6800f55a0cee2ace2d27588570f0101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Fri, 13 May 2022 09:00:56 +0200 Subject: [PATCH 05/12] fix(build): use last x86 node version, fix last npm version and usage of symlinks --- README.md | 3 +++ build/build.js | 42 ++++++++++++++++++++++++++++++++++++++---- lib/npm.js | 15 +++++++++------ 3 files changed, 50 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index e1ebdf30..4c358060 100644 --- a/README.md +++ b/README.md @@ -289,6 +289,9 @@ MIT License v0.10.0 * Fix building shims (for newer go versions) by using go modules +* Fix getting latest npm version +* Use last available x86 version for building +* Resolve symlinks for npm's node_modules v0.9.1 * Fix issue with deprecated call to Tar.Extract in the NPM handler. diff --git a/build/build.js b/build/build.js index 9534801a..c813f175 100644 --- a/build/build.js +++ b/build/build.js @@ -82,8 +82,8 @@ var goSrcDir = path.join(nodistDir,'src'); var npm = new (require('../lib/npm'))({nodistDir: stagingDir}); //default npm version to the latest at the time of writing -var npmVersion = '3.3.8'; -var nodeVersion = '4.2.1'; +var npmVersion = '6.14.16'; +var nodeVersion = '16.15.0'; var versionPathx86 = ''; var versionPathx64 = ''; @@ -97,6 +97,32 @@ var uninstallFolders = []; 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) { + for (var key in nodeVersions) { + if (nodeVersions[key].files.includes(fileType)) { + return nodeVersions[key].version; + } + } +} + +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) @@ -181,7 +207,7 @@ P.all([ }); }) .then(function(res){ - nodeVersion = res.body[0].version; + nodeVersion = getLatestNodeVersionFor(res.body, 'win-x86-exe'); nodeLatestUrlx86 = nodeLatestUrlx86.replace('VERSION',nodeVersion); nodeLatestUrlx64 = nodeLatestUrlx64.replace('VERSION',nodeVersion); console.log('Latest version of Node ' + nodeVersion); @@ -253,8 +279,16 @@ P.all([ console.log('Install node_modules for distribution'); return exec('npm install',{cwd: stagingDir}); }) - .spread(function(){ + .then(function() { console.log('Installation complete'); + return resolveLinkedWorkspaces(path.join(stagingNpmDir, npmVersion.replace('v', ''), 'node_modules')); + }) + .then(function(movedLinks) { + if (movedLinks) { + console.log(`Resolved ${movedLinks} symlinks in node_modules folder`); + } + }) + .then(function() { console.log('Build Nodist.nsi'); return recursiveReaddir(stagingDir); }) diff --git a/lib/npm.js b/lib/npm.js index b72b3741..8c496ec9 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -102,13 +102,16 @@ NPMIST.listInstalled = function listInstalled(cb) { * @return {string} */ NPMIST.latestVersion = function(){ - return octokit.repos.getLatestRelease({ + // use list instead of getLatestRelease because there are non npm releases in the cli repo + return octokit.rest.repos.listReleases({ owner: 'npm', - repo: 'cli' - }) - .then(function(result){ - return result.data.tag_name; - }); + repo: 'cli', + per_page: 20 + }).then((response) => response.data.map(release => release.tag_name) + .filter((version) => /^v\d+\.\d+\.\d+$/.test(version)) + .sort(semver.compare) + .pop() + ); }; /** From 82ab4b6262188b2b5f7ef3ba380fb40664ea7e08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Fri, 13 May 2022 17:02:22 +0200 Subject: [PATCH 06/12] fix(tests): fix tests and add check for node and cleanup before run --- .gitignore | 2 ++ test/cli-test.js | 37 +++++++++++++++++++++++++------------ 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index ffa8805a..a8cabf75 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,5 @@ node_modules /build/out /npmv /pkg +/test/tmp +/node.exe diff --git a/test/cli-test.js b/test/cli-test.js index 90337b17..e3ca0b56 100644 --- a/test/cli-test.js +++ b/test/cli-test.js @@ -6,6 +6,7 @@ var nodist = require('../lib/nodist.js'); var fs = require('fs'); var path = require('path'); var spawn = require('child_process').spawn; +var rimraf = require('rimraf'); var testPath = path.resolve(__dirname + '/tmp'); var testVersion = '4.2.1'; @@ -18,6 +19,17 @@ var proxy = ( process.env.https_proxy || '' ); +// check if node is available for tests +if (!fs.existsSync(path.join(__dirname, '..', 'node.exe'))) { + console.log('node.exe missing in the main directory'); + process.exit(1); +} + +// clean testpath +if ((process.env.NODIST_TESTS_CLEAN || '1') === '1') { + rimraf.sync(testPath); +} + //setup new nodist var n = new nodist( process.env.NODIST_NODE_MIRROR || 'https://nodejs.org/dist', @@ -42,8 +54,8 @@ var execNodist = function execNodist(args, cb){ { env: { NODIST_PREFIX: testPath, - NODIST_NODE_MIRROR: n.iojsSourceUrl, - NODIST_IOJS_MIRROR: n.sourceUrl, + NODIST_NODE_MIRROR: n.sourceUrl, + NODIST_IOJS_MIRROR: n.iojsSourceUrl, HTTP_PROXY: proxy, DEBUG: process.env.DEBUG } @@ -60,13 +72,13 @@ var execNodist = function execNodist(args, cb){ stderr = stderr + chunk.toString(); }); cp.on('error', function(err){ - console.log('execution error',err); + debug('execNodist', 'exec failed with error', err); cb(err); }); cp.on('close', function(code){ - debug('execNodist', 'exec complete', code); - console.log('exit code',code); - cb(null, stdout, stderr, code); + var err = null; + debug('execNodist', 'exec completed with', { err, stdout, stderr, code }); + cb(err, stdout, stderr, code); }); }; @@ -76,9 +88,9 @@ vows.describe('nodist cli') topic: function() { execNodist(['add',testVersion], this.callback); }, - 'should install the specified version': function(err) { - console.log('got response for should install', err); + 'should install the specified version': function(err, stdout) { assert.isNull(err); + assert.match(stdout, new RegExp(testVersion)); debug('nodist add test for', n.getPathToExe(testVersion)); debug('nodist add exists', fs.existsSync(n.getPathToExe(testVersion))); assert.ok(fs.existsSync(n.getPathToExe(testVersion))); @@ -93,7 +105,7 @@ vows.describe('nodist cli') 'should list the installed version': function(err, stdout) { assert.ifError(err); var versions = stdout.toString().split('\n').map(function(v) { - return v.substr(2); + return v.trim(); }); assert.ok(versions.some(function(v) { return v === testVersion; })); } @@ -115,8 +127,9 @@ vows.describe('nodist cli') topic: function(){ execNodist(['rm',testVersion], this.callback); }, - 'should remove the specified version': function(err){ - assert.ifError(err); + 'should remove the specified version': function(err, stdout){ + assert.isNull(err); + assert.equal(stdout, ''); assert.ok(!fs.existsSync(n.getPathToExe(testVersion))); }, 'nodist list': { @@ -126,7 +139,7 @@ vows.describe('nodist cli') 'should not list the installed version': function(err, stdout){ assert.ifError(err); var versions = stdout.toString().split('\n').map(function(v){ - return v.substr(2); + return v.trim(); }); assert.ok(!versions.some(function(v) { return v === testVersion; })); } From 339ea5370f16f37d4303d6afbc6bde5e50c0d111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Fri, 13 May 2022 17:22:33 +0200 Subject: [PATCH 07/12] fix(chore): update dependencies, changelog, usage and build templates --- README.md | 11 +-- build/Nodist.template.nsi | 4 +- build/build.js | 1 - build/nodist.template.nuspec | 16 ++--- cli.js | 2 +- lib/npm.js | 1 - package-lock.json | 133 ++++++++++++++++------------------- package.json | 25 ++++--- usage.txt | 3 + 9 files changed, 95 insertions(+), 101 deletions(-) diff --git a/README.md b/README.md index 4c358060..556e7359 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ A node.js and npm version manager for the windows folks out there. Inspired by [n](https://github.com/visionmedia/n). And [nodenv](https://github.com/OiNutter/nodenv). -*Heads up! Nodist v0.8 is here! Nodist supports cmd, Powershell, Git bash and Cygwin!* +*Heads up! Nodist v0.10 is here! Nodist supports cmd, Powershell, Git bash and Cygwin!* ``` C:\> nodist + 5 @@ -252,7 +252,7 @@ To see all debug messages, set the DEBUG env var before running nodist or node a ## Testing -The default test suite can be ran using npm +The default test suite can be run using npm ``` $ npm test @@ -282,7 +282,7 @@ Afterwards you'll find the installer in `build/out/NodistSetup.exe` and fully pr The chocolatey package will be in `build/out/package`, you can run `cpack` and `cpush --source https://chocolatey.org/` inside that directory (if you are a registered maintainer). ## Legal -Copyright (c) 2012-2019 by Marcel Klehr, Bryan Tong (@nullivex) +Copyright (c) 2012-2022 by Marcel Klehr, Bryan Tong (@nullivex) MIT License ## Changelog @@ -290,8 +290,11 @@ MIT License v0.10.0 * Fix building shims (for newer go versions) by using go modules * Fix getting latest npm version -* Use last available x86 version for building +* Use last available x86 version for building (first node 18 versions are not available for x86) * Resolve symlinks for npm's node_modules +* Use octokit lib to access github, add NODIST_GITHUB_TOKEN env variable PR#246 +* Fix `npm ls` to resolve correct version PR#240 +* Fix tests v0.9.1 * Fix issue with deprecated call to Tar.Extract in the NPM handler. diff --git a/build/Nodist.template.nsi b/build/Nodist.template.nsi index 03d8217d..7b9b886e 100644 --- a/build/Nodist.template.nsi +++ b/build/Nodist.template.nsi @@ -6,9 +6,9 @@ !define APP_NAME "Nodist" !define COMP_NAME "Nodist" -!define WEB_SITE "https://github.com/marcelklehr/nodist" +!define WEB_SITE "https://github.com/nullivex/nodist" !define VERSION ";VERSION;.0" -!define COPYRIGHT "Marcel Klehr ? 2015" +!define COPYRIGHT "Marcel Klehr ? 2022" !define DESCRIPTION "Node Version Manager for Windows" !define LICENSE_TXT "staging\LICENSE.txt" !define INSTALLER_NAME "NodistSetup.exe" diff --git a/build/build.js b/build/build.js index c813f175..43bf301c 100644 --- a/build/build.js +++ b/build/build.js @@ -21,7 +21,6 @@ P.promisifyAll(fs); P.promisifyAll(helper); P.promisifyAll(request); exec = P.promisify(exec); -mkdirp = P.promisify(mkdirp); ncp = P.promisify(ncp); rimraf = P.promisify(rimraf); recursiveReaddir = P.promisify(recursiveReaddir); diff --git a/build/nodist.template.nuspec b/build/nodist.template.nuspec index bdaa2823..4fd5638e 100644 --- a/build/nodist.template.nuspec +++ b/build/nodist.template.nuspec @@ -7,16 +7,16 @@ Marcel Klehr Marcel Klehr A Node.js version manager. - A Node.js and io.js version manager. Inspired by n and nodenv. See github page https://github.com/marcelklehr/nodist for documentation. - https://github.com/marcelklehr/nodist - https://github.com/marcelklehr/nodist - https://raw.githubusercontent.com/marcelklehr/nodist/master/usage.txt - https://github.com/marcelklehr/nodist/issues + A Node.js and io.js version manager. Inspired by n and nodenv. See github page https://github.com/nullivex/nodist for documentation. + https://github.com/nullivex/nodist + https://github.com/nullivex/nodist + https://raw.githubusercontent.com/nullivex/nodist/master/usage.txt + https://github.com/marcelklehr/nullivex/issues node nodejs javascript admin nvm version management - 2013-2016 - https://github.com/marcelklehr/nodist/blob/master/LICENSE.txt + 2013-2022 + https://github.com/nullivex/nodist/blob/master/LICENSE.txt false - https://github.com/marcelklehr/nodist#changelog + https://github.com/nullivex/nodist#changelog diff --git a/cli.js b/cli.js index 8d5e7ccb..4632cabf 100644 --- a/cli.js +++ b/cli.js @@ -198,7 +198,7 @@ else if (command.match(/^npm$/i)){ }); }); } else - if(subcmd.match(/^remove|\-$/i)){ + if(subcmd.match(/^remove|rm|\-$/i)){ version = argv[2]; npm.resolveVersionLocally(version, function(er, v){ if(er) abort(er.message+'. Sorry.'); diff --git a/lib/npm.js b/lib/npm.js index 8c496ec9..3ced1937 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -16,7 +16,6 @@ var vermanager = require('./versions') //make some promising APIs P.promisifyAll(fs); -mkdirp = P.promisify(mkdirp); ncp = P.promisify(ncp); rimraf = P.promisify(rimraf); diff --git a/package-lock.json b/package-lock.json index beefd0cd..0473a9fc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "nodist", - "version": "0.9.1", + "version": "0.10.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -173,9 +173,9 @@ "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, "bluebird": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", - "integrity": "sha512-/qKPUQlaW1OyR51WeCPBvRnAlnZFUJkCSG5HzGnuIqhgyJtF+T94lFnn33eiazjRm2LAHVy2guNnaq48X9SJuw==" + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==" }, "brace-expansion": { "version": "1.1.11", @@ -192,9 +192,9 @@ "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, "chownr": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", - "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" }, "combined-stream": { "version": "1.0.7", @@ -223,11 +223,11 @@ } }, "debug": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz", - "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "requires": { - "ms": "^2.1.1" + "ms": "2.1.2" } }, "delayed-stream": { @@ -297,11 +297,11 @@ } }, "fs-minipass": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", - "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "requires": { - "minipass": "^2.2.1" + "minipass": "^3.0.0" } }, "fs.realpath": { @@ -424,6 +424,14 @@ "verror": "1.10.0" } }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, "mime-db": { "version": "1.38.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", @@ -445,40 +453,32 @@ "brace-expansion": "^1.1.7" } }, - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, "minipass": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", - "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", + "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==", "requires": { - "safe-buffer": "^5.1.2", - "yallist": "^3.0.0" + "yallist": "^4.0.0" } }, "minizlib": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.2.1.tgz", - "integrity": "sha512-7+4oTUOWKg7AuL3vloEWekXY2/D20cevzsrNT2kGWm+39J9hGTCBv8VI5Pm5lXZ/o3/mdR4f8rflAPhnQb8mPA==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "requires": { - "minipass": "^2.2.1" + "minipass": "^3.0.0", + "yallist": "^4.0.0" } }, "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" }, "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "ncp": { "version": "2.0.0", @@ -577,9 +577,9 @@ } }, "rimraf": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", - "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "requires": { "glob": "^7.1.3" } @@ -595,9 +595,12 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "semver": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.0.0.tgz", - "integrity": "sha512-0UewU+9rFapKFnlbirLi3byoOuhrSsli/z/ihNnvM24vgF+8sNBiI1LZPBSH9wJKUwaUbw+s3hToDLCXkrghrQ==" + "version": "7.3.7", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.7.tgz", + "integrity": "sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g==", + "requires": { + "lru-cache": "^6.0.0" + } }, "sshpk": { "version": "1.16.1", @@ -616,32 +619,16 @@ } }, "tar": { - "version": "4.4.8", - "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.8.tgz", - "integrity": "sha512-LzHF64s5chPQQS0IYBn9IN5h3i98c12bo4NCO7e0sGM2llXQ3p2FGC5sdENN4cTW48O915Sh+x+EXx7XW96xYQ==", - "requires": { - "chownr": "^1.1.1", - "fs-minipass": "^1.2.5", - "minipass": "^2.3.4", - "minizlib": "^1.1.1", - "mkdirp": "^0.5.0", - "safe-buffer": "^5.1.2", - "yallist": "^3.0.2" - }, - "dependencies": { - "minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - } + "version": "6.1.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", + "integrity": "sha512-an/KZQzQUkZCkuoAA64hM92X0Urb6VpRhAFllDzz44U2mcD5scmT3zBc4VgVpkugF580+DQn8eAFSyoQt0tznA==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^3.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" } }, "tough-cookie": { @@ -737,9 +724,9 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" }, "yallist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz", - "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A==" + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/package.json b/package.json index 62d24cb6..a6d5b950 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nodist", - "version": "0.9.1", + "version": "0.10.0", "description": "Natural node version manager for windows", "keywords": [ "node", @@ -10,32 +10,35 @@ "windows" ], "author": "Marcel Klehr ", - "homepage": "https://github.com/marcelklehr/nodist", + "homepage": "https://github.com/nullivex/nodist", "license": "MIT", "bugs": { - "url": "https://github.com/marcelklehr/nodist/issues" + "url": "https://github.com/nullivex/nodist/issues" }, "repository": { "type": "git", - "url": "http://github.com/marcelklehr/nodist.git" + "url": "https://github.com/nullivex/nodist.git" }, "dependencies": { "@octokit/rest": "^18.12.0", - "bluebird": "^3.5.3", - "debug": "^4.1.1", - "mkdirp": "~0.5", + "bluebird": "^3.7.2", + "debug": "^4.3.4", + "mkdirp": "^1.0.4", "ncp": "^2.0.0", - "progress": "2.x", + "progress": "^2.0.3", "promisepipe": "^3.0.0", "recursive-readdir": "^2.2.2", "request": "~2.88.0", - "rimraf": "~2", - "semver": "^6.0.0", - "tar": "4.x" + "rimraf": "^3.0.2", + "semver": "^7.3.7", + "tar": "^6.1.11" }, "devDependencies": { "vows": "^0.8.3" }, + "engines": { + "node": ">= 10" + }, "scripts": { "build": "node ./build/build.js", "test": "node ./node_modules/vows/bin/vows --spec ./test/*-test.js" diff --git a/usage.txt b/usage.txt index 42aaeffc..7b73871c 100644 --- a/usage.txt +++ b/usage.txt @@ -70,3 +70,6 @@ Env vars: from (e.g. http://mymirror.com/dist). NODIST_IOJS_MIRROR Set an alternative URL to fetch io.js exectuables from. + + NODIST_GITHUB_TOKEN Set a github token to bypass API rate limit exceeded errors + Checkout https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token From 8c9fa1c738582fed5c619e023670b2913865ad8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Fri, 13 May 2022 20:04:16 +0200 Subject: [PATCH 08/12] feat(npm8): support npm 8 by fixing symlinks during installation --- lib/npm.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/lib/npm.js b/lib/npm.js index 3ced1937..0fc9fd9d 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -36,6 +36,36 @@ 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 of changed links + */ +async function resolveLinkedWorkspaces(dirPath) { + let fixedLinks = 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); + debug('Fix symlink for ', filePath, 'with target', linkTarget); + await fs.unlinkAsync(filePath); + try { + await fs.symlinkAsync(linkTarget, filePath, 'junction'); + } catch (e) { + await fs.renameAsync(path.join(dirPath, linkTarget), filePath); + } + fixedLinks++; + } else if (file.isDirectory()) { + dirPromises.push(resolveLinkedWorkspaces(filePath)); + } + } + return (await Promise.all(dirPromises)).reduce((sum, num) => sum + num, fixedLinks); +} + /** * List available NPM versions * @return {string} @@ -274,6 +304,15 @@ NPMIST.install = function(v,done){ .on('end', resolve) }) }) + .then(() => { + if (semver.gte(version, '8.0.0')) { + debug('Fix symlinks for npm version >= 8'); + return resolveLinkedWorkspaces(path.join(archivePath, 'node_modules')) + .then(fixedLinks => { + debug(`Fixed ${fixedLinks} symlinks for npm node_modules`); + }); + } + }) .then(() => { done(null, version) }) From d7122b0c2b9ec774352b7c042a5fe6166f8a491f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Mon, 16 May 2022 14:33:39 +0200 Subject: [PATCH 09/12] build(nsis): use EnVar plugin for path env variable updates --- .jshintrc | 2 +- README.md | 3 +- build/Nodist.template.nsi | 193 ++------------------------------------ build/build.js | 10 +- 4 files changed, 16 insertions(+), 192 deletions(-) diff --git a/.jshintrc b/.jshintrc index 5f011f26..8bd37891 100644 --- a/.jshintrc +++ b/.jshintrc @@ -2,7 +2,7 @@ "asi": false, "laxcomma": true, "node": true, - "esnext": true, + "esversion": 8, "bitwise": false, "eqeqeq": true, "immed": true, diff --git a/README.md b/README.md index 556e7359..83da22ec 100644 --- a/README.md +++ b/README.md @@ -268,8 +268,9 @@ Testing also accepts env variables for using a mirror to download from, as well ## Building Building nodist requires * [go](https://golang.org) for compiling the shim - * [NSIS](http://nsis.sourceforge.net/Main_Page) v3 for compiling the installer (use the large strings build to avoid errors when manipulating PATH) + * [NSIS](http://nsis.sourceforge.net/Main_Page) v3 for compiling the installer * NSIS Plugin: [AccessControl](http://nsis.sourceforge.net/AccessControl_plug-in) + * NSIS Plugin: [EnVar Plugin](https://nsis.sourceforge.io/EnVar_plug-in) * node.js for running the build script * and npm for installing nodist's dependencies diff --git a/build/Nodist.template.nsi b/build/Nodist.template.nsi index 7b9b886e..a35b5327 100644 --- a/build/Nodist.template.nsi +++ b/build/Nodist.template.nsi @@ -7,11 +7,12 @@ !define APP_NAME "Nodist" !define COMP_NAME "Nodist" !define WEB_SITE "https://github.com/nullivex/nodist" -!define VERSION ";VERSION;.0" -!define COPYRIGHT "Marcel Klehr ? 2022" +!define SHORT_VERSION ";VERSION;" +!define COPYRIGHT "Marcel Klehr © 2015-2022" +!define VERSION "${SHORT_VERSION}.0" !define DESCRIPTION "Node Version Manager for Windows" !define LICENSE_TXT "staging\LICENSE.txt" -!define INSTALLER_NAME "NodistSetup.exe" +!define INSTALLER_NAME "NodistSetup-${SHORT_VERSION}.exe" !define MAIN_APP_EXE "node.exe" !define INSTALL_TYPE "SetShellVarContext all" !define REG_ROOT "HKLM" @@ -95,8 +96,8 @@ SetOutPath "$INSTDIR" ;ADD_FILES; ; Set Path -Push "$INSTDIR\bin" -Call AddToPath +EnVar::SetHKLM +EnVar::AddValue "Path" "$INSTDIR\bin" ; Detect x64 ${IF} ${RunningX64} @@ -187,8 +188,8 @@ ExecWait 'npm config delete prefix' ;DELETE_FOLDERS; ; Remove install dir from PATH -Push "$INSTDIR\bin" -Call un.RemoveFromPath +EnVar::SetHKLM +EnVar::DeleteValue "PATH" "$INSTDIR\bin" ; delete variables DeleteRegValue ${ENV_HKLM} NODIST_PREFIX @@ -224,181 +225,3 @@ RmDir "$SMPROGRAMS\Nodist" DeleteRegKey ${REG_ROOT} "${REG_APP_PATH}" DeleteRegKey ${REG_ROOT} "${UNINSTALL_PATH}" SectionEnd - -###################################################################### - -;-------------------------------------------------------------------- -; Path functions -; -; Based on example from: -; http://nsis.sourceforge.net/Path_Manipulation -; - -; Registry Entry for environment (NT4,2000,XP) -; All users: -!define Environ 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' -; Current user only: -;!define Environ 'HKCU "Environment"' - - -; AddToPath - Appends dir to PATH -; (does not work on Win9x/ME) -; -; Usage: -; Push "dir" -; Call AddToPath - -Function AddToPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - - ; NSIS ReadRegStr returns empty string on string overflow - ; Native calls are used here to check actual length of PATH - - ; $4 = RegOpenKey(HKEY_LOCAL_MACHINE, "SYSTEM\...\Environment", &$3) - System::Call "advapi32::RegOpenKey(i 0x80000002, t'SYSTEM\CurrentControlSet\Control\Session Manager\Environment', *i.r3) i.r4" - IntCmp $4 0 0 done done - ; $4 = RegQueryValueEx($3, "PATH", (DWORD*)0, (DWORD*)0, &$1, ($2=NSIS_MAX_STRLEN, &$2)) - ; RegCloseKey($3) - System::Call "advapi32::RegQueryValueEx(i $3, t'PATH', i 0, i 0, t.r1, *i ${NSIS_MAX_STRLEN} r2) i.r4" - System::Call "advapi32::RegCloseKey(i $3)" - - IntCmp $4 234 0 +4 +4 ; $4 == ERROR_MORE_DATA - DetailPrint "AddToPath: original length $2 > ${NSIS_MAX_STRLEN}" - MessageBox MB_OK "PATH not updated, original length $2 > ${NSIS_MAX_STRLEN}" - Goto done - - IntCmp $4 0 +5 ; $4 != NO_ERROR - IntCmp $4 2 +3 ; $4 != ERROR_FILE_NOT_FOUND - DetailPrint "AddToPath: unexpected error code $4" - Goto done - StrCpy $1 "" - - ; Check if already in PATH - Push "$1;" - Push "$0;" - Call StrStr - Pop $2 - StrCmp $2 "" 0 done - Push "$1;" - Push "$0\;" - Call StrStr - Pop $2 - StrCmp $2 "" 0 done - - ; Prevent NSIS string overflow - StrLen $2 $0 - StrLen $3 $1 - IntOp $2 $2 + $3 - IntOp $2 $2 + 2 ; $2 = strlen(dir) + strlen(PATH) + sizeof(";") - IntCmp $2 ${NSIS_MAX_STRLEN} +4 +4 0 - DetailPrint "AddToPath: new length $2 > ${NSIS_MAX_STRLEN}" - MessageBox MB_OK "PATH not updated, new length $2 > ${NSIS_MAX_STRLEN}." - Goto done - - ; Append dir to PATH - DetailPrint "Add to PATH: $0" - StrCpy $2 $1 1 -1 - StrCmp $2 ";" 0 +2 - StrCpy $1 $1 -1 ; remove trailing ';' - StrCmp $1 "" +2 ; no leading ';' - StrCpy $0 "$1;$0" - WriteRegExpandStr ${Environ} "PATH" $0 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - -done: - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - - -; RemoveFromPath - Removes dir from PATH -; -; Usage: -; Push "dir" -; Call RemoveFromPath - -Function un.RemoveFromPath - Exch $0 - Push $1 - Push $2 - Push $3 - Push $4 - Push $5 - Push $6 - - ReadRegStr $1 ${Environ} "PATH" - StrCpy $5 $1 1 -1 - StrCmp $5 ";" +2 - StrCpy $1 "$1;" ; ensure trailing ';' - Push $1 - Push "$0;" - Call un.StrStr - Pop $2 ; pos of our dir - StrCmp $2 "" done - - DetailPrint "Remove from PATH: $0" - StrLen $3 "$0;" - StrLen $4 $2 - StrCpy $5 $1 -$4 ; $5 is now the part before the path to remove - StrCpy $6 $2 "" $3 ; $6 is now the part after the path to remove - StrCpy $3 "$5$6" - StrCpy $5 $3 1 -1 - StrCmp $5 ";" 0 +2 - StrCpy $3 $3 -1 ; remove trailing ';' - WriteRegExpandStr ${Environ} "PATH" $3 - SendMessage ${HWND_BROADCAST} ${WM_WININICHANGE} 0 "STR:Environment" /TIMEOUT=5000 - -done: - Pop $6 - Pop $5 - Pop $4 - Pop $3 - Pop $2 - Pop $1 - Pop $0 -FunctionEnd - -; StrStr - find substring in a string -; -; Usage: -; Push "this is some string" -; Push "some" -; Call StrStr -; Pop $0 ; "some string" - -!macro StrStr un -Function ${un}StrStr - Exch $R1 ; $R1=substring, stack=[old$R1,string,...] - Exch ; stack=[string,old$R1,...] - Exch $R2 ; $R2=string, stack=[old$R2,old$R1,...] - Push $R3 - Push $R4 - Push $R5 - StrLen $R3 $R1 - StrCpy $R4 0 - ; $R1=substring, $R2=string, $R3=strlen(substring) - ; $R4=count, $R5=tmp - loop: - StrCpy $R5 $R2 $R3 $R4 - StrCmp $R5 $R1 done - StrCmp $R5 "" done - IntOp $R4 $R4 + 1 - Goto loop -done: - StrCpy $R1 $R2 "" $R4 - Pop $R5 - Pop $R4 - Pop $R3 - Pop $R2 - Exch $R1 ; $R1=old$R1, stack=[result,...] -FunctionEnd -!macroend -!insertmacro StrStr "" -!insertmacro StrStr "un." diff --git a/build/build.js b/build/build.js index 43bf301c..01cc2921 100644 --- a/build/build.js +++ b/build/build.js @@ -124,7 +124,7 @@ async function resolveLinkedWorkspaces(dirPath) { //start by clearing the staging and tmp folders P.all([ - rimraf(outDir) + rimraf(outDir), ]) .then(function(){ return P.all([ @@ -186,19 +186,19 @@ P.all([ }) .then(function(){ console.log('Finished copying static files'); - + console.log('Compiling node shim'); return exec('go build -o "'+stagingBin +'/node.exe" shim-node.go', { cwd: goSrcDir }); }) .then(function(){ console.log('Done compiling node shim'); - + console.log('Compiling shim'); return exec('go build -o "'+stagingBin +'/npm.exe" shim-npm.go', { cwd: goSrcDir }); }) .then(function() { console.log('Done compiling npm shim'); - + console.log('Determining latest version of node'); return request.getAsync({ url: 'https://nodejs.org/dist/index.json', @@ -364,7 +364,7 @@ P.all([ , helper.copyFileAsync(nodistDir+'/build/chocolateyuninstall.ps1', packageDir+'/tools/chocolateyuninstall.ps1') , helper.copyFileAsync(nodistDir+'/LICENSE.txt', packageDir+'/tools/LICENSE.txt') , helper.copyFileAsync(nodistDir+'/build/VERIFICATION.txt', packageDir+'/tools/VERIFICATION.txt') - , helper.copyFileAsync(outDir+'/NodistSetup.exe', packageDir+'/tools/Installer.exe') + , helper.copyFileAsync(outDir+'/NodistSetup-'+pkg.version+'.exe', packageDir+'/tools/Installer.exe') ]); }) .then(() => { From f8db08d21c81cc1985d419eca56cfbd43484ce92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Mon, 16 May 2022 18:11:19 +0200 Subject: [PATCH 10/12] feat(npx): add shim for npx --- README.md | 14 +++--- build/build.js | 10 +++- src/shim-npx.go | 127 ++++++++++++++++++++++++++++++++++++++++++++++++ usage.txt | 2 + 4 files changed, 145 insertions(+), 8 deletions(-) create mode 100644 src/shim-npx.go diff --git a/README.md b/README.md index 83da22ec..1716869d 100644 --- a/README.md +++ b/README.md @@ -58,7 +58,7 @@ source ~/.bashrc ``` ### Activating nodist in PowerShell -You might need to 'Unblock' the file `bin\nodist.ps1` by right clicking on it in the Explorer and selecting that menu entry. +You might need to 'Unblock' the file `bin\nodist.ps1` by right-clicking on it in the Explorer and selecting that menu entry. If you cannot see the unblock option after right-clicking > Properties in Explorer you can also perform the unblock via the following PowerShell command: @@ -121,13 +121,15 @@ When you're just running node, the *directory of interest* is the directory of t Package.json inspection is turned off by default as of nodist v0.8.5. You can turn it on by setting `NODIST_INSPECT_PACKAGEJSON=1`. -### npm -Any instances of node invoked by npm will be locked to the same version npm runs on. +### npm / npx +Any instances of node invoked by npm/npx will be locked to the same version npm/npx runs on. Currently, all node and npm versions share the same global npm module space. If you have installed native modules (globally or locally) you may have to run `npm rebuild` after changing the node version (implicitly or explicitly). There is an [open issue](https://github.com/marcelklehr/nodist/issues/169) about how to avoid rebuilding globally installed native modules, feedback/input is welcome. +The npx shim will try to run the npx shipped with the currently selected npm version. + ### Commands *All commands automatically install the latest matching version before setting the version pattern.* @@ -279,7 +281,7 @@ If you have met all requirements, run the build command: ``` > npm run build ``` -Afterwards you'll find the installer in `build/out/NodistSetup.exe` and fully prepared installation folder in `build/out/staging` (you could zip this, for example). +Afterwards you'll find the installer in `build/out/NodistSetup-vX.X.X.exe` and fully prepared installation folder in `build/out/staging` (you could zip this, for example). The chocolatey package will be in `build/out/package`, you can run `cpack` and `cpush --source https://chocolatey.org/` inside that directory (if you are a registered maintainer). ## Legal @@ -290,12 +292,12 @@ MIT License v0.10.0 * Fix building shims (for newer go versions) by using go modules +* 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) -* Resolve symlinks for npm's node_modules +* Resolve symlinks for npm's node_modules to support npm >= 8 * Use octokit lib to access github, add NODIST_GITHUB_TOKEN env variable PR#246 * Fix `npm ls` to resolve correct version PR#240 -* Fix tests v0.9.1 * Fix issue with deprecated call to Tar.Extract in the NPM handler. diff --git a/build/build.js b/build/build.js index 01cc2921..ff5cb56b 100644 --- a/build/build.js +++ b/build/build.js @@ -193,12 +193,18 @@ P.all([ .then(function(){ console.log('Done compiling node shim'); - console.log('Compiling shim'); + console.log('Compiling npm shim'); return exec('go build -o "'+stagingBin +'/npm.exe" shim-npm.go', { cwd: goSrcDir }); }) - .then(function() { + .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 }); + }) + .then(function() { + console.log('Done compiling npx shim'); + console.log('Determining latest version of node'); return request.getAsync({ url: 'https://nodejs.org/dist/index.json', diff --git a/src/shim-npx.go b/src/shim-npx.go new file mode 100644 index 00000000..54200044 --- /dev/null +++ b/src/shim-npx.go @@ -0,0 +1,127 @@ +package main + +import ( + "fmt" + "os" + "errors" + "os/exec" + "os/signal" + "syscall" + nodist "github.com/nullivex/nodist/lib" +) + +import . "github.com/visionmedia/go-debug" + +var debug = Debug("nodist:shim-npx") + +func main() { + if "" == os.Getenv("NODIST_PREFIX") { + fmt.Println("Please set the path to the nodist directory in the NODIST_PREFIX environment variable.") + os.Exit(40) + } + + dir, err := getTargetDirectory() + + if err != nil { + fmt.Println("Sorry, there's a problem with nodist. Couldn't determine the target directory. Please report this.") + os.Exit(46) + } + + // Determine node version first + + spec := nodist.GetCurrentNodeVersionSpec(dir) + + if spec == "" { + fmt.Println("Sorry, there's a problem with nodist. Couldn't decide which node version to use. Please set a version.") + os.Exit(41) + } + + version, err := nodist.ResolveNodeVersion(spec) + + if err != nil { + fmt.Println("Sorry, there's a problem with nodist. Couldn't resolve node version spec %s: %s", spec, err.Error()) + os.Exit(44) + } + + if version == "" { + fmt.Println("Sorry, there's a problem with nodist. Couldn't find an installed node version that matches version spec ", spec) + os.Exit(45) + } + + debug("determined node version: %s", version) + + // Determine npm version + + npmSpec := nodist.GetCurrentNpmVersionSpec(dir) + debug("current npm version spec: %s", npmSpec) + + if npmSpec == "" { + fmt.Println("Sorry, there's a problem with nodist. Couldn't decide which npm version to use. Please set a version.") + os.Exit(41) + } + + npmVersion, err := nodist.ResolveNpmVersion(npmSpec, version) + + if err != nil { + fmt.Println("Sorry, there's a problem with nodist. Couldn't resolve npm version spec", npmSpec, ":", err.Error()) + os.Exit(44) + } + + debug("determined npm version: %s", npmVersion) + + // Set up binary path + + path := os.Getenv("NODIST_PREFIX")+"/npmv" + + path = path+"/"+npmVersion + 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 npm! + + cmd := exec.Command("node", args...) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + cmd.Stdin = os.Stdin + cmd.Env = os.Environ() + cmd.Env = append(cmd.Env, "NODIST_NODE_VERSION="+version)// Lock the node version for all child processes + // Set npm prefix correctly. Can't do this in installer, since npm doesn't know where to look (it looks at /v/x.x.x/ by default, so we'd have to put an npmrc in every version folder, which is overkill) + cmd.Env = append(cmd.Env, "npm_config_prefix="+os.Getenv("NODIST_PREFIX")+"/bin") + + + // Proxy signals + sigc := make(chan os.Signal, 1) + signal.Notify(sigc) + go func() { + for s := range sigc { + cmd.Process.Signal(s) + } + }() + + err = cmd.Run() + signal.Stop(sigc) + + if err != nil { + exitError, isExitError := err.(*(exec.ExitError)) + if isExitError { + // You know it. Black Magic... + os.Exit(exitError.Sys().(syscall.WaitStatus).ExitStatus()) + } else { + fmt.Println("Sorry, there's a problem with nodist.") + fmt.Println("Error: ", err) + os.Exit(42) + } + } +} + +func getTargetDirectory() (dir string, returnedError error) { + dir, returnedError = os.Getwd() + return +} diff --git a/usage.txt b/usage.txt index 7b73871c..61f62b51 100644 --- a/usage.txt +++ b/usage.txt @@ -71,5 +71,7 @@ Env vars: NODIST_IOJS_MIRROR Set an alternative URL to fetch io.js exectuables from. + NODIST_INSPECT_PACKAGEJSON Will check the package.json for node / npm version when set to '1' + NODIST_GITHUB_TOKEN Set a github token to bypass API rate limit exceeded errors Checkout https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token From 55ea5d6824a32f7112d3a9dbc330144e70043ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Mon, 16 May 2022 19:03:41 +0200 Subject: [PATCH 11/12] feat(ci): add GitHub action workflows for tests and release - download used NSIS plugins before build and use them from that local folder - raise minimum node version (needed for building and using nodist) to 12 --- .github/workflows/release.yml | 31 ++++++ .github/workflows/tests.yml | 28 +++++ .gitignore | 1 + .jshintrc | 5 +- README.md | 2 + build/Nodist.template.nsi | 11 +- build/build.js | 4 + build/fetch_nsis_plugins.mjs | 60 +++++++++++ package-lock.json | 190 ++++++++++++++++++++++++++++++++++ package.json | 5 +- 10 files changed, 331 insertions(+), 6 deletions(-) create mode 100644 .github/workflows/release.yml create mode 100644 .github/workflows/tests.yml create mode 100644 build/fetch_nsis_plugins.mjs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..ffd2707c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,31 @@ +name: release + +on: + push: + tags: + - 'v[0-9]+.[0-9]+.[0-9]+' + - 'v[0-9]+.[0-9]+.[0-9]+-*' + +jobs: + run-build: + runs-on: windows-2022 + permissions: + contents: write + steps: + - uses: actions/checkout@v3 + - name: Use Node.js 16 + uses: actions/setup-node@v3 + with: + node-version: 16 + cache: 'npm' + - run: npm ci + - name: Copy Node.exe to repository directory + run: Copy-Item (Get-Command node.exe | Select-Object -ExpandProperty Definition) . + - run: npm test + - run: npm run build + - name: Create release draft + uses: ncipollo/release-action@v1 + with: + artifacts: "build/out/NodistSetup-*.exe" + token: ${{ secrets.GITHUB_TOKEN }} + draft: true diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 00000000..a6d172a9 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,28 @@ +name: run-tests + +on: + push: + branches: + - '**' + tags-ignore: + - '**' + +jobs: + run-tests: + runs-on: windows-2022 + + strategy: + matrix: + node-versions: [16.x] + + steps: + - uses: actions/checkout@v3 + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v3 + with: + node-version: ${{ matrix.node-version }} + cache: 'npm' + - run: npm ci + - name: Copy Node.exe to repository directory + run: Copy-Item (Get-Command node.exe | Select-Object -ExpandProperty Definition) . + - run: npm test diff --git a/.gitignore b/.gitignore index a8cabf75..f4d9c6eb 100644 --- a/.gitignore +++ b/.gitignore @@ -8,3 +8,4 @@ node_modules /pkg /test/tmp /node.exe +/build/nsis_plugins diff --git a/.jshintrc b/.jshintrc index 8bd37891..3f6c1172 100644 --- a/.jshintrc +++ b/.jshintrc @@ -2,7 +2,7 @@ "asi": false, "laxcomma": true, "node": true, - "esversion": 8, + "esversion": 11, "bitwise": false, "eqeqeq": true, "immed": true, @@ -15,5 +15,6 @@ "unused": true, "trailing": true, "smarttabs": true, - "strict": true + "strict": true, + "module": true } diff --git a/README.md b/README.md index 1716869d..8eaf2360 100644 --- a/README.md +++ b/README.md @@ -271,6 +271,7 @@ Testing also accepts env variables for using a mirror to download from, as well Building nodist requires * [go](https://golang.org) for compiling the shim * [NSIS](http://nsis.sourceforge.net/Main_Page) v3 for compiling the installer + * NSIS plugins will be automatically downloaded before build: * NSIS Plugin: [AccessControl](http://nsis.sourceforge.net/AccessControl_plug-in) * NSIS Plugin: [EnVar Plugin](https://nsis.sourceforge.io/EnVar_plug-in) * node.js for running the build script @@ -298,6 +299,7 @@ v0.10.0 * Resolve symlinks for npm's node_modules to support npm >= 8 * Use octokit lib to access github, add NODIST_GITHUB_TOKEN env variable PR#246 * Fix `npm ls` to resolve correct version PR#240 +* Minimal node version to build nodist raised to 12 v0.9.1 * Fix issue with deprecated call to Tar.Extract in the NPM handler. diff --git a/build/Nodist.template.nsi b/build/Nodist.template.nsi index a35b5327..c6f7ec86 100644 --- a/build/Nodist.template.nsi +++ b/build/Nodist.template.nsi @@ -18,6 +18,7 @@ !define REG_ROOT "HKLM" !define REG_APP_PATH "Software\Microsoft\Windows\CurrentVersion\App Paths\${MAIN_APP_EXE}" !define UNINSTALL_PATH "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APP_NAME}" +!define PLUGINS_PATH ";PLUGINS_PATH;" ; HKLM (all users) vs HKCU (current user) defines !define ENV_HKLM 'HKLM "SYSTEM\CurrentControlSet\Control\Session Manager\Environment"' @@ -27,6 +28,13 @@ !include "WinMessages.nsh" !include "x64.nsh" +; add additional plugins +!addplugindir /x86-ansi "${PLUGINS_PATH}\Plugins\x86-ansi" +!addplugindir /x86-ansi "${PLUGINS_PATH}\Plugins\i386-ansi" +!addplugindir /x86-unicode "${PLUGINS_PATH}\Plugins\x86-unicode" +!addplugindir /x86-unicode "${PLUGINS_PATH}\Plugins\i386-unicode" +!addplugindir /amd64-unicode "${PLUGINS_PATH}\Plugins\amd64-unicode" + ###################################################################### VIProductVersion "${VERSION}" @@ -49,9 +57,6 @@ InstallDir "$PROGRAMFILES\Nodist" ###################################################################### -!include "StrFunc.nsh" -${StrRep} - !include "MUI.nsh" !define MUI_ABORTWARNING diff --git a/build/build.js b/build/build.js index ff5cb56b..4cbb6942 100644 --- a/build/build.js +++ b/build/build.js @@ -329,6 +329,10 @@ P.all([ ';VERSION;', pkg.version ); + nsiTemplate = nsiTemplate.replace( + ';PLUGINS_PATH;', + path.join(nodistDir, 'build', 'nsis_plugins'), + ); nsiTemplate = nsiTemplate.replace( ';ADD_FILES;', installManifest.join('\n') diff --git a/build/fetch_nsis_plugins.mjs b/build/fetch_nsis_plugins.mjs new file mode 100644 index 00000000..fc938d2c --- /dev/null +++ b/build/fetch_nsis_plugins.mjs @@ -0,0 +1,60 @@ +'use strict'; + +import fs from 'fs'; +import os from 'os'; +import path from 'path'; +import * as stream from 'stream'; +import { fileURLToPath } from 'url'; +import { promisify } from 'util'; + +import axios from 'axios'; +import unzip from 'node-unzip-2'; + +const finished = promisify(stream.finished); + +const plugins = [ + 'https://nsis.sourceforge.io/mediawiki/images/7/7f/EnVar_plugin.zip', + 'https://nsis.sourceforge.io/mediawiki/images/4/4a/AccessControl.zip' +]; + +async function downloadFile(url, outputLocation) { + const writer = fs.createWriteStream(outputLocation); + + return axios.get(url, { responseType: 'stream' }).then(response => { + response.data.pipe(writer); + return finished(writer); + }); +} + +const dirname = path.dirname(fileURLToPath(import.meta.url)); +const nsisPluginsDir = path.join(dirname, 'nsis_plugins'); +const nsisPluginsInstalledFile = path.join(nsisPluginsDir, 'installed.txt'); + +if (fs.existsSync(nsisPluginsInstalledFile)) { + console.log('NSIS plugins installed already, skipping downloading plugins'); + process.exit(0); +} + +fs.mkdirSync(nsisPluginsDir); +const tmpDir = os.tmpdir(); + +Promise.all( + plugins.map(async (url) => { + const targetFileName = url.split('/').pop(); + const targetPath = path.join(tmpDir, targetFileName); + await downloadFile(url, targetPath); + const readStream = fs.createReadStream(targetPath); + const unzipped = new Promise(function(resolve, reject) { + readStream.on('close', resolve); + readStream.on('error', reject); + }); + readStream.pipe(unzip.Extract({ path: nsisPluginsDir })); + await unzipped; + return targetFileName; + }) +).then((plugins) => { + fs.writeFileSync(nsisPluginsInstalledFile, 'plugins installed'); + console.log('Finished downloading NSIS plugins'); + plugins.forEach(plugin => console.log(` - ${plugin}`)); +}); + diff --git a/package-lock.json b/package-lock.json index 0473a9fc..fd1e9087 100644 --- a/package-lock.json +++ b/package-lock.json @@ -154,6 +154,35 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + }, + "dependencies": { + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + } + } + }, "balanced-match": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", @@ -172,6 +201,16 @@ "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.2.tgz", "integrity": "sha512-3pZEU3NT5BFUo/AD5ERPWOgQOCZITni6iavr5AUw5AUwQjMlI0kzu5btnyD39AF0gUEsDPwJT+oY1ORBJijPjQ==" }, + "binary": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", + "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "chainsaw": "~0.1.0" + } + }, "bluebird": { "version": "3.7.2", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", @@ -186,11 +225,26 @@ "concat-map": "0.0.1" } }, + "buffers": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", + "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" }, + "chainsaw": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", + "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", + "dev": true, + "requires": { + "traverse": ">=0.3.0 <0.4" + } + }, "chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -281,6 +335,11 @@ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" }, + "follow-redirects": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.0.tgz", + "integrity": "sha512-aExlJShTV4qOUOL7yF1U5tvLCB0xQuudbf6toyYA0E/acBNw71mvjFTnLaRp50aQaYocMR0a/RMMBIHeZnGyjQ==" + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -309,6 +368,38 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, + "fstream": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "inherits": "~2.0.0", + "mkdirp": ">=0.5 0", + "rimraf": "2" + }, + "dependencies": { + "mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dev": true, + "requires": { + "minimist": "^1.2.6" + } + }, + "rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "dev": true, + "requires": { + "glob": "^7.1.3" + } + } + } + }, "getpass": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", @@ -340,6 +431,12 @@ } } }, + "graceful-fs": { + "version": "4.2.10", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", + "dev": true + }, "har-schema": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", @@ -388,6 +485,12 @@ "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" }, + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, "isstream": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", @@ -432,6 +535,16 @@ "yallist": "^4.0.0" } }, + "match-stream": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/match-stream/-/match-stream-0.0.2.tgz", + "integrity": "sha1-mesFAJOzTf+t5CG5rAtBCpz6F88=", + "dev": true, + "requires": { + "buffers": "~0.1.1", + "readable-stream": "~1.0.0" + } + }, "mime-db": { "version": "1.38.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.38.0.tgz", @@ -453,6 +566,12 @@ "brace-expansion": "^1.1.7" } }, + "minimist": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "dev": true + }, "minipass": { "version": "3.1.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz", @@ -493,6 +612,20 @@ "whatwg-url": "^5.0.0" } }, + "node-unzip-2": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-unzip-2/-/node-unzip-2-0.2.8.tgz", + "integrity": "sha512-fmJi73zTRW7RSo/1wyrKc2srKMwb3L6Ppke/7elzQ0QRt6sUjfiIcVsWdrqO5uEHAdvRKXjoySuo4HYe5BB0rw==", + "dev": true, + "requires": { + "binary": "~0.3.0", + "fstream": "~1.0.12", + "match-stream": "~0.0.2", + "pullstream": "~0.4.0", + "readable-stream": "~1.0.0", + "setimmediate": "~1.0.1" + } + }, "oauth-sign": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", @@ -506,6 +639,12 @@ "wrappy": "1" } }, + "over": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/over/-/over-0.0.5.tgz", + "integrity": "sha1-8phS5w/X4l82DgE6jsRMgq7bVwg=", + "dev": true + }, "path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", @@ -531,6 +670,18 @@ "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.31.tgz", "integrity": "sha512-/6pt4+C+T+wZUieKR620OpzN/LlnNKuWjy1iFLQ/UG35JqHlR/89MP1d96dUfkf6Dne3TuLQzOYEYshJ+Hx8mw==" }, + "pullstream": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/pullstream/-/pullstream-0.4.1.tgz", + "integrity": "sha1-1vs79a7Wl+gxFQ6xACwlo/iuExQ=", + "dev": true, + "requires": { + "over": ">= 0.0.5 < 1", + "readable-stream": "~1.0.31", + "setimmediate": ">= 1.0.2 < 2", + "slice-stream": ">= 1.0.0 < 2" + } + }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -541,6 +692,18 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, "recursive-readdir": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.2.tgz", @@ -602,6 +765,21 @@ "lru-cache": "^6.0.0" } }, + "setimmediate": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true + }, + "slice-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-stream/-/slice-stream-1.0.0.tgz", + "integrity": "sha1-WzO9ZvATsaf4ZGCwPUY97DmtPqA=", + "dev": true, + "requires": { + "readable-stream": "~1.0.31" + } + }, "sshpk": { "version": "1.16.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz", @@ -618,6 +796,12 @@ "tweetnacl": "~0.14.0" } }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, "tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -652,6 +836,12 @@ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" }, + "traverse": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", + "integrity": "sha1-cXuPIgzAu3tE5AUUwisui7xw2Lk=", + "dev": true + }, "tunnel-agent": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", diff --git a/package.json b/package.json index a6d5b950..79ac9298 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ }, "dependencies": { "@octokit/rest": "^18.12.0", + "axios": "^0.27.2", "bluebird": "^3.7.2", "debug": "^4.3.4", "mkdirp": "^1.0.4", @@ -34,12 +35,14 @@ "tar": "^6.1.11" }, "devDependencies": { + "node-unzip-2": "^0.2.8", "vows": "^0.8.3" }, "engines": { - "node": ">= 10" + "node": ">= 12" }, "scripts": { + "prebuild": "node ./build/fetch_nsis_plugins.mjs", "build": "node ./build/build.js", "test": "node ./node_modules/vows/bin/vows --spec ./test/*-test.js" }, From ca57c5a5efabb473ca2e168ea3828b78f1659145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Gro=C3=9Fe?= Date: Sat, 15 Oct 2022 11:58:16 +0200 Subject: [PATCH 12/12] fix(build): fetching of latest npm version could fail --- build/fetch_nsis_plugins.mjs | 1 + cli.js | 2 +- lib/npm.js | 31 +++++++++++++++++++++---------- test/cli-test.js | 10 ++-------- test/helper.js | 21 +++++++++++++++++++++ test/npm-test.js | 25 +++++++++++++++++++++++++ 6 files changed, 71 insertions(+), 19 deletions(-) create mode 100644 test/helper.js create mode 100644 test/npm-test.js diff --git a/build/fetch_nsis_plugins.mjs b/build/fetch_nsis_plugins.mjs index fc938d2c..53951a89 100644 --- a/build/fetch_nsis_plugins.mjs +++ b/build/fetch_nsis_plugins.mjs @@ -56,5 +56,6 @@ Promise.all( fs.writeFileSync(nsisPluginsInstalledFile, 'plugins installed'); console.log('Finished downloading NSIS plugins'); plugins.forEach(plugin => console.log(` - ${plugin}`)); + // TODO: remove files from tmp folder }); diff --git a/cli.js b/cli.js index 4632cabf..dd7616a5 100644 --- a/cli.js +++ b/cli.js @@ -83,7 +83,7 @@ var wantX64 = (+process.env.NODIST_X64) === 1; var envVersion = process.env.NODIST_NODE_VERSION ? process.env.NODIST_NODE_VERSION.replace(/"/g, '') : process.env.NODIST_NODE_VERSION; var npmEnvVersion = process.env.NODIST_NPM_VERSION ? - process.env.NODIST_NPM_VERSION.replace(/"/g, '') : process.NODIST_NPM_VERSION + process.env.NODIST_NPM_VERSION.replace(/"/g, '') : process.env.NODIST_NPM_VERSION; // Create a nodist instance var n = new nodist( diff --git a/lib/npm.js b/lib/npm.js index 0fc9fd9d..7743b20c 100644 --- a/lib/npm.js +++ b/lib/npm.js @@ -126,21 +126,32 @@ NPMIST.listInstalled = function listInstalled(cb) { }); }; -/** - * Get latest NPM version - * @return {string} - */ -NPMIST.latestVersion = function(){ - // use list instead of getLatestRelease because there are non npm releases in the cli repo +function getNpmReleases(page) { return octokit.rest.repos.listReleases({ owner: 'npm', repo: 'cli', - per_page: 20 + per_page: 50, + page, }).then((response) => response.data.map(release => release.tag_name) - .filter((version) => /^v\d+\.\d+\.\d+$/.test(version)) - .sort(semver.compare) - .pop() + .filter((version) => /^v\d+\.\d+\.\d+$/.test(version)) + .sort(semver.compare) ); +} + +/** + * Get latest NPM version + * @return {string} + */ +NPMIST.latestVersion = async function(){ + // use list instead of getLatestRelease because there are non npm releases in the cli repo + let releases = []; + let page = 1; + while (releases.length === 0) { + releases = await getNpmReleases(page); + page += 1; + } + + return releases.pop(); }; /** diff --git a/test/cli-test.js b/test/cli-test.js index e3ca0b56..f26a1e9c 100644 --- a/test/cli-test.js +++ b/test/cli-test.js @@ -2,13 +2,12 @@ var vows = require('vows'); var debug = require('debug')('nodist:test'); var assert = require('assert'); -var nodist = require('../lib/nodist.js'); var fs = require('fs'); var path = require('path'); var spawn = require('child_process').spawn; var rimraf = require('rimraf'); +var { testPath, createNodistInstance } = require('./helper'); -var testPath = path.resolve(__dirname + '/tmp'); var testVersion = '4.2.1'; //populate proxy if we can @@ -31,12 +30,7 @@ if ((process.env.NODIST_TESTS_CLEAN || '1') === '1') { } //setup new nodist -var n = new nodist( - process.env.NODIST_NODE_MIRROR || 'https://nodejs.org/dist', - process.env.NODIST_IOJS_MIRROR || 'https://iojs.org/dist', - path.resolve(testPath) -); - +var n = createNodistInstance(); /** * Exec Nodist for Testing diff --git a/test/helper.js b/test/helper.js new file mode 100644 index 00000000..7dfa33a0 --- /dev/null +++ b/test/helper.js @@ -0,0 +1,21 @@ +const path = require('path'); +const Nodist = require('../lib/nodist'); + +const testPath = path.resolve(__dirname + '/tmp'); + +const createNodistInstance = () => new Nodist( + process.env.NODIST_NODE_MIRROR || 'https://nodejs.org/dist', + process.env.NODIST_IOJS_MIRROR || 'https://iojs.org/dist', + path.resolve(testPath) +); + +const promiseWithCallback = (promise, callback) => promise.then( + res => { callback(null, res); }, + err => { callback(err); }, +); + +module.exports = { + createNodistInstance, + promiseWithCallback, + testPath, +}; diff --git a/test/npm-test.js b/test/npm-test.js new file mode 100644 index 00000000..1d8f497a --- /dev/null +++ b/test/npm-test.js @@ -0,0 +1,25 @@ +'use strict'; +const assert = require('assert'); +const debug = require('debug')('nodist:test'); +const vows = require('vows'); + +const Npmist = require('../lib/npm'); +const { createNodistInstance, promiseWithCallback } = require('./helper'); + +const npmBaseVersion = '6.10.1'; + +vows.describe('npm') + .addBatch({ + 'NPMIST': { + topic: new Npmist(createNodistInstance(), npmBaseVersion), + 'calling `latestVersion()`': { + topic(npmist) { promiseWithCallback(npmist.latestVersion(), this.callback); }, + 'should return valid version number': (error, result) => { + assert.ifError(error); + debug('latestVersion: ' + result); + assert.match(result, /^v\d+\.\d+\.\d+$/); + } + } + } + }) + .export(module);