update
This commit is contained in:
@@ -0,0 +1,748 @@
|
||||
/*!
|
||||
* router
|
||||
* Copyright(c) 2013 Roman Shtylman
|
||||
* Copyright(c) 2014-2022 Douglas Christopher Wilson
|
||||
* MIT Licensed
|
||||
*/
|
||||
|
||||
'use strict'
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
* @private
|
||||
*/
|
||||
|
||||
const isPromise = require('is-promise')
|
||||
const Layer = require('./lib/layer')
|
||||
const { METHODS } = require('node:http')
|
||||
const parseUrl = require('parseurl')
|
||||
const Route = require('./lib/route')
|
||||
const debug = require('debug')('router')
|
||||
const deprecate = require('depd')('router')
|
||||
|
||||
/**
|
||||
* Module variables.
|
||||
* @private
|
||||
*/
|
||||
|
||||
const slice = Array.prototype.slice
|
||||
const flatten = Array.prototype.flat
|
||||
const methods = METHODS.map((method) => method.toLowerCase())
|
||||
|
||||
/**
|
||||
* Expose `Router`.
|
||||
*/
|
||||
|
||||
module.exports = Router
|
||||
|
||||
/**
|
||||
* Expose `Route`.
|
||||
*/
|
||||
|
||||
module.exports.Route = Route
|
||||
|
||||
/**
|
||||
* Initialize a new `Router` with the given `options`.
|
||||
*
|
||||
* @param {object} [options]
|
||||
* @return {Router} which is a callable function
|
||||
* @public
|
||||
*/
|
||||
|
||||
function Router (options) {
|
||||
if (!(this instanceof Router)) {
|
||||
return new Router(options)
|
||||
}
|
||||
|
||||
const opts = options || {}
|
||||
|
||||
function router (req, res, next) {
|
||||
router.handle(req, res, next)
|
||||
}
|
||||
|
||||
// inherit from the correct prototype
|
||||
Object.setPrototypeOf(router, this)
|
||||
|
||||
router.caseSensitive = opts.caseSensitive
|
||||
router.mergeParams = opts.mergeParams
|
||||
router.params = {}
|
||||
router.strict = opts.strict
|
||||
router.stack = []
|
||||
|
||||
return router
|
||||
}
|
||||
|
||||
/**
|
||||
* Router prototype inherits from a Function.
|
||||
*/
|
||||
|
||||
/* istanbul ignore next */
|
||||
Router.prototype = function () {}
|
||||
|
||||
/**
|
||||
* Map the given param placeholder `name`(s) to the given callback.
|
||||
*
|
||||
* Parameter mapping is used to provide pre-conditions to routes
|
||||
* which use normalized placeholders. For example a _:user_id_ parameter
|
||||
* could automatically load a user's information from the database without
|
||||
* any additional code.
|
||||
*
|
||||
* The callback uses the same signature as middleware, the only difference
|
||||
* being that the value of the placeholder is passed, in this case the _id_
|
||||
* of the user. Once the `next()` function is invoked, just like middleware
|
||||
* it will continue on to execute the route, or subsequent parameter functions.
|
||||
*
|
||||
* Just like in middleware, you must either respond to the request or call next
|
||||
* to avoid stalling the request.
|
||||
*
|
||||
* router.param('user_id', function(req, res, next, id){
|
||||
* User.find(id, function(err, user){
|
||||
* if (err) {
|
||||
* return next(err)
|
||||
* } else if (!user) {
|
||||
* return next(new Error('failed to load user'))
|
||||
* }
|
||||
* req.user = user
|
||||
* next()
|
||||
* })
|
||||
* })
|
||||
*
|
||||
* @param {string} name
|
||||
* @param {function} fn
|
||||
* @public
|
||||
*/
|
||||
|
||||
Router.prototype.param = function param (name, fn) {
|
||||
if (!name) {
|
||||
throw new TypeError('argument name is required')
|
||||
}
|
||||
|
||||
if (typeof name !== 'string') {
|
||||
throw new TypeError('argument name must be a string')
|
||||
}
|
||||
|
||||
if (!fn) {
|
||||
throw new TypeError('argument fn is required')
|
||||
}
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('argument fn must be a function')
|
||||
}
|
||||
|
||||
let params = this.params[name]
|
||||
|
||||
if (!params) {
|
||||
params = this.params[name] = []
|
||||
}
|
||||
|
||||
params.push(fn)
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatch a req, res into the router.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
Router.prototype.handle = function handle (req, res, callback) {
|
||||
if (!callback) {
|
||||
throw new TypeError('argument callback is required')
|
||||
}
|
||||
|
||||
debug('dispatching %s %s', req.method, req.url)
|
||||
|
||||
let idx = 0
|
||||
let methods
|
||||
const protohost = getProtohost(req.url) || ''
|
||||
let removed = ''
|
||||
const self = this
|
||||
let slashAdded = false
|
||||
let sync = 0
|
||||
const paramcalled = {}
|
||||
|
||||
// middleware and routes
|
||||
const stack = this.stack
|
||||
|
||||
// manage inter-router variables
|
||||
const parentParams = req.params
|
||||
const parentUrl = req.baseUrl || ''
|
||||
let done = restore(callback, req, 'baseUrl', 'next', 'params')
|
||||
|
||||
// setup next layer
|
||||
req.next = next
|
||||
|
||||
// for options requests, respond with a default if nothing else responds
|
||||
if (req.method === 'OPTIONS') {
|
||||
methods = []
|
||||
done = wrap(done, generateOptionsResponder(res, methods))
|
||||
}
|
||||
|
||||
// setup basic req values
|
||||
req.baseUrl = parentUrl
|
||||
req.originalUrl = req.originalUrl || req.url
|
||||
|
||||
next()
|
||||
|
||||
function next (err) {
|
||||
let layerError = err === 'route'
|
||||
? null
|
||||
: err
|
||||
|
||||
// remove added slash
|
||||
if (slashAdded) {
|
||||
req.url = req.url.slice(1)
|
||||
slashAdded = false
|
||||
}
|
||||
|
||||
// restore altered req.url
|
||||
if (removed.length !== 0) {
|
||||
req.baseUrl = parentUrl
|
||||
req.url = protohost + removed + req.url.slice(protohost.length)
|
||||
removed = ''
|
||||
}
|
||||
|
||||
// signal to exit router
|
||||
if (layerError === 'router') {
|
||||
setImmediate(done, null)
|
||||
return
|
||||
}
|
||||
|
||||
// no more matching layers
|
||||
if (idx >= stack.length) {
|
||||
setImmediate(done, layerError)
|
||||
return
|
||||
}
|
||||
|
||||
// max sync stack
|
||||
if (++sync > 100) {
|
||||
return setImmediate(next, err)
|
||||
}
|
||||
|
||||
// get pathname of request
|
||||
const path = getPathname(req)
|
||||
|
||||
if (path == null) {
|
||||
return done(layerError)
|
||||
}
|
||||
|
||||
// find next matching layer
|
||||
let layer
|
||||
let match
|
||||
let route
|
||||
|
||||
while (match !== true && idx < stack.length) {
|
||||
layer = stack[idx++]
|
||||
match = matchLayer(layer, path)
|
||||
route = layer.route
|
||||
|
||||
if (typeof match !== 'boolean') {
|
||||
// hold on to layerError
|
||||
layerError = layerError || match
|
||||
}
|
||||
|
||||
if (match !== true) {
|
||||
continue
|
||||
}
|
||||
|
||||
if (!route) {
|
||||
// process non-route handlers normally
|
||||
continue
|
||||
}
|
||||
|
||||
if (layerError) {
|
||||
// routes do not match with a pending error
|
||||
match = false
|
||||
continue
|
||||
}
|
||||
|
||||
const method = req.method
|
||||
const hasMethod = route._handlesMethod(method)
|
||||
|
||||
// build up automatic options response
|
||||
if (!hasMethod && method === 'OPTIONS' && methods) {
|
||||
methods.push.apply(methods, route._methods())
|
||||
}
|
||||
|
||||
// don't even bother matching route
|
||||
if (!hasMethod && method !== 'HEAD') {
|
||||
match = false
|
||||
}
|
||||
}
|
||||
|
||||
// no match
|
||||
if (match !== true) {
|
||||
return done(layerError)
|
||||
}
|
||||
|
||||
// store route for dispatch on change
|
||||
if (route) {
|
||||
req.route = route
|
||||
}
|
||||
|
||||
// Capture one-time layer values
|
||||
req.params = self.mergeParams
|
||||
? mergeParams(layer.params, parentParams)
|
||||
: layer.params
|
||||
const layerPath = layer.path
|
||||
|
||||
// this should be done for the layer
|
||||
processParams(self.params, layer, paramcalled, req, res, function (err) {
|
||||
if (err) {
|
||||
next(layerError || err)
|
||||
} else if (route) {
|
||||
layer.handleRequest(req, res, next)
|
||||
} else {
|
||||
trimPrefix(layer, layerError, layerPath, path)
|
||||
}
|
||||
|
||||
sync = 0
|
||||
})
|
||||
}
|
||||
|
||||
function trimPrefix (layer, layerError, layerPath, path) {
|
||||
if (layerPath.length !== 0) {
|
||||
// Validate path is a prefix match
|
||||
if (layerPath !== path.substring(0, layerPath.length)) {
|
||||
next(layerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Validate path breaks on a path separator
|
||||
const c = path[layerPath.length]
|
||||
if (c && c !== '/') {
|
||||
next(layerError)
|
||||
return
|
||||
}
|
||||
|
||||
// Trim off the part of the url that matches the route
|
||||
// middleware (.use stuff) needs to have the path stripped
|
||||
debug('trim prefix (%s) from url %s', layerPath, req.url)
|
||||
removed = layerPath
|
||||
req.url = protohost + req.url.slice(protohost.length + removed.length)
|
||||
|
||||
// Ensure leading slash
|
||||
if (!protohost && req.url[0] !== '/') {
|
||||
req.url = '/' + req.url
|
||||
slashAdded = true
|
||||
}
|
||||
|
||||
// Setup base URL (no trailing slash)
|
||||
req.baseUrl = parentUrl + (removed[removed.length - 1] === '/'
|
||||
? removed.substring(0, removed.length - 1)
|
||||
: removed)
|
||||
}
|
||||
|
||||
debug('%s %s : %s', layer.name, layerPath, req.originalUrl)
|
||||
|
||||
if (layerError) {
|
||||
layer.handleError(layerError, req, res, next)
|
||||
} else {
|
||||
layer.handleRequest(req, res, next)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the given middleware function, with optional path, defaulting to "/".
|
||||
*
|
||||
* Use (like `.all`) will run for any http METHOD, but it will not add
|
||||
* handlers for those methods so OPTIONS requests will not consider `.use`
|
||||
* functions even if they could respond.
|
||||
*
|
||||
* The other difference is that _route_ path is stripped and not visible
|
||||
* to the handler function. The main effect of this feature is that mounted
|
||||
* handlers can operate without any code changes regardless of the "prefix"
|
||||
* pathname.
|
||||
*
|
||||
* @public
|
||||
*/
|
||||
|
||||
Router.prototype.use = function use (handler) {
|
||||
let offset = 0
|
||||
let path = '/'
|
||||
|
||||
// default path to '/'
|
||||
// disambiguate router.use([handler])
|
||||
if (typeof handler !== 'function') {
|
||||
let arg = handler
|
||||
|
||||
while (Array.isArray(arg) && arg.length !== 0) {
|
||||
arg = arg[0]
|
||||
}
|
||||
|
||||
// first arg is the path
|
||||
if (typeof arg !== 'function') {
|
||||
offset = 1
|
||||
path = handler
|
||||
}
|
||||
}
|
||||
|
||||
const callbacks = flatten.call(slice.call(arguments, offset), Infinity)
|
||||
|
||||
if (callbacks.length === 0) {
|
||||
throw new TypeError('argument handler is required')
|
||||
}
|
||||
|
||||
for (let i = 0; i < callbacks.length; i++) {
|
||||
const fn = callbacks[i]
|
||||
|
||||
if (typeof fn !== 'function') {
|
||||
throw new TypeError('argument handler must be a function')
|
||||
}
|
||||
|
||||
// add the middleware
|
||||
debug('use %o %s', path, fn.name || '<anonymous>')
|
||||
|
||||
const layer = new Layer(path, {
|
||||
sensitive: this.caseSensitive,
|
||||
strict: false,
|
||||
end: false
|
||||
}, fn)
|
||||
|
||||
layer.route = undefined
|
||||
|
||||
this.stack.push(layer)
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new Route for the given path.
|
||||
*
|
||||
* Each route contains a separate middleware stack and VERB handlers.
|
||||
*
|
||||
* See the Route api documentation for details on adding handlers
|
||||
* and middleware to routes.
|
||||
*
|
||||
* @param {string} path
|
||||
* @return {Route}
|
||||
* @public
|
||||
*/
|
||||
|
||||
Router.prototype.route = function route (path) {
|
||||
const route = new Route(path)
|
||||
|
||||
const layer = new Layer(path, {
|
||||
sensitive: this.caseSensitive,
|
||||
strict: this.strict,
|
||||
end: true
|
||||
}, handle)
|
||||
|
||||
function handle (req, res, next) {
|
||||
route.dispatch(req, res, next)
|
||||
}
|
||||
|
||||
layer.route = route
|
||||
|
||||
this.stack.push(layer)
|
||||
return route
|
||||
}
|
||||
|
||||
// create Router#VERB functions
|
||||
methods.concat('all').forEach(function (method) {
|
||||
Router.prototype[method] = function (path) {
|
||||
const route = this.route(path)
|
||||
route[method].apply(route, slice.call(arguments, 1))
|
||||
return this
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Generate a callback that will make an OPTIONS response.
|
||||
*
|
||||
* @param {OutgoingMessage} res
|
||||
* @param {array} methods
|
||||
* @private
|
||||
*/
|
||||
|
||||
function generateOptionsResponder (res, methods) {
|
||||
return function onDone (fn, err) {
|
||||
if (err || methods.length === 0) {
|
||||
return fn(err)
|
||||
}
|
||||
|
||||
trySendOptionsResponse(res, methods, fn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get pathname of request.
|
||||
*
|
||||
* @param {IncomingMessage} req
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getPathname (req) {
|
||||
try {
|
||||
return parseUrl(req).pathname
|
||||
} catch (err) {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get get protocol + host for a URL.
|
||||
*
|
||||
* @param {string} url
|
||||
* @private
|
||||
*/
|
||||
|
||||
function getProtohost (url) {
|
||||
if (typeof url !== 'string' || url.length === 0 || url[0] === '/') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const searchIndex = url.indexOf('?')
|
||||
const pathLength = searchIndex !== -1
|
||||
? searchIndex
|
||||
: url.length
|
||||
const fqdnIndex = url.substring(0, pathLength).indexOf('://')
|
||||
|
||||
return fqdnIndex !== -1
|
||||
? url.substring(0, url.indexOf('/', 3 + fqdnIndex))
|
||||
: undefined
|
||||
}
|
||||
|
||||
/**
|
||||
* Match path to a layer.
|
||||
*
|
||||
* @param {Layer} layer
|
||||
* @param {string} path
|
||||
* @private
|
||||
*/
|
||||
|
||||
function matchLayer (layer, path) {
|
||||
try {
|
||||
return layer.match(path)
|
||||
} catch (err) {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merge params with parent params
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function mergeParams (params, parent) {
|
||||
if (typeof parent !== 'object' || !parent) {
|
||||
return params
|
||||
}
|
||||
|
||||
// make copy of parent for base
|
||||
const obj = Object.assign({}, parent)
|
||||
|
||||
// simple non-numeric merging
|
||||
if (!(0 in params) || !(0 in parent)) {
|
||||
return Object.assign(obj, params)
|
||||
}
|
||||
|
||||
let i = 0
|
||||
let o = 0
|
||||
|
||||
// determine numeric gap in params
|
||||
while (i in params) {
|
||||
i++
|
||||
}
|
||||
|
||||
// determine numeric gap in parent
|
||||
while (o in parent) {
|
||||
o++
|
||||
}
|
||||
|
||||
// offset numeric indices in params before merge
|
||||
for (i--; i >= 0; i--) {
|
||||
params[i + o] = params[i]
|
||||
|
||||
// create holes for the merge when necessary
|
||||
if (i < o) {
|
||||
delete params[i]
|
||||
}
|
||||
}
|
||||
|
||||
return Object.assign(obj, params)
|
||||
}
|
||||
|
||||
/**
|
||||
* Process any parameters for the layer.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function processParams (params, layer, called, req, res, done) {
|
||||
// captured parameters from the layer, keys and values
|
||||
const keys = layer.keys
|
||||
|
||||
// fast track
|
||||
if (!keys || keys.length === 0) {
|
||||
return done()
|
||||
}
|
||||
|
||||
let i = 0
|
||||
let paramIndex = 0
|
||||
let key
|
||||
let paramVal
|
||||
let paramCallbacks
|
||||
let paramCalled
|
||||
|
||||
// process params in order
|
||||
// param callbacks can be async
|
||||
function param (err) {
|
||||
if (err) {
|
||||
return done(err)
|
||||
}
|
||||
|
||||
if (i >= keys.length) {
|
||||
return done()
|
||||
}
|
||||
|
||||
paramIndex = 0
|
||||
key = keys[i++]
|
||||
paramVal = req.params[key]
|
||||
paramCallbacks = params[key]
|
||||
paramCalled = called[key]
|
||||
|
||||
if (paramVal === undefined || !paramCallbacks) {
|
||||
return param()
|
||||
}
|
||||
|
||||
// param previously called with same value or error occurred
|
||||
if (paramCalled && (paramCalled.match === paramVal ||
|
||||
(paramCalled.error && paramCalled.error !== 'route'))) {
|
||||
// restore value
|
||||
req.params[key] = paramCalled.value
|
||||
|
||||
// next param
|
||||
return param(paramCalled.error)
|
||||
}
|
||||
|
||||
called[key] = paramCalled = {
|
||||
error: null,
|
||||
match: paramVal,
|
||||
value: paramVal
|
||||
}
|
||||
|
||||
paramCallback()
|
||||
}
|
||||
|
||||
// single param callbacks
|
||||
function paramCallback (err) {
|
||||
const fn = paramCallbacks[paramIndex++]
|
||||
|
||||
// store updated value
|
||||
paramCalled.value = req.params[key]
|
||||
|
||||
if (err) {
|
||||
// store error
|
||||
paramCalled.error = err
|
||||
param(err)
|
||||
return
|
||||
}
|
||||
|
||||
if (!fn) return param()
|
||||
|
||||
try {
|
||||
const ret = fn(req, res, paramCallback, paramVal, key)
|
||||
if (isPromise(ret)) {
|
||||
if (!(ret instanceof Promise)) {
|
||||
deprecate('parameters that are Promise-like are deprecated, use a native Promise instead')
|
||||
}
|
||||
|
||||
ret.then(null, function (error) {
|
||||
paramCallback(error || new Error('Rejected promise'))
|
||||
})
|
||||
}
|
||||
} catch (e) {
|
||||
paramCallback(e)
|
||||
}
|
||||
}
|
||||
|
||||
param()
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore obj props after function
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function restore (fn, obj) {
|
||||
const props = new Array(arguments.length - 2)
|
||||
const vals = new Array(arguments.length - 2)
|
||||
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
props[i] = arguments[i + 2]
|
||||
vals[i] = obj[props[i]]
|
||||
}
|
||||
|
||||
return function () {
|
||||
// restore vals
|
||||
for (let i = 0; i < props.length; i++) {
|
||||
obj[props[i]] = vals[i]
|
||||
}
|
||||
|
||||
return fn.apply(this, arguments)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an OPTIONS response.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function sendOptionsResponse (res, methods) {
|
||||
const options = Object.create(null)
|
||||
|
||||
// build unique method map
|
||||
for (let i = 0; i < methods.length; i++) {
|
||||
options[methods[i]] = true
|
||||
}
|
||||
|
||||
// construct the allow list
|
||||
const allow = Object.keys(options).sort().join(', ')
|
||||
|
||||
// send response
|
||||
res.setHeader('Allow', allow)
|
||||
res.setHeader('Content-Length', Buffer.byteLength(allow))
|
||||
res.setHeader('Content-Type', 'text/plain')
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff')
|
||||
res.end(allow)
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to send an OPTIONS response.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function trySendOptionsResponse (res, methods, next) {
|
||||
try {
|
||||
sendOptionsResponse(res, methods)
|
||||
} catch (err) {
|
||||
next(err)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a function
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
||||
function wrap (old, fn) {
|
||||
return function proxy () {
|
||||
const args = new Array(arguments.length + 1)
|
||||
|
||||
args[0] = old
|
||||
for (let i = 0, len = arguments.length; i < len; i++) {
|
||||
args[i + 1] = arguments[i]
|
||||
}
|
||||
|
||||
fn.apply(this, args)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
# unpipe
|
||||
|
||||
[![NPM Version][npm-image]][npm-url]
|
||||
[![NPM Downloads][downloads-image]][downloads-url]
|
||||
[![Node.js Version][node-image]][node-url]
|
||||
[![Build Status][travis-image]][travis-url]
|
||||
[![Test Coverage][coveralls-image]][coveralls-url]
|
||||
|
||||
Unpipe a stream from all destinations.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
$ npm install unpipe
|
||||
```
|
||||
|
||||
## API
|
||||
|
||||
```js
|
||||
var unpipe = require('unpipe')
|
||||
```
|
||||
|
||||
### unpipe(stream)
|
||||
|
||||
Unpipes all destinations from a given stream. With stream 2+, this is
|
||||
equivalent to `stream.unpipe()`. When used with streams 1 style streams
|
||||
(typically Node.js 0.8 and below), this module attempts to undo the
|
||||
actions done in `stream.pipe(dest)`.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
|
||||
[npm-image]: https://img.shields.io/npm/v/unpipe.svg
|
||||
[npm-url]: https://npmjs.org/package/unpipe
|
||||
[node-image]: https://img.shields.io/node/v/unpipe.svg
|
||||
[node-url]: http://nodejs.org/download/
|
||||
[travis-image]: https://img.shields.io/travis/stream-utils/unpipe.svg
|
||||
[travis-url]: https://travis-ci.org/stream-utils/unpipe
|
||||
[coveralls-image]: https://img.shields.io/coveralls/stream-utils/unpipe.svg
|
||||
[coveralls-url]: https://coveralls.io/r/stream-utils/unpipe?branch=master
|
||||
[downloads-image]: https://img.shields.io/npm/dm/unpipe.svg
|
||||
[downloads-url]: https://npmjs.org/package/unpipe
|
||||
@@ -0,0 +1,85 @@
|
||||
{
|
||||
"name": "side-channel",
|
||||
"version": "1.1.0",
|
||||
"description": "Store information about any JS value in a side channel. Uses WeakMap if available.",
|
||||
"main": "index.js",
|
||||
"exports": {
|
||||
".": "./index.js",
|
||||
"./package.json": "./package.json"
|
||||
},
|
||||
"types": "./index.d.ts",
|
||||
"scripts": {
|
||||
"prepack": "npmignore --auto --commentLines=autogenerated",
|
||||
"prepublishOnly": "safe-publish-latest",
|
||||
"prepublish": "not-in-publish || npm run prepublishOnly",
|
||||
"prelint": "eclint check $(git ls-files | xargs find 2> /dev/null | grep -vE 'node_modules|\\.git')",
|
||||
"lint": "eslint --ext=js,mjs .",
|
||||
"postlint": "tsc -p . && attw -P",
|
||||
"pretest": "npm run lint",
|
||||
"tests-only": "nyc tape 'test/**/*.js'",
|
||||
"test": "npm run tests-only",
|
||||
"posttest": "npx npm@'>=10.2' audit --production",
|
||||
"version": "auto-changelog && git add CHANGELOG.md",
|
||||
"postversion": "auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f \"v$(node -e \"console.log(require('./package.json').version)\")\""
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ljharb/side-channel.git"
|
||||
},
|
||||
"keywords": [
|
||||
"weakmap",
|
||||
"map",
|
||||
"side",
|
||||
"channel",
|
||||
"metadata"
|
||||
],
|
||||
"author": "Jordan Harband <ljharb@gmail.com>",
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
},
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/ljharb/side-channel/issues"
|
||||
},
|
||||
"homepage": "https://github.com/ljharb/side-channel#readme",
|
||||
"dependencies": {
|
||||
"es-errors": "^1.3.0",
|
||||
"object-inspect": "^1.13.3",
|
||||
"side-channel-list": "^1.0.0",
|
||||
"side-channel-map": "^1.0.1",
|
||||
"side-channel-weakmap": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@arethetypeswrong/cli": "^0.17.1",
|
||||
"@ljharb/eslint-config": "^21.1.1",
|
||||
"@ljharb/tsconfig": "^0.2.2",
|
||||
"@types/object-inspect": "^1.13.0",
|
||||
"@types/tape": "^5.6.5",
|
||||
"auto-changelog": "^2.5.0",
|
||||
"eclint": "^2.8.1",
|
||||
"encoding": "^0.1.13",
|
||||
"eslint": "=8.8.0",
|
||||
"in-publish": "^2.0.1",
|
||||
"npmignore": "^0.3.1",
|
||||
"nyc": "^10.3.2",
|
||||
"safe-publish-latest": "^2.0.0",
|
||||
"tape": "^5.9.0",
|
||||
"typescript": "next"
|
||||
},
|
||||
"auto-changelog": {
|
||||
"output": "CHANGELOG.md",
|
||||
"template": "keepachangelog",
|
||||
"unreleased": false,
|
||||
"commitLimit": false,
|
||||
"backfillLimit": false,
|
||||
"hideCredit": true
|
||||
},
|
||||
"publishConfig": {
|
||||
"ignore": [
|
||||
".github/workflows"
|
||||
]
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: [ljharb]
|
||||
patreon: # Replace with a single Patreon username
|
||||
open_collective: # Replace with a single Open Collective username
|
||||
ko_fi: # Replace with a single Ko-fi username
|
||||
tidelift: npm/es-object
|
||||
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
|
||||
liberapay: # Replace with a single Liberapay username
|
||||
issuehunt: # Replace with a single IssueHunt username
|
||||
otechie: # Replace with a single Otechie username
|
||||
custom: # Replace with a single custom sponsorship URL
|
||||
@@ -0,0 +1,26 @@
|
||||
'use strict';
|
||||
|
||||
require('core-js');
|
||||
|
||||
var inspect = require('./');
|
||||
var test = require('tape');
|
||||
|
||||
test('Maps', function (t) {
|
||||
t.equal(inspect(new Map([[1, 2]])), 'Map (1) {1 => 2}');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('WeakMaps', function (t) {
|
||||
t.equal(inspect(new WeakMap([[{}, 2]])), 'WeakMap { ? }');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('Sets', function (t) {
|
||||
t.equal(inspect(new Set([[1, 2]])), 'Set (1) {[ 1, 2 ]}');
|
||||
t.end();
|
||||
});
|
||||
|
||||
test('WeakSets', function (t) {
|
||||
t.equal(inspect(new WeakSet([[1, 2]])), 'WeakSet { ? }');
|
||||
t.end();
|
||||
});
|
||||
Reference in New Issue
Block a user