新增调试信息
This commit is contained in:
+22
@@ -0,0 +1,22 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2014 Google Inc.
|
||||
Copyright (c) 2012-2013 Johannes Ewald
|
||||
|
||||
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.
|
||||
+174
@@ -0,0 +1,174 @@
|
||||
# Requizzle
|
||||
|
||||

|
||||
|
||||
Swizzle a little something into your Node.js modules.
|
||||
|
||||
## What's Requizzle?
|
||||
|
||||
Requizzle provides a drop-in replacement for Node.js's `require()` function.
|
||||
This replacement enables you to change a module's source code when Node.js loads
|
||||
the module.
|
||||
|
||||
You can use Requizzle in your test cases, or in production code if you like to
|
||||
live dangerously.
|
||||
|
||||
## How can I change a module with Requizzle?
|
||||
|
||||
There are several different ways:
|
||||
|
||||
### Look for modules in new places
|
||||
|
||||
With Requizzle, you can add directories to the module lookup path, which forces
|
||||
Node.js to search those directories for modules. This can be useful if:
|
||||
|
||||
+ You're tired of writing code like `require('../../../../../lib/foo')`.
|
||||
+ You want to expose your app's modules to external plugins.
|
||||
|
||||
### Add code before or after the module's source code
|
||||
|
||||
Tamper with modules to your heart's delight by adding arbitrary code before or
|
||||
after the module's own source code.
|
||||
|
||||
### Mess with child modules
|
||||
|
||||
When you use Requizzle to require a module, you can force each child module's
|
||||
`require` method to inherit your changes to the parent module. (By default, only
|
||||
the parent module is changed.)
|
||||
|
||||
## Will Requizzle break my dependencies?
|
||||
|
||||
Probably not. It's true that Requizzle gives you plenty of new and exciting ways
|
||||
to tamper with, and possibly break, your module dependencies. But Requizzle also
|
||||
tries not to break anything on its own. In particular:
|
||||
|
||||
+ **Requizzle preserves strict-mode declarations**. If a module starts with a
|
||||
strict-mode declaration, Requizzle keeps it in place. Your changes will appear
|
||||
after the strict-mode declaration.
|
||||
+ **Requizzle leaves native modules alone**. If you use Requizzle to load one of
|
||||
Node.js's built-in modules, such as `fs` or `path`, Requizzle won't mess with
|
||||
it.
|
||||
|
||||
## Usage
|
||||
|
||||
The Requizzle module exports a single function, which returns a drop-in
|
||||
replacement for `require()`.
|
||||
|
||||
When you call the function, you must pass in an `options` object, which can
|
||||
include any of these properties:
|
||||
|
||||
+ `extras`: A pair of functions that return text to insert before or after the
|
||||
module's source code. Each function accepts two parameters: `targetPath`, the
|
||||
path to the required module, and `parentModule`, the `Module` object for the
|
||||
module's parent. Each function must return a string.
|
||||
+ `extras.before`: A function that returns text to insert before the
|
||||
module's source code.
|
||||
+ `extras.after`: A function that returns text to insert after the module's
|
||||
source code.
|
||||
+ `infect`: Determines whether child modules are infected with the same changes
|
||||
as the parent module. Set to `true` to force child modules to inherit your
|
||||
changes. Defaults to `false`.
|
||||
+ `requirePaths`: Additional paths to search for required modules. For example,
|
||||
if `requirePaths` is set to `['/usr/lib/junk/modules']`, and you save a
|
||||
JavaScript module at `/usr/lib/junk/modules/mymodule.js`, you can require the
|
||||
module as `mymodule`.
|
||||
|
||||
You can provide an array of paths, which will be searched before the default
|
||||
module paths, or an object with the following properties:
|
||||
|
||||
+ `requirePaths.before`: An array of paths to search before the default
|
||||
module paths.
|
||||
+ `requirePaths.after`: An array of paths to search after the default module
|
||||
paths. Use this property if you want the module to use its own local
|
||||
dependencies when possible, then fall back to the additional paths if
|
||||
necessary.
|
||||
|
||||
By default, the require path is not changed.
|
||||
|
||||
## Examples
|
||||
|
||||
```js
|
||||
const requizzle = require('requizzle');
|
||||
|
||||
// Say hello and goodbye to each module.
|
||||
const logRequire = requizzle({
|
||||
extras: {
|
||||
before: function(targetPath, parentModule) {
|
||||
return 'console.log("Hello %s!", ' + targetPath + ');\n';
|
||||
},
|
||||
after: function(targetPath, parentModule) {
|
||||
return 'console.log("Goodbye %s!", ' + targetPath + ');\n';
|
||||
}
|
||||
}
|
||||
});
|
||||
// Prints "Hello /path/to/mymodule.js!" and "Goodbye /path/to/mymodule.js!"
|
||||
const myModule = logRequire('mymodule');
|
||||
|
||||
// Look for modules in the current module's `lib` directory, and force child
|
||||
// modules to do the same.
|
||||
const path = require('path');
|
||||
const extraPathRequire = requizzle({
|
||||
infect: true,
|
||||
requirePaths: [path.join(__dirname, 'lib')]
|
||||
});
|
||||
// If `foo` needs to require a module in `./lib`, it can use `require('bar')`
|
||||
// instead of `require('./lib/bar')`.
|
||||
const foo = extraPathRequire('./foo');
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
Here are some problems you might run into when you use Requizzle, along with
|
||||
solutions to each problem. If you run into any problems that aren't addressed
|
||||
here, please file a new issue!
|
||||
|
||||
### Requizzle slowed down my code! A lot!
|
||||
|
||||
Requizzle adds minimal overhead to the module-loading process. However, your
|
||||
code will run _much_ slower than usual if you do both of the following:
|
||||
|
||||
+ Use Requizzle's `infect` option.
|
||||
+ Require modules that have a lot of `require()` calls within the scope of
|
||||
individual functions.
|
||||
|
||||
If Requizzle seems to slow down your app, look for module calls that are within
|
||||
function scope, then move them to each module's top-level scope.
|
||||
|
||||
### Requizzle made my module do something weird!
|
||||
|
||||
Do you have any
|
||||
[circular dependencies](https://nodejs.org/api/modules.html#modules_cycles) in
|
||||
the modules that aren't working? Circular dependencies can cause unusual
|
||||
behavior with Requizzle, just as they can without Requizzle. Try breaking the
|
||||
circular dependency.
|
||||
|
||||
### Requizzle violates the [Law of Demeter](https://wikipedia.org/wiki/Law_of_Demeter)! It's an unnatural abomination!
|
||||
|
||||
Fair enough.
|
||||
|
||||
## Changelog
|
||||
|
||||
+ 0.2.4 (November 2022): Fixed a compatibility issue with
|
||||
[core modules](https://nodejs.org/docs/latest-v18.x/api/modules.html#core-modules)
|
||||
that are loaded with the `node:` prefix, as in `require('node:fs')`.
|
||||
+ 0.2.3 (July 2019): Updated dependencies.
|
||||
+ 0.2.2 (May 2019): Fixed a compability issue with Node.js 12.
|
||||
+ 0.2.1 (December 2014): The `requirePaths` option no longer inserts an extra
|
||||
line break into the source file.
|
||||
+ 0.2.0 (June 2014): The `requirePaths` option can now contain `before` and
|
||||
`after` properties. Paths in the `before` property will be searched first; paths
|
||||
in the `after` property will be searched last.
|
||||
+ 0.1.1 (June 2014): If the `requirePaths` option is used, the module loader now
|
||||
searches the extra paths first rather than last.
|
||||
+ 0.1.0 (June 2014): Initial release.
|
||||
|
||||
## Acknowledgements
|
||||
|
||||
Requizzle is very loosely adapted from Johannes Ewald's
|
||||
[rewire](https://github.com/jhnns/rewire) module, which is designed to modify a
|
||||
module's behavior for unit testing. If Requizzle doesn't meet your needs, please
|
||||
take a look at rewire!
|
||||
|
||||
## License
|
||||
|
||||
[MIT license](https://github.com/hegemonic/requizzle/blob/main/LICENSE).
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
const _ = require('lodash');
|
||||
const Requizzle = require('./lib/requizzle');
|
||||
|
||||
module.exports = function requizzle(options) {
|
||||
let instance;
|
||||
|
||||
if (!options || typeof options !== 'object') {
|
||||
throw new TypeError("Requizzle's options parameter must be a non-null object.");
|
||||
}
|
||||
options = _.clone(options);
|
||||
options.parent = module.parent;
|
||||
|
||||
return (filepath) => {
|
||||
instance = instance || new Requizzle(options);
|
||||
|
||||
return instance.requizzle(filepath);
|
||||
};
|
||||
};
|
||||
module.exports.Requizzle = Requizzle;
|
||||
|
||||
// force Node.js to reload this module each time it's required, so module.parent is always correct
|
||||
delete require.cache[__filename];
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
Copyright 2012-2013 Johannes Ewald
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
const _ = require('lodash');
|
||||
const fs = require('fs');
|
||||
const Module = require('module');
|
||||
|
||||
const originalWrapper = Module.wrapper.slice(0);
|
||||
const requizzleWrappers = {
|
||||
extras: require('./wrappers/extras'),
|
||||
requirePaths: require('./wrappers/requirepaths'),
|
||||
strict: require('./wrappers/strict'),
|
||||
};
|
||||
|
||||
function wrap(wrappers, script) {
|
||||
return wrappers[0] + script + wrappers[1];
|
||||
}
|
||||
|
||||
function replaceWrapper(wrapperObj) {
|
||||
const joiner = '\n';
|
||||
const before = wrapperObj.before.join(joiner);
|
||||
const after = wrapperObj.after.join(joiner);
|
||||
const wrappers = [originalWrapper[0] + before, after + originalWrapper[1]];
|
||||
|
||||
Module.wrap = wrap.bind(null, wrappers);
|
||||
}
|
||||
|
||||
function restoreWrapper() {
|
||||
Module.wrap = wrap.bind(null, originalWrapper);
|
||||
}
|
||||
|
||||
function createModule(targetPath, parentModule, moduleCache) {
|
||||
moduleCache[targetPath] = moduleCache[targetPath] || new Module(targetPath, parentModule);
|
||||
|
||||
return moduleCache[targetPath];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for `require()` to prevent the target module's dependencies from being swizzled.
|
||||
*
|
||||
* @param {!Module} targetModule - The module that is being swizzled.
|
||||
* @param {!function} nodeRequire - The original `require()` method for the target module.
|
||||
* @param {!string} filepath - The value passed to `require()`.
|
||||
* @return {!Module} The requested module dependency.
|
||||
*/
|
||||
function requireProxy(targetModule, nodeRequire, filepath) {
|
||||
restoreWrapper();
|
||||
targetModule.require = nodeRequire;
|
||||
|
||||
return nodeRequire.call(targetModule, filepath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for `require()` to swizzle the target module's dependencies, using the same settings as
|
||||
* the target module.
|
||||
*
|
||||
* @param {!Module} targetModule - The module that is being swizzled.
|
||||
* @param {!Object} opts - The Requizzle options object.
|
||||
* @param {!string} filepath - The value passed to `require()`.
|
||||
* @return {!Module} The requested module dependency.
|
||||
*/
|
||||
function infectProxy(targetModule, cache, opts, filepath) {
|
||||
let moduleExports;
|
||||
// loaded here to avoid circular dependencies
|
||||
const Requizzle = require('./requizzle');
|
||||
let requizzle;
|
||||
|
||||
opts = _.clone(opts);
|
||||
opts.parent = targetModule;
|
||||
requizzle = new Requizzle(opts, cache);
|
||||
|
||||
moduleExports = requizzle.requizzle(filepath);
|
||||
|
||||
return moduleExports;
|
||||
}
|
||||
|
||||
exports.load = function load(targetPath, parentModule, wrapper, cache, options) {
|
||||
let nodeRequire;
|
||||
let targetModule;
|
||||
|
||||
// Handle circular requires, and avoid reloading modules unnecessarily
|
||||
if (cache.module[targetPath]) {
|
||||
return cache.module[targetPath];
|
||||
}
|
||||
|
||||
targetModule = createModule(targetPath, parentModule, cache.module);
|
||||
nodeRequire = targetModule.require;
|
||||
|
||||
if (options.infect) {
|
||||
targetModule.require = (filepath) => infectProxy(targetModule, cache, options, filepath);
|
||||
} else {
|
||||
targetModule.require = (filepath) => requireProxy(targetModule, nodeRequire, filepath);
|
||||
}
|
||||
|
||||
// update the wrapper before we load the target module
|
||||
replaceWrapper(wrapper);
|
||||
|
||||
targetModule.load(targetModule.id);
|
||||
|
||||
// make sure the wrapper is restored even if the target module doesn't load any dependencies
|
||||
restoreWrapper();
|
||||
|
||||
return targetModule;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check whether the entire module includes a `'use strict'` declaration.
|
||||
*
|
||||
* @param {string} src - The source file to check.
|
||||
* @return {boolean} Set to `true` if the module includes a `use strict` declaration.
|
||||
*/
|
||||
function detectStrictMode(src) {
|
||||
return /^\s*(?:["']use strict["'])[ \t]*(?:[\r\n]|;)/g.test(src);
|
||||
}
|
||||
|
||||
function loadSource(targetPath, sourceCache) {
|
||||
if (sourceCache[targetPath] === undefined) {
|
||||
sourceCache[targetPath] = fs.readFileSync(targetPath, 'utf8');
|
||||
}
|
||||
|
||||
return sourceCache[targetPath];
|
||||
}
|
||||
|
||||
exports.createWrapper = function createWrapper(targetPath, parentModule, cache, options) {
|
||||
let src;
|
||||
const wrapperObject = {
|
||||
before: [],
|
||||
after: [],
|
||||
};
|
||||
|
||||
function add(wrapperFunctions, opts) {
|
||||
const params = [targetPath, parentModule, opts];
|
||||
|
||||
['before', 'after'].forEach((item) => {
|
||||
const result = wrapperFunctions[item].apply(null, params);
|
||||
|
||||
if (result) {
|
||||
wrapperObject[item].push(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Preserve the module's `use strict` declaration if present
|
||||
src = loadSource(targetPath, cache.source);
|
||||
if (detectStrictMode(src) === true) {
|
||||
add(requizzleWrappers.strict);
|
||||
}
|
||||
|
||||
if (options.requirePaths) {
|
||||
add(requizzleWrappers.requirePaths, options.requirePaths);
|
||||
}
|
||||
|
||||
if (options.extras) {
|
||||
add(requizzleWrappers.extras, options.extras);
|
||||
}
|
||||
|
||||
return wrapperObject;
|
||||
};
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
Copyright 2012-2013 Johannes Ewald
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
/** @module lib/requizzle */
|
||||
|
||||
const loader = require('./loader');
|
||||
const Module = require('module');
|
||||
|
||||
const NATIVE_MODULE_PREFIX = 'node:';
|
||||
|
||||
/**
|
||||
* Function that returns text to swizzle into the module.
|
||||
*
|
||||
* @typedef module:lib/requizzle~wrapperFunction
|
||||
* @type {function}
|
||||
* @param {string} targetPath - The path to the target module.
|
||||
* @param {string} parentModulePath - The path to the module that is requiring the target module.
|
||||
* @return {string} The text to insert before or after the module's source code.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Options for the wrappers that will be swizzled into the target module.
|
||||
*
|
||||
* @typedef module:lib/requizzle~options
|
||||
* @type {Object}
|
||||
* @property {Object=} options.extras - Functions that generate text to swizzle into the target
|
||||
* module.
|
||||
* @property {module:lib/requizzle~wrapperFunction} options.extras.after - Function that returns
|
||||
* text to insert after the module's source code.
|
||||
* @property {module:lib/requizzle~wrapperFunction} options.extras.before - Function that returns
|
||||
* text to insert before the module's source code.
|
||||
* @property {(Array.<string>|string)} options.requirePaths - Additional paths to search when
|
||||
* resolving module paths in the target module.
|
||||
*/
|
||||
|
||||
function isNativeModule(targetPath, parentModule) {
|
||||
let lookupPaths;
|
||||
let isNative = false;
|
||||
|
||||
if (targetPath.startsWith(NATIVE_MODULE_PREFIX)) {
|
||||
isNative = true;
|
||||
} else {
|
||||
lookupPaths = Module._resolveLookupPaths(targetPath, parentModule, true);
|
||||
/* istanbul ignore next */
|
||||
isNative =
|
||||
lookupPaths === null ||
|
||||
(lookupPaths.length === 2 && lookupPaths[1].length === 0 && lookupPaths[0] === targetPath);
|
||||
}
|
||||
|
||||
return isNative;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a `Requizzle` instance. If you provide options, Requizzle will default to those options
|
||||
* when you call {@link Requizzle#requizzle}.
|
||||
*
|
||||
* @class
|
||||
* @param {!module:lib/requizzle~options} options - Options for the wrappers that will be swizzled
|
||||
* into the target module.
|
||||
* @param {Object=} cache - For internal use.
|
||||
*/
|
||||
class Requizzle {
|
||||
constructor(options, cache) {
|
||||
this._options = options;
|
||||
this._cache = cache || {
|
||||
module: {},
|
||||
source: {},
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the module, swizzling in the requested changes.
|
||||
*
|
||||
* @param {!string} targetPath - The path to the module that will be loaded.
|
||||
* @return {Module} The swizzled module.
|
||||
*/
|
||||
requizzle(targetPath) {
|
||||
const options = this._options;
|
||||
const parentModule = options.parent;
|
||||
let targetModule;
|
||||
let wrapper;
|
||||
|
||||
// Don't interfere with native modules
|
||||
if (isNativeModule(targetPath, parentModule)) {
|
||||
return require(targetPath);
|
||||
}
|
||||
|
||||
// Resolve the filename relative to the parent module
|
||||
targetPath = Module._resolveFilename(targetPath, parentModule);
|
||||
|
||||
wrapper = loader.createWrapper(targetPath, parentModule, this._cache, this._options);
|
||||
targetModule = loader.load(targetPath, parentModule, wrapper, this._cache, this._options);
|
||||
|
||||
return targetModule.exports;
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = Requizzle;
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
function callFunction(targetPath, parentModule, func) {
|
||||
if (!func) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return func(targetPath, parentModule);
|
||||
}
|
||||
|
||||
exports.before = function before(targetPath, parentModule, options) {
|
||||
return callFunction(targetPath, parentModule, options.before);
|
||||
};
|
||||
|
||||
exports.after = function after(targetPath, parentModule, options) {
|
||||
return callFunction(targetPath, parentModule, options.after);
|
||||
};
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
const path = require('path');
|
||||
|
||||
function resolvePaths({ filepath }, paths) {
|
||||
if (!paths) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return paths.slice(0).map((p) => path.resolve(filepath, p));
|
||||
}
|
||||
|
||||
function requirePaths(parentModule, opts) {
|
||||
const result = {
|
||||
before: [],
|
||||
after: [],
|
||||
};
|
||||
|
||||
if (!parentModule) {
|
||||
return result;
|
||||
}
|
||||
|
||||
if (Array.isArray(opts)) {
|
||||
result.before = resolvePaths(parentModule, opts);
|
||||
} else {
|
||||
result.before = resolvePaths(parentModule, opts.before);
|
||||
result.after = resolvePaths(parentModule, opts.after);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
exports.before = function before(targetPath, parentModule, opts) {
|
||||
const resolvedPaths = requirePaths(parentModule, opts);
|
||||
|
||||
return (
|
||||
`module.paths = ${JSON.stringify(resolvedPaths.before)}.concat(module.paths)` +
|
||||
`.concat(${JSON.stringify(resolvedPaths.after)}); `
|
||||
);
|
||||
};
|
||||
|
||||
exports.after = function after() {
|
||||
return '';
|
||||
};
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
Copyright 2014 Google LLC
|
||||
|
||||
Use of this source code is governed by the MIT License, available in this package's LICENSE file
|
||||
or at http://opensource.org/licenses/MIT.
|
||||
*/
|
||||
exports.before = function before() {
|
||||
return '"use strict";';
|
||||
};
|
||||
|
||||
exports.after = function after() {
|
||||
return '';
|
||||
};
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
{
|
||||
"name": "requizzle",
|
||||
"version": "0.2.4",
|
||||
"description": "Swizzle a little something into your require() calls.",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "gulp test"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/hegemonic/requizzle.git"
|
||||
},
|
||||
"keywords": [
|
||||
"module",
|
||||
"modules",
|
||||
"require",
|
||||
"inject",
|
||||
"dependency",
|
||||
"swizzle"
|
||||
],
|
||||
"author": "Jeff Williams <jeffrey.l.williams@gmail.com>",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/hegemonic/requizzle/issues"
|
||||
},
|
||||
"homepage": "https://github.com/hegemonic/requizzle",
|
||||
"dependencies": {
|
||||
"lodash": "^4.17.21"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@jsdoc/eslint-config": "^1.1.9",
|
||||
"@jsdoc/prettier-config": "^0.1.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"expectations": "^1.0.0",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-eslint-new": "^1.7.0",
|
||||
"gulp-mocha": "^8.0.0"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user