Last commit july 5th

This commit is contained in:
2024-07-05 13:46:23 +02:00
parent dad0d86e8c
commit b0e4dfbb76
24982 changed files with 2621219 additions and 413 deletions

15
spa/node_modules/bin-links/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,15 @@
The ISC License
Copyright (c) npm, Inc.
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.

90
spa/node_modules/bin-links/README.md generated vendored Normal file
View File

@@ -0,0 +1,90 @@
# bin-links [![npm version](https://img.shields.io/npm/v/bin-links.svg)](https://npm.im/bin-links) [![license](https://img.shields.io/npm/l/bin-links.svg)](https://npm.im/bin-links) [![Travis](https://img.shields.io/travis/npm/bin-links.svg)](https://travis-ci.org/npm/bin-links) [![AppVeyor](https://ci.appveyor.com/api/projects/status/github/npm/bin-links?svg=true)](https://ci.appveyor.com/project/npm/bin-links) [![Coverage Status](https://coveralls.io/repos/github/npm/bin-links/badge.svg?branch=latest)](https://coveralls.io/github/npm/bin-links?branch=latest)
[`bin-links`](https://github.com/npm/bin-links) is a standalone library that links
binaries and man pages for JavaScript packages
## Install
`$ npm install bin-links`
## Table of Contents
* [Example](#example)
* [Features](#features)
* [Contributing](#contributing)
* [API](#api)
* [`binLinks`](#binLinks)
* [`binLinks.getPaths()`](#getPaths)
* [`binLinks.checkBins()`](#checkBins)
### Example
```javascript
const binLinks = require('bin-links')
const readPackageJson = require('read-package-json-fast')
binLinks({
path: '/path/to/node_modules/some-package',
pkg: readPackageJson('/path/to/node_modules/some-package/package.json'),
// true if it's a global install, false for local. default: false
global: true,
// true if it's the top level package being installed, false otherwise
top: true,
// true if you'd like to recklessly overwrite files.
force: true,
})
```
### Features
* Links bin files listed under the `bin` property of pkg to the
`node_modules/.bin` directory of the installing environment. (Or
`${prefix}/bin` for top level global packages on unix, and `${prefix}`
for top level global packages on Windows.)
* Links man files listed under the `man` property of pkg to the share/man
directory. (This is only done for top-level global packages on Unix
systems.)
### Contributing
The npm team enthusiastically welcomes contributions and project participation!
There's a bunch of things you can do if you want to contribute! The [Contributor
Guide](CONTRIBUTING.md) has all the information you need for everything from
reporting bugs to contributing entire new features. Please don't hesitate to
jump in if you'd like to, or even ask us questions if something isn't clear.
### API
#### <a name="binLinks"></a> `> binLinks({path, pkg, force, global, top})`
Returns a Promise that resolves when the requisite things have been linked.
#### <a name="getPaths"></a> `> binLinks.getPaths({path, pkg, global, top })`
Returns an array of all the paths of links and shims that _might_ be
created (assuming that they exist!) for the package at the specified path.
Does not touch the filesystem.
#### <a name="checkBins"></a> `> binLinks.checkBins({path, pkg, global, top, force })`
Checks if there are any conflicting bins which will prevent the linking of
bins for the given package. Returns a Promise that resolves with no value
if the way is clear, and rejects if there's something in the way.
Always returns successfully if `global` or `top` are false, or if `force`
is true, or if the `pkg` object does not contain any bins to link.
Note that changes to the file system _may_ still cause the `binLinks`
method to fail even if this method succeeds. Does not check for
conflicting `man` links.
Reads from the filesystem but does not make any changes.
##### Example
```javascript
binLinks({path, pkg, force, global, top}).then(() => console.log('bins linked!'))
```

9
spa/node_modules/bin-links/lib/bin-target.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
const isWindows = require('./is-windows.js')
const getPrefix = require('./get-prefix.js')
const getNodeModules = require('./get-node-modules.js')
const { dirname } = require('path')
module.exports = ({ top, path }) =>
!top ? getNodeModules(path) + '/.bin'
: isWindows ? getPrefix(path)
: dirname(getPrefix(path)) + '/bin'

74
spa/node_modules/bin-links/lib/check-bin.js generated vendored Normal file
View File

@@ -0,0 +1,74 @@
// check to see if a bin is allowed to be overwritten
// either rejects or resolves to nothing. return value not relevant.
const isWindows = require('./is-windows.js')
const binTarget = require('./bin-target.js')
const { resolve, dirname } = require('path')
const readCmdShim = require('read-cmd-shim')
const { readlink } = require('fs/promises')
const checkBin = async ({ bin, path, top, global, force }) => {
// always ok to clobber when forced
// always ok to clobber local bins, or when forced
if (force || !global || !top) {
return
}
// ok, need to make sure, then
const target = resolve(binTarget({ path, top }), bin)
path = resolve(path)
return isWindows ? checkShim({ target, path }) : checkLink({ target, path })
}
// only enoent is allowed. anything else is a problem.
const handleReadLinkError = async ({ er, target }) =>
er.code === 'ENOENT' ? null
: failEEXIST({ target })
const checkLink = async ({ target, path }) => {
const current = await readlink(target)
.catch(er => handleReadLinkError({ er, target }))
if (!current) {
return
}
const resolved = resolve(dirname(target), current)
if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
return failEEXIST({ target })
}
}
const handleReadCmdShimError = ({ er, target }) =>
er.code === 'ENOENT' ? null
: failEEXIST({ target })
const failEEXIST = ({ target }) =>
Promise.reject(Object.assign(new Error('EEXIST: file already exists'), {
path: target,
code: 'EEXIST',
}))
const checkShim = async ({ target, path }) => {
const shims = [
target,
target + '.cmd',
target + '.ps1',
]
await Promise.all(shims.map(async shim => {
const current = await readCmdShim(shim)
.catch(er => handleReadCmdShimError({ er, target: shim }))
if (!current) {
return
}
const resolved = resolve(dirname(shim), current.replace(/\\/g, '/'))
if (resolved.toLowerCase().indexOf(path.toLowerCase()) !== 0) {
return failEEXIST({ target: shim })
}
}))
}
module.exports = checkBin

18
spa/node_modules/bin-links/lib/check-bins.js generated vendored Normal file
View File

@@ -0,0 +1,18 @@
const checkBin = require('./check-bin.js')
const normalize = require('npm-normalize-package-bin')
const checkBins = async ({ pkg, path, top, global, force }) => {
// always ok to clobber when forced
// always ok to clobber local bins, or when forced
if (force || !global || !top) {
return
}
pkg = normalize(pkg)
if (!pkg.bin) {
return
}
await Promise.all(Object.keys(pkg.bin)
.map(bin => checkBin({ bin, path, top, global, force })))
}
module.exports = checkBins

42
spa/node_modules/bin-links/lib/fix-bin.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
// make sure that bins are executable, and that they don't have
// windows line-endings on the hashbang line.
const {
chmod,
open,
readFile,
} = require('fs/promises')
const execMode = 0o777 & (~process.umask())
const writeFileAtomic = require('write-file-atomic')
const isWindowsHashBang = buf =>
buf[0] === '#'.charCodeAt(0) &&
buf[1] === '!'.charCodeAt(0) &&
/^#![^\n]+\r\n/.test(buf.toString())
const isWindowsHashbangFile = file => {
const FALSE = () => false
return open(file, 'r').then(fh => {
const buf = Buffer.alloc(2048)
return fh.read(buf, 0, 2048, 0)
.then(
() => {
const isWHB = isWindowsHashBang(buf)
return fh.close().then(() => isWHB, () => isWHB)
},
// don't leak FD if read() fails
() => fh.close().then(FALSE, FALSE)
)
}, FALSE)
}
const dos2Unix = file =>
readFile(file, 'utf8').then(content =>
writeFileAtomic(file, content.replace(/^(#![^\n]+)\r\n/, '$1\n')))
const fixBin = (file, mode = execMode) => chmod(file, mode)
.then(() => isWindowsHashbangFile(file))
.then(isWHB => isWHB ? dos2Unix(file) : null)
module.exports = fixBin

19
spa/node_modules/bin-links/lib/get-node-modules.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
// we know it's global and/or not top, so the path has to be
// {prefix}/node_modules/{name}. Can't rely on pkg.name, because
// it might be installed as an alias.
const { dirname, basename } = require('path')
// this gets called a lot and can't change, so memoize it
const memo = new Map()
module.exports = path => {
if (memo.has(path)) {
return memo.get(path)
}
const scopeOrNm = dirname(path)
const nm = basename(scopeOrNm) === 'node_modules' ? scopeOrNm
: dirname(scopeOrNm)
memo.set(path, nm)
return nm
}

42
spa/node_modules/bin-links/lib/get-paths.js generated vendored Normal file
View File

@@ -0,0 +1,42 @@
// get all the paths that are (or might be) installed for a given pkg
// There's no guarantee that all of these will be installed, but if they
// are present, then we can assume that they're associated.
const binTarget = require('./bin-target.js')
const manTarget = require('./man-target.js')
const { resolve, basename, extname } = require('path')
const isWindows = require('./is-windows.js')
module.exports = ({ path, pkg, global, top }) => {
if (top && !global) {
return []
}
const binSet = []
const binTarg = binTarget({ path, top })
if (pkg.bin) {
for (const bin of Object.keys(pkg.bin)) {
const b = resolve(binTarg, bin)
binSet.push(b)
if (isWindows) {
binSet.push(b + '.cmd')
binSet.push(b + '.ps1')
}
}
}
const manTarg = manTarget({ path, top })
const manSet = []
if (manTarg && pkg.man && Array.isArray(pkg.man) && pkg.man.length) {
for (const man of pkg.man) {
if (!/.\.[0-9]+(\.gz)?$/.test(man)) {
return binSet
}
const section = extname(basename(man, '.gz')).slice(1)
const base = basename(man)
manSet.push(resolve(manTarg, 'man' + section, base))
}
}
return manSet.length ? [...binSet, ...manSet] : binSet
}

3
spa/node_modules/bin-links/lib/get-prefix.js generated vendored Normal file
View File

@@ -0,0 +1,3 @@
const { dirname } = require('path')
const getNodeModules = require('./get-node-modules.js')
module.exports = path => dirname(getNodeModules(path))

44
spa/node_modules/bin-links/lib/index.js generated vendored Normal file
View File

@@ -0,0 +1,44 @@
const linkBins = require('./link-bins.js')
const linkMans = require('./link-mans.js')
const binLinks = opts => {
const { path, pkg, force, global, top } = opts
// global top pkgs on windows get bins installed in {prefix}, and no mans
//
// unix global top pkgs get their bins installed in {prefix}/bin,
// and mans in {prefix}/share/man
//
// non-top pkgs get their bins installed in {prefix}/node_modules/.bin,
// and do not install mans
//
// non-global top pkgs don't have any bins or mans linked. From here on
// out, if it's top, we know that it's global, so no need to pass that
// option further down the stack.
if (top && !global) {
return Promise.resolve()
}
return Promise.all([
// allow clobbering within the local node_modules/.bin folder.
// only global bins are protected in this way, or else it is
// yet another vector for excessive dependency conflicts.
linkBins({ path, pkg, top, force: force || !top }),
linkMans({ path, pkg, top, force }),
])
}
const shimBin = require('./shim-bin.js')
const linkGently = require('./link-gently.js')
const resetSeen = () => {
shimBin.resetSeen()
linkGently.resetSeen()
}
const checkBins = require('./check-bins.js')
const getPaths = require('./get-paths.js')
module.exports = Object.assign(binLinks, {
checkBins,
resetSeen,
getPaths,
})

2
spa/node_modules/bin-links/lib/is-windows.js generated vendored Normal file
View File

@@ -0,0 +1,2 @@
const platform = process.env.__TESTING_BIN_LINKS_PLATFORM__ || process.platform
module.exports = platform === 'win32'

9
spa/node_modules/bin-links/lib/link-bin.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
const linkGently = require('./link-gently.js')
const fixBin = require('./fix-bin.js')
// linking bins is simple. just symlink, and if we linked it, fix the bin up
const linkBin = ({ path, to, from, absFrom, force }) =>
linkGently({ path, to, from, absFrom, force })
.then(linked => linked && fixBin(absFrom))
module.exports = linkBin

23
spa/node_modules/bin-links/lib/link-bins.js generated vendored Normal file
View File

@@ -0,0 +1,23 @@
const isWindows = require('./is-windows.js')
const binTarget = require('./bin-target.js')
const { dirname, resolve, relative } = require('path')
const linkBin = isWindows ? require('./shim-bin.js') : require('./link-bin.js')
const normalize = require('npm-normalize-package-bin')
const linkBins = ({ path, pkg, top, force }) => {
pkg = normalize(pkg)
if (!pkg.bin) {
return Promise.resolve([])
}
const promises = []
const target = binTarget({ path, top })
for (const [key, val] of Object.entries(pkg.bin)) {
const to = resolve(target, key)
const absFrom = resolve(path, val)
const from = relative(dirname(to), absFrom)
promises.push(linkBin({ path, from, to, absFrom, force }))
}
return Promise.all(promises)
}
module.exports = linkBins

90
spa/node_modules/bin-links/lib/link-gently.js generated vendored Normal file
View File

@@ -0,0 +1,90 @@
// if the thing isn't there, skip it
// if there's a non-symlink there already, eexist
// if there's a symlink already, pointing somewhere else, eexist
// if there's a symlink already, pointing into our pkg, remove it first
// then create the symlink
const { resolve, dirname } = require('path')
const { lstat, mkdir, readlink, rm, symlink } = require('fs/promises')
const throwNonEnoent = er => {
if (er.code !== 'ENOENT') {
throw er
}
}
const rmOpts = {
recursive: true,
force: true,
}
// even in --force mode, we never create a link over a link we've
// already created. you can have multiple packages in a tree trying
// to contend for the same bin, or the same manpage listed multiple times,
// which creates a race condition and nondeterminism.
const seen = new Set()
const SKIP = Symbol('skip - missing or already installed')
const CLOBBER = Symbol('clobber - ours or in forceful mode')
const linkGently = async ({ path, to, from, absFrom, force }) => {
if (seen.has(to)) {
return false
}
seen.add(to)
// if the script or manpage isn't there, just ignore it.
// this arguably *should* be an install error of some sort,
// or at least a warning, but npm has always behaved this
// way in the past, so it'd be a breaking change
return Promise.all([
lstat(absFrom).catch(throwNonEnoent),
lstat(to).catch(throwNonEnoent),
]).then(([stFrom, stTo]) => {
// not present in package, skip it
if (!stFrom) {
return SKIP
}
// exists! maybe clobber if we can
if (stTo) {
if (!stTo.isSymbolicLink()) {
return force && rm(to, rmOpts).then(() => CLOBBER)
}
return readlink(to).then(target => {
if (target === from) {
return SKIP
} // skip it, already set up like we want it.
target = resolve(dirname(to), target)
if (target.indexOf(path) === 0 || force) {
return rm(to, rmOpts).then(() => CLOBBER)
}
// neither skip nor clobber
return false
})
} else {
// doesn't exist, dir might not either
return mkdir(dirname(to), { recursive: true })
}
})
.then(skipOrClobber => {
if (skipOrClobber === SKIP) {
return false
}
return symlink(from, to, 'file').catch(er => {
if (skipOrClobber === CLOBBER || force) {
return rm(to, rmOpts).then(() => symlink(from, to, 'file'))
}
throw er
}).then(() => true)
})
}
const resetSeen = () => {
for (const p of seen) {
seen.delete(p)
}
}
module.exports = Object.assign(linkGently, { resetSeen })

53
spa/node_modules/bin-links/lib/link-mans.js generated vendored Normal file
View File

@@ -0,0 +1,53 @@
const { dirname, relative, join, resolve, basename } = require('path')
const linkGently = require('./link-gently.js')
const manTarget = require('./man-target.js')
const linkMans = async ({ path, pkg, top, force }) => {
const target = manTarget({ path, top })
if (!target || !Array.isArray(pkg?.man) || !pkg.man.length) {
return []
}
const links = []
// `new Set` to filter out duplicates
for (let man of new Set(pkg.man)) {
if (!man || typeof man !== 'string') {
continue
}
// break any links to c:\\blah or /foo/blah or ../blah
man = join('/', man).replace(/\\|:/g, '/').slice(1)
const parseMan = man.match(/\.([0-9]+)(\.gz)?$/)
if (!parseMan) {
throw Object.assign(new Error('invalid man entry name\n' +
'Man files must end with a number, ' +
'and optionally a .gz suffix if they are compressed.'
), {
code: 'EBADMAN',
path,
pkgid: pkg._id,
man,
})
}
const section = parseMan[1]
const base = basename(man)
const absFrom = resolve(path, man)
/* istanbul ignore if - that unpossible */
if (absFrom.indexOf(path) !== 0) {
throw Object.assign(new Error('invalid man entry'), {
code: 'EBADMAN',
path,
pkgid: pkg._id,
man,
})
}
const to = resolve(target, 'man' + section, base)
const from = relative(dirname(to), absFrom)
links.push(linkGently({ from, to, path, absFrom, force }))
}
return Promise.all(links)
}
module.exports = linkMans

6
spa/node_modules/bin-links/lib/man-target.js generated vendored Normal file
View File

@@ -0,0 +1,6 @@
const isWindows = require('./is-windows.js')
const getPrefix = require('./get-prefix.js')
const { dirname } = require('path')
module.exports = ({ top, path }) => !top || isWindows ? null
: dirname(getPrefix(path)) + '/share/man'

86
spa/node_modules/bin-links/lib/shim-bin.js generated vendored Normal file
View File

@@ -0,0 +1,86 @@
const { resolve, dirname } = require('path')
const { lstat } = require('fs/promises')
const throwNonEnoent = er => {
if (er.code !== 'ENOENT') {
throw er
}
}
const cmdShim = require('cmd-shim')
const readCmdShim = require('read-cmd-shim')
const fixBin = require('./fix-bin.js')
// even in --force mode, we never create a shim over a shim we've
// already created. you can have multiple packages in a tree trying
// to contend for the same bin, which creates a race condition and
// nondeterminism.
const seen = new Set()
const failEEXIST = ({ to, from }) =>
Promise.reject(Object.assign(new Error('EEXIST: file already exists'), {
path: to,
dest: from,
code: 'EEXIST',
}))
const handleReadCmdShimError = ({ er, from, to }) =>
er.code === 'ENOENT' ? null
: er.code === 'ENOTASHIM' ? failEEXIST({ from, to })
: Promise.reject(er)
const SKIP = Symbol('skip - missing or already installed')
const shimBin = ({ path, to, from, absFrom, force }) => {
const shims = [
to,
to + '.cmd',
to + '.ps1',
]
for (const shim of shims) {
if (seen.has(shim)) {
return true
}
seen.add(shim)
}
return Promise.all([
...shims,
absFrom,
].map(f => lstat(f).catch(throwNonEnoent))).then((stats) => {
const [, , , stFrom] = stats
if (!stFrom) {
return SKIP
}
if (force) {
return false
}
return Promise.all(shims.map((s, i) => [s, stats[i]]).map(([s, st]) => {
if (!st) {
return false
}
return readCmdShim(s)
.then(target => {
target = resolve(dirname(to), target)
if (target.indexOf(resolve(path)) !== 0) {
return failEEXIST({ from, to, path })
}
return false
}, er => handleReadCmdShimError({ er, from, to }))
}))
})
.then(skip => skip !== SKIP && doShim(absFrom, to))
}
const doShim = (absFrom, to) =>
cmdShim(absFrom, to).then(() => fixBin(absFrom))
const resetSeen = () => {
for (const p of seen) {
seen.delete(p)
}
}
module.exports = Object.assign(shimBin, { resetSeen })

View File

@@ -0,0 +1,16 @@
The ISC License
Copyright (c) 2015-2023 Benjamin Coe, Isaac Z. Schlueter, and Contributors
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

@@ -0,0 +1,74 @@
# signal-exit
When you want to fire an event no matter how a process exits:
- reaching the end of execution.
- explicitly having `process.exit(code)` called.
- having `process.kill(pid, sig)` called.
- receiving a fatal signal from outside the process
Use `signal-exit`.
```js
// Hybrid module, either works
import { onExit } from 'signal-exit'
// or:
// const { onExit } = require('signal-exit')
onExit((code, signal) => {
console.log('process exited!', code, signal)
})
```
## API
`remove = onExit((code, signal) => {}, options)`
The return value of the function is a function that will remove
the handler.
Note that the function _only_ fires for signals if the signal
would cause the process to exit. That is, there are no other
listeners, and it is a fatal signal.
If the global `process` object is not suitable for this purpose
(ie, it's unset, or doesn't have an `emit` method, etc.) then the
`onExit` function is a no-op that returns a no-op `remove` method.
### Options
- `alwaysLast`: Run this handler after any other signal or exit
handlers. This causes `process.emit` to be monkeypatched.
### Capturing Signal Exits
If the handler returns an exact boolean `true`, and the exit is a
due to signal, then the signal will be considered handled, and
will _not_ trigger a synthetic `process.kill(process.pid,
signal)` after firing the `onExit` handlers.
In this case, it your responsibility as the caller to exit with a
signal (for example, by calling `process.kill()`) if you wish to
preserve the same exit status that would otherwise have occurred.
If you do not, then the process will likely exit gracefully with
status 0 at some point, assuming that no other terminating signal
or other exit trigger occurs.
Prior to calling handlers, the `onExit` machinery is unloaded, so
any subsequent exits or signals will not be handled, even if the
signal is captured and the exit is thus prevented.
Note that numeric code exits may indicate that the process is
already committed to exiting, for example due to a fatal
exception or unhandled promise rejection, and so there is no way to
prevent it safely.
### Browser Fallback
The `'signal-exit/browser'` module is the same fallback shim that
just doesn't do anything, but presents the same function
interface.
Patches welcome to add something that hooks onto
`window.onbeforeunload` or similar, but it might just not be a
thing that makes sense there.

View File

@@ -0,0 +1,12 @@
/**
* This is a browser shim that provides the same functional interface
* as the main node export, but it does nothing.
* @module
*/
import type { Handler } from './index.js';
export declare const onExit: (cb: Handler, opts: {
alwaysLast?: boolean;
}) => () => void;
export declare const load: () => void;
export declare const unload: () => void;
//# sourceMappingURL=browser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACzC,eAAO,MAAM,MAAM,EAAE,CACnB,EAAE,EAAE,OAAO,EACX,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,KAC3B,MAAM,IAAqB,CAAA;AAChC,eAAO,MAAM,IAAI,YAAW,CAAA;AAC5B,eAAO,MAAM,MAAM,YAAW,CAAA"}

View File

@@ -0,0 +1,10 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.unload = exports.load = exports.onExit = void 0;
const onExit = () => () => { };
exports.onExit = onExit;
const load = () => { };
exports.load = load;
const unload = () => { };
exports.unload = unload;
//# sourceMappingURL=browser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":";;;AAMO,MAAM,MAAM,GAGD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAHnB,QAAA,MAAM,UAGa;AACzB,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;AAAf,QAAA,IAAI,QAAW;AACrB,MAAM,MAAM,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;AAAjB,QAAA,MAAM,UAAW","sourcesContent":["/**\n * This is a browser shim that provides the same functional interface\n * as the main node export, but it does nothing.\n * @module\n */\nimport type { Handler } from './index.js'\nexport const onExit: (\n cb: Handler,\n opts: { alwaysLast?: boolean }\n) => () => void = () => () => {}\nexport const load = () => {}\nexport const unload = () => {}\n"]}

View File

@@ -0,0 +1,48 @@
/// <reference types="node" />
import { signals } from './signals.js';
export { signals };
/**
* A function that takes an exit code and signal as arguments
*
* In the case of signal exits *only*, a return value of true
* will indicate that the signal is being handled, and we should
* not synthetically exit with the signal we received. Regardless
* of the handler return value, the handler is unloaded when an
* otherwise fatal signal is received, so you get exactly 1 shot
* at it, unless you add another onExit handler at that point.
*
* In the case of numeric code exits, we may already have committed
* to exiting the process, for example via a fatal exception or
* unhandled promise rejection, so it is impossible to stop safely.
*/
export type Handler = (code: number | null | undefined, signal: NodeJS.Signals | null) => true | void;
export declare const
/**
* Called when the process is exiting, whether via signal, explicit
* exit, or running out of stuff to do.
*
* If the global process object is not suitable for instrumentation,
* then this will be a no-op.
*
* Returns a function that may be used to unload signal-exit.
*/
onExit: (cb: Handler, opts?: {
alwaysLast?: boolean | undefined;
} | undefined) => () => void,
/**
* Load the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
load: () => void,
/**
* Unload the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
unload: () => void;
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,CAAA;AAuBlB;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,GAAG,CACpB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAC1B,IAAI,GAAG,IAAI,CAAA;AA8QhB,eAAO;AACL;;;;;;;;GAQG;AACH,MAAM,OAzMO,OAAO;;wBAPiD,IAAI;AAkNzE;;;;;;GAMG;AACH,IAAI;AAEJ;;;;;;GAMG;AACH,MAAM,YAGP,CAAA"}

View File

@@ -0,0 +1,279 @@
"use strict";
var _a;
Object.defineProperty(exports, "__esModule", { value: true });
exports.unload = exports.load = exports.onExit = exports.signals = void 0;
// Note: since nyc uses this module to output coverage, any lines
// that are in the direct sync flow of nyc's outputCoverage are
// ignored, since we can never get coverage for them.
// grab a reference to node's real process object right away
const signals_js_1 = require("./signals.js");
Object.defineProperty(exports, "signals", { enumerable: true, get: function () { return signals_js_1.signals; } });
const processOk = (process) => !!process &&
typeof process === 'object' &&
typeof process.removeListener === 'function' &&
typeof process.emit === 'function' &&
typeof process.reallyExit === 'function' &&
typeof process.listeners === 'function' &&
typeof process.kill === 'function' &&
typeof process.pid === 'number' &&
typeof process.on === 'function';
const kExitEmitter = Symbol.for('signal-exit emitter');
const global = globalThis;
const ObjectDefineProperty = Object.defineProperty.bind(Object);
// teeny special purpose ee
class Emitter {
emitted = {
afterExit: false,
exit: false,
};
listeners = {
afterExit: [],
exit: [],
};
count = 0;
id = Math.random();
constructor() {
if (global[kExitEmitter]) {
return global[kExitEmitter];
}
ObjectDefineProperty(global, kExitEmitter, {
value: this,
writable: false,
enumerable: false,
configurable: false,
});
}
on(ev, fn) {
this.listeners[ev].push(fn);
}
removeListener(ev, fn) {
const list = this.listeners[ev];
const i = list.indexOf(fn);
/* c8 ignore start */
if (i === -1) {
return;
}
/* c8 ignore stop */
if (i === 0 && list.length === 1) {
list.length = 0;
}
else {
list.splice(i, 1);
}
}
emit(ev, code, signal) {
if (this.emitted[ev]) {
return false;
}
this.emitted[ev] = true;
let ret = false;
for (const fn of this.listeners[ev]) {
ret = fn(code, signal) === true || ret;
}
if (ev === 'exit') {
ret = this.emit('afterExit', code, signal) || ret;
}
return ret;
}
}
class SignalExitBase {
}
const signalExitWrap = (handler) => {
return {
onExit(cb, opts) {
return handler.onExit(cb, opts);
},
load() {
return handler.load();
},
unload() {
return handler.unload();
},
};
};
class SignalExitFallback extends SignalExitBase {
onExit() {
return () => { };
}
load() { }
unload() { }
}
class SignalExit extends SignalExitBase {
// "SIGHUP" throws an `ENOSYS` error on Windows,
// so use a supported signal instead
/* c8 ignore start */
#hupSig = process.platform === 'win32' ? 'SIGINT' : 'SIGHUP';
/* c8 ignore stop */
#emitter = new Emitter();
#process;
#originalProcessEmit;
#originalProcessReallyExit;
#sigListeners = {};
#loaded = false;
constructor(process) {
super();
this.#process = process;
// { <signal>: <listener fn>, ... }
this.#sigListeners = {};
for (const sig of signals_js_1.signals) {
this.#sigListeners[sig] = () => {
// If there are no other listeners, an exit is coming!
// Simplest way: remove us and then re-send the signal.
// We know that this will kill the process, so we can
// safely emit now.
const listeners = this.#process.listeners(sig);
let { count } = this.#emitter;
// This is a workaround for the fact that signal-exit v3 and signal
// exit v4 are not aware of each other, and each will attempt to let
// the other handle it, so neither of them do. To correct this, we
// detect if we're the only handler *except* for previous versions
// of signal-exit, and increment by the count of listeners it has
// created.
/* c8 ignore start */
const p = process;
if (typeof p.__signal_exit_emitter__ === 'object' &&
typeof p.__signal_exit_emitter__.count === 'number') {
count += p.__signal_exit_emitter__.count;
}
/* c8 ignore stop */
if (listeners.length === count) {
this.unload();
const ret = this.#emitter.emit('exit', null, sig);
/* c8 ignore start */
const s = sig === 'SIGHUP' ? this.#hupSig : sig;
if (!ret)
process.kill(process.pid, s);
/* c8 ignore stop */
}
};
}
this.#originalProcessReallyExit = process.reallyExit;
this.#originalProcessEmit = process.emit;
}
onExit(cb, opts) {
/* c8 ignore start */
if (!processOk(this.#process)) {
return () => { };
}
/* c8 ignore stop */
if (this.#loaded === false) {
this.load();
}
const ev = opts?.alwaysLast ? 'afterExit' : 'exit';
this.#emitter.on(ev, cb);
return () => {
this.#emitter.removeListener(ev, cb);
if (this.#emitter.listeners['exit'].length === 0 &&
this.#emitter.listeners['afterExit'].length === 0) {
this.unload();
}
};
}
load() {
if (this.#loaded) {
return;
}
this.#loaded = true;
// This is the number of onSignalExit's that are in play.
// It's important so that we can count the correct number of
// listeners on signals, and don't wait for the other one to
// handle it instead of us.
this.#emitter.count += 1;
for (const sig of signals_js_1.signals) {
try {
const fn = this.#sigListeners[sig];
if (fn)
this.#process.on(sig, fn);
}
catch (_) { }
}
this.#process.emit = (ev, ...a) => {
return this.#processEmit(ev, ...a);
};
this.#process.reallyExit = (code) => {
return this.#processReallyExit(code);
};
}
unload() {
if (!this.#loaded) {
return;
}
this.#loaded = false;
signals_js_1.signals.forEach(sig => {
const listener = this.#sigListeners[sig];
/* c8 ignore start */
if (!listener) {
throw new Error('Listener not defined for signal: ' + sig);
}
/* c8 ignore stop */
try {
this.#process.removeListener(sig, listener);
/* c8 ignore start */
}
catch (_) { }
/* c8 ignore stop */
});
this.#process.emit = this.#originalProcessEmit;
this.#process.reallyExit = this.#originalProcessReallyExit;
this.#emitter.count -= 1;
}
#processReallyExit(code) {
/* c8 ignore start */
if (!processOk(this.#process)) {
return 0;
}
this.#process.exitCode = code || 0;
/* c8 ignore stop */
this.#emitter.emit('exit', this.#process.exitCode, null);
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
}
#processEmit(ev, ...args) {
const og = this.#originalProcessEmit;
if (ev === 'exit' && processOk(this.#process)) {
if (typeof args[0] === 'number') {
this.#process.exitCode = args[0];
/* c8 ignore start */
}
/* c8 ignore start */
const ret = og.call(this.#process, ev, ...args);
/* c8 ignore start */
this.#emitter.emit('exit', this.#process.exitCode, null);
/* c8 ignore stop */
return ret;
}
else {
return og.call(this.#process, ev, ...args);
}
}
}
const process = globalThis.process;
// wrap so that we call the method on the actual handler, without
// exporting it directly.
_a = signalExitWrap(processOk(process) ? new SignalExit(process) : new SignalExitFallback()),
/**
* Called when the process is exiting, whether via signal, explicit
* exit, or running out of stuff to do.
*
* If the global process object is not suitable for instrumentation,
* then this will be a no-op.
*
* Returns a function that may be used to unload signal-exit.
*/
exports.onExit = _a.onExit,
/**
* Load the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
exports.load = _a.load,
/**
* Unload the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
exports.unload = _a.unload;
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
{
"type": "commonjs"
}

View File

@@ -0,0 +1,29 @@
/// <reference types="node" />
/**
* This is not the set of all possible signals.
*
* It IS, however, the set of all signals that trigger
* an exit on either Linux or BSD systems. Linux is a
* superset of the signal names supported on BSD, and
* the unknown signals just fail to register, so we can
* catch that easily enough.
*
* Windows signals are a different set, since there are
* signals that terminate Windows processes, but don't
* terminate (or don't even exist) on Posix systems.
*
* Don't bother with SIGKILL. It's uncatchable, which
* means that we can't fire any callbacks anyway.
*
* If a user does happen to register a handler on a non-
* fatal signal like SIGWINCH or something, and then
* exit, it'll end up firing `process.emit('exit')`, so
* the handler will be fired anyway.
*
* SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
* artificially, inherently leave the process in a
* state from which it is not safe to try and enter JS
* listeners.
*/
export declare const signals: NodeJS.Signals[];
//# sourceMappingURL=signals.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/signals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,OAAO,EAAO,CAAA"}

View File

@@ -0,0 +1,42 @@
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.signals = void 0;
/**
* This is not the set of all possible signals.
*
* It IS, however, the set of all signals that trigger
* an exit on either Linux or BSD systems. Linux is a
* superset of the signal names supported on BSD, and
* the unknown signals just fail to register, so we can
* catch that easily enough.
*
* Windows signals are a different set, since there are
* signals that terminate Windows processes, but don't
* terminate (or don't even exist) on Posix systems.
*
* Don't bother with SIGKILL. It's uncatchable, which
* means that we can't fire any callbacks anyway.
*
* If a user does happen to register a handler on a non-
* fatal signal like SIGWINCH or something, and then
* exit, it'll end up firing `process.emit('exit')`, so
* the handler will be fired anyway.
*
* SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
* artificially, inherently leave the process in a
* state from which it is not safe to try and enter JS
* listeners.
*/
exports.signals = [];
exports.signals.push('SIGHUP', 'SIGINT', 'SIGTERM');
if (process.platform !== 'win32') {
exports.signals.push('SIGALRM', 'SIGABRT', 'SIGVTALRM', 'SIGXCPU', 'SIGXFSZ', 'SIGUSR2', 'SIGTRAP', 'SIGSYS', 'SIGQUIT', 'SIGIOT'
// should detect profiler and enable/disable accordingly.
// see #21
// 'SIGPROF'
);
}
if (process.platform === 'linux') {
exports.signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT');
}
//# sourceMappingURL=signals.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/signals.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACU,QAAA,OAAO,GAAqB,EAAE,CAAA;AAC3C,eAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;AAE3C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;IAChC,eAAO,CAAC,IAAI,CACV,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ;IACR,yDAAyD;IACzD,UAAU;IACV,YAAY;KACb,CAAA;CACF;AAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;IAChC,eAAO,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;CACxD","sourcesContent":["/**\n * This is not the set of all possible signals.\n *\n * It IS, however, the set of all signals that trigger\n * an exit on either Linux or BSD systems. Linux is a\n * superset of the signal names supported on BSD, and\n * the unknown signals just fail to register, so we can\n * catch that easily enough.\n *\n * Windows signals are a different set, since there are\n * signals that terminate Windows processes, but don't\n * terminate (or don't even exist) on Posix systems.\n *\n * Don't bother with SIGKILL. It's uncatchable, which\n * means that we can't fire any callbacks anyway.\n *\n * If a user does happen to register a handler on a non-\n * fatal signal like SIGWINCH or something, and then\n * exit, it'll end up firing `process.emit('exit')`, so\n * the handler will be fired anyway.\n *\n * SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised\n * artificially, inherently leave the process in a\n * state from which it is not safe to try and enter JS\n * listeners.\n */\nexport const signals: NodeJS.Signals[] = []\nsignals.push('SIGHUP', 'SIGINT', 'SIGTERM')\n\nif (process.platform !== 'win32') {\n signals.push(\n 'SIGALRM',\n 'SIGABRT',\n 'SIGVTALRM',\n 'SIGXCPU',\n 'SIGXFSZ',\n 'SIGUSR2',\n 'SIGTRAP',\n 'SIGSYS',\n 'SIGQUIT',\n 'SIGIOT'\n // should detect profiler and enable/disable accordingly.\n // see #21\n // 'SIGPROF'\n )\n}\n\nif (process.platform === 'linux') {\n signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT')\n}\n"]}

View File

@@ -0,0 +1,12 @@
/**
* This is a browser shim that provides the same functional interface
* as the main node export, but it does nothing.
* @module
*/
import type { Handler } from './index.js';
export declare const onExit: (cb: Handler, opts: {
alwaysLast?: boolean;
}) => () => void;
export declare const load: () => void;
export declare const unload: () => void;
//# sourceMappingURL=browser.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA;AACzC,eAAO,MAAM,MAAM,EAAE,CACnB,EAAE,EAAE,OAAO,EACX,IAAI,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,KAC3B,MAAM,IAAqB,CAAA;AAChC,eAAO,MAAM,IAAI,YAAW,CAAA;AAC5B,eAAO,MAAM,MAAM,YAAW,CAAA"}

View File

@@ -0,0 +1,4 @@
export const onExit = () => () => { };
export const load = () => { };
export const unload = () => { };
//# sourceMappingURL=browser.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/browser.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,MAAM,GAGD,GAAG,EAAE,CAAC,GAAG,EAAE,GAAE,CAAC,CAAA;AAChC,MAAM,CAAC,MAAM,IAAI,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA;AAC5B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,GAAE,CAAC,CAAA","sourcesContent":["/**\n * This is a browser shim that provides the same functional interface\n * as the main node export, but it does nothing.\n * @module\n */\nimport type { Handler } from './index.js'\nexport const onExit: (\n cb: Handler,\n opts: { alwaysLast?: boolean }\n) => () => void = () => () => {}\nexport const load = () => {}\nexport const unload = () => {}\n"]}

View File

@@ -0,0 +1,48 @@
/// <reference types="node" />
import { signals } from './signals.js';
export { signals };
/**
* A function that takes an exit code and signal as arguments
*
* In the case of signal exits *only*, a return value of true
* will indicate that the signal is being handled, and we should
* not synthetically exit with the signal we received. Regardless
* of the handler return value, the handler is unloaded when an
* otherwise fatal signal is received, so you get exactly 1 shot
* at it, unless you add another onExit handler at that point.
*
* In the case of numeric code exits, we may already have committed
* to exiting the process, for example via a fatal exception or
* unhandled promise rejection, so it is impossible to stop safely.
*/
export type Handler = (code: number | null | undefined, signal: NodeJS.Signals | null) => true | void;
export declare const
/**
* Called when the process is exiting, whether via signal, explicit
* exit, or running out of stuff to do.
*
* If the global process object is not suitable for instrumentation,
* then this will be a no-op.
*
* Returns a function that may be used to unload signal-exit.
*/
onExit: (cb: Handler, opts?: {
alwaysLast?: boolean | undefined;
} | undefined) => () => void,
/**
* Load the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
load: () => void,
/**
* Unload the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
unload: () => void;
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,CAAA;AAuBlB;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,OAAO,GAAG,CACpB,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAC/B,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAC1B,IAAI,GAAG,IAAI,CAAA;AA8QhB,eAAO;AACL;;;;;;;;GAQG;AACH,MAAM,OAzMO,OAAO;;wBAPiD,IAAI;AAkNzE;;;;;;GAMG;AACH,IAAI;AAEJ;;;;;;GAMG;AACH,MAAM,YAGP,CAAA"}

View File

@@ -0,0 +1,275 @@
// Note: since nyc uses this module to output coverage, any lines
// that are in the direct sync flow of nyc's outputCoverage are
// ignored, since we can never get coverage for them.
// grab a reference to node's real process object right away
import { signals } from './signals.js';
export { signals };
const processOk = (process) => !!process &&
typeof process === 'object' &&
typeof process.removeListener === 'function' &&
typeof process.emit === 'function' &&
typeof process.reallyExit === 'function' &&
typeof process.listeners === 'function' &&
typeof process.kill === 'function' &&
typeof process.pid === 'number' &&
typeof process.on === 'function';
const kExitEmitter = Symbol.for('signal-exit emitter');
const global = globalThis;
const ObjectDefineProperty = Object.defineProperty.bind(Object);
// teeny special purpose ee
class Emitter {
emitted = {
afterExit: false,
exit: false,
};
listeners = {
afterExit: [],
exit: [],
};
count = 0;
id = Math.random();
constructor() {
if (global[kExitEmitter]) {
return global[kExitEmitter];
}
ObjectDefineProperty(global, kExitEmitter, {
value: this,
writable: false,
enumerable: false,
configurable: false,
});
}
on(ev, fn) {
this.listeners[ev].push(fn);
}
removeListener(ev, fn) {
const list = this.listeners[ev];
const i = list.indexOf(fn);
/* c8 ignore start */
if (i === -1) {
return;
}
/* c8 ignore stop */
if (i === 0 && list.length === 1) {
list.length = 0;
}
else {
list.splice(i, 1);
}
}
emit(ev, code, signal) {
if (this.emitted[ev]) {
return false;
}
this.emitted[ev] = true;
let ret = false;
for (const fn of this.listeners[ev]) {
ret = fn(code, signal) === true || ret;
}
if (ev === 'exit') {
ret = this.emit('afterExit', code, signal) || ret;
}
return ret;
}
}
class SignalExitBase {
}
const signalExitWrap = (handler) => {
return {
onExit(cb, opts) {
return handler.onExit(cb, opts);
},
load() {
return handler.load();
},
unload() {
return handler.unload();
},
};
};
class SignalExitFallback extends SignalExitBase {
onExit() {
return () => { };
}
load() { }
unload() { }
}
class SignalExit extends SignalExitBase {
// "SIGHUP" throws an `ENOSYS` error on Windows,
// so use a supported signal instead
/* c8 ignore start */
#hupSig = process.platform === 'win32' ? 'SIGINT' : 'SIGHUP';
/* c8 ignore stop */
#emitter = new Emitter();
#process;
#originalProcessEmit;
#originalProcessReallyExit;
#sigListeners = {};
#loaded = false;
constructor(process) {
super();
this.#process = process;
// { <signal>: <listener fn>, ... }
this.#sigListeners = {};
for (const sig of signals) {
this.#sigListeners[sig] = () => {
// If there are no other listeners, an exit is coming!
// Simplest way: remove us and then re-send the signal.
// We know that this will kill the process, so we can
// safely emit now.
const listeners = this.#process.listeners(sig);
let { count } = this.#emitter;
// This is a workaround for the fact that signal-exit v3 and signal
// exit v4 are not aware of each other, and each will attempt to let
// the other handle it, so neither of them do. To correct this, we
// detect if we're the only handler *except* for previous versions
// of signal-exit, and increment by the count of listeners it has
// created.
/* c8 ignore start */
const p = process;
if (typeof p.__signal_exit_emitter__ === 'object' &&
typeof p.__signal_exit_emitter__.count === 'number') {
count += p.__signal_exit_emitter__.count;
}
/* c8 ignore stop */
if (listeners.length === count) {
this.unload();
const ret = this.#emitter.emit('exit', null, sig);
/* c8 ignore start */
const s = sig === 'SIGHUP' ? this.#hupSig : sig;
if (!ret)
process.kill(process.pid, s);
/* c8 ignore stop */
}
};
}
this.#originalProcessReallyExit = process.reallyExit;
this.#originalProcessEmit = process.emit;
}
onExit(cb, opts) {
/* c8 ignore start */
if (!processOk(this.#process)) {
return () => { };
}
/* c8 ignore stop */
if (this.#loaded === false) {
this.load();
}
const ev = opts?.alwaysLast ? 'afterExit' : 'exit';
this.#emitter.on(ev, cb);
return () => {
this.#emitter.removeListener(ev, cb);
if (this.#emitter.listeners['exit'].length === 0 &&
this.#emitter.listeners['afterExit'].length === 0) {
this.unload();
}
};
}
load() {
if (this.#loaded) {
return;
}
this.#loaded = true;
// This is the number of onSignalExit's that are in play.
// It's important so that we can count the correct number of
// listeners on signals, and don't wait for the other one to
// handle it instead of us.
this.#emitter.count += 1;
for (const sig of signals) {
try {
const fn = this.#sigListeners[sig];
if (fn)
this.#process.on(sig, fn);
}
catch (_) { }
}
this.#process.emit = (ev, ...a) => {
return this.#processEmit(ev, ...a);
};
this.#process.reallyExit = (code) => {
return this.#processReallyExit(code);
};
}
unload() {
if (!this.#loaded) {
return;
}
this.#loaded = false;
signals.forEach(sig => {
const listener = this.#sigListeners[sig];
/* c8 ignore start */
if (!listener) {
throw new Error('Listener not defined for signal: ' + sig);
}
/* c8 ignore stop */
try {
this.#process.removeListener(sig, listener);
/* c8 ignore start */
}
catch (_) { }
/* c8 ignore stop */
});
this.#process.emit = this.#originalProcessEmit;
this.#process.reallyExit = this.#originalProcessReallyExit;
this.#emitter.count -= 1;
}
#processReallyExit(code) {
/* c8 ignore start */
if (!processOk(this.#process)) {
return 0;
}
this.#process.exitCode = code || 0;
/* c8 ignore stop */
this.#emitter.emit('exit', this.#process.exitCode, null);
return this.#originalProcessReallyExit.call(this.#process, this.#process.exitCode);
}
#processEmit(ev, ...args) {
const og = this.#originalProcessEmit;
if (ev === 'exit' && processOk(this.#process)) {
if (typeof args[0] === 'number') {
this.#process.exitCode = args[0];
/* c8 ignore start */
}
/* c8 ignore start */
const ret = og.call(this.#process, ev, ...args);
/* c8 ignore start */
this.#emitter.emit('exit', this.#process.exitCode, null);
/* c8 ignore stop */
return ret;
}
else {
return og.call(this.#process, ev, ...args);
}
}
}
const process = globalThis.process;
// wrap so that we call the method on the actual handler, without
// exporting it directly.
export const {
/**
* Called when the process is exiting, whether via signal, explicit
* exit, or running out of stuff to do.
*
* If the global process object is not suitable for instrumentation,
* then this will be a no-op.
*
* Returns a function that may be used to unload signal-exit.
*/
onExit,
/**
* Load the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
load,
/**
* Unload the listeners. Likely you never need to call this, unless
* doing a rather deep integration with signal-exit functionality.
* Mostly exposed for the benefit of testing.
*
* @internal
*/
unload, } = signalExitWrap(processOk(process) ? new SignalExit(process) : new SignalExitFallback());
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,3 @@
{
"type": "module"
}

View File

@@ -0,0 +1,29 @@
/// <reference types="node" />
/**
* This is not the set of all possible signals.
*
* It IS, however, the set of all signals that trigger
* an exit on either Linux or BSD systems. Linux is a
* superset of the signal names supported on BSD, and
* the unknown signals just fail to register, so we can
* catch that easily enough.
*
* Windows signals are a different set, since there are
* signals that terminate Windows processes, but don't
* terminate (or don't even exist) on Posix systems.
*
* Don't bother with SIGKILL. It's uncatchable, which
* means that we can't fire any callbacks anyway.
*
* If a user does happen to register a handler on a non-
* fatal signal like SIGWINCH or something, and then
* exit, it'll end up firing `process.emit('exit')`, so
* the handler will be fired anyway.
*
* SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
* artificially, inherently leave the process in a
* state from which it is not safe to try and enter JS
* listeners.
*/
export declare const signals: NodeJS.Signals[];
//# sourceMappingURL=signals.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signals.d.ts","sourceRoot":"","sources":["../../src/signals.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,OAAO,EAAO,CAAA"}

View File

@@ -0,0 +1,39 @@
/**
* This is not the set of all possible signals.
*
* It IS, however, the set of all signals that trigger
* an exit on either Linux or BSD systems. Linux is a
* superset of the signal names supported on BSD, and
* the unknown signals just fail to register, so we can
* catch that easily enough.
*
* Windows signals are a different set, since there are
* signals that terminate Windows processes, but don't
* terminate (or don't even exist) on Posix systems.
*
* Don't bother with SIGKILL. It's uncatchable, which
* means that we can't fire any callbacks anyway.
*
* If a user does happen to register a handler on a non-
* fatal signal like SIGWINCH or something, and then
* exit, it'll end up firing `process.emit('exit')`, so
* the handler will be fired anyway.
*
* SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised
* artificially, inherently leave the process in a
* state from which it is not safe to try and enter JS
* listeners.
*/
export const signals = [];
signals.push('SIGHUP', 'SIGINT', 'SIGTERM');
if (process.platform !== 'win32') {
signals.push('SIGALRM', 'SIGABRT', 'SIGVTALRM', 'SIGXCPU', 'SIGXFSZ', 'SIGUSR2', 'SIGTRAP', 'SIGSYS', 'SIGQUIT', 'SIGIOT'
// should detect profiler and enable/disable accordingly.
// see #21
// 'SIGPROF'
);
}
if (process.platform === 'linux') {
signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT');
}
//# sourceMappingURL=signals.js.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"signals.js","sourceRoot":"","sources":["../../src/signals.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,MAAM,OAAO,GAAqB,EAAE,CAAA;AAC3C,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAA;AAE3C,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;IAChC,OAAO,CAAC,IAAI,CACV,SAAS,EACT,SAAS,EACT,WAAW,EACX,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,QAAQ,EACR,SAAS,EACT,QAAQ;IACR,yDAAyD;IACzD,UAAU;IACV,YAAY;KACb,CAAA;CACF;AAED,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE;IAChC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAA;CACxD","sourcesContent":["/**\n * This is not the set of all possible signals.\n *\n * It IS, however, the set of all signals that trigger\n * an exit on either Linux or BSD systems. Linux is a\n * superset of the signal names supported on BSD, and\n * the unknown signals just fail to register, so we can\n * catch that easily enough.\n *\n * Windows signals are a different set, since there are\n * signals that terminate Windows processes, but don't\n * terminate (or don't even exist) on Posix systems.\n *\n * Don't bother with SIGKILL. It's uncatchable, which\n * means that we can't fire any callbacks anyway.\n *\n * If a user does happen to register a handler on a non-\n * fatal signal like SIGWINCH or something, and then\n * exit, it'll end up firing `process.emit('exit')`, so\n * the handler will be fired anyway.\n *\n * SIGBUS, SIGFPE, SIGSEGV and SIGILL, when not raised\n * artificially, inherently leave the process in a\n * state from which it is not safe to try and enter JS\n * listeners.\n */\nexport const signals: NodeJS.Signals[] = []\nsignals.push('SIGHUP', 'SIGINT', 'SIGTERM')\n\nif (process.platform !== 'win32') {\n signals.push(\n 'SIGALRM',\n 'SIGABRT',\n 'SIGVTALRM',\n 'SIGXCPU',\n 'SIGXFSZ',\n 'SIGUSR2',\n 'SIGTRAP',\n 'SIGSYS',\n 'SIGQUIT',\n 'SIGIOT'\n // should detect profiler and enable/disable accordingly.\n // see #21\n // 'SIGPROF'\n )\n}\n\nif (process.platform === 'linux') {\n signals.push('SIGIO', 'SIGPOLL', 'SIGPWR', 'SIGSTKFLT')\n}\n"]}

View File

@@ -0,0 +1,106 @@
{
"name": "signal-exit",
"version": "4.1.0",
"description": "when you want to fire an event no matter how a process exits.",
"main": "./dist/cjs/index.js",
"module": "./dist/mjs/index.js",
"browser": "./dist/mjs/browser.js",
"types": "./dist/mjs/index.d.ts",
"exports": {
".": {
"import": {
"types": "./dist/mjs/index.d.ts",
"default": "./dist/mjs/index.js"
},
"require": {
"types": "./dist/cjs/index.d.ts",
"default": "./dist/cjs/index.js"
}
},
"./signals": {
"import": {
"types": "./dist/mjs/signals.d.ts",
"default": "./dist/mjs/signals.js"
},
"require": {
"types": "./dist/cjs/signals.d.ts",
"default": "./dist/cjs/signals.js"
}
},
"./browser": {
"import": {
"types": "./dist/mjs/browser.d.ts",
"default": "./dist/mjs/browser.js"
},
"require": {
"types": "./dist/cjs/browser.d.ts",
"default": "./dist/cjs/browser.js"
}
}
},
"files": [
"dist"
],
"engines": {
"node": ">=14"
},
"repository": {
"type": "git",
"url": "https://github.com/tapjs/signal-exit.git"
},
"keywords": [
"signal",
"exit"
],
"author": "Ben Coe <ben@npmjs.com>",
"license": "ISC",
"devDependencies": {
"@types/cross-spawn": "^6.0.2",
"@types/node": "^18.15.11",
"@types/signal-exit": "^3.0.1",
"@types/tap": "^15.0.8",
"c8": "^7.13.0",
"prettier": "^2.8.6",
"tap": "^16.3.4",
"ts-node": "^10.9.1",
"typedoc": "^0.23.28",
"typescript": "^5.0.2"
},
"scripts": {
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags",
"preprepare": "rm -rf dist",
"prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json && bash ./scripts/fixup.sh",
"pretest": "npm run prepare",
"presnap": "npm run prepare",
"test": "c8 tap",
"snap": "c8 tap",
"format": "prettier --write . --loglevel warn",
"typedoc": "typedoc --tsconfig tsconfig-esm.json ./src/*.ts"
},
"prettier": {
"semi": false,
"printWidth": 75,
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"jsxSingleQuote": false,
"bracketSameLine": true,
"arrowParens": "avoid",
"endOfLine": "lf"
},
"tap": {
"coverage": false,
"jobs": 1,
"node-arg": [
"--no-warnings",
"--loader",
"ts-node/esm"
],
"ts": false
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
}

View File

@@ -0,0 +1,6 @@
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

@@ -0,0 +1,91 @@
write-file-atomic
-----------------
This is an extension for node's `fs.writeFile` that makes its operation
atomic and allows you set ownership (uid/gid of the file).
### `writeFileAtomic(filename, data, [options], [callback])`
#### Description:
Atomically and asynchronously writes data to a file, replacing the file if it already
exists. data can be a string or a buffer.
#### Options:
* filename **String**
* data **String** | **Buffer**
* options **Object** | **String**
* chown **Object** default, uid & gid of existing file, if any
* uid **Number**
* gid **Number**
* encoding **String** | **Null** default = 'utf8'
* fsync **Boolean** default = true
* mode **Number** default, from existing file, if any
* tmpfileCreated **Function** called when the tmpfile is created
* callback **Function**
#### Usage:
```js
var writeFileAtomic = require('write-file-atomic')
writeFileAtomic(filename, data, [options], [callback])
```
The file is initially named `filename + "." + murmurhex(__filename, process.pid, ++invocations)`.
Note that `require('worker_threads').threadId` is used in addition to `process.pid` if running inside of a worker thread.
If writeFile completes successfully then, if passed the **chown** option it will change
the ownership of the file. Finally it renames the file back to the filename you specified. If
it encounters errors at any of these steps it will attempt to unlink the temporary file and then
pass the error back to the caller.
If multiple writes are concurrently issued to the same file, the write operations are put into a queue and serialized in the order they were called, using Promises. Writes to different files are still executed in parallel.
If provided, the **chown** option requires both **uid** and **gid** properties or else
you'll get an error. If **chown** is not specified it will default to using
the owner of the previous file. To prevent chown from being ran you can
also pass `false`, in which case the file will be created with the current user's credentials.
If **mode** is not specified, it will default to using the permissions from
an existing file, if any. Expicitly setting this to `false` remove this default, resulting
in a file created with the system default permissions.
If options is a String, it's assumed to be the **encoding** option. The **encoding** option is ignored if **data** is a buffer. It defaults to 'utf8'.
If the **fsync** option is **false**, writeFile will skip the final fsync call.
If the **tmpfileCreated** option is specified it will be called with the name of the tmpfile when created.
Example:
```javascript
writeFileAtomic('message.txt', 'Hello Node', {chown:{uid:100,gid:50}}, function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
```
This function also supports async/await:
```javascript
(async () => {
try {
await writeFileAtomic('message.txt', 'Hello Node', {chown:{uid:100,gid:50}});
console.log('It\'s saved!');
} catch (err) {
console.error(err);
process.exit(1);
}
})();
```
### `writeFileAtomicSync(filename, data, [options])`
#### Description:
The synchronous version of **writeFileAtomic**.
#### Usage:
```js
var writeFileAtomicSync = require('write-file-atomic').sync
writeFileAtomicSync(filename, data, [options])
```

View File

@@ -0,0 +1,267 @@
'use strict'
module.exports = writeFile
module.exports.sync = writeFileSync
module.exports._getTmpname = getTmpname // for testing
module.exports._cleanupOnExit = cleanupOnExit
const fs = require('fs')
const MurmurHash3 = require('imurmurhash')
const { onExit } = require('signal-exit')
const path = require('path')
const { promisify } = require('util')
const activeFiles = {}
// if we run inside of a worker_thread, `process.pid` is not unique
/* istanbul ignore next */
const threadId = (function getId () {
try {
const workerThreads = require('worker_threads')
/// if we are in main thread, this is set to `0`
return workerThreads.threadId
} catch (e) {
// worker_threads are not available, fallback to 0
return 0
}
})()
let invocations = 0
function getTmpname (filename) {
return filename + '.' +
MurmurHash3(__filename)
.hash(String(process.pid))
.hash(String(threadId))
.hash(String(++invocations))
.result()
}
function cleanupOnExit (tmpfile) {
return () => {
try {
fs.unlinkSync(typeof tmpfile === 'function' ? tmpfile() : tmpfile)
} catch {
// ignore errors
}
}
}
function serializeActiveFile (absoluteName) {
return new Promise(resolve => {
// make a queue if it doesn't already exist
if (!activeFiles[absoluteName]) {
activeFiles[absoluteName] = []
}
activeFiles[absoluteName].push(resolve) // add this job to the queue
if (activeFiles[absoluteName].length === 1) {
resolve()
} // kick off the first one
})
}
// https://github.com/isaacs/node-graceful-fs/blob/master/polyfills.js#L315-L342
function isChownErrOk (err) {
if (err.code === 'ENOSYS') {
return true
}
const nonroot = !process.getuid || process.getuid() !== 0
if (nonroot) {
if (err.code === 'EINVAL' || err.code === 'EPERM') {
return true
}
}
return false
}
async function writeFileAsync (filename, data, options = {}) {
if (typeof options === 'string') {
options = { encoding: options }
}
let fd
let tmpfile
/* istanbul ignore next -- The closure only gets called when onExit triggers */
const removeOnExitHandler = onExit(cleanupOnExit(() => tmpfile))
const absoluteName = path.resolve(filename)
try {
await serializeActiveFile(absoluteName)
const truename = await promisify(fs.realpath)(filename).catch(() => filename)
tmpfile = getTmpname(truename)
if (!options.mode || !options.chown) {
// Either mode or chown is not explicitly set
// Default behavior is to copy it from original file
const stats = await promisify(fs.stat)(truename).catch(() => {})
if (stats) {
if (options.mode == null) {
options.mode = stats.mode
}
if (options.chown == null && process.getuid) {
options.chown = { uid: stats.uid, gid: stats.gid }
}
}
}
fd = await promisify(fs.open)(tmpfile, 'w', options.mode)
if (options.tmpfileCreated) {
await options.tmpfileCreated(tmpfile)
}
if (ArrayBuffer.isView(data)) {
await promisify(fs.write)(fd, data, 0, data.length, 0)
} else if (data != null) {
await promisify(fs.write)(fd, String(data), 0, String(options.encoding || 'utf8'))
}
if (options.fsync !== false) {
await promisify(fs.fsync)(fd)
}
await promisify(fs.close)(fd)
fd = null
if (options.chown) {
await promisify(fs.chown)(tmpfile, options.chown.uid, options.chown.gid).catch(err => {
if (!isChownErrOk(err)) {
throw err
}
})
}
if (options.mode) {
await promisify(fs.chmod)(tmpfile, options.mode).catch(err => {
if (!isChownErrOk(err)) {
throw err
}
})
}
await promisify(fs.rename)(tmpfile, truename)
} finally {
if (fd) {
await promisify(fs.close)(fd).catch(
/* istanbul ignore next */
() => {}
)
}
removeOnExitHandler()
await promisify(fs.unlink)(tmpfile).catch(() => {})
activeFiles[absoluteName].shift() // remove the element added by serializeSameFile
if (activeFiles[absoluteName].length > 0) {
activeFiles[absoluteName][0]() // start next job if one is pending
} else {
delete activeFiles[absoluteName]
}
}
}
async function writeFile (filename, data, options, callback) {
if (options instanceof Function) {
callback = options
options = {}
}
const promise = writeFileAsync(filename, data, options)
if (callback) {
try {
const result = await promise
return callback(result)
} catch (err) {
return callback(err)
}
}
return promise
}
function writeFileSync (filename, data, options) {
if (typeof options === 'string') {
options = { encoding: options }
} else if (!options) {
options = {}
}
try {
filename = fs.realpathSync(filename)
} catch (ex) {
// it's ok, it'll happen on a not yet existing file
}
const tmpfile = getTmpname(filename)
if (!options.mode || !options.chown) {
// Either mode or chown is not explicitly set
// Default behavior is to copy it from original file
try {
const stats = fs.statSync(filename)
options = Object.assign({}, options)
if (!options.mode) {
options.mode = stats.mode
}
if (!options.chown && process.getuid) {
options.chown = { uid: stats.uid, gid: stats.gid }
}
} catch (ex) {
// ignore stat errors
}
}
let fd
const cleanup = cleanupOnExit(tmpfile)
const removeOnExitHandler = onExit(cleanup)
let threw = true
try {
fd = fs.openSync(tmpfile, 'w', options.mode || 0o666)
if (options.tmpfileCreated) {
options.tmpfileCreated(tmpfile)
}
if (ArrayBuffer.isView(data)) {
fs.writeSync(fd, data, 0, data.length, 0)
} else if (data != null) {
fs.writeSync(fd, String(data), 0, String(options.encoding || 'utf8'))
}
if (options.fsync !== false) {
fs.fsyncSync(fd)
}
fs.closeSync(fd)
fd = null
if (options.chown) {
try {
fs.chownSync(tmpfile, options.chown.uid, options.chown.gid)
} catch (err) {
if (!isChownErrOk(err)) {
throw err
}
}
}
if (options.mode) {
try {
fs.chmodSync(tmpfile, options.mode)
} catch (err) {
if (!isChownErrOk(err)) {
throw err
}
}
}
fs.renameSync(tmpfile, filename)
threw = false
} finally {
if (fd) {
try {
fs.closeSync(fd)
} catch (ex) {
// ignore close errors at this stage, error may have closed fd already.
}
}
removeOnExitHandler()
if (threw) {
cleanup()
}
}
}

View File

@@ -0,0 +1,57 @@
{
"name": "write-file-atomic",
"version": "5.0.1",
"description": "Write files in an atomic fashion w/configurable ownership",
"main": "./lib/index.js",
"scripts": {
"test": "tap",
"posttest": "npm run lint",
"lint": "eslint \"**/*.js\"",
"postlint": "template-oss-check",
"lintfix": "npm run lint -- --fix",
"snap": "tap",
"template-oss-apply": "template-oss-apply --force"
},
"repository": {
"type": "git",
"url": "https://github.com/npm/write-file-atomic.git"
},
"keywords": [
"writeFile",
"atomic"
],
"author": "GitHub Inc.",
"license": "ISC",
"bugs": {
"url": "https://github.com/npm/write-file-atomic/issues"
},
"homepage": "https://github.com/npm/write-file-atomic",
"dependencies": {
"imurmurhash": "^0.1.4",
"signal-exit": "^4.0.1"
},
"devDependencies": {
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.14.1",
"tap": "^16.0.1"
},
"files": [
"bin/",
"lib/"
],
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
"version": "4.14.1",
"publish": "true"
},
"tap": {
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
]
}
}

59
spa/node_modules/bin-links/package.json generated vendored Normal file
View File

@@ -0,0 +1,59 @@
{
"name": "bin-links",
"version": "4.0.4",
"description": "JavaScript package binary linker",
"main": "./lib/index.js",
"scripts": {
"snap": "tap",
"test": "tap",
"lint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
"postlint": "template-oss-check",
"lintfix": "npm run lint -- --fix",
"posttest": "npm run lint",
"template-oss-apply": "template-oss-apply --force"
},
"repository": {
"type": "git",
"url": "git+https://github.com/npm/bin-links.git"
},
"keywords": [
"npm",
"link",
"bins"
],
"license": "ISC",
"dependencies": {
"cmd-shim": "^6.0.0",
"npm-normalize-package-bin": "^3.0.0",
"read-cmd-shim": "^4.0.0",
"write-file-atomic": "^5.0.0"
},
"devDependencies": {
"@npmcli/eslint-config": "^4.0.0",
"@npmcli/template-oss": "4.22.0",
"require-inject": "^1.4.4",
"tap": "^16.0.1"
},
"tap": {
"check-coverage": true,
"coverage-map": "map.js",
"nyc-arg": [
"--exclude",
"tap-snapshots/**"
]
},
"files": [
"bin/",
"lib/"
],
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
},
"author": "GitHub Inc.",
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"windowsCI": false,
"version": "4.22.0",
"publish": true
}
}