deps: upgrade npm to 7.7.4

PR-URL: https://github.com/nodejs/node/pull/37897
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Rich Trott <rtrott@gmail.com>
This commit is contained in:
Ruy Adorno 2021-03-24 17:25:32 -04:00 committed by Rich Trott
parent 42dc4d14cd
commit ce300d6f76
82 changed files with 1001 additions and 2204 deletions

2
deps/npm/AUTHORS vendored
View File

@ -765,3 +765,5 @@ Jan Sepke <625043+jansepke@users.noreply.github.com>
Augusto Moura <augusto.borgesm@gmail.com>
Eric Chow <eric.zjp.chow@gmail.com>
kbayrhammer <klaus.bayrhammer@redbull.com>
James Chen-Smith <jameschensmith@gmail.com>
Yash Singh <saiansh2525@gmail.com>

77
deps/npm/CHANGELOG.md vendored
View File

@ -1,3 +1,80 @@
## v7.7.4 (2021-03-24)
### BUG FIXES
* [`200bee74b`](https://github.com/npm/cli/commit/200bee74b31a738687446b7b535cac67b1c582fd)
[#2951](https://github.com/npm/cli/issues/2951)
fix(config): accept explicit `production=false`
([@wraithgar](https://github.com/wraithgar))
* [`7b45e9df6`](https://github.com/npm/cli/commit/7b45e9df6102c7bd6e403d1fdc9939581c38f546)
[#2950](https://github.com/npm/cli/issues/2950)
warn if using workspaces config options in `npm config`
([@ruyadorno](https://github.com/ruyadorno))
## v7.7.3 (2021-03-24)
### BUG FIXES
* [`c76f04ac2`](https://github.com/npm/cli/commit/c76f04ac28ddf2ae4df4b3ce0aec684a118de1b5)
[#2925](https://github.com/npm/cli/issues/2925)
fix(set-script): add completion
([@Yash-Singh1](https://github.com/Yash-Singh1))
* [`0379eab69`](https://github.com/npm/cli/commit/0379eab698b78ae4aa89bbe2043607f420e52f11)
[#2929](https://github.com/npm/cli/issues/2929)
fix(install): ignore auditLevel
`npm install` should not be affected by the `auditLevel` config, as the
results of audit do not change its exit status.
([@wraithgar](https://github.com/wraithgar))
* [`98efadeb4`](https://github.com/npm/cli/commit/98efadeb4b2ae9289f14ed6f42a169230faf7239)
[#2923](https://github.com/npm/cli/issues/2923)
fix(audit-level): add `info` audit level
This is a valid level but wasn't configured to be allowed.
Also added this param to the usage output for `npm audit`
([@wraithgar](https://github.com/wraithgar))
* [`e8d2adcf4`](https://github.com/npm/cli/commit/e8d2adcf40ad63030f844c9aa44c6d16e2146797)
[#2945](https://github.com/npm/cli/issues/2945)
config should not error when workspaces are configured
([@nlf](https://github.com/nlf))
* [`aba2bc623`](https://github.com/npm/cli/commit/aba2bc623ea99e563b1b15b81dbb4ba94f86fe4c)
[#2944](https://github.com/npm/cli/issues/2944)
fix(progress): re-add progress bar to reify
The logger was no longer in flatOptions, we pass it in explicitly now
([@wraithgar](https://github.com/wraithgar))
* [`877b4ed29`](https://github.com/npm/cli/commit/877b4ed2925c97b5249a4d33575420dda64f7339)
[#2946](https://github.com/npm/cli/issues/2946)
fix(flatOptions): re-add `_auth`
This was not being added to flatOptions, and things like
`npm-registry-fetch` are looking for it.
([@wraithgar](https://github.com/wraithgar))
## v7.7.2 (2021-03-24)
### BUG FIXES
* [`a4df2b98d`](https://github.com/npm/cli/commit/a4df2b98d89429b19cd29b5fc895cdbfc0a6bd78)
[#2942](https://github.com/npm/cli/issues/2942)
Restore --dev flag, unify --omit flatteners
([@isaacs](https://github.com/isaacs))
### DEPENDENCIES
* [`2cbfaac0e`](https://github.com/npm/cli/commit/2cbfaac0ecd5810316f6d76168ed9618bd11bf3a)
`hosted-git-info@4.0.2`
* [#83](https://github.com/npm/hosted-git-info/pull/83) Do not parse
urls for gitlab
([@nlf](https://github.com/nlf))
## v7.7.1 (2021-03-24)
### BUG FIXES
* [`543b0e39b`](https://github.com/npm/cli/commit/543b0e39bcb94fc408804b01ca9c0d7b960b2681)
[#2930](https://github.com/npm/cli/issues/2930)
fix(uninstall): use correct local prefix
([@jameschensmith](https://github.com/jameschensmith))
* [`dce4960ef`](https://github.com/npm/cli/commit/dce4960ef6d52af128affe7755b2ca72de913b6c)
[#2932](https://github.com/npm/cli/issues/2932)
fix(config): flatten savePrefix properly
([@wraithgar](https://github.com/wraithgar))
## v7.7.0 (2021-03-23)
### FEATURES

View File

@ -21,3 +21,4 @@ duplications, without actually changing the package tree.
* [npm ls](/cli-commands/ls)
* [npm update](/cli-commands/update)
* [npm install](/cli-commands/install)

View File

@ -185,7 +185,7 @@ registry and all registries configured for scopes. See the documentation for
#### `audit-level`
* Default: null
* Type: "low", "moderate", "high", "critical", "none", or null
* Type: "info", "low", "moderate", "high", "critical", "none", or null
The minimum level of vulnerability for `npm audit` to exit with a non-zero
exit code.
@ -1382,6 +1382,14 @@ What authentication strategy to use with `adduser`/`login`.
`--cache-min=9999 (or bigger)` is an alias for `--prefer-offline`.
#### `dev`
* Default: false
* Type: Boolean
* DEPRECATED: Please use --include=dev instead.
Alias for `--include=dev`.
#### `init.author.email`
* Default: ""
@ -1451,8 +1459,8 @@ Alias for --include=optional or --omit=optional
#### `production`
* Default: false
* Type: Boolean
* Default: null
* Type: null or Boolean
* DEPRECATED: Use `--omit=dev` instead.
Alias for `--omit=dev`

View File

@ -159,7 +159,7 @@ tree at all, use <a href="../commands/npm-explain.html"><code>npm explain</code>
the results to only the paths to the packages named. Note that nested
packages will <em>also</em> show the paths to the specified packages. For
example, running <code>npm ls promzard</code> in npms source tree will show:</p>
<pre lang="bash"><code>npm@7.7.0 /path/to/npm
<pre lang="bash"><code>npm@7.7.4 /path/to/npm
└─┬ init-package-json@0.0.4
└── promzard@0.1.5
</code></pre>

View File

@ -148,7 +148,7 @@ npm command-line interface
<pre lang="bash"><code>npm &lt;command&gt; [args]
</code></pre>
<h3 id="version">Version</h3>
<p>7.7.0</p>
<p>7.7.4</p>
<h3 id="description">Description</h3>
<p>npm is the package manager for the Node JavaScript platform. It puts
modules in place so that node can find them, and manages dependency

File diff suppressed because one or more lines are too long

View File

@ -18,6 +18,7 @@ class Audit extends BaseCommand {
/* istanbul ignore next - see test/lib/load-all-commands.js */
static get params () {
return [
'audit-level',
'dry-run',
'force',
'json',

11
deps/npm/lib/ci.js vendored
View File

@ -42,8 +42,14 @@ class CI extends BaseCommand {
}
const where = this.npm.prefix
const arb = new Arborist({ ...this.npm.flatOptions, path: where })
const opts = {
...this.npm.flatOptions,
path: where,
log: this.npm.log,
save: false, // npm ci should never modify the lockfile or package.json
}
const arb = new Arborist(opts)
await Promise.all([
arb.loadVirtual().catch(er => {
log.verbose('loadVirtual', er.stack)
@ -55,8 +61,7 @@ class CI extends BaseCommand {
}),
removeNodeModules(where),
])
// npm ci should never modify the lockfile or package.json
await arb.reify({ ...this.npm.flatOptions, save: false })
await arb.reify(opts)
const ignoreScripts = this.npm.config.get('ignore-scripts')
// run the same set of scripts that `npm install` runs.

View File

@ -88,6 +88,11 @@ class Config extends BaseCommand {
this.config(args).then(() => cb()).catch(cb)
}
execWorkspaces (args, filters, cb) {
this.npm.log.warn('config', 'This command does not support workspaces.')
this.exec(args, cb)
}
async config ([action, ...args]) {
this.npm.log.disableProgress()
try {

View File

@ -30,6 +30,7 @@ class Dedupe extends BaseCommand {
const where = this.npm.prefix
const opts = {
...this.npm.flatOptions,
log: this.npm.log,
path: where,
dryRun,
}

12
deps/npm/lib/exec.js vendored
View File

@ -175,7 +175,11 @@ class Exec extends BaseCommand {
if (needInstall) {
const installDir = this.cacheInstallDir(packages)
await mkdirp(installDir)
const arb = new Arborist({ ...this.npm.flatOptions, path: installDir })
const arb = new Arborist({
...this.npm.flatOptions,
log: this.npm.log,
path: installDir,
})
const tree = await arb.loadActual()
// at this point, we have to ensure that we get the exact same
@ -212,7 +216,11 @@ class Exec extends BaseCommand {
throw new Error('canceled')
}
}
await arb.reify({ ...this.npm.flatOptions, add })
await arb.reify({
...this.npm.flatOptions,
log: this.npm.log,
add,
})
}
pathArr.unshift(resolve(installDir, 'node_modules/.bin'))
}

View File

@ -126,15 +126,16 @@ class Install extends BaseCommand {
if (this.npm.config.get('dev'))
log.warn('install', 'Usage of the `--dev` option is deprecated. Use `--include=dev` instead.')
const arb = new Arborist({
const opts = {
...this.npm.flatOptions,
log: this.npm.log,
auditLevel: null,
path: where,
})
await arb.reify({
...this.npm.flatOptions,
add: args,
})
}
const arb = new Arborist(opts)
await arb.reify(opts)
if (!args.length && !isGlobalInstall && !ignoreScripts) {
const scriptShell = this.npm.config.get('script-shell') || undefined
const scripts = [

View File

@ -66,6 +66,7 @@ class Link extends BaseCommand {
const globalOpts = {
...this.npm.flatOptions,
path: globalTop,
log: this.npm.log,
global: true,
prune: false,
}
@ -113,12 +114,14 @@ class Link extends BaseCommand {
// reify all the pending names as symlinks there
const localArb = new Arborist({
...this.npm.flatOptions,
log: this.npm.log,
path: this.npm.prefix,
save,
})
await localArb.reify({
...this.npm.flatOptions,
path: this.npm.prefix,
log: this.npm.log,
add: names.map(l => `file:${resolve(globalTop, 'node_modules', l)}`),
save,
})
@ -131,9 +134,13 @@ class Link extends BaseCommand {
const arb = new Arborist({
...this.npm.flatOptions,
path: globalTop,
log: this.npm.log,
global: true,
})
await arb.reify({ add: [`file:${this.npm.prefix}`] })
await arb.reify({
add: [`file:${this.npm.prefix}`],
log: this.npm.log,
})
await reifyFinish(this.npm, arb)
}

View File

@ -30,11 +30,13 @@ class Prune extends BaseCommand {
async prune () {
const where = this.npm.prefix
const arb = new Arborist({
const opts = {
...this.npm.flatOptions,
path: where,
})
await arb.prune(this.npm.flatOptions)
log: this.npm.log,
}
const arb = new Arborist(opts)
await arb.prune(opts)
await reifyFinish(this.npm, arb)
}
}

View File

@ -2,6 +2,7 @@ const log = require('npmlog')
const fs = require('fs')
const parseJSON = require('json-parse-even-better-errors')
const rpj = require('read-package-json-fast')
const { resolve } = require('path')
const BaseCommand = require('./base-command.js')
class SetScript extends BaseCommand {
@ -20,6 +21,16 @@ class SetScript extends BaseCommand {
return ['[<script>] [<command>]']
}
async completion (opts) {
const argv = opts.conf.argv.remain
if (argv.length === 2) {
// find the script name
const json = resolve(this.npm.localPrefix, 'package.json')
const { scripts = {} } = await rpj(json).catch(er => ({}))
return Object.keys(scripts)
}
}
exec (args, cb) {
this.set(args).then(() => cb()).catch(cb)
}

View File

@ -38,8 +38,9 @@ class Uninstall extends BaseCommand {
async uninstall (args) {
// the /path/to/node_modules/..
const global = this.npm.config.get('global')
const prefix = this.npm.config.get('prefix')
const path = global ? resolve(this.npm.globalDir, '..') : prefix
const path = global
? resolve(this.npm.globalDir, '..')
: this.npm.localPrefix
if (!args.length) {
if (!global)
@ -60,12 +61,15 @@ class Uninstall extends BaseCommand {
}
}
const arb = new Arborist({ ...this.npm.flatOptions, path })
await arb.reify({
const opts = {
...this.npm.flatOptions,
path,
log: this.npm.log,
rm: args,
})
}
const arb = new Arborist(opts)
await arb.reify(opts)
await reifyFinish(this.npm, arb)
}
}

View File

@ -51,6 +51,7 @@ class Update extends BaseCommand {
const arb = new Arborist({
...this.npm.flatOptions,
log: this.npm.log,
path: where,
})

View File

@ -22,6 +22,36 @@ const maybeReadFile = file => {
}
}
const buildOmitList = obj => {
const include = obj.include || []
const omit = obj.omit || []
const only = obj.only
if (/^prod(uction)?$/.test(only) || obj.production)
omit.push('dev')
else if (obj.production === false)
include.push('dev')
if (/^dev/.test(obj.also))
include.push('dev')
if (obj.dev)
include.push('dev')
if (obj.optional === false)
omit.push('optional')
else if (obj.optional === true)
include.push('optional')
obj.omit = [...new Set(omit)].filter(type => !include.includes(type))
obj.include = [...new Set(include)]
if (obj.omit.includes('dev'))
process.env.NODE_ENV = 'production'
return obj.omit
}
const editor = process.env.EDITOR ||
process.env.VISUAL ||
(isWindows ? 'notepad.exe' : 'vi')
@ -115,6 +145,7 @@ define('_auth', {
is safer to use a registry-provided authentication bearer token stored in
the ~/.npmrc file by running \`npm login\`.
`,
flatten,
})
define('access', {
@ -164,12 +195,6 @@ define('also', {
`,
deprecated: 'Please use --include=dev instead.',
flatten (key, obj, flatOptions) {
if (!/^dev(elopment)?$/.test(obj.also))
return
// add to include, and call the omit flattener
obj.include = obj.include || []
obj.include.push('dev')
definitions.omit.flatten('omit', obj, flatOptions)
},
})
@ -198,7 +223,7 @@ define('audit', {
define('audit-level', {
default: null,
type: ['low', 'moderate', 'high', 'critical', 'none', null],
type: ['info', 'low', 'moderate', 'high', 'critical', 'none', null],
description: `
The minimum level of vulnerability for \`npm audit\` to exit with
a non-zero exit code.
@ -477,6 +502,18 @@ define('description', {
},
})
define('dev', {
default: false,
type: Boolean,
description: `
Alias for \`--include=dev\`.
`,
deprecated: 'Please use --include=dev instead.',
flatten (key, obj, flatOptions) {
definitions.omit.flatten('omit', obj, flatOptions)
},
})
define('diff', {
default: [],
type: [String, Array],
@ -1218,10 +1255,7 @@ define('omit', {
scripts.
`,
flatten (key, obj, flatOptions) {
const include = obj.include || []
const omit = flatOptions.omit || []
flatOptions.omit = omit.concat(obj[key])
.filter(type => type && !include.includes(type))
flatOptions.omit = buildOmitList(obj)
},
})
@ -1236,12 +1270,6 @@ define('only', {
\`--omit=dev\`.
`,
flatten (key, obj, flatOptions) {
const value = obj[key]
if (!/^prod(uction)?$/.test(value))
return
obj.omit = obj.omit || []
obj.omit.push('dev')
definitions.omit.flatten('omit', obj, flatOptions)
},
})
@ -1259,16 +1287,6 @@ define('optional', {
Alias for --include=optional or --omit=optional
`,
flatten (key, obj, flatOptions) {
const value = obj[key]
if (value === null)
return
else if (value === true) {
obj.include = obj.include || []
obj.include.push('optional')
} else {
obj.omit = obj.omit || []
obj.omit.push('optional')
}
definitions.omit.flatten('omit', obj, flatOptions)
},
})
@ -1380,17 +1398,11 @@ define('preid', {
})
define('production', {
default: false,
type: Boolean,
default: null,
type: [null, Boolean],
deprecated: 'Use `--omit=dev` instead.',
description: 'Alias for `--omit=dev`',
flatten (key, obj, flatOptions) {
const value = obj[key]
if (!value)
return
obj.omit = obj.omit || []
obj.omit.push('dev')
definitions.omit.flatten('omit', obj, flatOptions)
},
})
@ -1581,7 +1593,9 @@ define('save-prefix', {
\`npm config set save-prefix='~'\` it would be set to \`~1.2.3\` which
only allows patch upgrades.
`,
flatten,
flatten (key, obj, flatOptions) {
flatOptions.savePrefix = obj['save-exact'] ? '' : obj['save-prefix']
},
})
define('save-prod', {

View File

@ -26,7 +26,7 @@ example, running \fBnpm ls promzard\fP in npm's source tree will show:
.P
.RS 2
.nf
npm@7\.7\.0 /path/to/npm
npm@7\.7\.4 /path/to/npm
└─┬ init\-package\-json@0\.0\.4
└── promzard@0\.1\.5
.fi

View File

@ -10,7 +10,7 @@ npm <command> [args]
.RE
.SS Version
.P
7\.7\.0
7\.7\.4
.SS Description
.P
npm is the package manager for the Node JavaScript platform\. It puts

View File

@ -245,7 +245,7 @@ npm help \fBaudit\fP for details on what is submitted\.
.IP \(bu 2
Default: null
.IP \(bu 2
Type: "low", "moderate", "high", "critical", "none", or null
Type: "info", "low", "moderate", "high", "critical", "none", or null
.RE
.P
@ -1847,6 +1847,18 @@ DEPRECATED: This option has been deprecated in favor of \fB\-\-prefer\-offline\f
.RE
.P
\fB\-\-cache\-min=9999 (or bigger)\fP is an alias for \fB\-\-prefer\-offline\fP\|\.
.SS \fBdev\fP
.RS 0
.IP \(bu 2
Default: false
.IP \(bu 2
Type: Boolean
.IP \(bu 2
DEPRECATED: Please use \-\-include=dev instead\.
.RE
.P
Alias for \fB\-\-include=dev\fP\|\.
.SS \fBinit\.author\.email\fP
.RS 0
.IP \(bu 2
@ -1949,9 +1961,9 @@ Alias for \-\-include=optional or \-\-omit=optional
.SS \fBproduction\fP
.RS 0
.IP \(bu 2
Default: false
Default: null
.IP \(bu 2
Type: Boolean
Type: null or Boolean
.IP \(bu 2
DEPRECATED: Use \fB\-\-omit=dev\fP instead\.

View File

@ -3,3 +3,4 @@
## 1.0.0
- Initial release

View File

@ -27,7 +27,7 @@ mapWorkspaces(`--- a/src/index.js
// @@ -1,4 +1,5 @@
// "use strict";
// +"use foo";
//
//
// const os = require("os");
```
@ -46,3 +46,4 @@ A **String** including the appropriate [ANSI escape codes](https://en.wikipedia.
## LICENSE
[ISC](./LICENSE)

View File

@ -4,14 +4,18 @@ const isFullwidthCodePoint = require('is-fullwidth-code-point');
const emojiRegex = require('emoji-regex');
const stringWidth = string => {
string = string.replace(emojiRegex(), ' ');
if (typeof string !== 'string' || string.length === 0) {
return 0;
}
string = stripAnsi(string);
if (string.length === 0) {
return 0;
}
string = string.replace(emojiRegex(), ' ');
let width = 0;
for (let i = 0; i < string.length; i++) {

View File

@ -1,6 +1,6 @@
{
"name": "string-width",
"version": "4.2.0",
"version": "4.2.2",
"description": "Get the visual width of a string - the number of columns required to display it",
"license": "MIT",
"repository": "sindresorhus/string-width",

View File

@ -1,4 +1,4 @@
# string-width [![Build Status](https://travis-ci.org/sindresorhus/string-width.svg?branch=master)](https://travis-ci.org/sindresorhus/string-width)
# string-width
> Get the visual width of a string - the number of columns required to display it

View File

@ -168,7 +168,7 @@ Basic example in a web page
const one = 'beep boop',
other = 'beep boob blah',
color = '';
let span = null;
const diff = Diff.diffChars(one, other),

View File

@ -13,26 +13,56 @@ declare namespace envPaths {
export interface Paths {
/**
Directory for data files.
Example locations (with the default `nodejs` suffix):
- macOS: `~/Library/Application Support/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Data` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Data`)
- Linux: `~/.local/share/MyApp-nodejs` (or `$XDG_DATA_HOME/MyApp-nodejs`)
*/
readonly data: string;
/**
Directory for data files.
Example locations (with the default `nodejs` suffix):
- macOS: `~/Library/Preferences/MyApp-nodejs`
- Windows: `%APPDATA%\MyApp-nodejs\Config` (for example, `C:\Users\USERNAME\AppData\Roaming\MyApp-nodejs\Config`)
- Linux: `~/.config/MyApp-nodejs` (or `$XDG_CONFIG_HOME/MyApp-nodejs`)
*/
readonly config: string;
/**
Directory for non-essential data files.
Example locations (with the default `nodejs` suffix):
- macOS: `~/Library/Caches/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Cache` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Cache`)
- Linux: `~/.cache/MyApp-nodejs` (or `$XDG_CACHE_HOME/MyApp-nodejs`)
*/
readonly cache: string;
/**
Directory for log files.
Example locations (with the default `nodejs` suffix):
- macOS: `~/Library/Logs/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Log` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Log`)
- Linux: `~/.local/state/MyApp-nodejs` (or `$XDG_STATE_HOME/MyApp-nodejs`)
*/
readonly log: string;
/**
Directory for temporary files.
Example locations (with the default `nodejs` suffix):
- macOS: `/var/folders/jf/f2twvvvs5jl_m49tf034ffpw0000gn/T/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\Temp\MyApp-nodejs` (for example, `C:\Users\USERNAME\AppData\Local\Temp\MyApp-nodejs`)
- Linux: `/tmp/USERNAME/MyApp-nodejs`
*/
readonly temp: string;
}
@ -42,6 +72,8 @@ declare const envPaths: {
/**
Get paths for storing things like data, config, cache, etc.
Note: It only generates the path strings. It doesn't create the directories for you. You could use [`make-dir`](https://github.com/sindresorhus/make-dir) to create the directories.
@param name - Name of your project. Used to generate the paths.
@returns The paths to use for your project on current OS.

View File

@ -1,6 +1,6 @@
{
"name": "env-paths",
"version": "2.2.0",
"version": "2.2.1",
"description": "Get paths for storing things like data, config, cache, etc",
"license": "MIT",
"repository": "sindresorhus/env-paths",

View File

@ -1,4 +1,4 @@
# env-paths [![Build Status](https://travis-ci.org/sindresorhus/env-paths.svg?branch=master)](https://travis-ci.org/sindresorhus/env-paths)
# env-paths
> Get paths for storing things like data, config, cache, etc
@ -29,7 +29,9 @@ paths.config
## API
### paths = envPaths(name, [options])
### paths = envPaths(name, options?)
Note: It only generates the path strings. It doesn't create the directories for you. You could use [`make-dir`](https://github.com/sindresorhus/make-dir) to create the directories.
#### name
@ -39,7 +41,7 @@ Name of your project. Used to generate the paths.
#### options
Type: `Object`
Type: `object`
##### suffix
@ -54,23 +56,60 @@ apps. Pass an empty string to disable it.
Directory for data files.
Example locations (with the default `nodejs` [suffix](#suffix)):
- macOS: `~/Library/Application Support/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Data` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Data`)
- Linux: `~/.local/share/MyApp-nodejs` (or `$XDG_DATA_HOME/MyApp-nodejs`)
### paths.config
Directory for config files.
Example locations (with the default `nodejs` [suffix](#suffix)):
- macOS: `~/Library/Preferences/MyApp-nodejs`
- Windows: `%APPDATA%\MyApp-nodejs\Config` (for example, `C:\Users\USERNAME\AppData\Roaming\MyApp-nodejs\Config`)
- Linux: `~/.config/MyApp-nodejs` (or `$XDG_CONFIG_HOME/MyApp-nodejs`)
### paths.cache
Directory for non-essential data files.
Example locations (with the default `nodejs` [suffix](#suffix)):
- macOS: `~/Library/Caches/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Cache` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Cache`)
- Linux: `~/.cache/MyApp-nodejs` (or `$XDG_CACHE_HOME/MyApp-nodejs`)
### paths.log
Directory for log files.
Example locations (with the default `nodejs` [suffix](#suffix)):
- macOS: `~/Library/Logs/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\MyApp-nodejs\Log` (for example, `C:\Users\USERNAME\AppData\Local\MyApp-nodejs\Log`)
- Linux: `~/.local/state/MyApp-nodejs` (or `$XDG_STATE_HOME/MyApp-nodejs`)
### paths.temp
Directory for temporary files.
Example locations (with the default `nodejs` [suffix](#suffix)):
## License
- macOS: `/var/folders/jf/f2twvvvs5jl_m49tf034ffpw0000gn/T/MyApp-nodejs`
- Windows: `%LOCALAPPDATA%\Temp\MyApp-nodejs` (for example, `C:\Users\USERNAME\AppData\Local\Temp\MyApp-nodejs`)
- Linux: `/tmp/USERNAME/MyApp-nodejs`
MIT © [Sindre Sorhus](https://sindresorhus.com)
---
<div align="center">
<b>
<a href="https://tidelift.com/subscription/pkg/npm-env-paths?utm_source=npm-env-paths&utm_medium=referral&utm_campaign=readme">Get professional support for this package with a Tidelift subscription</a>
</b>
<br>
<sub>
Tidelift helps make open source sustainable for maintainers while giving companies<br>assurances about security, maintenance, and licensing for their dependencies.
</sub>
</div>

View File

@ -79,7 +79,7 @@ gitHosts.gitlab = Object.assign({}, defaults, {
tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`,
extract: (url) => {
const path = url.pathname.slice(1)
if (path.includes('/-/')) {
if (path.includes('/-/') || path.includes('/archive.tar.gz')) {
return
}

View File

@ -1,6 +1,6 @@
{
"name": "hosted-git-info",
"version": "4.0.1",
"version": "4.0.2",
"description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab",
"main": "index.js",
"repository": {

View File

@ -27,3 +27,4 @@
## 1.0.0
- Initial release

View File

@ -34,8 +34,8 @@ Returns:
```patch
diff --git a/package.json b/package.json
index v1.1.0..v1.1.1 100644
--- a/package.json
+++ b/package.json
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "abbrev",
@ -95,3 +95,4 @@ Throws an error if either `a` or `b` are missing or if trying to diff more than
## LICENSE
[ISC](./LICENSE)

View File

@ -1,3 +1,11 @@
1.46.0 / 2021-02-13
===================
* Add extension `.amr` to `audio/amr`
* Add extension `.m4s` to `video/iso.segment`
* Add extension `.opus` to `audio/ogg`
* Add new upstream MIME types
1.45.0 / 2020-09-22
===================

View File

@ -3,7 +3,7 @@
[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-image]][node-url]
[![Build Status][travis-image]][travis-url]
[![Build Status][ci-image]][ci-url]
[![Coverage Status][coveralls-image]][coveralls-url]
This is a database of all mime types.
@ -91,6 +91,8 @@ definitively lists the media type. If an extension is going to be listed as
associateed with this media type, the source must definitively link the
media type and extension as well.
[ci-image]: https://badgen.net/github/checks/jshttp/mime-db/master?label=ci
[ci-url]: https://github.com/jshttp/mime-db/actions?query=workflow%3Aci
[coveralls-image]: https://badgen.net/coveralls/c/github/jshttp/mime-db/master
[coveralls-url]: https://coveralls.io/r/jshttp/mime-db?branch=master
[node-image]: https://badgen.net/npm/node/mime-db
@ -98,5 +100,3 @@ media type and extension as well.
[npm-downloads-image]: https://badgen.net/npm/dm/mime-db
[npm-url]: https://npmjs.org/package/mime-db
[npm-version-image]: https://badgen.net/npm/v/mime-db
[travis-image]: https://badgen.net/travis/jshttp/mime-db/master
[travis-url]: https://travis-ci.org/jshttp/mime-db

View File

@ -236,6 +236,9 @@
"application/cfw": {
"source": "iana"
},
"application/clr": {
"source": "iana"
},
"application/clue+xml": {
"source": "iana",
"compressible": true
@ -402,6 +405,15 @@
"application/efi": {
"source": "iana"
},
"application/elm+json": {
"source": "iana",
"charset": "UTF-8",
"compressible": true
},
"application/elm+xml": {
"source": "iana",
"compressible": true
},
"application/emergencycalldata.cap+xml": {
"source": "iana",
"charset": "UTF-8",
@ -663,6 +675,10 @@
"source": "iana",
"compressible": true
},
"application/jscalendar+json": {
"source": "iana",
"compressible": true
},
"application/json": {
"source": "iana",
"charset": "UTF-8",
@ -1171,6 +1187,10 @@
"source": "iana",
"extensions": ["cww"]
},
"application/prs.cyn": {
"source": "iana",
"charset": "7-BIT"
},
"application/prs.hpub+zip": {
"source": "iana",
"compressible": false
@ -1690,6 +1710,9 @@
"source": "iana",
"compressible": true
},
"application/vnd.3gpp.interworking-data": {
"source": "iana"
},
"application/vnd.3gpp.mc-signalling-ear": {
"source": "iana"
},
@ -1905,6 +1928,9 @@
"application/vnd.afpc.afplinedata-pagedef": {
"source": "iana"
},
"application/vnd.afpc.cmoca-cmresource": {
"source": "iana"
},
"application/vnd.afpc.foca-charset": {
"source": "iana"
},
@ -1917,6 +1943,9 @@
"application/vnd.afpc.modca": {
"source": "iana"
},
"application/vnd.afpc.modca-cmtable": {
"source": "iana"
},
"application/vnd.afpc.modca-formdef": {
"source": "iana"
},
@ -2334,6 +2363,14 @@
"application/vnd.cybank": {
"source": "iana"
},
"application/vnd.cyclonedx+json": {
"source": "iana",
"compressible": true
},
"application/vnd.cyclonedx+xml": {
"source": "iana",
"compressible": true
},
"application/vnd.d2l.coursepackage1p0+zip": {
"source": "iana",
"compressible": false
@ -2857,6 +2894,9 @@
"source": "iana",
"extensions": ["ggb"]
},
"application/vnd.geogebra.slides": {
"source": "iana"
},
"application/vnd.geogebra.tool": {
"source": "iana",
"extensions": ["ggt"]
@ -4812,6 +4852,10 @@
"source": "iana",
"extensions": ["see"]
},
"application/vnd.seis+json": {
"source": "iana",
"compressible": true
},
"application/vnd.sema": {
"source": "iana",
"extensions": ["sema"]
@ -5232,6 +5276,9 @@
"source": "iana",
"extensions": ["wtb"]
},
"application/vnd.wfa.dpp": {
"source": "iana"
},
"application/vnd.wfa.p2p": {
"source": "iana"
},
@ -6166,7 +6213,8 @@
"extensions": ["adp"]
},
"audio/amr": {
"source": "iana"
"source": "iana",
"extensions": ["amr"]
},
"audio/amr-wb": {
"source": "iana"
@ -6415,7 +6463,7 @@
"audio/ogg": {
"source": "iana",
"compressible": false,
"extensions": ["oga","ogg","spx"]
"extensions": ["oga","ogg","spx","opus"]
},
"audio/opus": {
"source": "iana"
@ -6463,6 +6511,9 @@
"source": "apache",
"extensions": ["s3m"]
},
"audio/scip": {
"source": "iana"
},
"audio/silk": {
"source": "apache",
"extensions": ["sil"]
@ -6806,6 +6857,7 @@
"source": "iana"
},
"image/avif": {
"source": "iana",
"compressible": false,
"extensions": ["avif"]
},
@ -7463,6 +7515,15 @@
"text/coffeescript": {
"extensions": ["coffee","litcoffee"]
},
"text/cql": {
"source": "iana"
},
"text/cql-expression": {
"source": "iana"
},
"text/cql-identifier": {
"source": "iana"
},
"text/css": {
"source": "iana",
"charset": "UTF-8",
@ -7492,6 +7553,9 @@
"text/enriched": {
"source": "iana"
},
"text/fhirpath": {
"source": "iana"
},
"text/flexfec": {
"source": "iana"
},
@ -7898,6 +7962,9 @@
"source": "iana",
"extensions": ["3g2"]
},
"video/av1": {
"source": "iana"
},
"video/bmpeg": {
"source": "iana"
},
@ -7944,7 +8011,8 @@
"source": "iana"
},
"video/iso.segment": {
"source": "iana"
"source": "iana",
"extensions": ["m4s"]
},
"video/jpeg": {
"source": "iana",
@ -8024,6 +8092,9 @@
"video/rtx": {
"source": "iana"
},
"video/scip": {
"source": "iana"
},
"video/smpte291": {
"source": "iana"
},

View File

@ -1,7 +1,7 @@
{
"name": "mime-db",
"description": "Media Type Database",
"version": "1.45.0",
"version": "1.46.0",
"contributors": [
"Douglas Christopher Wilson <doug@somethingdoug.com>",
"Jonathan Ong <me@jongleberry.com> (http://jongleberry.com)",
@ -22,16 +22,16 @@
"bluebird": "3.7.2",
"co": "4.6.0",
"cogent": "1.0.1",
"csv-parse": "4.12.0",
"eslint": "7.9.0",
"eslint-config-standard": "14.1.1",
"eslint-plugin-import": "2.22.0",
"csv-parse": "4.15.1",
"eslint": "7.20.0",
"eslint-config-standard": "15.0.1",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-markdown": "1.0.2",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-standard": "4.0.1",
"eslint-plugin-promise": "4.3.1",
"eslint-plugin-standard": "4.1.0",
"gnode": "0.1.2",
"mocha": "8.1.3",
"mocha": "8.3.0",
"nyc": "15.1.0",
"raw-body": "2.4.1",
"stream-to-array": "2.3.0"
@ -51,8 +51,8 @@
"fetch": "node scripts/fetch-apache && gnode scripts/fetch-iana && node scripts/fetch-nginx",
"lint": "eslint --plugin markdown --ext js,md .",
"test": "mocha --reporter spec --bail --check-leaks test/",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test",
"test-travis": "nyc --reporter=text npm test",
"update": "npm run fetch && npm run build",
"version": "node scripts/version-history.js && git add HISTORY.md"
}

View File

@ -1,3 +1,12 @@
2.1.29 / 2021-02-17
===================
* deps: mime-db@1.46.0
- Add extension `.amr` to `audio/amr`
- Add extension `.m4s` to `video/iso.segment`
- Add extension `.opus` to `audio/ogg`
- Add new upstream MIME types
2.1.28 / 2021-01-01
===================

View File

@ -36,8 +36,6 @@ so open a PR there if you'd like to add mime types.
## API
<!-- eslint-disable no-unused-vars -->
```js
var mime = require('mime-types')
```
@ -48,8 +46,6 @@ All functions return `false` if input is invalid or not found.
Lookup the content-type associated with a file.
<!-- eslint-disable no-undef -->
```js
mime.lookup('json') // 'application/json'
mime.lookup('.md') // 'text/markdown'
@ -68,8 +64,6 @@ content-type, otherwise the given content-type is used. Then if the
content-type does not already have a `charset` parameter, `mime.charset`
is used to get the default charset and add to the returned content-type.
<!-- eslint-disable no-undef -->
```js
mime.contentType('markdown') // 'text/x-markdown; charset=utf-8'
mime.contentType('file.json') // 'application/json; charset=utf-8'
@ -84,8 +78,6 @@ mime.contentType(path.extname('/path/to/file.json')) // 'application/json; chars
Get the default extension for a content-type.
<!-- eslint-disable no-undef -->
```js
mime.extension('application/octet-stream') // 'bin'
```
@ -94,8 +86,6 @@ mime.extension('application/octet-stream') // 'bin'
Lookup the implied default charset of a content-type.
<!-- eslint-disable no-undef -->
```js
mime.charset('text/markdown') // 'UTF-8'
```

View File

@ -1,7 +1,7 @@
{
"name": "mime-types",
"description": "The ultimate javascript content-type utility.",
"version": "2.1.28",
"version": "2.1.29",
"contributors": [
"Douglas Christopher Wilson <doug@somethingdoug.com>",
"Jeremiah Senkpiel <fishrock123@rocketmail.com> (https://searchbeam.jit.su)",
@ -14,17 +14,17 @@
],
"repository": "jshttp/mime-types",
"dependencies": {
"mime-db": "1.45.0"
"mime-db": "1.46.0"
},
"devDependencies": {
"eslint": "7.17.0",
"eslint": "7.20.0",
"eslint-config-standard": "14.1.1",
"eslint-plugin-import": "2.22.1",
"eslint-plugin-markdown": "1.0.2",
"eslint-plugin-markdown": "2.0.0",
"eslint-plugin-node": "11.1.0",
"eslint-plugin-promise": "4.2.1",
"eslint-plugin-promise": "4.3.1",
"eslint-plugin-standard": "4.1.0",
"mocha": "8.2.1",
"mocha": "8.3.0",
"nyc": "15.1.0"
},
"files": [
@ -36,7 +36,7 @@
"node": ">= 0.6"
},
"scripts": {
"lint": "eslint --plugin markdown --ext js,md .",
"lint": "eslint .",
"test": "mocha --reporter spec test/test.js",
"test-ci": "nyc --reporter=lcov --reporter=text npm test",
"test-cov": "nyc --reporter=html --reporter=text npm test"

View File

@ -1,185 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="3.0.8"></a>
## [3.0.8](https://github.com/npm/hosted-git-info/compare/v3.0.7...v3.0.8) (2021-01-28)
### Bug Fixes
* simplify the regular expression for shortcut matching ([bede0dc](https://github.com/npm/hosted-git-info/commit/bede0dc)), closes [#76](https://github.com/npm/hosted-git-info/issues/76)
<a name="3.0.7"></a>
## [3.0.7](https://github.com/npm/hosted-git-info/compare/v3.0.6...v3.0.7) (2020-10-15)
### Bug Fixes
* correctly filter out urls for tarballs in gitlab ([eb5bd5a](https://github.com/npm/hosted-git-info/commit/eb5bd5a)), closes [#69](https://github.com/npm/hosted-git-info/issues/69)
<a name="3.0.6"></a>
## [3.0.6](https://github.com/npm/hosted-git-info/compare/v3.0.5...v3.0.6) (2020-10-12)
### Bug Fixes
* support to github gist legacy hash length ([c067102](https://github.com/npm/hosted-git-info/commit/c067102)), closes [#68](https://github.com/npm/hosted-git-info/issues/68)
<a name="3.0.5"></a>
## [3.0.5](https://github.com/npm/hosted-git-info/compare/v3.0.4...v3.0.5) (2020-07-11)
<a name="3.0.4"></a>
## [3.0.4](https://github.com/npm/hosted-git-info/compare/v3.0.3...v3.0.4) (2020-02-26)
### Bug Fixes
* Do not pass scp-style URLs to the WhatWG url.URL ([0835306](https://github.com/npm/hosted-git-info/commit/0835306)), closes [#60](https://github.com/npm/hosted-git-info/issues/60) [#63](https://github.com/npm/hosted-git-info/issues/63)
<a name="3.0.3"></a>
## [3.0.3](https://github.com/npm/hosted-git-info/compare/v3.0.2...v3.0.3) (2020-02-25)
<a name="3.0.2"></a>
## [3.0.2](https://github.com/npm/hosted-git-info/compare/v3.0.1...v3.0.2) (2019-10-08)
### Bug Fixes
* do not encodeURIComponent the domain ([3e5fbec](https://github.com/npm/hosted-git-info/commit/3e5fbec)), closes [#53](https://github.com/npm/hosted-git-info/issues/53)
<a name="3.0.1"></a>
## [3.0.1](https://github.com/npm/hosted-git-info/compare/v3.0.0...v3.0.1) (2019-10-07)
### Bug Fixes
* update pathmatch for gitlab ([e3e3054](https://github.com/npm/hosted-git-info/commit/e3e3054)), closes [#52](https://github.com/npm/hosted-git-info/issues/52)
* updated pathmatch for gitlab ([fa87af7](https://github.com/npm/hosted-git-info/commit/fa87af7))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/npm/hosted-git-info/compare/v2.8.3...v3.0.0) (2019-08-12)
### Bug Fixes
* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([37c2891](https://github.com/npm/hosted-git-info/commit/37c2891)), closes [#38](https://github.com/npm/hosted-git-info/issues/38)
### BREAKING CHANGES
* **cache:** Drop support for node 0.x
<a name="2.8.3"></a>
## [2.8.3](https://github.com/npm/hosted-git-info/compare/v2.8.2...v2.8.3) (2019-08-12)
<a name="2.8.2"></a>
## [2.8.2](https://github.com/npm/hosted-git-info/compare/v2.8.1...v2.8.2) (2019-08-05)
### Bug Fixes
* http protocol use sshurl by default ([3b1d629](https://github.com/npm/hosted-git-info/commit/3b1d629)), closes [#48](https://github.com/npm/hosted-git-info/issues/48)
<a name="2.8.1"></a>
## [2.8.1](https://github.com/npm/hosted-git-info/compare/v2.8.0...v2.8.1) (2019-08-05)
### Bug Fixes
* ignore noCommittish on tarball url generation ([5d4a8d7](https://github.com/npm/hosted-git-info/commit/5d4a8d7))
* use gist tarball url that works for anonymous gists ([1692435](https://github.com/npm/hosted-git-info/commit/1692435))
<a name="2.8.0"></a>
# [2.8.0](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.0) (2019-08-05)
### Bug Fixes
* Allow slashes in gitlab project section ([bbcf7b2](https://github.com/npm/hosted-git-info/commit/bbcf7b2)), closes [#46](https://github.com/npm/hosted-git-info/issues/46) [#43](https://github.com/npm/hosted-git-info/issues/43)
* **git-host:** disallow URI-encoded slash (%2F) in `path` ([3776fa5](https://github.com/npm/hosted-git-info/commit/3776fa5)), closes [#44](https://github.com/npm/hosted-git-info/issues/44)
* **gitlab:** Do not URL encode slashes in project name for GitLab https URL ([cbf04f9](https://github.com/npm/hosted-git-info/commit/cbf04f9)), closes [#47](https://github.com/npm/hosted-git-info/issues/47)
* do not allow invalid gist urls ([d5cf830](https://github.com/npm/hosted-git-info/commit/d5cf830))
* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([e518222](https://github.com/npm/hosted-git-info/commit/e518222)), closes [#38](https://github.com/npm/hosted-git-info/issues/38)
### Features
* give these objects a name ([60abaea](https://github.com/npm/hosted-git-info/commit/60abaea))
<a name="2.7.1"></a>
## [2.7.1](https://github.com/npm/hosted-git-info/compare/v2.7.0...v2.7.1) (2018-07-07)
### Bug Fixes
* **index:** Guard against non-string types ([5bc580d](https://github.com/npm/hosted-git-info/commit/5bc580d))
* **parse:** Crash on strings that parse to having no host ([c931482](https://github.com/npm/hosted-git-info/commit/c931482)), closes [#35](https://github.com/npm/hosted-git-info/issues/35)
<a name="2.7.0"></a>
# [2.7.0](https://github.com/npm/hosted-git-info/compare/v2.6.1...v2.7.0) (2018-07-06)
### Bug Fixes
* **github tarball:** update github tarballtemplate ([6efd582](https://github.com/npm/hosted-git-info/commit/6efd582)), closes [#34](https://github.com/npm/hosted-git-info/issues/34)
* **gitlab docs:** switched to lowercase anchors for readmes ([701bcd1](https://github.com/npm/hosted-git-info/commit/701bcd1))
### Features
* **all:** Support www. prefixes on hostnames ([3349575](https://github.com/npm/hosted-git-info/commit/3349575)), closes [#32](https://github.com/npm/hosted-git-info/issues/32)
<a name="2.6.1"></a>
## [2.6.1](https://github.com/npm/hosted-git-info/compare/v2.6.0...v2.6.1) (2018-06-25)
### Bug Fixes
* **Revert:** "compat: remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25))" ([cce5a62](https://github.com/npm/hosted-git-info/commit/cce5a62))
* **Revert:** "git-host: fix forgotten extend()" ([a815ec9](https://github.com/npm/hosted-git-info/commit/a815ec9))
<a name="2.6.0"></a>
# [2.6.0](https://github.com/npm/hosted-git-info/compare/v2.5.0...v2.6.0) (2018-03-07)
### Bug Fixes
* **compat:** remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25)) ([627ab55](https://github.com/npm/hosted-git-info/commit/627ab55))
* **git-host:** fix forgotten extend() ([eba1f7b](https://github.com/npm/hosted-git-info/commit/eba1f7b))
### Features
* **browse:** fragment support for browse() ([#28](https://github.com/npm/hosted-git-info/issues/28)) ([cd5e5bb](https://github.com/npm/hosted-git-info/commit/cd5e5bb))

View File

@ -1,13 +0,0 @@
Copyright (c) 2015, Rebecca Turner
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,133 +0,0 @@
# hosted-git-info
This will let you identify and transform various git hosts URLs between
protocols. It also can tell you what the URL is for the raw path for
particular file for direct access without git.
## Example
```javascript
var hostedGitInfo = require("hosted-git-info")
var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opts)
/* info looks like:
{
type: "github",
domain: "github.com",
user: "npm",
project: "hosted-git-info"
}
*/
```
If the URL can't be matched with a git host, `null` will be returned. We
can match git, ssh and https urls. Additionally, we can match ssh connect
strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg,
`github:npm/hosted-git-info`). GitHub specifically, is detected in the case
of a third, unprefixed, form: `npm/hosted-git-info`.
If it does match, the returned object has properties of:
* info.type -- The short name of the service
* info.domain -- The domain for git protocol use
* info.user -- The name of the user/org on the git host
* info.project -- The name of the project on the git host
## Version Contract
The major version will be bumped any time…
* The constructor stops accepting URLs that it previously accepted.
* A method is removed.
* A method can no longer accept the number and type of arguments it previously accepted.
* A method can return a different type than it currently returns.
Implications:
* I do not consider the specific format of the urls returned from, say
`.https()` to be a part of the contract. The contract is that it will
return a string that can be used to fetch the repo via HTTPS. But what
that string looks like, specifically, can change.
* Dropping support for a hosted git provider would constitute a breaking
change.
## Usage
### var info = hostedGitInfo.fromUrl(gitSpecifier[, options])
* *gitSpecifer* is a URL of a git repository or a SCP-style specifier of one.
* *options* is an optional object. It can have the following properties:
* *noCommittish* — If true then committishes won't be included in generated URLs.
* *noGitPlus* — If true then `git+` won't be prefixed on URLs.
## Methods
All of the methods take the same options as the `fromUrl` factory. Options
provided to a method override those provided to the constructor.
* info.file(path, opts)
Given the path of a file relative to the repository, returns a URL for
directly fetching it from the githost. If no committish was set then
`master` will be used as the default.
For example `hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git#v1.0.0").file("package.json")`
would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/package.json`
* info.shortcut(opts)
eg, `github:npm/hosted-git-info`
* info.browse(path, fragment, opts)
eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/package.json`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/REAMDE.md#supported-hosts`
* info.bugs(opts)
eg, `https://github.com/npm/hosted-git-info/issues`
* info.docs(opts)
eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0#readme`
* info.https(opts)
eg, `git+https://github.com/npm/hosted-git-info.git`
* info.sshurl(opts)
eg, `git+ssh://git@github.com/npm/hosted-git-info.git`
* info.ssh(opts)
eg, `git@github.com:npm/hosted-git-info.git`
* info.path(opts)
eg, `npm/hosted-git-info`
* info.tarball(opts)
eg, `https://github.com/npm/hosted-git-info/archive/v1.2.0.tar.gz`
* info.getDefaultRepresentation()
Returns the default output type. The default output type is based on the
string you passed in to be parsed
* info.toString(opts)
Uses the getDefaultRepresentation to call one of the other methods to get a URL for
this resource. As such `hostedGitInfo.fromUrl(url).toString()` will give
you a normalized version of the URL that still uses the same protocol.
Shortcuts will still be returned as shortcuts, but the special case github
form of `org/project` will be normalized to `github:org/project`.
SSH connect strings will be normalized into `git+ssh` URLs.
## Supported hosts
Currently this supports GitHub, Bitbucket and GitLab. Pull requests for
additional hosts welcome.

View File

@ -1,154 +0,0 @@
'use strict'
const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : ''
const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : ''
const defaults = {
sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`,
sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`,
browsefiletemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'master')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`,
docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`,
httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
filetemplate: ({ domain, user, project, committish, path }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish) || 'master'}/${path}`,
shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin('#', committish)}`,
pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin('#', committish)}`,
bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`,
hashformat: formatHashFragment
}
const gitHosts = {}
gitHosts.github = Object.assign({}, defaults, {
// First two are insecure and generally shouldn't be used any more, but
// they are still supported.
protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'github.com',
treepath: 'tree',
filetemplate: ({ auth, user, project, committish, path }) => `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish) || 'master'}/${path}`,
gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish) || 'master'}`,
extract: (url) => {
let [, user, project, type, committish] = url.pathname.split('/', 5)
if (type && type !== 'tree') {
return
}
if (!type) {
committish = url.hash.slice(1)
}
if (project && project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (!user || !project) {
return
}
return { user, project, committish }
}
})
gitHosts.bitbucket = Object.assign({}, defaults, {
protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'bitbucket.org',
treepath: 'src',
tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish) || 'master'}.tar.gz`,
extract: (url) => {
let [, user, project, aux] = url.pathname.split('/', 4)
if (['get'].includes(aux)) {
return
}
if (project && project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (!user || !project) {
return
}
return { user, project, committish: url.hash.slice(1) }
}
})
gitHosts.gitlab = Object.assign({}, defaults, {
protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'gitlab.com',
treepath: 'tree',
httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`,
extract: (url) => {
const path = url.pathname.slice(1)
if (path.includes('/-/')) {
return
}
const segments = path.split('/')
let project = segments.pop()
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
const user = segments.join('/')
if (!user || !project) {
return
}
return { user, project, committish: url.hash.slice(1) }
}
})
gitHosts.gist = Object.assign({}, defaults, {
protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'gist.github.com',
sshtemplate: ({ domain, project, committish }) => `git@${domain}:${project}.git${maybeJoin('#', committish)}`,
sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`,
browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
browsefiletemplate: ({ domain, project, committish, path, hashformat }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`,
docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`,
filetemplate: ({ user, project, committish, path }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`,
shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin('#', committish)}`,
pathtemplate: ({ project, committish }) => `${project}${maybeJoin('#', committish)}`,
bugstemplate: ({ domain, project }) => `https://${domain}/${project}`,
gittemplate: ({ domain, project, committish }) => `git://${domain}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ project, committish }) => `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish) || 'master'}`,
extract: (url) => {
let [, user, project, aux] = url.pathname.split('/', 4)
if (aux === 'raw') {
return
}
if (!project) {
if (!user) {
return
}
project = user
user = null
}
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
return { user, project, committish: url.hash.slice(1) }
},
hashformat: function (fragment) {
return fragment && 'file-' + formatHashFragment(fragment)
}
})
const names = Object.keys(gitHosts)
gitHosts.byShortcut = {}
gitHosts.byDomain = {}
for (const name of names) {
gitHosts.byShortcut[`${name}:`] = name
gitHosts.byDomain[gitHosts[name].domain] = name
}
function formatHashFragment (fragment) {
return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
}
module.exports = gitHosts

View File

@ -1,110 +0,0 @@
'use strict'
const gitHosts = require('./git-host-info.js')
class GitHost {
constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) {
Object.assign(this, gitHosts[type])
this.type = type
this.user = user
this.auth = auth
this.project = project
this.committish = committish
this.default = defaultRepresentation
this.opts = opts
}
hash () {
return this.committish ? `#${this.committish}` : ''
}
ssh (opts) {
return this._fill(this.sshtemplate, opts)
}
_fill (template, opts) {
if (typeof template === 'function') {
const options = { ...this, ...this.opts, ...opts }
// the path should always be set so we don't end up with 'undefined' in urls
if (!options.path) {
options.path = ''
}
// template functions will insert the leading slash themselves
if (options.path.startsWith('/')) {
options.path = options.path.slice(1)
}
if (options.noCommittish) {
options.committish = null
}
const result = template(options)
return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result
}
return null
}
sshurl (opts) {
return this._fill(this.sshurltemplate, opts)
}
browse (path, fragment, opts) {
// not a string, treat path as opts
if (typeof path !== 'string') {
return this._fill(this.browsetemplate, path)
}
if (typeof fragment !== 'string') {
opts = fragment
fragment = null
}
return this._fill(this.browsefiletemplate, { ...opts, fragment, path })
}
docs (opts) {
return this._fill(this.docstemplate, opts)
}
bugs (opts) {
return this._fill(this.bugstemplate, opts)
}
https (opts) {
return this._fill(this.httpstemplate, opts)
}
git (opts) {
return this._fill(this.gittemplate, opts)
}
shortcut (opts) {
return this._fill(this.shortcuttemplate, opts)
}
path (opts) {
return this._fill(this.pathtemplate, opts)
}
tarball (opts) {
return this._fill(this.tarballtemplate, { ...opts, noCommittish: false })
}
file (path, opts) {
return this._fill(this.filetemplate, { ...opts, path })
}
getDefaultRepresentation () {
return this.default
}
toString (opts) {
if (this.default && typeof this[this.default] === 'function') {
return this[this.default](opts)
}
return this.sshurl(opts)
}
}
module.exports = GitHost

View File

@ -1,237 +0,0 @@
'use strict'
const url = require('url')
const gitHosts = require('./git-host-info.js')
const GitHost = module.exports = require('./git-host.js')
const LRU = require('lru-cache')
const cache = new LRU({ max: 1000 })
const protocolToRepresentationMap = {
'git+ssh:': 'sshurl',
'git+https:': 'https',
'ssh:': 'sshurl',
'git:': 'git'
}
function protocolToRepresentation (protocol) {
return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}
const authProtocols = {
'git:': true,
'https:': true,
'git+https:': true,
'http:': true,
'git+http:': true
}
const knownProtocols = Object.keys(gitHosts.byShortcut).concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:'])
module.exports.fromUrl = function (giturl, opts) {
if (typeof giturl !== 'string') {
return
}
const key = giturl + JSON.stringify(opts || {})
if (!cache.has(key)) {
cache.set(key, fromUrl(giturl, opts))
}
return cache.get(key)
}
function fromUrl (giturl, opts) {
if (!giturl) {
return
}
const url = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl)
const parsed = parseGitUrl(url)
if (!parsed) {
return parsed
}
const gitHostShortcut = gitHosts.byShortcut[parsed.protocol]
const gitHostDomain = gitHosts.byDomain[parsed.hostname.startsWith('www.') ? parsed.hostname.slice(4) : parsed.hostname]
const gitHostName = gitHostShortcut || gitHostDomain
if (!gitHostName) {
return
}
const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain]
let auth = null
if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) {
auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}`
}
let committish = null
let user = null
let project = null
let defaultRepresentation = null
try {
if (gitHostShortcut) {
let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname
const firstAt = pathname.indexOf('@')
// we ignore auth for shortcuts, so just trim it out
if (firstAt > -1) {
pathname = pathname.slice(firstAt + 1)
}
const lastSlash = pathname.lastIndexOf('/')
if (lastSlash > -1) {
user = decodeURIComponent(pathname.slice(0, lastSlash))
// we want nulls only, never empty strings
if (!user) {
user = null
}
project = decodeURIComponent(pathname.slice(lastSlash + 1))
} else {
project = decodeURIComponent(pathname)
}
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (parsed.hash) {
committish = decodeURIComponent(parsed.hash.slice(1))
}
defaultRepresentation = 'shortcut'
} else {
if (!gitHostInfo.protocols.includes(parsed.protocol)) {
return
}
const segments = gitHostInfo.extract(parsed)
if (!segments) {
return
}
user = segments.user && decodeURIComponent(segments.user)
project = decodeURIComponent(segments.project)
committish = decodeURIComponent(segments.committish)
defaultRepresentation = protocolToRepresentation(parsed.protocol)
}
} catch (err) {
/* istanbul ignore else */
if (err instanceof URIError) {
return
} else {
throw err
}
}
return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
}
// accepts input like git:github.com:user/repo and inserts the // after the first :
const correctProtocol = (arg) => {
const firstColon = arg.indexOf(':')
const proto = arg.slice(0, firstColon + 1)
if (knownProtocols.includes(proto)) {
return arg
}
const firstAt = arg.indexOf('@')
if (firstAt > -1) {
if (firstAt > firstColon) {
return `git+ssh://${arg}`
} else {
return arg
}
}
const doubleSlash = arg.indexOf('//')
if (doubleSlash === firstColon + 1) {
return arg
}
return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1)
}
// look for github shorthand inputs, such as npm/cli
const isGitHubShorthand = (arg) => {
// it cannot contain whitespace before the first #
// it cannot start with a / because that's probably an absolute file path
// but it must include a slash since repos are username/repository
// it cannot start with a . because that's probably a relative file path
// it cannot start with an @ because that's a scoped package if it passes the other tests
// it cannot contain a : before a # because that tells us that there's a protocol
// a second / may not exist before a #
const firstHash = arg.indexOf('#')
const firstSlash = arg.indexOf('/')
const secondSlash = arg.indexOf('/', firstSlash + 1)
const firstColon = arg.indexOf(':')
const firstSpace = /\s/.exec(arg)
const firstAt = arg.indexOf('@')
const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash)
const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash)
const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash)
const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash)
const hasSlash = firstSlash > 0
// if a # is found, what we really want to know is that the character immediately before # is not a /
const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/')
const doesNotStartWithDot = !arg.startsWith('.')
return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash && doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash && secondSlashOnlyAfterHash
}
// attempt to correct an scp style url so that it will parse with `new URL()`
const correctUrl = (giturl) => {
const firstAt = giturl.indexOf('@')
const lastHash = giturl.lastIndexOf('#')
let firstColon = giturl.indexOf(':')
let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity)
let corrected
if (lastColon > firstAt) {
// the last : comes after the first @ (or there is no @)
// like it would in:
// proto://hostname.com:user/repo
// username@hostname.com:user/repo
// :password@hostname.com:user/repo
// username:password@hostname.com:user/repo
// proto://username@hostname.com:user/repo
// proto://:password@hostname.com:user/repo
// proto://username:password@hostname.com:user/repo
// then we replace the last : with a / to create a valid path
corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1)
// // and we find our new : positions
firstColon = corrected.indexOf(':')
lastColon = corrected.lastIndexOf(':')
}
if (firstColon === -1 && giturl.indexOf('//') === -1) {
// we have no : at all
// as it would be in:
// username@hostname.com/user/repo
// then we prepend a protocol
corrected = `git+ssh://${corrected}`
}
return corrected
}
// try to parse the url as its given to us, if that throws
// then we try to clean the url and parse that result instead
// THIS FUNCTION SHOULD NEVER THROW
const parseGitUrl = (giturl) => {
let result
try {
result = new url.URL(giturl)
} catch (err) {}
if (result) {
return result
}
const correctedUrl = correctUrl(giturl)
try {
result = new url.URL(correctedUrl)
} catch (err) {}
return result
}

View File

@ -1,52 +0,0 @@
{
"name": "hosted-git-info",
"version": "4.0.1",
"description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/hosted-git-info.git"
},
"keywords": [
"git",
"github",
"bitbucket",
"gitlab"
],
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org)",
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/hosted-git-info/issues"
},
"homepage": "https://github.com/npm/hosted-git-info",
"scripts": {
"posttest": "standard",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"preversion": "npm test",
"snap": "tap",
"test": "tap",
"test:coverage": "tap --coverage-report=html"
},
"dependencies": {
"lru-cache": "^6.0.0"
},
"devDependencies": {
"standard": "^16.0.3",
"standard-version": "^9.1.0",
"tap": "^14.11.0"
},
"files": [
"index.js",
"git-host.js",
"git-host-info.js"
],
"engines": {
"node": ">=10"
},
"tap": {
"color": 1,
"coverage": true,
"esm": false
}
}

View File

@ -1,185 +0,0 @@
# Change Log
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
<a name="3.0.8"></a>
## [3.0.8](https://github.com/npm/hosted-git-info/compare/v3.0.7...v3.0.8) (2021-01-28)
### Bug Fixes
* simplify the regular expression for shortcut matching ([bede0dc](https://github.com/npm/hosted-git-info/commit/bede0dc)), closes [#76](https://github.com/npm/hosted-git-info/issues/76)
<a name="3.0.7"></a>
## [3.0.7](https://github.com/npm/hosted-git-info/compare/v3.0.6...v3.0.7) (2020-10-15)
### Bug Fixes
* correctly filter out urls for tarballs in gitlab ([eb5bd5a](https://github.com/npm/hosted-git-info/commit/eb5bd5a)), closes [#69](https://github.com/npm/hosted-git-info/issues/69)
<a name="3.0.6"></a>
## [3.0.6](https://github.com/npm/hosted-git-info/compare/v3.0.5...v3.0.6) (2020-10-12)
### Bug Fixes
* support to github gist legacy hash length ([c067102](https://github.com/npm/hosted-git-info/commit/c067102)), closes [#68](https://github.com/npm/hosted-git-info/issues/68)
<a name="3.0.5"></a>
## [3.0.5](https://github.com/npm/hosted-git-info/compare/v3.0.4...v3.0.5) (2020-07-11)
<a name="3.0.4"></a>
## [3.0.4](https://github.com/npm/hosted-git-info/compare/v3.0.3...v3.0.4) (2020-02-26)
### Bug Fixes
* Do not pass scp-style URLs to the WhatWG url.URL ([0835306](https://github.com/npm/hosted-git-info/commit/0835306)), closes [#60](https://github.com/npm/hosted-git-info/issues/60) [#63](https://github.com/npm/hosted-git-info/issues/63)
<a name="3.0.3"></a>
## [3.0.3](https://github.com/npm/hosted-git-info/compare/v3.0.2...v3.0.3) (2020-02-25)
<a name="3.0.2"></a>
## [3.0.2](https://github.com/npm/hosted-git-info/compare/v3.0.1...v3.0.2) (2019-10-08)
### Bug Fixes
* do not encodeURIComponent the domain ([3e5fbec](https://github.com/npm/hosted-git-info/commit/3e5fbec)), closes [#53](https://github.com/npm/hosted-git-info/issues/53)
<a name="3.0.1"></a>
## [3.0.1](https://github.com/npm/hosted-git-info/compare/v3.0.0...v3.0.1) (2019-10-07)
### Bug Fixes
* update pathmatch for gitlab ([e3e3054](https://github.com/npm/hosted-git-info/commit/e3e3054)), closes [#52](https://github.com/npm/hosted-git-info/issues/52)
* updated pathmatch for gitlab ([fa87af7](https://github.com/npm/hosted-git-info/commit/fa87af7))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/npm/hosted-git-info/compare/v2.8.3...v3.0.0) (2019-08-12)
### Bug Fixes
* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([37c2891](https://github.com/npm/hosted-git-info/commit/37c2891)), closes [#38](https://github.com/npm/hosted-git-info/issues/38)
### BREAKING CHANGES
* **cache:** Drop support for node 0.x
<a name="2.8.3"></a>
## [2.8.3](https://github.com/npm/hosted-git-info/compare/v2.8.2...v2.8.3) (2019-08-12)
<a name="2.8.2"></a>
## [2.8.2](https://github.com/npm/hosted-git-info/compare/v2.8.1...v2.8.2) (2019-08-05)
### Bug Fixes
* http protocol use sshurl by default ([3b1d629](https://github.com/npm/hosted-git-info/commit/3b1d629)), closes [#48](https://github.com/npm/hosted-git-info/issues/48)
<a name="2.8.1"></a>
## [2.8.1](https://github.com/npm/hosted-git-info/compare/v2.8.0...v2.8.1) (2019-08-05)
### Bug Fixes
* ignore noCommittish on tarball url generation ([5d4a8d7](https://github.com/npm/hosted-git-info/commit/5d4a8d7))
* use gist tarball url that works for anonymous gists ([1692435](https://github.com/npm/hosted-git-info/commit/1692435))
<a name="2.8.0"></a>
# [2.8.0](https://github.com/npm/hosted-git-info/compare/v2.7.1...v2.8.0) (2019-08-05)
### Bug Fixes
* Allow slashes in gitlab project section ([bbcf7b2](https://github.com/npm/hosted-git-info/commit/bbcf7b2)), closes [#46](https://github.com/npm/hosted-git-info/issues/46) [#43](https://github.com/npm/hosted-git-info/issues/43)
* **git-host:** disallow URI-encoded slash (%2F) in `path` ([3776fa5](https://github.com/npm/hosted-git-info/commit/3776fa5)), closes [#44](https://github.com/npm/hosted-git-info/issues/44)
* **gitlab:** Do not URL encode slashes in project name for GitLab https URL ([cbf04f9](https://github.com/npm/hosted-git-info/commit/cbf04f9)), closes [#47](https://github.com/npm/hosted-git-info/issues/47)
* do not allow invalid gist urls ([d5cf830](https://github.com/npm/hosted-git-info/commit/d5cf830))
* **cache:** Switch to lru-cache to save ourselves from unlimited memory consumption ([e518222](https://github.com/npm/hosted-git-info/commit/e518222)), closes [#38](https://github.com/npm/hosted-git-info/issues/38)
### Features
* give these objects a name ([60abaea](https://github.com/npm/hosted-git-info/commit/60abaea))
<a name="2.7.1"></a>
## [2.7.1](https://github.com/npm/hosted-git-info/compare/v2.7.0...v2.7.1) (2018-07-07)
### Bug Fixes
* **index:** Guard against non-string types ([5bc580d](https://github.com/npm/hosted-git-info/commit/5bc580d))
* **parse:** Crash on strings that parse to having no host ([c931482](https://github.com/npm/hosted-git-info/commit/c931482)), closes [#35](https://github.com/npm/hosted-git-info/issues/35)
<a name="2.7.0"></a>
# [2.7.0](https://github.com/npm/hosted-git-info/compare/v2.6.1...v2.7.0) (2018-07-06)
### Bug Fixes
* **github tarball:** update github tarballtemplate ([6efd582](https://github.com/npm/hosted-git-info/commit/6efd582)), closes [#34](https://github.com/npm/hosted-git-info/issues/34)
* **gitlab docs:** switched to lowercase anchors for readmes ([701bcd1](https://github.com/npm/hosted-git-info/commit/701bcd1))
### Features
* **all:** Support www. prefixes on hostnames ([3349575](https://github.com/npm/hosted-git-info/commit/3349575)), closes [#32](https://github.com/npm/hosted-git-info/issues/32)
<a name="2.6.1"></a>
## [2.6.1](https://github.com/npm/hosted-git-info/compare/v2.6.0...v2.6.1) (2018-06-25)
### Bug Fixes
* **Revert:** "compat: remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25))" ([cce5a62](https://github.com/npm/hosted-git-info/commit/cce5a62))
* **Revert:** "git-host: fix forgotten extend()" ([a815ec9](https://github.com/npm/hosted-git-info/commit/a815ec9))
<a name="2.6.0"></a>
# [2.6.0](https://github.com/npm/hosted-git-info/compare/v2.5.0...v2.6.0) (2018-03-07)
### Bug Fixes
* **compat:** remove Object.assign fallback ([#25](https://github.com/npm/hosted-git-info/issues/25)) ([627ab55](https://github.com/npm/hosted-git-info/commit/627ab55))
* **git-host:** fix forgotten extend() ([eba1f7b](https://github.com/npm/hosted-git-info/commit/eba1f7b))
### Features
* **browse:** fragment support for browse() ([#28](https://github.com/npm/hosted-git-info/issues/28)) ([cd5e5bb](https://github.com/npm/hosted-git-info/commit/cd5e5bb))

View File

@ -1,13 +0,0 @@
Copyright (c) 2015, Rebecca Turner
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.

View File

@ -1,133 +0,0 @@
# hosted-git-info
This will let you identify and transform various git hosts URLs between
protocols. It also can tell you what the URL is for the raw path for
particular file for direct access without git.
## Example
```javascript
var hostedGitInfo = require("hosted-git-info")
var info = hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git", opts)
/* info looks like:
{
type: "github",
domain: "github.com",
user: "npm",
project: "hosted-git-info"
}
*/
```
If the URL can't be matched with a git host, `null` will be returned. We
can match git, ssh and https urls. Additionally, we can match ssh connect
strings (`git@github.com:npm/hosted-git-info`) and shortcuts (eg,
`github:npm/hosted-git-info`). GitHub specifically, is detected in the case
of a third, unprefixed, form: `npm/hosted-git-info`.
If it does match, the returned object has properties of:
* info.type -- The short name of the service
* info.domain -- The domain for git protocol use
* info.user -- The name of the user/org on the git host
* info.project -- The name of the project on the git host
## Version Contract
The major version will be bumped any time…
* The constructor stops accepting URLs that it previously accepted.
* A method is removed.
* A method can no longer accept the number and type of arguments it previously accepted.
* A method can return a different type than it currently returns.
Implications:
* I do not consider the specific format of the urls returned from, say
`.https()` to be a part of the contract. The contract is that it will
return a string that can be used to fetch the repo via HTTPS. But what
that string looks like, specifically, can change.
* Dropping support for a hosted git provider would constitute a breaking
change.
## Usage
### var info = hostedGitInfo.fromUrl(gitSpecifier[, options])
* *gitSpecifer* is a URL of a git repository or a SCP-style specifier of one.
* *options* is an optional object. It can have the following properties:
* *noCommittish* — If true then committishes won't be included in generated URLs.
* *noGitPlus* — If true then `git+` won't be prefixed on URLs.
## Methods
All of the methods take the same options as the `fromUrl` factory. Options
provided to a method override those provided to the constructor.
* info.file(path, opts)
Given the path of a file relative to the repository, returns a URL for
directly fetching it from the githost. If no committish was set then
`master` will be used as the default.
For example `hostedGitInfo.fromUrl("git@github.com:npm/hosted-git-info.git#v1.0.0").file("package.json")`
would return `https://raw.githubusercontent.com/npm/hosted-git-info/v1.0.0/package.json`
* info.shortcut(opts)
eg, `github:npm/hosted-git-info`
* info.browse(path, fragment, opts)
eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/package.json`,
`https://github.com/npm/hosted-git-info/tree/v1.2.0/REAMDE.md#supported-hosts`
* info.bugs(opts)
eg, `https://github.com/npm/hosted-git-info/issues`
* info.docs(opts)
eg, `https://github.com/npm/hosted-git-info/tree/v1.2.0#readme`
* info.https(opts)
eg, `git+https://github.com/npm/hosted-git-info.git`
* info.sshurl(opts)
eg, `git+ssh://git@github.com/npm/hosted-git-info.git`
* info.ssh(opts)
eg, `git@github.com:npm/hosted-git-info.git`
* info.path(opts)
eg, `npm/hosted-git-info`
* info.tarball(opts)
eg, `https://github.com/npm/hosted-git-info/archive/v1.2.0.tar.gz`
* info.getDefaultRepresentation()
Returns the default output type. The default output type is based on the
string you passed in to be parsed
* info.toString(opts)
Uses the getDefaultRepresentation to call one of the other methods to get a URL for
this resource. As such `hostedGitInfo.fromUrl(url).toString()` will give
you a normalized version of the URL that still uses the same protocol.
Shortcuts will still be returned as shortcuts, but the special case github
form of `org/project` will be normalized to `github:org/project`.
SSH connect strings will be normalized into `git+ssh` URLs.
## Supported hosts
Currently this supports GitHub, Bitbucket and GitLab. Pull requests for
additional hosts welcome.

View File

@ -1,154 +0,0 @@
'use strict'
const maybeJoin = (...args) => args.every(arg => arg) ? args.join('') : ''
const maybeEncode = (arg) => arg ? encodeURIComponent(arg) : ''
const defaults = {
sshtemplate: ({ domain, user, project, committish }) => `git@${domain}:${user}/${project}.git${maybeJoin('#', committish)}`,
sshurltemplate: ({ domain, user, project, committish }) => `git+ssh://git@${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
browsetemplate: ({ domain, user, project, committish, treepath }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}`,
browsefiletemplate: ({ domain, user, project, committish, treepath, path, fragment, hashformat }) => `https://${domain}/${user}/${project}/${treepath}/${maybeEncode(committish || 'master')}/${path}${maybeJoin('#', hashformat(fragment || ''))}`,
docstemplate: ({ domain, user, project, treepath, committish }) => `https://${domain}/${user}/${project}${maybeJoin('/', treepath, '/', maybeEncode(committish))}#readme`,
httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
filetemplate: ({ domain, user, project, committish, path }) => `https://${domain}/${user}/${project}/raw/${maybeEncode(committish) || 'master'}/${path}`,
shortcuttemplate: ({ type, user, project, committish }) => `${type}:${user}/${project}${maybeJoin('#', committish)}`,
pathtemplate: ({ user, project, committish }) => `${user}/${project}${maybeJoin('#', committish)}`,
bugstemplate: ({ domain, user, project }) => `https://${domain}/${user}/${project}/issues`,
hashformat: formatHashFragment
}
const gitHosts = {}
gitHosts.github = Object.assign({}, defaults, {
// First two are insecure and generally shouldn't be used any more, but
// they are still supported.
protocols: ['git:', 'http:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'github.com',
treepath: 'tree',
filetemplate: ({ auth, user, project, committish, path }) => `https://${maybeJoin(auth, '@')}raw.githubusercontent.com/${user}/${project}/${maybeEncode(committish) || 'master'}/${path}`,
gittemplate: ({ auth, domain, user, project, committish }) => `git://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ domain, user, project, committish }) => `https://codeload.${domain}/${user}/${project}/tar.gz/${maybeEncode(committish) || 'master'}`,
extract: (url) => {
let [, user, project, type, committish] = url.pathname.split('/', 5)
if (type && type !== 'tree') {
return
}
if (!type) {
committish = url.hash.slice(1)
}
if (project && project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (!user || !project) {
return
}
return { user, project, committish }
}
})
gitHosts.bitbucket = Object.assign({}, defaults, {
protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'bitbucket.org',
treepath: 'src',
tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/get/${maybeEncode(committish) || 'master'}.tar.gz`,
extract: (url) => {
let [, user, project, aux] = url.pathname.split('/', 4)
if (['get'].includes(aux)) {
return
}
if (project && project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (!user || !project) {
return
}
return { user, project, committish: url.hash.slice(1) }
}
})
gitHosts.gitlab = Object.assign({}, defaults, {
protocols: ['git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'gitlab.com',
treepath: 'tree',
httpstemplate: ({ auth, domain, user, project, committish }) => `git+https://${maybeJoin(auth, '@')}${domain}/${user}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ domain, user, project, committish }) => `https://${domain}/${user}/${project}/repository/archive.tar.gz?ref=${maybeEncode(committish) || 'master'}`,
extract: (url) => {
const path = url.pathname.slice(1)
if (path.includes('/-/')) {
return
}
const segments = path.split('/')
let project = segments.pop()
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
const user = segments.join('/')
if (!user || !project) {
return
}
return { user, project, committish: url.hash.slice(1) }
}
})
gitHosts.gist = Object.assign({}, defaults, {
protocols: ['git:', 'git+ssh:', 'git+https:', 'ssh:', 'https:'],
domain: 'gist.github.com',
sshtemplate: ({ domain, project, committish }) => `git@${domain}:${project}.git${maybeJoin('#', committish)}`,
sshurltemplate: ({ domain, project, committish }) => `git+ssh://git@${domain}/${project}.git${maybeJoin('#', committish)}`,
browsetemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
browsefiletemplate: ({ domain, project, committish, path, hashformat }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}${maybeJoin('#', hashformat(path))}`,
docstemplate: ({ domain, project, committish }) => `https://${domain}/${project}${maybeJoin('/', maybeEncode(committish))}`,
httpstemplate: ({ domain, project, committish }) => `git+https://${domain}/${project}.git${maybeJoin('#', committish)}`,
filetemplate: ({ user, project, committish, path }) => `https://gist.githubusercontent.com/${user}/${project}/raw${maybeJoin('/', maybeEncode(committish))}/${path}`,
shortcuttemplate: ({ type, project, committish }) => `${type}:${project}${maybeJoin('#', committish)}`,
pathtemplate: ({ project, committish }) => `${project}${maybeJoin('#', committish)}`,
bugstemplate: ({ domain, project }) => `https://${domain}/${project}`,
gittemplate: ({ domain, project, committish }) => `git://${domain}/${project}.git${maybeJoin('#', committish)}`,
tarballtemplate: ({ project, committish }) => `https://codeload.github.com/gist/${project}/tar.gz/${maybeEncode(committish) || 'master'}`,
extract: (url) => {
let [, user, project, aux] = url.pathname.split('/', 4)
if (aux === 'raw') {
return
}
if (!project) {
if (!user) {
return
}
project = user
user = null
}
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
return { user, project, committish: url.hash.slice(1) }
},
hashformat: function (fragment) {
return fragment && 'file-' + formatHashFragment(fragment)
}
})
const names = Object.keys(gitHosts)
gitHosts.byShortcut = {}
gitHosts.byDomain = {}
for (const name of names) {
gitHosts.byShortcut[`${name}:`] = name
gitHosts.byDomain[gitHosts[name].domain] = name
}
function formatHashFragment (fragment) {
return fragment.toLowerCase().replace(/^\W+|\/|\W+$/g, '').replace(/\W+/g, '-')
}
module.exports = gitHosts

View File

@ -1,110 +0,0 @@
'use strict'
const gitHosts = require('./git-host-info.js')
class GitHost {
constructor (type, user, auth, project, committish, defaultRepresentation, opts = {}) {
Object.assign(this, gitHosts[type])
this.type = type
this.user = user
this.auth = auth
this.project = project
this.committish = committish
this.default = defaultRepresentation
this.opts = opts
}
hash () {
return this.committish ? `#${this.committish}` : ''
}
ssh (opts) {
return this._fill(this.sshtemplate, opts)
}
_fill (template, opts) {
if (typeof template === 'function') {
const options = { ...this, ...this.opts, ...opts }
// the path should always be set so we don't end up with 'undefined' in urls
if (!options.path) {
options.path = ''
}
// template functions will insert the leading slash themselves
if (options.path.startsWith('/')) {
options.path = options.path.slice(1)
}
if (options.noCommittish) {
options.committish = null
}
const result = template(options)
return options.noGitPlus && result.startsWith('git+') ? result.slice(4) : result
}
return null
}
sshurl (opts) {
return this._fill(this.sshurltemplate, opts)
}
browse (path, fragment, opts) {
// not a string, treat path as opts
if (typeof path !== 'string') {
return this._fill(this.browsetemplate, path)
}
if (typeof fragment !== 'string') {
opts = fragment
fragment = null
}
return this._fill(this.browsefiletemplate, { ...opts, fragment, path })
}
docs (opts) {
return this._fill(this.docstemplate, opts)
}
bugs (opts) {
return this._fill(this.bugstemplate, opts)
}
https (opts) {
return this._fill(this.httpstemplate, opts)
}
git (opts) {
return this._fill(this.gittemplate, opts)
}
shortcut (opts) {
return this._fill(this.shortcuttemplate, opts)
}
path (opts) {
return this._fill(this.pathtemplate, opts)
}
tarball (opts) {
return this._fill(this.tarballtemplate, { ...opts, noCommittish: false })
}
file (path, opts) {
return this._fill(this.filetemplate, { ...opts, path })
}
getDefaultRepresentation () {
return this.default
}
toString (opts) {
if (this.default && typeof this[this.default] === 'function') {
return this[this.default](opts)
}
return this.sshurl(opts)
}
}
module.exports = GitHost

View File

@ -1,237 +0,0 @@
'use strict'
const url = require('url')
const gitHosts = require('./git-host-info.js')
const GitHost = module.exports = require('./git-host.js')
const LRU = require('lru-cache')
const cache = new LRU({ max: 1000 })
const protocolToRepresentationMap = {
'git+ssh:': 'sshurl',
'git+https:': 'https',
'ssh:': 'sshurl',
'git:': 'git'
}
function protocolToRepresentation (protocol) {
return protocolToRepresentationMap[protocol] || protocol.slice(0, -1)
}
const authProtocols = {
'git:': true,
'https:': true,
'git+https:': true,
'http:': true,
'git+http:': true
}
const knownProtocols = Object.keys(gitHosts.byShortcut).concat(['http:', 'https:', 'git:', 'git+ssh:', 'git+https:', 'ssh:'])
module.exports.fromUrl = function (giturl, opts) {
if (typeof giturl !== 'string') {
return
}
const key = giturl + JSON.stringify(opts || {})
if (!cache.has(key)) {
cache.set(key, fromUrl(giturl, opts))
}
return cache.get(key)
}
function fromUrl (giturl, opts) {
if (!giturl) {
return
}
const url = isGitHubShorthand(giturl) ? 'github:' + giturl : correctProtocol(giturl)
const parsed = parseGitUrl(url)
if (!parsed) {
return parsed
}
const gitHostShortcut = gitHosts.byShortcut[parsed.protocol]
const gitHostDomain = gitHosts.byDomain[parsed.hostname.startsWith('www.') ? parsed.hostname.slice(4) : parsed.hostname]
const gitHostName = gitHostShortcut || gitHostDomain
if (!gitHostName) {
return
}
const gitHostInfo = gitHosts[gitHostShortcut || gitHostDomain]
let auth = null
if (authProtocols[parsed.protocol] && (parsed.username || parsed.password)) {
auth = `${parsed.username}${parsed.password ? ':' + parsed.password : ''}`
}
let committish = null
let user = null
let project = null
let defaultRepresentation = null
try {
if (gitHostShortcut) {
let pathname = parsed.pathname.startsWith('/') ? parsed.pathname.slice(1) : parsed.pathname
const firstAt = pathname.indexOf('@')
// we ignore auth for shortcuts, so just trim it out
if (firstAt > -1) {
pathname = pathname.slice(firstAt + 1)
}
const lastSlash = pathname.lastIndexOf('/')
if (lastSlash > -1) {
user = decodeURIComponent(pathname.slice(0, lastSlash))
// we want nulls only, never empty strings
if (!user) {
user = null
}
project = decodeURIComponent(pathname.slice(lastSlash + 1))
} else {
project = decodeURIComponent(pathname)
}
if (project.endsWith('.git')) {
project = project.slice(0, -4)
}
if (parsed.hash) {
committish = decodeURIComponent(parsed.hash.slice(1))
}
defaultRepresentation = 'shortcut'
} else {
if (!gitHostInfo.protocols.includes(parsed.protocol)) {
return
}
const segments = gitHostInfo.extract(parsed)
if (!segments) {
return
}
user = segments.user && decodeURIComponent(segments.user)
project = decodeURIComponent(segments.project)
committish = decodeURIComponent(segments.committish)
defaultRepresentation = protocolToRepresentation(parsed.protocol)
}
} catch (err) {
/* istanbul ignore else */
if (err instanceof URIError) {
return
} else {
throw err
}
}
return new GitHost(gitHostName, user, auth, project, committish, defaultRepresentation, opts)
}
// accepts input like git:github.com:user/repo and inserts the // after the first :
const correctProtocol = (arg) => {
const firstColon = arg.indexOf(':')
const proto = arg.slice(0, firstColon + 1)
if (knownProtocols.includes(proto)) {
return arg
}
const firstAt = arg.indexOf('@')
if (firstAt > -1) {
if (firstAt > firstColon) {
return `git+ssh://${arg}`
} else {
return arg
}
}
const doubleSlash = arg.indexOf('//')
if (doubleSlash === firstColon + 1) {
return arg
}
return arg.slice(0, firstColon + 1) + '//' + arg.slice(firstColon + 1)
}
// look for github shorthand inputs, such as npm/cli
const isGitHubShorthand = (arg) => {
// it cannot contain whitespace before the first #
// it cannot start with a / because that's probably an absolute file path
// but it must include a slash since repos are username/repository
// it cannot start with a . because that's probably a relative file path
// it cannot start with an @ because that's a scoped package if it passes the other tests
// it cannot contain a : before a # because that tells us that there's a protocol
// a second / may not exist before a #
const firstHash = arg.indexOf('#')
const firstSlash = arg.indexOf('/')
const secondSlash = arg.indexOf('/', firstSlash + 1)
const firstColon = arg.indexOf(':')
const firstSpace = /\s/.exec(arg)
const firstAt = arg.indexOf('@')
const spaceOnlyAfterHash = !firstSpace || (firstHash > -1 && firstSpace.index > firstHash)
const atOnlyAfterHash = firstAt === -1 || (firstHash > -1 && firstAt > firstHash)
const colonOnlyAfterHash = firstColon === -1 || (firstHash > -1 && firstColon > firstHash)
const secondSlashOnlyAfterHash = secondSlash === -1 || (firstHash > -1 && secondSlash > firstHash)
const hasSlash = firstSlash > 0
// if a # is found, what we really want to know is that the character immediately before # is not a /
const doesNotEndWithSlash = firstHash > -1 ? arg[firstHash - 1] !== '/' : !arg.endsWith('/')
const doesNotStartWithDot = !arg.startsWith('.')
return spaceOnlyAfterHash && hasSlash && doesNotEndWithSlash && doesNotStartWithDot && atOnlyAfterHash && colonOnlyAfterHash && secondSlashOnlyAfterHash
}
// attempt to correct an scp style url so that it will parse with `new URL()`
const correctUrl = (giturl) => {
const firstAt = giturl.indexOf('@')
const lastHash = giturl.lastIndexOf('#')
let firstColon = giturl.indexOf(':')
let lastColon = giturl.lastIndexOf(':', lastHash > -1 ? lastHash : Infinity)
let corrected
if (lastColon > firstAt) {
// the last : comes after the first @ (or there is no @)
// like it would in:
// proto://hostname.com:user/repo
// username@hostname.com:user/repo
// :password@hostname.com:user/repo
// username:password@hostname.com:user/repo
// proto://username@hostname.com:user/repo
// proto://:password@hostname.com:user/repo
// proto://username:password@hostname.com:user/repo
// then we replace the last : with a / to create a valid path
corrected = giturl.slice(0, lastColon) + '/' + giturl.slice(lastColon + 1)
// // and we find our new : positions
firstColon = corrected.indexOf(':')
lastColon = corrected.lastIndexOf(':')
}
if (firstColon === -1 && giturl.indexOf('//') === -1) {
// we have no : at all
// as it would be in:
// username@hostname.com/user/repo
// then we prepend a protocol
corrected = `git+ssh://${corrected}`
}
return corrected
}
// try to parse the url as its given to us, if that throws
// then we try to clean the url and parse that result instead
// THIS FUNCTION SHOULD NEVER THROW
const parseGitUrl = (giturl) => {
let result
try {
result = new url.URL(giturl)
} catch (err) {}
if (result) {
return result
}
const correctedUrl = correctUrl(giturl)
try {
result = new url.URL(correctedUrl)
} catch (err) {}
return result
}

View File

@ -1,52 +0,0 @@
{
"name": "hosted-git-info",
"version": "4.0.1",
"description": "Provides metadata and conversions from repository urls for GitHub, Bitbucket and GitLab",
"main": "index.js",
"repository": {
"type": "git",
"url": "git+https://github.com/npm/hosted-git-info.git"
},
"keywords": [
"git",
"github",
"bitbucket",
"gitlab"
],
"author": "Rebecca Turner <me@re-becca.org> (http://re-becca.org)",
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/hosted-git-info/issues"
},
"homepage": "https://github.com/npm/hosted-git-info",
"scripts": {
"posttest": "standard",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"preversion": "npm test",
"snap": "tap",
"test": "tap",
"test:coverage": "tap --coverage-report=html"
},
"dependencies": {
"lru-cache": "^6.0.0"
},
"devDependencies": {
"standard": "^16.0.3",
"standard-version": "^9.1.0",
"tap": "^14.11.0"
},
"files": [
"index.js",
"git-host.js",
"git-host-info.js"
],
"engines": {
"node": ">=10"
},
"tap": {
"color": 1,
"coverage": true,
"esm": false
}
}

View File

@ -1,6 +1,6 @@
# Changelog
All notable changes to this project will be documented in this file.
All notable changes to this project will be documented in this file.
## [6.1.1](https://github.com/npm/npm-pick-manifest/compare/v6.0.0...v6.1.0) (2020-04-07)

View File

@ -213,3 +213,4 @@ test('readPackageSync', function (t) {
);
});
});

View File

@ -66,7 +66,7 @@ Creates a new `RetryOperation` object. `options` is the same as `retry.timeouts(
* `forever`: Whether to retry forever, defaults to `false`.
* `unref`: Whether to [unref](https://nodejs.org/api/timers.html#timers_unref) the setTimeout's, defaults to `false`.
* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.
* `maxRetryTime`: The maximum time (in milliseconds) that the retried operation is allowed to run. Default is `Infinity`.
### retry.timeouts([options])

View File

@ -4,11 +4,12 @@ Fully featured SOCKS proxy client supporting SOCKSv4, SOCKSv4a, and SOCKSv5. Inc
### Features
* Supports SOCKS v4, v4a, and v5 protocols.
* Supports SOCKS v4, v4a, v5, and v5h protocols.
* Supports the CONNECT, BIND, and ASSOCIATE commands.
* Supports callbacks, promises, and events for proxy connection creation async flow control.
* Supports proxy chaining (CONNECT only).
* Supports user/pass authentication.
* Supports user/password authentication.
* Supports custom authentication.
* Built in UDP frame creation & parse functions.
* Created with TypeScript, type definitions are provided.
@ -396,17 +397,19 @@ Looking for a guide to migrate from v1? Look [here](docs/migratingFromV1.md)
### SocksClient
SocksClient establishes SOCKS proxy connections to remote destination hosts. These proxy connections are fully transparent to the server and once established act as full duplex streams. SOCKS v4, v4a, and v5 are supported, as well as the connect, bind, and associate commands.
SocksClient establishes SOCKS proxy connections to remote destination hosts. These proxy connections are fully transparent to the server and once established act as full duplex streams. SOCKS v4, v4a, v5, and v5h are supported, as well as the connect, bind, and associate commands.
SocksClient supports creating connections using callbacks, promises, and async/await flow control using two static factory functions createConnection and createConnectionChain. It also internally extends EventEmitter which results in allowing event handling based async flow control.
**SOCKS Compatibility Table**
Note: When using 4a please specify type: 4, and when using 5h please specify type 5.
| Socks Version | TCP | UDP | IPv4 | IPv6 | Hostname |
| --- | :---: | :---: | :---: | :---: | :---: |
| SOCKS v4 | ✅ | ❌ | ✅ | ❌ | ❌ |
| SOCKS v4a | ✅ | ❌ | ✅ | ❌ | ✅ |
| SOCKS v5 | ✅ | ✅ | ✅ | ✅ | ✅ |
| SOCKS v5 (includes 5hh) | ✅ | ✅ | ✅ | ✅ | ✅ |
### new SocksClient(options)
@ -419,11 +422,22 @@ SocksClient supports creating connections using callbacks, promises, and async/a
proxy: {
host: '159.203.75.200', // ipv4, ipv6, or hostname
port: 1080,
type: 5 // Proxy version (4 or 5). For v4a, just use 4.
type: 5 // Proxy version (4 or 5). For v4a use 4, for v5h use 5.
// Optional fields
userId: 'some username', // Used for SOCKS4 userId auth, and SOCKS5 user/pass auth in conjunction with password.
password: 'some password' // Used in conjunction with userId for user/pass auth for SOCKS5 proxies.
password: 'some password', // Used in conjunction with userId for user/pass auth for SOCKS5 proxies.
custom_auth_method: 0x80, // If using a custom auth method, specify the type here. If this is set, ALL other custom_auth_*** options must be set as well.
custom_auth_request_handler: async () =>. {
// This will be called when it's time to send the custom auth handshake. You must return a Buffer containing the data to send as your authentication.
return Buffer.from([0x01,0x02,0x03]);
},
// This is the expected size (bytes) of the custom auth response from the proxy server.
custom_auth_response_size: 2,
// This is called when the auth response is received. The received packet is passed in as a Buffer, and you must return a boolean indicating the response from the server said your custom auth was successful or failed.
custom_auth_response_handler: async (data) => {
return data[1] === 0x00;
}
},
command: 'connect', // connect, bind, associate

View File

@ -45,7 +45,7 @@ class SocksClient extends events_1.EventEmitter {
catch (err) {
if (typeof callback === 'function') {
callback(err);
return resolve(); // Resolves pending promise (prevents memory leaks).
return resolve(err); // Resolves pending promise (prevents memory leaks).
}
else {
return reject(err);
@ -57,7 +57,7 @@ class SocksClient extends events_1.EventEmitter {
client.removeAllListeners();
if (typeof callback === 'function') {
callback(null, info);
resolve(); // Resolves pending promise (prevents memory leaks).
resolve(info); // Resolves pending promise (prevents memory leaks).
}
else {
resolve(info);
@ -68,7 +68,7 @@ class SocksClient extends events_1.EventEmitter {
client.removeAllListeners();
if (typeof callback === 'function') {
callback(err);
resolve(); // Resolves pending promise (prevents memory leaks).
resolve(err); // Resolves pending promise (prevents memory leaks).
}
else {
reject(err);
@ -94,7 +94,7 @@ class SocksClient extends events_1.EventEmitter {
catch (err) {
if (typeof callback === 'function') {
callback(err);
return resolve(); // Resolves pending promise (prevents memory leaks).
return resolve(err); // Resolves pending promise (prevents memory leaks).
}
else {
return reject(err);
@ -121,6 +121,7 @@ class SocksClient extends events_1.EventEmitter {
command: 'connect',
proxy: nextProxy,
destination: nextDestination,
// Initial connection ignores this as sock is undefined. Subsequent connections re-use the first proxy socket to form a chain.
});
// If sock is undefined, assign it here.
if (!sock) {
@ -129,7 +130,7 @@ class SocksClient extends events_1.EventEmitter {
}
if (typeof callback === 'function') {
callback(null, { socket: sock });
resolve(); // Resolves pending promise (prevents memory leaks).
resolve({ socket: sock }); // Resolves pending promise (prevents memory leaks).
}
else {
resolve({ socket: sock });
@ -138,7 +139,7 @@ class SocksClient extends events_1.EventEmitter {
catch (err) {
if (typeof callback === 'function') {
callback(err);
resolve(); // Resolves pending promise (prevents memory leaks).
resolve(err); // Resolves pending promise (prevents memory leaks).
}
else {
reject(err);
@ -472,17 +473,22 @@ class SocksClient extends events_1.EventEmitter {
*/
sendSocks5InitialHandshake() {
const buff = new smart_buffer_1.SmartBuffer();
buff.writeUInt8(0x05);
// By default we always support no auth.
const supportedAuthMethods = [constants_1.Socks5Auth.NoAuth];
// We should only tell the proxy we support user/pass auth if auth info is actually provided.
// Note: As of Tor v0.3.5.7+, if user/pass auth is an option from the client, by default it will always take priority.
if (this.options.proxy.userId || this.options.proxy.password) {
buff.writeUInt8(2);
buff.writeUInt8(constants_1.Socks5Auth.NoAuth);
buff.writeUInt8(constants_1.Socks5Auth.UserPass);
supportedAuthMethods.push(constants_1.Socks5Auth.UserPass);
}
else {
buff.writeUInt8(1);
buff.writeUInt8(constants_1.Socks5Auth.NoAuth);
// Custom auth method?
if (this.options.proxy.custom_auth_method !== undefined) {
supportedAuthMethods.push(this.options.proxy.custom_auth_method);
}
// Build handshake packet
buff.writeUInt8(0x05);
buff.writeUInt8(supportedAuthMethods.length);
for (const authMethod of supportedAuthMethods) {
buff.writeUInt8(authMethod);
}
this.nextRequiredPacketBufferSize =
constants_1.SOCKS_INCOMING_PACKET_SIZES.Socks5InitialHandshakeResponse;
@ -498,17 +504,24 @@ class SocksClient extends events_1.EventEmitter {
if (data[0] !== 0x05) {
this.closeSocket(constants_1.ERRORS.InvalidSocks5IntiailHandshakeSocksVersion);
}
else if (data[1] === 0xff) {
else if (data[1] === constants_1.SOCKS5_NO_ACCEPTABLE_AUTH) {
this.closeSocket(constants_1.ERRORS.InvalidSocks5InitialHandshakeNoAcceptedAuthType);
}
else {
// If selected Socks v5 auth method is no auth, send final handshake request.
if (data[1] === constants_1.Socks5Auth.NoAuth) {
this.socks5ChosenAuthType = constants_1.Socks5Auth.NoAuth;
this.sendSocks5CommandRequest();
// If selected Socks v5 auth method is user/password, send auth handshake.
}
else if (data[1] === constants_1.Socks5Auth.UserPass) {
this.socks5ChosenAuthType = constants_1.Socks5Auth.UserPass;
this.sendSocks5UserPassAuthentication();
// If selected Socks v5 auth method is the custom_auth_method, send custom handshake.
}
else if (data[1] === this.options.proxy.custom_auth_method) {
this.socks5ChosenAuthType = this.options.proxy.custom_auth_method;
this.sendSocks5CustomAuthentication();
}
else {
this.closeSocket(constants_1.ERRORS.InvalidSocks5InitialHandshakeUnknownAuthType);
@ -534,19 +547,52 @@ class SocksClient extends events_1.EventEmitter {
this.socket.write(buff.toBuffer());
this.setState(constants_1.SocksClientState.SentAuthentication);
}
sendSocks5CustomAuthentication() {
return __awaiter(this, void 0, void 0, function* () {
this.nextRequiredPacketBufferSize = this.options.proxy.custom_auth_response_size;
this.socket.write(yield this.options.proxy.custom_auth_request_handler());
this.setState(constants_1.SocksClientState.SentAuthentication);
});
}
handleSocks5CustomAuthHandshakeResponse(data) {
return __awaiter(this, void 0, void 0, function* () {
return yield this.options.proxy.custom_auth_response_handler(data);
});
}
handleSocks5AuthenticationNoAuthHandshakeResponse(data) {
return __awaiter(this, void 0, void 0, function* () {
return data[1] === 0x00;
});
}
handleSocks5AuthenticationUserPassHandshakeResponse(data) {
return __awaiter(this, void 0, void 0, function* () {
return data[1] === 0x00;
});
}
/**
* Handles Socks v5 auth handshake response.
* @param data
*/
handleInitialSocks5AuthenticationHandshakeResponse() {
this.setState(constants_1.SocksClientState.ReceivedAuthenticationResponse);
const data = this.receiveBuffer.get(2);
if (data[1] !== 0x00) {
this.closeSocket(constants_1.ERRORS.Socks5AuthenticationFailed);
}
else {
this.sendSocks5CommandRequest();
}
return __awaiter(this, void 0, void 0, function* () {
this.setState(constants_1.SocksClientState.ReceivedAuthenticationResponse);
let authResult = false;
if (this.socks5ChosenAuthType === constants_1.Socks5Auth.NoAuth) {
authResult = yield this.handleSocks5AuthenticationNoAuthHandshakeResponse(this.receiveBuffer.get(2));
}
else if (this.socks5ChosenAuthType === constants_1.Socks5Auth.UserPass) {
authResult = yield this.handleSocks5AuthenticationUserPassHandshakeResponse(this.receiveBuffer.get(2));
}
else if (this.socks5ChosenAuthType === this.options.proxy.custom_auth_method) {
authResult = yield this.handleSocks5CustomAuthHandshakeResponse(this.receiveBuffer.get(this.options.proxy.custom_auth_response_size));
}
if (!authResult) {
this.closeSocket(constants_1.ERRORS.Socks5AuthenticationFailed);
}
else {
this.sendSocks5CommandRequest();
}
});
}
/**
* Sends Socks v5 final handshake request.

File diff suppressed because one or more lines are too long

View File

@ -1,6 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.SOCKS_INCOMING_PACKET_SIZES = exports.SocksClientState = exports.Socks5Response = exports.Socks5HostType = exports.Socks5Auth = exports.Socks4Response = exports.SocksCommand = exports.ERRORS = exports.DEFAULT_TIMEOUT = void 0;
exports.SOCKS5_NO_ACCEPTABLE_AUTH = exports.SOCKS5_CUSTOM_AUTH_END = exports.SOCKS5_CUSTOM_AUTH_START = exports.SOCKS_INCOMING_PACKET_SIZES = exports.SocksClientState = exports.Socks5Response = exports.Socks5HostType = exports.Socks5Auth = exports.Socks4Response = exports.SocksCommand = exports.ERRORS = exports.DEFAULT_TIMEOUT = void 0;
const DEFAULT_TIMEOUT = 30000;
exports.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
// prettier-ignore
@ -13,6 +13,8 @@ const ERRORS = {
InvalidSocksClientOptionsProxy: 'Invalid SOCKS proxy details were provided.',
InvalidSocksClientOptionsTimeout: 'An invalid timeout value was provided. Please enter a value above 0 (in ms).',
InvalidSocksClientOptionsProxiesLength: 'At least two socks proxies must be provided for chaining.',
InvalidSocksClientOptionsCustomAuthRange: 'Custom auth must be a value between 0x80 and 0xFE.',
InvalidSocksClientOptionsCustomAuthOptions: 'When a custom_auth_method is provided, custom_auth_request_handler, custom_auth_response_size, and custom_auth_response_handler must also be provided and valid.',
NegotiationError: 'Negotiation error',
SocketClosed: 'Socket closed',
ProxyConnectionTimedOut: 'Proxy connection timed out',
@ -41,7 +43,7 @@ const SOCKS_INCOMING_PACKET_SIZES = {
Socks5ResponseIPv6: 22,
Socks5ResponseHostname: (hostNameLength) => hostNameLength + 7,
// Command response + incoming connection (bind)
Socks4Response: 8,
Socks4Response: 8, // 2 header + 2 port + 4 ip
};
exports.SOCKS_INCOMING_PACKET_SIZES = SOCKS_INCOMING_PACKET_SIZES;
var SocksCommand;
@ -66,6 +68,12 @@ var Socks5Auth;
Socks5Auth[Socks5Auth["UserPass"] = 2] = "UserPass";
})(Socks5Auth || (Socks5Auth = {}));
exports.Socks5Auth = Socks5Auth;
const SOCKS5_CUSTOM_AUTH_START = 0x80;
exports.SOCKS5_CUSTOM_AUTH_START = SOCKS5_CUSTOM_AUTH_START;
const SOCKS5_CUSTOM_AUTH_END = 0xfe;
exports.SOCKS5_CUSTOM_AUTH_END = SOCKS5_CUSTOM_AUTH_END;
const SOCKS5_NO_ACCEPTABLE_AUTH = 0xff;
exports.SOCKS5_NO_ACCEPTABLE_AUTH = SOCKS5_NO_ACCEPTABLE_AUTH;
var Socks5Response;
(function (Socks5Response) {
Socks5Response[Socks5Response["Granted"] = 0] = "Granted";

View File

@ -1 +1 @@
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":";;;AAIA,MAAM,eAAe,GAAG,KAAK,CAAC;AA6L5B,0CAAe;AAzLjB,kBAAkB;AAClB,MAAM,MAAM,GAAG;IACb,mBAAmB,EAAE,wFAAwF;IAC7G,+BAA+B,EAAE,oGAAoG;IACrI,wBAAwB,EAAE,8FAA8F;IACxH,oCAAoC,EAAE,2CAA2C;IACjF,uCAAuC,EAAE,uFAAuF;IAChI,8BAA8B,EAAE,4CAA4C;IAC5E,gCAAgC,EAAE,8EAA8E;IAChH,sCAAsC,EAAE,2DAA2D;IACnG,gBAAgB,EAAE,mBAAmB;IACrC,YAAY,EAAE,eAAe;IAC7B,uBAAuB,EAAE,4BAA4B;IACrD,aAAa,EAAE,qDAAqD;IACpE,8BAA8B,EAAE,4CAA4C;IAC5E,6BAA6B,EAAE,kCAAkC;IACjE,uCAAuC,EAAE,6CAA6C;IACtF,0CAA0C,EAAE,iDAAiD;IAC7F,qCAAqC,EAAE,oDAAoD;IAC3F,yCAAyC,EAAE,mEAAmE;IAC9G,+CAA+C,EAAE,6EAA6E;IAC9H,4CAA4C,EAAE,yEAAyE;IACvH,0BAA0B,EAAE,8BAA8B;IAC1D,2BAA2B,EAAE,kDAAkD;IAC/E,mCAAmC,EAAE,kCAAkC;IACvE,uCAAuC,EAAE,sDAAsD;IAC/F,0CAA0C,EAAE,iDAAiD;CAC9F,CAAC;AA+JA,wBAAM;AA7JR,MAAM,2BAA2B,GAAG;IAClC,8BAA8B,EAAE,CAAC;IACjC,oCAAoC,EAAE,CAAC;IACvC,gDAAgD;IAChD,oBAAoB,EAAE,CAAC;IACvB,kBAAkB,EAAE,EAAE;IACtB,kBAAkB,EAAE,EAAE;IACtB,sBAAsB,EAAE,CAAC,cAAsB,EAAE,EAAE,CAAC,cAAc,GAAG,CAAC;IACtE,gDAAgD;IAChD,cAAc,EAAE,CAAC;CAClB,CAAC;AAmKA,kEAA2B;AA/J7B,IAAK,YAIJ;AAJD,WAAK,YAAY;IACf,qDAAc,CAAA;IACd,+CAAW,CAAA;IACX,yDAAgB,CAAA;AAClB,CAAC,EAJI,YAAY,KAAZ,YAAY,QAIhB;AA6IC,oCAAY;AA3Id,IAAK,cAKJ;AALD,WAAK,cAAc;IACjB,0DAAc,CAAA;IACd,wDAAa,CAAA;IACb,4DAAe,CAAA;IACf,sEAAoB,CAAA;AACtB,CAAC,EALI,cAAc,KAAd,cAAc,QAKlB;AAuIC,wCAAc;AArIhB,IAAK,UAIJ;AAJD,WAAK,UAAU;IACb,+CAAa,CAAA;IACb,+CAAa,CAAA;IACb,mDAAe,CAAA;AACjB,CAAC,EAJI,UAAU,KAAV,UAAU,QAId;AAkIC,gCAAU;AAhIZ,IAAK,cAUJ;AAVD,WAAK,cAAc;IACjB,yDAAc,CAAA;IACd,yDAAc,CAAA;IACd,+DAAiB,CAAA;IACjB,+EAAyB,CAAA;IACzB,yEAAsB,CAAA;IACtB,6EAAwB,CAAA;IACxB,+DAAiB,CAAA;IACjB,iFAA0B,CAAA;IAC1B,iFAA0B,CAAA;AAC5B,CAAC,EAVI,cAAc,KAAd,cAAc,QAUlB;AAwHC,wCAAc;AAtHhB,IAAK,cAIJ;AAJD,WAAK,cAAc;IACjB,mDAAW,CAAA;IACX,2DAAe,CAAA;IACf,mDAAW,CAAA;AACb,CAAC,EAJI,cAAc,KAAd,cAAc,QAIlB;AAiHC,wCAAc;AA/GhB,IAAK,gBAcJ;AAdD,WAAK,gBAAgB;IACnB,6DAAW,CAAA;IACX,mEAAc,CAAA;IACd,iEAAa,CAAA;IACb,uFAAwB,CAAA;IACxB,+GAAoC,CAAA;IACpC,mFAAsB,CAAA;IACtB,2GAAkC,CAAA;IAClC,mFAAsB,CAAA;IACtB,yFAAyB,CAAA;IACzB,iGAA6B,CAAA;IAC7B,sEAAgB,CAAA;IAChB,wEAAiB,CAAA;IACjB,0DAAU,CAAA;AACZ,CAAC,EAdI,gBAAgB,KAAhB,gBAAgB,QAcpB;AAmGC,4CAAgB"}
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"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"}

View File

@ -26,6 +26,8 @@ function validateSocksClientOptions(options, acceptedCommands = ['connect', 'bin
if (!isValidSocksProxy(options.proxy)) {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsProxy, options);
}
// Validate custom auth (if set)
validateCustomProxyAuth(options.proxy, options);
// Check timeout
if (options.timeout && !isValidTimeoutValue(options.timeout)) {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsTimeout, options);
@ -61,6 +63,8 @@ function validateSocksClientChainOptions(options) {
if (!isValidSocksProxy(proxy)) {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsProxy, options);
}
// Validate custom auth (if set)
validateCustomProxyAuth(proxy, options);
});
// Check timeout
if (options.timeout && !isValidTimeoutValue(options.timeout)) {
@ -68,6 +72,29 @@ function validateSocksClientChainOptions(options) {
}
}
exports.validateSocksClientChainOptions = validateSocksClientChainOptions;
function validateCustomProxyAuth(proxy, options) {
if (proxy.custom_auth_method !== undefined) {
// Invalid auth method range
if (proxy.custom_auth_method < constants_1.SOCKS5_CUSTOM_AUTH_START ||
proxy.custom_auth_method > constants_1.SOCKS5_CUSTOM_AUTH_END) {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthRange, options);
}
// Missing custom_auth_request_handler
if (proxy.custom_auth_request_handler === undefined ||
typeof proxy.custom_auth_request_handler !== 'function') {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
}
// Missing custom_auth_response_size
if (proxy.custom_auth_response_size === undefined) {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
}
// Missing/invalid custom_auth_response_handler
if (proxy.custom_auth_response_handler === undefined ||
typeof proxy.custom_auth_response_handler !== 'function') {
throw new util_1.SocksClientError(constants_1.ERRORS.InvalidSocksClientOptionsCustomAuthOptions, options);
}
}
}
/**
* Validates a SocksRemoteHost
* @param remoteHost { SocksRemoteHost }

View File

@ -1 +1 @@
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/common/helpers.ts"],"names":[],"mappings":"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"}
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../src/common/helpers.ts"],"names":[],"mappings":"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"}

View File

@ -1,7 +1,7 @@
{
"name": "socks",
"private": false,
"version": "2.5.1",
"version": "2.6.0",
"description": "Fully featured SOCKS proxy client supporting SOCKSv4, SOCKSv4a, and SOCKSv5. Includes Bind and Associate functionality.",
"main": "build/index.js",
"typings": "typings/index.d.ts",
@ -34,17 +34,17 @@
"readmeFilename": "README.md",
"devDependencies": {
"@types/ip": "1.1.0",
"@types/mocha": "^8.0.3",
"@types/node": "^14.14.3",
"@types/mocha": "^8.2.1",
"@types/node": "^14.14.35",
"coveralls": "3.1.0",
"mocha": "^8.2.0",
"mocha": "^8.3.2",
"nyc": "15.1.0",
"prettier": "^2.1.2",
"prettier": "^2.2.1",
"socks5-server": "^0.1.1",
"ts-node": "^9.0.0",
"ts-node": "^9.1.1",
"tslint": "^6.1.3",
"tslint-config-airbnb": "^5.11.2",
"typescript": "^4.0.3"
"typescript": "^4.2.3"
},
"dependencies": {
"ip": "^1.1.5",
@ -57,7 +57,7 @@
"coverage": "NODE_ENV=test nyc npm test",
"coveralls": "NODE_ENV=test nyc npm test && nyc report --reporter=text-lcov | coveralls",
"lint": "tslint --project tsconfig.json 'src/**/*.ts'",
"build": "rm -rf build typings && tslint --project tsconfig.json && prettier --write ./src/**/*.ts --config .prettierrc.yaml && tsc -p ."
"build": "rm -rf build typings && prettier --write ./src/**/*.ts --config .prettierrc.yaml && tsc -p ."
},
"nyc": {
"extension": [

View File

@ -22,6 +22,7 @@ declare class SocksClient extends EventEmitter implements SocksClient {
private state;
private receiveBuffer;
private nextRequiredPacketBufferSize;
private socks5ChosenAuthType;
private onDataReceived;
private onClose;
private onError;
@ -132,6 +133,10 @@ declare class SocksClient extends EventEmitter implements SocksClient {
* Note: No auth and user/pass are currently supported.
*/
private sendSocks5UserPassAuthentication;
private sendSocks5CustomAuthentication;
private handleSocks5CustomAuthHandshakeResponse;
private handleSocks5AuthenticationNoAuthHandshakeResponse;
private handleSocks5AuthenticationUserPassHandshakeResponse;
/**
* Handles Socks v5 auth handshake response.
* @param data

View File

@ -13,6 +13,8 @@ declare const ERRORS: {
InvalidSocksClientOptionsProxy: string;
InvalidSocksClientOptionsTimeout: string;
InvalidSocksClientOptionsProxiesLength: string;
InvalidSocksClientOptionsCustomAuthRange: string;
InvalidSocksClientOptionsCustomAuthOptions: string;
NegotiationError: string;
SocketClosed: string;
ProxyConnectionTimedOut: string;
@ -57,6 +59,9 @@ declare enum Socks5Auth {
GSSApi = 1,
UserPass = 2
}
declare const SOCKS5_CUSTOM_AUTH_START = 128;
declare const SOCKS5_CUSTOM_AUTH_END = 254;
declare const SOCKS5_NO_ACCEPTABLE_AUTH = 255;
declare enum Socks5Response {
Granted = 0,
Failure = 1,
@ -98,6 +103,10 @@ declare type SocksProxy = RequireOnlyOne<{
type: SocksProxyType;
userId?: string;
password?: string;
custom_auth_method?: number;
custom_auth_request_handler?: () => Promise<Buffer>;
custom_auth_response_size?: number;
custom_auth_response_handler?: (data: Buffer) => Promise<boolean>;
}, 'host' | 'ipaddress'>;
/**
* Represents a remote host
@ -138,4 +147,4 @@ interface SocksUDPFrameDetails {
remoteHost: SocksRemoteHost;
data: Buffer;
}
export { DEFAULT_TIMEOUT, ERRORS, SocksProxyType, SocksCommand, Socks4Response, Socks5Auth, Socks5HostType, Socks5Response, SocksClientState, SocksProxy, SocksRemoteHost, SocksCommandOption, SocksClientOptions, SocksClientChainOptions, SocksClientEstablishedEvent, SocksClientBoundEvent, SocksUDPFrameDetails, SOCKS_INCOMING_PACKET_SIZES, };
export { DEFAULT_TIMEOUT, ERRORS, SocksProxyType, SocksCommand, Socks4Response, Socks5Auth, Socks5HostType, Socks5Response, SocksClientState, SocksProxy, SocksRemoteHost, SocksCommandOption, SocksClientOptions, SocksClientChainOptions, SocksClientEstablishedEvent, SocksClientBoundEvent, SocksUDPFrameDetails, SOCKS_INCOMING_PACKET_SIZES, SOCKS5_CUSTOM_AUTH_START, SOCKS5_CUSTOM_AUTH_END, SOCKS5_NO_ACCEPTABLE_AUTH, };

View File

@ -127,13 +127,13 @@ Example: In-place generation of two binary IDs
```javascript
// Generate two ids in an array
const arr = new Array();
uuidv1(null, arr, 0); // ⇨
uuidv1(null, arr, 0); // ⇨
// [
// 44, 94, 164, 192, 64, 103,
// 17, 233, 146, 52, 155, 29,
// 235, 77, 59, 125
// ]
uuidv1(null, arr, 16); // ⇨
uuidv1(null, arr, 16); // ⇨
// [
// 44, 94, 164, 192, 64, 103, 17, 233,
// 146, 52, 155, 29, 235, 77, 59, 125,
@ -208,14 +208,14 @@ Example: Generate two IDs in a single buffer
```javascript
const buffer = new Array();
uuidv4(null, buffer, 0); // ⇨
uuidv4(null, buffer, 0); // ⇨
// [
// 155, 29, 235, 77, 59,
// 125, 75, 173, 155, 221,
// 43, 13, 123, 61, 203,
// 109
// ]
uuidv4(null, buffer, 16); // ⇨
uuidv4(null, buffer, 16); // ⇨
// [
// 155, 29, 235, 77, 59, 125, 75, 173,
// 155, 221, 43, 13, 123, 61, 203, 109,

View File

@ -1,5 +1,5 @@
{
"version": "7.7.0",
"version": "7.7.4",
"name": "npm",
"description": "a package manager for JavaScript",
"keywords": [
@ -59,7 +59,7 @@
"columnify": "~1.5.4",
"glob": "^7.1.4",
"graceful-fs": "^4.2.6",
"hosted-git-info": "^4.0.1",
"hosted-git-info": "^4.0.2",
"ini": "^2.0.0",
"init-package-json": "^2.0.2",
"is-cidr": "^4.0.2",

View File

@ -32,6 +32,7 @@ Array [
"commit-hooks",
"depth",
"description",
"dev",
"diff",
"diff-ignore-all-space",
"diff-name-only",

View File

@ -64,7 +64,7 @@ registry and all registries configured for scopes. See the documentation for
#### \`audit-level\`
* Default: null
* Type: "low", "moderate", "high", "critical", "none", or null
* Type: "info", "low", "moderate", "high", "critical", "none", or null
The minimum level of vulnerability for \`npm audit\` to exit with a non-zero
exit code.
@ -1261,6 +1261,14 @@ What authentication strategy to use with \`adduser\`/\`login\`.
\`--cache-min=9999 (or bigger)\` is an alias for \`--prefer-offline\`.
#### \`dev\`
* Default: false
* Type: Boolean
* DEPRECATED: Please use --include=dev instead.
Alias for \`--include=dev\`.
#### \`init.author.email\`
* Default: ""
@ -1330,8 +1338,8 @@ Alias for --include=optional or --omit=optional
#### \`production\`
* Default: false
* Type: Boolean
* Default: null
* Type: null or Boolean
* DEPRECATED: Use \`--omit=dev\` instead.
Alias for \`--omit=dev\`

View File

@ -166,9 +166,9 @@ npm help npm more involved overview
All commands:
access npm access
Set access level on published packages
Usage:
npm access public [<package>]
npm access restricted [<package>]
@ -179,62 +179,62 @@ All commands:
npm access ls-packages [<user>|<scope>|<scope:team>]
npm access ls-collaborators [<package> [<user>]]
npm access edit [<package>]
Run "npm help access" for more info
adduser npm adduser
Add a registry user account
Usage:
npm adduser
Options:
[--registry <registry>] [--scope <@scope>] [--always-auth]
aliases: login, add-user
Run "npm help adduser" for more info
audit npm audit
Run a security audit
Usage:
npm audit [fix]
Options:
[--dry-run] [-f|--force] [--json] [--package-lock-only] [--production]
[--audit-level <info|low|moderate|high|critical|none>] [--dry-run] [-f|--force] [--json] [--package-lock-only] [--production]
Run "npm help audit" for more info
bin npm bin
Display npm bin folder
Usage:
npm bin
Options:
[-g|--global]
Run "npm help bin" for more info
bugs npm bugs
Report bugs for a package in a web browser
Usage:
npm bugs [<pkgname>]
alias: issues
Run "npm help bugs" for more info
cache npm cache
Manipulates packages cache
Usage:
npm cache add <tarball file>
npm cache add <folder>
@ -243,223 +243,223 @@ All commands:
npm cache add <name>@<version>
npm cache clean
npm cache verify
Run "npm help cache" for more info
ci npm ci
Install a project with a clean slate
Usage:
npm ci
aliases: clean-install, ic, install-clean, isntall-clean
Run "npm help ci" for more info
completion npm completion
Tab Completion for npm
Usage:
npm completion
Run "npm help completion" for more info
config npm config
Manage the npm configuration files
Usage:
npm config set <key>=<value> [<key>=<value> ...]
npm config get [<key> [<key> ...]]
npm config delete <key> [<key> ...]
npm config list [--json]
npm config edit
alias: c
Run "npm help config" for more info
dedupe npm dedupe
Reduce duplication in the package tree
Usage:
npm dedupe
alias: ddp
Run "npm help dedupe" for more info
deprecate npm deprecate
Deprecate a version of a package
Usage:
npm deprecate <pkg>[@<version>] <message>
Run "npm help deprecate" for more info
diff npm diff
The registry diff command
Usage:
npm diff [...<paths>]
npm diff --diff=<pkg-name> [...<paths>]
npm diff --diff=<version-a> [--diff=<version-b>] [...<paths>]
npm diff --diff=<spec-a> [--diff=<spec-b>] [...<paths>]
npm diff [--diff-ignore-all-space] [--diff-name-only] [...<paths>] [...<paths>]
Run "npm help diff" for more info
dist-tag npm dist-tag
Modify package distribution tags
Usage:
npm dist-tag add <pkg>@<version> [<tag>]
npm dist-tag rm <pkg> <tag>
npm dist-tag ls [<pkg>]
alias: dist-tags
Run "npm help dist-tag" for more info
docs npm docs
Open documentation for a package in a web browser
Usage:
npm docs [<pkgname> [<pkgname> ...]]
alias: home
Run "npm help docs" for more info
doctor npm doctor
Check your npm environment
Usage:
npm doctor
Run "npm help doctor" for more info
edit npm edit
Edit an installed package
Usage:
npm edit <pkg>[/<subpkg>...]
Run "npm help edit" for more info
exec npm exec
Run a command from a local or remote npm package
Usage:
npm exec -- <pkg>[@<version>] [args...]
npm exec --package=<pkg>[@<version>] -- <cmd> [args...]
npm exec -c '<cmd> [args...]'
npm exec --package=foo -c '<cmd> [args...]'
alias: x
Run "npm help exec" for more info
explain npm explain
Explain installed packages
Usage:
npm explain <folder | specifier>
alias: why
Run "npm help explain" for more info
explore npm explore
Browse an installed package
Usage:
npm explore <pkg> [ -- <command>]
Run "npm help explore" for more info
find-dupes npm find-dupes
Find duplication in the package tree
Usage:
npm find-dupes
Run "npm help find-dupes" for more info
fund npm fund
Retrieve funding information
Usage:
npm fund [[<@scope>/]<pkg>]
Options:
[--json] [--browser|--browser <browser>] [--unicode] [--which <fundingSourceNumber>]
Run "npm help fund" for more info
get npm get
Get a value from the npm configuration
Usage:
npm get [<key> ...] (See \`npm config\`)
Run "npm help get" for more info
help npm help
Get help on npm
Usage:
npm help <term> [<terms..>]
alias: hlep
Run "npm help help" for more info
hook npm hook
Manage registry hooks
Usage:
npm hook add <pkg> <url> <secret> [--type=<type>]
npm hook ls [pkg]
npm hook rm <id>
npm hook update <id> <url> <secret>
Run "npm help hook" for more info
init npm init
Create a package.json file
Usage:
npm init [--force|-f|--yes|-y|--scope]
npm init <@scope> (same as \`npx <@scope>/create\`)
npm init [<@scope>/]<name> (same as \`npx [<@scope>/]create-<name>\`)
aliases: create, innit
Run "npm help init" for more info
install npm install
Install a package
Usage:
npm install [<@scope>/]<pkg>
npm install [<@scope>/]<pkg>@<tag>
@ -471,29 +471,29 @@ All commands:
npm install <tarball url>
npm install <git:// url>
npm install <github username>/<github project>
Options:
[-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact]
aliases: i, in, ins, inst, insta, instal, isnt, isnta, isntal, add
Run "npm help install" for more info
install-ci-test npm install-ci-test
Install a project with a clean slate and run tests
Usage:
npm install-ci-test
alias: cit
Run "npm help install-ci-test" for more info
install-test npm install-test
Install package(s) and run tests
Usage:
npm install-test [<@scope>/]<pkg>
npm install-test [<@scope>/]<pkg>@<tag>
@ -505,420 +505,420 @@ All commands:
npm install-test <tarball url>
npm install-test <git:// url>
npm install-test <github username>/<github project>
Options:
[-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer] [-E|--save-exact]
alias: it
Run "npm help install-test" for more info
link npm link
Symlink a package folder
Usage:
npm link (in package dir)
npm link [<@scope>/]<pkg>[@<version>]
alias: ln
Run "npm help link" for more info
ll npm ll
List installed packages
Usage:
npm ll [[<@scope>/]<pkg> ...]
alias: la
Run "npm help ll" for more info
login npm adduser
Add a registry user account
Usage:
npm adduser
Options:
[--registry <registry>] [--scope <@scope>] [--always-auth]
aliases: login, add-user
Run "npm help adduser" for more info
logout npm logout
Log out of the registry
Usage:
npm logout
Options:
[--registry <registry>] [--scope <@scope>]
Run "npm help logout" for more info
ls npm ls
List installed packages
Usage:
npm ls npm ls [[<@scope>/]<pkg> ...]
alias: list
Run "npm help ls" for more info
org npm org
Manage orgs
Usage:
npm org set orgname username [developer | admin | owner]
npm org rm orgname username
npm org ls orgname [<username>]
alias: ogr
Run "npm help org" for more info
outdated npm outdated
Check for outdated packages
Usage:
npm outdated [[<@scope>/]<pkg> ...]
Run "npm help outdated" for more info
owner npm owner
Manage package owners
Usage:
npm owner add <user> [<@scope>/]<pkg>
npm owner rm <user> [<@scope>/]<pkg>
npm owner ls [<@scope>/]<pkg>
alias: author
Run "npm help owner" for more info
pack npm pack
Create a tarball from a package
Usage:
npm pack [[<@scope>/]<pkg>...]
Options:
[--dry-run]
Run "npm help pack" for more info
ping npm ping
Ping npm registry
Usage:
npm ping
Options:
[--registry <registry>]
Run "npm help ping" for more info
prefix npm prefix
Display prefix
Usage:
npm prefix [-g]
Run "npm help prefix" for more info
profile npm profile
Change settings on your registry profile
Usage:
npm profile enable-2fa [auth-only|auth-and-writes]
npm profile disable-2fa
npm profile get [<key>]
npm profile set <key> <value>
Run "npm help profile" for more info
prune npm prune
Remove extraneous packages
Usage:
npm prune [[<@scope>/]<pkg>...]
Options:
[--production]
Run "npm help prune" for more info
publish npm publish
Publish a package
Usage:
npm publish [<folder>]
Options:
[--tag <tag>] [--access <restricted|public>] [--dry-run]
Run "npm help publish" for more info
rebuild npm rebuild
Rebuild a package
Usage:
npm rebuild [[<@scope>/]<name>[@<version>] ...]
alias: rb
Run "npm help rebuild" for more info
repo npm repo
Open package repository page in the browser
Usage:
npm repo [<pkgname> [<pkgname> ...]]
Run "npm help repo" for more info
restart npm restart
Restart a package
Usage:
npm restart [-- <args>]
Run "npm help restart" for more info
root npm root
Display npm root
Usage:
npm root
Options:
[-g|--global]
Run "npm help root" for more info
run-script npm run-script
Run arbitrary package scripts
Usage:
npm run-script <command> [-- <args>]
aliases: run, rum, urn
Run "npm help run-script" for more info
search npm search
Search for pacakges
Usage:
npm search [search terms ...]
Options:
[-l|--long] [--json] [-p|--parseable] [--no-description]
aliases: s, se, find
Run "npm help search" for more info
set npm set
Set a value in the npm configuration
Usage:
npm set <key>=<value> [<key>=<value> ...] (See \`npm config\`)
Run "npm help set" for more info
set-script npm set-script
Set tasks in the scripts section of package.json
Usage:
npm set-script [<script>] [<command>]
Run "npm help set-script" for more info
shrinkwrap npm shrinkwrap
Lock down dependency versions for publication
Usage:
npm shrinkwrap
Run "npm help shrinkwrap" for more info
star npm star
Mark your favorite packages
Usage:
npm star [<pkg>...]
Run "npm help star" for more info
stars npm stars
View packages marked as favorites
Usage:
npm stars [<user>]
Run "npm help stars" for more info
start npm start
Start a package
Usage:
npm start [-- <args>]
Run "npm help start" for more info
stop npm stop
Stop a package
Usage:
npm stop [-- <args>]
Run "npm help stop" for more info
team npm team
Manage organization teams and team memberships
Usage:
npm team create <scope:team> [--otp <otpcode>]
npm team destroy <scope:team> [--otp <otpcode>]
npm team add <scope:team> <user> [--otp <otpcode>]
npm team rm <scope:team> <user> [--otp <otpcode>]
npm team ls <scope>|<scope:team>
Run "npm help team" for more info
test npm test
Test a package
Usage:
npm test [-- <args>]
aliases: tst, t
Run "npm help test" for more info
token npm token
Manage your authentication tokens
Usage:
npm token list
npm token revoke <id|token>
npm token create [--read-only] [--cidr=list]
Run "npm help token" for more info
uninstall npm uninstall
Remove a package
Usage:
npm uninstall [<@scope>/]<pkg>...
Options:
[-S|--save|--no-save|--save-prod|--save-dev|--save-optional|--save-peer]
aliases: un, unlink, remove, rm, r
Run "npm help uninstall" for more info
unpublish npm unpublish
Remove a package from the registry
Usage:
npm unpublish [<@scope>/]<pkg>[@<version>]
Run "npm help unpublish" for more info
unstar npm unstar
Remove an item from your favorite packages
Usage:
npm unstar [<pkg>...]
Run "npm help unstar" for more info
update npm update
Update packages
Usage:
npm update [<pkg>...]
Options:
[-g|--global]
aliases: up, upgrade, udpate
Run "npm help update" for more info
version npm version
Bump a package version
Usage:
npm version [<newversion> | major | minor | patch | premajor | preminor | prepatch | prerelease [--preid=<prerelease-id>] | from-git]
alias: verison
Run "npm help version" for more info
view npm view
View registry info
Usage:
npm view [<@scope>/]<pkg>[@<version>] [<field>[.subfield]...]
aliases: v, info, show
Run "npm help view" for more info
whoami npm whoami
Display npm username
Usage:
npm whoami
Options:
[--registry <registry>]
Run "npm help whoami" for more info
Specify configs in the ini-formatted file:

View File

@ -20,7 +20,7 @@ bundle-dep
name: my-cool-pkg
version: 1.0.0
filename: my-cool-pkg-1.0.0.tgz
package size: 216 B
package size: 216 B
unpacked size: 101 B
shasum: a604258e06adecec0b18f48e901c5802f19f7dab
integrity: sha512-fnN6NmI8DerTt[...]6rH17jx7OIFig==

View File

@ -54,6 +54,7 @@ const cliConfig = {
const npm = {
log: {
warn: () => null,
info: () => null,
enableProgress: () => null,
disableProgress: () => null,
@ -93,6 +94,22 @@ t.test('config no args', t => {
})
})
t.test('config ignores workspaces', t => {
npm.log.warn = (title, msg) => {
t.equal(title, 'config', 'should warn with expected title')
t.equal(
msg,
'This command does not support workspaces.',
'should warn with unsupported option msg'
)
}
config.execWorkspaces([], [], (err) => {
t.match(err, /usage instructions/, 'should not error out when workspaces are defined')
npm.log.warn = () => null
t.end()
})
})
t.test('config list', t => {
t.plan(2)
@ -389,7 +406,7 @@ t.test('config set invalid key', t => {
npm.config.validate = npmConfigValidate
delete npm.config.save
delete npm.config.set
delete npm.log.warn
npm.log.warn = () => null
})
config.exec(['set', 'foo', 'bar'], (err) => {

View File

@ -32,7 +32,7 @@ test('should install using Arborist', (t) => {
const npm = mockNpm({
config: { dev: true },
flatOptions: { global: false },
flatOptions: { global: false, auditLevel: 'low' },
globalDir: 'path/to/node_modules/',
prefix: 'foo',
})
@ -42,7 +42,9 @@ test('should install using Arborist', (t) => {
install.exec(['fizzbuzz'], er => {
if (er)
throw er
t.match(ARB_ARGS, { global: false, path: 'foo' })
t.match(ARB_ARGS,
{ global: false, path: 'foo', auditLevel: null },
'Arborist gets correct args and ignores auditLevel')
t.equal(REIFY_CALLED, true, 'called reify')
t.strictSame(SCRIPTS, [], 'no scripts when adding dep')
t.end()

View File

@ -2,6 +2,43 @@ const test = require('tap')
const requireInject = require('require-inject')
const parseJSON = require('json-parse-even-better-errors')
test.test('completion', t => {
const SetScript = requireInject('../../lib/set-script.js')
const emptyDir = t.testdir()
t.test('already have a script name', async t => {
const setScript = new SetScript({localPrefix: emptyDir})
const res = await setScript.completion({conf: {argv: {remain: ['npm', 'run', 'x']}}})
t.equal(res, undefined)
t.end()
})
t.test('no package.json', async t => {
const setScript = new SetScript({localPrefix: emptyDir})
const res = await setScript.completion({conf: {argv: {remain: ['npm', 'run']}}})
t.strictSame(res, [])
t.end()
})
t.test('has package.json, no scripts', async t => {
const localPrefix = t.testdir({
'package.json': JSON.stringify({}),
})
const setScript = new SetScript({localPrefix})
const res = await setScript.completion({conf: {argv: {remain: ['npm', 'run']}}})
t.strictSame(res, [])
t.end()
})
t.test('has package.json, with scripts', async t => {
const localPrefix = t.testdir({
'package.json': JSON.stringify({
scripts: { hello: 'echo hello', world: 'echo world' },
}),
})
const setScript = new SetScript({localPrefix})
const res = await setScript.completion({conf: {argv: {remain: ['npm', 'run']}}})
t.strictSame(res, ['hello', 'world'])
t.end()
})
t.end()
})
test.test('fails on invalid arguments', (t) => {
const SetScript = requireInject('../../lib/set-script.js', {
npmlog: {},

View File

@ -22,6 +22,7 @@ const uninstall = new Uninstall(npm)
t.afterEach(cb => {
npm.globalDir = ''
npm.prefix = ''
npm.localPrefix = ''
npm.flatOptions.global = false
npm.flatOptions.prefix = ''
cb()
@ -85,7 +86,7 @@ t.test('remove single installed lib', t => {
const b = resolve(path, 'node_modules/b')
t.ok(() => fs.statSync(b))
npm.config.set('prefix', path)
npm.localPrefix = path
uninstall.exec(['b'], err => {
if (err)
@ -148,7 +149,7 @@ t.test('remove multiple installed libs', t => {
t.ok(() => fs.statSync(a))
t.ok(() => fs.statSync(b))
npm.config.set('prefix', path)
npm.localPrefix = path
uninstall.exec(['b'], err => {
if (err)
@ -196,7 +197,6 @@ t.test('no args global', t => {
npm.localPrefix = resolve(path, 'projects', 'a')
npm.globalDir = resolve(path, 'lib', 'node_modules')
npm.config.set('global', true)
npm.config.set('prefix', path)
const a = resolve(path, 'lib/node_modules/a')
t.ok(() => fs.statSync(a))

View File

@ -10,6 +10,7 @@ const config = {
const noop = () => null
const npm = mockNpm({
globalDir: '',
log: noop,
config,
prefix: '',
})
@ -38,7 +39,7 @@ t.test('no args', t => {
constructor (args) {
t.deepEqual(
args,
{ ...npm.flatOptions, path: npm.prefix },
{ ...npm.flatOptions, path: npm.prefix, log: noop },
'should call arborist contructor with expected args'
)
}
@ -72,7 +73,7 @@ t.test('with args', t => {
constructor (args) {
t.deepEqual(
args,
{ ...npm.flatOptions, path: npm.prefix },
{ ...npm.flatOptions, path: npm.prefix, log: noop },
'should call arborist contructor with expected args'
)
}
@ -140,7 +141,7 @@ t.test('update --global', t => {
const { path, ...opts } = args
t.deepEqual(
opts,
npm.flatOptions,
{ ...npm.flatOptions, log: noop },
'should call arborist contructor with expected options'
)

View File

@ -194,18 +194,26 @@ t.test('flatteners that populate flat.omit array', t => {
// ignored if setting is not dev or development
obj.also = 'ignored'
definitions.also.flatten('also', obj, flat)
t.strictSame(obj, {also: 'ignored'}, 'nothing done')
t.strictSame(flat, {}, 'nothing done')
t.strictSame(obj, {also: 'ignored', omit: [], include: []}, 'nothing done')
t.strictSame(flat, {omit: []}, 'nothing done')
obj.also = 'development'
definitions.also.flatten('also', obj, flat)
t.strictSame(obj, { also: 'development', include: ['dev'] }, 'marked dev as included')
t.strictSame(obj, {
also: 'development',
omit: [],
include: ['dev'],
}, 'marked dev as included')
t.strictSame(flat, { omit: [] }, 'nothing omitted, so nothing changed')
obj.omit = ['dev', 'optional']
obj.include = []
definitions.also.flatten('also', obj, flat)
t.strictSame(obj, { also: 'development', omit: ['dev', 'optional'], include: ['dev'] }, 'marked dev as included')
t.strictSame(obj, {
also: 'development',
omit: ['optional'],
include: ['dev'],
}, 'marked dev as included')
t.strictSame(flat, { omit: ['optional'] }, 'removed dev from omit')
t.end()
})
@ -237,7 +245,7 @@ t.test('flatteners that populate flat.omit array', t => {
const flat = {}
const obj = { only: 'asdf' }
definitions.only.flatten('only', obj, flat)
t.strictSame(flat, {}, 'ignored if value is not production')
t.strictSame(flat, { omit: [] }, 'ignored if value is not production')
obj.only = 'prod'
definitions.only.flatten('only', obj, flat)
@ -256,18 +264,30 @@ t.test('flatteners that populate flat.omit array', t => {
const obj = { optional: null }
definitions.optional.flatten('optional', obj, flat)
t.strictSame(obj, { optional: null }, 'do nothing by default')
t.strictSame(flat, {}, 'do nothing by default')
t.strictSame(obj, {
optional: null,
omit: [],
include: [],
}, 'do nothing by default')
t.strictSame(flat, { omit: [] }, 'do nothing by default')
obj.optional = true
definitions.optional.flatten('optional', obj, flat)
t.strictSame(obj, {include: ['optional'], optional: true}, 'include optional when set')
t.strictSame(obj, {
omit: [],
optional: true,
include: ['optional'],
}, 'include optional when set')
t.strictSame(flat, {omit: []}, 'nothing to omit in flatOptions')
delete obj.include
obj.optional = false
definitions.optional.flatten('optional', obj, flat)
t.strictSame(obj, {omit: ['optional'], optional: false}, 'omit optional when set false')
t.strictSame(obj, {
omit: ['optional'],
optional: false,
include: [],
}, 'omit optional when set false')
t.strictSame(flat, {omit: ['optional']}, 'omit optional when set false')
t.end()
@ -277,25 +297,49 @@ t.test('flatteners that populate flat.omit array', t => {
const flat = {}
const obj = {production: true}
definitions.production.flatten('production', obj, flat)
t.strictSame(obj, {production: true, omit: ['dev']}, '--production sets --omit=dev')
t.strictSame(obj, {
production: true,
omit: ['dev'],
include: [],
}, '--production sets --omit=dev')
t.strictSame(flat, {omit: ['dev']}, '--production sets --omit=dev')
delete obj.omit
obj.production = false
delete flat.omit
definitions.production.flatten('production', obj, flat)
t.strictSame(obj, {production: false}, '--no-production has no effect')
t.strictSame(flat, {}, '--no-production has no effect')
t.strictSame(obj, {
production: false,
include: ['dev'],
omit: [],
}, '--no-production explicitly includes dev')
t.strictSame(flat, { omit: [] }, '--no-production has no effect')
obj.production = true
obj.include = ['dev']
definitions.production.flatten('production', obj, flat)
t.strictSame(obj, {production: true, include: ['dev'], omit: ['dev']}, 'omit and include dev')
t.strictSame(obj, {
production: true,
include: ['dev'],
omit: [],
}, 'omit and include dev')
t.strictSame(flat, {omit: []}, 'do not omit dev when included')
t.end()
})
t.test('dev', t => {
const flat = {}
const obj = {dev: true}
definitions.dev.flatten('dev', obj, flat)
t.strictSame(obj, {
dev: true,
omit: [],
include: ['dev'],
})
t.end()
})
t.end()
})
@ -695,3 +739,18 @@ t.test('user-agent', t => {
t.equal(flat.userAgent, expectCI)
t.end()
})
t.test('save-prefix', t => {
const obj = {
'save-exact': true,
'save-prefix': '~1.2.3',
}
const flat = {}
definitions['save-prefix']
.flatten('save-prefix', { ...obj, 'save-exact': true }, flat)
t.strictSame(flat, { savePrefix: '' })
definitions['save-prefix']
.flatten('save-prefix', { ...obj, 'save-exact': false }, flat)
t.strictSame(flat, { savePrefix: '~1.2.3' })
t.end()
})

View File

@ -6,6 +6,8 @@ delete process.env.NODE
process.execPath = '/path/to/node'
const obj = {
'save-exact': true,
'save-prefix': 'ignored',
'save-dev': true,
'@foobar:registry': 'https://foo.bar.com/',
'//foo.bar.com:_authToken': 'foobarbazquuxasdf',
@ -15,6 +17,8 @@ const obj = {
const flat = flatten(obj)
t.strictSame(flat, {
saveType: 'dev',
saveExact: true,
savePrefix: '',
'@foobar:registry': 'https://foo.bar.com/',
'//foo.bar.com:_authToken': 'foobarbazquuxasdf',
npmBin: '/path/to/npm',
@ -26,6 +30,8 @@ t.strictSame(flat, {
process.env.NODE = '/usr/local/bin/node.exe'
flatten({ 'save-dev': false }, flat)
t.strictSame(flat, {
saveExact: true,
savePrefix: '',
'@foobar:registry': 'https://foo.bar.com/',
'//foo.bar.com:_authToken': 'foobarbazquuxasdf',
npmBin: '/path/to/npm',