Initial commit
This commit is contained in:
37
node_modules/update-check/.editorconfig
generated
vendored
Normal file
37
node_modules/update-check/.editorconfig
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[{*.json,*.json.example,*.gyp,*.yml,*.yaml}]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
|
||||
[{*.py,*.asm}]
|
||||
indent_style = space
|
||||
|
||||
[*.py]
|
||||
indent_size = 4
|
||||
|
||||
[*.asm]
|
||||
indent_size = 8
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
# Ideal settings - some plugins might support these.
|
||||
[*.js]
|
||||
quote_type = single
|
||||
|
||||
[{*.c,*.cc,*.h,*.hh,*.cpp,*.hpp,*.m,*.mm,*.mpp,*.js,*.java,*.go,*.rs,*.php,*.ng,*.jsx,*.ts,*.d,*.cs,*.swift}]
|
||||
curly_bracket_next_line = false
|
||||
spaces_around_operators = true
|
||||
spaces_around_brackets = outside
|
||||
# close enough to 1TB
|
||||
indent_brace_style = K&R
|
||||
1
node_modules/update-check/.yarnrc
generated
vendored
Normal file
1
node_modules/update-check/.yarnrc
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
save-prefix ""
|
||||
21
node_modules/update-check/LICENSE
generated
vendored
Normal file
21
node_modules/update-check/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2018 ZEIT, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
79
node_modules/update-check/README.md
generated
vendored
Normal file
79
node_modules/update-check/README.md
generated
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
# update-check
|
||||
|
||||
This is a very minimal approach to update checking for [globally installed](https://docs.npmjs.com/getting-started/installing-npm-packages-globally) packages.
|
||||
|
||||
Because it's so simple, the error surface is very tiny and your user's are guaranteed to receive the update message if there's a new version.
|
||||
|
||||
You can read more about the reasoning behind this project [here](https://twitter.com/notquiteleo/status/983193273224200192).
|
||||
|
||||
## Usage
|
||||
|
||||
Firstly, install the package with [yarn](https://yarnpkg.com/en/)...
|
||||
|
||||
```bash
|
||||
yarn add update-check
|
||||
```
|
||||
|
||||
...or [npm](https://www.npmjs.com/):
|
||||
|
||||
```bash
|
||||
npm install update-check
|
||||
```
|
||||
|
||||
Next, initialize it.
|
||||
|
||||
If there's a new update available, the package will return the content of latest version's `package.json` file:
|
||||
|
||||
```js
|
||||
const pkg = require('./package');
|
||||
const checkForUpdate = require('update-check');
|
||||
|
||||
let update = null;
|
||||
|
||||
try {
|
||||
update = await checkForUpdate(pkg);
|
||||
} catch (err) {
|
||||
console.error(`Failed to check for updates: ${err}`);
|
||||
}
|
||||
|
||||
if (update) {
|
||||
console.log(`The latest version is ${update.latest}. Please update!`);
|
||||
}
|
||||
```
|
||||
|
||||
That's it! You're done.
|
||||
|
||||
### Configuration
|
||||
|
||||
If you want, you can also pass options to customize the package's behavior:
|
||||
|
||||
```js
|
||||
const pkg = require('./package');
|
||||
const checkForUpdate = require('update-check');
|
||||
|
||||
let update = null;
|
||||
|
||||
try {
|
||||
update = await checkForUpdate(pkg, {
|
||||
interval: 3600000, // For how long to cache latest version (default: 1 day)
|
||||
distTag: 'canary' // A npm distribution tag for comparision (default: 'latest')
|
||||
});
|
||||
} catch (err) {
|
||||
console.error(`Failed to check for updates: ${err}`);
|
||||
}
|
||||
|
||||
if (update) {
|
||||
console.log(`The latest version is ${update.latest}. Please update!`);
|
||||
}
|
||||
```
|
||||
|
||||
## Contributing
|
||||
|
||||
1. [Fork](https://help.github.com/articles/fork-a-repo/) this repository to your own GitHub account and then [clone](https://help.github.com/articles/cloning-a-repository/) it to your local device
|
||||
2. Link the package to the global module directory: `npm link`
|
||||
3. Within the module you want to test your local development instance of the package, just link it: `npm link update-check`. Instead of the default one from npm, node will now use your clone.
|
||||
|
||||
## Author
|
||||
|
||||
Leo Lamprecht ([@notquiteleo](https://twitter.com/notquiteleo)) - [ZEIT](https://zeit.co)
|
||||
|
||||
201
node_modules/update-check/index.js
generated
vendored
Normal file
201
node_modules/update-check/index.js
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// Native
|
||||
const {URL} = require('url');
|
||||
const {join} = require('path');
|
||||
const fs = require('fs');
|
||||
const {promisify} = require('util');
|
||||
const {tmpdir} = require('os');
|
||||
|
||||
// Packages
|
||||
const registryUrl = require('registry-url');
|
||||
|
||||
const writeFile = promisify(fs.writeFile);
|
||||
const mkdir = promisify(fs.mkdir);
|
||||
const readFile = promisify(fs.readFile);
|
||||
const compareVersions = (a, b) => a.localeCompare(b, 'en-US', {numeric: true});
|
||||
const encode = value => encodeURIComponent(value).replace(/^%40/, '@');
|
||||
|
||||
const getFile = async (details, distTag) => {
|
||||
const rootDir = tmpdir();
|
||||
const subDir = join(rootDir, 'update-check');
|
||||
|
||||
if (!fs.existsSync(subDir)) {
|
||||
mkdir(subDir);
|
||||
}
|
||||
|
||||
let name = `${details.name}-${distTag}.json`;
|
||||
|
||||
if (details.scope) {
|
||||
name = `${details.scope}-${name}`;
|
||||
}
|
||||
|
||||
return join(subDir, name);
|
||||
};
|
||||
|
||||
const evaluateCache = async (file, time, interval) => {
|
||||
if (fs.existsSync(file)) {
|
||||
const content = await readFile(file, 'utf8');
|
||||
const {lastUpdate, latest} = JSON.parse(content);
|
||||
const nextCheck = lastUpdate + interval;
|
||||
|
||||
// As long as the time of the next check is in
|
||||
// the future, we don't need to run it yet
|
||||
if (nextCheck > time) {
|
||||
return {
|
||||
shouldCheck: false,
|
||||
latest
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
shouldCheck: true,
|
||||
latest: null
|
||||
};
|
||||
};
|
||||
|
||||
const updateCache = async (file, latest, lastUpdate) => {
|
||||
const content = JSON.stringify({
|
||||
latest,
|
||||
lastUpdate
|
||||
});
|
||||
|
||||
await writeFile(file, content, 'utf8');
|
||||
};
|
||||
|
||||
const loadPackage = (url, authInfo) => new Promise((resolve, reject) => {
|
||||
const options = {
|
||||
host: url.hostname,
|
||||
path: url.pathname,
|
||||
port: url.port,
|
||||
headers: {
|
||||
accept: 'application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*'
|
||||
},
|
||||
timeout: 2000
|
||||
};
|
||||
|
||||
if (authInfo) {
|
||||
options.headers.authorization = `${authInfo.type} ${authInfo.token}`;
|
||||
}
|
||||
|
||||
const {get} = require(url.protocol === 'https:' ? 'https' : 'http');
|
||||
get(options, response => {
|
||||
const {statusCode} = response;
|
||||
|
||||
if (statusCode !== 200) {
|
||||
const error = new Error(`Request failed with code ${statusCode}`);
|
||||
error.code = statusCode;
|
||||
|
||||
reject(error);
|
||||
|
||||
// Consume response data to free up RAM
|
||||
response.resume();
|
||||
return;
|
||||
}
|
||||
|
||||
let rawData = '';
|
||||
response.setEncoding('utf8');
|
||||
|
||||
response.on('data', chunk => {
|
||||
rawData += chunk;
|
||||
});
|
||||
|
||||
response.on('end', () => {
|
||||
try {
|
||||
const parsedData = JSON.parse(rawData);
|
||||
resolve(parsedData);
|
||||
} catch (e) {
|
||||
reject(e);
|
||||
}
|
||||
});
|
||||
}).on('error', reject).on('timeout', reject);
|
||||
});
|
||||
|
||||
const getMostRecent = async ({full, scope}, distTag) => {
|
||||
const regURL = registryUrl(scope);
|
||||
const url = new URL(full, regURL);
|
||||
|
||||
let spec = null;
|
||||
|
||||
try {
|
||||
spec = await loadPackage(url);
|
||||
} catch (err) {
|
||||
// We need to cover:
|
||||
// 401 or 403 for when we don't have access
|
||||
// 404 when the package is hidden
|
||||
if (err.code && String(err.code).startsWith(4)) {
|
||||
// We only want to load this package for when we
|
||||
// really need to use the token
|
||||
const registryAuthToken = require('registry-auth-token');
|
||||
const authInfo = registryAuthToken(regURL, {recursive: true});
|
||||
|
||||
spec = await loadPackage(url, authInfo);
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
const version = spec['dist-tags'][distTag];
|
||||
|
||||
if (!version) {
|
||||
throw new Error(`Distribution tag ${distTag} is not available`);
|
||||
}
|
||||
|
||||
return version;
|
||||
};
|
||||
|
||||
const defaultConfig = {
|
||||
interval: 3600000,
|
||||
distTag: 'latest'
|
||||
};
|
||||
|
||||
const getDetails = name => {
|
||||
const spec = {
|
||||
full: encode(name)
|
||||
};
|
||||
|
||||
if (name.includes('/')) {
|
||||
const parts = name.split('/');
|
||||
|
||||
spec.scope = parts[0];
|
||||
spec.name = parts[1];
|
||||
} else {
|
||||
spec.scope = null;
|
||||
spec.name = name;
|
||||
}
|
||||
|
||||
return spec;
|
||||
};
|
||||
|
||||
module.exports = async (pkg, config) => {
|
||||
if (typeof pkg !== 'object') {
|
||||
throw new Error('The first parameter should be your package.json file content');
|
||||
}
|
||||
|
||||
const details = getDetails(pkg.name);
|
||||
const time = Date.now();
|
||||
const {distTag, interval} = Object.assign({}, defaultConfig, config);
|
||||
const file = await getFile(details, distTag);
|
||||
|
||||
let latest = null;
|
||||
let shouldCheck = true;
|
||||
|
||||
({shouldCheck, latest} = await evaluateCache(file, time, interval));
|
||||
|
||||
if (shouldCheck) {
|
||||
latest = await getMostRecent(details, distTag);
|
||||
|
||||
// If we pulled an update, we need to update the cache
|
||||
await updateCache(file, latest, time);
|
||||
}
|
||||
|
||||
const comparision = compareVersions(pkg.version, latest);
|
||||
|
||||
if (comparision === -1) {
|
||||
return {
|
||||
latest,
|
||||
fromCache: !shouldCheck
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
37
node_modules/update-check/package.json
generated
vendored
Normal file
37
node_modules/update-check/package.json
generated
vendored
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "update-check",
|
||||
"version": "1.5.2",
|
||||
"description": "Minimalistic update notifications for command line interfaces",
|
||||
"main": "./index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"lint": "zeit-eslint --ext .jsx,.js .",
|
||||
"lint-staged": "git diff --diff-filter=ACMRT --cached --name-only '*.js' '*.jsx' | xargs zeit-eslint"
|
||||
},
|
||||
"repository": "zeit/update-check",
|
||||
"keywords": [
|
||||
"update",
|
||||
"notifications",
|
||||
"checker",
|
||||
"notifier"
|
||||
],
|
||||
"author": "leo",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@zeit/eslint-config-node": "0.2.13",
|
||||
"@zeit/git-hooks": "0.1.4",
|
||||
"eslint": "4.19.1"
|
||||
},
|
||||
"eslintConfig": {
|
||||
"extends": [
|
||||
"@zeit/eslint-config-node"
|
||||
]
|
||||
},
|
||||
"git": {
|
||||
"pre-commit": "lint-staged"
|
||||
},
|
||||
"dependencies": {
|
||||
"registry-auth-token": "3.3.2",
|
||||
"registry-url": "3.1.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user