Aktueller Stand

This commit is contained in:
2026-01-23 01:33:35 +01:00
parent 082dc5e110
commit 2766dd12c5
10109 changed files with 1578841 additions and 77685 deletions

108
backend/node_modules/proper-lockfile/CHANGELOG.md generated vendored Normal file
View File

@@ -0,0 +1,108 @@
# 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="4.1.2"></a>
## [4.1.2](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.1...v4.1.2) (2021-01-25)
### Bug Fixes
* fix node 14 updating graceful-fs ([#102](https://github.com/moxystudio/node-proper-lockfile/issues/102)) ([b0d988e](https://github.com/moxystudio/node-proper-lockfile/commit/b0d988e))
<a name="4.1.1"></a>
## [4.1.1](https://github.com/moxystudio/node-proper-lockfile/compare/v4.1.0...v4.1.1) (2019-04-03)
### Bug Fixes
* fix mtime precision on some filesystems ([#88](https://github.com/moxystudio/node-proper-lockfile/issues/88)) ([f266158](https://github.com/moxystudio/node-proper-lockfile/commit/f266158)), closes [#82](https://github.com/moxystudio/node-proper-lockfile/issues/82) [#87](https://github.com/moxystudio/node-proper-lockfile/issues/87)
<a name="4.1.0"></a>
# [4.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v4.0.0...v4.1.0) (2019-03-18)
### Features
* allow second precision in mtime comparison ([#78](https://github.com/moxystudio/node-proper-lockfile/issues/78)) ([b2816a6](https://github.com/moxystudio/node-proper-lockfile/commit/b2816a6))
<a name="4.0.0"></a>
# [4.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.2.0...v4.0.0) (2019-03-12)
### Bug Fixes
* fix typo in error message ([#68](https://github.com/moxystudio/node-proper-lockfile/issues/68)) ([b91cb55](https://github.com/moxystudio/node-proper-lockfile/commit/b91cb55))
### Features
* make staleness check more robust ([#74](https://github.com/moxystudio/node-proper-lockfile/issues/74)) ([9cc0973](https://github.com/moxystudio/node-proper-lockfile/commit/9cc0973)), closes [#71](https://github.com/moxystudio/node-proper-lockfile/issues/71) [/github.com/ipfs/js-ipfs-repo/issues/188#issuecomment-468682971](https://github.com//github.com/ipfs/js-ipfs-repo/issues/188/issues/issuecomment-468682971)
### BREAKING CHANGES
* We were marking the lock as compromised when system went into sleep or if the event loop was busy taking too long to run the internals timers, Now we keep track of the mtime updated by the current process, and if we lose some cycles in the update process but recover and the mtime is still ours we do not mark the lock as compromised.
<a name="3.2.0"></a>
# [3.2.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.1.0...v3.2.0) (2018-11-19)
### Features
* add lock path option ([#66](https://github.com/moxystudio/node-proper-lockfile/issues/66)) ([32f1b8d](https://github.com/moxystudio/node-proper-lockfile/commit/32f1b8d))
<a name="3.1.0"></a>
# [3.1.0](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.2...v3.1.0) (2018-11-15)
### Bug Fixes
* **package:** update retry to version 0.12.0 ([#50](https://github.com/moxystudio/node-proper-lockfile/issues/50)) ([d400b98](https://github.com/moxystudio/node-proper-lockfile/commit/d400b98))
### Features
* add signal exit ([#65](https://github.com/moxystudio/node-proper-lockfile/issues/65)) ([f20bc45](https://github.com/moxystudio/node-proper-lockfile/commit/f20bc45))
<a name="3.0.2"></a>
## [3.0.2](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.1...v3.0.2) (2018-01-30)
<a name="3.0.1"></a>
## [3.0.1](https://github.com/moxystudio/node-proper-lockfile/compare/v3.0.0...v3.0.1) (2018-01-20)
### Bug Fixes
* restore ability to use lockfile() directly ([0ef8fbc](https://github.com/moxystudio/node-proper-lockfile/commit/0ef8fbc))
<a name="3.0.0"></a>
# [3.0.0](https://github.com/moxystudio/node-proper-lockfile/compare/v2.0.1...v3.0.0) (2018-01-20)
### Chores
* update project to latest node lts ([b1d43e5](https://github.com/moxystudio/node-proper-lockfile/commit/b1d43e5))
### BREAKING CHANGES
* remove callback support
* use of node lts language features such as object spread
* compromised function in lock() has been moved to an option

21
backend/node_modules/proper-lockfile/LICENSE generated vendored Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

183
backend/node_modules/proper-lockfile/README.md generated vendored Normal file
View File

@@ -0,0 +1,183 @@
# proper-lockfile
[![NPM version][npm-image]][npm-url] [![Downloads][downloads-image]][npm-url] [![Build Status][travis-image]][travis-url] [![Coverage Status][codecov-image]][codecov-url] [![Dependency status][david-dm-image]][david-dm-url] [![Dev Dependency status][david-dm-dev-image]][david-dm-dev-url]
[npm-url]:https://npmjs.org/package/proper-lockfile
[downloads-image]:https://img.shields.io/npm/dm/proper-lockfile.svg
[npm-image]:https://img.shields.io/npm/v/proper-lockfile.svg
[travis-url]:https://travis-ci.org/moxystudio/node-proper-lockfile
[travis-image]:https://img.shields.io/travis/moxystudio/node-proper-lockfile/master.svg
[codecov-url]:https://codecov.io/gh/moxystudio/node-proper-lockfile
[codecov-image]:https://img.shields.io/codecov/c/github/moxystudio/node-proper-lockfile/master.svg
[david-dm-url]:https://david-dm.org/moxystudio/node-proper-lockfile
[david-dm-image]:https://img.shields.io/david/moxystudio/node-proper-lockfile.svg
[david-dm-dev-url]:https://david-dm.org/moxystudio/node-proper-lockfile?type=dev
[david-dm-dev-image]:https://img.shields.io/david/dev/moxystudio/node-proper-lockfile.svg
An inter-process and inter-machine lockfile utility that works on a local or network file system.
## Installation
`$ npm install proper-lockfile`
## Design
There are various ways to achieve [file locking](http://en.wikipedia.org/wiki/File_locking).
This library utilizes the `mkdir` strategy which works atomically on any kind of file system, even network based ones.
The lockfile path is based on the file path you are trying to lock by suffixing it with `.lock`.
When a lock is successfully acquired, the lockfile's `mtime` (modified time) is periodically updated to prevent staleness. This allows to effectively check if a lock is stale by checking its `mtime` against a stale threshold. If the update of the mtime fails several times, the lock might be compromised. The `mtime` is [supported](http://en.wikipedia.org/wiki/Comparison_of_file_systems) in almost every `filesystem`.
### Comparison
This library is similar to [lockfile](https://github.com/isaacs/lockfile) but the latter has some drawbacks:
- It relies on `open` with `O_EXCL` flag which has problems in network file systems. `proper-lockfile` uses `mkdir` which doesn't have this issue.
> O_EXCL is broken on NFS file systems; programs which rely on it for performing locking tasks will contain a race condition.
- The lockfile staleness check is done via `ctime` (creation time) which is unsuitable for long running processes. `proper-lockfile` constantly updates lockfiles `mtime` to do proper staleness check.
- It does not check if the lockfile was compromised which can lead to undesirable situations. `proper-lockfile` checks the lockfile when updating the `mtime`.
- It has a default value of `0` for the stale option which isn't good because any crash or process kill that the package can't handle gracefully will leave the lock active forever.
### Compromised
`proper-lockfile` does not detect cases in which:
- A `lockfile` is manually removed and someone else acquires the lock right after
- Different `stale`/`update` values are being used for the same file, possibly causing two locks to be acquired on the same file
`proper-lockfile` detects cases in which:
- Updates to the `lockfile` fail
- Updates take longer than expected, possibly causing the lock to become stale for a certain amount of time
As you see, the first two are a consequence of bad usage. Technically, it was possible to detect the first two but it would introduce complexity and eventual race conditions.
## Usage
### .lock(file, [options])
Tries to acquire a lock on `file` or rejects the promise on error.
If the lock succeeds, a `release` function is provided that should be called when you want to release the lock. The `release` function also rejects the promise on error (e.g. when the lock was already compromised).
Available options:
- `stale`: Duration in milliseconds in which the lock is considered stale, defaults to `10000` (minimum value is `5000`)
- `update`: The interval in milliseconds in which the lockfile's `mtime` will be updated, defaults to `stale/2` (minimum value is `1000`, maximum value is `stale/2`)
- `retries`: The number of retries or a [retry](https://www.npmjs.org/package/retry) options object, defaults to `0`
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
- `fs`: A custom fs to use, defaults to `graceful-fs`
- `onCompromised`: Called if the lock gets compromised, defaults to a function that simply throws the error which will probably cause the process to die
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
```js
const lockfile = require('proper-lockfile');
lockfile.lock('some/file')
.then((release) => {
// Do something while the file is locked
// Call the provided release function when you're done,
// which will also return a promise
return release();
})
.catch((e) => {
// either lock could not be acquired
// or releasing it failed
console.error(e)
});
// Alternatively, you may use lockfile('some/file') directly.
```
### .unlock(file, [options])
Releases a previously acquired lock on `file` or rejects the promise on error.
Whenever possible you should use the `release` function instead (as exemplified above). Still there are cases in which it's hard to keep a reference to it around code. In those cases `unlock()` might be handy.
Available options:
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
- `fs`: A custom fs to use, defaults to `graceful-fs`
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
```js
const lockfile = require('proper-lockfile');
lockfile.lock('some/file')
.then(() => {
// Do something while the file is locked
// Later..
return lockfile.unlock('some/file');
});
```
### .check(file, [options])
Check if the file is locked and its lockfile is not stale, rejects the promise on error.
Available options:
- `stale`: Duration in milliseconds in which the lock is considered stale, defaults to `10000` (minimum value is `5000`)
- `realpath`: Resolve symlinks using realpath, defaults to `true` (note that if `true`, the `file` must exist previously)
- `fs`: A custom fs to use, defaults to `graceful-fs`
- `lockfilePath`: Custom lockfile path. e.g.: If you want to lock a directory and create the lock file inside it, you can pass `file` as `<dir path>` and `options.lockfilePath` as `<dir path>/dir.lock`
```js
const lockfile = require('proper-lockfile');
lockfile.check('some/file')
.then((isLocked) => {
// isLocked will be true if 'some/file' is locked, false otherwise
});
```
### .lockSync(file, [options])
Sync version of `.lock()`.
Returns the `release` function or throws on error.
### .unlockSync(file, [options])
Sync version of `.unlock()`.
Throws on error.
### .checkSync(file, [options])
Sync version of `.check()`.
Returns a boolean or throws on error.
## Graceful exit
`proper-lockfile` automatically removes locks if the process exits, except if the process is killed with SIGKILL or it crashes due to a VM fatal error (e.g.: out of memory).
## Tests
`$ npm test`
`$ npm test -- --watch` during development
The test suite is very extensive. There's even a stress test to guarantee exclusiveness of locks.
## License
Released under the [MIT License](https://www.opensource.org/licenses/mit-license.php).

40
backend/node_modules/proper-lockfile/index.js generated vendored Normal file
View File

@@ -0,0 +1,40 @@
'use strict';
const lockfile = require('./lib/lockfile');
const { toPromise, toSync, toSyncOptions } = require('./lib/adapter');
async function lock(file, options) {
const release = await toPromise(lockfile.lock)(file, options);
return toPromise(release);
}
function lockSync(file, options) {
const release = toSync(lockfile.lock)(file, toSyncOptions(options));
return toSync(release);
}
function unlock(file, options) {
return toPromise(lockfile.unlock)(file, options);
}
function unlockSync(file, options) {
return toSync(lockfile.unlock)(file, toSyncOptions(options));
}
function check(file, options) {
return toPromise(lockfile.check)(file, options);
}
function checkSync(file, options) {
return toSync(lockfile.check)(file, toSyncOptions(options));
}
module.exports = lock;
module.exports.lock = lock;
module.exports.unlock = unlock;
module.exports.lockSync = lockSync;
module.exports.unlockSync = unlockSync;
module.exports.check = check;
module.exports.checkSync = checkSync;

85
backend/node_modules/proper-lockfile/lib/adapter.js generated vendored Normal file
View File

@@ -0,0 +1,85 @@
'use strict';
const fs = require('graceful-fs');
function createSyncFs(fs) {
const methods = ['mkdir', 'realpath', 'stat', 'rmdir', 'utimes'];
const newFs = { ...fs };
methods.forEach((method) => {
newFs[method] = (...args) => {
const callback = args.pop();
let ret;
try {
ret = fs[`${method}Sync`](...args);
} catch (err) {
return callback(err);
}
callback(null, ret);
};
});
return newFs;
}
// ----------------------------------------------------------
function toPromise(method) {
return (...args) => new Promise((resolve, reject) => {
args.push((err, result) => {
if (err) {
reject(err);
} else {
resolve(result);
}
});
method(...args);
});
}
function toSync(method) {
return (...args) => {
let err;
let result;
args.push((_err, _result) => {
err = _err;
result = _result;
});
method(...args);
if (err) {
throw err;
}
return result;
};
}
function toSyncOptions(options) {
// Shallow clone options because we are oging to mutate them
options = { ...options };
// Transform fs to use the sync methods instead
options.fs = createSyncFs(options.fs || fs);
// Retries are not allowed because it requires the flow to be sync
if (
(typeof options.retries === 'number' && options.retries > 0) ||
(options.retries && typeof options.retries.retries === 'number' && options.retries.retries > 0)
) {
throw Object.assign(new Error('Cannot use retries with the sync api'), { code: 'ESYNC' });
}
return options;
}
module.exports = {
toPromise,
toSync,
toSyncOptions,
};

342
backend/node_modules/proper-lockfile/lib/lockfile.js generated vendored Normal file
View File

@@ -0,0 +1,342 @@
'use strict';
const path = require('path');
const fs = require('graceful-fs');
const retry = require('retry');
const onExit = require('signal-exit');
const mtimePrecision = require('./mtime-precision');
const locks = {};
function getLockFile(file, options) {
return options.lockfilePath || `${file}.lock`;
}
function resolveCanonicalPath(file, options, callback) {
if (!options.realpath) {
return callback(null, path.resolve(file));
}
// Use realpath to resolve symlinks
// It also resolves relative paths
options.fs.realpath(file, callback);
}
function acquireLock(file, options, callback) {
const lockfilePath = getLockFile(file, options);
// Use mkdir to create the lockfile (atomic operation)
options.fs.mkdir(lockfilePath, (err) => {
if (!err) {
// At this point, we acquired the lock!
// Probe the mtime precision
return mtimePrecision.probe(lockfilePath, options.fs, (err, mtime, mtimePrecision) => {
// If it failed, try to remove the lock..
/* istanbul ignore if */
if (err) {
options.fs.rmdir(lockfilePath, () => {});
return callback(err);
}
callback(null, mtime, mtimePrecision);
});
}
// If error is not EEXIST then some other error occurred while locking
if (err.code !== 'EEXIST') {
return callback(err);
}
// Otherwise, check if lock is stale by analyzing the file mtime
if (options.stale <= 0) {
return callback(Object.assign(new Error('Lock file is already being held'), { code: 'ELOCKED', file }));
}
options.fs.stat(lockfilePath, (err, stat) => {
if (err) {
// Retry if the lockfile has been removed (meanwhile)
// Skip stale check to avoid recursiveness
if (err.code === 'ENOENT') {
return acquireLock(file, { ...options, stale: 0 }, callback);
}
return callback(err);
}
if (!isLockStale(stat, options)) {
return callback(Object.assign(new Error('Lock file is already being held'), { code: 'ELOCKED', file }));
}
// If it's stale, remove it and try again!
// Skip stale check to avoid recursiveness
removeLock(file, options, (err) => {
if (err) {
return callback(err);
}
acquireLock(file, { ...options, stale: 0 }, callback);
});
});
});
}
function isLockStale(stat, options) {
return stat.mtime.getTime() < Date.now() - options.stale;
}
function removeLock(file, options, callback) {
// Remove lockfile, ignoring ENOENT errors
options.fs.rmdir(getLockFile(file, options), (err) => {
if (err && err.code !== 'ENOENT') {
return callback(err);
}
callback();
});
}
function updateLock(file, options) {
const lock = locks[file];
// Just for safety, should never happen
/* istanbul ignore if */
if (lock.updateTimeout) {
return;
}
lock.updateDelay = lock.updateDelay || options.update;
lock.updateTimeout = setTimeout(() => {
lock.updateTimeout = null;
// Stat the file to check if mtime is still ours
// If it is, we can still recover from a system sleep or a busy event loop
options.fs.stat(lock.lockfilePath, (err, stat) => {
const isOverThreshold = lock.lastUpdate + options.stale < Date.now();
// If it failed to update the lockfile, keep trying unless
// the lockfile was deleted or we are over the threshold
if (err) {
if (err.code === 'ENOENT' || isOverThreshold) {
return setLockAsCompromised(file, lock, Object.assign(err, { code: 'ECOMPROMISED' }));
}
lock.updateDelay = 1000;
return updateLock(file, options);
}
const isMtimeOurs = lock.mtime.getTime() === stat.mtime.getTime();
if (!isMtimeOurs) {
return setLockAsCompromised(
file,
lock,
Object.assign(
new Error('Unable to update lock within the stale threshold'),
{ code: 'ECOMPROMISED' }
));
}
const mtime = mtimePrecision.getMtime(lock.mtimePrecision);
options.fs.utimes(lock.lockfilePath, mtime, mtime, (err) => {
const isOverThreshold = lock.lastUpdate + options.stale < Date.now();
// Ignore if the lock was released
if (lock.released) {
return;
}
// If it failed to update the lockfile, keep trying unless
// the lockfile was deleted or we are over the threshold
if (err) {
if (err.code === 'ENOENT' || isOverThreshold) {
return setLockAsCompromised(file, lock, Object.assign(err, { code: 'ECOMPROMISED' }));
}
lock.updateDelay = 1000;
return updateLock(file, options);
}
// All ok, keep updating..
lock.mtime = mtime;
lock.lastUpdate = Date.now();
lock.updateDelay = null;
updateLock(file, options);
});
});
}, lock.updateDelay);
// Unref the timer so that the nodejs process can exit freely
// This is safe because all acquired locks will be automatically released
// on process exit
// We first check that `lock.updateTimeout.unref` exists because some users
// may be using this module outside of NodeJS (e.g., in an electron app),
// and in those cases `setTimeout` return an integer.
/* istanbul ignore else */
if (lock.updateTimeout.unref) {
lock.updateTimeout.unref();
}
}
function setLockAsCompromised(file, lock, err) {
// Signal the lock has been released
lock.released = true;
// Cancel lock mtime update
// Just for safety, at this point updateTimeout should be null
/* istanbul ignore if */
if (lock.updateTimeout) {
clearTimeout(lock.updateTimeout);
}
if (locks[file] === lock) {
delete locks[file];
}
lock.options.onCompromised(err);
}
// ----------------------------------------------------------
function lock(file, options, callback) {
/* istanbul ignore next */
options = {
stale: 10000,
update: null,
realpath: true,
retries: 0,
fs,
onCompromised: (err) => { throw err; },
...options,
};
options.retries = options.retries || 0;
options.retries = typeof options.retries === 'number' ? { retries: options.retries } : options.retries;
options.stale = Math.max(options.stale || 0, 2000);
options.update = options.update == null ? options.stale / 2 : options.update || 0;
options.update = Math.max(Math.min(options.update, options.stale / 2), 1000);
// Resolve to a canonical file path
resolveCanonicalPath(file, options, (err, file) => {
if (err) {
return callback(err);
}
// Attempt to acquire the lock
const operation = retry.operation(options.retries);
operation.attempt(() => {
acquireLock(file, options, (err, mtime, mtimePrecision) => {
if (operation.retry(err)) {
return;
}
if (err) {
return callback(operation.mainError());
}
// We now own the lock
const lock = locks[file] = {
lockfilePath: getLockFile(file, options),
mtime,
mtimePrecision,
options,
lastUpdate: Date.now(),
};
// We must keep the lock fresh to avoid staleness
updateLock(file, options);
callback(null, (releasedCallback) => {
if (lock.released) {
return releasedCallback &&
releasedCallback(Object.assign(new Error('Lock is already released'), { code: 'ERELEASED' }));
}
// Not necessary to use realpath twice when unlocking
unlock(file, { ...options, realpath: false }, releasedCallback);
});
});
});
});
}
function unlock(file, options, callback) {
options = {
fs,
realpath: true,
...options,
};
// Resolve to a canonical file path
resolveCanonicalPath(file, options, (err, file) => {
if (err) {
return callback(err);
}
// Skip if the lock is not acquired
const lock = locks[file];
if (!lock) {
return callback(Object.assign(new Error('Lock is not acquired/owned by you'), { code: 'ENOTACQUIRED' }));
}
lock.updateTimeout && clearTimeout(lock.updateTimeout); // Cancel lock mtime update
lock.released = true; // Signal the lock has been released
delete locks[file]; // Delete from locks
removeLock(file, options, callback);
});
}
function check(file, options, callback) {
options = {
stale: 10000,
realpath: true,
fs,
...options,
};
options.stale = Math.max(options.stale || 0, 2000);
// Resolve to a canonical file path
resolveCanonicalPath(file, options, (err, file) => {
if (err) {
return callback(err);
}
// Check if lockfile exists
options.fs.stat(getLockFile(file, options), (err, stat) => {
if (err) {
// If does not exist, file is not locked. Otherwise, callback with error
return err.code === 'ENOENT' ? callback(null, false) : callback(err);
}
// Otherwise, check if lock is stale by analyzing the file mtime
return callback(null, !isLockStale(stat, options));
});
});
}
function getLocks() {
return locks;
}
// Remove acquired locks on exit
/* istanbul ignore next */
onExit(() => {
for (const file in locks) {
const options = locks[file].options;
try { options.fs.rmdirSync(getLockFile(file, options)); } catch (e) { /* Empty */ }
}
});
module.exports.lock = lock;
module.exports.unlock = unlock;
module.exports.check = check;
module.exports.getLocks = getLocks;

View File

@@ -0,0 +1,55 @@
'use strict';
const cacheSymbol = Symbol();
function probe(file, fs, callback) {
const cachedPrecision = fs[cacheSymbol];
if (cachedPrecision) {
return fs.stat(file, (err, stat) => {
/* istanbul ignore if */
if (err) {
return callback(err);
}
callback(null, stat.mtime, cachedPrecision);
});
}
// Set mtime by ceiling Date.now() to seconds + 5ms so that it's "not on the second"
const mtime = new Date((Math.ceil(Date.now() / 1000) * 1000) + 5);
fs.utimes(file, mtime, mtime, (err) => {
/* istanbul ignore if */
if (err) {
return callback(err);
}
fs.stat(file, (err, stat) => {
/* istanbul ignore if */
if (err) {
return callback(err);
}
const precision = stat.mtime.getTime() % 1000 === 0 ? 's' : 'ms';
// Cache the precision in a non-enumerable way
Object.defineProperty(fs, cacheSymbol, { value: precision });
callback(null, stat.mtime, precision);
});
});
}
function getMtime(precision) {
let now = Date.now();
if (precision === 's') {
now = Math.ceil(now / 1000) * 1000;
}
return new Date(now);
}
module.exports.probe = probe;
module.exports.getMtime = getMtime;

View File

@@ -0,0 +1,16 @@
The ISC License
Copyright (c) 2015, 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,39 @@
# signal-exit
[![Build Status](https://travis-ci.org/tapjs/signal-exit.png)](https://travis-ci.org/tapjs/signal-exit)
[![Coverage](https://coveralls.io/repos/tapjs/signal-exit/badge.svg?branch=master)](https://coveralls.io/r/tapjs/signal-exit?branch=master)
[![NPM version](https://img.shields.io/npm/v/signal-exit.svg)](https://www.npmjs.com/package/signal-exit)
[![Standard Version](https://img.shields.io/badge/release-standard%20version-brightgreen.svg)](https://github.com/conventional-changelog/standard-version)
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
var onExit = require('signal-exit')
onExit(function (code, signal) {
console.log('process exited!')
})
```
## API
`var remove = onExit(function (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.
## Options
* `alwaysLast`: Run this handler after any other signal or exit
handlers. This causes `process.emit` to be monkeypatched.

View File

@@ -0,0 +1,202 @@
// 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
var process = global.process
const processOk = function (process) {
return 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'
}
// some kind of non-node environment, just no-op
/* istanbul ignore if */
if (!processOk(process)) {
module.exports = function () {
return function () {}
}
} else {
var assert = require('assert')
var signals = require('./signals.js')
var isWin = /^win/i.test(process.platform)
var EE = require('events')
/* istanbul ignore if */
if (typeof EE !== 'function') {
EE = EE.EventEmitter
}
var emitter
if (process.__signal_exit_emitter__) {
emitter = process.__signal_exit_emitter__
} else {
emitter = process.__signal_exit_emitter__ = new EE()
emitter.count = 0
emitter.emitted = {}
}
// Because this emitter is a global, we have to check to see if a
// previous version of this library failed to enable infinite listeners.
// I know what you're about to say. But literally everything about
// signal-exit is a compromise with evil. Get used to it.
if (!emitter.infinite) {
emitter.setMaxListeners(Infinity)
emitter.infinite = true
}
module.exports = function (cb, opts) {
/* istanbul ignore if */
if (!processOk(global.process)) {
return function () {}
}
assert.equal(typeof cb, 'function', 'a callback must be provided for exit handler')
if (loaded === false) {
load()
}
var ev = 'exit'
if (opts && opts.alwaysLast) {
ev = 'afterexit'
}
var remove = function () {
emitter.removeListener(ev, cb)
if (emitter.listeners('exit').length === 0 &&
emitter.listeners('afterexit').length === 0) {
unload()
}
}
emitter.on(ev, cb)
return remove
}
var unload = function unload () {
if (!loaded || !processOk(global.process)) {
return
}
loaded = false
signals.forEach(function (sig) {
try {
process.removeListener(sig, sigListeners[sig])
} catch (er) {}
})
process.emit = originalProcessEmit
process.reallyExit = originalProcessReallyExit
emitter.count -= 1
}
module.exports.unload = unload
var emit = function emit (event, code, signal) {
/* istanbul ignore if */
if (emitter.emitted[event]) {
return
}
emitter.emitted[event] = true
emitter.emit(event, code, signal)
}
// { <signal>: <listener fn>, ... }
var sigListeners = {}
signals.forEach(function (sig) {
sigListeners[sig] = function listener () {
/* istanbul ignore if */
if (!processOk(global.process)) {
return
}
// 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.
var listeners = process.listeners(sig)
if (listeners.length === emitter.count) {
unload()
emit('exit', null, sig)
/* istanbul ignore next */
emit('afterexit', null, sig)
/* istanbul ignore next */
if (isWin && sig === 'SIGHUP') {
// "SIGHUP" throws an `ENOSYS` error on Windows,
// so use a supported signal instead
sig = 'SIGINT'
}
/* istanbul ignore next */
process.kill(process.pid, sig)
}
}
})
module.exports.signals = function () {
return signals
}
var loaded = false
var load = function load () {
if (loaded || !processOk(global.process)) {
return
}
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.
emitter.count += 1
signals = signals.filter(function (sig) {
try {
process.on(sig, sigListeners[sig])
return true
} catch (er) {
return false
}
})
process.emit = processEmit
process.reallyExit = processReallyExit
}
module.exports.load = load
var originalProcessReallyExit = process.reallyExit
var processReallyExit = function processReallyExit (code) {
/* istanbul ignore if */
if (!processOk(global.process)) {
return
}
process.exitCode = code || /* istanbul ignore next */ 0
emit('exit', process.exitCode, null)
/* istanbul ignore next */
emit('afterexit', process.exitCode, null)
/* istanbul ignore next */
originalProcessReallyExit.call(process, process.exitCode)
}
var originalProcessEmit = process.emit
var processEmit = function processEmit (ev, arg) {
if (ev === 'exit' && processOk(global.process)) {
/* istanbul ignore else */
if (arg !== undefined) {
process.exitCode = arg
}
var ret = originalProcessEmit.apply(this, arguments)
/* istanbul ignore next */
emit('exit', process.exitCode, null)
/* istanbul ignore next */
emit('afterexit', process.exitCode, null)
/* istanbul ignore next */
return ret
} else {
return originalProcessEmit.apply(this, arguments)
}
}
}

View File

@@ -0,0 +1,38 @@
{
"name": "signal-exit",
"version": "3.0.7",
"description": "when you want to fire an event no matter how a process exits.",
"main": "index.js",
"scripts": {
"test": "tap",
"snap": "tap",
"preversion": "npm test",
"postversion": "npm publish",
"prepublishOnly": "git push origin --follow-tags"
},
"files": [
"index.js",
"signals.js"
],
"repository": {
"type": "git",
"url": "https://github.com/tapjs/signal-exit.git"
},
"keywords": [
"signal",
"exit"
],
"author": "Ben Coe <ben@npmjs.com>",
"license": "ISC",
"bugs": {
"url": "https://github.com/tapjs/signal-exit/issues"
},
"homepage": "https://github.com/tapjs/signal-exit",
"devDependencies": {
"chai": "^3.5.0",
"coveralls": "^3.1.1",
"nyc": "^15.1.0",
"standard-version": "^9.3.1",
"tap": "^15.1.1"
}
}

View File

@@ -0,0 +1,53 @@
// 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.
//
// 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.
module.exports = [
'SIGABRT',
'SIGALRM',
'SIGHUP',
'SIGINT',
'SIGTERM'
]
if (process.platform !== 'win32') {
module.exports.push(
'SIGVTALRM',
'SIGXCPU',
'SIGXFSZ',
'SIGUSR2',
'SIGTRAP',
'SIGSYS',
'SIGQUIT',
'SIGIOT'
// should detect profiler and enable/disable accordingly.
// see #21
// 'SIGPROF'
)
}
if (process.platform === 'linux') {
module.exports.push(
'SIGIO',
'SIGPOLL',
'SIGPWR',
'SIGSTKFLT',
'SIGUNUSED'
)
}

71
backend/node_modules/proper-lockfile/package.json generated vendored Normal file
View File

@@ -0,0 +1,71 @@
{
"name": "proper-lockfile",
"version": "4.1.2",
"description": "A inter-process and inter-machine lockfile utility that works on a local or network file system",
"keywords": [
"lock",
"locking",
"file",
"lockfile",
"fs",
"cross-process"
],
"author": "André Cruz <andre@moxy.studio>",
"homepage": "https://github.com/moxystudio/node-proper-lockfile",
"repository": {
"type": "git",
"url": "git@github.com:moxystudio/node-proper-lockfile.git"
},
"license": "MIT",
"main": "index.js",
"files": [
"lib"
],
"scripts": {
"lint": "eslint .",
"test": "jest --env node --coverage --runInBand",
"prerelease": "npm t && npm run lint",
"release": "standard-version",
"postrelease": "git push --follow-tags origin HEAD && npm publish"
},
"husky": {
"hooks": {
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS",
"pre-commit": "lint-staged"
}
},
"lint-staged": {
"*.js": [
"eslint --fix",
"git add"
]
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
},
"dependencies": {
"graceful-fs": "^4.2.4",
"retry": "^0.12.0",
"signal-exit": "^3.0.2"
},
"devDependencies": {
"@commitlint/cli": "^7.0.0",
"@commitlint/config-conventional": "^7.0.1",
"@segment/clear-timeouts": "^2.0.0",
"delay": "^4.1.0",
"eslint": "^5.3.0",
"eslint-config-moxy": "^7.1.0",
"execa": "^1.0.0",
"husky": "^1.1.4",
"jest": "^24.5.0",
"lint-staged": "^8.0.4",
"mkdirp": "^0.5.1",
"p-defer": "^2.1.0",
"rimraf": "^2.6.2",
"stable": "^0.1.8",
"standard-version": "^5.0.0",
"thread-sleep": "^2.1.0"
}
}